]> git.mxchange.org Git - friendica.git/blob - bin/composer.phar
Fix moving stored data
[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') && ini_get('apc.enable_cli') && ini_get('apc.cache_by_default')) {
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 ?\94\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.phppe\0\0È\90u[pe\0\0¬ËÕi¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Autoload/ClassMapGenerator.php\8b\12\0\0È\90u[\8b\12\0\0\8dĶ\ 1\0\0\0\0\0\0\16\0\0\0src/Composer/Cache.php\92\13\0\0È\90u[\92\13\0\0­b\9a\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Command/AboutCommand.phpÍ\ 2\0\0È\90u[Í\ 2\0\0³¢Ay¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/ArchiveCommand.phpc\14\0\0È\90u[c\14\0\0¥{\aï¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/BaseCommand.phpÜ\v\0\0È\90u[Ü\v\0\0\1a\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Command/BaseDependencyCommand.phpñ\18\0\0È\90u[ñ\18\0\0XgFð¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Command/CheckPlatformReqsCommand.php\9d\f\0\0È\90u[\9d\f\0\0\9fL\92\9e\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/ClearCacheCommand.php^\ 5\0\0È\90u[^\ 5\0\0\15¨ãj¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/ConfigCommand.php\89I\0\0È\90u[\89I\0\0ä³ï\80\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Command/CreateProjectCommand.php%5\0\0È\90u[%5\0\0è\1aP-¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/DependsCommand.php¸\ 2\0\0È\90u[¸\ 2\0\0\ 1K\e°¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/DiagnoseCommand.phpmI\0\0È\90u[mI\0\0]úE!¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Command/DumpAutoloadCommand.php\13
28 \0\0Ȑu[\13
29 \0\0Ý\ 4¸:¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ExecCommand.phpk\a\0\0È\90u[k\a\0\0¼\93À[¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/GlobalCommand.php@       \0\0È\90u[@ \0\0·©ð\ 1\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/HomeCommand.phpÄ\ e\0\0È\90u[Ä\ e\0\0Ç\aH\ 3\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/InitCommand.php\95K\0\0È\90u[\95K\0\0\84y\b\9f\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/InstallCommand.php\17\14\0\0È\90u[\17\14\0\0[\1c \9a\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/LicensesCommand.php;\ e\0\0È\90u[;\ e\0\0\a\99\8f\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/OutdatedCommand.php±
30 \0\0È\90u[±
31 \0\0¼\ 1LÓ¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/ProhibitsCommand.phpÌ\ 2\0\0È\90u[Ì\ 2\0\0\15¨[®¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/RemoveCommand.php\9c\15\0\0È\90u[\9c\15\0\0\8f¯¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/RequireCommand.php× \0\0È\90u[× \0\0³ª¨ß¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/RunScriptCommand.phpã\ e\0\0È\90u[ã\ e\0\0\98\15\eÔ¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Command/ScriptAliasCommand.phpp\ 5\0\0È\90u[p\ 5\0\0g\r\86\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/SearchCommand.php\10 \0\0È\90u[\10 \0\0Ò=Á\8b\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/SelfUpdateCommand.phpÌ2\0\0È\90u[Ì2\0\0\11Ú6\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ShowCommand.php_m\0\0È\90u[_m\0\0\82¤:a¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/StatusCommand.php\\15\0\0È\90u[\\15\0\0«I\ 3\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/SuggestsCommand.php©\r\0\0È\90u[©\r\0\0<Q\11þ¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/UpdateCommand.phpµ#\0\0È\90u[µ#\0\0@\8a4-¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/ValidateCommand.phpP\14\0\0È\90u[P\14\0\0|ugü¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Composer.phpù  \0\0È\90u[ù \0\0Ù÷\83À¶\ 1\0\0\0\0\0\0\17\0\0\0src/Composer/Config.phpÎ"\0\0È\90u[Î"\0\0)\16Î\¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Config/ConfigSourceInterface.php\ e\ 2\0\0È\90u[\ e\ 2\0\0³\f[/¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Config/JsonConfigSource.phpu\13\0\0È\90u[u\13\0\0\1c\83\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Console/Application.phpÚ3\0\0È\90u[Ú3\0\0\vý%D¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Console/HtmlOutputFormatter.php3\ 6\0\0È\90u[3\ 6\0\0Ú\81Eu¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/DependencyResolver/Decisions.phpQ\ f\0\0È\90u[Q\ f\0\0?\98¬$¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/DefaultPolicy.php\ 2\17\0\0È\90u[\ 2\17\0\0õÝv\7f\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/GenericRule.phpµ\ 3\0\0È\90u[µ\ 3\0\0\19᫤¶\ 1\0\0\0\0\0\0>\0\0\0src/Composer/DependencyResolver/Operation/InstallOperation.phpC\ 2\0\0È\90u[C\ 2\0\0´\õ*¶\ 1\0\0\0\0\0\0I\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php÷\ 2\0\0È\90u[÷\ 2\0\0ïÎà÷¶\ 1\0\0\0\0\0\0K\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpý\ 2\0\0È\90u[ý\ 2\0\0\193#\86\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ\0\0\0È\90u[Ó\0\0\0Ùâ&ä¶\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/SolverOperation.php¹\ 1\0\0È\90u[¹\ 1\0\0&¢e
32\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/UninstallOperation.phpI\ 2\0\0È\90u[I\ 2\0\0FûÂɶ\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/UpdateOperation.phph\ 3\0\0È\90u[h\ 3\0\0öSÕ]¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/PolicyInterface.php­\ 1\0\0È\90u[­\ 1\0\0\18\9f\8b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Pool.php°"\0\0È\90u[°"\0\0\1d   \8e\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Problem.php¤\18\0\0È\90u[¤\18\0\0\0\ 5\13Þ¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Request.php\83\ 4\0\0È\90u[\83\ 4\0\0åVP\84\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Rule.php«\18\0\0È\90u[«\18\0\0ôÓç´¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/Rule2Literals.php\18\ 5\0\0È\90u[\18\ 5\0\0tZÅɶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/RuleSet.phpª
33 \0\0È\90u[ª
34 \0\0\82\e\ 1\0\0\0\0\0\04\0\0\0src/Composer/DependencyResolver/RuleSetGenerator.phpF\e\0\0È\90u[F\e\0\0/I\ 4ж\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/RuleSetIterator.php\11\ 6\0\0È\90u[\11\ 6\0\0\9bCü$¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchChain.phpi\ 1\0\0È\90u[i\ 1\0\0\9a\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchGraph.phpá\ 6\0\0È\90u[á\ 6\0\0\89rôv¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/RuleWatchNode.php\ 5\ 4\0\0È\90u[\ 5\ 4\0\0\8fGd7¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/DependencyResolver/Solver.php,:\0\0È\90u[,:\0\0²ã~\9c\ 1\0\0\0\0\0\06\0\0\0src/Composer/DependencyResolver/SolverBugException.php\99\ 1\0\0È\90u[\99\ 1\0\0X\12g6¶\ 1\0\0\0\0\0\0;\0\0\0src/Composer/DependencyResolver/SolverProblemsException.phpô\a\0\0È\90u[ô\a\0\0×|Ŧ¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/Transaction.php×\13\0\0È\90u[×\13\0\0Vmì\9f\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Downloader/ArchiveDownloader.phpÆ      \0\0È\90u[Æ \0\0G s0¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Downloader/ChangeReportInterface.phpÌ\0\0\0È\90u[Ì\0\0\0¯à¨¿¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Downloader/DownloadManager.php`\15\0\0È\90u[`\15\0\0#ÏX\14\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/DownloaderInterface.phpÊ\ 1\0\0È\90u[Ê\ 1\0\0gs!l¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Downloader/DvcsDownloaderInterface.phpÑ\0\0\0È\90u[Ñ\0\0\0\9c¿¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/FileDownloader.php?\1c\0\0È\90u[?\1c\0\0"A\16ý¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/FilesystemException.php
35 \ 1\0\0Ȑu[
36 \ 1\0\0.-\1e\8b\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Downloader/FossilDownloader.php\82\v\0\0È\90u[\82\v\0\0Ü\81Ii¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/GitDownloader.phpq4\0\0È\90u[q4\0\0ZÎÇ׶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/GzipDownloader.phpó\ 6\0\0È\90u[ó\ 6\0\0}Úo¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/HgDownloader.php\94\b\0\0È\90u[\94\b\0\0ßis̶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PathDownloader.phpQ\11\0\0È\90u[Q\11\0\0Cn\ 3¤¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Downloader/PearPackageExtractor.phpu\e\0\0È\90u[u\e\0\0z\84\15\87\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/PerforceDownloader.php§\a\0\0È\90u[§\a\0\0â\83\10¨¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PharDownloader.phpå\0\0\0È\90u[å\0\0\0ÞÉ\1fç¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/RarDownloader.php\9e\a\0\0È\90u[\9e\a\0\06      3U¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/SvnDownloader.phpG\14\0\0È\90u[G\14\0\0M#j\1d\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/TarDownloader.phpã\0\0\0È\90u[ã\0\0\0Í\92X?¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/TransportException.php=\ 2\0\0È\90u[=\ 2\0\0ZÎÈÞ¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Downloader/VcsCapableDownloaderInterface.phpÔ\0\0\0È\90u[Ô\0\0\0`§ôö¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/VcsDownloader.php¡\16\0\0È\90u[¡\16\0\0(   à>¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/XzDownloader.php§\ 4\0\0È\90u[§\ 4\0\0W$;á¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/ZipDownloader.phpè\14\0\0È\90u[è\14\0\0Ó9\88ÿ¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/EventDispatcher/Event.php \ 2\0\0È\90u[ \ 2\0\0±\99jï¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/EventDispatcher/EventDispatcher.php 2\0\0È\90u[ 2\0\0anÕ3¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/EventSubscriberInterface.php©\0\0\0È\90u[©\0\0\0\ 1\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/ScriptExecutionException.phpv\0\0\0È\90u[v\0\0\0wZ8S¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Exception/NoSslException.phpf\0\0\0È\90u[f\0\0\0ËíM\9d\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Factory.phpR=\0\0È\90u[R=\0\0\ 2¤¶\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/BaseIO.php\8c\10\0\0È\90u[\8c\10\0\0(\82l\91\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/IO/BufferIO.php*\ 4\0\0È\90u[*\ 4\0\0¢®hT¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/IO/ConsoleIO.php6\17\0\0È\90u[6\17\0\0ö\19#$¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/IO/IOInterface.phpì\ 5\0\0È\90u[ì\ 5\0\0\0Õ\9d\ e\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/NullIO.phpÀ\ 4\0\0È\90u[À\ 4\0\0F`sʶ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/Installer.php\1e\9d\0\0È\90u[\1e\9d\0\0¡q4Ŷ\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/BinaryInstaller.php×\11\0\0È\90u[×\11\0\0£\14æq¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Installer/BinaryPresenceInterface.phpË\0\0\0È\90u[Ë\0\0\0À5\9a¨¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/InstallationManager.php-\17\0\0È\90u[-\17\0\0¾}\8c\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Installer/InstallerEvent.php\ e\ 6\0\0È\90u[\ e\ 6\0\0lÔzi¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/InstallerEvents.phpÞ\0\0\0È\90u[Þ\0\0\0ì\9f@G¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Installer/InstallerInterface.phpã\ 2\0\0È\90u[ã\ 2\0\0^\83\93ʶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/LibraryInstaller.php%\14\0\0È\90u[%\14\0\0\f»\8f̶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Installer/MetapackageInstaller.php\9c\ 4\0\0È\90u[\9c\ 4\0\0Æ\12Å!¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/NoopInstaller.php+\ 5\0\0È\90u[+\ 5\0\0À·M}¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Installer/PackageEvent.phpe\ 3\0\0È\90u[e\ 3\0\0;° \1a\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PackageEvents.php¸\ 1\0\0È\90u[¸\ 1\0\0dbØs¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/PearBinaryInstaller.phpø\f\0\0È\90u[ø\f\0\0\95\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PearInstaller.php¢\a\0\0È\90u[¢\a\0\0È\82¶Ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/PluginInstaller.php\8b\ 6\0\0È\90u[\8b\ 6\0\0\ fÒX8¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/ProjectInstaller.php\1d\ 6\0\0È\90u[\1d\ 6\0\0*0@P¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Installer/SuggestedPackagesReporter.php:\a\0\0È\90u[:\a\0\0\82´UV¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Json/JsonFile.phpî\13\0\0È\90u[î\13\0\0b-~\ 4\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Json/JsonFormatter.phpb\ 6\0\0È\90u[b\ 6\0\0\12ÝN\9a\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Json/JsonManipulator.php\923\0\0È\90u[\923\0\0é7\12\e\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Json/JsonValidationException.php\\ 1\0\0È\90u[\\ 1\0\0.Xóܶ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Package/AliasPackage.php\ 5\17\0\0È\90u[\ 5\17\0\0¹\97~\9a\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFilter.php     \ 2\0\0È\90u[ \ 2\0\0yY+¦¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFinder.phpÞ\ 5\0\0È\90u[Þ\ 5\0\0\f²²¹¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Archiver/ArchiveManager.php\86\f\0\0È\90u[\86\f\0\0ß5°\7f\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/ArchiverInterface.php\a\ 1\0\0È\90u[\a\ 1\0\0ñ´>\v\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/BaseExcludeFilter.php\96\ 6\0\0È\90u[\96\ 6\0\0y¶=ƶ\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ComposerExcludeFilter.php\1f\ 1\0\0È\90u[\1f\ 1\0\0\8bSZ0¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Package/Archiver/GitExcludeFilter.phpr\ 3\0\0È\90u[r\ 3\0\03\91Mh¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Archiver/HgExcludeFilter.php\v\ 5\0\0È\90u[\v\ 5\0\0\r\95¦S¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Archiver/PharArchiver.php?\ 6\0\0È\90u[?\ 6\0\0®\97      u¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/Archiver/ZipArchiver.php½\ 4\0\0È\90u[½\ 4\0\0\82¨¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/BasePackage.php&\r\0\0È\90u[&\r\0\0\e'\1fݶ\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Comparer/Comparer.php8\b\0\0È\90u[8\b\0\0O\f2¨¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Package/CompletePackage.phpü\ 6\0\0È\90u[ü\ 6\0\0þM˶¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/CompletePackageInterface.phpõ\ 1\0\0È\90u[õ\ 1\0\0¦Ê\81ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Dumper/ArrayDumper.php=\f\0\0È\90u[=\f\0\0T\\8b\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Package/Link.php\88\ 5\0\0È\90u[\88\ 5\0\0å¶Y«¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/EmptyConstraint.php\82\ 1\0\0È\90u[\82\ 1\0\0\ eé~\8b\ 1\0\0\0\0\0\0?\0\0\0src/Composer/Package/LinkConstraint/LinkConstraintInterface.phpd\ 1\0\0È\90u[d\ 1\0\0¤ôLn¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/MultiConstraint.php\82\ 1\0\0È\90u[\82\ 1\0\0ób`ý¶\ 1\0\0\0\0\0\0:\0\0\0src/Composer/Package/LinkConstraint/SpecificConstraint.phpi\ 1\0\0È\90u[i\ 1\0\0Þ\94\9a\ 1\0\0\0\0\0\09\0\0\0src/Composer/Package/LinkConstraint/VersionConstraint.phpX\ 1\0\0È\90u[X\ 1\0\0\ 2}`y¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Loader/ArrayLoader.php\1f\1e\0\0È\90u[\1f\1e\0\0n~\9c\9b\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Loader/InvalidPackageException.phpE\ 2\0\0È\90u[E\ 2\0\0xb\13¾¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Loader/JsonLoader.phpù\ 1\0\0È\90u[ù\ 1\0\0!~\88\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Loader/LoaderInterface.php²\0\0\0È\90u[²\0\0\0¦}úζ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Loader/RootPackageLoader.php\11\17\0\0È\90u[\11\17\0\0-\82£{¶\ 1\0\0\0\0\0\05\0\0\0src/Composer/Package/Loader/ValidatingArrayLoader.php­6\0\0È\90u[­6\0\0\\ 2æ0¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Package/Locker.php¥!\0\0È\90u[¥!\0\0/=xö¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Package/Package.phpÉ\1a\0\0È\90u[É\1a\0\0\8f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/PackageInterface.php \a\0\0È\90u[ \a\0\0ûÇ^ƶ\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/RootAliasPackage.php\1f        \0\0È\90u[\1f \0\0      _\80ø¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/RootPackage.php\11\ 5\0\0È\90u[\11\ 5\0\0\ 2\8eÎ_¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/RootPackageInterface.php¹\ 3\0\0È\90u[¹\ 3\0\0"maV¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Version/VersionGuesser.phpÏ\1d\0\0È\90u[Ï\1d\0\0ÌÂß\ 4\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Version/VersionParser.php¥\ 5\0\0È\90u[¥\ 5\0\0ô´\16à¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Version/VersionSelector.phpK\f\0\0È\90u[K\f\0\0²<\ fȶ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Plugin/Capability/Capability.phpW\0\0\0È\90u[W\0\0\0æ_¨1¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Plugin/Capability/CommandProvider.php\97\0\0\0È\90u[\97\0\0\0ûOâ>¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Plugin/Capable.php\7f\0\0\0È\90u[\7f\0\0\0Æq\15\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/CommandEvent.phpâ\ 2\0\0È\90u[â\ 2\0\0³ÆÇW¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/PluginEvents.phpö\0\0\0È\90u[ö\0\0\0á1=z¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Plugin/PluginInterface.phpô\0\0\0È\90u[ô\0\0\0)'*ض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Plugin/PluginManager.php\e$\0\0È\90u[\e$\0\0\8b\ 2K©¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Plugin/PreCommandRunEvent.phpõ\ 1\0\0È\90u[õ\ 1\0\0:ðd\1e\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Plugin/PreFileDownloadEvent.php`\ 2\0\0È\90u[`\ 2\0\0\09-ζ\ 1\0\0\0\0\0\04\0\0\0src/Composer/Question/StrictConfirmationQuestion.php\1e\ 5\0\0È\90u[\1e\ 5\0\0'.³è¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Repository/ArrayRepository.php\13\ e\0\0È\90u[\13\ e\0\0éÌt\0\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ArtifactRepository.phpê\f\0\0È\90u[ê\f\0\0\ f\88\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/BaseRepository.phpv\r\0\0È\90u[v\r\0\0\84Ü\18\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ComposerRepository.phpÐU\0\0È\90u[ÐU\0\0ü­l\8d\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/CompositeRepository.php;\b\0\0È\90u[;\b\0\0¤¯S\1f\ 1\0\0\0\0\0\0;\0\0\0src/Composer/Repository/ConfigurableRepositoryInterface.php\85\0\0\0È\90u[\85\0\0\0±\9f_\1c\ 1\0\0\0\0\0\00\0\0\0src/Composer/Repository/FilesystemRepository.php$\ 5\0\0È\90u[$\ 5\0\0¾Ãá\85\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/InstalledArrayRepository.php£\0\0\0È\90u[£\0\0\0/ö~>¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Repository/InstalledFilesystemRepository.php£\0\0\0È\90u[£\0\0\0V
37 \95\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/InstalledRepositoryInterface.php\87\0\0\0È\90u[\87\0\0\0\18£9p¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/Repository/InvalidRepositoryException.phpn\0\0\0È\90u[n\0\0\0à\93ë\98\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/PackageRepository.phpj\ 3\0\0È\90u[j\ 3\0\0¥ôò̶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PathRepository.php\96\v\0\0È\90u[\96\v\0\0\ 2\12\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Pear/BaseChannelReader.phpI\ 5\0\0È\90u[I\ 5\0\0c\b6³¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ChannelInfo.phpÄ\ 1\0\0È\90u[Ä\ 1\0\0:T*ɶ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Pear/ChannelReader.phpí\ 6\0\0È\90u[í\ 6\0\0?ÈYT¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest10Reader.php®        \0\0È\90u[® \0\0\99ÖÛú¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest11Reader.php& \0\0È\90u[& \0\0òUb\b\ 1\0\0\0\0\0\05\0\0\0src/Composer/Repository/Pear/DependencyConstraint.phpq\ 2\0\0È\90u[q\ 2\0\09\ e\17\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Pear/DependencyInfo.phpq\ 1\0\0È\90u[q\ 1\0\0fºTò¶\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/Pear/PackageDependencyParser.php\85\16\0\0È\90u[\85\16\0\0÷$Li¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/PackageInfo.php°\ 3\0\0È\90u[°\ 3\0\0\9f\r¸\f\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ReleaseInfo.php\92\ 1\0\0È\90u[\92\ 1\0\0o\93\8aö\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PearRepository.phpª\16\0\0È\90u[ª\16\0\0)\9f\83\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/PlatformRepository.php\b\e\0\0È\90u[\b\e\0\04&~û¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryFactory.php2\12\0\0È\90u[2\12\0\0\12t\ 4\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/RepositoryInterface.phpÛ\ 1\0\0È\90u[Û\ 1\0\0\92\11âÁ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryManager.php2
38 \0\0Ȑu[2
39 \0\0á\855#¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/RepositorySecurityException.phpo\0\0\0È\90u[o\0\0\0pÕ«ª¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Vcs/BitbucketDriver.phpô\1e\0\0È\90u[ô\1e\0\0\ 4x¤ü¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/FossilDriver.php¦\12\0\0È\90u[¦\12\0\0ébîd¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/GitBitbucketDriver.phpê\ 5\0\0È\90u[ê\ 5\0\0Ã\8e»\14\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/GitDriver.php¼\11\0\0È\90u[¼\11\0\0\8a©Ðê¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitHubDriver.php\)\0\0È\90u[\)\0\0'\9b\95\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitLabDriver.phpÍ#\0\0È\90u[Í#\0\0ßNìʶ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/Vcs/HgBitbucketDriver.phpä\ 5\0\0È\90u[ä\ 5\0\0i\9büà¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Repository/Vcs/HgDriver.phpV\11\0\0È\90u[V\11\0\0IÁFò¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Vcs/PerforceDriver.php'     \0\0È\90u[' \0\0ÙóH\ 5\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/SvnDriver.php\89\1c\0\0È\90u[\89\1c\0\0ÍßǬ¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/VcsDriver.phpæ
40 \0\0È\90u[æ
41 \0\0eׯ-¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/VcsDriverInterface.php÷\ 2\0\0È\90u[÷\ 2\0\0ÇX[\89\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/VcsRepository.php\r!\0\0È\90u[\r!\0\0c\ 6ÕK¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Repository/WritableArrayRepository.php\ f\ 3\0\0È\90u[\ f\ 3\0\0¾G\17\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/WritableRepositoryInterface.php\89\ 1\0\0È\90u[\89\ 1\0\0\91/sï¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/CommandEvent.phpW\0\0\0È\90u[W\0\0\0£VZt¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Script/Event.phpµ\ 2\0\0È\90u[µ\ 2\0\0lt¦M¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/PackageEvent.php\9c\0\0\0È\90u[\9c\0\0\0§ÿÉ\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/ScriptEvents.phpP\ 4\0\0È\90u[P\ 4\0\0\87\8f\ 4¶¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/SelfUpdate/Keys.php\9d\ 1\0\0È\90u[\9d\ 1\0\0\vîÊN¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/SelfUpdate/Versions.phpì\ 5\0\0È\90u[ì\ 5\0\0͵\91\83\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/AuthHelper.phpË\ 3\0\0È\90u[Ë\ 3\0\0>zx\96\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/Bitbucket.php%\15\0\0È\90u[%\15\0\0n=gÓ¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/ComposerMirror.php±\ 4\0\0È\90u[±\ 4\0\0­½øض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ConfigValidator.php÷\13\0\0È\90u[÷\13\0\0v\95Í\ 4\ 1\0\0\0\0\0\0"\0\0\0src/Composer/Util/ErrorHandler.php\87\ 4\0\0È\90u[\87\ 4\0\0He\1c\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/Filesystem.phpg/\0\0È\90u[g/\0\0|Îq÷¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Git.phpg&\0\0È\90u[g&\0\0]ó²´¶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitHub.phpw\r\0\0È\90u[w\r\0\0\e-SE¶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitLab.php\99\f\0\0È\90u[\99\f\0\0\17BLF¶\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Util/Hg.php¾\a\0\0È\90u[¾\a\0\0\f\9d\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/IniHelper.phph\ 2\0\0È\90u[h\ 2\0\0;F\b\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/NoProxyPattern.php¾\ 6\0\0È\90u[¾\ 6\0\0Z+°m¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Perforce.php\821\0\0È\90u[\821\0\0,\9cbx¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Platform.phpü\ 4\0\0È\90u[ü\ 4\0\0s­fç¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ProcessExecutor.phpÚ\v\0\0È\90u[Ú\v\0\0£ÒÙ\ 5\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Util/RemoteFilesystem.php
42 j\0\0Ȑu[
43 j\0\0\81Å\v´¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Silencer.phpé\ 2\0\0È\90u[é\ 2\0\0\93Vjf¶\ 1\0\0\0\0\0\0!\0\0\0src/Composer/Util/SpdxLicense.php\ 3\ 1\0\0È\90u[\ 3\ 1\0\0¾7
44 ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Util/StreamContextFactory.php\1d\10\0\0È\90u[\1d\10\0\0\9fÁI\ 2\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Svn.php'\14\0\0È\90u['\14\0\0|×x\89\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/TlsHelper.phpn
45 \0\0Ȑu[n
46 \0\0S¯Í:¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Url.php£\a\0\0È\90u[£\a\0\03\9cÉܶ\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/XdebugHandler.phpð\ 1\0\0È\90u[ð\ 1\0\0zÓf~¶\ 1\0\0\0\0\0\0\11\0\0\0src/bootstrap.php¹\ 1\0\0È\90u[¹\ 1\0\0\15I}\9c\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Autoload/ClassLoader.phpn4\0\0È\90u[n4\0\0êíÌ;¶\ 1\0\0\0\0\0\0#\0\0\0res/composer-repository-schema.jsonð\ f\0\0È\90u[ð\ f\0\0\81GÐà¶\ 1\0\0\0\0\0\0\18\0\0\0res/composer-schema.jsonÏ\95\0\0È\90u[Ï\95\0\0&\8fR\1a\ 1\0\0\0\0\0\06\0\0\0vendor/composer/spdx-licenses/res/spdx-exceptions.json\r\b\0\0È\90u[\r\b\0\0º\10¯\ f\ 1\0\0\0\0\0\04\0\0\0vendor/composer/spdx-licenses/res/spdx-licenses.json\9f\8f\0\0È\90u[\9f\8f\0\0J*B\14\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Resources/bin/hiddeninput.exe\0$\0\0È\90u[\0$\0\0\95\8d¥v¶\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Application.php\82W\0\0È\90u[\82W\0\0âPáz¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Command/Command.phpñ"\0\0È\90u[ñ"\0\0Ø\ eô\17\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/HelpCommand.phpØ\a\0\0È\90u[Ø\a\0\0$Y\1c«¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/ListCommand.phpZ\b\0\0È\90u[Z\b\0\0É£ \16\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/ConsoleEvents.phpé\0\0\0È\90u[é\0\0\0RÛÔe¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/console/Descriptor/ApplicationDescription.phpÐ\b\0\0È\90u[Ð\b\0\0\99\8e5°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Descriptor/Descriptor.php\8e\a\0\0È\90u[\8e\a\0\0éð8\9f\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Descriptor/DescriptorInterface.phpü\0\0\0È\90u[ü\0\0\0±Q\aµ¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/JsonDescriptor.phpÜ\r\0\0È\90u[Ü\r\0\0\9dɶ\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Descriptor/MarkdownDescriptor.php´\ e\0\0È\90u[´\ e\0\0\90!³g¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/TextDescriptor.php²\1e\0\0È\90u[²\1e\0\0\8f­ùâ¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Descriptor/XmlDescriptor.phpý\e\0\0È\90u[ý\e\0\0
47 G1¿¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Event/ConsoleCommandEvent.php°\ 1\0\0È\90u[°\ 1\0\0\a!\0ȶ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Event/ConsoleEvent.phpÅ\ 2\0\0È\90u[Å\ 2\0\0ÒxÛ\¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleExceptionEvent.php\12\ 3\0\0È\90u[\12\ 3\0\0á\162é¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleTerminateEvent.phpz\ 2\0\0È\90u[z\ 2\0\0³,îL¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/CommandNotFoundException.phpÔ\ 1\0\0È\90u[Ô\ 1\0\0È÷ L¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Exception/ExceptionInterface.phpf\0\0\0È\90u[f\0\0\0¡ABª¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/InvalidArgumentException.php¦\0\0\0È\90u[¦\0\0\0Ö̽Z¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/console/Exception/InvalidOptionException.php¦\0\0\0È\90u[¦\0\0\0\13Ë×H¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Exception/LogicException.php\92\0\0\0È\90u[\92\0\0\0ÍO\e¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/console/Exception/RuntimeException.php\96\0\0\0È\90u[\96\0\0\0Ùí,6¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Formatter/OutputFormatter.php2\ e\0\0È\90u[2\ e\0\0RÌYh¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Formatter/OutputFormatterInterface.php\8c\ 1\0\0È\90u[\8c\ 1\0\0òññÀ¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyle.phpJ\10\0\0È\90u[J\10\0\0ÏDSȶ\ 1\0\0\0\0\0\0B\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php\84\ 1\0\0È\90u[\84\ 1\0\0÷½\10\ 1\0\0\0\0\0\0>\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleStack.php>\ 5\0\0È\90u[>\ 5\0\0[\86¿\96\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Helper/DebugFormatterHelper.phpx\b\0\0È\90u[x\b\0\0N©Ø¼¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/DescriptorHelper.phpw\ 5\0\0È\90u[w\ 5\0\0ÅHð.¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Helper/DialogHelper.phpú\1e\0\0È\90u[ú\1e\0\0 "8m¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/FormatterHelper.phpc\ 4\0\0È\90u[c\ 4\0\0\93ý«N¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Helper/Helper.php¨\a\0\0È\90u[¨\a\0\0\9coû3¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/HelperInterface.phpå\0\0\0È\90u[å\0\0\0\1f\8a \18\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/HelperSet.phpÉ\a\0\0È\90u[É\a\0\0\f\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/InputAwareHelper.phpc\ 1\0\0È\90u[c\ 1\0\0ñø\90\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Helper/ProcessHelper.phpÑ     \0\0È\90u[Ñ \0\0@±ã\81\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/ProgressBar.phpk%\0\0È\90u[k%\0\0H]\84ȶ\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/ProgressHelper.php\\e\0\0È\90u[\\e\0\0è\12K+¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Helper/ProgressIndicator.phpK\14\0\0È\90u[K\14\0\0í\1cÍ°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/QuestionHelper.phpm\1c\0\0È\90u[m\1c\0\0ùÓ/¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Helper/SymfonyQuestionHelper.phpl
48 \0\0Ȑu[l
49 \0\0\1e÷ÞL¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/console/Helper/Table.phpª*\0\0È\90u[ª*\0\0í8ïM¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/TableCell.php\80\ 3\0\0È\90u[\80\ 3\0\0Ìî*Û¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/TableHelper.php\ e\f\0\0È\90u[\ e\f\0\0\83u®¹¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/TableSeparator.phpÊ\0\0\0È\90u[Ê\0\0\0az\1f\1c\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Helper/TableStyle.php\1f
50 \0\0Ȑu[\1f
51 \0\0PÞµ¦¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Input/ArgvInput.php\99\15\0\0È\90u[\99\15\0\0,»Bô¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Input/ArrayInput.php"\v\0\0È\90u["\v\0\0\99\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Input/Input.php¢\v\0\0È\90u[¢\v\0\0\94\87B"¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Input/InputArgument.php\10\ 6\0\0È\90u[\10\ 6\0\0&<¦¯¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Input/InputAwareInterface.php\9a\0\0\0È\90u[\9a\0\0\0\87jT\9f\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Input/InputDefinition.php\8a\19\0\0È\90u[\8a\19\0\0\9cäf²¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Input/InputInterface.php¡\ 3\0\0È\90u[¡\ 3\0\0,t^>¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/InputOption.php\11\f\0\0È\90u[\11\f\0\0¸¬\8f\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/StringInput.php\96\ 6\0\0È\90u[\96\ 6\0\0cì\(¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/console/LICENSE)\ 4\0\0È\90u[)\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Logger/ConsoleLogger.php.    \0\0È\90u[. \0\0¤\8c\85ζ\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Output/BufferedOutput.php_\ 1\0\0È\90u[_\ 1\0\0\8b >P¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Output/ConsoleOutput.php°\a\0\0È\90u[°\a\0\0]k~o¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Output/ConsoleOutputInterface.phpà\0\0\0È\90u[à\0\0\0\87\86Æʶ\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Output/NullOutput.phpÏ\ 3\0\0È\90u[Ï\ 3\0\0®\98\8b\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Output/Output.php\98  \0\0È\90u[\98 \0\0\1fpf\¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Output/OutputInterface.php\17\ 3\0\0È\90u[\17\ 3\0\0\0ì\ 6\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Output/StreamOutput.php­\ 6\0\0È\90u[­\ 6\0\0Îs6­¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Question/ChoiceQuestion.phpw
52 \0\0Ȑu[w
53 \0\02\15t\ 6\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Question/ConfirmationQuestion.phpç\ 2\0\0È\90u[ç\ 2\0\0\r­òf¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Question/Question.phpË     \0\0È\90u[Ë \0\0ÒqµR¶\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/console/Shell.phpå\ f\0\0È\90u[å\ f\0\0\95\9axS¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Style/OutputStyle.php\\ 5\0\0È\90u[\\ 5\0\0wפ\ 4\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Style/StyleInterface.phpÏ\ 3\0\0È\90u[Ï\ 3\0\0&nÅѶ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Style/SymfonyStyle.phpÜ\1f\0\0È\90u[Ü\1f\0\0j®|R¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Tester/ApplicationTester.phpÏ\ 5\0\0È\90u[Ï\ 5\0\0s\9e9i¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Tester/CommandTester.phpª\ 6\0\0È\90u[ª\ 6\0\0µ.âr¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/debug/BufferingLogger.phpt\ 1\0\0È\90u[t\ 1\0\0=\0hܶ\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/debug/Debug.php\ 6\ 3\0\0È\90u[\ 6\ 3\0\0\ e\98'Ķ\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/DebugClassLoader.php¡\1d\0\0È\90u[¡\1d\0\0tÅÍT¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/debug/ErrorHandler.php\13H\0\0È\90u[\13H\0\0\82vÌJ¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/debug/Exception/ClassNotFoundException.php\96\ 1\0\0È\90u[\96\ 1\0\0i\89æô¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/debug/Exception/ContextErrorException.php\98\ 1\0\0È\90u[\98\ 1\0\0-
54 d2¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/debug/Exception/DummyException.php\ 2\ 1\0\0È\90u[\ 2\ 1\0\0®+Ãê¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalErrorException.php\f\a\0\0È\90u[\f\a\0\0\8893?¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalThrowableError.phpW\ 2\0\0È\90u[W\ 2\0\0?àèK¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/debug/Exception/FlattenException.php²\16\0\0È\90u[²\16\0\0HòÑ\ f\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/debug/Exception/OutOfMemoryException.php~\0\0\0È\90u[~\0\0\0ë¨oâ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/debug/Exception/UndefinedFunctionException.php\9a\ 1\0\0È\90u[\9a\ 1\0\0\81ñJÀ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/debug/Exception/UndefinedMethodException.php\98\ 1\0\0È\90u[\98\ 1\0\0nöêض\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/ExceptionHandler.php!3\0\0È\90u[!3\0\0\fÏq ¶\ 1\0\0\0\0\0\0I\0\0\0vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php7\12\0\0È\90u[7\12\0\0Ñj/=¶\ 1\0\0\0\0\0\0E\0\0\0vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php\ 3\ 1\0\0È\90u[\ 3\ 1\0\0ĹBV¶\ 1\0\0\0\0\0\0M\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.phpu\b\0\0È\90u[u\b\0\0éj\ 3\19\ 1\0\0\0\0\0\0K\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.phpN\ 5\0\0È\90u[N\ 5\0\0Ço-ç¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/symfony/debug/LICENSE)\ 4\0\0È\90u[)\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/filesystem/Exception/ExceptionInterface.phpi\0\0\0È\90u[i\0\0\0$ ÿ\9b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/filesystem/Exception/FileNotFoundException.php¼\ 1\0\0È\90u[¼\ 1\0\0pí\¶¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/filesystem/Exception/IOException.php\87\ 1\0\0È\90u[\87\ 1\0\0\80ü#Ѷ\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/filesystem/Exception/IOExceptionInterface.php¦\0\0\0È\90u[¦\0\0\0jÙwM¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/filesystem/Filesystem.phpK4\0\0È\90u[K4\0\0½oC·¶\ 1\0\0\0\0\0\0!\0\0\0vendor/symfony/filesystem/LICENSE)\ 4\0\0È\90u[)\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/filesystem/LockHandler.phpö\ 5\0\0È\90u[ö\ 5\0\0\9fZµ1¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Adapter/AbstractAdapter.php\\v\0\0È\90u[\\v\0\0h\19\88\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Adapter/AbstractFindAdapter.php\8b\19\0\0È\90u[\8b\19\0\0\85\ eÔж\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/finder/Adapter/AdapterInterface.php\9b\ 3\0\0È\90u[\9b\ 3\0\0M\aþ\e\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/BsdFindAdapter.php2\a\0\0È\90u[2\a\0\0\15+Eì¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/GnuFindAdapter.php\15\a\0\0È\90u[\15\a\0\0è\84JL¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/finder/Adapter/PhpAdapter.phpô\a\0\0È\90u[ô\a\0\0Þdè;¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Comparator/Comparator.php\8c\ 3\0\0È\90u[\8c\ 3\0\0\16wþT¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Comparator/DateComparator.php#\ 3\0\0È\90u[#\ 3\0\0\16°\1fζ\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Comparator/NumberComparator.php|\ 3\0\0È\90u[|\ 3\0\0ITÇͶ\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Exception/AccessDeniedException.php\84\0\0\0È\90u[\84\0\0\0½¾s\9c\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Exception/AdapterFailureException.php¬\ 2\0\0È\90u[¬\ 2\0\0w\1e\18\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/finder/Exception/ExceptionInterface.php\84\0\0\0È\90u[\84\0\0\0\1cGz-¶\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Exception/OperationNotPermitedException.php)\ 1\0\0È\90u[)\ 1\0\0x\1f§e¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/finder/Exception/ShellCommandFailureException.phpº\ 2\0\0È\90u[º\ 2\0\0\98þ\15\98\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Expression/Expression.php\a\ 6\0\0È\90u[\a\ 6\0\0i¥:Ŷ\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/finder/Expression/Glob.phpf\ 4\0\0È\90u[f\ 4\0\0DÞcj¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/finder/Expression/Regex.php\ 4\ f\0\0È\90u[\ 4\ f\0\0ü(Ã϶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Expression/ValueInterface.phpÍ\ 1\0\0È\90u[Í\ 1\0\0\p4\86\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/finder/Finder.php].\0\0È\90u[].\0\0dìÇ¿¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/finder/Glob.phpK\ 5\0\0È\90u[K\ 5\0\0já±n¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/finder/Iterator/CustomFilterIterator.php[\ 2\0\0È\90u[[\ 2\0\0­\ 4åW¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpx\ 2\0\0È\90u[x\ 2\0\0\ fô\ 3\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpî\ 1\0\0È\90u[î\ 1\0\0üÍ\9d\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.phpí\ 5\0\0È\90u[í\ 5\0\0n\ 5õH¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/finder/Iterator/FilePathsIterator.php \ 6\0\0È\90u[ \ 6\0\0^ÁkF¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FileTypeFilterIterator.phpZ\ 2\0\0È\90u[Z\ 2\0\0(\1a&ø¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/finder/Iterator/FilecontentFilterIterator.php5\ 2\0\0È\90u[5\ 2\0\0\9aí\1f\14\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FilenameFilterIterator.phpr\ 1\0\0È\90u[r\ 1\0\0t\b\1a\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Iterator/FilterIterator.phpÃ\ 2\0\0È\90u[Ã\ 2\0\0\9a+µÞ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php-\ 5\0\0È\90u[-\ 5\0\0ºÎÒ_¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Iterator/PathFilterIterator.phpÏ\ 1\0\0È\90u[Ï\ 1\0\0º\1cªÇ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php\13   \0\0È\90u[\13 \0\0 \12ÿ¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpe\ 2\0\0È\90u[e\ 2\0\0\9f\92áé¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Iterator/SortableIterator.php*\ 6\0\0È\90u[*\ 6\0\0\80õ´^¶\ 1\0\0\0\0\0\0\1d\0\0\0vendor/symfony/finder/LICENSE)\ 4\0\0È\90u[)\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/finder/Shell/Command.php<\v\0\0È\90u[<\v\0\0\84\ 6R\9f\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/Shell/Shell.phpp\ 4\0\0È\90u[p\ 4\0\0QT\10\8f\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/SplFileInfo.php\ 6\ 3\0\0È\90u[\ 6\ 3\0\0þ\0íù¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/polyfill-ctype/Ctype.phpH   \0\0È\90u[H \0\0³\9dÕݶ\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/polyfill-ctype/LICENSE$\ 4\0\0È\90u[$\ 4\0\0?\87s:¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/polyfill-ctype/bootstrap.phpI\ 3\0\0È\90u[I\ 3\0\0\8fD!e¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/polyfill-mbstring/LICENSE)\ 4\0\0È\90u[)\ 4\0\0±\ 3íж\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/polyfill-mbstring/Mbstring.php\13C\0\0È\90u[\13C\0\0\19æø\ 6\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php2A\0\0È\90u[2A\0\0½\11=¨¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php¡A\0\0È\90u[¡A\0\0\ eÚ       Í¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/polyfill-mbstring/bootstrap.phpË\10\0\0È\90u[Ë\10\0\0ó<Ë¢¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/process/Exception/ExceptionInterface.phpf\0\0\0È\90u[f\0\0\0]ö>T¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/InvalidArgumentException.php¨\0\0\0È\90u[¨\0\0\0ÐÀ+_¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/process/Exception/LogicException.php\94\0\0\0È\90u[\94\0\0\0 ³ãñ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/process/Exception/ProcessFailedException.phpx\ 3\0\0È\90u[x\ 3\0\0¨Ìzy¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/ProcessTimedOutException.php\1f\ 4\0\0È\90u[\1f\ 4\0\0\7fï\ e«¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/process/Exception/RuntimeException.php\98\0\0\0È\90u[\98\0\0\0¢\eØ:¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/process/ExecutableFinder.php\9a\ 4\0\0È\90u[\9a\ 4\0\0T\92³É¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/process/LICENSE)\ 4\0\0È\90u[)\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/PhpExecutableFinder.phpÈ\ 4\0\0È\90u[È\ 4\0\0\9a(À®¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/process/PhpProcess.phpú\ 3\0\0È\90u[ú\ 3\0\0¯\93Õ\81\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/Pipes/AbstractPipes.php»\a\0\0È\90u[»\a\0\0 V\10\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/process/Pipes/PipesInterface.phpD\ 1\0\0È\90u[D\ 1\0\0vØ\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/process/Pipes/UnixPipes.php>\b\0\0È\90u[>\b\0\0ª\95ir¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/process/Pipes/WindowsPipes.php\89\v\0\0È\90u[\89\v\0\0\bÀ"¢¶\ 1\0\0\0\0\0\0"\0\0\0vendor/symfony/process/Process.php£R\0\0È\90u[£R\0\0ÁÜÕ(¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/process/ProcessBuilder.phpß
55 \0\0È\90u[ß
56 \0\0^\83\17\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/process/ProcessUtils.phpK\ 6\0\0È\90u[K\ 6\0\02ÁÞg¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/seld/jsonlint/LICENSE"\ 4\0\0È\90u["\ 4\0\0a\83sy¶\ 1\0\0\0\0\0\0@\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php*\ 1\0\0È\90u[*\ 1\0\0\19\95pñ¶\ 1\0\0\0\0\0\05\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.php/2\0\0È\90u[/2\0\0­ß\98ö¶\ 1\0\0\0\0\0\00\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.php\ 6\ f\0\0È\90u[\ 6\ f\0\0%ÿ3N¶\ 1\0\0\0\0\0\0;\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/ParsingException.php\1e\ 1\0\0È\90u[\1e\ 1\0\0\89²\10ñ¶\ 1\0\0\0\0\0\04\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/Undefined.php>\0\0\0È\90u[>\0\0\0ÿq\9f\9f\ 1\0\0\0\0\0\0(\0\0\0vendor/justinrainbow/json-schema/LICENSE \ 4\0\0È\90u[ \ 4\0\0ºç\ 6©¶\ 1\0\0\0\0\0\0.\0\0\0vendor/justinrainbow/json-schema/demo/demo.phpñ\ 1\0\0È\90u[ñ\ 1\0\0f\e\12\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php¡      \0\0È\90u[¡ \0\0\86wÌl¶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php)\r\0\0È\90u[)\r\0\0\14\14\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php§\r\0\0È\90u[§\r\0\0\9b\18\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php¼\ 1\0\0È\90u[¼\ 1\0\0ÿ Q\9c\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php]\ 3\0\0È\90u[]\ 3\0\0V\8eU<¶\ 1\0\0\0\0\0\0G\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.phpã\f\0\0È\90u[ã\f\0\0á0;\16\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php\85\14\0\0È\90u[\85\14\0\0\93T\9cÚ¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php\9a
57 \0\0È\90u[\9a
58 \0\0\15\1ez&¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.phpÃ\11\0\0È\90u[Ã\11\0\0©Å¼x¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php0 \0\0È\90u[0 \0\0×j´\98\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php\7f\ 4\0\0È\90u[\7f\ 4\0\0¥w\9a\87\ 1\0\0\0\0\0\0X\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.phpa\ 4\0\0È\90u[a\ 4\0\0\v     qö\ 1\0\0\0\0\0\0Y\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.phpp\ 2\0\0È\90u[p\ 2\0\0\12r\1fë¶\ 1\0\0\0\0\0\0\\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php\89\ 1\0\0È\90u[\89\ 1\0\0\93µ+j¶\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php&\ f\0\0È\90u[&\ f\0\04\98©T¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php,"\0\0È\90u[,"\0\0ulÙ·¶\ 1\0\0\0\0\0\0F\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.phpè\ 6\0\0È\90u[è\ 6\0\0\ 6{N\96\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.phpI\0\0\0È\90u[I\0\0\0%|\19°¶\ 1\0\0\0\0\0\0V\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php\95\0\0\0È\90u[\95\0\0\0\8bàG\ 5\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidConfigException.phpl\0\0\0È\90u[l\0\0\0A!L׶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaException.phpl\0\0\0È\90u[l\0\0\0è2÷þ¶\ 1\0\0\0\0\0\0]\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.phpu\0\0\0È\90u[u\0\0\0=hç\a\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.phpw\0\0\0È\90u[w\0\0\0N-ò[¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ\ 2\0\0È\90u[Þ\ 2\0\0\r
59\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpo\0\0\0È\90u[o\0\0\0píÛù¶\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php\85\0\0\0È\90u[\85\0\0\0\b%\85\97\ 1\0\0\0\0\0\0^\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php\80\0\0\0È\90u[\80\0\0\0u-#1¶\ 1\0\0\0\0\0\0R\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.phpj\0\0\0È\90u[j\0\0\0å\1a>\8f\ 1\0\0\0\0\0\0Q\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ValidationException.phpf\0\0\0È\90u[f\0\0\0¬¤\84þ¶\ 1\0\0\0\0\0\0K\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.phpþ\ 5\0\0È\90u[þ\ 5\0\0M\8f\84õ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php \ 2\0\0È\90u[ \ 2\0\0f4÷³¶\ 1\0\0\0\0\0\0A\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php\9c\r\0\0È\90u[\9c\r\0\0\ 2åfO¶\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php\ 1\ 1\0\0È\90u[\ 1\ 1\0\0o\8a+}¶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.phpá\0\0\0È\90u[á\0\0\0[þA\81\ 1\0\0\0\0\0\0G\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php¥\ 4\0\0È\90u[¥\ 4\0\0Ô§Lb¶\ 1\0\0\0\0\0\0R\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php%\ 5\0\0È\90u[%\ 5\0\05"\10 ¶\ 1\0\0\0\0\0\0R\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php,\ 2\0\0È\90u[,\ 2\0\01\955þ¶\ 1\0\0\0\0\0\0X\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php®\0\0\0È\90u[®\0\0\0ÿ\8bÁå¶\ 1\0\0\0\0\0\0C\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php\ 5\v\0\0È\90u[\ 5\v\0\0£\9f)à¶\ 1\0\0\0\0\0\0D\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php&\13\0\0È\90u[&\13\0\0¼î\82¢¶\ 1\0\0\0\0\0\0H\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php\83\0\0\0È\90u[\83\0\0\0\12J\80\1f\ 1\0\0\0\0\0\0I\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php\85\0\0\0È\90u[\85\0\0\0íæ\e\ 1\0\0\0\0\0\0=\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Validator.phpx\ 5\0\0È\90u[x\ 5\0\0e\17Ãþ¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/spdx-licenses/LICENSE\1c\ 4\0\0È\90u[\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\02\0\0\0vendor/composer/spdx-licenses/src/SpdxLicenses.phpH\14\0\0È\90u[H\14\0\0Í\89T\ 4\ 1\0\0\0\0\0\0\1e\0\0\0vendor/composer/semver/LICENSE\1c\ 4\0\0È\90u[\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\0)\0\0\0vendor/composer/semver/src/Comparator.php\ 2\ 4\0\0È\90u[\ 2\ 4\0\0wl\83ï¶\ 1\0\0\0\0\0\0<\0\0\0vendor/composer/semver/src/Constraint/AbstractConstraint.php×\ 2\0\0È\90u[×\ 2\0\0õî>\8e\ 1\0\0\0\0\0\04\0\0\0vendor/composer/semver/src/Constraint/Constraint.phpª\f\0\0È\90u[ª\f\0\0ÇO7²¶\ 1\0\0\0\0\0\0=\0\0\0vendor/composer/semver/src/Constraint/ConstraintInterface.phpß\0\0\0È\90u[ß\0\0\00C,\87\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/EmptyConstraint.phpé\ 1\0\0È\90u[é\ 1\0\0!-Ø\99\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/MultiConstraint.php1\ 5\0\0È\90u[1\ 5\0\0í xU¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/semver/src/Semver.phpv\ 6\0\0È\90u[v\ 6\0\0\8b×È\9b\ 1\0\0\0\0\0\0,\0\0\0vendor/composer/semver/src/VersionParser.php¿*\0\0È\90u[¿*\0\0\13)mƶ\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/ca-bundle/LICENSE\1c\ 4\0\0È\90u[\1c\ 4\0\0*!^`¶\ 1\0\0\0\0\0\0*\0\0\0vendor/composer/ca-bundle/src/CaBundle.php\15\1d\0\0È\90u[\15\1d\0\0Ê\v~Ķ\ 1\0\0\0\0\0\0&\0\0\0vendor/composer/xdebug-handler/LICENSE)\ 4\0\0È\90u[)\ 4\0\0#Ô;^¶\ 1\0\0\0\0\0\00\0\0\0vendor/composer/xdebug-handler/src/PhpConfig.php´\ 2\0\0È\90u[´\ 2\0\0*D\92\0\ 1\0\0\0\0\0\0.\0\0\0vendor/composer/xdebug-handler/src/Process.phpt\b\0\0È\90u[t\b\0\0Û\8cú&¶\ 1\0\0\0\0\0\0-\0\0\0vendor/composer/xdebug-handler/src/Status.phpì  \0\0È\90u[ì \0\0je¿û¶\ 1\0\0\0\0\0\04\0\0\0vendor/composer/xdebug-handler/src/XdebugHandler.php\9a\1c\0\0È\90u[\9a\1c\0\0ÞéE?¶\ 1\0\0\0\0\0\0\16\0\0\0vendor/psr/log/LICENSE=\ 4\0\0È\90u[=\ 4\0\0\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/AbstractLogger.php;\ 4\0\0È\90u[;\ 4\0\0ñ>3[¶\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/InvalidArgumentException.php`\0\0\0È\90u[`\0\0\0 \88X1¶\ 1\0\0\0\0\0\0#\0\0\0vendor/psr/log/Psr/Log/LogLevel.phpû\0\0\0È\90u[û\0\0\0jðñ8¶\ 1\0\0\0\0\0\0/\0\0\0vendor/psr/log/Psr/Log/LoggerAwareInterface.php|\0\0\0È\90u[|\0\0\0$\13£\88\ 1\0\0\0\0\0\0+\0\0\0vendor/psr/log/Psr/Log/LoggerAwareTrait.php§\0\0\0È\90u[§\0\0\0T½úB¶\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/LoggerInterface.phpÆ\ 2\0\0È\90u[Æ\ 2\0\0»\12sg¶\ 1\0\0\0\0\0\0&\0\0\0vendor/psr/log/Psr/Log/LoggerTrait.phpi\ 4\0\0È\90u[i\ 4\0\035§Þ¶\ 1\0\0\0\0\0\0%\0\0\0vendor/psr/log/Psr/Log/NullLogger.php\9e\0\0\0È\90u[\9e\0\0\0Ç\ 2Ã\1f\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.phpü\f\0\0È\90u[ü\f\0\0iq0ض\ 1\0\0\0\0\0\0\13\0\0\0vendor/autoload.php\82\0\0\0È\90u[\82\0\0\0Z\10\94\9f\ 1\0\0\0\0\0\0'\0\0\0vendor/composer/autoload_namespaces.phpd\0\0\0È\90u[d\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_psr4.php÷\ 4\0\0È\90u[÷\ 4\0\0Å*\9a\16\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/autoload_classmap.phpd\0\0\0È\90u[d\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0"\0\0\0vendor/composer/autoload_files.php\1f\ 1\0\0È\90u[\1f\ 1\0\0¥\0 ®¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_real.phpI\a\0\0È\90u[I\a\0\0f]\ eÿ¶\ 1\0\0\0\0\0\0#\0\0\0vendor/composer/autoload_static.php§
60 \0\0È\90u[§
61 \0\0\16ë Î¶\ 1\0\0\0\0\0\0\1f\0\0\0vendor/composer/ClassLoader.php\83\18\0\0È\90u[\83\18\0\0«Ñëæ¶\ 1\0\0\0\0\0\0(\0\0\0vendor/composer/ca-bundle/res/cacert.pem»C\ 3\0È\90u[»C\ 3\0f.À¬¶\ 1\0\0\0\0\0\0\f\0\0\0bin/composeró\ 5\0\0È\90u[ó\ 5\0\0]UÌ\80\ 1\0\0\0\0\0\0\a\0\0\0LICENSE.\ 4\0\0È\90u[.\ 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
85
86
87
88
89 class AutoloadGenerator
90 {
91
92
93
94 private $eventDispatcher;
95
96
97
98
99 private $io;
100
101
102
103
104 private $devMode = false;
105
106
107
108
109 private $classMapAuthoritative = false;
110
111
112
113
114 private $apcu = false;
115
116
117
118
119 private $runScripts = false;
120
121 public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
122 {
123 $this->eventDispatcher = $eventDispatcher;
124 $this->io = $io;
125 }
126
127 public function setDevMode($devMode = true)
128 {
129 $this->devMode = (bool) $devMode;
130 }
131
132
133
134
135
136
137
138 public function setClassMapAuthoritative($classMapAuthoritative)
139 {
140 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
141 }
142
143
144
145
146
147
148 public function setApcu($apcu)
149 {
150 $this->apcu = (bool) $apcu;
151 }
152
153
154
155
156
157
158 public function setRunScripts($runScripts = true)
159 {
160 $this->runScripts = (bool) $runScripts;
161 }
162
163 public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
164 {
165 if ($this->classMapAuthoritative) {
166
167  $scanPsr0Packages = true;
168 }
169 if ($this->runScripts) {
170 $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
171 'optimize' => (bool) $scanPsr0Packages,
172 ));
173 }
174
175 $filesystem = new Filesystem();
176 $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
177
178  
179  
180  $basePath = $filesystem->normalizePath(realpath(realpath(getcwd())));
181 $vendorPath = $filesystem->normalizePath(realpath(realpath($config->get('vendor-dir'))));
182 $useGlobalIncludePath = (bool) $config->get('use-include-path');
183 $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
184 $targetDir = $vendorPath.'/'.$targetDir;
185 $filesystem->ensureDirectoryExists($targetDir);
186
187 $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
188 $vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
189 $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
190
191 $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
192 $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
193
194 $namespacesFile = <<<EOF
195 <?php
196
197 // autoload_namespaces.php @generated by Composer
198
199 \$vendorDir = $vendorPathCode52;
200 \$baseDir = $appBaseDirCode;
201
202 return array(
203
204 EOF;
205
206 $psr4File = <<<EOF
207 <?php
208
209 // autoload_psr4.php @generated by Composer
210
211 \$vendorDir = $vendorPathCode52;
212 \$baseDir = $appBaseDirCode;
213
214 return array(
215
216 EOF;
217
218
219  $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
220 $autoloads = $this->parseAutoloads($packageMap, $mainPackage, $this->devMode === false);
221
222
223  foreach ($autoloads['psr-0'] as $namespace => $paths) {
224 $exportedPaths = array();
225 foreach ($paths as $path) {
226 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
227 }
228 $exportedPrefix = var_export($namespace, true);
229 $namespacesFile .= "    $exportedPrefix => ";
230 $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
231 }
232 $namespacesFile .= ");\n";
233
234
235  foreach ($autoloads['psr-4'] as $namespace => $paths) {
236 $exportedPaths = array();
237 foreach ($paths as $path) {
238 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
239 }
240 $exportedPrefix = var_export($namespace, true);
241 $psr4File .= "    $exportedPrefix => ";
242 $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
243 }
244 $psr4File .= ");\n";
245
246 $classmapFile = <<<EOF
247 <?php
248
249 // autoload_classmap.php @generated by Composer
250
251 \$vendorDir = $vendorPathCode52;
252 \$baseDir = $appBaseDirCode;
253
254 return array(
255
256 EOF;
257
258
259  $targetDirLoader = null;
260 $mainAutoload = $mainPackage->getAutoload();
261 if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
262 $levels = substr_count($filesystem->normalizePath($mainPackage->getTargetDir()), '/') + 1;
263 $prefixes = implode(', ', array_map(function ($prefix) {
264 return var_export($prefix, true);
265 }, array_keys($mainAutoload['psr-0'])));
266 $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
267
268 $targetDirLoader = <<<EOF
269
270     public static function autoload(\$class)
271     {
272         \$dir = $baseDirFromTargetDirCode . '/';
273         \$prefixes = array($prefixes);
274         foreach (\$prefixes as \$prefix) {
275             if (0 !== strpos(\$class, \$prefix)) {
276                 continue;
277             }
278             \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), $levels)).'.php';
279             if (!\$path = stream_resolve_include_path(\$path)) {
280                 return false;
281             }
282             require \$path;
283
284             return true;
285         }
286     }
287
288 EOF;
289 }
290
291 $blacklist = null;
292 if (!empty($autoloads['exclude-from-classmap'])) {
293 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
294 }
295
296
297  $classMap = array();
298 if ($scanPsr0Packages) {
299 $namespacesToScan = array();
300
301
302  foreach (array('psr-0', 'psr-4') as $psrType) {
303 foreach ($autoloads[$psrType] as $namespace => $paths) {
304 $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
305 }
306 }
307
308 krsort($namespacesToScan);
309
310 foreach ($namespacesToScan as $namespace => $groups) {
311 foreach ($groups as $group) {
312 foreach ($group['paths'] as $dir) {
313 $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
314 if (!is_dir($dir)) {
315 continue;
316 }
317
318 $namespaceFilter = $namespace === '' ? null : $namespace;
319 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespaceFilter, $classMap);
320 }
321 }
322 }
323 }
324
325 foreach ($autoloads['classmap'] as $dir) {
326 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, $classMap);
327 }
328
329 ksort($classMap);
330 foreach ($classMap as $class => $code) {
331 $classmapFile .= '    '.var_export($class, true).' => '.$code;
332 }
333 $classmapFile .= ");\n";
334
335 if (!$suffix) {
336 if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
337 $content = file_get_contents($vendorPath.'/autoload.php');
338 if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
339 $suffix = $match[1];
340 }
341 }
342
343 if (!$suffix) {
344 $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true));
345 }
346 }
347
348 file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
349 file_put_contents($targetDir.'/autoload_psr4.php', $psr4File);
350 file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);
351 $includePathFilePath = $targetDir.'/include_paths.php';
352 if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
353 file_put_contents($includePathFilePath, $includePathFileContents);
354 } elseif (file_exists($includePathFilePath)) {
355 unlink($includePathFilePath);
356 }
357 $includeFilesFilePath = $targetDir.'/autoload_files.php';
358 if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
359 file_put_contents($includeFilesFilePath, $includeFilesFileContents);
360 } elseif (file_exists($includeFilesFilePath)) {
361 unlink($includeFilesFilePath);
362 }
363 file_put_contents($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
364 file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
365 file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
366
367 $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
368 $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
369
370 if ($this->runScripts) {
371 $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
372 'optimize' => (bool) $scanPsr0Packages,
373 ));
374 }
375 }
376
377 private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist = null, $namespaceFilter = null, array $classMap = array())
378 {
379 foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter) as $class => $path) {
380 $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
381 if (!isset($classMap[$class])) {
382 $classMap[$class] = $pathCode;
383 } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
384 $this->io->writeError(
385 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
386 ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
387 );
388 }
389 }
390
391 return $classMap;
392 }
393
394 private function generateClassMap($dir, $blacklist = null, $namespaceFilter = null, $showAmbiguousWarning = true)
395 {
396 return ClassMapGenerator::createMap($dir, $blacklist, $showAmbiguousWarning ? $this->io : null, $namespaceFilter);
397 }
398
399 public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
400 {
401
402  $packageMap = array(array($mainPackage, ''));
403
404 foreach ($packages as $package) {
405 if ($package instanceof AliasPackage) {
406 continue;
407 }
408 $this->validatePackage($package);
409
410 $packageMap[] = array(
411 $package,
412 $installationManager->getInstallPath($package),
413 );
414 }
415
416 return $packageMap;
417 }
418
419
420
421
422
423
424 protected function validatePackage(PackageInterface $package)
425 {
426 $autoload = $package->getAutoload();
427 if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
428 $name = $package->getName();
429 $package->getTargetDir();
430 throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '$name'.");
431 }
432 if (!empty($autoload['psr-4'])) {
433 foreach ($autoload['psr-4'] as $namespace => $dirs) {
434 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
435 throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '$namespace' does not, use '$namespace\\'.");
436 }
437 }
438 }
439 }
440
441
442
443
444
445
446
447
448
449 public function parseAutoloads(array $packageMap, PackageInterface $mainPackage, $filterOutRequireDevPackages = false)
450 {
451 $mainPackageMap = array_shift($packageMap);
452 if ($filterOutRequireDevPackages) {
453 $packageMap = $this->filterPackageMap($packageMap, $mainPackage);
454 }
455 $sortedPackageMap = $this->sortPackageMap($packageMap);
456 $sortedPackageMap[] = $mainPackageMap;
457 array_unshift($packageMap, $mainPackageMap);
458
459 $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
460 $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
461 $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
462 $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
463 $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
464
465 krsort($psr0);
466 krsort($psr4);
467
468 return array(
469 'psr-0' => $psr0,
470 'psr-4' => $psr4,
471 'classmap' => $classmap,
472 'files' => $files,
473 'exclude-from-classmap' => $exclude,
474 );
475 }
476
477
478
479
480
481
482
483 public function createLoader(array $autoloads)
484 {
485 $loader = new ClassLoader();
486
487 if (isset($autoloads['psr-0'])) {
488 foreach ($autoloads['psr-0'] as $namespace => $path) {
489 $loader->add($namespace, $path);
490 }
491 }
492
493 if (isset($autoloads['psr-4'])) {
494 foreach ($autoloads['psr-4'] as $namespace => $path) {
495 $loader->addPsr4($namespace, $path);
496 }
497 }
498
499 if (isset($autoloads['classmap'])) {
500 $blacklist = null;
501 if (!empty($autoloads['exclude-from-classmap'])) {
502 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
503 }
504
505 foreach ($autoloads['classmap'] as $dir) {
506 try {
507 $loader->addClassMap($this->generateClassMap($dir, $blacklist, null, false));
508 } catch (\RuntimeException $e) {
509 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
510 }
511 }
512 }
513
514 return $loader;
515 }
516
517 protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
518 {
519 $includePaths = array();
520
521 foreach ($packageMap as $item) {
522 list($package, $installPath) = $item;
523
524 if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
525 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
526 }
527
528 foreach ($package->getIncludePaths() as $includePath) {
529 $includePath = trim($includePath, '/');
530 $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
531 }
532 }
533
534 if (!$includePaths) {
535 return;
536 }
537
538 $includePathsCode = '';
539 foreach ($includePaths as $path) {
540 $includePathsCode .= "    " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
541 }
542
543 return <<<EOF
544 <?php
545
546 // include_paths.php @generated by Composer
547
548 \$vendorDir = $vendorPathCode;
549 \$baseDir = $appBaseDirCode;
550
551 return array(
552 $includePathsCode);
553
554 EOF;
555 }
556
557 protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
558 {
559 $filesCode = '';
560 foreach ($files as $fileIdentifier => $functionFile) {
561 $filesCode .= '    ' . var_export($fileIdentifier, true) . ' => '
562 . $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile) . ",\n";
563 }
564
565 if (!$filesCode) {
566 return false;
567 }
568
569 return <<<EOF
570 <?php
571
572 // autoload_files.php @generated by Composer
573
574 \$vendorDir = $vendorPathCode;
575 \$baseDir = $appBaseDirCode;
576
577 return array(
578 $filesCode);
579
580 EOF;
581 }
582
583 protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $path)
584 {
585 if (!$filesystem->isAbsolutePath($path)) {
586 $path = $basePath . '/' . $path;
587 }
588 $path = $filesystem->normalizePath($path);
589
590 $baseDir = '';
591 if (strpos($path.'/', $vendorPath.'/') === 0) {
592 $path = substr($path, strlen($vendorPath));
593 $baseDir = '$vendorDir';
594
595 if ($path !== false) {
596 $baseDir .= " . ";
597 }
598 } else {
599 $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, true));
600 if (!$filesystem->isAbsolutePath($path)) {
601 $baseDir = '$baseDir . ';
602 $path = '/' . $path;
603 }
604 }
605
606 if (preg_match('/\.phar.+$/', $path)) {
607 $baseDir = "'phar://' . " . $baseDir;
608 }
609
610 return $baseDir . (($path !== false) ? var_export($path, true) : "");
611 }
612
613 protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix)
614 {
615 $lastChar = $vendorPathToTargetDirCode[strlen($vendorPathToTargetDirCode) - 1];
616 if ("'" === $lastChar || '"' === $lastChar) {
617 $vendorPathToTargetDirCode = substr($vendorPathToTargetDirCode, 0, -1).'/autoload_real.php'.$lastChar;
618 } else {
619 $vendorPathToTargetDirCode .= " . '/autoload_real.php'";
620 }
621
622 return <<<AUTOLOAD
623 <?php
624
625 // autoload.php @generated by Composer
626
627 require_once $vendorPathToTargetDirCode;
628
629 return ComposerAutoloaderInit$suffix::getLoader();
630
631 AUTOLOAD;
632 }
633
634 protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion = 70000)
635 {
636 $file = <<<HEADER
637 <?php
638
639 // autoload_real.php @generated by Composer
640
641 class ComposerAutoloaderInit$suffix
642 {
643     private static \$loader;
644
645     public static function loadClassLoader(\$class)
646     {
647         if ('Composer\\Autoload\\ClassLoader' === \$class) {
648             require __DIR__ . '/ClassLoader.php';
649         }
650     }
651
652     public static function getLoader()
653     {
654         if (null !== self::\$loader) {
655             return self::\$loader;
656         }
657
658         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader);
659         self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
660         spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
661
662
663 HEADER;
664
665 if ($useIncludePath) {
666 $file .= <<<'INCLUDE_PATH'
667         $includePaths = require __DIR__ . '/include_paths.php';
668         $includePaths[] = get_include_path();
669         set_include_path(implode(PATH_SEPARATOR, $includePaths));
670
671
672 INCLUDE_PATH;
673 }
674
675 $file .= <<<STATIC_INIT
676         \$useStaticLoader = PHP_VERSION_ID >= $staticPhpVersion && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
677         if (\$useStaticLoader) {
678             require_once __DIR__ . '/autoload_static.php';
679
680             call_user_func(\Composer\Autoload\ComposerStaticInit$suffix::getInitializer(\$loader));
681         } else {
682
683 STATIC_INIT;
684
685 if (!$this->classMapAuthoritative) {
686 $file .= <<<'PSR04'
687             $map = require __DIR__ . '/autoload_namespaces.php';
688             foreach ($map as $namespace => $path) {
689                 $loader->set($namespace, $path);
690             }
691
692             $map = require __DIR__ . '/autoload_psr4.php';
693             foreach ($map as $namespace => $path) {
694                 $loader->setPsr4($namespace, $path);
695             }
696
697
698 PSR04;
699 }
700
701 if ($useClassMap) {
702 $file .= <<<'CLASSMAP'
703             $classMap = require __DIR__ . '/autoload_classmap.php';
704             if ($classMap) {
705                 $loader->addClassMap($classMap);
706             }
707
708 CLASSMAP;
709 }
710
711 $file .= "        }\n\n";
712
713 if ($this->classMapAuthoritative) {
714 $file .= <<<'CLASSMAPAUTHORITATIVE'
715         $loader->setClassMapAuthoritative(true);
716
717 CLASSMAPAUTHORITATIVE;
718 }
719
720 if ($this->apcu) {
721 $apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
722 $file .= <<<APCU
723         \$loader->setApcuPrefix('$apcuPrefix');
724
725 APCU;
726 }
727
728 if ($useGlobalIncludePath) {
729 $file .= <<<'INCLUDEPATH'
730         $loader->setUseIncludePath(true);
731
732 INCLUDEPATH;
733 }
734
735 if ($targetDirLoader) {
736 $file .= <<<REGISTER_TARGET_DIR_AUTOLOAD
737         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true, true);
738
739
740 REGISTER_TARGET_DIR_AUTOLOAD;
741 }
742
743 $file .= <<<REGISTER_LOADER
744         \$loader->register($prependAutoloader);
745
746
747 REGISTER_LOADER;
748
749 if ($useIncludeFiles) {
750 $file .= <<<INCLUDE_FILES
751         if (\$useStaticLoader) {
752             \$includeFiles = Composer\Autoload\ComposerStaticInit$suffix::\$files;
753         } else {
754             \$includeFiles = require __DIR__ . '/autoload_files.php';
755         }
756         foreach (\$includeFiles as \$fileIdentifier => \$file) {
757             composerRequire$suffix(\$fileIdentifier, \$file);
758         }
759
760
761 INCLUDE_FILES;
762 }
763
764 $file .= <<<METHOD_FOOTER
765         return \$loader;
766     }
767
768 METHOD_FOOTER;
769
770 $file .= $targetDirLoader;
771
772 if ($useIncludeFiles) {
773 return $file . <<<FOOTER
774 }
775
776 function composerRequire$suffix(\$fileIdentifier, \$file)
777 {
778     if (empty(\$GLOBALS['__composer_autoload_files'][\$fileIdentifier])) {
779         require \$file;
780
781         \$GLOBALS['__composer_autoload_files'][\$fileIdentifier] = true;
782     }
783 }
784
785 FOOTER;
786 }
787
788 return $file . <<<FOOTER
789 }
790
791 FOOTER;
792 }
793
794 protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion)
795 {
796 $staticPhpVersion = 50600;
797
798 $file = <<<HEADER
799 <?php
800
801 // autoload_static.php @generated by Composer
802
803 namespace Composer\Autoload;
804
805 class ComposerStaticInit$suffix
806 {
807
808 HEADER;
809
810 $loader = new ClassLoader();
811
812 $map = require $targetDir . '/autoload_namespaces.php';
813 foreach ($map as $namespace => $path) {
814 $loader->set($namespace, $path);
815 }
816
817 $map = require $targetDir . '/autoload_psr4.php';
818 foreach ($map as $namespace => $path) {
819 $loader->setPsr4($namespace, $path);
820 }
821
822 $classMap = require $targetDir . '/autoload_classmap.php';
823 if ($classMap) {
824 $loader->addClassMap($classMap);
825 }
826
827 $filesystem = new Filesystem();
828
829 $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
830 $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
831
832 $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
833 $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
834
835 $initializer = '';
836 $prefix = "\0Composer\Autoload\ClassLoader\0";
837 $prefixLen = strlen($prefix);
838 if (file_exists($targetDir . '/autoload_files.php')) {
839 $maps = array('files' => require $targetDir . '/autoload_files.php');
840 } else {
841 $maps = array();
842 }
843
844 foreach ((array) $loader as $prop => $value) {
845 if ($value && 0 === strpos($prop, $prefix)) {
846 $maps[substr($prop, $prefixLen)] = $value;
847 }
848 }
849
850 foreach ($maps as $prop => $value) {
851 if (count($value) > 32767) {
852
853  
854  $staticPhpVersion = 70000;
855 }
856 $value = var_export($value, true);
857 $value = str_replace($absoluteVendorPathCode, $vendorPathCode, $value);
858 $value = str_replace($absoluteAppBaseDirCode, $appBaseDirCode, $value);
859 $value = ltrim(preg_replace('/^ */m', '    $0$0', $value));
860
861 $file .= sprintf("    public static $%s = %s;\n\n", $prop, $value);
862 if ('files' !== $prop) {
863 $initializer .= "            \$loader->$prop = ComposerStaticInit$suffix::\$$prop;\n";
864 }
865 }
866
867 return $file . <<<INITIALIZER
868     public static function getInitializer(ClassLoader \$loader)
869     {
870         return \Closure::bind(function () use (\$loader) {
871 $initializer
872         }, null, ClassLoader::class);
873     }
874 }
875
876 INITIALIZER;
877 }
878
879 protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
880 {
881 $autoloads = array();
882
883 foreach ($packageMap as $item) {
884 list($package, $installPath) = $item;
885
886 $autoload = $package->getAutoload();
887 if ($this->devMode && $package === $mainPackage) {
888 $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
889 }
890
891
892  if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
893 continue;
894 }
895 if (null !== $package->getTargetDir() && $package !== $mainPackage) {
896 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
897 }
898
899 foreach ($autoload[$type] as $namespace => $paths) {
900 foreach ((array) $paths as $path) {
901 if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
902
903  if ($package === $mainPackage) {
904 $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
905 $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
906 } else {
907
908  $path = $package->getTargetDir() . '/' . $path;
909 }
910 }
911
912 if ($type === 'exclude-from-classmap') {
913
914  $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
915
916
917  $path = str_replace('\\*\\*', '.+?', $path);
918 $path = str_replace('\\*', '[^/]+?', $path);
919
920
921  $updir = null;
922 $path = preg_replace_callback(
923 '{^((?:(?:\\\\\\.){1,2}+/)+)}',
924 function ($matches) use (&$updir) {
925 if (isset($matches[1])) {
926
927  $updir = str_replace('\\.', '.', $matches[1]);
928 }
929
930 return '';
931 },
932 $path
933 );
934 if (empty($installPath)) {
935 $installPath = strtr(getcwd(), '\\', '/');
936 }
937
938 $resolvedPath = realpath($installPath . '/' . $updir);
939 $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path;
940 continue;
941 }
942
943 $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
944
945 if ($type === 'files') {
946 $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
947 continue;
948 } elseif ($type === 'classmap') {
949 $autoloads[] = $relativePath;
950 continue;
951 }
952
953 $autoloads[$namespace][] = $relativePath;
954 }
955 }
956 }
957
958 return $autoloads;
959 }
960
961 protected function getFileIdentifier(PackageInterface $package, $path)
962 {
963 return md5($package->getName() . ':' . $path);
964 }
965
966
967
968
969
970
971
972
973 protected function filterPackageMap(array $packageMap, PackageInterface $mainPackage)
974 {
975 $packages = array();
976 $include = array();
977
978 foreach ($packageMap as $item) {
979 $package = $item[0];
980 $name = $package->getName();
981 $packages[$name] = $package;
982 }
983
984 $add = function (PackageInterface $package) use (&$add, $packages, &$include) {
985 foreach ($package->getRequires() as $link) {
986 $target = $link->getTarget();
987 if (!isset($include[$target])) {
988 $include[$target] = true;
989 if (isset($packages[$target])) {
990 $add($packages[$target]);
991 }
992 }
993 }
994 };
995 $add($mainPackage);
996
997 return array_filter(
998 $packageMap,
999 function ($item) use ($include) {
1000 $package = $item[0];
1001 $name = $package->getName();
1002
1003 return isset($include[$name]);
1004 }
1005 );
1006 }
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016 protected function sortPackageMap(array $packageMap)
1017 {
1018 $packages = array();
1019 $paths = array();
1020 $usageList = array();
1021
1022 foreach ($packageMap as $item) {
1023 list($package, $path) = $item;
1024 $name = $package->getName();
1025 $packages[$name] = $package;
1026 $paths[$name] = $path;
1027
1028 foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) {
1029 $target = $link->getTarget();
1030 $usageList[$target][] = $name;
1031 }
1032 }
1033
1034 $computing = array();
1035 $computed = array();
1036 $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
1037
1038  if (isset($computed[$name])) {
1039 return $computed[$name];
1040 }
1041
1042
1043  if (isset($computing[$name])) {
1044 return 0;
1045 }
1046
1047 $computing[$name] = true;
1048 $weight = 0;
1049
1050 if (isset($usageList[$name])) {
1051 foreach ($usageList[$name] as $user) {
1052 $weight -= 1 - $computeImportance($user);
1053 }
1054 }
1055
1056 unset($computing[$name]);
1057 $computed[$name] = $weight;
1058
1059 return $weight;
1060 };
1061
1062 $weightList = array();
1063
1064 foreach ($packages as $name => $package) {
1065 $weight = $computeImportance($name);
1066 $weightList[$name] = $weight;
1067 }
1068
1069 $stable_sort = function (&$array) {
1070 static $transform, $restore;
1071
1072 $i = 0;
1073
1074 if (!$transform) {
1075 $transform = function (&$v, $k) use (&$i) {
1076 $v = array($v, ++$i, $k, $v);
1077 };
1078
1079 $restore = function (&$v, $k) {
1080 $v = $v[3];
1081 };
1082 }
1083
1084 array_walk($array, $transform);
1085 asort($array);
1086 array_walk($array, $restore);
1087 };
1088
1089 $stable_sort($weightList);
1090
1091 $sortedPackageMap = array();
1092
1093 foreach (array_keys($weightList) as $name) {
1094 $sortedPackageMap[] = array($packages[$name], $paths[$name]);
1095 }
1096
1097 return $sortedPackageMap;
1098 }
1099
1100
1101
1102
1103
1104
1105
1106 protected function safeCopy($source, $target)
1107 {
1108 $source = fopen($source, 'r');
1109 $target = fopen($target, 'w+');
1110
1111 stream_copy_to_stream($source, $target);
1112 fclose($source);
1113 fclose($target);
1114 }
1115 }
1116 <?php
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134 namespace Composer\Autoload;
1135
1136 use Symfony\Component\Finder\Finder;
1137 use Composer\IO\IOInterface;
1138 use Composer\Util\Filesystem;
1139
1140
1141
1142
1143
1144
1145
1146 class ClassMapGenerator
1147 {
1148
1149
1150
1151
1152
1153
1154 public static function dump($dirs, $file)
1155 {
1156 $maps = array();
1157
1158 foreach ($dirs as $dir) {
1159 $maps = array_merge($maps, static::createMap($dir));
1160 }
1161
1162 file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
1163 }
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176 public static function createMap($path, $blacklist = null, IOInterface $io = null, $namespace = null)
1177 {
1178 if (is_string($path)) {
1179 if (is_file($path)) {
1180 $path = array(new \SplFileInfo($path));
1181 } elseif (is_dir($path)) {
1182 $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
1183 } else {
1184 throw new \RuntimeException(
1185 'Could not scan for classes inside "'.$path.
1186 '" which does not appear to be a file nor a folder'
1187 );
1188 }
1189 }
1190
1191 $map = array();
1192 $filesystem = new Filesystem();
1193 $cwd = realpath(getcwd());
1194
1195 foreach ($path as $file) {
1196 $filePath = $file->getPathname();
1197 if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
1198 continue;
1199 }
1200
1201 if (!$filesystem->isAbsolutePath($filePath)) {
1202 $filePath = $cwd . '/' . $filePath;
1203 $filePath = $filesystem->normalizePath($filePath);
1204 } else {
1205 $filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath);
1206 }
1207
1208
1209  if ($blacklist && preg_match($blacklist, strtr(realpath($filePath), '\\', '/'))) {
1210 continue;
1211 }
1212
1213  if ($blacklist && preg_match($blacklist, strtr($filePath, '\\', '/'))) {
1214 continue;
1215 }
1216
1217 $classes = self::findClasses($filePath);
1218
1219 foreach ($classes as $class) {
1220
1221  if (null !== $namespace && 0 !== strpos($class, $namespace)) {
1222 continue;
1223 }
1224
1225 if (!isset($map[$class])) {
1226 $map[$class] = $filePath;
1227 } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
1228 $io->writeError(
1229 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
1230 ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
1231 );
1232 }
1233 }
1234 }
1235
1236 return $map;
1237 }
1238
1239
1240
1241
1242
1243
1244
1245
1246 private static function findClasses($path)
1247 {
1248 $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
1249 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
1250 $extraTypes .= '|enum';
1251 }
1252
1253
1254  
1255  $contents = @php_strip_whitespace($path);
1256 if (!$contents) {
1257 if (!file_exists($path)) {
1258 $message = 'File at "%s" does not exist, check your classmap definitions';
1259 } elseif (!is_readable($path)) {
1260 $message = 'File at "%s" is not readable, check its permissions';
1261 } elseif ('' === trim(file_get_contents($path))) {
1262
1263  return array();
1264 } else {
1265 $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
1266 }
1267 $error = error_get_last();
1268 if (isset($error['message'])) {
1269 $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
1270 }
1271 throw new \RuntimeException(sprintf($message, $path));
1272 }
1273
1274
1275  if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
1276 return array();
1277 }
1278
1279
1280  $contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents);
1281
1282  $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
1283
1284  if (substr($contents, 0, 2) !== '<?') {
1285 $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
1286 if ($replacements === 0) {
1287 return array();
1288 }
1289 }
1290
1291  $contents = preg_replace('{\?>.+<\?}s', '?><?', $contents);
1292
1293  $pos = strrpos($contents, '?>');
1294 if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
1295 $contents = substr($contents, 0, $pos);
1296 }
1297
1298  if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
1299 $contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
1300 }
1301
1302 preg_match_all('{
1303             (?:
1304                  \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
1305                | \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*+ [\{;]
1306             )
1307         }ix', $contents, $matches);
1308
1309 $classes = array();
1310 $namespace = '';
1311
1312 for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
1313 if (!empty($matches['ns'][$i])) {
1314 $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
1315 } else {
1316 $name = $matches['name'][$i];
1317
1318  if ($name === 'extends' || $name === 'implements') {
1319 continue;
1320 }
1321 if ($name[0] === ':') {
1322
1323  $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
1324 } elseif ($matches['type'][$i] === 'enum') {
1325
1326  
1327  
1328  
1329  $name = rtrim($name, ':');
1330 }
1331 $classes[] = ltrim($namespace . $name, '\\');
1332 }
1333 }
1334
1335 return $classes;
1336 }
1337 }
1338 <?php
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350 namespace Composer;
1351
1352 use Composer\IO\IOInterface;
1353 use Composer\Util\Filesystem;
1354 use Composer\Util\Silencer;
1355 use Symfony\Component\Finder\Finder;
1356
1357
1358
1359
1360
1361
1362 class Cache
1363 {
1364 private static $cacheCollected = false;
1365 private $io;
1366 private $root;
1367 private $enabled = true;
1368 private $whitelist;
1369 private $filesystem;
1370
1371
1372
1373
1374
1375
1376
1377 public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
1378 {
1379 $this->io = $io;
1380 $this->root = rtrim($cacheDir, '/\\') . '/';
1381 $this->whitelist = $whitelist;
1382 $this->filesystem = $filesystem ?: new Filesystem();
1383
1384 if (preg_match('{(^|[\\\\/])(\$null|NUL|/dev/null)([\\\\/]|$)}', $cacheDir)) {
1385 $this->enabled = false;
1386
1387 return;
1388 }
1389
1390 if (
1391 (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, true))
1392 || !is_writable($this->root)
1393 ) {
1394 $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
1395 $this->enabled = false;
1396 }
1397 }
1398
1399 public function isEnabled()
1400 {
1401 return $this->enabled;
1402 }
1403
1404 public function getRoot()
1405 {
1406 return $this->root;
1407 }
1408
1409 public function read($file)
1410 {
1411 if ($this->enabled) {
1412 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1413 if (file_exists($this->root . $file)) {
1414 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1415
1416 return file_get_contents($this->root . $file);
1417 }
1418 }
1419
1420 return false;
1421 }
1422
1423 public function write($file, $contents)
1424 {
1425 if ($this->enabled) {
1426 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1427
1428 $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
1429
1430 try {
1431 return file_put_contents($this->root . $file, $contents);
1432 } catch (\ErrorException $e) {
1433 $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', true, IOInterface::DEBUG);
1434 if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
1435
1436  unlink($this->root . $file);
1437
1438 $message = sprintf(
1439 '<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available</warning>',
1440 $this->root . $file,
1441 $m[1],
1442 $m[2],
1443 @disk_free_space($this->root . dirname($file))
1444 );
1445
1446 $this->io->writeError($message);
1447
1448 return false;
1449 }
1450
1451 throw $e;
1452 }
1453 }
1454
1455 return false;
1456 }
1457
1458
1459
1460
1461 public function copyFrom($file, $source)
1462 {
1463 if ($this->enabled) {
1464 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1465 $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
1466
1467 if (!file_exists($source)) {
1468 $this->io->writeError('<error>'.$source.' does not exist, can not write into cache</error>');
1469 } elseif ($this->io->isDebug()) {
1470 $this->io->writeError('Writing '.$this->root . $file.' into cache from '.$source);
1471 }
1472
1473 return copy($source, $this->root . $file);
1474 }
1475
1476 return false;
1477 }
1478
1479
1480
1481
1482 public function copyTo($file, $target)
1483 {
1484 if ($this->enabled) {
1485 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1486 if (file_exists($this->root . $file)) {
1487 try {
1488 touch($this->root . $file, filemtime($this->root . $file), time());
1489 } catch (\ErrorException $e) {
1490
1491  
1492  Silencer::call('touch', $this->root . $file);
1493 }
1494
1495 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1496
1497 return copy($this->root . $file, $target);
1498 }
1499 }
1500
1501 return false;
1502 }
1503
1504 public function gcIsNecessary()
1505 {
1506 return (!self::$cacheCollected && !mt_rand(0, 50));
1507 }
1508
1509 public function remove($file)
1510 {
1511 if ($this->enabled) {
1512 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1513 if (file_exists($this->root . $file)) {
1514 return $this->filesystem->unlink($this->root . $file);
1515 }
1516 }
1517
1518 return false;
1519 }
1520
1521 public function clear()
1522 {
1523 if ($this->enabled) {
1524 return $this->filesystem->removeDirectory($this->root);
1525 }
1526
1527 return false;
1528 }
1529
1530 public function gc($ttl, $maxSize)
1531 {
1532 if ($this->enabled) {
1533 $expire = new \DateTime();
1534 $expire->modify('-'.$ttl.' seconds');
1535
1536 $finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
1537 foreach ($finder as $file) {
1538 $this->filesystem->unlink($file->getPathname());
1539 }
1540
1541 $totalSize = $this->filesystem->size($this->root);
1542 if ($totalSize > $maxSize) {
1543 $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
1544 while ($totalSize > $maxSize && $iterator->valid()) {
1545 $filepath = $iterator->current()->getPathname();
1546 $totalSize -= $this->filesystem->size($filepath);
1547 $this->filesystem->unlink($filepath);
1548 $iterator->next();
1549 }
1550 }
1551
1552 self::$cacheCollected = true;
1553
1554 return true;
1555 }
1556
1557 return false;
1558 }
1559
1560 public function sha1($file)
1561 {
1562 if ($this->enabled) {
1563 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1564 if (file_exists($this->root . $file)) {
1565 return sha1_file($this->root . $file);
1566 }
1567 }
1568
1569 return false;
1570 }
1571
1572 public function sha256($file)
1573 {
1574 if ($this->enabled) {
1575 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1576 if (file_exists($this->root . $file)) {
1577 return hash_file('sha256', $this->root . $file);
1578 }
1579 }
1580
1581 return false;
1582 }
1583
1584 protected function getFinder()
1585 {
1586 return Finder::create()->in($this->root)->files();
1587 }
1588 }
1589 <?php
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601 namespace Composer\Command;
1602
1603 use Symfony\Component\Console\Input\InputInterface;
1604 use Symfony\Component\Console\Output\OutputInterface;
1605
1606
1607
1608
1609 class AboutCommand extends BaseCommand
1610 {
1611 protected function configure()
1612 {
1613 $this
1614 ->setName('about')
1615 ->setDescription('Shows the short information about Composer.')
1616 ->setHelp(
1617 <<<EOT
1618 <info>php composer.phar about</info>
1619 EOT
1620 )
1621 ;
1622 }
1623
1624 protected function execute(InputInterface $input, OutputInterface $output)
1625 {
1626 $this->getIO()->write(
1627 <<<EOT
1628 <info>Composer - Package Management for PHP</info>
1629 <comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
1630 See https://getcomposer.org/ for more information.</comment>
1631 EOT
1632 );
1633 }
1634 }
1635 <?php
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647 namespace Composer\Command;
1648
1649 use Composer\Factory;
1650 use Composer\IO\IOInterface;
1651 use Composer\Config;
1652 use Composer\Composer;
1653 use Composer\Repository\CompositeRepository;
1654 use Composer\Repository\RepositoryFactory;
1655 use Composer\Script\ScriptEvents;
1656 use Composer\Plugin\CommandEvent;
1657 use Composer\Plugin\PluginEvents;
1658 use Composer\Util\Filesystem;
1659 use Symfony\Component\Console\Input\InputArgument;
1660 use Symfony\Component\Console\Input\InputInterface;
1661 use Symfony\Component\Console\Input\InputOption;
1662 use Symfony\Component\Console\Output\OutputInterface;
1663
1664
1665
1666
1667
1668
1669 class ArchiveCommand extends BaseCommand
1670 {
1671 protected function configure()
1672 {
1673 $this
1674 ->setName('archive')
1675 ->setDescription('Creates an archive of this composer package.')
1676 ->setDefinition(array(
1677 new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project'),
1678 new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'),
1679 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar or zip'),
1680 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
1681 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
1682 .' Note that the format will be appended.'),
1683 new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
1684 ))
1685 ->setHelp(
1686 <<<EOT
1687 The <info>archive</info> command creates an archive of the specified format
1688 containing the files and directories of the Composer project or the specified
1689 package in the specified version and writes it to the specified directory.
1690
1691 <info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
1692
1693 EOT
1694 )
1695 ;
1696 }
1697
1698 protected function execute(InputInterface $input, OutputInterface $output)
1699 {
1700 $config = Factory::createConfig();
1701 $composer = $this->getComposer(false);
1702 if ($composer) {
1703 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
1704 $eventDispatcher = $composer->getEventDispatcher();
1705 $eventDispatcher->dispatch($commandEvent->getName(), $commandEvent);
1706 $eventDispatcher->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
1707 }
1708
1709 if (null === $input->getOption('format')) {
1710 $input->setOption('format', $config->get('archive-format'));
1711 }
1712 if (null === $input->getOption('dir')) {
1713 $input->setOption('dir', $config->get('archive-dir'));
1714 }
1715
1716 $returnCode = $this->archive(
1717 $this->getIO(),
1718 $config,
1719 $input->getArgument('package'),
1720 $input->getArgument('version'),
1721 $input->getOption('format'),
1722 $input->getOption('dir'),
1723 $input->getOption('file'),
1724 $input->getOption('ignore-filters'),
1725 $composer
1726 );
1727
1728 if (0 === $returnCode && $composer) {
1729 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
1730 }
1731
1732 return $returnCode;
1733 }
1734
1735 protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null, $ignoreFilters = false, Composer $composer = null)
1736 {
1737 if ($composer) {
1738 $archiveManager = $composer->getArchiveManager();
1739 } else {
1740 $factory = new Factory;
1741 $downloadManager = $factory->createDownloadManager($io, $config);
1742 $archiveManager = $factory->createArchiveManager($config, $downloadManager);
1743 }
1744
1745 if ($packageName) {
1746 $package = $this->selectPackage($io, $packageName, $version);
1747
1748 if (!$package) {
1749 return 1;
1750 }
1751 } else {
1752 $package = $this->getComposer()->getPackage();
1753 }
1754
1755 $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
1756 $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
1757 $fs = new Filesystem;
1758 $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
1759
1760 $io->writeError('Created: ', false);
1761 $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
1762
1763 return 0;
1764 }
1765
1766 protected function selectPackage(IOInterface $io, $packageName, $version = null)
1767 {
1768 $io->writeError('<info>Searching for the specified package.</info>');
1769
1770 if ($composer = $this->getComposer(false)) {
1771 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
1772 $repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
1773 } else {
1774 $defaultRepos = RepositoryFactory::defaultRepos($this->getIO());
1775 $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
1776 $repo = new CompositeRepository($defaultRepos);
1777 }
1778
1779 $packages = $repo->findPackages($packageName, $version);
1780
1781 if (count($packages) > 1) {
1782 $package = reset($packages);
1783 $io->writeError('<info>Found multiple matches, selected '.$package->getPrettyString().'.</info>');
1784 $io->writeError('Alternatives were '.implode(', ', array_map(function ($p) {
1785 return $p->getPrettyString();
1786 }, $packages)).'.');
1787 $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
1788 } elseif ($packages) {
1789 $package = reset($packages);
1790 $io->writeError('<info>Found an exact match '.$package->getPrettyString().'.</info>');
1791 } else {
1792 $io->writeError('<error>Could not find a package matching '.$packageName.'.</error>');
1793
1794 return false;
1795 }
1796
1797 return $package;
1798 }
1799 }
1800 <?php
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812 namespace Composer\Command;
1813
1814 use Composer\Composer;
1815 use Composer\Config;
1816 use Composer\Console\Application;
1817 use Composer\Factory;
1818 use Composer\IO\IOInterface;
1819 use Composer\IO\NullIO;
1820 use Composer\Plugin\PreCommandRunEvent;
1821 use Composer\Plugin\PluginEvents;
1822 use Symfony\Component\Console\Input\InputInterface;
1823 use Symfony\Component\Console\Output\OutputInterface;
1824 use Symfony\Component\Console\Command\Command;
1825
1826
1827
1828
1829
1830
1831
1832 abstract class BaseCommand extends Command
1833 {
1834
1835
1836
1837 private $composer;
1838
1839
1840
1841
1842 private $io;
1843
1844
1845
1846
1847
1848
1849
1850 public function getComposer($required = true, $disablePlugins = null)
1851 {
1852 if (null === $this->composer) {
1853 $application = $this->getApplication();
1854 if ($application instanceof Application) {
1855
1856 $this->composer = $application->getComposer($required, $disablePlugins);
1857 } elseif ($required) {
1858 throw new \RuntimeException(
1859 'Could not create a Composer\Composer instance, you must inject '.
1860 'one if this command is not used with a Composer\Console\Application instance'
1861 );
1862 }
1863 }
1864
1865 return $this->composer;
1866 }
1867
1868
1869
1870
1871 public function setComposer(Composer $composer)
1872 {
1873 $this->composer = $composer;
1874 }
1875
1876
1877
1878
1879 public function resetComposer()
1880 {
1881 $this->composer = null;
1882 $this->getApplication()->resetComposer();
1883 }
1884
1885
1886
1887
1888
1889
1890
1891
1892 public function isProxyCommand()
1893 {
1894 return false;
1895 }
1896
1897
1898
1899
1900 public function getIO()
1901 {
1902 if (null === $this->io) {
1903 $application = $this->getApplication();
1904 if ($application instanceof Application) {
1905
1906 $this->io = $application->getIO();
1907 } else {
1908 $this->io = new NullIO();
1909 }
1910 }
1911
1912 return $this->io;
1913 }
1914
1915
1916
1917
1918 public function setIO(IOInterface $io)
1919 {
1920 $this->io = $io;
1921 }
1922
1923
1924
1925
1926 protected function initialize(InputInterface $input, OutputInterface $output)
1927 {
1928
1929  $disablePlugins = $input->hasParameterOption('--no-plugins');
1930 $composer = $this->getComposer(false, $disablePlugins);
1931 if (null === $composer) {
1932 $composer = Factory::createGlobal($this->getIO(), $disablePlugins);
1933 }
1934 if ($composer) {
1935 $preCommandRunEvent = new PreCommandRunEvent(PluginEvents::PRE_COMMAND_RUN, $input, $this->getName());
1936 $composer->getEventDispatcher()->dispatch($preCommandRunEvent->getName(), $preCommandRunEvent);
1937 }
1938
1939 if (true === $input->hasParameterOption(array('--no-ansi')) && $input->hasOption('no-progress')) {
1940 $input->setOption('no-progress', true);
1941 }
1942
1943 parent::initialize($input, $output);
1944 }
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955 protected function getPreferredInstallOptions(Config $config, InputInterface $input, $keepVcsRequiresPreferSource = false)
1956 {
1957 $preferSource = false;
1958 $preferDist = false;
1959
1960 switch ($config->get('preferred-install')) {
1961 case 'source':
1962 $preferSource = true;
1963 break;
1964 case 'dist':
1965 $preferDist = true;
1966 break;
1967 case 'auto':
1968 default:
1969
1970  break;
1971 }
1972
1973 if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
1974 $preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
1975 $preferDist = $input->getOption('prefer-dist');
1976 }
1977
1978 return array($preferSource, $preferDist);
1979 }
1980 }
1981 <?php
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993 namespace Composer\Command;
1994
1995 use Composer\DependencyResolver\Pool;
1996 use Composer\Package\Link;
1997 use Composer\Package\PackageInterface;
1998 use Composer\Repository\ArrayRepository;
1999 use Composer\Repository\CompositeRepository;
2000 use Composer\Repository\PlatformRepository;
2001 use Composer\Repository\RepositoryFactory;
2002 use Composer\Plugin\CommandEvent;
2003 use Composer\Plugin\PluginEvents;
2004 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
2005 use Composer\Package\Version\VersionParser;
2006 use Symfony\Component\Console\Helper\Table;
2007 use Symfony\Component\Console\Input\InputArgument;
2008 use Symfony\Component\Console\Input\InputInterface;
2009 use Symfony\Component\Console\Input\InputOption;
2010 use Symfony\Component\Console\Output\OutputInterface;
2011
2012
2013
2014
2015
2016
2017 class BaseDependencyCommand extends BaseCommand
2018 {
2019 const ARGUMENT_PACKAGE = 'package';
2020 const ARGUMENT_CONSTRAINT = 'constraint';
2021 const OPTION_RECURSIVE = 'recursive';
2022 const OPTION_TREE = 'tree';
2023
2024 protected $colors;
2025
2026
2027
2028
2029 protected function configure()
2030 {
2031 $this->setDefinition(array(
2032 new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
2033 new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
2034 new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
2035 new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
2036 ));
2037 }
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047 protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
2048 {
2049
2050  $composer = $this->getComposer();
2051 $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
2052 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
2053
2054
2055  $platformOverrides = $composer->getConfig()->get('platform') ?: array();
2056 $repository = new CompositeRepository(array(
2057 new ArrayRepository(array($composer->getPackage())),
2058 $composer->getRepositoryManager()->getLocalRepository(),
2059 new PlatformRepository(array(), $platformOverrides),
2060 ));
2061 $pool = new Pool();
2062 $pool->addRepository($repository);
2063
2064
2065  list($needle, $textConstraint) = array_pad(
2066 explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
2067 2,
2068 $input->getArgument(self::ARGUMENT_CONSTRAINT)
2069 );
2070
2071
2072  $packages = $pool->whatProvides(strtolower($needle));
2073 if (empty($packages)) {
2074 throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
2075 }
2076
2077
2078  
2079  if (!$repository->findPackage($needle, $textConstraint)) {
2080 $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
2081 if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
2082 $repository->addRepository(new ArrayRepository(array(clone $match)));
2083 }
2084 }
2085
2086
2087  $needles = array($needle);
2088 if ($inverted) {
2089 foreach ($packages as $package) {
2090 $needles = array_merge($needles, array_map(function (Link $link) {
2091 return $link->getTarget();
2092 }, $package->getReplaces()));
2093 }
2094 }
2095
2096
2097  if ('*' !== $textConstraint) {
2098 $versionParser = new VersionParser();
2099 $constraint = $versionParser->parseConstraints($textConstraint);
2100 } else {
2101 $constraint = null;
2102 }
2103
2104
2105  $renderTree = $input->getOption(self::OPTION_TREE);
2106 $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
2107
2108
2109  $results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
2110 if (empty($results)) {
2111 $extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
2112 $this->getIO()->writeError(sprintf(
2113 '<info>There is no installed package depending on "%s"%s</info>',
2114 $needle,
2115 $extra
2116 ));
2117 } elseif ($renderTree) {
2118 $this->initStyles($output);
2119 $root = $packages[0];
2120 $this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
2121 $this->printTree($results);
2122 } else {
2123 $this->printTable($output, $results);
2124 }
2125
2126 return 0;
2127 }
2128
2129
2130
2131
2132
2133
2134
2135 protected function printTable(OutputInterface $output, $results)
2136 {
2137 $table = array();
2138 $doubles = array();
2139 do {
2140 $queue = array();
2141 $rows = array();
2142 foreach ($results as $result) {
2143
2144
2145
2146
2147 list($package, $link, $children) = $result;
2148 $unique = (string) $link;
2149 if (isset($doubles[$unique])) {
2150 continue;
2151 }
2152 $doubles[$unique] = true;
2153 $version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
2154 $rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
2155 if ($children) {
2156 $queue = array_merge($queue, $children);
2157 }
2158 }
2159 $results = $queue;
2160 $table = array_merge($rows, $table);
2161 } while (!empty($results));
2162
2163
2164  $renderer = new Table($output);
2165 $renderer->setStyle('compact');
2166 $rendererStyle = $renderer->getStyle();
2167 $rendererStyle->setVerticalBorderChar('');
2168 $rendererStyle->setCellRowContentFormat('%s  ');
2169 $renderer->setRows($table)->render();
2170 }
2171
2172
2173
2174
2175
2176
2177 protected function initStyles(OutputInterface $output)
2178 {
2179 $this->colors = array(
2180 'green',
2181 'yellow',
2182 'cyan',
2183 'magenta',
2184 'blue',
2185 );
2186
2187 foreach ($this->colors as $color) {
2188 $style = new OutputFormatterStyle($color);
2189 $output->getFormatter()->setStyle($color, $style);
2190 }
2191 }
2192
2193
2194
2195
2196
2197
2198
2199
2200 protected function printTree($results, $prefix = '', $level = 1)
2201 {
2202 $count = count($results);
2203 $idx = 0;
2204 foreach ($results as $result) {
2205
2206
2207
2208
2209
2210 list($package, $link, $children) = $result;
2211
2212 $color = $this->colors[$level % count($this->colors)];
2213 $prevColor = $this->colors[($level - 1) % count($this->colors)];
2214 $isLast = (++$idx == $count);
2215 $versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
2216 $packageText = rtrim(sprintf('<%s>%s</%1$s> %s', $color, $package->getPrettyName(), $versionText));
2217 $linkText = sprintf('%s <%s>%s</%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
2218 $circularWarn = $children === false ? '(circular dependency aborted here)' : '';
2219 $this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
2220 if ($children) {
2221 $this->printTree($children, $prefix . ($isLast ? '   ' : '│  '), $level + 1);
2222 }
2223 }
2224 }
2225
2226 private function writeTreeLine($line)
2227 {
2228 $io = $this->getIO();
2229 if (!$io->isDecorated()) {
2230 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
2231 }
2232
2233 $io->write($line);
2234 }
2235 }
2236 <?php
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248 namespace Composer\Command;
2249
2250 use Composer\Package\Link;
2251 use Composer\Package\PackageInterface;
2252 use Composer\Semver\Constraint\Constraint;
2253 use Symfony\Component\Console\Helper\Table;
2254 use Symfony\Component\Console\Input\InputInterface;
2255 use Symfony\Component\Console\Output\OutputInterface;
2256 use Composer\Repository\PlatformRepository;
2257
2258 class CheckPlatformReqsCommand extends BaseCommand
2259 {
2260 protected function configure()
2261 {
2262 $this->setName('check-platform-reqs')
2263 ->setDescription('Check that platform requirements are satisfied.')
2264 ->setHelp(
2265 <<<EOT
2266 Checks that your PHP and extensions versions match the platform requirements of the installed packages.
2267
2268 <info>php composer.phar check-platform-reqs</info>
2269
2270 EOT
2271 );
2272 }
2273
2274 protected function execute(InputInterface $input, OutputInterface $output)
2275 {
2276 $composer = $this->getComposer();
2277
2278 $repos = $composer->getRepositoryManager()->getLocalRepository();
2279
2280 $allPackages = array_merge(array($composer->getPackage()), $repos->getPackages());
2281 $requires = $composer->getPackage()->getDevRequires();
2282 foreach ($requires as $require => $link) {
2283 $requires[$require] = array($link);
2284 }
2285
2286
2287
2288
2289 foreach ($allPackages as $package) {
2290 foreach ($package->getRequires() as $require => $link) {
2291 $requires[$require][] = $link;
2292 }
2293 }
2294 ksort($requires);
2295
2296 $platformRepo = new PlatformRepository(array(), array());
2297 $currentPlatformPackages = $platformRepo->getPackages();
2298 $currentPlatformPackageMap = array();
2299
2300
2301
2302
2303 foreach ($currentPlatformPackages as $currentPlatformPackage) {
2304 $currentPlatformPackageMap[$currentPlatformPackage->getName()] = $currentPlatformPackage;
2305 }
2306
2307 $results = array();
2308
2309 $exitCode = 0;
2310
2311
2312
2313
2314 foreach ($requires as $require => $links) {
2315 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $require)) {
2316 if (isset($currentPlatformPackageMap[$require])) {
2317 $pass = true;
2318 $version = $currentPlatformPackageMap[$require]->getVersion();
2319
2320 foreach ($links as $link) {
2321 if (!$link->getConstraint()->matches(new Constraint('=', $version))) {
2322 $results[] = array(
2323 $currentPlatformPackageMap[$require]->getPrettyName(),
2324 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2325 $link,
2326 '<error>failed</error>',
2327 );
2328 $pass = false;
2329
2330 $exitCode = max($exitCode, 1);
2331 }
2332 }
2333
2334 if ($pass) {
2335 $results[] = array(
2336 $currentPlatformPackageMap[$require]->getPrettyName(),
2337 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2338 null,
2339 '<info>success</info>',
2340 );
2341 }
2342 } else {
2343 $results[] = array(
2344 $require,
2345 'n/a',
2346 $links[0],
2347 '<error>missing</error>',
2348 );
2349
2350 $exitCode = max($exitCode, 2);
2351 }
2352 }
2353 }
2354
2355 $this->printTable($output, $results);
2356
2357 return $exitCode;
2358 }
2359
2360 protected function printTable(OutputInterface $output, $results)
2361 {
2362 $table = array();
2363 $rows = array();
2364 foreach ($results as $result) {
2365
2366
2367
2368 list($platformPackage, $version, $link, $status) = $result;
2369 $rows[] = array(
2370 $platformPackage,
2371 $version,
2372 $link ? sprintf('%s %s %s (%s)', $link->getSource(), $link->getDescription(), $link->getTarget(), $link->getPrettyConstraint()) : '',
2373 $status,
2374 );
2375 }
2376 $table = array_merge($rows, $table);
2377
2378
2379  $renderer = new Table($output);
2380 $renderer->setStyle('compact');
2381 $rendererStyle = $renderer->getStyle();
2382 $rendererStyle->setVerticalBorderChar('');
2383 $rendererStyle->setCellRowContentFormat('%s  ');
2384 $renderer->setRows($table)->render();
2385 }
2386 }
2387 <?php
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399 namespace Composer\Command;
2400
2401 use Composer\Cache;
2402 use Composer\Factory;
2403 use Symfony\Component\Console\Input\InputInterface;
2404 use Symfony\Component\Console\Output\OutputInterface;
2405
2406
2407
2408
2409 class ClearCacheCommand extends BaseCommand
2410 {
2411 protected function configure()
2412 {
2413 $this
2414 ->setName('clear-cache')
2415 ->setAliases(array('clearcache'))
2416 ->setDescription('Clears composer\'s internal package cache.')
2417 ->setHelp(
2418 <<<EOT
2419 The <info>clear-cache</info> deletes all cached packages from composer's
2420 cache directory.
2421 EOT
2422 )
2423 ;
2424 }
2425
2426 protected function execute(InputInterface $input, OutputInterface $output)
2427 {
2428 $config = Factory::createConfig();
2429 $io = $this->getIO();
2430
2431 $cachePaths = array(
2432 'cache-vcs-dir' => $config->get('cache-vcs-dir'),
2433 'cache-repo-dir' => $config->get('cache-repo-dir'),
2434 'cache-files-dir' => $config->get('cache-files-dir'),
2435 'cache-dir' => $config->get('cache-dir'),
2436 );
2437
2438 foreach ($cachePaths as $key => $cachePath) {
2439 $cachePath = realpath($cachePath);
2440 if (!$cachePath) {
2441 $io->writeError("<info>Cache directory does not exist ($key): $cachePath</info>");
2442
2443 continue;
2444 }
2445 $cache = new Cache($io, $cachePath);
2446 if (!$cache->isEnabled()) {
2447 $io->writeError("<info>Cache is not enabled ($key): $cachePath</info>");
2448
2449 continue;
2450 }
2451
2452 $io->writeError("<info>Clearing cache ($key): $cachePath</info>");
2453 $cache->clear();
2454 }
2455
2456 $io->writeError('<info>All caches cleared.</info>');
2457 }
2458 }
2459 <?php
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471 namespace Composer\Command;
2472
2473 use Composer\Util\Platform;
2474 use Composer\Util\Silencer;
2475 use Symfony\Component\Console\Input\InputInterface;
2476 use Symfony\Component\Console\Input\InputArgument;
2477 use Symfony\Component\Console\Input\InputOption;
2478 use Symfony\Component\Console\Output\OutputInterface;
2479 use Composer\Config;
2480 use Composer\Config\JsonConfigSource;
2481 use Composer\Factory;
2482 use Composer\Json\JsonFile;
2483 use Composer\Semver\VersionParser;
2484 use Composer\Package\BasePackage;
2485
2486
2487
2488
2489
2490 class ConfigCommand extends BaseCommand
2491 {
2492
2493
2494
2495 protected $config;
2496
2497
2498
2499
2500 protected $configFile;
2501
2502
2503
2504
2505 protected $configSource;
2506
2507
2508
2509
2510 protected $authConfigFile;
2511
2512
2513
2514
2515 protected $authConfigSource;
2516
2517
2518
2519
2520 protected function configure()
2521 {
2522 $this
2523 ->setName('config')
2524 ->setDescription('Sets config options.')
2525 ->setDefinition(array(
2526 new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'),
2527 new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'),
2528 new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
2529 new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
2530 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
2531 new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
2532 new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
2533 new InputArgument('setting-key', null, 'Setting key'),
2534 new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
2535 ))
2536 ->setHelp(
2537 <<<EOT
2538 This command allows you to edit composer config settings and repositories
2539 in either the local composer.json file or the global config.json file.
2540
2541 Additionally it lets you edit most properties in the local composer.json.
2542
2543 To set a config setting:
2544
2545     <comment>%command.full_name% bin-dir bin/</comment>
2546
2547 To read a config setting:
2548
2549     <comment>%command.full_name% bin-dir</comment>
2550     Outputs: <info>bin</info>
2551
2552 To edit the global config.json file:
2553
2554     <comment>%command.full_name% --global</comment>
2555
2556 To add a repository:
2557
2558     <comment>%command.full_name% repositories.foo vcs https://bar.com</comment>
2559
2560 To remove a repository (repo is a short alias for repositories):
2561
2562     <comment>%command.full_name% --unset repo.foo</comment>
2563
2564 To disable packagist:
2565
2566     <comment>%command.full_name% repo.packagist false</comment>
2567
2568 You can alter repositories in the global config.json file by passing in the
2569 <info>--global</info> option.
2570
2571 To edit the file in an external editor:
2572
2573     <comment>%command.full_name% --editor</comment>
2574
2575 To choose your editor you can set the "EDITOR" env variable.
2576
2577 To get a list of configuration values in the file:
2578
2579     <comment>%command.full_name% --list</comment>
2580
2581 You can always pass more than one option. As an example, if you want to edit the
2582 global config.json file.
2583
2584     <comment>%command.full_name% --editor --global</comment>
2585 EOT
2586 )
2587 ;
2588 }
2589
2590
2591
2592
2593 protected function initialize(InputInterface $input, OutputInterface $output)
2594 {
2595 parent::initialize($input, $output);
2596
2597 if ($input->getOption('global') && null !== $input->getOption('file')) {
2598 throw new \RuntimeException('--file and --global can not be combined');
2599 }
2600
2601 $io = $this->getIO();
2602 $this->config = Factory::createConfig($io);
2603
2604
2605  
2606  $configFile = $input->getOption('global')
2607 ? ($this->config->get('home') . '/config.json')
2608 : ($input->getOption('file') ?: Factory::getComposerFile());
2609
2610
2611  if (
2612 ($configFile === 'composer.json' || $configFile === './composer.json')
2613 && !file_exists($configFile)
2614 && realpath(getcwd()) === realpath($this->config->get('home'))
2615 ) {
2616 file_put_contents($configFile, "{\n}\n");
2617 }
2618
2619 $this->configFile = new JsonFile($configFile, null, $io);
2620 $this->configSource = new JsonConfigSource($this->configFile);
2621
2622 $authConfigFile = $input->getOption('global')
2623 ? ($this->config->get('home') . '/auth.json')
2624 : dirname(realpath($configFile)) . '/auth.json';
2625
2626 $this->authConfigFile = new JsonFile($authConfigFile, null, $io);
2627 $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
2628
2629
2630  if ($input->getOption('global') && !$this->configFile->exists()) {
2631 touch($this->configFile->getPath());
2632 $this->configFile->write(array('config' => new \ArrayObject));
2633 Silencer::call('chmod', $this->configFile->getPath(), 0600);
2634 }
2635 if ($input->getOption('global') && !$this->authConfigFile->exists()) {
2636 touch($this->authConfigFile->getPath());
2637 $this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject));
2638 Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
2639 }
2640
2641 if (!$this->configFile->exists()) {
2642 throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
2643 }
2644 }
2645
2646
2647
2648
2649 protected function execute(InputInterface $input, OutputInterface $output)
2650 {
2651
2652  if ($input->getOption('editor')) {
2653 $editor = escapeshellcmd(getenv('EDITOR'));
2654 if (!$editor) {
2655 if (Platform::isWindows()) {
2656 $editor = 'notepad';
2657 } else {
2658 foreach (array('editor', 'vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
2659 if (exec('which '.$candidate)) {
2660 $editor = $candidate;
2661 break;
2662 }
2663 }
2664 }
2665 }
2666
2667 $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
2668 system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
2669
2670 return 0;
2671 }
2672
2673 if (!$input->getOption('global')) {
2674 $this->config->merge($this->configFile->read());
2675 $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
2676 }
2677
2678
2679  if ($input->getOption('list')) {
2680 $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
2681
2682 return 0;
2683 }
2684
2685 $settingKey = $input->getArgument('setting-key');
2686 if (!$settingKey) {
2687 return 0;
2688 }
2689
2690
2691  if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
2692 throw new \RuntimeException('You can not combine a setting value with --unset');
2693 }
2694
2695
2696  if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
2697 $properties = array('name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra');
2698 $rawData = $this->configFile->read();
2699 $data = $this->config->all();
2700 if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
2701 if (!isset($matches[1]) || $matches[1] === '') {
2702 $value = isset($data['repositories']) ? $data['repositories'] : array();
2703 } else {
2704 if (!isset($data['repositories'][$matches[1]])) {
2705 throw new \InvalidArgumentException('There is no '.$matches[1].' repository defined');
2706 }
2707
2708 $value = $data['repositories'][$matches[1]];
2709 }
2710 } elseif (strpos($settingKey, '.')) {
2711 $bits = explode('.', $settingKey);
2712 if ($bits[0] === 'extra') {
2713 $data = $rawData;
2714 } else {
2715 $data = $data['config'];
2716 }
2717 $match = false;
2718 foreach ($bits as $bit) {
2719 $key = isset($key) ? $key.'.'.$bit : $bit;
2720 $match = false;
2721 if (isset($data[$key])) {
2722 $match = true;
2723 $data = $data[$key];
2724 unset($key);
2725 }
2726 }
2727
2728 if (!$match) {
2729 throw new \RuntimeException($settingKey.' is not defined.');
2730 }
2731
2732 $value = $data;
2733 } elseif (isset($data['config'][$settingKey])) {
2734 $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
2735 } elseif (in_array($settingKey, $properties, true) && isset($rawData[$settingKey])) {
2736 $value = $rawData[$settingKey];
2737 } else {
2738 throw new \RuntimeException($settingKey.' is not defined');
2739 }
2740
2741 if (is_array($value)) {
2742 $value = json_encode($value);
2743 }
2744
2745 $this->getIO()->write($value);
2746
2747 return 0;
2748 }
2749
2750 $values = $input->getArgument('setting-value'); 
2751
2752 $booleanValidator = function ($val) {
2753 return in_array($val, array('true', 'false', '1', '0'), true);
2754 };
2755 $booleanNormalizer = function ($val) {
2756 return $val !== 'false' && (bool) $val;
2757 };
2758
2759
2760  $uniqueConfigValues = array(
2761 'process-timeout' => array('is_numeric', 'intval'),
2762 'use-include-path' => array($booleanValidator, $booleanNormalizer),
2763 'preferred-install' => array(
2764 function ($val) {
2765 return in_array($val, array('auto', 'source', 'dist'), true);
2766 },
2767 function ($val) {
2768 return $val;
2769 },
2770 ),
2771 'store-auths' => array(
2772 function ($val) {
2773 return in_array($val, array('true', 'false', 'prompt'), true);
2774 },
2775 function ($val) {
2776 if ('prompt' === $val) {
2777 return 'prompt';
2778 }
2779
2780 return $val !== 'false' && (bool) $val;
2781 },
2782 ),
2783 'notify-on-install' => array($booleanValidator, $booleanNormalizer),
2784 'vendor-dir' => array('is_string', function ($val) {
2785 return $val;
2786 }),
2787 'bin-dir' => array('is_string', function ($val) {
2788 return $val;
2789 }),
2790 'archive-dir' => array('is_string', function ($val) {
2791 return $val;
2792 }),
2793 'archive-format' => array('is_string', function ($val) {
2794 return $val;
2795 }),
2796 'data-dir' => array('is_string', function ($val) {
2797 return $val;
2798 }),
2799 'cache-dir' => array('is_string', function ($val) {
2800 return $val;
2801 }),
2802 'cache-files-dir' => array('is_string', function ($val) {
2803 return $val;
2804 }),
2805 'cache-repo-dir' => array('is_string', function ($val) {
2806 return $val;
2807 }),
2808 'cache-vcs-dir' => array('is_string', function ($val) {
2809 return $val;
2810 }),
2811 'cache-ttl' => array('is_numeric', 'intval'),
2812 'cache-files-ttl' => array('is_numeric', 'intval'),
2813 'cache-files-maxsize' => array(
2814 function ($val) {
2815 return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0;
2816 },
2817 function ($val) {
2818 return $val;
2819 },
2820 ),
2821 'bin-compat' => array(
2822 function ($val) {
2823 return in_array($val, array('auto', 'full'));
2824 },
2825 function ($val) {
2826 return $val;
2827 },
2828 ),
2829 'discard-changes' => array(
2830 function ($val) {
2831 return in_array($val, array('stash', 'true', 'false', '1', '0'), true);
2832 },
2833 function ($val) {
2834 if ('stash' === $val) {
2835 return 'stash';
2836 }
2837
2838 return $val !== 'false' && (bool) $val;
2839 },
2840 ),
2841 'autoloader-suffix' => array('is_string', function ($val) {
2842 return $val === 'null' ? null : $val;
2843 }),
2844 'sort-packages' => array($booleanValidator, $booleanNormalizer),
2845 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
2846 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
2847 'apcu-autoloader' => array($booleanValidator, $booleanNormalizer),
2848 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
2849 'disable-tls' => array($booleanValidator, $booleanNormalizer),
2850 'secure-http' => array($booleanValidator, $booleanNormalizer),
2851 'cafile' => array(
2852 function ($val) {
2853 return file_exists($val) && is_readable($val);
2854 },
2855 function ($val) {
2856 return $val === 'null' ? null : $val;
2857 },
2858 ),
2859 'capath' => array(
2860 function ($val) {
2861 return is_dir($val) && is_readable($val);
2862 },
2863 function ($val) {
2864 return $val === 'null' ? null : $val;
2865 },
2866 ),
2867 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
2868 'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
2869 );
2870 $multiConfigValues = array(
2871 'github-protocols' => array(
2872 function ($vals) {
2873 if (!is_array($vals)) {
2874 return 'array expected';
2875 }
2876
2877 foreach ($vals as $val) {
2878 if (!in_array($val, array('git', 'https', 'ssh'))) {
2879 return 'valid protocols include: git, https, ssh';
2880 }
2881 }
2882
2883 return true;
2884 },
2885 function ($vals) {
2886 return $vals;
2887 },
2888 ),
2889 'github-domains' => array(
2890 function ($vals) {
2891 if (!is_array($vals)) {
2892 return 'array expected';
2893 }
2894
2895 return true;
2896 },
2897 function ($vals) {
2898 return $vals;
2899 },
2900 ),
2901 'gitlab-domains' => array(
2902 function ($vals) {
2903 if (!is_array($vals)) {
2904 return 'array expected';
2905 }
2906
2907 return true;
2908 },
2909 function ($vals) {
2910 return $vals;
2911 },
2912 ),
2913 );
2914
2915 if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) {
2916 return $this->configSource->removeConfigSetting($settingKey);
2917 }
2918 if (isset($uniqueConfigValues[$settingKey])) {
2919 return $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
2920 }
2921 if (isset($multiConfigValues[$settingKey])) {
2922 return $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
2923 }
2924
2925
2926  $uniqueProps = array(
2927 'name' => array('is_string', function ($val) {
2928 return $val;
2929 }),
2930 'type' => array('is_string', function ($val) {
2931 return $val;
2932 }),
2933 'description' => array('is_string', function ($val) {
2934 return $val;
2935 }),
2936 'homepage' => array('is_string', function ($val) {
2937 return $val;
2938 }),
2939 'version' => array('is_string', function ($val) {
2940 return $val;
2941 }),
2942 'minimum-stability' => array(
2943 function ($val) {
2944 return isset(BasePackage::$stabilities[VersionParser::normalizeStability($val)]);
2945 },
2946 function ($val) {
2947 return VersionParser::normalizeStability($val);
2948 },
2949 ),
2950 'prefer-stable' => array($booleanValidator, $booleanNormalizer),
2951 );
2952 $multiProps = array(
2953 'keywords' => array(
2954 function ($vals) {
2955 if (!is_array($vals)) {
2956 return 'array expected';
2957 }
2958
2959 return true;
2960 },
2961 function ($vals) {
2962 return $vals;
2963 },
2964 ),
2965 'license' => array(
2966 function ($vals) {
2967 if (!is_array($vals)) {
2968 return 'array expected';
2969 }
2970
2971 return true;
2972 },
2973 function ($vals) {
2974 return $vals;
2975 },
2976 ),
2977 );
2978
2979 if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) {
2980 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');
2981 }
2982 if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
2983 return $this->configSource->removeProperty($settingKey);
2984 }
2985 if (isset($uniqueProps[$settingKey])) {
2986 return $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
2987 }
2988 if (isset($multiProps[$settingKey])) {
2989 return $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
2990 }
2991
2992
2993  if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
2994 if ($input->getOption('unset')) {
2995 return $this->configSource->removeRepository($matches[1]);
2996 }
2997
2998 if (2 === count($values)) {
2999 return $this->configSource->addRepository($matches[1], array(
3000 'type' => $values[0],
3001 'url' => $values[1],
3002 ));
3003 }
3004
3005 if (1 === count($values)) {
3006 $value = strtolower($values[0]);
3007 if (true === $booleanValidator($value)) {
3008 if (false === $booleanNormalizer($value)) {
3009 return $this->configSource->addRepository($matches[1], false);
3010 }
3011 } else {
3012 $value = JsonFile::parseJson($values[0]);
3013
3014 return $this->configSource->addRepository($matches[1], $value);
3015 }
3016 }
3017
3018 throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
3019 }
3020
3021
3022  if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) {
3023 if ($input->getOption('unset')) {
3024 return $this->configSource->removeProperty($settingKey);
3025 }
3026
3027 return $this->configSource->addProperty($settingKey, $values[0]);
3028 }
3029
3030
3031  if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
3032 if ($input->getOption('unset')) {
3033 return $this->configSource->removeConfigSetting($settingKey);
3034 }
3035
3036 return $this->configSource->addConfigSetting($settingKey, $values[0]);
3037 }
3038 if ($settingKey === 'platform' && $input->getOption('unset')) {
3039 return $this->configSource->removeConfigSetting($settingKey);
3040 }
3041
3042
3043  if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic)\.(.+)/', $settingKey, $matches)) {
3044 if ($input->getOption('unset')) {
3045 $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3046 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3047
3048 return;
3049 }
3050
3051 if ($matches[1] === 'bitbucket-oauth') {
3052 if (2 !== count($values)) {
3053 throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got '.count($values));
3054 }
3055 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3056 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
3057 } elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token'), true)) {
3058 if (1 !== count($values)) {
3059 throw new \RuntimeException('Too many arguments, expected only one token');
3060 }
3061 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3062 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], $values[0]);
3063 } elseif ($matches[1] === 'http-basic') {
3064 if (2 !== count($values)) {
3065 throw new \RuntimeException('Expected two arguments (username, password), got '.count($values));
3066 }
3067 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3068 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
3069 }
3070
3071 return;
3072 }
3073
3074
3075  if (preg_match('/^scripts\.(.+)/', $settingKey, $matches)) {
3076 if ($input->getOption('unset')) {
3077 return $this->configSource->removeProperty($settingKey);
3078 }
3079
3080 return $this->configSource->addProperty($settingKey, count($values) > 1 ? $values : $values[0]);
3081 }
3082
3083 throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
3084 }
3085
3086 protected function handleSingleValue($key, array $callbacks, array $values, $method)
3087 {
3088 list($validator, $normalizer) = $callbacks;
3089 if (1 !== count($values)) {
3090 throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
3091 }
3092
3093 if (true !== $validation = $validator($values[0])) {
3094 throw new \RuntimeException(sprintf(
3095 '"%s" is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3096 $values[0]
3097 ));
3098 }
3099
3100 return call_user_func(array($this->configSource, $method), $key, $normalizer($values[0]));
3101 }
3102
3103 protected function handleMultiValue($key, array $callbacks, array $values, $method)
3104 {
3105 list($validator, $normalizer) = $callbacks;
3106 if (true !== $validation = $validator($values)) {
3107 throw new \RuntimeException(sprintf(
3108 '%s is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3109 json_encode($values)
3110 ));
3111 }
3112
3113 return call_user_func(array($this->configSource, $method), $key, $normalizer($values));
3114 }
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124 protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
3125 {
3126 $origK = $k;
3127 $io = $this->getIO();
3128 foreach ($contents as $key => $value) {
3129 if ($k === null && !in_array($key, array('config', 'repositories'))) {
3130 continue;
3131 }
3132
3133 $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null;
3134
3135 if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
3136 $k .= preg_replace('{^config\.}', '', $key . '.');
3137 $this->listConfiguration($value, $rawVal, $output, $k);
3138 $k = $origK;
3139
3140 continue;
3141 }
3142
3143 if (is_array($value)) {
3144 $value = array_map(function ($val) {
3145 return is_array($val) ? json_encode($val) : $val;
3146 }, $value);
3147
3148 $value = '['.implode(', ', $value).']';
3149 }
3150
3151 if (is_bool($value)) {
3152 $value = var_export($value, true);
3153 }
3154
3155 if (is_string($rawVal) && $rawVal != $value) {
3156 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>');
3157 } else {
3158 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>');
3159 }
3160 }
3161 }
3162 }
3163 <?php
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175 namespace Composer\Command;
3176
3177 use Composer\Config;
3178 use Composer\Factory;
3179 use Composer\Installer;
3180 use Composer\Installer\ProjectInstaller;
3181 use Composer\Installer\InstallationManager;
3182 use Composer\Installer\SuggestedPackagesReporter;
3183 use Composer\IO\IOInterface;
3184 use Composer\Package\BasePackage;
3185 use Composer\DependencyResolver\Pool;
3186 use Composer\DependencyResolver\Operation\InstallOperation;
3187 use Composer\Package\Version\VersionSelector;
3188 use Composer\Package\AliasPackage;
3189 use Composer\Repository\RepositoryFactory;
3190 use Composer\Repository\CompositeRepository;
3191 use Composer\Repository\PlatformRepository;
3192 use Composer\Repository\InstalledFilesystemRepository;
3193 use Composer\Script\ScriptEvents;
3194 use Composer\Util\Silencer;
3195 use Symfony\Component\Console\Input\InputArgument;
3196 use Symfony\Component\Console\Input\InputInterface;
3197 use Symfony\Component\Console\Input\InputOption;
3198 use Symfony\Component\Console\Output\OutputInterface;
3199 use Symfony\Component\Finder\Finder;
3200 use Composer\Json\JsonFile;
3201 use Composer\Config\JsonConfigSource;
3202 use Composer\Util\Filesystem;
3203 use Composer\Package\Version\VersionParser;
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213 class CreateProjectCommand extends BaseCommand
3214 {
3215
3216
3217
3218 protected $suggestedPackagesReporter;
3219
3220 protected function configure()
3221 {
3222 $this
3223 ->setName('create-project')
3224 ->setDescription('Creates new project from a package into given directory.')
3225 ->setDefinition(array(
3226 new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'),
3227 new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'),
3228 new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
3229 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
3230 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
3231 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
3232 new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
3233 new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
3234 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
3235 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
3236 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
3237 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'),
3238 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
3239 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.'),
3240 new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deleting the vcs folder.'),
3241 new InputOption('remove-vcs', null, InputOption::VALUE_NONE, 'Whether to force deletion of the vcs folder without prompting.'),
3242 new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
3243 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
3244 ))
3245 ->setHelp(
3246 <<<EOT
3247 The <info>create-project</info> command creates a new project from a given
3248 package into a new directory. If executed without params and in a directory
3249 with a composer.json file it installs the packages for the current project.
3250
3251 You can use this command to bootstrap new projects or setup a clean
3252 version-controlled installation for developers of your project.
3253
3254 <info>php composer.phar create-project vendor/project target-directory [version]</info>
3255
3256 You can also specify the version with the package name using = or : as separator.
3257
3258 <info>php composer.phar create-project vendor/project:version target-directory</info>
3259
3260 To install unstable packages, either specify the version you want, or use the
3261 --stability=dev (where dev can be one of RC, beta, alpha or dev).
3262
3263 To setup a developer workable version you should create the project using the source
3264 controlled code by appending the <info>'--prefer-source'</info> flag.
3265
3266 To install a package from another repository than the default one you
3267 can pass the <info>'--repository=https://myrepository.org'</info> flag.
3268
3269 EOT
3270 )
3271 ;
3272 }
3273
3274 protected function execute(InputInterface $input, OutputInterface $output)
3275 {
3276 $config = Factory::createConfig();
3277 $io = $this->getIO();
3278
3279 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input, true);
3280
3281 if ($input->getOption('dev')) {
3282 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
3283 }
3284 if ($input->getOption('no-custom-installers')) {
3285 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
3286 $input->setOption('no-plugins', true);
3287 }
3288
3289 return $this->installProject(
3290 $io,
3291 $config,
3292 $input,
3293 $input->getArgument('package'),
3294 $input->getArgument('directory'),
3295 $input->getArgument('version'),
3296 $input->getOption('stability'),
3297 $preferSource,
3298 $preferDist,
3299 !$input->getOption('no-dev'),
3300 $input->getOption('repository') ?: $input->getOption('repository-url'),
3301 $input->getOption('no-plugins'),
3302 $input->getOption('no-scripts'),
3303 $input->getOption('no-progress'),
3304 $input->getOption('no-install'),
3305 $input->getOption('ignore-platform-reqs'),
3306 !$input->getOption('no-secure-http')
3307 );
3308 }
3309
3310 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)
3311 {
3312 $oldCwd = getcwd();
3313
3314
3315  $io->loadConfiguration($config);
3316
3317 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
3318
3319 if ($packageName !== null) {
3320 $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $noProgress, $ignorePlatformReqs, $secureHttp);
3321 } else {
3322 $installedFromVcs = false;
3323 }
3324
3325 $composer = Factory::create($io, null, $disablePlugins);
3326 $composer->getDownloadManager()->setOutputProgress(!$noProgress);
3327
3328 $fs = new Filesystem();
3329
3330 if ($noScripts === false) {
3331
3332  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
3333 }
3334
3335
3336  $config = $composer->getConfig();
3337 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
3338
3339
3340  if ($noInstall === false) {
3341 $installer = Installer::create($io, $composer);
3342 $installer->setPreferSource($preferSource)
3343 ->setPreferDist($preferDist)
3344 ->setDevMode($installDevPackages)
3345 ->setRunScripts(!$noScripts)
3346 ->setIgnorePlatformRequirements($ignorePlatformReqs)
3347 ->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
3348 ->setOptimizeAutoloader($config->get('optimize-autoloader'));
3349
3350 if ($disablePlugins) {
3351 $installer->disablePlugins();
3352 }
3353
3354 $status = $installer->run();
3355 if (0 !== $status) {
3356 return $status;
3357 }
3358 }
3359
3360 $hasVcs = $installedFromVcs;
3361 if (
3362 !$input->getOption('keep-vcs')
3363 && $installedFromVcs
3364 && (
3365 $input->getOption('remove-vcs')
3366 || !$io->isInteractive()
3367 || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true)
3368 )
3369 ) {
3370 $finder = new Finder();
3371 $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
3372 foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_') as $vcsName) {
3373 $finder->name($vcsName);
3374 }
3375
3376 try {
3377 $dirs = iterator_to_array($finder);
3378 unset($finder);
3379 foreach ($dirs as $dir) {
3380 if (!$fs->removeDirectory($dir)) {
3381 throw new \RuntimeException('Could not remove '.$dir);
3382 }
3383 }
3384 } catch (\Exception $e) {
3385 $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
3386 }
3387
3388 $hasVcs = false;
3389 }
3390
3391
3392  if (!$hasVcs) {
3393 $package = $composer->getPackage();
3394 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3395 foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
3396 foreach ($package->{'get'.$meta['method']}() as $link) {
3397 if ($link->getPrettyConstraint() === 'self.version') {
3398 $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
3399 }
3400 }
3401 }
3402 }
3403
3404 if ($noScripts === false) {
3405
3406  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
3407 }
3408
3409 chdir($oldCwd);
3410 $vendorComposerDir = $config->get('vendor-dir').'/composer';
3411 if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
3412 Silencer::call('rmdir', $vendorComposerDir);
3413 $vendorDir = $config->get('vendor-dir');
3414 if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
3415 Silencer::call('rmdir', $vendorDir);
3416 }
3417 }
3418
3419 return 0;
3420 }
3421
3422 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)
3423 {
3424 if (!$secureHttp) {
3425 $config->merge(array('config' => array('secure-http' => false)));
3426 }
3427
3428 if (null === $repository) {
3429 $sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config));
3430 } else {
3431 $sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true);
3432 }
3433
3434 $parser = new VersionParser();
3435 $requirements = $parser->parseNameVersionPairs(array($packageName));
3436 $name = strtolower($requirements[0]['name']);
3437 if (!$packageVersion && isset($requirements[0]['version'])) {
3438 $packageVersion = $requirements[0]['version'];
3439 }
3440
3441 if (null === $stability) {
3442 if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
3443 $stability = $match[1];
3444 } else {
3445 $stability = VersionParser::parseStability($packageVersion);
3446 }
3447 }
3448
3449 $stability = VersionParser::normalizeStability($stability);
3450
3451 if (!isset(BasePackage::$stabilities[$stability])) {
3452 throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
3453 }
3454
3455 $pool = new Pool($stability);
3456 $pool->addRepository($sourceRepo);
3457
3458 $phpVersion = null;
3459 $prettyPhpVersion = null;
3460 if (!$ignorePlatformReqs) {
3461 $platformOverrides = $config->get('platform') ?: array();
3462
3463  $platform = new PlatformRepository(array(), $platformOverrides);
3464 $phpPackage = $platform->findPackage('php', '*');
3465 $phpVersion = $phpPackage->getVersion();
3466 $prettyPhpVersion = $phpPackage->getPrettyVersion();
3467 }
3468
3469
3470  $versionSelector = new VersionSelector($pool);
3471 $package = $versionSelector->findBestCandidate($name, $packageVersion, $phpVersion, $stability);
3472
3473 if (!$package) {
3474 $errorMessage = "Could not find package $name with " . ($packageVersion ? "version $packageVersion" : "stability $stability");
3475 if ($phpVersion && $versionSelector->findBestCandidate($name, $packageVersion, null, $stability)) {
3476 throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version '.$prettyPhpVersion.'.');
3477 }
3478
3479 throw new \InvalidArgumentException($errorMessage .'.');
3480 }
3481
3482 if (null === $directory) {
3483 $parts = explode("/", $name, 2);
3484 $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
3485 }
3486
3487
3488  if (function_exists('pcntl_async_signals')) {
3489 @mkdir($directory, 0777, true);
3490 if ($realDir = realpath($directory)) {
3491 pcntl_async_signals(true);
3492 pcntl_signal(SIGINT, function () use ($realDir) {
3493 $fs = new Filesystem();
3494 $fs->removeDirectory($realDir);
3495 exit(130);
3496 });
3497 }
3498 }
3499
3500 $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')</info>');
3501
3502 if ($disablePlugins) {
3503 $io->writeError('<info>Plugins have been disabled.</info>');
3504 }
3505
3506 if ($package instanceof AliasPackage) {
3507 $package = $package->getAliasOf();
3508 }
3509
3510 $dm = $this->createDownloadManager($io, $config);
3511 $dm->setPreferSource($preferSource)
3512 ->setPreferDist($preferDist)
3513 ->setOutputProgress(!$noProgress);
3514
3515 $projectInstaller = new ProjectInstaller($directory, $dm);
3516 $im = $this->createInstallationManager();
3517 $im->addInstaller($projectInstaller);
3518 $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
3519 $im->notifyInstalls($io);
3520
3521
3522  $this->suggestedPackagesReporter->addSuggestionsFromPackage($package);
3523
3524 $installedFromVcs = 'source' === $package->getInstallationSource();
3525
3526 $io->writeError('<info>Created project in ' . $directory . '</info>');
3527 chdir($directory);
3528
3529 $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
3530 putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
3531
3532 return $installedFromVcs;
3533 }
3534
3535 protected function createDownloadManager(IOInterface $io, Config $config)
3536 {
3537 $factory = new Factory();
3538
3539 return $factory->createDownloadManager($io, $config);
3540 }
3541
3542 protected function createInstallationManager()
3543 {
3544 return new InstallationManager();
3545 }
3546 }
3547 <?php
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559 namespace Composer\Command;
3560
3561 use Symfony\Component\Console\Input\InputInterface;
3562 use Symfony\Component\Console\Output\OutputInterface;
3563
3564
3565
3566
3567 class DependsCommand extends BaseDependencyCommand
3568 {
3569
3570
3571
3572 protected function configure()
3573 {
3574 parent::configure();
3575
3576 $this
3577 ->setName('depends')
3578 ->setAliases(array('why'))
3579 ->setDescription('Shows which packages cause the given package to be installed.')
3580 ->setHelp(
3581 <<<EOT
3582 Displays detailed information about where a package is referenced.
3583
3584 <info>php composer.phar depends composer/composer</info>
3585
3586 EOT
3587 )
3588 ;
3589 }
3590
3591
3592
3593
3594
3595
3596
3597
3598 protected function execute(InputInterface $input, OutputInterface $output)
3599 {
3600 return parent::doExecute($input, $output, false);
3601 }
3602 }
3603 <?php
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615 namespace Composer\Command;
3616
3617 use Composer\Composer;
3618 use Composer\Factory;
3619 use Composer\Config;
3620 use Composer\Downloader\TransportException;
3621 use Composer\Repository\PlatformRepository;
3622 use Composer\Plugin\CommandEvent;
3623 use Composer\Plugin\PluginEvents;
3624 use Composer\Util\ConfigValidator;
3625 use Composer\Util\IniHelper;
3626 use Composer\Util\ProcessExecutor;
3627 use Composer\Util\RemoteFilesystem;
3628 use Composer\Util\StreamContextFactory;
3629 use Composer\SelfUpdate\Keys;
3630 use Composer\SelfUpdate\Versions;
3631 use Composer\IO\NullIO;
3632 use Symfony\Component\Console\Input\InputInterface;
3633 use Symfony\Component\Console\Output\OutputInterface;
3634
3635
3636
3637
3638 class DiagnoseCommand extends BaseCommand
3639 {
3640
3641 protected $rfs;
3642
3643
3644 protected $process;
3645
3646
3647 protected $exitCode = 0;
3648
3649 protected function configure()
3650 {
3651 $this
3652 ->setName('diagnose')
3653 ->setDescription('Diagnoses the system to identify common errors.')
3654 ->setHelp(
3655 <<<EOT
3656 The <info>diagnose</info> command checks common errors to help debugging problems.
3657
3658 The process exit code will be 1 in case of warnings and 2 for errors.
3659
3660 EOT
3661 )
3662 ;
3663 }
3664
3665
3666
3667
3668 protected function execute(InputInterface $input, OutputInterface $output)
3669 {
3670 $composer = $this->getComposer(false);
3671 $io = $this->getIO();
3672
3673 if ($composer) {
3674 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
3675 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
3676
3677 $io->write('Checking composer.json: ', false);
3678 $this->outputResult($this->checkComposerSchema());
3679 }
3680
3681 if ($composer) {
3682 $config = $composer->getConfig();
3683 } else {
3684 $config = Factory::createConfig();
3685 }
3686
3687 $config->merge(array('config' => array('secure-http' => false)));
3688 $config->prohibitUrlByConfig('http://repo.packagist.org', new NullIO);
3689
3690 $this->rfs = Factory::createRemoteFilesystem($io, $config);
3691 $this->process = new ProcessExecutor($io);
3692
3693 $io->write('Checking platform settings: ', false);
3694 $this->outputResult($this->checkPlatform());
3695
3696 $io->write('Checking git settings: ', false);
3697 $this->outputResult($this->checkGit());
3698
3699 $io->write('Checking http connectivity to packagist: ', false);
3700 $this->outputResult($this->checkHttp('http', $config));
3701
3702 $io->write('Checking https connectivity to packagist: ', false);
3703 $this->outputResult($this->checkHttp('https', $config));
3704
3705 $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
3706 if (!empty($opts['http']['proxy'])) {
3707 $io->write('Checking HTTP proxy: ', false);
3708 $this->outputResult($this->checkHttpProxy());
3709 $io->write('Checking HTTP proxy support for request_fulluri: ', false);
3710 $this->outputResult($this->checkHttpProxyFullUriRequestParam());
3711 $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
3712 $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
3713 }
3714
3715 if ($oauth = $config->get('github-oauth')) {
3716 foreach ($oauth as $domain => $token) {
3717 $io->write('Checking '.$domain.' oauth access: ', false);
3718 $this->outputResult($this->checkGithubOauth($domain, $token));
3719 }
3720 } else {
3721 $io->write('Checking github.com rate limit: ', false);
3722 try {
3723 $rate = $this->getGithubRateLimit('github.com');
3724 $this->outputResult(true);
3725 if (10 > $rate['remaining']) {
3726 $io->write('<warning>WARNING</warning>');
3727 $io->write(sprintf(
3728 '<comment>Github has a rate limit on their API. '
3729 . 'You currently have <options=bold>%u</options=bold> '
3730 . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
3731 . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
3732 . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>',
3733 $rate['remaining'],
3734 $rate['limit']
3735 ));
3736 }
3737 } catch (\Exception $e) {
3738 if ($e instanceof TransportException && $e->getCode() === 401) {
3739 $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
3740 } else {
3741 $this->outputResult($e);
3742 }
3743 }
3744 }
3745
3746 $io->write('Checking disk free space: ', false);
3747 $this->outputResult($this->checkDiskSpace($config));
3748
3749 if ('phar:' === substr(__FILE__, 0, 5)) {
3750 $io->write('Checking pubkeys: ', false);
3751 $this->outputResult($this->checkPubKeys($config));
3752
3753 $io->write('Checking composer version: ', false);
3754 $this->outputResult($this->checkVersion($config));
3755 }
3756
3757 $io->write(sprintf('Composer version: <comment>%s</comment>', Composer::VERSION));
3758
3759 $platformOverrides = $config->get('platform') ?: array();
3760 $platformRepo = new PlatformRepository(array(), $platformOverrides);
3761 $phpPkg = $platformRepo->findPackage('php', '*');
3762 $phpVersion = $phpPkg->getPrettyVersion();
3763 if (false !== strpos($phpPkg->getDescription(), 'overridden')) {
3764 $phpVersion .= ' - ' . $phpPkg->getDescription();
3765 }
3766
3767 $io->write(sprintf('PHP version: <comment>%s</comment>', $phpVersion));
3768
3769 if (defined('PHP_BINARY')) {
3770 $io->write(sprintf('PHP binary path: <comment>%s</comment>', PHP_BINARY));
3771 }
3772
3773 return $this->exitCode;
3774 }
3775
3776 private function checkComposerSchema()
3777 {
3778 $validator = new ConfigValidator($this->getIO());
3779 list($errors, , $warnings) = $validator->validate(Factory::getComposerFile());
3780
3781 if ($errors || $warnings) {
3782 $messages = array(
3783 'error' => $errors,
3784 'warning' => $warnings,
3785 );
3786
3787 $output = '';
3788 foreach ($messages as $style => $msgs) {
3789 foreach ($msgs as $msg) {
3790 $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . PHP_EOL;
3791 }
3792 }
3793
3794 return rtrim($output);
3795 }
3796
3797 return true;
3798 }
3799
3800 private function checkGit()
3801 {
3802 $this->process->execute('git config color.ui', $output);
3803 if (strtolower(trim($output)) === 'always') {
3804 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>';
3805 }
3806
3807 return true;
3808 }
3809
3810 private function checkHttp($proto, Config $config)
3811 {
3812 $disableTls = false;
3813 $result = array();
3814 if ($proto === 'https' && $config->get('disable-tls') === true) {
3815 $disableTls = true;
3816 $result[] = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
3817 }
3818 if ($proto === 'https' && !extension_loaded('openssl') && !$disableTls) {
3819 $result[] = '<error>Composer is configured to use SSL/TLS protection but the openssl extension is not available.</error>';
3820 }
3821
3822 try {
3823 $this->rfs->getContents('packagist.org', $proto . '://repo.packagist.org/packages.json', false);
3824 } catch (TransportException $e) {
3825 if (false !== strpos($e->getMessage(), 'cafile')) {
3826 $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
3827 $result[] = '<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>';
3828 $result[] = '<error>You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option.</error>';
3829 } else {
3830 array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage());
3831 }
3832 }
3833
3834 if (count($result) > 0) {
3835 return $result;
3836 }
3837
3838 return true;
3839 }
3840
3841 private function checkHttpProxy()
3842 {
3843 $protocol = extension_loaded('openssl') ? 'https' : 'http';
3844 try {
3845 $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/packages.json', false), true);
3846 $hash = reset($json['provider-includes']);
3847 $hash = $hash['sha256'];
3848 $path = str_replace('%hash%', $hash, key($json['provider-includes']));
3849 $provider = $this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/'.$path, false);
3850
3851 if (hash('sha256', $provider) !== $hash) {
3852 return 'It seems that your proxy is modifying http traffic on the fly';
3853 }
3854 } catch (\Exception $e) {
3855 return $e;
3856 }
3857
3858 return true;
3859 }
3860
3861
3862
3863
3864
3865
3866
3867
3868 private function checkHttpProxyFullUriRequestParam()
3869 {
3870 $url = 'http://repo.packagist.org/packages.json';
3871 try {
3872 $this->rfs->getContents('packagist.org', $url, false);
3873 } catch (TransportException $e) {
3874 try {
3875 $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
3876 } catch (TransportException $e) {
3877 return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
3878 }
3879
3880 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"';
3881 }
3882
3883 return true;
3884 }
3885
3886
3887
3888
3889
3890
3891
3892
3893 private function checkHttpsProxyFullUriRequestParam()
3894 {
3895 if (!extension_loaded('openssl')) {
3896 return 'You need the openssl extension installed for this check';
3897 }
3898
3899 $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
3900 try {
3901 $this->rfs->getContents('github.com', $url, false);
3902 } catch (TransportException $e) {
3903 try {
3904 $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
3905 } catch (TransportException $e) {
3906 return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
3907 }
3908
3909 return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
3910 }
3911
3912 return true;
3913 }
3914
3915 private function checkGithubOauth($domain, $token)
3916 {
3917 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3918 try {
3919 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
3920
3921 return $this->rfs->getContents($domain, $url, false, array(
3922 'retry-auth-failure' => false,
3923 )) ? true : 'Unexpected error';
3924 } catch (\Exception $e) {
3925 if ($e instanceof TransportException && $e->getCode() === 401) {
3926 return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
3927 }
3928
3929 return $e;
3930 }
3931 }
3932
3933
3934
3935
3936
3937
3938
3939 private function getGithubRateLimit($domain, $token = null)
3940 {
3941 if ($token) {
3942 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3943 }
3944
3945 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
3946 $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
3947 $data = json_decode($json, true);
3948
3949 return $data['resources']['core'];
3950 }
3951
3952 private function checkDiskSpace($config)
3953 {
3954 $minSpaceFree = 1024 * 1024;
3955 if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
3956 || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
3957 ) {
3958 return '<error>The disk hosting '.$dir.' is full</error>';
3959 }
3960
3961 return true;
3962 }
3963
3964 private function checkPubKeys($config)
3965 {
3966 $home = $config->get('home');
3967 $errors = array();
3968 $io = $this->getIO();
3969
3970 if (file_exists($home.'/keys.tags.pub') && file_exists($home.'/keys.dev.pub')) {
3971 $io->write('');
3972 }
3973
3974 if (file_exists($home.'/keys.tags.pub')) {
3975 $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.tags.pub'));
3976 } else {
3977 $errors[] = '<error>Missing pubkey for tags verification</error>';
3978 }
3979
3980 if (file_exists($home.'/keys.dev.pub')) {
3981 $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.dev.pub'));
3982 } else {
3983 $errors[] = '<error>Missing pubkey for dev verification</error>';
3984 }
3985
3986 if ($errors) {
3987 $errors[] = '<error>Run composer self-update --update-keys to set them up</error>';
3988 }
3989
3990 return $errors ?: true;
3991 }
3992
3993 private function checkVersion($config)
3994 {
3995 $versionsUtil = new Versions($config, $this->rfs);
3996 $latest = $versionsUtil->getLatest();
3997
3998 if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
3999 return '<comment>You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')</comment>';
4000 }
4001
4002 return true;
4003 }
4004
4005
4006
4007
4008 private function outputResult($result)
4009 {
4010 $io = $this->getIO();
4011 if (true === $result) {
4012 $io->write('<info>OK</info>');
4013
4014 return;
4015 }
4016
4017 $hadError = false;
4018 if ($result instanceof \Exception) {
4019 $result = '<error>['.get_class($result).'] '.$result->getMessage().'</error>';
4020 }
4021
4022 if (!$result) {
4023
4024  $hadError = true;
4025 } else {
4026 if (!is_array($result)) {
4027 $result = array($result);
4028 }
4029 foreach ($result as $message) {
4030 if (false !== strpos($message, '<error>')) {
4031 $hadError = true;
4032 }
4033 }
4034 }
4035
4036 if ($hadError) {
4037 $io->write('<error>FAIL</error>');
4038 $this->exitCode = 2;
4039 } else {
4040 $io->write('<warning>WARNING</warning>');
4041 $this->exitCode = 1;
4042 }
4043
4044 if ($result) {
4045 foreach ($result as $message) {
4046 $io->write($message);
4047 }
4048 }
4049 }
4050
4051 private function checkPlatform()
4052 {
4053 $output = '';
4054 $out = function ($msg, $style) use (&$output) {
4055 $output .= '<'.$style.'>'.$msg.'</'.$style.'>'.PHP_EOL;
4056 };
4057
4058
4059  $errors = array();
4060 $warnings = array();
4061 $displayIniMessage = false;
4062
4063 $iniMessage = PHP_EOL.PHP_EOL.IniHelper::getMessage();
4064 $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.';
4065
4066 if (!function_exists('json_decode')) {
4067 $errors['json'] = true;
4068 }
4069
4070 if (!extension_loaded('Phar')) {
4071 $errors['phar'] = true;
4072 }
4073
4074 if (!extension_loaded('filter')) {
4075 $errors['filter'] = true;
4076 }
4077
4078 if (!extension_loaded('hash')) {
4079 $errors['hash'] = true;
4080 }
4081
4082 if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
4083 $errors['iconv_mbstring'] = true;
4084 }
4085
4086 if (!ini_get('allow_url_fopen')) {
4087 $errors['allow_url_fopen'] = true;
4088 }
4089
4090 if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
4091 $errors['ioncube'] = ioncube_loader_version();
4092 }
4093
4094 if (PHP_VERSION_ID < 50302) {
4095 $errors['php'] = PHP_VERSION;
4096 }
4097
4098 if (!isset($errors['php']) && PHP_VERSION_ID < 50304) {
4099 $warnings['php'] = PHP_VERSION;
4100 }
4101
4102 if (!extension_loaded('openssl')) {
4103 $errors['openssl'] = true;
4104 }
4105
4106 if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) {
4107 $warnings['openssl_version'] = true;
4108 }
4109
4110 if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) {
4111 $warnings['apc_cli'] = true;
4112 }
4113
4114 if (!extension_loaded('zlib')) {
4115 $warnings['zlib'] = true;
4116 }
4117
4118 ob_start();
4119 phpinfo(INFO_GENERAL);
4120 $phpinfo = ob_get_clean();
4121 if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
4122 $configure = $match[1];
4123
4124 if (false !== strpos($configure, '--enable-sigchild')) {
4125 $warnings['sigchild'] = true;
4126 }
4127
4128 if (false !== strpos($configure, '--with-curlwrappers')) {
4129 $warnings['curlwrappers'] = true;
4130 }
4131 }
4132
4133 if (ini_get('xdebug.profiler_enabled')) {
4134 $warnings['xdebug_profile'] = true;
4135 } elseif (extension_loaded('xdebug')) {
4136 $warnings['xdebug_loaded'] = true;
4137 }
4138
4139 if (!empty($errors)) {
4140 foreach ($errors as $error => $current) {
4141 switch ($error) {
4142 case 'json':
4143 $text = PHP_EOL."The json extension is missing.".PHP_EOL;
4144 $text .= "Install it or recompile php without --disable-json";
4145 break;
4146
4147 case 'phar':
4148 $text = PHP_EOL."The phar extension is missing.".PHP_EOL;
4149 $text .= "Install it or recompile php without --disable-phar";
4150 break;
4151
4152 case 'filter':
4153 $text = PHP_EOL."The filter extension is missing.".PHP_EOL;
4154 $text .= "Install it or recompile php without --disable-filter";
4155 break;
4156
4157 case 'hash':
4158 $text = PHP_EOL."The hash extension is missing.".PHP_EOL;
4159 $text .= "Install it or recompile php without --disable-hash";
4160 break;
4161
4162 case 'iconv_mbstring':
4163 $text = PHP_EOL."The iconv OR mbstring extension is required and both are missing.".PHP_EOL;
4164 $text .= "Install either of them or recompile php without --disable-iconv";
4165 break;
4166
4167 case 'unicode':
4168 $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
4169 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4170 $text .= "    detect_unicode = Off";
4171 $displayIniMessage = true;
4172 break;
4173
4174 case 'suhosin':
4175 $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
4176 $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;
4177 $text .= "    suhosin.executor.include.whitelist = phar ".$current;
4178 $displayIniMessage = true;
4179 break;
4180
4181 case 'php':
4182 $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
4183 break;
4184
4185 case 'allow_url_fopen':
4186 $text = PHP_EOL."The allow_url_fopen setting is incorrect.".PHP_EOL;
4187 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4188 $text .= "    allow_url_fopen = On";
4189 $displayIniMessage = true;
4190 break;
4191
4192 case 'ioncube':
4193 $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
4194 $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;
4195 $text .= "    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
4196 $displayIniMessage = true;
4197 break;
4198
4199 case 'openssl':
4200 $text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
4201 $text .= "If possible you should enable it or recompile php with --with-openssl";
4202 break;
4203 }
4204 $out($text, 'error');
4205 }
4206
4207 $output .= PHP_EOL;
4208 }
4209
4210 if (!empty($warnings)) {
4211 foreach ($warnings as $warning => $current) {
4212 switch ($warning) {
4213 case 'apc_cli':
4214 $text = "The apc.enable_cli setting is incorrect.".PHP_EOL;
4215 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4216 $text .= "  apc.enable_cli = Off";
4217 $displayIniMessage = true;
4218 break;
4219
4220 case 'zlib':
4221 $text = 'The zlib extension is not loaded, this can slow down Composer a lot.'.PHP_EOL;
4222 $text .= 'If possible, enable it or recompile php with --with-zlib'.PHP_EOL;
4223 $displayIniMessage = true;
4224 break;
4225
4226 case 'sigchild':
4227 $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms.".PHP_EOL;
4228 $text .= "Recompile it without this flag if possible, see also:".PHP_EOL;
4229 $text .= "  https://bugs.php.net/bug.php?id=22999";
4230 break;
4231
4232 case 'curlwrappers':
4233 $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.".PHP_EOL;
4234 $text .= " Recompile it without this flag if possible";
4235 break;
4236
4237 case 'php':
4238 $text = "Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL;
4239 $text .= " Composer works with 5.3.2+ for most people, but there might be edge case issues.";
4240 break;
4241
4242 case 'openssl_version':
4243
4244  $opensslVersion = strstr(trim(strstr(OPENSSL_VERSION_TEXT, ' ')), ' ', true);
4245 $opensslVersion = $opensslVersion ?: OPENSSL_VERSION_TEXT;
4246
4247 $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1.".PHP_EOL;
4248 $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above.";
4249 break;
4250
4251 case 'xdebug_loaded':
4252 $text = "The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL;
4253 $text .= " Disabling it when using Composer is recommended.";
4254 break;
4255
4256 case 'xdebug_profile':
4257 $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL;
4258 $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL;
4259 $text .= "  xdebug.profiler_enabled = 0";
4260 $displayIniMessage = true;
4261 break;
4262 }
4263 $out($text, 'comment');
4264 }
4265 }
4266
4267 if ($displayIniMessage) {
4268 $out($iniMessage, 'comment');
4269 }
4270
4271 return !$warnings && !$errors ? true : $output;
4272 }
4273 }
4274 <?php
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286 namespace Composer\Command;
4287
4288 use Composer\Plugin\CommandEvent;
4289 use Composer\Plugin\PluginEvents;
4290 use Symfony\Component\Console\Input\InputInterface;
4291 use Symfony\Component\Console\Input\InputOption;
4292 use Symfony\Component\Console\Output\OutputInterface;
4293
4294
4295
4296
4297 class DumpAutoloadCommand extends BaseCommand
4298 {
4299 protected function configure()
4300 {
4301 $this
4302 ->setName('dump-autoload')
4303 ->setAliases(array('dumpautoload'))
4304 ->setDescription('Dumps the autoloader.')
4305 ->setDefinition(array(
4306 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
4307 new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
4308 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
4309 new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
4310 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
4311 ))
4312 ->setHelp(
4313 <<<EOT
4314 <info>php composer.phar dump-autoload</info>
4315 EOT
4316 )
4317 ;
4318 }
4319
4320 protected function execute(InputInterface $input, OutputInterface $output)
4321 {
4322 $composer = $this->getComposer();
4323
4324 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
4325 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
4326
4327 $installationManager = $composer->getInstallationManager();
4328 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
4329 $package = $composer->getPackage();
4330 $config = $composer->getConfig();
4331
4332 $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
4333 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
4334 $apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
4335
4336 if ($authoritative) {
4337 $this->getIO()->writeError('<info>Generating optimized autoload files (authoritative)</info>');
4338 } elseif ($optimize) {
4339 $this->getIO()->writeError('<info>Generating optimized autoload files</info>');
4340 } else {
4341 $this->getIO()->writeError('<info>Generating autoload files</info>');
4342 }
4343
4344 $generator = $composer->getAutoloadGenerator();
4345 $generator->setDevMode(!$input->getOption('no-dev'));
4346 $generator->setClassMapAuthoritative($authoritative);
4347 $generator->setApcu($apcu);
4348 $generator->setRunScripts(!$input->getOption('no-scripts'));
4349 $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
4350 }
4351 }
4352 <?php
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364 namespace Composer\Command;
4365
4366 use Symfony\Component\Console\Input\InputInterface;
4367 use Symfony\Component\Console\Input\InputOption;
4368 use Symfony\Component\Console\Output\OutputInterface;
4369 use Symfony\Component\Console\Input\InputArgument;
4370
4371
4372
4373
4374 class ExecCommand extends BaseCommand
4375 {
4376 protected function configure()
4377 {
4378 $this
4379 ->setName('exec')
4380 ->setDescription('Executes a vendored binary/script.')
4381 ->setDefinition(array(
4382 new InputOption('list', 'l', InputOption::VALUE_NONE),
4383 new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit'),
4384 new InputArgument(
4385 'args',
4386 InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
4387 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
4388 ),
4389 ))
4390 ;
4391 }
4392
4393 protected function execute(InputInterface $input, OutputInterface $output)
4394 {
4395 $composer = $this->getComposer();
4396 $binDir = $composer->getConfig()->get('bin-dir');
4397 if ($input->getOption('list') || !$input->getArgument('binary')) {
4398 $bins = glob($binDir . '/*');
4399 $bins = array_merge($bins, array_map(function ($e) {
4400 return "$e (local)";
4401 }, $composer->getPackage()->getBinaries()));
4402
4403 if (!$bins) {
4404 throw new \RuntimeException("No binaries found in composer.json or in bin-dir ($binDir)");
4405 }
4406
4407 $this->getIO()->write(
4408 <<<EOT
4409 <comment>Available binaries:</comment>
4410 EOT
4411 );
4412
4413 foreach ($bins as $bin) {
4414
4415  if (isset($previousBin) && $bin === $previousBin.'.bat') {
4416 continue;
4417 }
4418
4419 $previousBin = $bin;
4420 $bin = basename($bin);
4421 $this->getIO()->write(
4422 <<<EOT
4423 <info>- $bin</info>
4424 EOT
4425 );
4426 }
4427
4428 return 0;
4429 }
4430
4431 $binary = $input->getArgument('binary');
4432
4433 $dispatcher = $composer->getEventDispatcher();
4434 $dispatcher->addListener('__exec_command', $binary);
4435 if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
4436 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
4437 }
4438
4439 return $dispatcher->dispatchScript('__exec_command', true, $input->getArgument('args'));
4440 }
4441 }
4442 <?php
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454 namespace Composer\Command;
4455
4456 use Composer\Factory;
4457 use Composer\Util\Filesystem;
4458 use Symfony\Component\Console\Input\InputInterface;
4459 use Symfony\Component\Console\Input\InputArgument;
4460 use Symfony\Component\Console\Input\StringInput;
4461 use Symfony\Component\Console\Output\OutputInterface;
4462
4463
4464
4465
4466 class GlobalCommand extends BaseCommand
4467 {
4468 protected function configure()
4469 {
4470 $this
4471 ->setName('global')
4472 ->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME).')
4473 ->setDefinition(array(
4474 new InputArgument('command-name', InputArgument::REQUIRED, ''),
4475 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
4476 ))
4477 ->setHelp(
4478 <<<EOT
4479 Use this command as a wrapper to run other Composer commands
4480 within the global context of COMPOSER_HOME.
4481
4482 You can use this to install CLI utilities globally, all you need
4483 is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.
4484
4485 COMPOSER_HOME is c:\Users\<user>\AppData\Roaming\Composer on Windows
4486 and /home/<user>/.composer on unix systems.
4487
4488 If your system uses freedesktop.org standards, then it will first check
4489 XDG_CONFIG_HOME or default to /home/<user>/.config/composer
4490
4491 Note: This path may vary depending on customizations to bin-dir in
4492 composer.json or the environmental variable COMPOSER_BIN_DIR.
4493
4494 EOT
4495 )
4496 ;
4497 }
4498
4499 public function run(InputInterface $input, OutputInterface $output)
4500 {
4501
4502  $tokens = preg_split('{\s+}', $input->__toString());
4503 $args = array();
4504 foreach ($tokens as $token) {
4505 if ($token && $token[0] !== '-') {
4506 $args[] = $token;
4507 if (count($args) >= 2) {
4508 break;
4509 }
4510 }
4511 }
4512
4513
4514  if (count($args) < 2) {
4515 return parent::run($input, $output);
4516 }
4517
4518
4519  $config = Factory::createConfig();
4520 $home = $config->get('home');
4521
4522 if (!is_dir($home)) {
4523 $fs = new Filesystem();
4524 $fs->ensureDirectoryExists($home);
4525 if (!is_dir($home)) {
4526 throw new \RuntimeException('Could not create home directory');
4527 }
4528 }
4529
4530 try {
4531 chdir($home);
4532 } catch (\Exception $e) {
4533 throw new \RuntimeException('Could not switch to home directory "'.$home.'"', 0, $e);
4534 }
4535 $this->getIO()->writeError('<info>Changed current directory to '.$home.'</info>');
4536
4537
4538  $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
4539 $this->getApplication()->resetComposer();
4540
4541 return $this->getApplication()->run($input, $output);
4542 }
4543
4544
4545
4546
4547 public function isProxyCommand()
4548 {
4549 return true;
4550 }
4551 }
4552 <?php
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564 namespace Composer\Command;
4565
4566 use Composer\Package\CompletePackageInterface;
4567 use Composer\Repository\RepositoryInterface;
4568 use Composer\Repository\ArrayRepository;
4569 use Composer\Repository\RepositoryFactory;
4570 use Composer\Util\Platform;
4571 use Composer\Util\ProcessExecutor;
4572 use Symfony\Component\Console\Input\InputArgument;
4573 use Symfony\Component\Console\Input\InputOption;
4574 use Symfony\Component\Console\Input\InputInterface;
4575 use Symfony\Component\Console\Output\OutputInterface;
4576
4577
4578
4579
4580 class HomeCommand extends BaseCommand
4581 {
4582
4583
4584
4585 protected function configure()
4586 {
4587 $this
4588 ->setName('browse')
4589 ->setAliases(array('home'))
4590 ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
4591 ->setDefinition(array(
4592 new InputArgument('packages', InputArgument::IS_ARRAY, 'Package(s) to browse to.'),
4593 new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
4594 new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
4595 ))
4596 ->setHelp(
4597 <<<EOT
4598 The home command opens or shows a package's repository URL or
4599 homepage in your default browser.
4600
4601 To open the homepage by default, use -H or --homepage.
4602 To show instead of open the repository or homepage URL, use -s or --show.
4603 EOT
4604 );
4605 }
4606
4607
4608
4609
4610 protected function execute(InputInterface $input, OutputInterface $output)
4611 {
4612 $repos = $this->initializeRepos();
4613 $io = $this->getIO();
4614 $return = 0;
4615
4616 $packages = $input->getArgument('packages');
4617 if (!$packages) {
4618 $io->writeError('No package specified, opening homepage for the root package');
4619 $packages = array($this->getComposer()->getPackage()->getName());
4620 }
4621
4622 foreach ($packages as $packageName) {
4623 $handled = false;
4624 $packageExists = false;
4625 foreach ($repos as $repo) {
4626 foreach ($repo->findPackages($packageName) as $package) {
4627 $packageExists = true;
4628 if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
4629 $handled = true;
4630 break 2;
4631 }
4632 }
4633 }
4634
4635 if (!$packageExists) {
4636 $return = 1;
4637 $io->writeError('<warning>Package '.$packageName.' not found</warning>');
4638 }
4639
4640 if (!$handled) {
4641 $return = 1;
4642 $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
4643 }
4644 }
4645
4646 return $return;
4647 }
4648
4649 private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
4650 {
4651 $support = $package->getSupport();
4652 $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
4653 if (!$url || $showHomepage) {
4654 $url = $package->getHomepage();
4655 }
4656
4657 if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
4658 return false;
4659 }
4660
4661 if ($showOnly) {
4662 $this->getIO()->write(sprintf('<info>%s</info>', $url));
4663 } else {
4664 $this->openBrowser($url);
4665 }
4666
4667 return true;
4668 }
4669
4670
4671
4672
4673
4674
4675 private function openBrowser($url)
4676 {
4677 $url = ProcessExecutor::escape($url);
4678
4679 $process = new ProcessExecutor($this->getIO());
4680 if (Platform::isWindows()) {
4681 return $process->execute('start "web" explorer "' . $url . '"', $output);
4682 }
4683
4684 $linux = $process->execute('which xdg-open', $output);
4685 $osx = $process->execute('which open', $output);
4686
4687 if (0 === $linux) {
4688 $process->execute('xdg-open ' . $url, $output);
4689 } elseif (0 === $osx) {
4690 $process->execute('open ' . $url, $output);
4691 } else {
4692 $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
4693 }
4694 }
4695
4696
4697
4698
4699
4700
4701
4702
4703 private function initializeRepos()
4704 {
4705 $composer = $this->getComposer(false);
4706
4707 if ($composer) {
4708 return array_merge(
4709 array(new ArrayRepository(array($composer->getPackage()))), 
4710  array($composer->getRepositoryManager()->getLocalRepository()), 
4711  $composer->getRepositoryManager()->getRepositories() 
4712  );
4713 }
4714
4715 return RepositoryFactory::defaultRepos($this->getIO());
4716 }
4717 }
4718 <?php
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730 namespace Composer\Command;
4731
4732 use Composer\DependencyResolver\Pool;
4733 use Composer\Factory;
4734 use Composer\Json\JsonFile;
4735 use Composer\Package\BasePackage;
4736 use Composer\Package\Version\VersionParser;
4737 use Composer\Package\Version\VersionSelector;
4738 use Composer\Repository\CompositeRepository;
4739 use Composer\Repository\PlatformRepository;
4740 use Composer\Repository\RepositoryFactory;
4741 use Composer\Util\ProcessExecutor;
4742 use Symfony\Component\Console\Input\InputInterface;
4743 use Symfony\Component\Console\Input\InputOption;
4744 use Symfony\Component\Console\Output\OutputInterface;
4745 use Symfony\Component\Process\ExecutableFinder;
4746 use Symfony\Component\Process\Process;
4747
4748
4749
4750
4751
4752 class InitCommand extends BaseCommand
4753 {
4754
4755 protected $repos;
4756
4757
4758 private $gitConfig;
4759
4760
4761 private $pools;
4762
4763
4764
4765
4766 protected function configure()
4767 {
4768 $this
4769 ->setName('init')
4770 ->setDescription('Creates a basic composer.json file in current directory.')
4771 ->setDefinition(array(
4772 new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
4773 new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
4774 new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
4775
4776  new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of package (e.g. library, project, metapackage, composer-plugin)'),
4777 new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
4778 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"'),
4779 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"'),
4780 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
4781 new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
4782 new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
4783 ))
4784 ->setHelp(
4785 <<<EOT
4786 The <info>init</info> command creates a basic composer.json file
4787 in the current directory.
4788
4789 <info>php composer.phar init</info>
4790
4791 EOT
4792 )
4793 ;
4794 }
4795
4796
4797
4798
4799 protected function execute(InputInterface $input, OutputInterface $output)
4800 {
4801 $io = $this->getIO();
4802
4803 $whitelist = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license');
4804 $options = array_filter(array_intersect_key($input->getOptions(), array_flip($whitelist)));
4805
4806 if (isset($options['author'])) {
4807 $options['authors'] = $this->formatAuthors($options['author']);
4808 unset($options['author']);
4809 }
4810
4811 $repositories = $input->getOption('repository');
4812 if ($repositories) {
4813 $config = Factory::createConfig($io);
4814 foreach ($repositories as $repo) {
4815 $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
4816 }
4817 }
4818
4819 if (isset($options['stability'])) {
4820 $options['minimum-stability'] = $options['stability'];
4821 unset($options['stability']);
4822 }
4823
4824 $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass;
4825 if (array() === $options['require']) {
4826 $options['require'] = new \stdClass;
4827 }
4828
4829 if (isset($options['require-dev'])) {
4830 $options['require-dev'] = $this->formatRequirements($options['require-dev']);
4831 if (array() === $options['require-dev']) {
4832 $options['require-dev'] = new \stdClass;
4833 }
4834 }
4835
4836 $file = new JsonFile(Factory::getComposerFile());
4837 $json = $file->encode($options);
4838
4839 if ($input->isInteractive()) {
4840 $io->writeError(array('', $json, ''));
4841 if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
4842 $io->writeError('<error>Command aborted</error>');
4843
4844 return 1;
4845 }
4846 }
4847
4848 $file->write($options);
4849
4850 if ($input->isInteractive() && is_dir('.git')) {
4851 $ignoreFile = realpath('.gitignore');
4852
4853 if (false === $ignoreFile) {
4854 $ignoreFile = realpath('.') . '/.gitignore';
4855 }
4856
4857 if (!$this->hasVendorIgnore($ignoreFile)) {
4858 $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
4859
4860 if ($io->askConfirmation($question, true)) {
4861 $this->addVendorIgnore($ignoreFile);
4862 }
4863 }
4864 }
4865 }
4866
4867
4868
4869
4870 protected function interact(InputInterface $input, OutputInterface $output)
4871 {
4872 $git = $this->getGitConfig();
4873 $io = $this->getIO();
4874 $formatter = $this->getHelperSet()->get('formatter');
4875
4876
4877  $repositories = $input->getOption('repository');
4878 if ($repositories) {
4879 $config = Factory::createConfig($io);
4880 $repos = array(new PlatformRepository);
4881 foreach ($repositories as $repo) {
4882 $repos[] = RepositoryFactory::fromString($io, $config, $repo);
4883 }
4884 $repos[] = RepositoryFactory::createRepo($io, $config, array(
4885 'type' => 'composer',
4886 'url' => 'https://repo.packagist.org',
4887 ));
4888
4889 $this->repos = new CompositeRepository($repos);
4890 unset($repos, $config, $repositories);
4891 }
4892
4893 $io->writeError(array(
4894 '',
4895 $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
4896 '',
4897 ));
4898
4899
4900  $io->writeError(array(
4901 '',
4902 'This command will guide you through creating your composer.json config.',
4903 '',
4904 ));
4905
4906 $cwd = realpath(".");
4907
4908 if (!$name = $input->getOption('name')) {
4909 $name = basename($cwd);
4910 $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
4911 $name = strtolower($name);
4912 if (!empty($_SERVER['COMPOSER_DEFAULT_VENDOR'])) {
4913 $name = $_SERVER['COMPOSER_DEFAULT_VENDOR'] . '/' . $name;
4914 } elseif (isset($git['github.user'])) {
4915 $name = $git['github.user'] . '/' . $name;
4916 } elseif (!empty($_SERVER['USERNAME'])) {
4917 $name = $_SERVER['USERNAME'] . '/' . $name;
4918 } elseif (!empty($_SERVER['USER'])) {
4919 $name = $_SERVER['USER'] . '/' . $name;
4920 } elseif (get_current_user()) {
4921 $name = get_current_user() . '/' . $name;
4922 } else {
4923
4924  $name = $name . '/' . $name;
4925 }
4926 $name = strtolower($name);
4927 } else {
4928 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $name)) {
4929 throw new \InvalidArgumentException(
4930 '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_.-]+'
4931 );
4932 }
4933 }
4934
4935 $name = $io->askAndValidate(
4936 'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
4937 function ($value) use ($name) {
4938 if (null === $value) {
4939 return $name;
4940 }
4941
4942 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $value)) {
4943 throw new \InvalidArgumentException(
4944 '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_.-]+'
4945 );
4946 }
4947
4948 return $value;
4949 },
4950 null,
4951 $name
4952 );
4953 $input->setOption('name', $name);
4954
4955 $description = $input->getOption('description') ?: false;
4956 $description = $io->ask(
4957 'Description [<comment>'.$description.'</comment>]: ',
4958 $description
4959 );
4960 $input->setOption('description', $description);
4961
4962 if (null === $author = $input->getOption('author')) {
4963 if (!empty($_SERVER['COMPOSER_DEFAULT_AUTHOR'])) {
4964 $author_name = $_SERVER['COMPOSER_DEFAULT_AUTHOR'];
4965 } elseif (isset($git['user.name'])) {
4966 $author_name = $git['user.name'];
4967 }
4968
4969 if (!empty($_SERVER['COMPOSER_DEFAULT_EMAIL'])) {
4970 $author_email = $_SERVER['COMPOSER_DEFAULT_EMAIL'];
4971 } elseif (isset($git['user.email'])) {
4972 $author_email = $git['user.email'];
4973 }
4974
4975 if (isset($author_name) && isset($author_email)) {
4976 $author = sprintf('%s <%s>', $author_name, $author_email);
4977 }
4978 }
4979
4980 $self = $this;
4981 $author = $io->askAndValidate(
4982 'Author [<comment>'.$author.'</comment>, n to skip]: ',
4983 function ($value) use ($self, $author) {
4984 if ($value === 'n' || $value === 'no') {
4985 return;
4986 }
4987 $value = $value ?: $author;
4988 $author = $self->parseAuthorString($value);
4989
4990 return sprintf('%s <%s>', $author['name'], $author['email']);
4991 },
4992 null,
4993 $author
4994 );
4995 $input->setOption('author', $author);
4996
4997 $minimumStability = $input->getOption('stability') ?: null;
4998 $minimumStability = $io->askAndValidate(
4999 'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
5000 function ($value) use ($minimumStability) {
5001 if (null === $value) {
5002 return $minimumStability;
5003 }
5004
5005 if (!isset(BasePackage::$stabilities[$value])) {
5006 throw new \InvalidArgumentException(
5007 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
5008 implode(', ', array_keys(BasePackage::$stabilities))
5009 );
5010 }
5011
5012 return $value;
5013 },
5014 null,
5015 $minimumStability
5016 );
5017 $input->setOption('stability', $minimumStability);
5018
5019 $type = $input->getOption('type') ?: false;
5020 $type = $io->ask(
5021 'Package Type (e.g. library, project, metapackage, composer-plugin) [<comment>'.$type.'</comment>]: ',
5022 $type
5023 );
5024 $input->setOption('type', $type);
5025
5026 if (null === $license = $input->getOption('license')) {
5027 if (!empty($_SERVER['COMPOSER_DEFAULT_LICENSE'])) {
5028 $license = $_SERVER['COMPOSER_DEFAULT_LICENSE'];
5029 }
5030 }
5031
5032 $license = $io->ask(
5033 'License [<comment>'.$license.'</comment>]: ',
5034 $license
5035 );
5036 $input->setOption('license', $license);
5037
5038 $io->writeError(array('', 'Define your dependencies.', ''));
5039
5040
5041  $repos = $this->getRepos();
5042 $preferredStability = $minimumStability ?: 'stable';
5043 $phpVersion = $repos->findPackage('php', '*')->getPrettyVersion();
5044
5045 $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
5046 $require = $input->getOption('require');
5047 $requirements = array();
5048 if ($require || $io->askConfirmation($question, true)) {
5049 $requirements = $this->determineRequirements($input, $output, $require, $phpVersion, $preferredStability);
5050 }
5051 $input->setOption('require', $requirements);
5052
5053 $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
5054 $requireDev = $input->getOption('require-dev');
5055 $devRequirements = array();
5056 if ($requireDev || $io->askConfirmation($question, true)) {
5057 $devRequirements = $this->determineRequirements($input, $output, $requireDev, $phpVersion, $preferredStability);
5058 }
5059 $input->setOption('require-dev', $devRequirements);
5060 }
5061
5062
5063
5064
5065
5066
5067 public function parseAuthorString($author)
5068 {
5069 if (preg_match('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P<email>.+?)>$/u', $author, $match)) {
5070 if ($this->isValidEmail($match['email'])) {
5071 return array(
5072 'name' => trim($match['name']),
5073 'email' => $match['email'],
5074 );
5075 }
5076 }
5077
5078 throw new \InvalidArgumentException(
5079 'Invalid author string.  Must be in the format: '.
5080 'John Smith <john@example.com>'
5081 );
5082 }
5083
5084 protected function findPackages($name)
5085 {
5086 return $this->getRepos()->search($name);
5087 }
5088
5089 protected function getRepos()
5090 {
5091 if (!$this->repos) {
5092 $this->repos = new CompositeRepository(array_merge(
5093 array(new PlatformRepository),
5094 RepositoryFactory::defaultRepos($this->getIO())
5095 ));
5096 }
5097
5098 return $this->repos;
5099 }
5100
5101 protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable')
5102 {
5103 if ($requires) {
5104 $requires = $this->normalizeRequirements($requires);
5105 $result = array();
5106 $io = $this->getIO();
5107
5108 foreach ($requires as $requirement) {
5109 if (!isset($requirement['version'])) {
5110
5111  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability);
5112 $requirement['version'] = $version;
5113
5114
5115  $requirement['name'] = $name;
5116
5117 $io->writeError(sprintf(
5118 'Using version <info>%s</info> for <info>%s</info>',
5119 $requirement['version'],
5120 $requirement['name']
5121 ));
5122 } else {
5123
5124  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $requirement['version'], 'dev');
5125
5126
5127  $requirement['name'] = $name;
5128 }
5129
5130 $result[] = $requirement['name'] . ' ' . $requirement['version'];
5131 }
5132
5133 return $result;
5134 }
5135
5136 $versionParser = new VersionParser();
5137 $io = $this->getIO();
5138 while (null !== $package = $io->ask('Search for a package: ')) {
5139 $matches = $this->findPackages($package);
5140
5141 if (count($matches)) {
5142 $exactMatch = null;
5143 $choices = array();
5144 foreach ($matches as $position => $foundPackage) {
5145 $abandoned = '';
5146 if (isset($foundPackage['abandoned'])) {
5147 if (is_string($foundPackage['abandoned'])) {
5148 $replacement = sprintf('Use %s instead', $foundPackage['abandoned']);
5149 } else {
5150 $replacement = 'No replacement was suggested';
5151 }
5152 $abandoned = sprintf('<warning>Abandoned. %s.</warning>', $replacement);
5153 }
5154
5155 $choices[] = sprintf(' <info>%5s</info> %s %s', "[$position]", $foundPackage['name'], $abandoned);
5156 if ($foundPackage['name'] === $package) {
5157 $exactMatch = true;
5158 break;
5159 }
5160 }
5161
5162
5163  if (!$exactMatch) {
5164 $io->writeError(array(
5165 '',
5166 sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
5167 '',
5168 ));
5169
5170 $io->writeError($choices);
5171 $io->writeError('');
5172
5173 $validator = function ($selection) use ($matches, $versionParser) {
5174 if ('' === $selection) {
5175 return false;
5176 }
5177
5178 if (is_numeric($selection) && isset($matches[(int) $selection])) {
5179 $package = $matches[(int) $selection];
5180
5181 return $package['name'];
5182 }
5183
5184 if (preg_match('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
5185 if (isset($packageMatches['version'])) {
5186
5187
5188
5189  $versionParser->parseConstraints($packageMatches['version']);
5190
5191 return $packageMatches['name'].' '.$packageMatches['version'];
5192 }
5193
5194
5195  return $packageMatches['name'];
5196 }
5197
5198 throw new \Exception('Not a valid selection');
5199 };
5200
5201 $package = $io->askAndValidate(
5202 'Enter package # to add, or the complete package name if it is not listed: ',
5203 $validator,
5204 3,
5205 false
5206 );
5207 }
5208
5209
5210  if (false !== $package && false === strpos($package, ' ')) {
5211 $validator = function ($input) {
5212 $input = trim($input);
5213
5214 return $input ?: false;
5215 };
5216
5217 $constraint = $io->askAndValidate(
5218 'Enter the version constraint to require (or leave blank to use the latest version): ',
5219 $validator,
5220 3,
5221 false
5222 );
5223
5224 if (false === $constraint) {
5225 list($name, $constraint) = $this->findBestVersionAndNameForPackage($input, $package, $phpVersion, $preferredStability);
5226
5227 $io->writeError(sprintf(
5228 'Using version <info>%s</info> for <info>%s</info>',
5229 $constraint,
5230 $package
5231 ));
5232 }
5233
5234 $package .= ' '.$constraint;
5235 }
5236
5237 if (false !== $package) {
5238 $requires[] = $package;
5239 }
5240 }
5241 }
5242
5243 return $requires;
5244 }
5245
5246 protected function formatAuthors($author)
5247 {
5248 return array($this->parseAuthorString($author));
5249 }
5250
5251 protected function formatRequirements(array $requirements)
5252 {
5253 $requires = array();
5254 $requirements = $this->normalizeRequirements($requirements);
5255 foreach ($requirements as $requirement) {
5256 $requires[$requirement['name']] = $requirement['version'];
5257 }
5258
5259 return $requires;
5260 }
5261
5262 protected function getGitConfig()
5263 {
5264 if (null !== $this->gitConfig) {
5265 return $this->gitConfig;
5266 }
5267
5268 $finder = new ExecutableFinder();
5269 $gitBin = $finder->find('git');
5270
5271 $cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
5272 $cmd->run();
5273
5274 if ($cmd->isSuccessful()) {
5275 $this->gitConfig = array();
5276 preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER);
5277 foreach ($matches as $match) {
5278 $this->gitConfig[$match[1]] = $match[2];
5279 }
5280
5281 return $this->gitConfig;
5282 }
5283
5284 return $this->gitConfig = array();
5285 }
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303 protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
5304 {
5305 if (!file_exists($ignoreFile)) {
5306 return false;
5307 }
5308
5309 $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
5310
5311 $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES);
5312 foreach ($lines as $line) {
5313 if (preg_match($pattern, $line)) {
5314 return true;
5315 }
5316 }
5317
5318 return false;
5319 }
5320
5321 protected function normalizeRequirements(array $requirements)
5322 {
5323 $parser = new VersionParser();
5324
5325 return $parser->parseNameVersionPairs($requirements);
5326 }
5327
5328 protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
5329 {
5330 $contents = "";
5331 if (file_exists($ignoreFile)) {
5332 $contents = file_get_contents($ignoreFile);
5333
5334 if ("\n" !== substr($contents, 0, -1)) {
5335 $contents .= "\n";
5336 }
5337 }
5338
5339 file_put_contents($ignoreFile, $contents . $vendor. "\n");
5340 }
5341
5342 protected function isValidEmail($email)
5343 {
5344
5345  if (!function_exists('filter_var')) {
5346 return true;
5347 }
5348
5349
5350  if (PHP_VERSION_ID < 50303) {
5351 return true;
5352 }
5353
5354 return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
5355 }
5356
5357 private function getPool(InputInterface $input, $minimumStability = null)
5358 {
5359 $key = $minimumStability ?: 'default';
5360
5361 if (!isset($this->pools[$key])) {
5362 $this->pools[$key] = $pool = new Pool($minimumStability ?: $this->getMinimumStability($input));
5363 $pool->addRepository($this->getRepos());
5364 }
5365
5366 return $this->pools[$key];
5367 }
5368
5369 private function getMinimumStability(InputInterface $input)
5370 {
5371 if ($input->hasOption('stability')) {
5372 return $input->getOption('stability') ?: 'stable';
5373 }
5374
5375 $file = Factory::getComposerFile();
5376 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
5377 if (!empty($composer['minimum-stability'])) {
5378 return $composer['minimum-stability'];
5379 }
5380 }
5381
5382 return 'stable';
5383 }
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399 private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null)
5400 {
5401
5402  $versionSelector = new VersionSelector($this->getPool($input, $minimumStability));
5403 $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
5404
5405
5406  if ($input->hasOption('ignore-platform-reqs') && $input->getOption('ignore-platform-reqs')) {
5407 $phpVersion = null;
5408 $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
5409 }
5410
5411 if (!$package) {
5412
5413  if ($phpVersion && $versionSelector->findBestCandidate($name, $requiredVersion, null, $preferredStability)) {
5414 throw new \InvalidArgumentException(sprintf(
5415 'Package %s at version %s has a PHP requirement incompatible with your PHP version (%s)',
5416 $name,
5417 $requiredVersion,
5418 $phpVersion
5419 ));
5420 }
5421
5422  if ($requiredVersion && $versionSelector->findBestCandidate($name, null, $phpVersion, $preferredStability)) {
5423 throw new \InvalidArgumentException(sprintf(
5424 'Could not find package %s in a version matching %s',
5425 $name,
5426 $requiredVersion
5427 ));
5428 }
5429
5430  if ($phpVersion && $versionSelector->findBestCandidate($name)) {
5431 throw new \InvalidArgumentException(sprintf(
5432 'Could not find package %s in any version matching your PHP version (%s)',
5433 $name,
5434 $phpVersion
5435 ));
5436 }
5437
5438
5439  $similar = $this->findSimilar($name);
5440 if ($similar) {
5441
5442  if ($requiredVersion === null && in_array($name, $similar, true)) {
5443 throw new \InvalidArgumentException(sprintf(
5444 'Could not find a version of package %s matching your minimum-stability (%s). Require it with an explicit version constraint allowing its desired stability.',
5445 $name,
5446 $this->getMinimumStability($input)
5447 ));
5448 }
5449
5450 throw new \InvalidArgumentException(sprintf(
5451 "Could not find package %s.\n\nDid you mean " . (count($similar) > 1 ? 'one of these' : 'this') . "?\n    %s",
5452 $name,
5453 implode("\n    ", $similar)
5454 ));
5455 }
5456
5457 throw new \InvalidArgumentException(sprintf(
5458 '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).',
5459 $name,
5460 $this->getMinimumStability($input)
5461 ));
5462 }
5463
5464 return array(
5465 $package->getPrettyName(),
5466 $versionSelector->findRecommendedRequireVersion($package),
5467 );
5468 }
5469
5470 private function findSimilar($package)
5471 {
5472 try {
5473 $results = $this->repos->search($package);
5474 } catch (\Exception $e) {
5475
5476  return array();
5477 }
5478 $similarPackages = array();
5479
5480 foreach ($results as $result) {
5481 $similarPackages[$result['name']] = levenshtein($package, $result['name']);
5482 }
5483 asort($similarPackages);
5484
5485 return array_keys(array_slice($similarPackages, 0, 5));
5486 }
5487 }
5488 <?php
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500 namespace Composer\Command;
5501
5502 use Composer\Installer;
5503 use Composer\Plugin\CommandEvent;
5504 use Composer\Plugin\PluginEvents;
5505 use Symfony\Component\Console\Input\InputInterface;
5506 use Symfony\Component\Console\Input\InputOption;
5507 use Symfony\Component\Console\Input\InputArgument;
5508 use Symfony\Component\Console\Output\OutputInterface;
5509
5510
5511
5512
5513
5514
5515
5516 class InstallCommand extends BaseCommand
5517 {
5518 protected function configure()
5519 {
5520 $this
5521 ->setName('install')
5522 ->setAliases(array('i'))
5523 ->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
5524 ->setDefinition(array(
5525 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5526 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5527 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
5528 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
5529 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
5530 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
5531 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
5532 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5533 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5534 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5535 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
5536 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5537 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5538 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5539 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5540 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
5541 ))
5542 ->setHelp(
5543 <<<EOT
5544 The <info>install</info> command reads the composer.lock file from
5545 the current directory, processes it, and downloads and installs all the
5546 libraries and dependencies outlined in that file. If the file does not
5547 exist it will look for composer.json and do the same.
5548
5549 <info>php composer.phar install</info>
5550
5551 EOT
5552 )
5553 ;
5554 }
5555
5556 protected function execute(InputInterface $input, OutputInterface $output)
5557 {
5558 $io = $this->getIO();
5559 if ($args = $input->getArgument('packages')) {
5560 $io->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
5561
5562 return 1;
5563 }
5564
5565 if ($input->getOption('no-custom-installers')) {
5566 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
5567 $input->setOption('no-plugins', true);
5568 }
5569
5570 if ($input->getOption('dev')) {
5571 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
5572 }
5573
5574 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5575 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5576
5577 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
5578 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5579
5580 $install = Installer::create($io, $composer);
5581
5582 $config = $composer->getConfig();
5583 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
5584
5585 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
5586 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
5587 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
5588
5589 $install
5590 ->setDryRun($input->getOption('dry-run'))
5591 ->setVerbose($input->getOption('verbose'))
5592 ->setPreferSource($preferSource)
5593 ->setPreferDist($preferDist)
5594 ->setDevMode(!$input->getOption('no-dev'))
5595 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
5596 ->setRunScripts(!$input->getOption('no-scripts'))
5597 ->setSkipSuggest($input->getOption('no-suggest'))
5598 ->setOptimizeAutoloader($optimize)
5599 ->setClassMapAuthoritative($authoritative)
5600 ->setApcuAutoloader($apcu)
5601 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5602 ;
5603
5604 if ($input->getOption('no-plugins')) {
5605 $install->disablePlugins();
5606 }
5607
5608 return $install->run();
5609 }
5610 }
5611 <?php
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623 namespace Composer\Command;
5624
5625 use Composer\Json\JsonFile;
5626 use Composer\Plugin\CommandEvent;
5627 use Composer\Plugin\PluginEvents;
5628 use Composer\Package\PackageInterface;
5629 use Composer\Repository\RepositoryInterface;
5630 use Symfony\Component\Console\Helper\Table;
5631 use Symfony\Component\Console\Input\InputInterface;
5632 use Symfony\Component\Console\Input\InputOption;
5633 use Symfony\Component\Console\Output\OutputInterface;
5634
5635
5636
5637
5638 class LicensesCommand extends BaseCommand
5639 {
5640 protected function configure()
5641 {
5642 $this
5643 ->setName('licenses')
5644 ->setDescription('Shows information about licenses of dependencies.')
5645 ->setDefinition(array(
5646 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5647 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
5648 ))
5649 ->setHelp(
5650 <<<EOT
5651 The license command displays detailed information about the licenses of
5652 the installed dependencies.
5653
5654 EOT
5655 )
5656 ;
5657 }
5658
5659 protected function execute(InputInterface $input, OutputInterface $output)
5660 {
5661 $composer = $this->getComposer();
5662
5663 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
5664 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5665
5666 $root = $composer->getPackage();
5667 $repo = $composer->getRepositoryManager()->getLocalRepository();
5668
5669 if ($input->getOption('no-dev')) {
5670 $packages = $this->filterRequiredPackages($repo, $root);
5671 } else {
5672 $packages = $this->appendPackages($repo->getPackages(), array());
5673 }
5674
5675 ksort($packages);
5676 $io = $this->getIO();
5677
5678 switch ($format = $input->getOption('format')) {
5679 case 'text':
5680 $io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
5681 $io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
5682 $io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
5683 $io->write('Dependencies:');
5684 $io->write('');
5685
5686 $table = new Table($output);
5687 $table->setStyle('compact');
5688 $tableStyle = $table->getStyle();
5689 $tableStyle->setVerticalBorderChar('');
5690 $tableStyle->setCellRowContentFormat('%s  ');
5691 $table->setHeaders(array('Name', 'Version', 'License'));
5692 foreach ($packages as $package) {
5693 $table->addRow(array(
5694 $package->getPrettyName(),
5695 $package->getFullPrettyVersion(),
5696 implode(', ', $package->getLicense()) ?: 'none',
5697 ));
5698 }
5699 $table->render();
5700 break;
5701
5702 case 'json':
5703 $dependencies = array();
5704 foreach ($packages as $package) {
5705 $dependencies[$package->getPrettyName()] = array(
5706 'version' => $package->getFullPrettyVersion(),
5707 'license' => $package->getLicense(),
5708 );
5709 }
5710
5711 $io->write(JsonFile::encode(array(
5712 'name' => $root->getPrettyName(),
5713 'version' => $root->getFullPrettyVersion(),
5714 'license' => $root->getLicense(),
5715 'dependencies' => $dependencies,
5716 )));
5717 break;
5718
5719 default:
5720 throw new \RuntimeException(sprintf('Unsupported format "%s".  See help for supported formats.', $format));
5721 }
5722 }
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732 private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
5733 {
5734 $requires = array_keys($package->getRequires());
5735
5736 $packageListNames = array_keys($bucket);
5737 $packages = array_filter(
5738 $repo->getPackages(),
5739 function ($package) use ($requires, $packageListNames) {
5740 return in_array($package->getName(), $requires) && !in_array($package->getName(), $packageListNames);
5741 }
5742 );
5743
5744 $bucket = $this->appendPackages($packages, $bucket);
5745
5746 foreach ($packages as $package) {
5747 $bucket = $this->filterRequiredPackages($repo, $package, $bucket);
5748 }
5749
5750 return $bucket;
5751 }
5752
5753
5754
5755
5756
5757
5758
5759
5760 public function appendPackages(array $packages, array $bucket)
5761 {
5762 foreach ($packages as $package) {
5763 $bucket[$package->getName()] = $package;
5764 }
5765
5766 return $bucket;
5767 }
5768 }
5769 <?php
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781 namespace Composer\Command;
5782
5783 use Symfony\Component\Console\Input\InputInterface;
5784 use Symfony\Component\Console\Input\InputArgument;
5785 use Symfony\Component\Console\Input\ArrayInput;
5786 use Symfony\Component\Console\Input\InputOption;
5787 use Symfony\Component\Console\Output\OutputInterface;
5788
5789
5790
5791
5792 class OutdatedCommand extends ShowCommand
5793 {
5794 protected function configure()
5795 {
5796 $this
5797 ->setName('outdated')
5798 ->setDescription('Shows a list of installed packages that have updates available, including their latest version.')
5799 ->setDefinition(array(
5800 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
5801 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'),
5802 new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'),
5803 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
5804 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
5805 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
5806 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5807 ))
5808 ->setHelp(
5809 <<<EOT
5810 The outdated command is just a proxy for `composer show -l`
5811
5812 The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:
5813
5814 - <info>green</info> (=): Dependency is in the latest version and is up to date.
5815 - <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
5816   compatibility breaks according to semver, so upgrade when you can but it
5817   may involve work.
5818 - <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
5819
5820
5821 EOT
5822 )
5823 ;
5824 }
5825
5826 protected function execute(InputInterface $input, OutputInterface $output)
5827 {
5828 $args = array(
5829 'show',
5830 '--latest' => true,
5831 );
5832 if (!$input->getOption('all')) {
5833 $args['--outdated'] = true;
5834 }
5835 if ($input->getOption('direct')) {
5836 $args['--direct'] = true;
5837 }
5838 if ($input->getArgument('package')) {
5839 $args['package'] = $input->getArgument('package');
5840 }
5841 if ($input->getOption('strict')) {
5842 $args['--strict'] = true;
5843 }
5844 if ($input->getOption('minor-only')) {
5845 $args['--minor-only'] = true;
5846 }
5847 $args['--format'] = $input->getOption('format');
5848
5849 $input = new ArrayInput($args);
5850
5851 return $this->getApplication()->run($input, $output);
5852 }
5853
5854
5855
5856
5857 public function isProxyCommand()
5858 {
5859 return true;
5860 }
5861 }
5862 <?php
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874 namespace Composer\Command;
5875
5876 use Symfony\Component\Console\Input\InputInterface;
5877 use Symfony\Component\Console\Output\OutputInterface;
5878
5879
5880
5881
5882 class ProhibitsCommand extends BaseDependencyCommand
5883 {
5884
5885
5886
5887 protected function configure()
5888 {
5889 parent::configure();
5890
5891 $this
5892 ->setName('prohibits')
5893 ->setAliases(array('why-not'))
5894 ->setDescription('Shows which packages prevent the given package from being installed.')
5895 ->setHelp(
5896 <<<EOT
5897 Displays detailed information about why a package cannot be installed.
5898
5899 <info>php composer.phar prohibits composer/composer</info>
5900
5901 EOT
5902 )
5903 ;
5904 }
5905
5906
5907
5908
5909
5910
5911
5912
5913 protected function execute(InputInterface $input, OutputInterface $output)
5914 {
5915 return parent::doExecute($input, $output, true);
5916 }
5917 }
5918 <?php
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930 namespace Composer\Command;
5931
5932 use Composer\Config\JsonConfigSource;
5933 use Composer\Installer;
5934 use Composer\Plugin\CommandEvent;
5935 use Composer\Plugin\PluginEvents;
5936 use Composer\Json\JsonFile;
5937 use Composer\Factory;
5938 use Symfony\Component\Console\Input\InputInterface;
5939 use Symfony\Component\Console\Input\InputOption;
5940 use Symfony\Component\Console\Input\InputArgument;
5941 use Symfony\Component\Console\Output\OutputInterface;
5942
5943
5944
5945
5946
5947 class RemoveCommand extends BaseCommand
5948 {
5949 protected function configure()
5950 {
5951 $this
5952 ->setName('remove')
5953 ->setDescription('Removes a package from the require or require-dev.')
5954 ->setDefinition(array(
5955 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
5956 new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
5957 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5958 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
5959 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5960 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
5961 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
5962 new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
5963 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5964 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5965 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5966 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5967 ))
5968 ->setHelp(
5969 <<<EOT
5970 The <info>remove</info> command removes a package from the current
5971 list of installed packages
5972
5973 <info>php composer.phar remove</info>
5974
5975 EOT
5976 )
5977 ;
5978 }
5979
5980 protected function execute(InputInterface $input, OutputInterface $output)
5981 {
5982 $packages = $input->getArgument('packages');
5983 $packages = array_map('strtolower', $packages);
5984
5985 $file = Factory::getComposerFile();
5986
5987 $jsonFile = new JsonFile($file);
5988 $composer = $jsonFile->read();
5989 $composerBackup = file_get_contents($jsonFile->getPath());
5990
5991 $json = new JsonConfigSource($jsonFile);
5992
5993 $type = $input->getOption('dev') ? 'require-dev' : 'require';
5994 $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
5995 $io = $this->getIO();
5996
5997 if ($input->getOption('update-with-dependencies')) {
5998 $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>');
5999 }
6000
6001
6002  foreach (array('require', 'require-dev') as $linkType) {
6003 if (isset($composer[$linkType])) {
6004 foreach ($composer[$linkType] as $name => $version) {
6005 $composer[$linkType][strtolower($name)] = $name;
6006 }
6007 }
6008 }
6009
6010 foreach ($packages as $package) {
6011 if (isset($composer[$type][$package])) {
6012 $json->removeLink($type, $composer[$type][$package]);
6013 } elseif (isset($composer[$altType][$package])) {
6014 $io->writeError('<warning>'.$composer[$altType][$package].' could not be found in '.$type.' but it is present in '.$altType.'</warning>');
6015 if ($io->isInteractive()) {
6016 if ($io->askConfirmation('Do you want to remove it from '.$altType.' [<comment>yes</comment>]? ', true)) {
6017 $json->removeLink($altType, $composer[$altType][$package]);
6018 }
6019 }
6020 } else {
6021 $io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
6022 }
6023 }
6024
6025 if ($input->getOption('no-update')) {
6026 return 0;
6027 }
6028
6029
6030  $this->resetComposer();
6031 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6032 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6033
6034 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
6035 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6036
6037 $install = Installer::create($io, $composer);
6038
6039 $updateDevMode = !$input->getOption('update-no-dev');
6040 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6041 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6042 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6043
6044 $install
6045 ->setVerbose($input->getOption('verbose'))
6046 ->setDevMode($updateDevMode)
6047 ->setOptimizeAutoloader($optimize)
6048 ->setClassMapAuthoritative($authoritative)
6049 ->setApcuAutoloader($apcu)
6050 ->setUpdate(true)
6051 ->setUpdateWhitelist($packages)
6052 ->setWhitelistTransitiveDependencies(!$input->getOption('no-update-with-dependencies'))
6053 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6054 ->setRunScripts(!$input->getOption('no-scripts'))
6055 ;
6056
6057 $status = $install->run();
6058 if ($status !== 0) {
6059 $io->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
6060 file_put_contents($jsonFile->getPath(), $composerBackup);
6061 }
6062
6063 return $status;
6064 }
6065 }
6066 <?php
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078 namespace Composer\Command;
6079
6080 use Symfony\Component\Console\Input\InputInterface;
6081 use Symfony\Component\Console\Input\InputArgument;
6082 use Symfony\Component\Console\Input\InputOption;
6083 use Symfony\Component\Console\Output\OutputInterface;
6084 use Composer\Factory;
6085 use Composer\Installer;
6086 use Composer\Json\JsonFile;
6087 use Composer\Json\JsonManipulator;
6088 use Composer\Package\Version\VersionParser;
6089 use Composer\Plugin\CommandEvent;
6090 use Composer\Plugin\PluginEvents;
6091 use Composer\Repository\CompositeRepository;
6092 use Composer\Repository\PlatformRepository;
6093
6094
6095
6096
6097
6098 class RequireCommand extends InitCommand
6099 {
6100 protected function configure()
6101 {
6102 $this
6103 ->setName('require')
6104 ->setDescription('Adds required packages to your composer.json and installs them.')
6105 ->setDefinition(array(
6106 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"'),
6107 new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
6108 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
6109 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
6110 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6111 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
6112 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
6113 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
6114 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
6115 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
6116 new InputOption('update-with-all-dependencies', null, InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
6117 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
6118 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
6119 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
6120 new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
6121 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
6122 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
6123 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
6124 ))
6125 ->setHelp(
6126 <<<EOT
6127 The require command adds required packages to your composer.json and installs them.
6128
6129 If you do not specify a package, composer will prompt you to search for a package, and given results, provide a list of 
6130 matches to require.
6131
6132 If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.
6133
6134 If you do not want to install the new dependencies immediately you can call it with --no-update
6135
6136 EOT
6137 )
6138 ;
6139 }
6140
6141 protected function execute(InputInterface $input, OutputInterface $output)
6142 {
6143 $file = Factory::getComposerFile();
6144 $io = $this->getIO();
6145
6146 $newlyCreated = !file_exists($file);
6147 if ($newlyCreated && !file_put_contents($file, "{\n}\n")) {
6148 $io->writeError('<error>'.$file.' could not be created.</error>');
6149
6150 return 1;
6151 }
6152 if (!is_readable($file)) {
6153 $io->writeError('<error>'.$file.' is not readable.</error>');
6154
6155 return 1;
6156 }
6157 if (!is_writable($file)) {
6158 $io->writeError('<error>'.$file.' is not writable.</error>');
6159
6160 return 1;
6161 }
6162
6163 if (filesize($file) === 0) {
6164 file_put_contents($file, "{\n}\n");
6165 }
6166
6167 $json = new JsonFile($file);
6168 $composerBackup = file_get_contents($json->getPath());
6169
6170 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6171 $repos = $composer->getRepositoryManager()->getRepositories();
6172
6173 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6174
6175  $this->repos = new CompositeRepository(array_merge(
6176 array(new PlatformRepository(array(), $platformOverrides)),
6177 $repos
6178 ));
6179
6180 if ($composer->getPackage()->getPreferStable()) {
6181 $preferredStability = 'stable';
6182 } else {
6183 $preferredStability = $composer->getPackage()->getMinimumStability();
6184 }
6185
6186 $phpVersion = $this->repos->findPackage('php', '*')->getPrettyVersion();
6187 $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability);
6188
6189 $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
6190 $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
6191 $requirements = $this->formatRequirements($requirements);
6192
6193
6194  $versionParser = new VersionParser();
6195 foreach ($requirements as $constraint) {
6196 $versionParser->parseConstraints($constraint);
6197 }
6198
6199 $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
6200
6201 if (!$this->updateFileCleanly($json, $requirements, $requireKey, $removeKey, $sortPackages)) {
6202 $composerDefinition = $json->read();
6203 foreach ($requirements as $package => $version) {
6204 $composerDefinition[$requireKey][$package] = $version;
6205 unset($composerDefinition[$removeKey][$package]);
6206 }
6207 $json->write($composerDefinition);
6208 }
6209
6210 $io->writeError('<info>'.$file.' has been '.($newlyCreated ? 'created' : 'updated').'</info>');
6211
6212 if ($input->getOption('no-update')) {
6213 return 0;
6214 }
6215 $updateDevMode = !$input->getOption('update-no-dev');
6216 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6217 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6218 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6219
6220
6221  $this->resetComposer();
6222 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6223 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6224
6225 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
6226 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6227
6228 $install = Installer::create($io, $composer);
6229
6230 $install
6231 ->setVerbose($input->getOption('verbose'))
6232 ->setPreferSource($input->getOption('prefer-source'))
6233 ->setPreferDist($input->getOption('prefer-dist'))
6234 ->setDevMode($updateDevMode)
6235 ->setRunScripts(!$input->getOption('no-scripts'))
6236 ->setSkipSuggest($input->getOption('no-suggest'))
6237 ->setOptimizeAutoloader($optimize)
6238 ->setClassMapAuthoritative($authoritative)
6239 ->setApcuAutoloader($apcu)
6240 ->setUpdate(true)
6241 ->setUpdateWhitelist(array_keys($requirements))
6242 ->setWhitelistTransitiveDependencies($input->getOption('update-with-dependencies'))
6243 ->setWhitelistAllDependencies($input->getOption('update-with-all-dependencies'))
6244 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6245 ->setPreferStable($input->getOption('prefer-stable'))
6246 ->setPreferLowest($input->getOption('prefer-lowest'))
6247 ;
6248
6249 $status = $install->run();
6250 if ($status !== 0) {
6251 if ($newlyCreated) {
6252 $io->writeError("\n".'<error>Installation failed, deleting '.$file.'.</error>');
6253 unlink($json->getPath());
6254 } else {
6255 $io->writeError("\n".'<error>Installation failed, reverting '.$file.' to its original content.</error>');
6256 file_put_contents($json->getPath(), $composerBackup);
6257 }
6258 }
6259
6260 return $status;
6261 }
6262
6263 private function updateFileCleanly($json, array $new, $requireKey, $removeKey, $sortPackages)
6264 {
6265 $contents = file_get_contents($json->getPath());
6266
6267 $manipulator = new JsonManipulator($contents);
6268
6269 foreach ($new as $package => $constraint) {
6270 if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
6271 return false;
6272 }
6273 if (!$manipulator->removeSubNode($removeKey, $package)) {
6274 return false;
6275 }
6276 }
6277
6278 file_put_contents($json->getPath(), $manipulator->getContents());
6279
6280 return true;
6281 }
6282
6283 protected function interact(InputInterface $input, OutputInterface $output)
6284 {
6285 return;
6286 }
6287 }
6288 <?php
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300 namespace Composer\Command;
6301
6302 use Composer\Script\Event as ScriptEvent;
6303 use Composer\Script\ScriptEvents;
6304 use Composer\Util\ProcessExecutor;
6305 use Symfony\Component\Console\Input\InputInterface;
6306 use Symfony\Component\Console\Input\InputOption;
6307 use Symfony\Component\Console\Input\InputArgument;
6308 use Symfony\Component\Console\Output\OutputInterface;
6309 use Symfony\Component\Console\Helper\Table;
6310
6311
6312
6313
6314 class RunScriptCommand extends BaseCommand
6315 {
6316
6317
6318
6319 protected $scriptEvents = array(
6320 ScriptEvents::PRE_INSTALL_CMD,
6321 ScriptEvents::POST_INSTALL_CMD,
6322 ScriptEvents::PRE_UPDATE_CMD,
6323 ScriptEvents::POST_UPDATE_CMD,
6324 ScriptEvents::PRE_STATUS_CMD,
6325 ScriptEvents::POST_STATUS_CMD,
6326 ScriptEvents::POST_ROOT_PACKAGE_INSTALL,
6327 ScriptEvents::POST_CREATE_PROJECT_CMD,
6328 ScriptEvents::PRE_ARCHIVE_CMD,
6329 ScriptEvents::POST_ARCHIVE_CMD,
6330 ScriptEvents::PRE_AUTOLOAD_DUMP,
6331 ScriptEvents::POST_AUTOLOAD_DUMP,
6332 );
6333
6334 protected function configure()
6335 {
6336 $this
6337 ->setName('run-script')
6338 ->setDescription('Runs the scripts defined in composer.json.')
6339 ->setDefinition(array(
6340 new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),
6341 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6342 new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'),
6343 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6344 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6345 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.'),
6346 ))
6347 ->setHelp(
6348 <<<EOT
6349 The <info>run-script</info> command runs scripts defined in composer.json:
6350
6351 <info>php composer.phar run-script post-update-cmd</info>
6352 EOT
6353 )
6354 ;
6355 }
6356
6357 protected function execute(InputInterface $input, OutputInterface $output)
6358 {
6359 if ($input->getOption('list')) {
6360 return $this->listScripts($output);
6361 } elseif (!$input->getArgument('script')) {
6362 throw new \RuntimeException('Missing required argument "script"');
6363 }
6364
6365 $script = $input->getArgument('script');
6366 if (!in_array($script, $this->scriptEvents)) {
6367 if (defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
6368 throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
6369 }
6370 }
6371
6372 $composer = $this->getComposer();
6373 $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
6374 $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode);
6375 $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event);
6376 if (!$hasListeners) {
6377 throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
6378 }
6379
6380 $args = $input->getArgument('args');
6381
6382 if (null !== $timeout = $input->getOption('timeout')) {
6383 if (!ctype_digit($timeout)) {
6384 throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever');
6385 }
6386
6387  ProcessExecutor::setTimeout((int) $timeout);
6388 }
6389
6390 return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
6391 }
6392
6393 protected function listScripts(OutputInterface $output)
6394 {
6395 $scripts = $this->getComposer()->getPackage()->getScripts();
6396
6397 if (!count($scripts)) {
6398 return 0;
6399 }
6400
6401 $io = $this->getIO();
6402 $io->writeError('<info>scripts:</info>');
6403 $table = array();
6404 foreach ($scripts as $name => $script) {
6405 $description = '';
6406 try {
6407 $cmd = $this->getApplication()->find($name);
6408 if ($cmd instanceof ScriptAliasCommand) {
6409 $description = $cmd->getDescription();
6410 }
6411 } catch (\Symfony\Component\Console\Exception\CommandNotFoundException $e) {
6412
6413  }
6414 $table[] = array('  '.$name, $description);
6415 }
6416
6417 $renderer = new Table($output);
6418 $renderer->setStyle('compact');
6419 $rendererStyle = $renderer->getStyle();
6420 $rendererStyle->setVerticalBorderChar('');
6421 $rendererStyle->setCellRowContentFormat('%s  ');
6422 $renderer->setRows($table)->render();
6423
6424 return 0;
6425 }
6426 }
6427 <?php
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439 namespace Composer\Command;
6440
6441 use Symfony\Component\Console\Input\InputInterface;
6442 use Symfony\Component\Console\Input\InputOption;
6443 use Symfony\Component\Console\Input\InputArgument;
6444 use Symfony\Component\Console\Output\OutputInterface;
6445
6446
6447
6448
6449 class ScriptAliasCommand extends BaseCommand
6450 {
6451 private $script;
6452 private $description;
6453
6454 public function __construct($script, $description)
6455 {
6456 $this->script = $script;
6457 $this->description = empty($description) ? 'Runs the '.$script.' script as defined in composer.json.' : $description;
6458
6459 parent::__construct();
6460 }
6461
6462 protected function configure()
6463 {
6464 $this
6465 ->setName($this->script)
6466 ->setDescription($this->description)
6467 ->setDefinition(array(
6468 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6469 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6470 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6471 ))
6472 ->setHelp(
6473 <<<EOT
6474 The <info>run-script</info> command runs scripts defined in composer.json:
6475
6476 <info>php composer.phar run-script post-update-cmd</info>
6477 EOT
6478 )
6479 ;
6480 }
6481
6482 protected function execute(InputInterface $input, OutputInterface $output)
6483 {
6484 $composer = $this->getComposer();
6485
6486 $args = $input->getArguments();
6487
6488 return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args']);
6489 }
6490 }
6491 <?php
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503 namespace Composer\Command;
6504
6505 use Composer\Factory;
6506 use Symfony\Component\Console\Input\InputInterface;
6507 use Symfony\Component\Console\Input\InputArgument;
6508 use Symfony\Component\Console\Input\InputOption;
6509 use Symfony\Component\Console\Output\OutputInterface;
6510 use Composer\Repository\CompositeRepository;
6511 use Composer\Repository\PlatformRepository;
6512 use Composer\Repository\RepositoryInterface;
6513 use Composer\Plugin\CommandEvent;
6514 use Composer\Plugin\PluginEvents;
6515
6516
6517
6518
6519 class SearchCommand extends BaseCommand
6520 {
6521 protected $matches;
6522 protected $lowMatches = array();
6523 protected $tokens;
6524 protected $output;
6525 protected $onlyName;
6526
6527 protected function configure()
6528 {
6529 $this
6530 ->setName('search')
6531 ->setDescription('Searches for packages.')
6532 ->setDefinition(array(
6533 new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
6534 new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
6535 new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
6536 ))
6537 ->setHelp(
6538 <<<EOT
6539 The search command searches for packages by its name
6540 <info>php composer.phar search symfony composer</info>
6541
6542 EOT
6543 )
6544 ;
6545 }
6546
6547 protected function execute(InputInterface $input, OutputInterface $output)
6548 {
6549
6550  $platformRepo = new PlatformRepository;
6551 $io = $this->getIO();
6552 if (!($composer = $this->getComposer(false))) {
6553 $composer = Factory::create($this->getIO(), array(), $input->hasParameterOption('--no-plugins'));
6554 }
6555 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6556 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6557 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6558
6559 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
6560 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6561
6562 $onlyName = $input->getOption('only-name');
6563 $type = $input->getOption('type') ?: null;
6564
6565 $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
6566 $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
6567
6568 foreach ($results as $result) {
6569 $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
6570 }
6571 }
6572 }
6573 <?php
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585 namespace Composer\Command;
6586
6587 use Composer\Composer;
6588 use Composer\Factory;
6589 use Composer\Config;
6590 use Composer\Util\Filesystem;
6591 use Composer\SelfUpdate\Keys;
6592 use Composer\SelfUpdate\Versions;
6593 use Composer\IO\IOInterface;
6594 use Composer\Downloader\FilesystemException;
6595 use Symfony\Component\Console\Input\InputInterface;
6596 use Symfony\Component\Console\Input\InputOption;
6597 use Symfony\Component\Console\Input\InputArgument;
6598 use Symfony\Component\Console\Output\OutputInterface;
6599 use Symfony\Component\Finder\Finder;
6600
6601
6602
6603
6604
6605
6606 class SelfUpdateCommand extends BaseCommand
6607 {
6608 const HOMEPAGE = 'getcomposer.org';
6609 const OLD_INSTALL_EXT = '-old.phar';
6610
6611 protected function configure()
6612 {
6613 $this
6614 ->setName('self-update')
6615 ->setAliases(array('selfupdate'))
6616 ->setDescription('Updates composer.phar to the latest version.')
6617 ->setDefinition(array(
6618 new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'),
6619 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'),
6620 new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'),
6621 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6622 new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'),
6623 new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'),
6624 new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'),
6625 new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'),
6626 new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit'),
6627 ))
6628 ->setHelp(
6629 <<<EOT
6630 The <info>self-update</info> command checks getcomposer.org for newer
6631 versions of composer and if found, installs the latest.
6632
6633 <info>php composer.phar self-update</info>
6634
6635 EOT
6636 )
6637 ;
6638 }
6639
6640 protected function execute(InputInterface $input, OutputInterface $output)
6641 {
6642 $config = Factory::createConfig();
6643
6644 if ($config->get('disable-tls') === true) {
6645 $baseUrl = 'http://' . self::HOMEPAGE;
6646 } else {
6647 $baseUrl = 'https://' . self::HOMEPAGE;
6648 }
6649
6650 $io = $this->getIO();
6651 $remoteFilesystem = Factory::createRemoteFilesystem($io, $config);
6652
6653 $versionsUtil = new Versions($config, $remoteFilesystem);
6654
6655
6656  foreach (array('stable', 'preview', 'snapshot') as $channel) {
6657 if ($input->getOption($channel)) {
6658 $versionsUtil->setChannel($channel);
6659 }
6660 }
6661
6662 if ($input->getOption('set-channel-only')) {
6663 return 0;
6664 }
6665
6666 $cacheDir = $config->get('cache-dir');
6667 $rollbackDir = $config->get('data-dir');
6668 $home = $config->get('home');
6669 $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
6670
6671 if ($input->getOption('update-keys')) {
6672 return $this->fetchKeys($io, $config);
6673 }
6674
6675
6676  $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
6677
6678
6679  if (!is_writable($tmpDir)) {
6680 throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written');
6681 }
6682
6683
6684  if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
6685 $composeUser = posix_getpwuid(posix_geteuid());
6686 $homeOwner = posix_getpwuid(fileowner($home));
6687 if (isset($composeUser['name']) && isset($homeOwner['name']) && $composeUser['name'] !== $homeOwner['name']) {
6688 $io->writeError('<warning>You are running composer as "'.$composeUser['name'].'", while "'.$home.'" is owned by "'.$homeOwner['name'].'"</warning>');
6689 }
6690 }
6691
6692 if ($input->getOption('rollback')) {
6693 return $this->rollback($output, $rollbackDir, $localFilename);
6694 }
6695
6696 $latest = $versionsUtil->getLatest();
6697 $latestVersion = $latest['version'];
6698 $updateVersion = $input->getArgument('version') ?: $latestVersion;
6699
6700 if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
6701 $io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
6702
6703 return 1;
6704 }
6705
6706 if (Composer::VERSION === $updateVersion) {
6707 $io->writeError(sprintf('<info>You are already using composer version %s (%s channel).</info>', $updateVersion, $versionsUtil->getChannel()));
6708
6709
6710  if ($input->getOption('clean-backups')) {
6711 $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir));
6712 }
6713
6714 return 0;
6715 }
6716
6717 $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar';
6718 $backupFile = sprintf(
6719 '%s/%s-%s%s',
6720 $rollbackDir,
6721 strtr(Composer::RELEASE_DATE, ' :', '_-'),
6722 preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION),
6723 self::OLD_INSTALL_EXT
6724 );
6725
6726 $updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion);
6727
6728 $io->write(sprintf("Updating to version <info>%s</info> (%s channel).", $updateVersion, $versionsUtil->getChannel()));
6729 $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
6730 $signature = $remoteFilesystem->getContents(self::HOMEPAGE, $remoteFilename.'.sig', false);
6731 $io->writeError('   ', false);
6732 $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
6733 $io->writeError('');
6734
6735 if (!file_exists($tempFilename) || !$signature) {
6736 $io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
6737
6738 return 1;
6739 }
6740
6741
6742  if (!extension_loaded('openssl') && $config->get('disable-tls')) {
6743 $io->writeError('<warning>Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls</warning>');
6744 } else {
6745 if (!extension_loaded('openssl')) {
6746 throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. '
6747 . '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.');
6748 }
6749
6750 $sigFile = 'file://'.$home.'/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub');
6751 if (!file_exists($sigFile)) {
6752 file_put_contents(
6753 $home.'/keys.dev.pub',
6754 <<<DEVPUBKEY
6755 -----BEGIN PUBLIC KEY-----
6756 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f
6757 FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi
6758 i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A
6759 hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f
6760 o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk
6761 8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn
6762 8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf
6763 TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9
6764 pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72
6765 8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4
6766 r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE
6767 wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ==
6768 -----END PUBLIC KEY-----
6769 DEVPUBKEY
6770 );
6771
6772 file_put_contents(
6773 $home.'/keys.tags.pub',
6774 <<<TAGSPUBKEY
6775 -----BEGIN PUBLIC KEY-----
6776 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2
6777 MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh
6778 vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO
6779 bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M
6780 mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf
6781 noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM
6782 nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ
6783 rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr
6784 RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK
6785 tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e
6786 TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95
6787 RGv89BPD+2DLnJysngsvVaUCAwEAAQ==
6788 -----END PUBLIC KEY-----
6789 TAGSPUBKEY
6790 );
6791 }
6792
6793 $pubkeyid = openssl_pkey_get_public($sigFile);
6794 $algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384';
6795 if (!in_array('SHA384', openssl_get_md_methods())) {
6796 throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
6797 }
6798 $signature = json_decode($signature, true);
6799 $signature = base64_decode($signature['sha384']);
6800 $verified = 1 === openssl_verify(file_get_contents($tempFilename), $signature, $pubkeyid, $algo);
6801 openssl_free_key($pubkeyid);
6802 if (!$verified) {
6803 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');
6804 }
6805 }
6806
6807
6808  if ($input->getOption('clean-backups')) {
6809 $this->cleanBackups($rollbackDir);
6810 }
6811
6812 if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
6813 @unlink($tempFilename);
6814 $io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
6815 $io->writeError('<error>Please re-run the self-update command to try again.</error>');
6816
6817 return 1;
6818 }
6819
6820 if (file_exists($backupFile)) {
6821 $io->writeError(sprintf(
6822 'Use <info>composer self-update --rollback</info> to return to version <comment>%s</comment>',
6823 Composer::VERSION
6824 ));
6825 } else {
6826 $io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
6827 }
6828 }
6829
6830 protected function fetchKeys(IOInterface $io, Config $config)
6831 {
6832 if (!$io->isInteractive()) {
6833 throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
6834 }
6835
6836 $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
6837
6838 $validator = function ($value) {
6839 if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
6840 throw new \UnexpectedValueException('Invalid input');
6841 }
6842
6843 return trim($value)."\n";
6844 };
6845
6846 $devKey = '';
6847 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
6848 $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
6849 while ($line = $io->ask('')) {
6850 $devKey .= trim($line)."\n";
6851 if (trim($line) === '-----END PUBLIC KEY-----') {
6852 break;
6853 }
6854 }
6855 }
6856 file_put_contents($keyPath = $config->get('home').'/keys.dev.pub', $match[0]);
6857 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6858
6859 $tagsKey = '';
6860 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
6861 $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
6862 while ($line = $io->ask('')) {
6863 $tagsKey .= trim($line)."\n";
6864 if (trim($line) === '-----END PUBLIC KEY-----') {
6865 break;
6866 }
6867 }
6868 }
6869 file_put_contents($keyPath = $config->get('home').'/keys.tags.pub', $match[0]);
6870 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6871
6872 $io->write('Public keys stored in '.$config->get('home'));
6873 }
6874
6875 protected function rollback(OutputInterface $output, $rollbackDir, $localFilename)
6876 {
6877 $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
6878 if (!$rollbackVersion) {
6879 throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"');
6880 }
6881
6882 $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
6883
6884 if (!is_file($oldFile)) {
6885 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
6886 }
6887 if (!is_readable($oldFile)) {
6888 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
6889 }
6890
6891 $io = $this->getIO();
6892 $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
6893 if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
6894 $io->writeError('<error>The backup file was corrupted ('.$err->getMessage().').</error>');
6895
6896 return 1;
6897 }
6898
6899 return 0;
6900 }
6901
6902
6903
6904
6905
6906
6907
6908
6909 protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
6910 {
6911 try {
6912 @chmod($newFilename, fileperms($localFilename));
6913 if (!ini_get('phar.readonly')) {
6914
6915  $phar = new \Phar($newFilename);
6916
6917  unset($phar);
6918 }
6919
6920
6921  if ($backupTarget && file_exists($localFilename)) {
6922 @copy($localFilename, $backupTarget);
6923 }
6924
6925 rename($newFilename, $localFilename);
6926
6927 return null;
6928 } catch (\Exception $e) {
6929 if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
6930 throw $e;
6931 }
6932
6933 return $e;
6934 }
6935 }
6936
6937 protected function cleanBackups($rollbackDir, $except = null)
6938 {
6939 $finder = $this->getOldInstallationFinder($rollbackDir);
6940 $io = $this->getIO();
6941 $fs = new Filesystem;
6942
6943 foreach ($finder as $file) {
6944 if ($except && $file->getBasename(self::OLD_INSTALL_EXT) === $except) {
6945 continue;
6946 }
6947 $file = (string) $file;
6948 $io->writeError('<info>Removing: '.$file.'</info>');
6949 $fs->remove($file);
6950 }
6951 }
6952
6953 protected function getLastBackupVersion($rollbackDir)
6954 {
6955 $finder = $this->getOldInstallationFinder($rollbackDir);
6956 $finder->sortByName();
6957 $files = iterator_to_array($finder);
6958
6959 if (count($files)) {
6960 return basename(end($files), self::OLD_INSTALL_EXT);
6961 }
6962
6963 return false;
6964 }
6965
6966 protected function getOldInstallationFinder($rollbackDir)
6967 {
6968 $finder = Finder::create()
6969 ->depth(0)
6970 ->files()
6971 ->name('*' . self::OLD_INSTALL_EXT)
6972 ->in($rollbackDir);
6973
6974 return $finder;
6975 }
6976 }
6977 <?php
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989 namespace Composer\Command;
6990
6991 use Composer\Composer;
6992 use Composer\DependencyResolver\DefaultPolicy;
6993 use Composer\DependencyResolver\Pool;
6994 use Composer\Json\JsonFile;
6995 use Composer\Package\BasePackage;
6996 use Composer\Package\CompletePackageInterface;
6997 use Composer\Package\PackageInterface;
6998 use Composer\Package\Version\VersionParser;
6999 use Composer\Package\Version\VersionSelector;
7000 use Composer\Plugin\CommandEvent;
7001 use Composer\Plugin\PluginEvents;
7002 use Composer\Repository\ArrayRepository;
7003 use Composer\Repository\ComposerRepository;
7004 use Composer\Repository\CompositeRepository;
7005 use Composer\Repository\PlatformRepository;
7006 use Composer\Repository\RepositoryFactory;
7007 use Composer\Repository\RepositoryInterface;
7008 use Composer\Semver\Constraint\ConstraintInterface;
7009 use Composer\Semver\Semver;
7010 use Composer\Spdx\SpdxLicenses;
7011 use Composer\Util\Platform;
7012 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
7013 use Symfony\Component\Console\Input\InputArgument;
7014 use Symfony\Component\Console\Input\InputInterface;
7015 use Symfony\Component\Console\Input\InputOption;
7016 use Symfony\Component\Console\Output\OutputInterface;
7017 use Symfony\Component\Console\Terminal;
7018
7019
7020
7021
7022
7023
7024
7025 class ShowCommand extends BaseCommand
7026 {
7027
7028 protected $versionParser;
7029 protected $colors;
7030
7031
7032 private $pool;
7033
7034 protected function configure()
7035 {
7036 $this
7037 ->setName('show')
7038 ->setAliases(array('info'))
7039 ->setDescription('Shows information about packages.')
7040 ->setDefinition(array(
7041 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
7042 new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
7043 new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'),
7044 new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'),
7045 new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
7046 new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
7047 new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
7048 new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
7049 new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
7050 new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
7051 new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'),
7052 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'),
7053 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
7054 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
7055 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
7056 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
7057 ))
7058 ->setHelp(
7059 <<<EOT
7060 The show command displays detailed information about a package, or
7061 lists all packages available.
7062
7063 EOT
7064 )
7065 ;
7066 }
7067
7068 protected function execute(InputInterface $input, OutputInterface $output)
7069 {
7070 $this->versionParser = new VersionParser;
7071 if ($input->getOption('tree')) {
7072 $this->initStyles($output);
7073 }
7074
7075 $composer = $this->getComposer(false);
7076 $io = $this->getIO();
7077
7078 if ($input->getOption('installed')) {
7079 $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>');
7080 }
7081
7082 if ($input->getOption('outdated')) {
7083 $input->setOption('latest', true);
7084 }
7085
7086 if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) {
7087 $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)');
7088
7089 return 1;
7090 }
7091
7092 if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) {
7093 $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)');
7094
7095 return 1;
7096 }
7097
7098 if ($input->getOption('tree') && $input->getOption('latest')) {
7099 $io->writeError('The --tree (-t) option is not usable in combination with --latest (-l)');
7100
7101 return 1;
7102 }
7103
7104 $format = $input->getOption('format');
7105 if (!in_array($format, array('text', 'json'))) {
7106 $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
7107
7108 return 1;
7109 }
7110
7111
7112  $platformOverrides = array();
7113 if ($composer) {
7114 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
7115 }
7116 $platformRepo = new PlatformRepository(array(), $platformOverrides);
7117 $phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
7118
7119 if ($input->getOption('self')) {
7120 $package = $this->getComposer()->getPackage();
7121 $repos = $installedRepo = new ArrayRepository(array($package));
7122 } elseif ($input->getOption('platform')) {
7123 $repos = $installedRepo = $platformRepo;
7124 } elseif ($input->getOption('available')) {
7125 $installedRepo = $platformRepo;
7126 if ($composer) {
7127 $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
7128 } else {
7129 $defaultRepos = RepositoryFactory::defaultRepos($io);
7130 $repos = new CompositeRepository($defaultRepos);
7131 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
7132 }
7133 } elseif ($input->getOption('all') && $composer) {
7134 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
7135 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
7136 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
7137 } elseif ($input->getOption('all')) {
7138 $defaultRepos = RepositoryFactory::defaultRepos($io);
7139 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
7140 $installedRepo = $platformRepo;
7141 $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
7142 } else {
7143 $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
7144 $rootPkg = $this->getComposer()->getPackage();
7145 if (!$installedRepo->getPackages() && ($rootPkg->getRequires() || $rootPkg->getDevRequires())) {
7146 $io->writeError('<warning>No dependencies installed. Try running composer install or update.</warning>');
7147 }
7148 }
7149
7150 if ($composer) {
7151 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
7152 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7153 }
7154
7155 if ($input->getOption('latest') && null === $composer) {
7156 $io->writeError('No composer.json found in the current directory, disabling "latest" option');
7157 $input->setOption('latest', false);
7158 }
7159
7160 $packageFilter = $input->getArgument('package');
7161
7162
7163  if (($packageFilter && false === strpos($packageFilter, '*')) || !empty($package)) {
7164 if (empty($package)) {
7165 list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version'));
7166
7167 if (empty($package)) {
7168 $options = $input->getOptions();
7169 if (!isset($options['working-dir']) || !file_exists('composer.json')) {
7170 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found');
7171 }
7172
7173 $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
7174
7175 return 1;
7176 }
7177 } else {
7178 $versions = array($package->getPrettyVersion() => $package->getVersion());
7179 }
7180
7181 $exitCode = 0;
7182 if ($input->getOption('tree')) {
7183 $arrayTree = $this->generatePackageTree($package, $installedRepo, $repos);
7184
7185 if ('json' === $format) {
7186 $io->write(JsonFile::encode(array('installed' => array($arrayTree))));
7187 } else {
7188 $this->displayPackageTree(array($arrayTree));
7189 }
7190 } else {
7191 $latestPackage = null;
7192 if ($input->getOption('latest')) {
7193 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion);
7194 }
7195 if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
7196 $exitCode = 1;
7197 }
7198 $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
7199 $this->printLinks($package, 'requires');
7200 $this->printLinks($package, 'devRequires', 'requires (dev)');
7201 if ($package->getSuggests()) {
7202 $io->write("\n<info>suggests</info>");
7203 foreach ($package->getSuggests() as $suggested => $reason) {
7204 $io->write($suggested . ' <comment>' . $reason . '</comment>');
7205 }
7206 }
7207 $this->printLinks($package, 'provides');
7208 $this->printLinks($package, 'conflicts');
7209 $this->printLinks($package, 'replaces');
7210 }
7211
7212 return $exitCode;
7213 }
7214
7215
7216  if ($input->getOption('tree')) {
7217 $rootRequires = $this->getRootRequires();
7218 $packages = $installedRepo->getPackages();
7219 usort($packages, 'strcmp');
7220 $arrayTree = array();
7221 foreach ($packages as $package) {
7222 if (in_array($package->getName(), $rootRequires, true)) {
7223 $arrayTree[] = $this->generatePackageTree($package, $installedRepo, $repos);
7224 }
7225 }
7226
7227 if ('json' === $format) {
7228 $io->write(JsonFile::encode(array('installed' => $arrayTree)));
7229 } else {
7230 $this->displayPackageTree($arrayTree);
7231 }
7232
7233 return 0;
7234 }
7235
7236 if ($repos instanceof CompositeRepository) {
7237 $repos = $repos->getRepositories();
7238 } elseif (!is_array($repos)) {
7239 $repos = array($repos);
7240 }
7241
7242
7243  $packages = array();
7244 if (null !== $packageFilter) {
7245 $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
7246 }
7247
7248 $packageListFilter = array();
7249 if ($input->getOption('direct')) {
7250 $packageListFilter = $this->getRootRequires();
7251 }
7252
7253 if (class_exists('Symfony\Component\Console\Terminal')) {
7254 $terminal = new Terminal();
7255 $width = $terminal->getWidth();
7256 } else {
7257
7258  list($width) = $this->getApplication()->getTerminalDimensions();
7259 }
7260 if (null === $width) {
7261
7262  
7263  $width = PHP_INT_MAX;
7264 }
7265 if (Platform::isWindows()) {
7266 $width--;
7267 } else {
7268 $width = max(80, $width);
7269 }
7270
7271 if ($input->getOption('path') && null === $composer) {
7272 $io->writeError('No composer.json found in the current directory, disabling "path" option');
7273 $input->setOption('path', false);
7274 }
7275
7276 foreach ($repos as $repo) {
7277 if ($repo === $platformRepo) {
7278 $type = 'platform';
7279 } elseif (
7280 $repo === $installedRepo
7281 || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
7282 ) {
7283 $type = 'installed';
7284 } else {
7285 $type = 'available';
7286 }
7287 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
7288 foreach ($repo->getProviderNames() as $name) {
7289 if (!$packageFilter || preg_match($packageFilter, $name)) {
7290 $packages[$type][$name] = $name;
7291 }
7292 }
7293 } else {
7294 foreach ($repo->getPackages() as $package) {
7295 if (!isset($packages[$type][$package->getName()])
7296 || !is_object($packages[$type][$package->getName()])
7297 || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
7298 ) {
7299 if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
7300 if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
7301 $packages[$type][$package->getName()] = $package;
7302 }
7303 }
7304 }
7305 }
7306 }
7307 }
7308
7309 $showAllTypes = $input->getOption('all');
7310 $showLatest = $input->getOption('latest');
7311 $showMinorOnly = $input->getOption('minor-only');
7312 $indent = $showAllTypes ? '  ' : '';
7313 $latestPackages = array();
7314 $exitCode = 0;
7315 $viewData = array();
7316 $viewMetaData = array();
7317 foreach (array('platform' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
7318 if (isset($packages[$type])) {
7319 ksort($packages[$type]);
7320
7321 $nameLength = $versionLength = $latestLength = 0;
7322
7323 if ($showLatest && $showVersion) {
7324 foreach ($packages[$type] as $package) {
7325 if (is_object($package)) {
7326 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion, $showMinorOnly);
7327 if ($latestPackage === false) {
7328 continue;
7329 }
7330
7331 $latestPackages[$package->getPrettyName()] = $latestPackage;
7332 }
7333 }
7334 }
7335
7336 $writePath = !$input->getOption('name-only') && $input->getOption('path');
7337 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
7338 $writeLatest = $writeVersion && $showLatest;
7339 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
7340
7341 $hasOutdatedPackages = false;
7342
7343 $viewData[$type] = array();
7344 foreach ($packages[$type] as $package) {
7345 $packageViewData = array();
7346 if (is_object($package)) {
7347 $latestPackage = null;
7348 if ($showLatest && isset($latestPackages[$package->getPrettyName()])) {
7349 $latestPackage = $latestPackages[$package->getPrettyName()];
7350 }
7351 if ($input->getOption('outdated') && $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
7352 continue;
7353 } elseif ($input->getOption('outdated') || $input->getOption('strict')) {
7354 $hasOutdatedPackages = true;
7355 }
7356
7357 $packageViewData['name'] = $package->getPrettyName();
7358 $nameLength = max($nameLength, strlen($package->getPrettyName()));
7359 if ($writeVersion) {
7360 $packageViewData['version'] = $package->getFullPrettyVersion();
7361 $versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
7362 }
7363 if ($writeLatest && $latestPackage) {
7364 $packageViewData['latest'] = $latestPackage->getFullPrettyVersion();
7365 $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
7366 $latestLength = max($latestLength, strlen($latestPackage->getFullPrettyVersion()));
7367 }
7368 if ($writeDescription) {
7369 $packageViewData['description'] = $package->getDescription();
7370 }
7371 if ($writePath) {
7372 $packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
7373 }
7374
7375 if ($latestPackage && $latestPackage->isAbandoned()) {
7376 $replacement = is_string($latestPackage->getReplacementPackage())
7377 ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead'
7378 : 'No replacement was suggested';
7379 $packageWarning = sprintf(
7380 'Package %s is abandoned, you should avoid using it. %s.',
7381 $package->getPrettyName(),
7382 $replacement
7383 );
7384 $packageViewData['warning'] = $packageWarning;
7385 }
7386 } else {
7387 $packageViewData['name'] = $package;
7388 $nameLength = max($nameLength, strlen($package));
7389 }
7390 $viewData[$type][] = $packageViewData;
7391 }
7392 $viewMetaData[$type] = array(
7393 'nameLength' => $nameLength,
7394 'versionLength' => $versionLength,
7395 'latestLength' => $latestLength,
7396 );
7397 if ($input->getOption('strict') && $hasOutdatedPackages) {
7398 $exitCode = 1;
7399 break;
7400 }
7401 }
7402 }
7403
7404 if ('json' === $format) {
7405 $io->write(JsonFile::encode($viewData));
7406 } else {
7407 foreach ($viewData as $type => $packages) {
7408 $nameLength = $viewMetaData[$type]['nameLength'];
7409 $versionLength = $viewMetaData[$type]['versionLength'];
7410 $latestLength = $viewMetaData[$type]['latestLength'];
7411
7412 $writeVersion = $nameLength + $versionLength + 3 <= $width;
7413 $writeLatest = $nameLength + $versionLength + $latestLength + 3 <= $width;
7414 $writeDescription = $nameLength + $versionLength + $latestLength + 24 <= $width;
7415
7416 if ($writeLatest && !$io->isDecorated()) {
7417 $latestLength += 2;
7418 }
7419
7420 if ($showAllTypes) {
7421 if ('available' === $type) {
7422 $io->write('<comment>' . $type . '</comment>:');
7423 } else {
7424 $io->write('<info>' . $type . '</info>:');
7425 }
7426 }
7427
7428 foreach ($packages as $package) {
7429 $io->write($indent . str_pad($package['name'], $nameLength, ' '), false);
7430 if (isset($package['version']) && $writeVersion) {
7431 $io->write(' ' . str_pad($package['version'], $versionLength, ' '), false);
7432 }
7433 if (isset($package['latest']) && $writeLatest) {
7434 $latestVersion = $package['latest'];
7435 $updateStatus = $package['latest-status'];
7436 $style = $this->updateStatusToVersionStyle($updateStatus);
7437 if (!$io->isDecorated()) {
7438 $latestVersion = str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('=', '!', '~'), $updateStatus) . ' ' . $latestVersion;
7439 }
7440 $io->write(' <' . $style . '>' . str_pad($latestVersion, $latestLength, ' ') . '</' . $style . '>', false);
7441 }
7442 if (isset($package['description']) && $writeDescription) {
7443 $description = strtok($package['description'], "\r\n");
7444 $remaining = $width - $nameLength - $versionLength - 4;
7445 if ($writeLatest) {
7446 $remaining -= $latestLength;
7447 }
7448 if (strlen($description) > $remaining) {
7449 $description = substr($description, 0, $remaining - 3) . '...';
7450 }
7451 $io->write(' ' . $description, false);
7452 }
7453 if (isset($package['path'])) {
7454 $io->write(' ' . $package['path'], false);
7455 }
7456 $io->write('');
7457 if (isset($package['warning'])) {
7458 $io->writeError('<warning>' . $package['warning'] . '</warning>');
7459 }
7460 }
7461
7462 if ($showAllTypes) {
7463 $io->write('');
7464 }
7465 }
7466 }
7467
7468 return $exitCode;
7469 }
7470
7471 protected function getRootRequires()
7472 {
7473 $rootPackage = $this->getComposer()->getPackage();
7474
7475 return array_map(
7476 'strtolower',
7477 array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))
7478 );
7479 }
7480
7481 protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package)
7482 {
7483 return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package));
7484 }
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496 protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
7497 {
7498 $name = strtolower($name);
7499 $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
7500
7501 $policy = new DefaultPolicy();
7502 $pool = new Pool('dev');
7503 $pool->addRepository($repos);
7504
7505 $matchedPackage = null;
7506 $versions = array();
7507 $matches = $pool->whatProvides($name, $constraint);
7508 foreach ($matches as $index => $package) {
7509
7510  if ($package->getName() !== $name) {
7511 unset($matches[$index]);
7512 continue;
7513 }
7514
7515
7516  if (null === $version && $installedRepo->hasPackage($package)) {
7517 $matchedPackage = $package;
7518 }
7519
7520 $versions[$package->getPrettyVersion()] = $package->getVersion();
7521 $matches[$index] = $package->getId();
7522 }
7523
7524
7525  if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
7526 $matchedPackage = $pool->literalToPackage($preferred[0]);
7527 }
7528
7529 return array($matchedPackage, $versions);
7530 }
7531
7532
7533
7534
7535
7536
7537
7538
7539 protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
7540 {
7541 $io = $this->getIO();
7542 $io->write('<info>name</info>     : ' . $package->getPrettyName());
7543 $io->write('<info>descrip.</info> : ' . $package->getDescription());
7544 $io->write('<info>keywords</info> : ' . implode(', ', $package->getKeywords() ?: array()));
7545 $this->printVersions($package, $versions, $installedRepo);
7546 if ($latestPackage) {
7547 $style = $this->getVersionStyle($latestPackage, $package);
7548 $io->write('<info>latest</info>   : <'.$style.'>' . $latestPackage->getPrettyVersion() . '</'.$style.'>');
7549 } else {
7550 $latestPackage = $package;
7551 }
7552 $io->write('<info>type</info>     : ' . $package->getType());
7553 $this->printLicenses($package);
7554 $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
7555 $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
7556 $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
7557
7558 if ($latestPackage->isAbandoned()) {
7559 $replacement = ($latestPackage->getReplacementPackage() !== null)
7560 ? ' The author suggests using the ' . $latestPackage->getReplacementPackage(). ' package instead.'
7561 : null;
7562
7563 $io->writeError(
7564 sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
7565 );
7566 }
7567
7568 if ($package->getSupport()) {
7569 $io->write("\n<info>support</info>");
7570 foreach ($package->getSupport() as $type => $value) {
7571 $io->write('<comment>' . $type . '</comment> : '.$value);
7572 }
7573 }
7574
7575 if ($package->getAutoload()) {
7576 $io->write("\n<info>autoload</info>");
7577 foreach ($package->getAutoload() as $type => $autoloads) {
7578 $io->write('<comment>' . $type . '</comment>');
7579
7580 if ($type === 'psr-0') {
7581 foreach ($autoloads as $name => $path) {
7582 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7583 }
7584 } elseif ($type === 'psr-4') {
7585 foreach ($autoloads as $name => $path) {
7586 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7587 }
7588 } elseif ($type === 'classmap') {
7589 $io->write(implode(', ', $autoloads));
7590 }
7591 }
7592 if ($package->getIncludePaths()) {
7593 $io->write('<comment>include-path</comment>');
7594 $io->write(implode(', ', $package->getIncludePaths()));
7595 }
7596 }
7597 }
7598
7599
7600
7601
7602
7603
7604
7605
7606 protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
7607 {
7608 uasort($versions, 'version_compare');
7609 $versions = array_keys(array_reverse($versions));
7610
7611
7612  if ($installedRepo->hasPackage($package)) {
7613 $installedVersion = $package->getPrettyVersion();
7614 $key = array_search($installedVersion, $versions);
7615 if (false !== $key) {
7616 $versions[$key] = '<info>* ' . $installedVersion . '</info>';
7617 }
7618 }
7619
7620 $versions = implode(', ', $versions);
7621
7622 $this->getIO()->write('<info>versions</info> : ' . $versions);
7623 }
7624
7625
7626
7627
7628
7629
7630
7631
7632 protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
7633 {
7634 $title = $title ?: $linkType;
7635 $io = $this->getIO();
7636 if ($links = $package->{'get'.ucfirst($linkType)}()) {
7637 $io->write("\n<info>" . $title . "</info>");
7638
7639 foreach ($links as $link) {
7640 $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
7641 }
7642 }
7643 }
7644
7645
7646
7647
7648
7649
7650 protected function printLicenses(CompletePackageInterface $package)
7651 {
7652 $spdxLicenses = new SpdxLicenses();
7653
7654 $licenses = $package->getLicense();
7655 $io = $this->getIO();
7656
7657 foreach ($licenses as $licenseId) {
7658 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
7659
7660 if (!$license) {
7661 $out = $licenseId;
7662 } else {
7663
7664  if ($license[1] === true) {
7665 $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
7666 } else {
7667 $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
7668 }
7669 }
7670
7671 $io->write('<info>license</info>  : ' . $out);
7672 }
7673 }
7674
7675
7676
7677
7678
7679
7680 protected function initStyles(OutputInterface $output)
7681 {
7682 $this->colors = array(
7683 'green',
7684 'yellow',
7685 'cyan',
7686 'magenta',
7687 'blue',
7688 );
7689
7690 foreach ($this->colors as $color) {
7691 $style = new OutputFormatterStyle($color);
7692 $output->getFormatter()->setStyle($color, $style);
7693 }
7694 }
7695
7696
7697
7698
7699
7700
7701 protected function displayPackageTree(array $arrayTree)
7702 {
7703 $io = $this->getIO();
7704 foreach ($arrayTree as $package) {
7705 $io->write(sprintf('<info>%s</info>', $package['name']), false);
7706 $io->write(' ' . $package['version'], false);
7707 $io->write(' ' . strtok($package['description'], "\r\n"));
7708
7709 if (isset($package['requires'])) {
7710 $requires = $package['requires'];
7711 $treeBar = '├';
7712 $j = 0;
7713 $total = count($requires);
7714 foreach ($requires as $require) {
7715 $requireName = $require['name'];
7716 $j++;
7717 if ($j === $total) {
7718 $treeBar = '└';
7719 }
7720 $level = 1;
7721 $color = $this->colors[$level];
7722 $info = sprintf(
7723 '%s──<%s>%s</%s> %s',
7724 $treeBar,
7725 $color,
7726 $requireName,
7727 $color,
7728 $require['version']
7729 );
7730 $this->writeTreeLine($info);
7731
7732 $treeBar = str_replace('└', ' ', $treeBar);
7733 $packagesInTree = array($package['name'], $requireName);
7734
7735 $this->displayTree($require, $packagesInTree, $treeBar, $level + 1);
7736 }
7737 }
7738 }
7739 }
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749 protected function generatePackageTree(
7750 PackageInterface $package,
7751 RepositoryInterface $installedRepo,
7752 RepositoryInterface $distantRepos
7753 ) {
7754 if (is_object($package)) {
7755 $requires = $package->getRequires();
7756 ksort($requires);
7757 $children = array();
7758 foreach ($requires as $requireName => $require) {
7759 $packagesInTree = array($package->getName(), $requireName);
7760
7761 $treeChildDesc = array(
7762 'name' => $requireName,
7763 'version' => $require->getPrettyConstraint(),
7764 );
7765
7766 $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree);
7767
7768 if ($deepChildren) {
7769 $treeChildDesc['requires'] = $deepChildren;
7770 }
7771
7772 $children[] = $treeChildDesc;
7773 }
7774 $tree = array(
7775 'name' => $package->getPrettyName(),
7776 'version' => $package->getPrettyVersion(),
7777 'description' => $package->getDescription(),
7778 );
7779
7780 if ($children) {
7781 $tree['requires'] = $children;
7782 }
7783
7784 return $tree;
7785 }
7786 }
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796 protected function displayTree(
7797 $package,
7798 array $packagesInTree,
7799 $previousTreeBar = '├',
7800 $level = 1
7801 ) {
7802 $previousTreeBar = str_replace('├', '│', $previousTreeBar);
7803 if (isset($package['requires'])) {
7804 $requires = $package['requires'];
7805 $treeBar = $previousTreeBar . '  ├';
7806 $i = 0;
7807 $total = count($requires);
7808 foreach ($requires as $require) {
7809 $currentTree = $packagesInTree;
7810 $i++;
7811 if ($i === $total) {
7812 $treeBar = $previousTreeBar . '  └';
7813 }
7814 $colorIdent = $level % count($this->colors);
7815 $color = $this->colors[$colorIdent];
7816
7817 $circularWarn = in_array(
7818 $require['name'],
7819 $currentTree,
7820 true
7821 ) ? '(circular dependency aborted here)' : '';
7822 $info = rtrim(sprintf(
7823 '%s──<%s>%s</%s> %s %s',
7824 $treeBar,
7825 $color,
7826 $require['name'],
7827 $color,
7828 $require['version'],
7829 $circularWarn
7830 ));
7831 $this->writeTreeLine($info);
7832
7833 $treeBar = str_replace('└', ' ', $treeBar);
7834
7835 $currentTree[] = $require['name'];
7836 $this->displayTree($require, $currentTree, $treeBar, $level + 1);
7837 }
7838 }
7839 }
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851 protected function addTree(
7852 $name,
7853 $package,
7854 RepositoryInterface $installedRepo,
7855 RepositoryInterface $distantRepos,
7856 array $packagesInTree
7857 ) {
7858 $children = array();
7859 list($package, $versions) = $this->getPackage(
7860 $installedRepo,
7861 $distantRepos,
7862 $name,
7863 $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint()
7864 );
7865 if (is_object($package)) {
7866 $requires = $package->getRequires();
7867 ksort($requires);
7868 foreach ($requires as $requireName => $require) {
7869 $currentTree = $packagesInTree;
7870
7871 $treeChildDesc = array(
7872 'name' => $requireName,
7873 'version' => $require->getPrettyConstraint(),
7874 );
7875
7876 if (!in_array($requireName, $currentTree, true)) {
7877 $currentTree[] = $requireName;
7878 $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $currentTree);
7879 if ($deepChildren) {
7880 $treeChildDesc['requires'] = $deepChildren;
7881 }
7882 }
7883
7884 $children[] = $treeChildDesc;
7885 }
7886 }
7887
7888 return $children;
7889 }
7890
7891 private function updateStatusToVersionStyle($updateStatus)
7892 {
7893
7894  
7895  
7896  return str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('info', 'highlight', 'comment'), $updateStatus);
7897 }
7898
7899 private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package)
7900 {
7901 if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) {
7902 return 'up-to-date';
7903 }
7904
7905 $constraint = $package->getVersion();
7906 if (0 !== strpos($constraint, 'dev-')) {
7907 $constraint = '^'.$constraint;
7908 }
7909 if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) {
7910
7911  return 'semver-safe-update';
7912 }
7913
7914
7915  return 'update-possible';
7916 }
7917
7918 private function writeTreeLine($line)
7919 {
7920 $io = $this->getIO();
7921 if (!$io->isDecorated()) {
7922 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
7923 }
7924
7925 $io->write($line);
7926 }
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938 private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
7939 {
7940
7941  $name = $package->getName();
7942 $versionSelector = new VersionSelector($this->getPool($composer));
7943 $stability = $composer->getPackage()->getMinimumStability();
7944 $flags = $composer->getPackage()->getStabilityFlags();
7945 if (isset($flags[$name])) {
7946 $stability = array_search($flags[$name], BasePackage::$stabilities, true);
7947 }
7948
7949 $bestStability = $stability;
7950 if ($composer->getPackage()->getPreferStable()) {
7951 $bestStability = $package->getStability();
7952 }
7953
7954 $targetVersion = null;
7955 if (0 === strpos($package->getVersion(), 'dev-')) {
7956 $targetVersion = $package->getVersion();
7957 }
7958
7959 if ($targetVersion === null && $minorOnly) {
7960 $targetVersion = '^' . $package->getVersion();
7961 }
7962
7963 return $versionSelector->findBestCandidate($name, $targetVersion, $phpVersion, $bestStability);
7964 }
7965
7966 private function getPool(Composer $composer)
7967 {
7968 if (!$this->pool) {
7969 $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
7970 $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
7971 }
7972
7973 return $this->pool;
7974 }
7975 }
7976 <?php
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988 namespace Composer\Command;
7989
7990 use Symfony\Component\Console\Input\InputInterface;
7991 use Symfony\Component\Console\Input\InputOption;
7992 use Symfony\Component\Console\Output\OutputInterface;
7993 use Composer\Downloader\ChangeReportInterface;
7994 use Composer\Downloader\DvcsDownloaderInterface;
7995 use Composer\Downloader\VcsCapableDownloaderInterface;
7996 use Composer\Package\Dumper\ArrayDumper;
7997 use Composer\Package\Version\VersionGuesser;
7998 use Composer\Package\Version\VersionParser;
7999 use Composer\Plugin\CommandEvent;
8000 use Composer\Plugin\PluginEvents;
8001 use Composer\Script\ScriptEvents;
8002 use Composer\Util\ProcessExecutor;
8003
8004
8005
8006
8007
8008 class StatusCommand extends BaseCommand
8009 {
8010 const EXIT_CODE_ERRORS = 1;
8011 const EXIT_CODE_UNPUSHED_CHANGES = 2;
8012 const EXIT_CODE_VERSION_CHANGES = 4;
8013
8014
8015
8016
8017 protected function configure()
8018 {
8019 $this
8020 ->setName('status')
8021 ->setDescription('Shows a list of locally modified packages, for packages installed from source.')
8022 ->setDefinition(array(
8023 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
8024 ))
8025 ->setHelp(
8026 <<<EOT
8027 The status command displays a list of dependencies that have
8028 been modified locally.
8029
8030 EOT
8031 )
8032 ;
8033 }
8034
8035
8036
8037
8038
8039
8040 protected function execute(InputInterface $input, OutputInterface $output)
8041 {
8042
8043  $composer = $this->getComposer();
8044
8045 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
8046 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8047
8048 $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
8049
8050 $dm = $composer->getDownloadManager();
8051 $im = $composer->getInstallationManager();
8052
8053
8054  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
8055
8056 $errors = array();
8057 $io = $this->getIO();
8058 $unpushedChanges = array();
8059 $vcsVersionChanges = array();
8060
8061 $parser = new VersionParser;
8062 $guesser = new VersionGuesser($composer->getConfig(), new ProcessExecutor($io), $parser);
8063 $dumper = new ArrayDumper;
8064
8065
8066  foreach ($installedRepo->getCanonicalPackages() as $package) {
8067 $downloader = $dm->getDownloaderForInstalledPackage($package);
8068 $targetDir = $im->getInstallPath($package);
8069
8070 if ($downloader instanceof ChangeReportInterface) {
8071 if (is_link($targetDir)) {
8072 $errors[$targetDir] = $targetDir . ' is a symbolic link.';
8073 }
8074
8075 if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
8076 $errors[$targetDir] = $changes;
8077 }
8078 }
8079
8080 if ($downloader instanceof VcsCapableDownloaderInterface) {
8081 if ($currentRef = $downloader->getVcsReference($package, $targetDir)) {
8082 switch ($package->getInstallationSource()) {
8083 case 'source':
8084 $previousRef = $package->getSourceReference();
8085 break;
8086 case 'dist':
8087 $previousRef = $package->getDistReference();
8088 break;
8089 default:
8090 $previousRef = null;
8091 }
8092
8093 $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir);
8094
8095 if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef) {
8096 $vcsVersionChanges[$targetDir] = array(
8097 'previous' => array(
8098 'version' => $package->getPrettyVersion(),
8099 'ref' => $previousRef,
8100 ),
8101 'current' => array(
8102 'version' => $currentVersion['pretty_version'],
8103 'ref' => $currentVersion['commit'],
8104 ),
8105 );
8106 }
8107 }
8108 }
8109
8110 if ($downloader instanceof DvcsDownloaderInterface) {
8111 if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
8112 $unpushedChanges[$targetDir] = $unpushed;
8113 }
8114 }
8115 }
8116
8117
8118  if (!$errors && !$unpushedChanges && !$vcsVersionChanges) {
8119 $io->writeError('<info>No local changes</info>');
8120
8121 return 0;
8122 }
8123
8124 if ($errors) {
8125 $io->writeError('<error>You have changes in the following dependencies:</error>');
8126
8127 foreach ($errors as $path => $changes) {
8128 if ($input->getOption('verbose')) {
8129 $indentedChanges = implode("\n", array_map(function ($line) {
8130 return '    ' . ltrim($line);
8131 }, explode("\n", $changes)));
8132 $io->write('<info>'.$path.'</info>:');
8133 $io->write($indentedChanges);
8134 } else {
8135 $io->write($path);
8136 }
8137 }
8138 }
8139
8140 if ($unpushedChanges) {
8141 $io->writeError('<warning>You have unpushed changes on the current branch in the following dependencies:</warning>');
8142
8143 foreach ($unpushedChanges as $path => $changes) {
8144 if ($input->getOption('verbose')) {
8145 $indentedChanges = implode("\n", array_map(function ($line) {
8146 return '    ' . ltrim($line);
8147 }, explode("\n", $changes)));
8148 $io->write('<info>'.$path.'</info>:');
8149 $io->write($indentedChanges);
8150 } else {
8151 $io->write($path);
8152 }
8153 }
8154 }
8155
8156 if ($vcsVersionChanges) {
8157 $io->writeError('<warning>You have version variations in the following dependencies:</warning>');
8158
8159 foreach ($vcsVersionChanges as $path => $changes) {
8160 if ($input->getOption('verbose')) {
8161
8162  $currentVersion = $changes['current']['version'] ?: $changes['current']['ref'];
8163 $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref'];
8164
8165 if ($io->isVeryVerbose()) {
8166
8167  $currentVersion .= sprintf(' (%s)', $changes['current']['ref']);
8168 $previousVersion .= sprintf(' (%s)', $changes['previous']['ref']);
8169 }
8170
8171 $io->write('<info>'.$path.'</info>:');
8172 $io->write(sprintf('    From <comment>%s</comment> to <comment>%s</comment>', $previousVersion, $currentVersion));
8173 } else {
8174 $io->write($path);
8175 }
8176 }
8177 }
8178
8179 if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) {
8180 $io->writeError('Use --verbose (-v) to see a list of files');
8181 }
8182
8183
8184  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
8185
8186 return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0);
8187 }
8188 }
8189 <?php
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201 namespace Composer\Command;
8202
8203 use Composer\Repository\PlatformRepository;
8204 use Symfony\Component\Console\Input\InputArgument;
8205 use Symfony\Component\Console\Input\InputInterface;
8206 use Symfony\Component\Console\Input\InputOption;
8207 use Symfony\Component\Console\Output\OutputInterface;
8208
8209 class SuggestsCommand extends BaseCommand
8210 {
8211 protected function configure()
8212 {
8213 $this
8214 ->setName('suggests')
8215 ->setDescription('Shows package suggestions.')
8216 ->setDefinition(array(
8217 new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package'),
8218 new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'),
8219 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
8220 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
8221 ))
8222 ->setHelp(
8223 <<<EOT
8224
8225 The <info>%command.name%</info> command shows a sorted list of suggested packages.
8226
8227 Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
8228
8229 EOT
8230 )
8231 ;
8232 }
8233
8234 protected function execute(InputInterface $input, OutputInterface $output)
8235 {
8236 $lock = $this->getComposer()->getLocker()->getLockData();
8237
8238 if (empty($lock)) {
8239 throw new \RuntimeException('Lockfile seems to be empty?');
8240 }
8241
8242 $packages = $lock['packages'];
8243
8244 if (!$input->getOption('no-dev')) {
8245 $packages += $lock['packages-dev'];
8246 }
8247
8248 $filter = $input->getArgument('packages');
8249
8250
8251  $installed = array();
8252 foreach ($packages as $package) {
8253 $installed[] = $package['name'];
8254
8255 if (!empty($package['provide'])) {
8256 $installed = array_merge($installed, array_keys($package['provide']));
8257 }
8258
8259 if (!empty($package['replace'])) {
8260 $installed = array_merge($installed, array_keys($package['replace']));
8261 }
8262 }
8263
8264
8265  $installed = array_flip($installed);
8266 ksort($installed);
8267
8268
8269  $platform = new PlatformRepository(array(), $this->getComposer()->getConfig()->get('platform') ?: array());
8270
8271
8272  $suggesters = array();
8273 $suggested = array();
8274 foreach ($packages as $package) {
8275 $packageName = $package['name'];
8276 if ((!empty($filter) && !in_array($packageName, $filter)) || empty($package['suggest'])) {
8277 continue;
8278 }
8279 foreach ($package['suggest'] as $suggestion => $reason) {
8280 if (false === strpos('/', $suggestion) && null !== $platform->findPackage($suggestion, '*')) {
8281 continue;
8282 }
8283 if (!isset($installed[$suggestion])) {
8284 $suggesters[$packageName][$suggestion] = $reason;
8285 $suggested[$suggestion][$packageName] = $reason;
8286 }
8287 }
8288 }
8289 ksort($suggesters);
8290 ksort($suggested);
8291
8292
8293  $mode = 0;
8294 $io = $this->getIO();
8295 if ($input->getOption('by-package') || $io->isVerbose()) {
8296 $mode |= 1;
8297 }
8298 if ($input->getOption('by-suggestion')) {
8299 $mode |= 2;
8300 }
8301
8302
8303  if ($mode === 0) {
8304 foreach (array_keys($suggested) as $suggestion) {
8305 $io->write(sprintf('<info>%s</info>', $suggestion));
8306 }
8307
8308 return;
8309 }
8310
8311
8312  if ($mode & 1) {
8313 foreach ($suggesters as $suggester => $suggestions) {
8314 $io->write(sprintf('<comment>%s</comment> suggests:', $suggester));
8315
8316 foreach ($suggestions as $suggestion => $reason) {
8317 $io->write(sprintf(' - <info>%s</info>: %s', $suggestion, $reason ?: '*'));
8318 }
8319 $io->write('');
8320 }
8321 }
8322
8323
8324  if ($mode & 2) {
8325
8326  if ($mode & 1) {
8327 $io->write(str_repeat('-', 78));
8328 }
8329 foreach ($suggested as $suggestion => $suggesters) {
8330 $io->write(sprintf('<comment>%s</comment> is suggested by:', $suggestion));
8331
8332 foreach ($suggesters as $suggester => $reason) {
8333 $io->write(sprintf(' - <info>%s</info>: %s', $suggester, $reason ?: '*'));
8334 }
8335 $io->write('');
8336 }
8337 }
8338 }
8339 }
8340 <?php
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352 namespace Composer\Command;
8353
8354 use Composer\Composer;
8355 use Composer\Installer;
8356 use Composer\IO\IOInterface;
8357 use Composer\Plugin\CommandEvent;
8358 use Composer\Plugin\PluginEvents;
8359 use Symfony\Component\Console\Helper\Table;
8360 use Symfony\Component\Console\Input\InputInterface;
8361 use Symfony\Component\Console\Input\InputOption;
8362 use Symfony\Component\Console\Input\InputArgument;
8363 use Symfony\Component\Console\Output\OutputInterface;
8364 use Symfony\Component\Console\Question\Question;
8365
8366
8367
8368
8369
8370 class UpdateCommand extends BaseCommand
8371 {
8372 protected function configure()
8373 {
8374 $this
8375 ->setName('update')
8376 ->setAliases(array('u', 'upgrade'))
8377 ->setDescription('Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
8378 ->setDefinition(array(
8379 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
8380 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
8381 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
8382 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
8383 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
8384 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
8385 new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
8386 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
8387 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
8388 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
8389 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
8390 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
8391 new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also dependencies of whitelisted packages to the whitelist, except those defined in root package.'),
8392 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.'),
8393 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
8394 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
8395 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
8396 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
8397 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
8398 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
8399 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
8400 new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
8401 new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
8402 ))
8403 ->setHelp(
8404 <<<EOT
8405 The <info>update</info> command reads the composer.json file from the
8406 current directory, processes it, and updates, removes or installs all the
8407 dependencies.
8408
8409 <info>php composer.phar update</info>
8410
8411 To limit the update operation to a few packages, you can list the package(s)
8412 you want to update as such:
8413
8414 <info>php composer.phar update vendor/package1 foo/mypackage [...]</info>
8415
8416 You may also use an asterisk (*) pattern to limit the update operation to package(s)
8417 from a specific vendor:
8418
8419 <info>php composer.phar update vendor/package1 foo/* [...]</info>
8420
8421 To select packages names interactively with auto-completion use <info>-i</info>.
8422
8423 EOT
8424 )
8425 ;
8426 }
8427
8428 protected function execute(InputInterface $input, OutputInterface $output)
8429 {
8430 $io = $this->getIO();
8431 if ($input->getOption('no-custom-installers')) {
8432 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
8433 $input->setOption('no-plugins', true);
8434 }
8435
8436 if ($input->getOption('dev')) {
8437 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
8438 }
8439
8440 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
8441
8442 $packages = $input->getArgument('packages');
8443
8444 if ($input->getOption('interactive')) {
8445 $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
8446 }
8447
8448 if ($input->getOption('root-reqs')) {
8449 $require = array_keys($composer->getPackage()->getRequires());
8450 if (!$input->getOption('no-dev')) {
8451 $requireDev = array_keys($composer->getPackage()->getDevRequires());
8452 $require = array_merge($require, $requireDev);
8453 }
8454
8455 if (!empty($packages)) {
8456 $packages = array_intersect($packages, $require);
8457 } else {
8458 $packages = $require;
8459 }
8460 }
8461
8462 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
8463
8464 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
8465 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8466
8467 $install = Installer::create($io, $composer);
8468
8469 $config = $composer->getConfig();
8470 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
8471
8472 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
8473 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
8474 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
8475
8476 $install
8477 ->setDryRun($input->getOption('dry-run'))
8478 ->setVerbose($input->getOption('verbose'))
8479 ->setPreferSource($preferSource)
8480 ->setPreferDist($preferDist)
8481 ->setDevMode(!$input->getOption('no-dev'))
8482 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
8483 ->setRunScripts(!$input->getOption('no-scripts'))
8484 ->setSkipSuggest($input->getOption('no-suggest'))
8485 ->setOptimizeAutoloader($optimize)
8486 ->setClassMapAuthoritative($authoritative)
8487 ->setApcuAutoloader($apcu)
8488 ->setUpdate(true)
8489 ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages)
8490 ->setWhitelistTransitiveDependencies($input->getOption('with-dependencies'))
8491 ->setWhitelistAllDependencies($input->getOption('with-all-dependencies'))
8492 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
8493 ->setPreferStable($input->getOption('prefer-stable'))
8494 ->setPreferLowest($input->getOption('prefer-lowest'))
8495 ;
8496
8497 if ($input->getOption('no-plugins')) {
8498 $install->disablePlugins();
8499 }
8500
8501 return $install->run();
8502 }
8503
8504 private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages)
8505 {
8506 if (!$input->isInteractive()) {
8507 throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
8508 }
8509
8510 $requires = array_merge(
8511 $composer->getPackage()->getRequires(),
8512 $composer->getPackage()->getDevRequires()
8513 );
8514 $autocompleterValues = array();
8515 foreach ($requires as $require) {
8516 $target = $require->getTarget();
8517 $autocompleterValues[strtolower($target)] = $target;
8518 }
8519
8520 $installedPackages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
8521 foreach ($installedPackages as $package) {
8522 $autocompleterValues[$package->getName()] = $package->getPrettyName();
8523 }
8524
8525 $helper = $this->getHelper('question');
8526 $question = new Question('<comment>Enter package name: </comment>', null);
8527
8528 $io->writeError('<info>Press enter without value to end submission</info>');
8529
8530 do {
8531 $autocompleterValues = array_diff($autocompleterValues, $packages);
8532 $question->setAutocompleterValues($autocompleterValues);
8533 $addedPackage = $helper->ask($input, $output, $question);
8534
8535 if (!is_string($addedPackage) || empty($addedPackage)) {
8536 break;
8537 }
8538
8539 $addedPackage = strtolower($addedPackage);
8540 if (!in_array($addedPackage, $packages)) {
8541 $packages[] = $addedPackage;
8542 }
8543 } while (true);
8544
8545 $packages = array_filter($packages);
8546 if (!$packages) {
8547 throw new \InvalidArgumentException('You must enter minimum one package.');
8548 }
8549
8550 $table = new Table($output);
8551 $table->setHeaders(array('Selected packages'));
8552 foreach ($packages as $package) {
8553 $table->addRow(array($package));
8554 }
8555 $table->render();
8556
8557 if ($io->askConfirmation(sprintf(
8558 'Would you like to continue and update the above package%s [<comment>yes</comment>]? ',
8559 1 === count($packages) ? '' : 's'
8560 ), true)) {
8561 return $packages;
8562 }
8563
8564 throw new \RuntimeException('Installation aborted.');
8565 }
8566 }
8567 <?php
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579 namespace Composer\Command;
8580
8581 use Composer\Factory;
8582 use Composer\Package\Loader\ValidatingArrayLoader;
8583 use Composer\Plugin\CommandEvent;
8584 use Composer\Plugin\PluginEvents;
8585 use Composer\Util\ConfigValidator;
8586 use Symfony\Component\Console\Input\InputArgument;
8587 use Symfony\Component\Console\Input\InputInterface;
8588 use Symfony\Component\Console\Input\InputOption;
8589 use Symfony\Component\Console\Output\OutputInterface;
8590
8591
8592
8593
8594
8595
8596
8597 class ValidateCommand extends BaseCommand
8598 {
8599
8600
8601
8602 protected function configure()
8603 {
8604 $this
8605 ->setName('validate')
8606 ->setDescription('Validates a composer.json and composer.lock.')
8607 ->setDefinition(array(
8608 new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'),
8609 new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
8610 new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
8611 new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
8612 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
8613 new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file'),
8614 ))
8615 ->setHelp(
8616 <<<EOT
8617 The validate command validates a given composer.json and composer.lock
8618
8619 Exit codes in case of errors are:
8620 1 validation warning(s), only when --strict is given
8621 2 validation error(s)
8622 3 file unreadable or missing
8623
8624 EOT
8625 );
8626 }
8627
8628
8629
8630
8631
8632
8633
8634 protected function execute(InputInterface $input, OutputInterface $output)
8635 {
8636 $file = $input->getArgument('file') ?: Factory::getComposerFile();
8637 $io = $this->getIO();
8638
8639 if (!file_exists($file)) {
8640 $io->writeError('<error>' . $file . ' not found.</error>');
8641
8642 return 3;
8643 }
8644 if (!is_readable($file)) {
8645 $io->writeError('<error>' . $file . ' is not readable.</error>');
8646
8647 return 3;
8648 }
8649
8650 $validator = new ConfigValidator($io);
8651 $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
8652 $checkPublish = !$input->getOption('no-check-publish');
8653 $checkLock = !$input->getOption('no-check-lock');
8654 $isStrict = $input->getOption('strict');
8655 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8656
8657 $lockErrors = array();
8658 $composer = Factory::create($io, $file, $input->hasParameterOption('--no-plugins'));
8659 $locker = $composer->getLocker();
8660 if ($locker->isLocked() && !$locker->isFresh()) {
8661 $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update`.';
8662 }
8663
8664 $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true);
8665
8666 $exitCode = $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 2 : ($isStrict && $warnings ? 1 : 0);
8667
8668 if ($input->getOption('with-dependencies')) {
8669 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
8670 foreach ($localRepo->getPackages() as $package) {
8671 $path = $composer->getInstallationManager()->getInstallPath($package);
8672 $file = $path . '/composer.json';
8673 if (is_dir($path) && file_exists($file)) {
8674 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8675 $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
8676
8677 $depCode = $errors || ($publishErrors && $checkPublish) ? 2 : ($isStrict && $warnings ? 1 : 0);
8678 $exitCode = max($depCode, $exitCode);
8679 }
8680 }
8681 }
8682
8683 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
8684 $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8685 $exitCode = max($eventCode, $exitCode);
8686
8687 return $exitCode;
8688 }
8689
8690 private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false)
8691 {
8692 if (!$errors && !$publishErrors && !$warnings) {
8693 $io->write('<info>' . $name . ' is valid</info>');
8694 } elseif (!$errors && !$publishErrors) {
8695 $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
8696 if ($printSchemaUrl) {
8697 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8698 }
8699 } elseif (!$errors) {
8700 $io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
8701 $io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
8702 if ($printSchemaUrl) {
8703 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8704 }
8705 } else {
8706 $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
8707 }
8708
8709
8710  if ($checkPublish) {
8711 $errors = array_merge($errors, $publishErrors);
8712 } else {
8713 $warnings = array_merge($warnings, $publishErrors);
8714 }
8715
8716
8717  if ($checkLock) {
8718 $errors = array_merge($errors, $lockErrors);
8719 } else {
8720 $warnings = array_merge($warnings, $lockErrors);
8721 }
8722
8723 $messages = array(
8724 'error' => $errors,
8725 'warning' => $warnings,
8726 );
8727
8728 foreach ($messages as $style => $msgs) {
8729 foreach ($msgs as $msg) {
8730 $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
8731 }
8732 }
8733 }
8734 }
8735 <?php
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747 namespace Composer;
8748
8749 use Composer\Package\RootPackageInterface;
8750 use Composer\Package\Locker;
8751 use Composer\Repository\RepositoryManager;
8752 use Composer\Installer\InstallationManager;
8753 use Composer\Plugin\PluginManager;
8754 use Composer\Downloader\DownloadManager;
8755 use Composer\EventDispatcher\EventDispatcher;
8756 use Composer\Autoload\AutoloadGenerator;
8757 use Composer\Package\Archiver\ArchiveManager;
8758
8759
8760
8761
8762
8763
8764 class Composer
8765 {
8766 const VERSION = '1.7.2';
8767 const BRANCH_ALIAS_VERSION = '';
8768 const RELEASE_DATE = '2018-08-16 16:57:12';
8769
8770
8771
8772
8773 private $package;
8774
8775
8776
8777
8778 private $locker;
8779
8780
8781
8782
8783 private $repositoryManager;
8784
8785
8786
8787
8788 private $downloadManager;
8789
8790
8791
8792
8793 private $installationManager;
8794
8795
8796
8797
8798 private $pluginManager;
8799
8800
8801
8802
8803 private $config;
8804
8805
8806
8807
8808 private $eventDispatcher;
8809
8810
8811
8812
8813 private $autoloadGenerator;
8814
8815
8816
8817
8818 private $archiveManager;
8819
8820
8821
8822
8823
8824 public function setPackage(RootPackageInterface $package)
8825 {
8826 $this->package = $package;
8827 }
8828
8829
8830
8831
8832 public function getPackage()
8833 {
8834 return $this->package;
8835 }
8836
8837
8838
8839
8840 public function setConfig(Config $config)
8841 {
8842 $this->config = $config;
8843 }
8844
8845
8846
8847
8848 public function getConfig()
8849 {
8850 return $this->config;
8851 }
8852
8853
8854
8855
8856 public function setLocker(Locker $locker)
8857 {
8858 $this->locker = $locker;
8859 }
8860
8861
8862
8863
8864 public function getLocker()
8865 {
8866 return $this->locker;
8867 }
8868
8869
8870
8871
8872 public function setRepositoryManager(RepositoryManager $manager)
8873 {
8874 $this->repositoryManager = $manager;
8875 }
8876
8877
8878
8879
8880 public function getRepositoryManager()
8881 {
8882 return $this->repositoryManager;
8883 }
8884
8885
8886
8887
8888 public function setDownloadManager(DownloadManager $manager)
8889 {
8890 $this->downloadManager = $manager;
8891 }
8892
8893
8894
8895
8896 public function getDownloadManager()
8897 {
8898 return $this->downloadManager;
8899 }
8900
8901
8902
8903
8904 public function setArchiveManager(ArchiveManager $manager)
8905 {
8906 $this->archiveManager = $manager;
8907 }
8908
8909
8910
8911
8912 public function getArchiveManager()
8913 {
8914 return $this->archiveManager;
8915 }
8916
8917
8918
8919
8920 public function setInstallationManager(InstallationManager $manager)
8921 {
8922 $this->installationManager = $manager;
8923 }
8924
8925
8926
8927
8928 public function getInstallationManager()
8929 {
8930 return $this->installationManager;
8931 }
8932
8933
8934
8935
8936 public function setPluginManager(PluginManager $manager)
8937 {
8938 $this->pluginManager = $manager;
8939 }
8940
8941
8942
8943
8944 public function getPluginManager()
8945 {
8946 return $this->pluginManager;
8947 }
8948
8949
8950
8951
8952 public function setEventDispatcher(EventDispatcher $eventDispatcher)
8953 {
8954 $this->eventDispatcher = $eventDispatcher;
8955 }
8956
8957
8958
8959
8960 public function getEventDispatcher()
8961 {
8962 return $this->eventDispatcher;
8963 }
8964
8965
8966
8967
8968 public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
8969 {
8970 $this->autoloadGenerator = $autoloadGenerator;
8971 }
8972
8973
8974
8975
8976 public function getAutoloadGenerator()
8977 {
8978 return $this->autoloadGenerator;
8979 }
8980 }
8981 <?php
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992
8993 namespace Composer;
8994
8995 use Composer\Config\ConfigSourceInterface;
8996 use Composer\Downloader\TransportException;
8997 use Composer\IO\IOInterface;
8998 use Composer\Util\Platform;
8999
9000
9001
9002
9003 class Config
9004 {
9005 const RELATIVE_PATHS = 1;
9006
9007 public static $defaultConfig = array(
9008 'process-timeout' => 300,
9009 'use-include-path' => false,
9010 'preferred-install' => 'auto',
9011 'notify-on-install' => true,
9012 'github-protocols' => array('https', 'ssh', 'git'),
9013 'vendor-dir' => 'vendor',
9014 'bin-dir' => '{$vendor-dir}/bin',
9015 'cache-dir' => '{$home}/cache',
9016 'data-dir' => '{$home}',
9017 'cache-files-dir' => '{$cache-dir}/files',
9018 'cache-repo-dir' => '{$cache-dir}/repo',
9019 'cache-vcs-dir' => '{$cache-dir}/vcs',
9020 'cache-ttl' => 15552000, 
9021  'cache-files-ttl' => null, 
9022  'cache-files-maxsize' => '300MiB',
9023 'bin-compat' => 'auto',
9024 'discard-changes' => false,
9025 'autoloader-suffix' => null,
9026 'sort-packages' => false,
9027 'optimize-autoloader' => false,
9028 'classmap-authoritative' => false,
9029 'apcu-autoloader' => false,
9030 'prepend-autoloader' => true,
9031 'github-domains' => array('github.com'),
9032 'bitbucket-expose-hostname' => true,
9033 'disable-tls' => false,
9034 'secure-http' => true,
9035 'cafile' => null,
9036 'capath' => null,
9037 'github-expose-hostname' => true,
9038 'gitlab-domains' => array('gitlab.com'),
9039 'store-auths' => 'prompt',
9040 'platform' => array(),
9041 'archive-format' => 'tar',
9042 'archive-dir' => '.',
9043 'htaccess-protect' => true,
9044
9045  
9046  
9047  
9048  
9049  
9050  );
9051
9052 public static $defaultRepositories = array(
9053 'packagist.org' => array(
9054 'type' => 'composer',
9055 'url' => 'https?://repo.packagist.org',
9056 'allow_ssl_downgrade' => true,
9057 ),
9058 );
9059
9060 private $config;
9061 private $baseDir;
9062 private $repositories;
9063
9064 private $configSource;
9065
9066 private $authConfigSource;
9067 private $useEnvironment;
9068 private $warnedHosts = array();
9069
9070
9071
9072
9073
9074 public function __construct($useEnvironment = true, $baseDir = null)
9075 {
9076
9077  $this->config = static::$defaultConfig;
9078 $this->repositories = static::$defaultRepositories;
9079 $this->useEnvironment = (bool) $useEnvironment;
9080 $this->baseDir = $baseDir;
9081 }
9082
9083 public function setConfigSource(ConfigSourceInterface $source)
9084 {
9085 $this->configSource = $source;
9086 }
9087
9088 public function getConfigSource()
9089 {
9090 return $this->configSource;
9091 }
9092
9093 public function setAuthConfigSource(ConfigSourceInterface $source)
9094 {
9095 $this->authConfigSource = $source;
9096 }
9097
9098 public function getAuthConfigSource()
9099 {
9100 return $this->authConfigSource;
9101 }
9102
9103
9104
9105
9106
9107
9108 public function merge($config)
9109 {
9110
9111  if (!empty($config['config']) && is_array($config['config'])) {
9112 foreach ($config['config'] as $key => $val) {
9113 if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic')) && isset($this->config[$key])) {
9114 $this->config[$key] = array_merge($this->config[$key], $val);
9115 } elseif ('preferred-install' === $key && isset($this->config[$key])) {
9116 if (is_array($val) || is_array($this->config[$key])) {
9117 if (is_string($val)) {
9118 $val = array('*' => $val);
9119 }
9120 if (is_string($this->config[$key])) {
9121 $this->config[$key] = array('*' => $this->config[$key]);
9122 }
9123 $this->config[$key] = array_merge($this->config[$key], $val);
9124
9125  if (isset($this->config[$key]['*'])) {
9126 $wildcard = $this->config[$key]['*'];
9127 unset($this->config[$key]['*']);
9128 $this->config[$key]['*'] = $wildcard;
9129 }
9130 } else {
9131 $this->config[$key] = $val;
9132 }
9133 } else {
9134 $this->config[$key] = $val;
9135 }
9136 }
9137 }
9138
9139 if (!empty($config['repositories']) && is_array($config['repositories'])) {
9140 $this->repositories = array_reverse($this->repositories, true);
9141 $newRepos = array_reverse($config['repositories'], true);
9142 foreach ($newRepos as $name => $repository) {
9143
9144  if (false === $repository) {
9145 $this->disableRepoByName($name);
9146 continue;
9147 }
9148
9149
9150  if (is_array($repository) && 1 === count($repository) && false === current($repository)) {
9151 $this->disableRepoByName(key($repository));
9152 continue;
9153 }
9154
9155
9156  if (is_int($name)) {
9157 $this->repositories[] = $repository;
9158 } else {
9159 if ($name === 'packagist') { 
9160  $this->repositories[$name . '.org'] = $repository;
9161 } else {
9162 $this->repositories[$name] = $repository;
9163 }
9164 }
9165 }
9166 $this->repositories = array_reverse($this->repositories, true);
9167 }
9168 }
9169
9170
9171
9172
9173 public function getRepositories()
9174 {
9175 return $this->repositories;
9176 }
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186 public function get($key, $flags = 0)
9187 {
9188 switch ($key) {
9189 case 'vendor-dir':
9190 case 'bin-dir':
9191 case 'process-timeout':
9192 case 'data-dir':
9193 case 'cache-dir':
9194 case 'cache-files-dir':
9195 case 'cache-repo-dir':
9196 case 'cache-vcs-dir':
9197 case 'cafile':
9198 case 'capath':
9199 case 'htaccess-protect':
9200
9201  $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
9202
9203 $val = $this->getComposerEnv($env);
9204 $val = rtrim((string) $this->process(false !== $val ? $val : $this->config[$key], $flags), '/\\');
9205 $val = Platform::expandPath($val);
9206
9207 if (substr($key, -4) !== '-dir') {
9208 return $val;
9209 }
9210
9211 return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
9212
9213 case 'cache-ttl':
9214 return (int) $this->config[$key];
9215
9216 case 'cache-files-maxsize':
9217 if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
9218 throw new \RuntimeException(
9219 "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
9220 );
9221 }
9222 $size = $matches[1];
9223 if (isset($matches[2])) {
9224 switch (strtolower($matches[2])) {
9225 case 'g':
9226 $size *= 1024;
9227
9228  
9229  case 'm':
9230 $size *= 1024;
9231
9232  
9233  case 'k':
9234 $size *= 1024;
9235 break;
9236 }
9237 }
9238
9239 return $size;
9240
9241 case 'cache-files-ttl':
9242 if (isset($this->config[$key])) {
9243 return (int) $this->config[$key];
9244 }
9245
9246 return (int) $this->config['cache-ttl'];
9247
9248 case 'home':
9249 $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $this->config[$key]);
9250
9251 return rtrim($this->process($val, $flags), '/\\');
9252
9253 case 'bin-compat':
9254 $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
9255
9256 if (!in_array($value, array('auto', 'full'))) {
9257 throw new \RuntimeException(
9258 "Invalid value for 'bin-compat': {$value}. Expected auto, full"
9259 );
9260 }
9261
9262 return $value;
9263
9264 case 'discard-changes':
9265 if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
9266 if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
9267 throw new \RuntimeException(
9268 "Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"
9269 );
9270 }
9271 if ('stash' === $env) {
9272 return 'stash';
9273 }
9274
9275
9276  return $env !== 'false' && (bool) $env;
9277 }
9278
9279 if (!in_array($this->config[$key], array(true, false, 'stash'), true)) {
9280 throw new \RuntimeException(
9281 "Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"
9282 );
9283 }
9284
9285 return $this->config[$key];
9286
9287 case 'github-protocols':
9288 $protos = $this->config['github-protocols'];
9289 if ($this->config['secure-http'] && false !== ($index = array_search('git', $protos))) {
9290 unset($protos[$index]);
9291 }
9292 if (reset($protos) === 'http') {
9293 throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
9294 }
9295
9296 return $protos;
9297
9298 case 'disable-tls':
9299 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
9300
9301 case 'secure-http':
9302 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
9303
9304 default:
9305 if (!isset($this->config[$key])) {
9306 return null;
9307 }
9308
9309 return $this->process($this->config[$key], $flags);
9310 }
9311 }
9312
9313 public function all($flags = 0)
9314 {
9315 $all = array(
9316 'repositories' => $this->getRepositories(),
9317 );
9318 foreach (array_keys($this->config) as $key) {
9319 $all['config'][$key] = $this->get($key, $flags);
9320 }
9321
9322 return $all;
9323 }
9324
9325 public function raw()
9326 {
9327 return array(
9328 'repositories' => $this->getRepositories(),
9329 'config' => $this->config,
9330 );
9331 }
9332
9333
9334
9335
9336
9337
9338
9339 public function has($key)
9340 {
9341 return array_key_exists($key, $this->config);
9342 }
9343
9344
9345
9346
9347
9348
9349
9350
9351 private function process($value, $flags)
9352 {
9353 $config = $this;
9354
9355 if (!is_string($value)) {
9356 return $value;
9357 }
9358
9359 return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
9360 return $config->get($match[1], $flags);
9361 }, $value);
9362 }
9363
9364
9365
9366
9367
9368
9369
9370
9371
9372 private function realpath($path)
9373 {
9374 if (preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) {
9375 return $path;
9376 }
9377
9378 return $this->baseDir . '/' . $path;
9379 }
9380
9381
9382
9383
9384
9385
9386
9387
9388
9389
9390 private function getComposerEnv($var)
9391 {
9392 if ($this->useEnvironment) {
9393 return getenv($var);
9394 }
9395
9396 return false;
9397 }
9398
9399 private function disableRepoByName($name)
9400 {
9401 if (isset($this->repositories[$name])) {
9402 unset($this->repositories[$name]);
9403 } elseif ($name === 'packagist') { 
9404  unset($this->repositories['packagist.org']);
9405 }
9406 }
9407
9408
9409
9410
9411
9412
9413
9414 public function prohibitUrlByConfig($url, IOInterface $io = null)
9415 {
9416
9417  if (false === filter_var($url, FILTER_VALIDATE_URL)) {
9418 return;
9419 }
9420
9421
9422  $scheme = parse_url($url, PHP_URL_SCHEME);
9423 if (in_array($scheme, array('http', 'git', 'ftp', 'svn'))) {
9424 if ($this->get('secure-http')) {
9425 throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
9426 } elseif ($io) {
9427 $host = parse_url($url, PHP_URL_HOST);
9428 if (!isset($this->warnedHosts[$host])) {
9429 $io->writeError("<warning>Warning: Accessing $host over $scheme which is an insecure protocol.</warning>");
9430 }
9431 $this->warnedHosts[$host] = true;
9432 }
9433 }
9434 }
9435 }
9436 <?php
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448 namespace Composer\Config;
9449
9450
9451
9452
9453
9454
9455
9456 interface ConfigSourceInterface
9457 {
9458
9459
9460
9461
9462
9463
9464 public function addRepository($name, $config);
9465
9466
9467
9468
9469
9470
9471 public function removeRepository($name);
9472
9473
9474
9475
9476
9477
9478
9479 public function addConfigSetting($name, $value);
9480
9481
9482
9483
9484
9485
9486 public function removeConfigSetting($name);
9487
9488
9489
9490
9491
9492
9493
9494 public function addProperty($name, $value);
9495
9496
9497
9498
9499
9500
9501 public function removeProperty($name);
9502
9503
9504
9505
9506
9507
9508
9509
9510 public function addLink($type, $name, $value);
9511
9512
9513
9514
9515
9516
9517
9518 public function removeLink($type, $name);
9519
9520
9521
9522
9523
9524
9525 public function getName();
9526 }
9527 <?php
9528
9529
9530
9531
9532
9533
9534
9535
9536
9537
9538
9539 namespace Composer\Config;
9540
9541 use Composer\Json\JsonFile;
9542 use Composer\Json\JsonManipulator;
9543 use Composer\Util\Silencer;
9544
9545
9546
9547
9548
9549
9550
9551 class JsonConfigSource implements ConfigSourceInterface
9552 {
9553
9554
9555
9556 private $file;
9557
9558
9559
9560
9561 private $authConfig;
9562
9563
9564
9565
9566
9567
9568
9569 public function __construct(JsonFile $file, $authConfig = false)
9570 {
9571 $this->file = $file;
9572 $this->authConfig = $authConfig;
9573 }
9574
9575
9576
9577
9578 public function getName()
9579 {
9580 return $this->file->getPath();
9581 }
9582
9583
9584
9585
9586 public function addRepository($name, $config)
9587 {
9588 $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
9589
9590  
9591  if (isset($config['repositories'])) {
9592 foreach ($config['repositories'] as $index => $val) {
9593 if ($index === $repo) {
9594 continue;
9595 }
9596 if (is_numeric($index) && ($val === array('packagist' => false) || $val === array('packagist.org' => false))) {
9597 unset($config['repositories'][$index]);
9598 $config['repositories']['packagist.org'] = false;
9599 break;
9600 }
9601 }
9602 }
9603
9604 $config['repositories'][$repo] = $repoConfig;
9605 });
9606 }
9607
9608
9609
9610
9611 public function removeRepository($name)
9612 {
9613 $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
9614 unset($config['repositories'][$repo]);
9615 });
9616 }
9617
9618
9619
9620
9621 public function addConfigSetting($name, $value)
9622 {
9623 $authConfig = $this->authConfig;
9624 $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) {
9625 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9626 list($key, $host) = explode('.', $key, 2);
9627 if ($authConfig) {
9628 $config[$key][$host] = $val;
9629 } else {
9630 $config['config'][$key][$host] = $val;
9631 }
9632 } else {
9633 $config['config'][$key] = $val;
9634 }
9635 });
9636 }
9637
9638
9639
9640
9641 public function removeConfigSetting($name)
9642 {
9643 $authConfig = $this->authConfig;
9644 $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) {
9645 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9646 list($key, $host) = explode('.', $key, 2);
9647 if ($authConfig) {
9648 unset($config[$key][$host]);
9649 } else {
9650 unset($config['config'][$key][$host]);
9651 }
9652 } else {
9653 unset($config['config'][$key]);
9654 }
9655 });
9656 }
9657
9658
9659
9660
9661 public function addProperty($name, $value)
9662 {
9663 $this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) {
9664 if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
9665 $bits = explode('.', $key);
9666 $last = array_pop($bits);
9667 $arr = &$config[reset($bits)];
9668 foreach ($bits as $bit) {
9669 if (!isset($arr[$bit])) {
9670 $arr[$bit] = array();
9671 }
9672 $arr = &$arr[$bit];
9673 }
9674 $arr[$last] = $val;
9675 } else {
9676 $config[$key] = $val;
9677 }
9678 });
9679 }
9680
9681
9682
9683
9684 public function removeProperty($name)
9685 {
9686 $authConfig = $this->authConfig;
9687 $this->manipulateJson('removeProperty', $name, function (&$config, $key) {
9688 if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
9689 $bits = explode('.', $key);
9690 $last = array_pop($bits);
9691 $arr = &$config[reset($bits)];
9692 foreach ($bits as $bit) {
9693 if (!isset($arr[$bit])) {
9694 return;
9695 }
9696 $arr = &$arr[$bit];
9697 }
9698 unset($arr[$last]);
9699 } else {
9700 unset($config[$key]);
9701 }
9702 });
9703 }
9704
9705
9706
9707
9708 public function addLink($type, $name, $value)
9709 {
9710 $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
9711 $config[$type][$name] = $value;
9712 });
9713 }
9714
9715
9716
9717
9718 public function removeLink($type, $name)
9719 {
9720 $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
9721 unset($config[$type][$name]);
9722 });
9723 }
9724
9725 protected function manipulateJson($method, $args, $fallback)
9726 {
9727 $args = func_get_args();
9728
9729  array_shift($args);
9730 $fallback = array_pop($args);
9731
9732 if ($this->file->exists()) {
9733 if (!is_writable($this->file->getPath())) {
9734 throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
9735 }
9736
9737 if (!is_readable($this->file->getPath())) {
9738 throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
9739 }
9740
9741 $contents = file_get_contents($this->file->getPath());
9742 } elseif ($this->authConfig) {
9743 $contents = "{\n}\n";
9744 } else {
9745 $contents = "{\n    \"config\": {\n    }\n}\n";
9746 }
9747
9748 $manipulator = new JsonManipulator($contents);
9749
9750 $newFile = !$this->file->exists();
9751
9752
9753  if ($this->authConfig && $method === 'addConfigSetting') {
9754 $method = 'addSubNode';
9755 list($mainNode, $name) = explode('.', $args[0], 2);
9756 $args = array($mainNode, $name, $args[1]);
9757 } elseif ($this->authConfig && $method === 'removeConfigSetting') {
9758 $method = 'removeSubNode';
9759 list($mainNode, $name) = explode('.', $args[0], 2);
9760 $args = array($mainNode, $name);
9761 }
9762
9763
9764  if (call_user_func_array(array($manipulator, $method), $args)) {
9765 file_put_contents($this->file->getPath(), $manipulator->getContents());
9766 } else {
9767
9768  $config = $this->file->read();
9769 $this->arrayUnshiftRef($args, $config);
9770 call_user_func_array($fallback, $args);
9771 $this->file->write($config);
9772 }
9773
9774 if ($newFile) {
9775 Silencer::call('chmod', $this->file->getPath(), 0600);
9776 }
9777 }
9778
9779
9780
9781
9782
9783
9784
9785
9786 private function arrayUnshiftRef(&$array, &$value)
9787 {
9788 $return = array_unshift($array, '');
9789 $array[0] = &$value;
9790
9791 return $return;
9792 }
9793 }
9794 <?php
9795
9796
9797
9798
9799
9800
9801
9802
9803
9804
9805
9806 namespace Composer\Console;
9807
9808 use Composer\IO\NullIO;
9809 use Composer\Util\Platform;
9810 use Composer\Util\Silencer;
9811 use Symfony\Component\Console\Application as BaseApplication;
9812 use Symfony\Component\Console\Input\InputInterface;
9813 use Symfony\Component\Console\Input\InputOption;
9814 use Symfony\Component\Console\Output\OutputInterface;
9815 use Composer\Command;
9816 use Composer\Composer;
9817 use Composer\Factory;
9818 use Composer\IO\IOInterface;
9819 use Composer\IO\ConsoleIO;
9820 use Composer\Json\JsonValidationException;
9821 use Composer\Util\ErrorHandler;
9822 use Composer\EventDispatcher\ScriptExecutionException;
9823 use Composer\Exception\NoSslException;
9824
9825
9826
9827
9828
9829
9830
9831
9832 class Application extends BaseApplication
9833 {
9834
9835
9836
9837 protected $composer;
9838
9839
9840
9841
9842 protected $io;
9843
9844 private static $logo = '   ______
9845   / ____/___  ____ ___  ____  ____  ________  _____
9846  / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
9847 / /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
9848 \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
9849                     /_/
9850 ';
9851
9852 private $hasPluginCommands = false;
9853 private $disablePluginsByDefault = false;
9854
9855 public function __construct()
9856 {
9857 static $shutdownRegistered = false;
9858
9859 if (function_exists('ini_set') && extension_loaded('xdebug')) {
9860 ini_set('xdebug.show_exception_trace', false);
9861 ini_set('xdebug.scream', false);
9862 }
9863
9864 if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
9865 date_default_timezone_set(Silencer::call('date_default_timezone_get'));
9866 }
9867
9868 if (!$shutdownRegistered) {
9869 $shutdownRegistered = true;
9870
9871 register_shutdown_function(function () {
9872 $lastError = error_get_last();
9873
9874 if ($lastError && $lastError['message'] &&
9875 (strpos($lastError['message'], 'Allowed memory') !== false  ||
9876 strpos($lastError['message'], 'exceeded memory') !== false )) {
9877 echo "\n". 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
9878 }
9879 });
9880 }
9881
9882 $this->io = new NullIO();
9883
9884 parent::__construct('Composer', Composer::VERSION);
9885 }
9886
9887
9888
9889
9890 public function run(InputInterface $input = null, OutputInterface $output = null)
9891 {
9892 if (null === $output) {
9893 $output = Factory::createOutput();
9894 }
9895
9896 return parent::run($input, $output);
9897 }
9898
9899
9900
9901
9902 public function doRun(InputInterface $input, OutputInterface $output)
9903 {
9904 $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
9905
9906 $io = $this->io = new ConsoleIO($input, $output, $this->getHelperSet());
9907 ErrorHandler::register($io);
9908
9909
9910  if ($newWorkDir = $this->getNewWorkingDir($input)) {
9911 $oldWorkingDir = getcwd();
9912 chdir($newWorkDir);
9913 $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
9914 }
9915
9916
9917  $commandName = '';
9918 if ($name = $this->getCommandName($input)) {
9919 try {
9920 $commandName = $this->find($name)->getName();
9921 } catch (\InvalidArgumentException $e) {
9922 }
9923 }
9924
9925
9926  if ($io->isInteractive() && !$newWorkDir && !in_array($commandName, array('', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project'), true) && !file_exists(Factory::getComposerFile())) {
9927 $dir = dirname(getcwd());
9928 $home = realpath(getenv('HOME') ?: getenv('USERPROFILE') ?: '/');
9929
9930
9931  while (dirname($dir) !== $dir && $dir !== $home) {
9932 if (file_exists($dir.'/'.Factory::getComposerFile())) {
9933 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)) {
9934 $oldWorkingDir = getcwd();
9935 chdir($dir);
9936 }
9937 break;
9938 }
9939 $dir = dirname($dir);
9940 }
9941 }
9942
9943 if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
9944 try {
9945 foreach ($this->getPluginCommands() as $command) {
9946 if ($this->has($command->getName())) {
9947 $io->writeError('<warning>Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped</warning>');
9948 } else {
9949 $this->add($command);
9950 }
9951 }
9952 } catch (NoSslException $e) {
9953
9954  }
9955
9956 $this->hasPluginCommands = true;
9957 }
9958
9959
9960  $isProxyCommand = false;
9961 if ($name = $this->getCommandName($input)) {
9962 try {
9963 $command = $this->find($name);
9964 $commandName = $command->getName();
9965 $isProxyCommand = ($command instanceof Command\BaseCommand && $command->isProxyCommand());
9966 } catch (\InvalidArgumentException $e) {
9967 }
9968 }
9969
9970 if (!$isProxyCommand) {
9971 $io->writeError(sprintf(
9972 'Running %s (%s) with %s on %s',
9973 Composer::VERSION,
9974 Composer::RELEASE_DATE,
9975 defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
9976 function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
9977 ), true, IOInterface::DEBUG);
9978
9979 if (PHP_VERSION_ID < 50302) {
9980 $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>');
9981 }
9982
9983 if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
9984 $io->writeError('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
9985 }
9986
9987 if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
9988 $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']));
9989 }
9990
9991 if (getenv('COMPOSER_NO_INTERACTION')) {
9992 $input->setInteractive(false);
9993 }
9994
9995 if (!Platform::isWindows() && function_exists('exec') && !getenv('COMPOSER_ALLOW_SUPERUSER')) {
9996 if (function_exists('posix_getuid') && posix_getuid() === 0) {
9997 if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
9998 $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
9999 }
10000 if ($uid = (int) getenv('SUDO_UID')) {
10001
10002  
10003  Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
10004 }
10005 }
10006
10007  Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
10008 }
10009
10010
10011  Silencer::call(function () use ($io) {
10012 $tempfile = sys_get_temp_dir() . '/temp-' . md5(microtime());
10013 if (!(file_put_contents($tempfile, __FILE__) && (file_get_contents($tempfile) == __FILE__) && unlink($tempfile) && !file_exists($tempfile))) {
10014 $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()));
10015 }
10016 });
10017
10018
10019  $file = Factory::getComposerFile();
10020 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
10021 if (isset($composer['scripts']) && is_array($composer['scripts'])) {
10022 foreach ($composer['scripts'] as $script => $dummy) {
10023 if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
10024 if ($this->has($script)) {
10025 $io->writeError('<warning>A script named '.$script.' would override a Composer command and has been skipped</warning>');
10026 } else {
10027 $description = null;
10028
10029 if (isset($composer['scripts-descriptions'][$script])) {
10030 $description = $composer['scripts-descriptions'][$script];
10031 }
10032
10033 $this->add(new Command\ScriptAliasCommand($script, $description));
10034 }
10035 }
10036 }
10037 }
10038 }
10039 }
10040
10041 try {
10042 if ($input->hasParameterOption('--profile')) {
10043 $startTime = microtime(true);
10044 $this->io->enableDebugging($startTime);
10045 }
10046
10047 $result = parent::doRun($input, $output);
10048
10049 if (isset($oldWorkingDir)) {
10050 chdir($oldWorkingDir);
10051 }
10052
10053 if (isset($startTime)) {
10054 $io->writeError('<info>Memory usage: '.round(memory_get_usage() / 1024 / 1024, 2).'MB (peak: '.round(memory_get_peak_usage() / 1024 / 1024, 2).'MB), time: '.round(microtime(true) - $startTime, 2).'s');
10055 }
10056
10057 restore_error_handler();
10058
10059 return $result;
10060 } catch (ScriptExecutionException $e) {
10061 return $e->getCode();
10062 } catch (\Exception $e) {
10063 $this->hintCommonErrors($e);
10064 restore_error_handler();
10065 throw $e;
10066 }
10067 }
10068
10069
10070
10071
10072
10073
10074 private function getNewWorkingDir(InputInterface $input)
10075 {
10076 $workingDir = $input->getParameterOption(array('--working-dir', '-d'));
10077 if (false !== $workingDir && !is_dir($workingDir)) {
10078 throw new \RuntimeException('Invalid working directory specified, '.$workingDir.' does not exist.');
10079 }
10080
10081 return $workingDir;
10082 }
10083
10084
10085
10086
10087 private function hintCommonErrors($exception)
10088 {
10089 $io = $this->getIO();
10090
10091 Silencer::suppress();
10092 try {
10093 $composer = $this->getComposer(false, true);
10094 if ($composer) {
10095 $config = $composer->getConfig();
10096
10097 $minSpaceFree = 1024 * 1024;
10098 if ((($df = disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
10099 || (($df = disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
10100 || (($df = disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
10101 ) {
10102 $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>', true, IOInterface::QUIET);
10103 }
10104 }
10105 } catch (\Exception $e) {
10106 }
10107 Silencer::restore();
10108
10109 if (Platform::isWindows() && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
10110 $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', true, IOInterface::QUIET);
10111 $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);
10112 }
10113
10114 if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
10115 $io->writeError('<error>The following exception is caused by a lack of memory or swap, or not having swap configured</error>', true, IOInterface::QUIET);
10116 $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
10117 }
10118 }
10119
10120
10121
10122
10123
10124
10125
10126 public function getComposer($required = true, $disablePlugins = null)
10127 {
10128 if (null === $disablePlugins) {
10129 $disablePlugins = $this->disablePluginsByDefault;
10130 }
10131
10132 if (null === $this->composer) {
10133 try {
10134 $this->composer = Factory::create($this->io, null, $disablePlugins);
10135 } catch (\InvalidArgumentException $e) {
10136 if ($required) {
10137 $this->io->writeError($e->getMessage());
10138 exit(1);
10139 }
10140 } catch (JsonValidationException $e) {
10141 $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
10142 $message = $e->getMessage() . ':' . PHP_EOL . $errors;
10143 throw new JsonValidationException($message);
10144 }
10145 }
10146
10147 return $this->composer;
10148 }
10149
10150
10151
10152
10153 public function resetComposer()
10154 {
10155 $this->composer = null;
10156 }
10157
10158
10159
10160
10161 public function getIO()
10162 {
10163 return $this->io;
10164 }
10165
10166 public function getHelp()
10167 {
10168 return self::$logo . parent::getHelp();
10169 }
10170
10171
10172
10173
10174 protected function getDefaultCommands()
10175 {
10176 $commands = array_merge(parent::getDefaultCommands(), array(
10177 new Command\AboutCommand(),
10178 new Command\ConfigCommand(),
10179 new Command\DependsCommand(),
10180 new Command\ProhibitsCommand(),
10181 new Command\InitCommand(),
10182 new Command\InstallCommand(),
10183 new Command\CreateProjectCommand(),
10184 new Command\UpdateCommand(),
10185 new Command\SearchCommand(),
10186 new Command\ValidateCommand(),
10187 new Command\ShowCommand(),
10188 new Command\SuggestsCommand(),
10189 new Command\RequireCommand(),
10190 new Command\DumpAutoloadCommand(),
10191 new Command\StatusCommand(),
10192 new Command\ArchiveCommand(),
10193 new Command\DiagnoseCommand(),
10194 new Command\RunScriptCommand(),
10195 new Command\LicensesCommand(),
10196 new Command\GlobalCommand(),
10197 new Command\ClearCacheCommand(),
10198 new Command\RemoveCommand(),
10199 new Command\HomeCommand(),
10200 new Command\ExecCommand(),
10201 new Command\OutdatedCommand(),
10202 new Command\CheckPlatformReqsCommand(),
10203 ));
10204
10205 if ('phar:' === substr(__FILE__, 0, 5)) {
10206 $commands[] = new Command\SelfUpdateCommand();
10207 }
10208
10209 return $commands;
10210 }
10211
10212
10213
10214
10215 public function getLongVersion()
10216 {
10217 if (Composer::BRANCH_ALIAS_VERSION) {
10218 return sprintf(
10219 '<info>%s</info> version <comment>%s (%s)</comment> %s',
10220 $this->getName(),
10221 Composer::BRANCH_ALIAS_VERSION,
10222 $this->getVersion(),
10223 Composer::RELEASE_DATE
10224 );
10225 }
10226
10227 return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE;
10228 }
10229
10230
10231
10232
10233 protected function getDefaultInputDefinition()
10234 {
10235 $definition = parent::getDefaultInputDefinition();
10236 $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
10237 $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'));
10238 $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
10239
10240 return $definition;
10241 }
10242
10243 private function getPluginCommands()
10244 {
10245 $commands = array();
10246
10247 $composer = $this->getComposer(false, false);
10248 if (null === $composer) {
10249 $composer = Factory::createGlobal($this->io, false);
10250 }
10251
10252 if (null !== $composer) {
10253 $pm = $composer->getPluginManager();
10254 foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $composer, 'io' => $this->io)) as $capability) {
10255 $newCommands = $capability->getCommands();
10256 if (!is_array($newCommands)) {
10257 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands');
10258 }
10259 foreach ($newCommands as $command) {
10260 if (!$command instanceof Command\BaseCommand) {
10261 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects');
10262 }
10263 }
10264 $commands = array_merge($commands, $newCommands);
10265 }
10266 }
10267
10268 return $commands;
10269 }
10270 }
10271 <?php
10272
10273
10274
10275
10276
10277
10278
10279
10280
10281
10282
10283 namespace Composer\Console;
10284
10285 use Symfony\Component\Console\Formatter\OutputFormatter;
10286
10287
10288
10289
10290 class HtmlOutputFormatter extends OutputFormatter
10291 {
10292 private static $availableForegroundColors = array(
10293 30 => 'black',
10294 31 => 'red',
10295 32 => 'green',
10296 33 => 'yellow',
10297 34 => 'blue',
10298 35 => 'magenta',
10299 36 => 'cyan',
10300 37 => 'white',
10301 );
10302 private static $availableBackgroundColors = array(
10303 40 => 'black',
10304 41 => 'red',
10305 42 => 'green',
10306 43 => 'yellow',
10307 44 => 'blue',
10308 45 => 'magenta',
10309 46 => 'cyan',
10310 47 => 'white',
10311 );
10312 private static $availableOptions = array(
10313 1 => 'bold',
10314 4 => 'underscore',
10315
10316  
10317  
10318  );
10319
10320
10321
10322
10323 public function __construct(array $styles = array())
10324 {
10325 parent::__construct(true, $styles);
10326 }
10327
10328 public function format($message)
10329 {
10330 $formatted = parent::format($message);
10331
10332 $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
10333
10334 return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted);
10335 }
10336
10337 private function formatHtml($matches)
10338 {
10339 $out = '<span style="';
10340 foreach (explode(';', $matches[1]) as $code) {
10341 if (isset(self::$availableForegroundColors[$code])) {
10342 $out .= 'color:'.self::$availableForegroundColors[$code].';';
10343 } elseif (isset(self::$availableBackgroundColors[$code])) {
10344 $out .= 'background-color:'.self::$availableBackgroundColors[$code].';';
10345 } elseif (isset(self::$availableOptions[$code])) {
10346 switch (self::$availableOptions[$code]) {
10347 case 'bold':
10348 $out .= 'font-weight:bold;';
10349 break;
10350
10351 case 'underscore':
10352 $out .= 'text-decoration:underline;';
10353 break;
10354 }
10355 }
10356 }
10357
10358 return $out.'">'.$matches[2].'</span>';
10359 }
10360 }
10361 <?php
10362
10363
10364
10365
10366
10367
10368
10369
10370
10371
10372
10373 namespace Composer\DependencyResolver;
10374
10375
10376
10377
10378
10379
10380 class Decisions implements \Iterator, \Countable
10381 {
10382 const DECISION_LITERAL = 0;
10383 const DECISION_REASON = 1;
10384
10385 protected $pool;
10386 protected $decisionMap;
10387 protected $decisionQueue = array();
10388
10389 public function __construct($pool)
10390 {
10391 $this->pool = $pool;
10392 $this->decisionMap = array();
10393 }
10394
10395 public function decide($literal, $level, $why)
10396 {
10397 $this->addDecision($literal, $level);
10398 $this->decisionQueue[] = array(
10399 self::DECISION_LITERAL => $literal,
10400 self::DECISION_REASON => $why,
10401 );
10402 }
10403
10404 public function satisfy($literal)
10405 {
10406 $packageId = abs($literal);
10407
10408 return (
10409 $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 ||
10410 $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0
10411 );
10412 }
10413
10414 public function conflict($literal)
10415 {
10416 $packageId = abs($literal);
10417
10418 return (
10419 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0) ||
10420 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0)
10421 );
10422 }
10423
10424 public function decided($literalOrPackageId)
10425 {
10426 return !empty($this->decisionMap[abs($literalOrPackageId)]);
10427 }
10428
10429 public function undecided($literalOrPackageId)
10430 {
10431 return empty($this->decisionMap[abs($literalOrPackageId)]);
10432 }
10433
10434 public function decidedInstall($literalOrPackageId)
10435 {
10436 $packageId = abs($literalOrPackageId);
10437
10438 return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
10439 }
10440
10441 public function decisionLevel($literalOrPackageId)
10442 {
10443 $packageId = abs($literalOrPackageId);
10444 if (isset($this->decisionMap[$packageId])) {
10445 return abs($this->decisionMap[$packageId]);
10446 }
10447
10448 return 0;
10449 }
10450
10451 public function decisionRule($literalOrPackageId)
10452 {
10453 $packageId = abs($literalOrPackageId);
10454
10455 foreach ($this->decisionQueue as $i => $decision) {
10456 if ($packageId === abs($decision[self::DECISION_LITERAL])) {
10457 return $decision[self::DECISION_REASON];
10458 }
10459 }
10460
10461 return null;
10462 }
10463
10464 public function atOffset($queueOffset)
10465 {
10466 return $this->decisionQueue[$queueOffset];
10467 }
10468
10469 public function validOffset($queueOffset)
10470 {
10471 return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
10472 }
10473
10474 public function lastReason()
10475 {
10476 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
10477 }
10478
10479 public function lastLiteral()
10480 {
10481 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
10482 }
10483
10484 public function reset()
10485 {
10486 while ($decision = array_pop($this->decisionQueue)) {
10487 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
10488 }
10489 }
10490
10491 public function resetToOffset($offset)
10492 {
10493 while (count($this->decisionQueue) > $offset + 1) {
10494 $decision = array_pop($this->decisionQueue);
10495 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
10496 }
10497 }
10498
10499 public function revertLast()
10500 {
10501 $this->decisionMap[abs($this->lastLiteral())] = 0;
10502 array_pop($this->decisionQueue);
10503 }
10504
10505 public function count()
10506 {
10507 return count($this->decisionQueue);
10508 }
10509
10510 public function rewind()
10511 {
10512 end($this->decisionQueue);
10513 }
10514
10515 public function current()
10516 {
10517 return current($this->decisionQueue);
10518 }
10519
10520 public function key()
10521 {
10522 return key($this->decisionQueue);
10523 }
10524
10525 public function next()
10526 {
10527 return prev($this->decisionQueue);
10528 }
10529
10530 public function valid()
10531 {
10532 return false !== current($this->decisionQueue);
10533 }
10534
10535 public function isEmpty()
10536 {
10537 return count($this->decisionQueue) === 0;
10538 }
10539
10540 protected function addDecision($literal, $level)
10541 {
10542 $packageId = abs($literal);
10543
10544 $previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
10545 if ($previousDecision != 0) {
10546 $literalString = $this->pool->literalToString($literal);
10547 $package = $this->pool->literalToPackage($literal);
10548 throw new SolverBugException(
10549 "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
10550 );
10551 }
10552
10553 if ($literal > 0) {
10554 $this->decisionMap[$packageId] = $level;
10555 } else {
10556 $this->decisionMap[$packageId] = -$level;
10557 }
10558 }
10559 }
10560 <?php
10561
10562
10563
10564
10565
10566
10567
10568
10569
10570
10571
10572 namespace Composer\DependencyResolver;
10573
10574 use Composer\Package\PackageInterface;
10575 use Composer\Package\AliasPackage;
10576 use Composer\Package\BasePackage;
10577 use Composer\Semver\Constraint\Constraint;
10578
10579
10580
10581
10582
10583 class DefaultPolicy implements PolicyInterface
10584 {
10585 private $preferStable;
10586 private $preferLowest;
10587
10588 public function __construct($preferStable = false, $preferLowest = false)
10589 {
10590 $this->preferStable = $preferStable;
10591 $this->preferLowest = $preferLowest;
10592 }
10593
10594 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
10595 {
10596 if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
10597 return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
10598 }
10599
10600 $constraint = new Constraint($operator, $b->getVersion());
10601 $version = new Constraint('==', $a->getVersion());
10602
10603 return $constraint->matchSpecific($version, true);
10604 }
10605
10606 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
10607 {
10608 $packages = array();
10609
10610 foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
10611 if ($candidate !== $package) {
10612 $packages[] = $candidate;
10613 }
10614 }
10615
10616 return $packages;
10617 }
10618
10619 public function getPriority(Pool $pool, PackageInterface $package)
10620 {
10621 return $pool->getPriority($package->getRepository());
10622 }
10623
10624 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
10625 {
10626 $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
10627
10628 foreach ($packages as &$literals) {
10629 $policy = $this;
10630 usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10631 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
10632 });
10633 }
10634
10635 foreach ($packages as &$literals) {
10636 $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
10637
10638 $literals = $this->pruneToBestVersion($pool, $literals);
10639
10640 $literals = $this->pruneRemoteAliases($pool, $literals);
10641 }
10642
10643 $selected = call_user_func_array('array_merge', $packages);
10644
10645
10646  usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10647 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
10648 });
10649
10650 return $selected;
10651 }
10652
10653 protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
10654 {
10655 $packages = array();
10656 foreach ($literals as $literal) {
10657 $packageName = $pool->literalToPackage($literal)->getName();
10658
10659 if (!isset($packages[$packageName])) {
10660 $packages[$packageName] = array();
10661 }
10662
10663 if (isset($installedMap[abs($literal)])) {
10664 array_unshift($packages[$packageName], $literal);
10665 } else {
10666 $packages[$packageName][] = $literal;
10667 }
10668 }
10669
10670 return $packages;
10671 }
10672
10673
10674
10675
10676 public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
10677 {
10678 if ($a->getRepository() === $b->getRepository()) {
10679
10680  if ($a->getName() === $b->getName()) {
10681 $aAliased = $a instanceof AliasPackage;
10682 $bAliased = $b instanceof AliasPackage;
10683 if ($aAliased && !$bAliased) {
10684 return -1; 
10685  }
10686 if (!$aAliased && $bAliased) {
10687 return 1; 
10688  }
10689 }
10690
10691 if (!$ignoreReplace) {
10692
10693  if ($this->replaces($a, $b)) {
10694 return 1; 
10695  }
10696 if ($this->replaces($b, $a)) {
10697 return -1; 
10698  }
10699
10700
10701  
10702  if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
10703 $requiredVendor = substr($requiredPackage, 0, $pos);
10704
10705 $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
10706 $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
10707
10708 if ($bIsSameVendor !== $aIsSameVendor) {
10709 return $aIsSameVendor ? -1 : 1;
10710 }
10711 }
10712 }
10713
10714
10715  if ($a->id === $b->id) {
10716 return 0;
10717 }
10718
10719 return ($a->id < $b->id) ? -1 : 1;
10720 }
10721
10722 if (isset($installedMap[$a->id])) {
10723 return -1;
10724 }
10725
10726 if (isset($installedMap[$b->id])) {
10727 return 1;
10728 }
10729
10730 return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
10731 }
10732
10733
10734
10735
10736
10737
10738
10739
10740
10741
10742
10743 protected function replaces(PackageInterface $source, PackageInterface $target)
10744 {
10745 foreach ($source->getReplaces() as $link) {
10746 if ($link->getTarget() === $target->getName()
10747
10748
10749  ) {
10750 return true;
10751 }
10752 }
10753
10754 return false;
10755 }
10756
10757 protected function pruneToBestVersion(Pool $pool, $literals)
10758 {
10759 $operator = $this->preferLowest ? '<' : '>';
10760 $bestLiterals = array($literals[0]);
10761 $bestPackage = $pool->literalToPackage($literals[0]);
10762 foreach ($literals as $i => $literal) {
10763 if (0 === $i) {
10764 continue;
10765 }
10766
10767 $package = $pool->literalToPackage($literal);
10768
10769 if ($this->versionCompare($package, $bestPackage, $operator)) {
10770 $bestPackage = $package;
10771 $bestLiterals = array($literal);
10772 } elseif ($this->versionCompare($package, $bestPackage, '==')) {
10773 $bestLiterals[] = $literal;
10774 }
10775 }
10776
10777 return $bestLiterals;
10778 }
10779
10780
10781
10782
10783 protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
10784 {
10785 $selected = array();
10786
10787 $priority = null;
10788
10789 foreach ($literals as $literal) {
10790 $package = $pool->literalToPackage($literal);
10791
10792 if (isset($installedMap[$package->id])) {
10793 $selected[] = $literal;
10794 continue;
10795 }
10796
10797 if (null === $priority) {
10798 $priority = $this->getPriority($pool, $package);
10799 }
10800
10801 if ($this->getPriority($pool, $package) != $priority) {
10802 break;
10803 }
10804
10805 $selected[] = $literal;
10806 }
10807
10808 return $selected;
10809 }
10810
10811
10812
10813
10814
10815
10816 protected function pruneRemoteAliases(Pool $pool, array $literals)
10817 {
10818 $hasLocalAlias = false;
10819
10820 foreach ($literals as $literal) {
10821 $package = $pool->literalToPackage($literal);
10822
10823 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10824 $hasLocalAlias = true;
10825 break;
10826 }
10827 }
10828
10829 if (!$hasLocalAlias) {
10830 return $literals;
10831 }
10832
10833 $selected = array();
10834 foreach ($literals as $literal) {
10835 $package = $pool->literalToPackage($literal);
10836
10837 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10838 $selected[] = $literal;
10839 }
10840 }
10841
10842 return $selected;
10843 }
10844 }
10845 <?php
10846
10847
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857 namespace Composer\DependencyResolver;
10858
10859 use Composer\Package\PackageInterface;
10860 use Composer\Package\Link;
10861
10862
10863
10864
10865 class GenericRule extends Rule
10866 {
10867 protected $literals;
10868
10869
10870
10871
10872
10873
10874
10875 public function __construct(array $literals, $reason, $reasonData, $job = null)
10876 {
10877 parent::__construct($reason, $reasonData, $job);
10878
10879
10880  sort($literals);
10881
10882 $this->literals = $literals;
10883 }
10884
10885 public function getLiterals()
10886 {
10887 return $this->literals;
10888 }
10889
10890 public function getHash()
10891 {
10892 $data = unpack('ihash', md5(implode(',', $this->literals), true));
10893
10894 return $data['hash'];
10895 }
10896
10897
10898
10899
10900
10901
10902
10903
10904
10905 public function equals(Rule $rule)
10906 {
10907 return $this->literals === $rule->getLiterals();
10908 }
10909
10910 public function isAssertion()
10911 {
10912 return 1 === count($this->literals);
10913 }
10914
10915
10916
10917
10918
10919
10920 public function __toString()
10921 {
10922 $result = $this->isDisabled() ? 'disabled(' : '(';
10923
10924 foreach ($this->literals as $i => $literal) {
10925 if ($i != 0) {
10926 $result .= '|';
10927 }
10928 $result .= $literal;
10929 }
10930
10931 $result .= ')';
10932
10933 return $result;
10934 }
10935 }
10936 <?php
10937
10938
10939
10940
10941
10942
10943
10944
10945
10946
10947
10948 namespace Composer\DependencyResolver\Operation;
10949
10950 use Composer\Package\PackageInterface;
10951
10952
10953
10954
10955
10956
10957 class InstallOperation extends SolverOperation
10958 {
10959 protected $package;
10960
10961
10962
10963
10964
10965
10966
10967 public function __construct(PackageInterface $package, $reason = null)
10968 {
10969 parent::__construct($reason);
10970
10971 $this->package = $package;
10972 }
10973
10974
10975
10976
10977
10978
10979 public function getPackage()
10980 {
10981 return $this->package;
10982 }
10983
10984
10985
10986
10987
10988
10989 public function getJobType()
10990 {
10991 return 'install';
10992 }
10993
10994
10995
10996
10997 public function __toString()
10998 {
10999 return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
11000 }
11001 }
11002 <?php
11003
11004
11005
11006
11007
11008
11009
11010
11011
11012
11013
11014 namespace Composer\DependencyResolver\Operation;
11015
11016 use Composer\Package\AliasPackage;
11017 use Composer\Package\PackageInterface;
11018
11019
11020
11021
11022
11023
11024 class MarkAliasInstalledOperation extends SolverOperation
11025 {
11026 protected $package;
11027
11028
11029
11030
11031
11032
11033
11034 public function __construct(AliasPackage $package, $reason = null)
11035 {
11036 parent::__construct($reason);
11037
11038 $this->package = $package;
11039 }
11040
11041
11042
11043
11044
11045
11046 public function getPackage()
11047 {
11048 return $this->package;
11049 }
11050
11051
11052
11053
11054
11055
11056 public function getJobType()
11057 {
11058 return 'markAliasInstalled';
11059 }
11060
11061
11062
11063
11064 public function __toString()
11065 {
11066 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
11067 }
11068 }
11069 <?php
11070
11071
11072
11073
11074
11075
11076
11077
11078
11079
11080
11081 namespace Composer\DependencyResolver\Operation;
11082
11083 use Composer\Package\AliasPackage;
11084 use Composer\Package\PackageInterface;
11085
11086
11087
11088
11089
11090
11091 class MarkAliasUninstalledOperation extends SolverOperation
11092 {
11093 protected $package;
11094
11095
11096
11097
11098
11099
11100
11101 public function __construct(AliasPackage $package, $reason = null)
11102 {
11103 parent::__construct($reason);
11104
11105 $this->package = $package;
11106 }
11107
11108
11109
11110
11111
11112
11113 public function getPackage()
11114 {
11115 return $this->package;
11116 }
11117
11118
11119
11120
11121
11122
11123 public function getJobType()
11124 {
11125 return 'markAliasUninstalled';
11126 }
11127
11128
11129
11130
11131 public function __toString()
11132 {
11133 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
11134 }
11135 }
11136 <?php
11137
11138
11139
11140
11141
11142
11143
11144
11145
11146
11147
11148 namespace Composer\DependencyResolver\Operation;
11149
11150
11151
11152
11153
11154
11155 interface OperationInterface
11156 {
11157
11158
11159
11160
11161
11162 public function getJobType();
11163
11164
11165
11166
11167
11168
11169 public function getReason();
11170
11171
11172
11173
11174
11175
11176 public function __toString();
11177 }
11178 <?php
11179
11180
11181
11182
11183
11184
11185
11186
11187
11188
11189
11190 namespace Composer\DependencyResolver\Operation;
11191
11192 use Composer\Package\PackageInterface;
11193
11194
11195
11196
11197
11198
11199 abstract class SolverOperation implements OperationInterface
11200 {
11201 protected $reason;
11202
11203
11204
11205
11206
11207
11208 public function __construct($reason = null)
11209 {
11210 $this->reason = $reason;
11211 }
11212
11213
11214
11215
11216
11217
11218 public function getReason()
11219 {
11220 return $this->reason;
11221 }
11222
11223 protected function formatVersion(PackageInterface $package)
11224 {
11225 return $package->getFullPrettyVersion();
11226 }
11227 }
11228 <?php
11229
11230
11231
11232
11233
11234
11235
11236
11237
11238
11239
11240 namespace Composer\DependencyResolver\Operation;
11241
11242 use Composer\Package\PackageInterface;
11243
11244
11245
11246
11247
11248
11249 class UninstallOperation extends SolverOperation
11250 {
11251 protected $package;
11252
11253
11254
11255
11256
11257
11258
11259 public function __construct(PackageInterface $package, $reason = null)
11260 {
11261 parent::__construct($reason);
11262
11263 $this->package = $package;
11264 }
11265
11266
11267
11268
11269
11270
11271 public function getPackage()
11272 {
11273 return $this->package;
11274 }
11275
11276
11277
11278
11279
11280
11281 public function getJobType()
11282 {
11283 return 'uninstall';
11284 }
11285
11286
11287
11288
11289 public function __toString()
11290 {
11291 return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
11292 }
11293 }
11294 <?php
11295
11296
11297
11298
11299
11300
11301
11302
11303
11304
11305
11306 namespace Composer\DependencyResolver\Operation;
11307
11308 use Composer\Package\PackageInterface;
11309
11310
11311
11312
11313
11314
11315 class UpdateOperation extends SolverOperation
11316 {
11317 protected $initialPackage;
11318 protected $targetPackage;
11319
11320
11321
11322
11323
11324
11325
11326
11327 public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
11328 {
11329 parent::__construct($reason);
11330
11331 $this->initialPackage = $initial;
11332 $this->targetPackage = $target;
11333 }
11334
11335
11336
11337
11338
11339
11340 public function getInitialPackage()
11341 {
11342 return $this->initialPackage;
11343 }
11344
11345
11346
11347
11348
11349
11350 public function getTargetPackage()
11351 {
11352 return $this->targetPackage;
11353 }
11354
11355
11356
11357
11358
11359
11360 public function getJobType()
11361 {
11362 return 'update';
11363 }
11364
11365
11366
11367
11368 public function __toString()
11369 {
11370 return 'Updating '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
11371 $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
11372 }
11373 }
11374 <?php
11375
11376
11377
11378
11379
11380
11381
11382
11383
11384
11385
11386 namespace Composer\DependencyResolver;
11387
11388 use Composer\Package\PackageInterface;
11389
11390
11391
11392
11393 interface PolicyInterface
11394 {
11395 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
11396
11397 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
11398
11399 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null);
11400 }
11401 <?php
11402
11403
11404
11405
11406
11407
11408
11409
11410
11411
11412
11413 namespace Composer\DependencyResolver;
11414
11415 use Composer\Package\BasePackage;
11416 use Composer\Package\AliasPackage;
11417 use Composer\Package\Version\VersionParser;
11418 use Composer\Semver\Constraint\ConstraintInterface;
11419 use Composer\Semver\Constraint\Constraint;
11420 use Composer\Semver\Constraint\EmptyConstraint;
11421 use Composer\Repository\RepositoryInterface;
11422 use Composer\Repository\CompositeRepository;
11423 use Composer\Repository\ComposerRepository;
11424 use Composer\Repository\InstalledRepositoryInterface;
11425 use Composer\Repository\PlatformRepository;
11426 use Composer\Package\PackageInterface;
11427
11428
11429
11430
11431
11432
11433
11434 class Pool implements \Countable
11435 {
11436 const MATCH_NAME = -1;
11437 const MATCH_NONE = 0;
11438 const MATCH = 1;
11439 const MATCH_PROVIDE = 2;
11440 const MATCH_REPLACE = 3;
11441 const MATCH_FILTERED = 4;
11442
11443 protected $repositories = array();
11444 protected $providerRepos = array();
11445 protected $packages = array();
11446 protected $packageByName = array();
11447 protected $packageByExactName = array();
11448 protected $acceptableStabilities;
11449 protected $stabilityFlags;
11450 protected $versionParser;
11451 protected $providerCache = array();
11452 protected $filterRequires;
11453 protected $whitelist = null;
11454 protected $id = 1;
11455
11456 public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
11457 {
11458 $this->versionParser = new VersionParser;
11459 $this->acceptableStabilities = array();
11460 foreach (BasePackage::$stabilities as $stability => $value) {
11461 if ($value <= BasePackage::$stabilities[$minimumStability]) {
11462 $this->acceptableStabilities[$stability] = $value;
11463 }
11464 }
11465 $this->stabilityFlags = $stabilityFlags;
11466 $this->filterRequires = $filterRequires;
11467 foreach ($filterRequires as $name => $constraint) {
11468 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
11469 unset($this->filterRequires[$name]);
11470 }
11471 }
11472 }
11473
11474 public function setWhitelist($whitelist)
11475 {
11476 $this->whitelist = $whitelist;
11477 $this->providerCache = array();
11478 }
11479
11480
11481
11482
11483
11484
11485
11486 public function addRepository(RepositoryInterface $repo, $rootAliases = array())
11487 {
11488 if ($repo instanceof CompositeRepository) {
11489 $repos = $repo->getRepositories();
11490 } else {
11491 $repos = array($repo);
11492 }
11493
11494 foreach ($repos as $repo) {
11495 $this->repositories[] = $repo;
11496
11497 $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
11498
11499 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
11500 $this->providerRepos[] = $repo;
11501 $repo->setRootAliases($rootAliases);
11502 $repo->resetPackageIds();
11503 } else {
11504 foreach ($repo->getPackages() as $package) {
11505 $names = $package->getNames();
11506 $stability = $package->getStability();
11507 if ($exempt || $this->isPackageAcceptable($names, $stability)) {
11508 $package->setId($this->id++);
11509 $this->packages[] = $package;
11510 $this->packageByExactName[$package->getName()][$package->id] = $package;
11511
11512 foreach ($names as $provided) {
11513 $this->packageByName[$provided][] = $package;
11514 }
11515
11516
11517  $name = $package->getName();
11518 if (isset($rootAliases[$name][$package->getVersion()])) {
11519 $alias = $rootAliases[$name][$package->getVersion()];
11520 if ($package instanceof AliasPackage) {
11521 $package = $package->getAliasOf();
11522 }
11523 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
11524 $aliasPackage->setRootPackageAlias(true);
11525 $aliasPackage->setId($this->id++);
11526
11527 $package->getRepository()->addPackage($aliasPackage);
11528 $this->packages[] = $aliasPackage;
11529 $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
11530
11531 foreach ($aliasPackage->getNames() as $name) {
11532 $this->packageByName[$name][] = $aliasPackage;
11533 }
11534 }
11535 }
11536 }
11537 }
11538 }
11539 }
11540
11541 public function getPriority(RepositoryInterface $repo)
11542 {
11543 $priority = array_search($repo, $this->repositories, true);
11544
11545 if (false === $priority) {
11546 throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
11547 }
11548
11549 return -$priority;
11550 }
11551
11552
11553
11554
11555
11556
11557
11558 public function packageById($id)
11559 {
11560 return $this->packages[$id - 1];
11561 }
11562
11563
11564
11565
11566 public function count()
11567 {
11568 return count($this->packages);
11569 }
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582 public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
11583 {
11584 if ($bypassFilters) {
11585 return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
11586 }
11587
11588 $key = ((int) $mustMatchName).$constraint;
11589 if (isset($this->providerCache[$name][$key])) {
11590 return $this->providerCache[$name][$key];
11591 }
11592
11593 return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
11594 }
11595
11596
11597
11598
11599 private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
11600 {
11601 $candidates = array();
11602
11603 foreach ($this->providerRepos as $repo) {
11604 foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
11605 $candidates[] = $candidate;
11606 if ($candidate->id < 1) {
11607 $candidate->setId($this->id++);
11608 $this->packages[$this->id - 2] = $candidate;
11609 }
11610 }
11611 }
11612
11613 if ($mustMatchName) {
11614 $candidates = array_filter($candidates, function ($candidate) use ($name) {
11615 return $candidate->getName() == $name;
11616 });
11617 if (isset($this->packageByExactName[$name])) {
11618 $candidates = array_merge($candidates, $this->packageByExactName[$name]);
11619 }
11620 } elseif (isset($this->packageByName[$name])) {
11621 $candidates = array_merge($candidates, $this->packageByName[$name]);
11622 }
11623
11624 $matches = $provideMatches = array();
11625 $nameMatch = false;
11626
11627 foreach ($candidates as $candidate) {
11628 $aliasOfCandidate = null;
11629
11630
11631  
11632  if ($candidate instanceof AliasPackage) {
11633 $aliasOfCandidate = $candidate->getAliasOf();
11634 }
11635
11636 if ($this->whitelist !== null && !$bypassFilters && (
11637 (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
11638 ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
11639 )) {
11640 continue;
11641 }
11642 switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
11643 case self::MATCH_NONE:
11644 break;
11645
11646 case self::MATCH_NAME:
11647 $nameMatch = true;
11648 break;
11649
11650 case self::MATCH:
11651 $nameMatch = true;
11652 $matches[] = $candidate;
11653 break;
11654
11655 case self::MATCH_PROVIDE:
11656 $provideMatches[] = $candidate;
11657 break;
11658
11659 case self::MATCH_REPLACE:
11660 $matches[] = $candidate;
11661 break;
11662
11663 case self::MATCH_FILTERED:
11664 break;
11665
11666 default:
11667 throw new \UnexpectedValueException('Unexpected match type');
11668 }
11669 }
11670
11671
11672  if ($nameMatch) {
11673 return $matches;
11674 }
11675
11676 return array_merge($matches, $provideMatches);
11677 }
11678
11679 public function literalToPackage($literal)
11680 {
11681 $packageId = abs($literal);
11682
11683 return $this->packageById($packageId);
11684 }
11685
11686 public function literalToPrettyString($literal, $installedMap)
11687 {
11688 $package = $this->literalToPackage($literal);
11689
11690 if (isset($installedMap[$package->id])) {
11691 $prefix = ($literal > 0 ? 'keep' : 'remove');
11692 } else {
11693 $prefix = ($literal > 0 ? 'install' : 'don\'t install');
11694 }
11695
11696 return $prefix.' '.$package->getPrettyString();
11697 }
11698
11699 public function isPackageAcceptable($name, $stability)
11700 {
11701 foreach ((array) $name as $n) {
11702
11703  if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
11704 return true;
11705 }
11706
11707
11708  if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
11709 return true;
11710 }
11711 }
11712
11713 return false;
11714 }
11715
11716
11717
11718
11719
11720
11721
11722
11723
11724
11725 private function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
11726 {
11727 $candidateName = $candidate->getName();
11728 $candidateVersion = $candidate->getVersion();
11729 $isDev = $candidate->getStability() === 'dev';
11730 $isAlias = $candidate instanceof AliasPackage;
11731
11732 if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
11733 $requireFilter = $this->filterRequires[$name];
11734 } else {
11735 $requireFilter = new EmptyConstraint;
11736 }
11737
11738 if ($candidateName === $name) {
11739 $pkgConstraint = new Constraint('==', $candidateVersion);
11740
11741 if ($constraint === null || $constraint->matches($pkgConstraint)) {
11742 return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
11743 }
11744
11745 return self::MATCH_NAME;
11746 }
11747
11748 $provides = $candidate->getProvides();
11749 $replaces = $candidate->getReplaces();
11750
11751
11752  if (isset($replaces[0]) || isset($provides[0])) {
11753 foreach ($provides as $link) {
11754 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11755 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11756 }
11757 }
11758
11759 foreach ($replaces as $link) {
11760 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11761 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11762 }
11763 }
11764
11765 return self::MATCH_NONE;
11766 }
11767
11768 if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
11769 return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11770 }
11771
11772 if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
11773 return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11774 }
11775
11776 return self::MATCH_NONE;
11777 }
11778 }
11779 <?php
11780
11781
11782
11783
11784
11785
11786
11787
11788
11789
11790
11791 namespace Composer\DependencyResolver;
11792
11793 use Composer\Package\CompletePackageInterface;
11794
11795
11796
11797
11798
11799
11800 class Problem
11801 {
11802
11803
11804
11805
11806 protected $reasonSeen;
11807
11808
11809
11810
11811
11812 protected $reasons = array();
11813
11814 protected $section = 0;
11815
11816 protected $pool;
11817
11818 public function __construct(Pool $pool)
11819 {
11820 $this->pool = $pool;
11821 }
11822
11823
11824
11825
11826
11827
11828 public function addRule(Rule $rule)
11829 {
11830 $this->addReason(spl_object_hash($rule), array(
11831 'rule' => $rule,
11832 'job' => $rule->getJob(),
11833 ));
11834 }
11835
11836
11837
11838
11839
11840
11841 public function getReasons()
11842 {
11843 return $this->reasons;
11844 }
11845
11846
11847
11848
11849
11850
11851
11852 public function getPrettyString(array $installedMap = array())
11853 {
11854 $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
11855
11856 if (count($reasons) === 1) {
11857 reset($reasons);
11858 $reason = current($reasons);
11859
11860 $rule = $reason['rule'];
11861 $job = $reason['job'];
11862
11863 if (isset($job['constraint'])) {
11864 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11865 } else {
11866 $packages = array();
11867 }
11868
11869 if ($job && $job['cmd'] === 'install' && empty($packages)) {
11870
11871
11872  if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') {
11873 $version = phpversion();
11874 $available = $this->pool->whatProvides($job['packageName']);
11875
11876 if (count($available)) {
11877 $firstAvailable = reset($available);
11878 $version = $firstAvailable->getPrettyVersion();
11879 $extra = $firstAvailable->getExtra();
11880 if ($firstAvailable instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) {
11881 $version .= '; ' . $firstAvailable->getDescription();
11882 }
11883 }
11884
11885 $msg = "\n    - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but ';
11886
11887 if (defined('HHVM_VERSION')) {
11888 return $msg . 'your HHVM version does not satisfy that requirement.';
11889 }
11890
11891 if ($job['packageName'] === 'hhvm') {
11892 return $msg . 'you are running this with PHP and not HHVM.';
11893 }
11894
11895 return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
11896 }
11897
11898
11899  if (0 === stripos($job['packageName'], 'ext-')) {
11900 if (false !== strpos($job['packageName'], ' ')) {
11901 return "\n    - The requested PHP extension ".$job['packageName'].' should be required as '.str_replace(' ', '-', $job['packageName']).'.';
11902 }
11903
11904 $ext = substr($job['packageName'], 4);
11905 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
11906
11907 return "\n    - The requested PHP extension ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
11908 }
11909
11910
11911  if (0 === stripos($job['packageName'], 'lib-')) {
11912 if (strtolower($job['packageName']) === 'lib-icu') {
11913 $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.';
11914
11915 return "\n    - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error;
11916 }
11917
11918 return "\n    - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.';
11919 }
11920
11921 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $job['packageName'])) {
11922 $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $job['packageName']);
11923
11924 return "\n    - The requested package ".$job['packageName'].' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
11925 }
11926
11927 if ($providers = $this->pool->whatProvides($job['packageName'], $job['constraint'], true, true)) {
11928 return "\n    - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.';
11929 }
11930
11931 if ($providers = $this->pool->whatProvides($job['packageName'], null, true, true)) {
11932 return "\n    - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
11933 }
11934
11935 return "\n    - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.';
11936 }
11937 }
11938
11939 $messages = array();
11940
11941 foreach ($reasons as $reason) {
11942 $rule = $reason['rule'];
11943 $job = $reason['job'];
11944
11945 if ($job) {
11946 $messages[] = $this->jobToText($job);
11947 } elseif ($rule) {
11948 if ($rule instanceof Rule) {
11949 $messages[] = $rule->getPrettyString($this->pool, $installedMap);
11950 }
11951 }
11952 }
11953
11954 return "\n    - ".implode("\n    - ", $messages);
11955 }
11956
11957
11958
11959
11960
11961
11962
11963 protected function addReason($id, $reason)
11964 {
11965 if (!isset($this->reasonSeen[$id])) {
11966 $this->reasonSeen[$id] = true;
11967 $this->reasons[$this->section][] = $reason;
11968 }
11969 }
11970
11971 public function nextSection()
11972 {
11973 $this->section++;
11974 }
11975
11976
11977
11978
11979
11980
11981
11982 protected function jobToText($job)
11983 {
11984 switch ($job['cmd']) {
11985 case 'install':
11986 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11987 if (!$packages) {
11988 return 'No package found to satisfy install request for '.$job['packageName'].$this->constraintToText($job['constraint']);
11989 }
11990
11991 return 'Installation request for '.$job['packageName'].$this->constraintToText($job['constraint']).' -> satisfiable by '.$this->getPackageList($packages).'.';
11992 case 'update':
11993 return 'Update request for '.$job['packageName'].$this->constraintToText($job['constraint']).'.';
11994 case 'remove':
11995 return 'Removal request for '.$job['packageName'].$this->constraintToText($job['constraint']).'';
11996 }
11997
11998 if (isset($job['constraint'])) {
11999 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12000 } else {
12001 $packages = array();
12002 }
12003
12004 return 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.$this->getPackageList($packages).'])';
12005 }
12006
12007 protected function getPackageList($packages)
12008 {
12009 $prepared = array();
12010 foreach ($packages as $package) {
12011 $prepared[$package->getName()]['name'] = $package->getPrettyName();
12012 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
12013 }
12014 foreach ($prepared as $name => $package) {
12015 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
12016 }
12017
12018 return implode(', ', $prepared);
12019 }
12020
12021
12022
12023
12024
12025
12026
12027 protected function constraintToText($constraint)
12028 {
12029 return $constraint ? ' '.$constraint->getPrettyString() : '';
12030 }
12031 }
12032 <?php
12033
12034
12035
12036
12037
12038
12039
12040
12041
12042
12043
12044 namespace Composer\DependencyResolver;
12045
12046 use Composer\Semver\Constraint\ConstraintInterface;
12047
12048
12049
12050
12051 class Request
12052 {
12053 protected $jobs;
12054
12055 public function __construct()
12056 {
12057 $this->jobs = array();
12058 }
12059
12060 public function install($packageName, ConstraintInterface $constraint = null)
12061 {
12062 $this->addJob($packageName, 'install', $constraint);
12063 }
12064
12065 public function update($packageName, ConstraintInterface $constraint = null)
12066 {
12067 $this->addJob($packageName, 'update', $constraint);
12068 }
12069
12070 public function remove($packageName, ConstraintInterface $constraint = null)
12071 {
12072 $this->addJob($packageName, 'remove', $constraint);
12073 }
12074
12075
12076
12077
12078
12079
12080
12081
12082
12083 public function fix($packageName, ConstraintInterface $constraint = null)
12084 {
12085 $this->addJob($packageName, 'install', $constraint, true);
12086 }
12087
12088 protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
12089 {
12090 $packageName = strtolower($packageName);
12091
12092 $this->jobs[] = array(
12093 'cmd' => $cmd,
12094 'packageName' => $packageName,
12095 'constraint' => $constraint,
12096 'fixed' => $fixed,
12097 );
12098 }
12099
12100 public function updateAll()
12101 {
12102 $this->jobs[] = array('cmd' => 'update-all');
12103 }
12104
12105 public function getJobs()
12106 {
12107 return $this->jobs;
12108 }
12109 }
12110 <?php
12111
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121
12122 namespace Composer\DependencyResolver;
12123
12124 use Composer\Package\CompletePackage;
12125 use Composer\Package\Link;
12126 use Composer\Package\PackageInterface;
12127
12128
12129
12130
12131
12132 abstract class Rule
12133 {
12134
12135  const RULE_INTERNAL_ALLOW_UPDATE = 1;
12136 const RULE_JOB_INSTALL = 2;
12137 const RULE_JOB_REMOVE = 3;
12138 const RULE_PACKAGE_CONFLICT = 6;
12139 const RULE_PACKAGE_REQUIRES = 7;
12140 const RULE_PACKAGE_OBSOLETES = 8;
12141 const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
12142 const RULE_PACKAGE_SAME_NAME = 10;
12143 const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
12144 const RULE_LEARNED = 12;
12145 const RULE_PACKAGE_ALIAS = 13;
12146
12147
12148  const BITFIELD_TYPE = 0;
12149 const BITFIELD_REASON = 8;
12150 const BITFIELD_DISABLED = 16;
12151
12152 protected $bitfield;
12153 protected $job;
12154 protected $reasonData;
12155
12156
12157
12158
12159
12160
12161 public function __construct($reason, $reasonData, $job = null)
12162 {
12163 $this->reasonData = $reasonData;
12164
12165 if ($job) {
12166 $this->job = $job;
12167 }
12168
12169 $this->bitfield = (0 << self::BITFIELD_DISABLED) |
12170 ($reason << self::BITFIELD_REASON) |
12171 (255 << self::BITFIELD_TYPE);
12172 }
12173
12174 abstract public function getLiterals();
12175
12176 abstract public function getHash();
12177
12178 public function getJob()
12179 {
12180 return $this->job;
12181 }
12182
12183 abstract public function equals(Rule $rule);
12184
12185 public function getReason()
12186 {
12187 return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
12188 }
12189
12190 public function getReasonData()
12191 {
12192 return $this->reasonData;
12193 }
12194
12195 public function getRequiredPackage()
12196 {
12197 if ($this->getReason() === self::RULE_JOB_INSTALL) {
12198 return $this->reasonData;
12199 }
12200
12201 if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
12202 return $this->reasonData->getTarget();
12203 }
12204 }
12205
12206 public function setType($type)
12207 {
12208 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
12209 }
12210
12211 public function getType()
12212 {
12213 return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
12214 }
12215
12216 public function disable()
12217 {
12218 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
12219 }
12220
12221 public function enable()
12222 {
12223 $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED);
12224 }
12225
12226 public function isDisabled()
12227 {
12228 return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
12229 }
12230
12231 public function isEnabled()
12232 {
12233 return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
12234 }
12235
12236 abstract public function isAssertion();
12237
12238 public function getPrettyString(Pool $pool, array $installedMap = array())
12239 {
12240 $literals = $this->getLiterals();
12241
12242 $ruleText = '';
12243 foreach ($literals as $i => $literal) {
12244 if ($i != 0) {
12245 $ruleText .= '|';
12246 }
12247 $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
12248 }
12249
12250 switch ($this->getReason()) {
12251 case self::RULE_INTERNAL_ALLOW_UPDATE:
12252 return $ruleText;
12253
12254 case self::RULE_JOB_INSTALL:
12255 return "Install command rule ($ruleText)";
12256
12257 case self::RULE_JOB_REMOVE:
12258 return "Remove command rule ($ruleText)";
12259
12260 case self::RULE_PACKAGE_CONFLICT:
12261 $package1 = $pool->literalToPackage($literals[0]);
12262 $package2 = $pool->literalToPackage($literals[1]);
12263
12264 return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
12265
12266 case self::RULE_PACKAGE_REQUIRES:
12267 $sourceLiteral = array_shift($literals);
12268 $sourcePackage = $pool->literalToPackage($sourceLiteral);
12269
12270 $requires = array();
12271 foreach ($literals as $literal) {
12272 $requires[] = $pool->literalToPackage($literal);
12273 }
12274
12275 $text = $this->reasonData->getPrettyString($sourcePackage);
12276 if ($requires) {
12277 $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
12278 } else {
12279 $targetName = $this->reasonData->getTarget();
12280
12281 if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
12282
12283  if (defined('HHVM_VERSION')) {
12284 return $text . ' -> your HHVM version does not satisfy that requirement.';
12285 }
12286
12287 if ($targetName === 'hhvm') {
12288 return $text . ' -> you are running this with PHP and not HHVM.';
12289 }
12290
12291 $packages = $pool->whatProvides($targetName);
12292 $package = count($packages) ? current($packages) : phpversion();
12293
12294 if (!($package instanceof CompletePackage)) {
12295 return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
12296 }
12297
12298 $extra = $package->getExtra();
12299
12300 if (!empty($extra['config.platform'])) {
12301 $text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
12302 } else {
12303 $text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
12304 }
12305
12306 return $text;
12307 }
12308
12309 if (0 === strpos($targetName, 'ext-')) {
12310
12311  $ext = substr($targetName, 4);
12312 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
12313
12314 return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
12315 }
12316
12317 if (0 === strpos($targetName, 'lib-')) {
12318
12319  $lib = substr($targetName, 4);
12320
12321 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.';
12322 }
12323
12324 if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
12325 return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
12326 }
12327
12328 return $text . ' -> no matching package found.';
12329 }
12330
12331 return $text;
12332
12333 case self::RULE_PACKAGE_OBSOLETES:
12334 return $ruleText;
12335 case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
12336 return $ruleText;
12337 case self::RULE_PACKAGE_SAME_NAME:
12338 return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $literals) . '.';
12339 case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
12340 return $ruleText;
12341 case self::RULE_LEARNED:
12342 return 'Conclusion: '.$ruleText;
12343 case self::RULE_PACKAGE_ALIAS:
12344 return $ruleText;
12345 default:
12346 return '('.$ruleText.')';
12347 }
12348 }
12349
12350
12351
12352
12353
12354
12355
12356 protected function formatPackagesUnique($pool, array $packages)
12357 {
12358 $prepared = array();
12359 foreach ($packages as $package) {
12360 if (!is_object($package)) {
12361 $package = $pool->literalToPackage($package);
12362 }
12363 $prepared[$package->getName()]['name'] = $package->getPrettyName();
12364 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
12365 }
12366 foreach ($prepared as $name => $package) {
12367 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
12368 }
12369
12370 return implode(', ', $prepared);
12371 }
12372 }
12373 <?php
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385 namespace Composer\DependencyResolver;
12386
12387 use Composer\Package\PackageInterface;
12388 use Composer\Package\Link;
12389
12390
12391
12392
12393 class Rule2Literals extends Rule
12394 {
12395 protected $literal1;
12396 protected $literal2;
12397
12398
12399
12400
12401
12402
12403
12404
12405 public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
12406 {
12407 parent::__construct($reason, $reasonData, $job);
12408
12409 if ($literal1 < $literal2) {
12410 $this->literal1 = $literal1;
12411 $this->literal2 = $literal2;
12412 } else {
12413 $this->literal1 = $literal2;
12414 $this->literal2 = $literal1;
12415 }
12416 }
12417
12418 public function getLiterals()
12419 {
12420 return array($this->literal1, $this->literal2);
12421 }
12422
12423 public function getHash()
12424 {
12425 return $this->literal1.','.$this->literal2;
12426 }
12427
12428
12429
12430
12431
12432
12433
12434
12435
12436 public function equals(Rule $rule)
12437 {
12438
12439  if ($rule instanceof self) {
12440 if ($this->literal1 !== $rule->literal1) {
12441 return false;
12442 }
12443
12444 if ($this->literal2 !== $rule->literal2) {
12445 return false;
12446 }
12447
12448 return true;
12449 }
12450
12451 $literals = $rule->getLiterals();
12452 if (2 != count($literals)) {
12453 return false;
12454 }
12455
12456 if ($this->literal1 !== $literals[0]) {
12457 return false;
12458 }
12459
12460 if ($this->literal2 !== $literals[1]) {
12461 return false;
12462 }
12463
12464 return true;
12465 }
12466
12467 public function isAssertion()
12468 {
12469 return false;
12470 }
12471
12472
12473
12474
12475
12476
12477 public function __toString()
12478 {
12479 $result = $this->isDisabled() ? 'disabled(' : '(';
12480
12481 $result .= $this->literal1 . '|' . $this->literal2 . ')';
12482
12483 return $result;
12484 }
12485 }
12486 <?php
12487
12488
12489
12490
12491
12492
12493
12494
12495
12496
12497
12498 namespace Composer\DependencyResolver;
12499
12500
12501
12502
12503 class RuleSet implements \IteratorAggregate, \Countable
12504 {
12505
12506  const TYPE_PACKAGE = 0;
12507 const TYPE_JOB = 1;
12508 const TYPE_LEARNED = 4;
12509
12510
12511
12512
12513
12514
12515 public $ruleById;
12516
12517 protected static $types = array(
12518 255 => 'UNKNOWN',
12519 self::TYPE_PACKAGE => 'PACKAGE',
12520 self::TYPE_JOB => 'JOB',
12521 self::TYPE_LEARNED => 'LEARNED',
12522 );
12523
12524 protected $rules;
12525 protected $nextRuleId;
12526
12527 protected $rulesByHash;
12528
12529 public function __construct()
12530 {
12531 $this->nextRuleId = 0;
12532
12533 foreach ($this->getTypes() as $type) {
12534 $this->rules[$type] = array();
12535 }
12536
12537 $this->rulesByHash = array();
12538 }
12539
12540 public function add(Rule $rule, $type)
12541 {
12542 if (!isset(self::$types[$type])) {
12543 throw new \OutOfBoundsException('Unknown rule type: ' . $type);
12544 }
12545
12546 $hash = $rule->getHash();
12547
12548
12549  if (isset($this->rulesByHash[$hash])) {
12550 $potentialDuplicates = $this->rulesByHash[$hash];
12551 if (is_array($potentialDuplicates)) {
12552 foreach ($potentialDuplicates as $potentialDuplicate) {
12553 if ($rule->equals($potentialDuplicate)) {
12554 return;
12555 }
12556 }
12557 } else {
12558 if ($rule->equals($potentialDuplicates)) {
12559 return;
12560 }
12561 }
12562 }
12563
12564 if (!isset($this->rules[$type])) {
12565 $this->rules[$type] = array();
12566 }
12567
12568 $this->rules[$type][] = $rule;
12569 $this->ruleById[$this->nextRuleId] = $rule;
12570 $rule->setType($type);
12571
12572 $this->nextRuleId++;
12573
12574 if (!isset($this->rulesByHash[$hash])) {
12575 $this->rulesByHash[$hash] = $rule;
12576 } elseif (is_array($this->rulesByHash[$hash])) {
12577 $this->rulesByHash[$hash][] = $rule;
12578 } else {
12579 $originalRule = $this->rulesByHash[$hash];
12580 $this->rulesByHash[$hash] = array($originalRule, $rule);
12581 }
12582 }
12583
12584 public function count()
12585 {
12586 return $this->nextRuleId;
12587 }
12588
12589 public function ruleById($id)
12590 {
12591 return $this->ruleById[$id];
12592 }
12593
12594 public function getRules()
12595 {
12596 return $this->rules;
12597 }
12598
12599 public function getIterator()
12600 {
12601 return new RuleSetIterator($this->getRules());
12602 }
12603
12604 public function getIteratorFor($types)
12605 {
12606 if (!is_array($types)) {
12607 $types = array($types);
12608 }
12609
12610 $allRules = $this->getRules();
12611 $rules = array();
12612
12613 foreach ($types as $type) {
12614 $rules[$type] = $allRules[$type];
12615 }
12616
12617 return new RuleSetIterator($rules);
12618 }
12619
12620 public function getIteratorWithout($types)
12621 {
12622 if (!is_array($types)) {
12623 $types = array($types);
12624 }
12625
12626 $rules = $this->getRules();
12627
12628 foreach ($types as $type) {
12629 unset($rules[$type]);
12630 }
12631
12632 return new RuleSetIterator($rules);
12633 }
12634
12635 public function getTypes()
12636 {
12637 $types = self::$types;
12638 unset($types[255]);
12639
12640 return array_keys($types);
12641 }
12642
12643 public function getPrettyString(Pool $pool = null)
12644 {
12645 $string = "\n";
12646 foreach ($this->rules as $type => $rules) {
12647 $string .= str_pad(self::$types[$type], 8, ' ') . ": ";
12648 foreach ($rules as $rule) {
12649 $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
12650 }
12651 $string .= "\n\n";
12652 }
12653
12654 return $string;
12655 }
12656
12657 public function __toString()
12658 {
12659 return $this->getPrettyString(null);
12660 }
12661 }
12662 <?php
12663
12664
12665
12666
12667
12668
12669
12670
12671
12672
12673
12674 namespace Composer\DependencyResolver;
12675
12676 use Composer\Package\PackageInterface;
12677 use Composer\Package\AliasPackage;
12678 use Composer\Repository\PlatformRepository;
12679
12680
12681
12682
12683 class RuleSetGenerator
12684 {
12685 protected $policy;
12686 protected $pool;
12687 protected $rules;
12688 protected $jobs;
12689 protected $installedMap;
12690 protected $whitelistedMap;
12691 protected $addedMap;
12692
12693 public function __construct(PolicyInterface $policy, Pool $pool)
12694 {
12695 $this->policy = $policy;
12696 $this->pool = $pool;
12697 }
12698
12699
12700
12701
12702
12703
12704
12705
12706
12707
12708
12709
12710
12711
12712
12713 protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
12714 {
12715 $literals = array(-$package->id);
12716
12717 foreach ($providers as $provider) {
12718
12719  if ($provider === $package) {
12720 return null;
12721 }
12722 $literals[] = $provider->id;
12723 }
12724
12725 return new GenericRule($literals, $reason, $reasonData);
12726 }
12727
12728
12729
12730
12731
12732
12733
12734
12735
12736
12737
12738
12739
12740 protected function createInstallOneOfRule(array $packages, $reason, $job)
12741 {
12742 $literals = array();
12743 foreach ($packages as $package) {
12744 $literals[] = $package->id;
12745 }
12746
12747 return new GenericRule($literals, $reason, $job['packageName'], $job);
12748 }
12749
12750
12751
12752
12753
12754
12755
12756
12757
12758
12759
12760
12761 protected function createRemoveRule(PackageInterface $package, $reason, $job)
12762 {
12763 return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
12764 }
12765
12766
12767
12768
12769
12770
12771
12772
12773
12774
12775
12776
12777
12778
12779
12780 protected function createRule2Literals(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
12781 {
12782
12783  if ($issuer === $provider) {
12784 return null;
12785 }
12786
12787 return new Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
12788 }
12789
12790
12791
12792
12793
12794
12795
12796
12797
12798
12799 private function addRule($type, Rule $newRule = null)
12800 {
12801 if (!$newRule) {
12802 return;
12803 }
12804
12805 $this->rules->add($newRule, $type);
12806 }
12807
12808 protected function whitelistFromPackage(PackageInterface $package)
12809 {
12810 $workQueue = new \SplQueue;
12811 $workQueue->enqueue($package);
12812
12813 while (!$workQueue->isEmpty()) {
12814 $package = $workQueue->dequeue();
12815 if (isset($this->whitelistedMap[$package->id])) {
12816 continue;
12817 }
12818
12819 $this->whitelistedMap[$package->id] = true;
12820
12821 foreach ($package->getRequires() as $link) {
12822 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
12823
12824 foreach ($possibleRequires as $require) {
12825 $workQueue->enqueue($require);
12826 }
12827 }
12828
12829 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
12830
12831 foreach ($obsoleteProviders as $provider) {
12832 if ($provider === $package) {
12833 continue;
12834 }
12835
12836 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12837 $workQueue->enqueue($provider);
12838 }
12839 }
12840 }
12841 }
12842
12843 protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
12844 {
12845 $workQueue = new \SplQueue;
12846 $workQueue->enqueue($package);
12847
12848 while (!$workQueue->isEmpty()) {
12849 $package = $workQueue->dequeue();
12850 if (isset($this->addedMap[$package->id])) {
12851 continue;
12852 }
12853
12854 $this->addedMap[$package->id] = true;
12855
12856 foreach ($package->getRequires() as $link) {
12857 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
12858 continue;
12859 }
12860
12861 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12862
12863 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
12864
12865 foreach ($possibleRequires as $require) {
12866 $workQueue->enqueue($require);
12867 }
12868 }
12869
12870 foreach ($package->getConflicts() as $link) {
12871 $possibleConflicts = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12872
12873 foreach ($possibleConflicts as $conflict) {
12874 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $conflict, Rule::RULE_PACKAGE_CONFLICT, $link));
12875 }
12876 }
12877
12878
12879  $isInstalled = isset($this->installedMap[$package->id]);
12880
12881 foreach ($package->getReplaces() as $link) {
12882 $obsoleteProviders = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12883
12884 foreach ($obsoleteProviders as $provider) {
12885 if ($provider === $package) {
12886 continue;
12887 }
12888
12889 if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12890 $reason = $isInstalled ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
12891 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $link));
12892 }
12893 }
12894 }
12895
12896 $packageName = $package->getName();
12897 $obsoleteProviders = $this->pool->whatProvides($packageName, null);
12898
12899 foreach ($obsoleteProviders as $provider) {
12900 if ($provider === $package) {
12901 continue;
12902 }
12903
12904 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12905 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
12906 } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12907 $reason = ($packageName == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
12908 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $package));
12909 }
12910 }
12911 }
12912 }
12913
12914 protected function obsoleteImpossibleForAlias($package, $provider)
12915 {
12916 $packageIsAlias = $package instanceof AliasPackage;
12917 $providerIsAlias = $provider instanceof AliasPackage;
12918
12919 $impossible = (
12920 ($packageIsAlias && $package->getAliasOf() === $provider) ||
12921 ($providerIsAlias && $provider->getAliasOf() === $package) ||
12922 ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
12923 );
12924
12925 return $impossible;
12926 }
12927
12928 protected function whitelistFromJobs()
12929 {
12930 foreach ($this->jobs as $job) {
12931 switch ($job['cmd']) {
12932 case 'install':
12933 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
12934 foreach ($packages as $package) {
12935 $this->whitelistFromPackage($package);
12936 }
12937 break;
12938 }
12939 }
12940 }
12941
12942 protected function addRulesForJobs($ignorePlatformReqs)
12943 {
12944 foreach ($this->jobs as $job) {
12945 switch ($job['cmd']) {
12946 case 'install':
12947 if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
12948 break;
12949 }
12950
12951 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12952 if ($packages) {
12953 foreach ($packages as $package) {
12954 if (!isset($this->installedMap[$package->id])) {
12955 $this->addRulesForPackage($package, $ignorePlatformReqs);
12956 }
12957 }
12958
12959 $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
12960 $this->addRule(RuleSet::TYPE_JOB, $rule);
12961 }
12962 break;
12963 case 'remove':
12964
12965  
12966  $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12967 foreach ($packages as $package) {
12968 $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
12969 $this->addRule(RuleSet::TYPE_JOB, $rule);
12970 }
12971 break;
12972 }
12973 }
12974 }
12975
12976 public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
12977 {
12978 $this->jobs = $jobs;
12979 $this->rules = new RuleSet;
12980 $this->installedMap = $installedMap;
12981
12982 $this->whitelistedMap = array();
12983 foreach ($this->installedMap as $package) {
12984 $this->whitelistFromPackage($package);
12985 }
12986 $this->whitelistFromJobs();
12987
12988 $this->pool->setWhitelist($this->whitelistedMap);
12989
12990 $this->addedMap = array();
12991 foreach ($this->installedMap as $package) {
12992 $this->addRulesForPackage($package, $ignorePlatformReqs);
12993 }
12994
12995 $this->addRulesForJobs($ignorePlatformReqs);
12996
12997 return $this->rules;
12998 }
12999 }
13000 <?php
13001
13002
13003
13004
13005
13006
13007
13008
13009
13010
13011
13012 namespace Composer\DependencyResolver;
13013
13014
13015
13016
13017 class RuleSetIterator implements \Iterator
13018 {
13019 protected $rules;
13020 protected $types;
13021
13022 protected $currentOffset;
13023 protected $currentType;
13024 protected $currentTypeOffset;
13025
13026 public function __construct(array $rules)
13027 {
13028 $this->rules = $rules;
13029 $this->types = array_keys($rules);
13030 sort($this->types);
13031
13032 $this->rewind();
13033 }
13034
13035 public function current()
13036 {
13037 return $this->rules[$this->currentType][$this->currentOffset];
13038 }
13039
13040 public function key()
13041 {
13042 return $this->currentType;
13043 }
13044
13045 public function next()
13046 {
13047 $this->currentOffset++;
13048
13049 if (!isset($this->rules[$this->currentType])) {
13050 return;
13051 }
13052
13053 if ($this->currentOffset >= count($this->rules[$this->currentType])) {
13054 $this->currentOffset = 0;
13055
13056 do {
13057 $this->currentTypeOffset++;
13058
13059 if (!isset($this->types[$this->currentTypeOffset])) {
13060 $this->currentType = -1;
13061 break;
13062 }
13063
13064 $this->currentType = $this->types[$this->currentTypeOffset];
13065 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
13066 }
13067 }
13068
13069 public function rewind()
13070 {
13071 $this->currentOffset = 0;
13072
13073 $this->currentTypeOffset = -1;
13074 $this->currentType = -1;
13075
13076 do {
13077 $this->currentTypeOffset++;
13078
13079 if (!isset($this->types[$this->currentTypeOffset])) {
13080 $this->currentType = -1;
13081 break;
13082 }
13083
13084 $this->currentType = $this->types[$this->currentTypeOffset];
13085 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
13086 }
13087
13088 public function valid()
13089 {
13090 return isset($this->rules[$this->currentType])
13091 && isset($this->rules[$this->currentType][$this->currentOffset]);
13092 }
13093 }
13094 <?php
13095
13096
13097
13098
13099
13100
13101
13102
13103
13104
13105
13106 namespace Composer\DependencyResolver;
13107
13108
13109
13110
13111
13112
13113
13114
13115
13116 class RuleWatchChain extends \SplDoublyLinkedList
13117 {
13118 protected $offset = 0;
13119
13120
13121
13122
13123
13124
13125 public function seek($offset)
13126 {
13127 $this->rewind();
13128 for ($i = 0; $i < $offset; $i++, $this->next());
13129 }
13130
13131
13132
13133
13134
13135
13136
13137
13138
13139 public function remove()
13140 {
13141 $offset = $this->key();
13142 $this->offsetUnset($offset);
13143 $this->seek($offset);
13144 }
13145 }
13146 <?php
13147
13148
13149
13150
13151
13152
13153
13154
13155
13156
13157
13158 namespace Composer\DependencyResolver;
13159
13160
13161
13162
13163
13164
13165
13166
13167
13168
13169
13170 class RuleWatchGraph
13171 {
13172 protected $watchChains = array();
13173
13174
13175
13176
13177
13178
13179
13180
13181
13182
13183
13184
13185
13186 public function insert(RuleWatchNode $node)
13187 {
13188 if ($node->getRule()->isAssertion()) {
13189 return;
13190 }
13191
13192 foreach (array($node->watch1, $node->watch2) as $literal) {
13193 if (!isset($this->watchChains[$literal])) {
13194 $this->watchChains[$literal] = new RuleWatchChain;
13195 }
13196
13197 $this->watchChains[$literal]->unshift($node);
13198 }
13199 }
13200
13201
13202
13203
13204
13205
13206
13207
13208
13209
13210
13211
13212
13213
13214
13215
13216
13217
13218
13219
13220
13221
13222
13223
13224 public function propagateLiteral($decidedLiteral, $level, $decisions)
13225 {
13226
13227  
13228  
13229  $literal = -$decidedLiteral;
13230
13231 if (!isset($this->watchChains[$literal])) {
13232 return null;
13233 }
13234
13235 $chain = $this->watchChains[$literal];
13236
13237 $chain->rewind();
13238 while ($chain->valid()) {
13239 $node = $chain->current();
13240 $otherWatch = $node->getOtherWatch($literal);
13241
13242 if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
13243 $ruleLiterals = $node->getRule()->getLiterals();
13244
13245 $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
13246 return $literal !== $ruleLiteral &&
13247 $otherWatch !== $ruleLiteral &&
13248 !$decisions->conflict($ruleLiteral);
13249 });
13250
13251 if ($alternativeLiterals) {
13252 reset($alternativeLiterals);
13253 $this->moveWatch($literal, current($alternativeLiterals), $node);
13254 continue;
13255 }
13256
13257 if ($decisions->conflict($otherWatch)) {
13258 return $node->getRule();
13259 }
13260
13261 $decisions->decide($otherWatch, $level, $node->getRule());
13262 }
13263
13264 $chain->next();
13265 }
13266
13267 return null;
13268 }
13269
13270
13271
13272
13273
13274
13275
13276
13277
13278
13279 protected function moveWatch($fromLiteral, $toLiteral, $node)
13280 {
13281 if (!isset($this->watchChains[$toLiteral])) {
13282 $this->watchChains[$toLiteral] = new RuleWatchChain;
13283 }
13284
13285 $node->moveWatch($fromLiteral, $toLiteral);
13286 $this->watchChains[$fromLiteral]->remove();
13287 $this->watchChains[$toLiteral]->unshift($node);
13288 }
13289 }
13290 <?php
13291
13292
13293
13294
13295
13296
13297
13298
13299
13300
13301
13302 namespace Composer\DependencyResolver;
13303
13304
13305
13306
13307
13308
13309
13310
13311 class RuleWatchNode
13312 {
13313 public $watch1;
13314 public $watch2;
13315
13316 protected $rule;
13317
13318
13319
13320
13321
13322
13323 public function __construct($rule)
13324 {
13325 $this->rule = $rule;
13326
13327 $literals = $rule->getLiterals();
13328
13329 $literalCount = count($literals);
13330 $this->watch1 = $literalCount > 0 ? $literals[0] : 0;
13331 $this->watch2 = $literalCount > 1 ? $literals[1] : 0;
13332 }
13333
13334
13335
13336
13337
13338
13339
13340
13341
13342 public function watch2OnHighest(Decisions $decisions)
13343 {
13344 $literals = $this->rule->getLiterals();
13345
13346
13347  if (count($literals) < 3) {
13348 return;
13349 }
13350
13351 $watchLevel = 0;
13352
13353 foreach ($literals as $literal) {
13354 $level = $decisions->decisionLevel($literal);
13355
13356 if ($level > $watchLevel) {
13357 $this->watch2 = $literal;
13358 $watchLevel = $level;
13359 }
13360 }
13361 }
13362
13363
13364
13365
13366
13367
13368 public function getRule()
13369 {
13370 return $this->rule;
13371 }
13372
13373
13374
13375
13376
13377
13378
13379 public function getOtherWatch($literal)
13380 {
13381 if ($this->watch1 == $literal) {
13382 return $this->watch2;
13383 }
13384
13385 return $this->watch1;
13386 }
13387
13388
13389
13390
13391
13392
13393
13394 public function moveWatch($from, $to)
13395 {
13396 if ($this->watch1 == $from) {
13397 $this->watch1 = $to;
13398 } else {
13399 $this->watch2 = $to;
13400 }
13401 }
13402 }
13403 <?php
13404
13405
13406
13407
13408
13409
13410
13411
13412
13413
13414
13415 namespace Composer\DependencyResolver;
13416
13417 use Composer\IO\IOInterface;
13418 use Composer\Repository\RepositoryInterface;
13419 use Composer\Repository\PlatformRepository;
13420
13421
13422
13423
13424 class Solver
13425 {
13426 const BRANCH_LITERALS = 0;
13427 const BRANCH_LEVEL = 1;
13428
13429
13430 protected $policy;
13431
13432 protected $pool;
13433
13434 protected $installed;
13435
13436 protected $rules;
13437
13438 protected $ruleSetGenerator;
13439
13440 protected $jobs;
13441
13442
13443 protected $updateMap = array();
13444
13445 protected $watchGraph;
13446
13447 protected $decisions;
13448
13449 protected $installedMap;
13450
13451
13452 protected $propagateIndex;
13453
13454 protected $branches = array();
13455
13456 protected $problems = array();
13457
13458 protected $learnedPool = array();
13459
13460 protected $learnedWhy = array();
13461
13462
13463 protected $io;
13464
13465
13466
13467
13468
13469
13470
13471 public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
13472 {
13473 $this->io = $io;
13474 $this->policy = $policy;
13475 $this->pool = $pool;
13476 $this->installed = $installed;
13477 $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
13478 }
13479
13480
13481
13482
13483 public function getRuleSetSize()
13484 {
13485 return count($this->rules);
13486 }
13487
13488
13489
13490 private function makeAssertionRuleDecisions()
13491 {
13492 $decisionStart = count($this->decisions) - 1;
13493
13494 $rulesCount = count($this->rules);
13495 for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
13496 $rule = $this->rules->ruleById[$ruleIndex];
13497
13498 if (!$rule->isAssertion() || $rule->isDisabled()) {
13499 continue;
13500 }
13501
13502 $literals = $rule->getLiterals();
13503 $literal = $literals[0];
13504
13505 if (!$this->decisions->decided($literal)) {
13506 $this->decisions->decide($literal, 1, $rule);
13507 continue;
13508 }
13509
13510 if ($this->decisions->satisfy($literal)) {
13511 continue;
13512 }
13513
13514
13515  if (RuleSet::TYPE_LEARNED === $rule->getType()) {
13516 $rule->disable();
13517 continue;
13518 }
13519
13520 $conflict = $this->decisions->decisionRule($literal);
13521
13522 if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
13523 $problem = new Problem($this->pool);
13524
13525 $problem->addRule($rule);
13526 $problem->addRule($conflict);
13527 $this->disableProblem($rule);
13528 $this->problems[] = $problem;
13529 continue;
13530 }
13531
13532
13533  $problem = new Problem($this->pool);
13534 $problem->addRule($rule);
13535 $problem->addRule($conflict);
13536
13537
13538  
13539  foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
13540 if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
13541 continue;
13542 }
13543
13544 $assertRuleLiterals = $assertRule->getLiterals();
13545 $assertRuleLiteral = $assertRuleLiterals[0];
13546
13547 if (abs($literal) !== abs($assertRuleLiteral)) {
13548 continue;
13549 }
13550
13551 $problem->addRule($assertRule);
13552 $this->disableProblem($assertRule);
13553 }
13554 $this->problems[] = $problem;
13555
13556 $this->decisions->resetToOffset($decisionStart);
13557 $ruleIndex = -1;
13558 }
13559 }
13560
13561 protected function setupInstalledMap()
13562 {
13563 $this->installedMap = array();
13564 foreach ($this->installed->getPackages() as $package) {
13565 $this->installedMap[$package->id] = $package;
13566 }
13567 }
13568
13569
13570
13571
13572 protected function checkForRootRequireProblems($ignorePlatformReqs)
13573 {
13574 foreach ($this->jobs as $job) {
13575 switch ($job['cmd']) {
13576 case 'update':
13577 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
13578 foreach ($packages as $package) {
13579 if (isset($this->installedMap[$package->id])) {
13580 $this->updateMap[$package->id] = true;
13581 }
13582 }
13583 break;
13584
13585 case 'update-all':
13586 foreach ($this->installedMap as $package) {
13587 $this->updateMap[$package->id] = true;
13588 }
13589 break;
13590
13591 case 'install':
13592 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
13593 break;
13594 }
13595
13596 if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
13597 $problem = new Problem($this->pool);
13598 $problem->addRule(new GenericRule(array(), null, null, $job));
13599 $this->problems[] = $problem;
13600 }
13601 break;
13602 }
13603 }
13604 }
13605
13606
13607
13608
13609
13610
13611 public function solve(Request $request, $ignorePlatformReqs = false)
13612 {
13613 $this->jobs = $request->getJobs();
13614
13615 $this->setupInstalledMap();
13616 $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
13617 $this->checkForRootRequireProblems($ignorePlatformReqs);
13618 $this->decisions = new Decisions($this->pool);
13619 $this->watchGraph = new RuleWatchGraph;
13620
13621 foreach ($this->rules as $rule) {
13622 $this->watchGraph->insert(new RuleWatchNode($rule));
13623 }
13624
13625
13626 $this->makeAssertionRuleDecisions();
13627
13628 $this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
13629 $before = microtime(true);
13630 $this->runSat(true);
13631 $this->io->writeError('', true, IOInterface::DEBUG);
13632 $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
13633
13634
13635  foreach ($this->installedMap as $packageId => $void) {
13636 if ($this->decisions->undecided($packageId)) {
13637 $this->decisions->decide(-$packageId, 1, null);
13638 }
13639 }
13640
13641 if ($this->problems) {
13642 throw new SolverProblemsException($this->problems, $this->installedMap);
13643 }
13644
13645 $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
13646
13647 return $transaction->getOperations();
13648 }
13649
13650
13651
13652
13653
13654
13655
13656
13657
13658
13659 protected function propagate($level)
13660 {
13661 while ($this->decisions->validOffset($this->propagateIndex)) {
13662 $decision = $this->decisions->atOffset($this->propagateIndex);
13663
13664 $conflict = $this->watchGraph->propagateLiteral(
13665 $decision[Decisions::DECISION_LITERAL],
13666 $level,
13667 $this->decisions
13668 );
13669
13670 $this->propagateIndex++;
13671
13672 if ($conflict) {
13673 return $conflict;
13674 }
13675 }
13676
13677 return null;
13678 }
13679
13680
13681
13682
13683
13684
13685 private function revert($level)
13686 {
13687 while (!$this->decisions->isEmpty()) {
13688 $literal = $this->decisions->lastLiteral();
13689
13690 if ($this->decisions->undecided($literal)) {
13691 break;
13692 }
13693
13694 $decisionLevel = $this->decisions->decisionLevel($literal);
13695
13696 if ($decisionLevel <= $level) {
13697 break;
13698 }
13699
13700 $this->decisions->revertLast();
13701 $this->propagateIndex = count($this->decisions);
13702 }
13703
13704 while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
13705 array_pop($this->branches);
13706 }
13707 }
13708
13709
13710
13711
13712
13713
13714
13715
13716
13717
13718
13719
13720
13721
13722
13723
13724
13725
13726
13727
13728 private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
13729 {
13730 $level++;
13731
13732 $this->decisions->decide($literal, $level, $rule);
13733
13734 while (true) {
13735 $rule = $this->propagate($level);
13736
13737 if (!$rule) {
13738 break;
13739 }
13740
13741 if ($level == 1) {
13742 return $this->analyzeUnsolvable($rule, $disableRules);
13743 }
13744
13745
13746  list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
13747
13748 if ($newLevel <= 0 || $newLevel >= $level) {
13749 throw new SolverBugException(
13750 "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
13751 );
13752 } elseif (!$newRule) {
13753 throw new SolverBugException(
13754 "No rule was learned from analyzing $rule at level $level."
13755 );
13756 }
13757
13758 $level = $newLevel;
13759
13760 $this->revert($level);
13761
13762 $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
13763
13764 $this->learnedWhy[spl_object_hash($newRule)] = $why;
13765
13766 $ruleNode = new RuleWatchNode($newRule);
13767 $ruleNode->watch2OnHighest($this->decisions);
13768 $this->watchGraph->insert($ruleNode);
13769
13770 $this->decisions->decide($learnLiteral, $level, $newRule);
13771 }
13772
13773 return $level;
13774 }
13775
13776
13777
13778
13779
13780
13781
13782
13783 private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
13784 {
13785
13786  $literals = $this->policy->selectPreferredPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
13787
13788 $selectedLiteral = array_shift($literals);
13789
13790
13791  if (count($literals)) {
13792 $this->branches[] = array($literals, $level);
13793 }
13794
13795 return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
13796 }
13797
13798
13799
13800
13801
13802
13803 protected function analyze($level, Rule $rule)
13804 {
13805 $analyzedRule = $rule;
13806 $ruleLevel = 1;
13807 $num = 0;
13808 $l1num = 0;
13809 $seen = array();
13810 $learnedLiterals = array(null);
13811
13812 $decisionId = count($this->decisions);
13813
13814 $this->learnedPool[] = array();
13815
13816 while (true) {
13817 $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
13818
13819 foreach ($rule->getLiterals() as $literal) {
13820
13821  if ($this->decisions->satisfy($literal)) {
13822 continue;
13823 }
13824
13825 if (isset($seen[abs($literal)])) {
13826 continue;
13827 }
13828 $seen[abs($literal)] = true;
13829
13830 $l = $this->decisions->decisionLevel($literal);
13831
13832 if (1 === $l) {
13833 $l1num++;
13834 } elseif ($level === $l) {
13835 $num++;
13836 } else {
13837
13838  $learnedLiterals[] = $literal;
13839
13840 if ($l > $ruleLevel) {
13841 $ruleLevel = $l;
13842 }
13843 }
13844 }
13845
13846 $l1retry = true;
13847 while ($l1retry) {
13848 $l1retry = false;
13849
13850 if (!$num && !--$l1num) {
13851
13852  break 2;
13853 }
13854
13855 while (true) {
13856 if ($decisionId <= 0) {
13857 throw new SolverBugException(
13858 "Reached invalid decision id $decisionId while looking through $rule for a literal present in the analyzed rule $analyzedRule."
13859 );
13860 }
13861
13862 $decisionId--;
13863
13864 $decision = $this->decisions->atOffset($decisionId);
13865 $literal = $decision[Decisions::DECISION_LITERAL];
13866
13867 if (isset($seen[abs($literal)])) {
13868 break;
13869 }
13870 }
13871
13872 unset($seen[abs($literal)]);
13873
13874 if ($num && 0 === --$num) {
13875 $learnedLiterals[0] = -abs($literal);
13876
13877 if (!$l1num) {
13878 break 2;
13879 }
13880
13881 foreach ($learnedLiterals as $i => $learnedLiteral) {
13882 if ($i !== 0) {
13883 unset($seen[abs($learnedLiteral)]);
13884 }
13885 }
13886
13887  $l1num++;
13888 $l1retry = true;
13889 }
13890 }
13891
13892 $decision = $this->decisions->atOffset($decisionId);
13893 $rule = $decision[Decisions::DECISION_REASON];
13894 }
13895
13896 $why = count($this->learnedPool) - 1;
13897
13898 if (!$learnedLiterals[0]) {
13899 throw new SolverBugException(
13900 "Did not find a learnable literal in analyzed rule $analyzedRule."
13901 );
13902 }
13903
13904 $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why);
13905
13906 return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
13907 }
13908
13909
13910
13911
13912
13913 private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule)
13914 {
13915 if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
13916 $why = spl_object_hash($conflictRule);
13917 $learnedWhy = $this->learnedWhy[$why];
13918 $problemRules = $this->learnedPool[$learnedWhy];
13919
13920 foreach ($problemRules as $problemRule) {
13921 $this->analyzeUnsolvableRule($problem, $problemRule);
13922 }
13923
13924 return;
13925 }
13926
13927 if ($conflictRule->getType() == RuleSet::TYPE_PACKAGE) {
13928
13929  return;
13930 }
13931
13932 $problem->nextSection();
13933 $problem->addRule($conflictRule);
13934 }
13935
13936
13937
13938
13939
13940
13941 private function analyzeUnsolvable(Rule $conflictRule, $disableRules)
13942 {
13943 $problem = new Problem($this->pool);
13944 $problem->addRule($conflictRule);
13945
13946 $this->analyzeUnsolvableRule($problem, $conflictRule);
13947
13948 $this->problems[] = $problem;
13949
13950 $seen = array();
13951 $literals = $conflictRule->getLiterals();
13952
13953 foreach ($literals as $literal) {
13954
13955  if ($this->decisions->satisfy($literal)) {
13956 continue;
13957 }
13958 $seen[abs($literal)] = true;
13959 }
13960
13961 foreach ($this->decisions as $decision) {
13962 $literal = $decision[Decisions::DECISION_LITERAL];
13963
13964
13965  if (!isset($seen[abs($literal)])) {
13966 continue;
13967 }
13968
13969 $why = $decision[Decisions::DECISION_REASON];
13970
13971 $problem->addRule($why);
13972 $this->analyzeUnsolvableRule($problem, $why);
13973
13974 $literals = $why->getLiterals();
13975
13976 foreach ($literals as $literal) {
13977
13978  if ($this->decisions->satisfy($literal)) {
13979 continue;
13980 }
13981 $seen[abs($literal)] = true;
13982 }
13983 }
13984
13985 if ($disableRules) {
13986 foreach ($this->problems[count($this->problems) - 1] as $reason) {
13987 $this->disableProblem($reason['rule']);
13988 }
13989
13990 $this->resetSolver();
13991
13992 return 1;
13993 }
13994
13995 return 0;
13996 }
13997
13998
13999
14000
14001 private function disableProblem(Rule $why)
14002 {
14003 $job = $why->getJob();
14004
14005 if (!$job) {
14006 $why->disable();
14007
14008 return;
14009 }
14010
14011
14012  foreach ($this->rules as $rule) {
14013
14014 if ($job === $rule->getJob()) {
14015 $rule->disable();
14016 }
14017 }
14018 }
14019
14020 private function resetSolver()
14021 {
14022 $this->decisions->reset();
14023
14024 $this->propagateIndex = 0;
14025 $this->branches = array();
14026
14027 $this->enableDisableLearnedRules();
14028 $this->makeAssertionRuleDecisions();
14029 }
14030
14031
14032
14033
14034
14035
14036
14037
14038 private function enableDisableLearnedRules()
14039 {
14040 foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
14041 $why = $this->learnedWhy[spl_object_hash($rule)];
14042 $problemRules = $this->learnedPool[$why];
14043
14044 $foundDisabled = false;
14045 foreach ($problemRules as $problemRule) {
14046 if ($problemRule->isDisabled()) {
14047 $foundDisabled = true;
14048 break;
14049 }
14050 }
14051
14052 if ($foundDisabled && $rule->isEnabled()) {
14053 $rule->disable();
14054 } elseif (!$foundDisabled && $rule->isDisabled()) {
14055 $rule->enable();
14056 }
14057 }
14058 }
14059
14060
14061
14062
14063 private function runSat($disableRules = true)
14064 {
14065 $this->propagateIndex = 0;
14066
14067
14068
14069
14070
14071
14072
14073
14074
14075
14076
14077 $decisionQueue = array();
14078 $decisionSupplementQueue = array();
14079
14080
14081
14082 $disableRules = array();
14083
14084 $level = 1;
14085 $systemLevel = $level + 1;
14086 $installedPos = 0;
14087
14088 while (true) {
14089 if (1 === $level) {
14090 $conflictRule = $this->propagate($level);
14091 if (null !== $conflictRule) {
14092 if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
14093 continue;
14094 }
14095
14096 return;
14097 }
14098 }
14099
14100
14101  if ($level < $systemLevel) {
14102 $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
14103 foreach ($iterator as $rule) {
14104 if ($rule->isEnabled()) {
14105 $decisionQueue = array();
14106 $noneSatisfied = true;
14107
14108 foreach ($rule->getLiterals() as $literal) {
14109 if ($this->decisions->satisfy($literal)) {
14110 $noneSatisfied = false;
14111 break;
14112 }
14113 if ($literal > 0 && $this->decisions->undecided($literal)) {
14114 $decisionQueue[] = $literal;
14115 }
14116 }
14117
14118 if ($noneSatisfied && count($decisionQueue)) {
14119
14120  
14121  if (count($this->installed) != count($this->updateMap)) {
14122 $prunedQueue = array();
14123 foreach ($decisionQueue as $literal) {
14124 if (isset($this->installedMap[abs($literal)])) {
14125 $prunedQueue[] = $literal;
14126 if (isset($this->updateMap[abs($literal)])) {
14127 $prunedQueue = $decisionQueue;
14128 break;
14129 }
14130 }
14131 }
14132 $decisionQueue = $prunedQueue;
14133 }
14134 }
14135
14136 if ($noneSatisfied && count($decisionQueue)) {
14137 $oLevel = $level;
14138 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
14139
14140 if (0 === $level) {
14141 return;
14142 }
14143 if ($level <= $oLevel) {
14144 break;
14145 }
14146 }
14147 }
14148 }
14149
14150 $systemLevel = $level + 1;
14151
14152
14153  $iterator->next();
14154 if ($iterator->valid()) {
14155 continue;
14156 }
14157 }
14158
14159 if ($level < $systemLevel) {
14160 $systemLevel = $level;
14161 }
14162
14163 $rulesCount = count($this->rules);
14164 $pass = 1;
14165
14166 $this->io->writeError('Looking at all rules.', true, IOInterface::DEBUG);
14167 for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
14168 if ($i == $rulesCount) {
14169 if (1 === $pass) {
14170 $this->io->writeError("Something's changed, looking at all rules again (pass #$pass)", false, IOInterface::DEBUG);
14171 } else {
14172 $this->io->overwriteError("Something's changed, looking at all rules again (pass #$pass)", false, null, IOInterface::DEBUG);
14173 }
14174
14175 $i = 0;
14176 $pass++;
14177 }
14178
14179 $rule = $this->rules->ruleById[$i];
14180 $literals = $rule->getLiterals();
14181
14182 if ($rule->isDisabled()) {
14183 continue;
14184 }
14185
14186 $decisionQueue = array();
14187
14188
14189  
14190  
14191  
14192  
14193  
14194  foreach ($literals as $literal) {
14195 if ($literal <= 0) {
14196 if (!$this->decisions->decidedInstall($literal)) {
14197 continue 2; 
14198  }
14199 } else {
14200 if ($this->decisions->decidedInstall($literal)) {
14201 continue 2; 
14202  }
14203 if ($this->decisions->undecided($literal)) {
14204 $decisionQueue[] = $literal;
14205 }
14206 }
14207 }
14208
14209
14210  if (count($decisionQueue) < 2) {
14211 continue;
14212 }
14213
14214 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
14215
14216 if (0 === $level) {
14217 return;
14218 }
14219
14220
14221  $rulesCount = count($this->rules);
14222 $n = -1;
14223 }
14224
14225 if ($level < $systemLevel) {
14226 continue;
14227 }
14228
14229
14230  if (count($this->branches)) {
14231 $lastLiteral = null;
14232 $lastLevel = null;
14233 $lastBranchIndex = 0;
14234 $lastBranchOffset = 0;
14235
14236 for ($i = count($this->branches) - 1; $i >= 0; $i--) {
14237 list($literals, $l) = $this->branches[$i];
14238
14239 foreach ($literals as $offset => $literal) {
14240 if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
14241 $lastLiteral = $literal;
14242 $lastBranchIndex = $i;
14243 $lastBranchOffset = $offset;
14244 $lastLevel = $l;
14245 }
14246 }
14247 }
14248
14249 if ($lastLiteral) {
14250 unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
14251
14252 $level = $lastLevel;
14253 $this->revert($level);
14254
14255 $why = $this->decisions->lastReason();
14256
14257 $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
14258
14259 if ($level == 0) {
14260 return;
14261 }
14262
14263 continue;
14264 }
14265 }
14266
14267 break;
14268 }
14269 }
14270 }
14271 <?php
14272
14273
14274
14275
14276
14277
14278
14279
14280
14281
14282
14283 namespace Composer\DependencyResolver;
14284
14285
14286
14287
14288 class SolverBugException extends \RuntimeException
14289 {
14290 public function __construct($message)
14291 {
14292 parent::__construct(
14293 $message."\nThis exception was most likely caused by a bug in Composer.\n".
14294 "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"
14295 );
14296 }
14297 }
14298 <?php
14299
14300
14301
14302
14303
14304
14305
14306
14307
14308
14309
14310 namespace Composer\DependencyResolver;
14311
14312 use Composer\Util\IniHelper;
14313
14314
14315
14316
14317 class SolverProblemsException extends \RuntimeException
14318 {
14319 protected $problems;
14320 protected $installedMap;
14321
14322 public function __construct(array $problems, array $installedMap)
14323 {
14324 $this->problems = $problems;
14325 $this->installedMap = $installedMap;
14326
14327 parent::__construct($this->createMessage(), 2);
14328 }
14329
14330 protected function createMessage()
14331 {
14332 $text = "\n";
14333 $hasExtensionProblems = false;
14334 foreach ($this->problems as $i => $problem) {
14335 $text .= "  Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
14336
14337 if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
14338 $hasExtensionProblems = true;
14339 }
14340 }
14341
14342 if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
14343 $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.";
14344 }
14345
14346 if ($hasExtensionProblems) {
14347 $text .= $this->createExtensionHint();
14348 }
14349
14350 return $text;
14351 }
14352
14353 public function getProblems()
14354 {
14355 return $this->problems;
14356 }
14357
14358 private function createExtensionHint()
14359 {
14360 $paths = IniHelper::getAll();
14361
14362 if (count($paths) === 1 && empty($paths[0])) {
14363 return '';
14364 }
14365
14366 $text = "\n  To enable extensions, verify that they are enabled in your .ini files:\n    - ";
14367 $text .= implode("\n    - ", $paths);
14368 $text .= "\n  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
14369
14370 return $text;
14371 }
14372
14373 private function hasExtensionProblems(array $reasonSets)
14374 {
14375 foreach ($reasonSets as $reasonSet) {
14376 foreach ($reasonSet as $reason) {
14377 if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
14378 return true;
14379 }
14380 }
14381 }
14382
14383 return false;
14384 }
14385 }
14386 <?php
14387
14388
14389
14390
14391
14392
14393
14394
14395
14396
14397
14398 namespace Composer\DependencyResolver;
14399
14400 use Composer\Package\AliasPackage;
14401
14402
14403
14404
14405 class Transaction
14406 {
14407 protected $policy;
14408 protected $pool;
14409 protected $installedMap;
14410 protected $decisions;
14411 protected $transaction;
14412
14413 public function __construct($policy, $pool, $installedMap, $decisions)
14414 {
14415 $this->policy = $policy;
14416 $this->pool = $pool;
14417 $this->installedMap = $installedMap;
14418 $this->decisions = $decisions;
14419 $this->transaction = array();
14420 }
14421
14422 public function getOperations()
14423 {
14424 $installMeansUpdateMap = $this->findUpdates();
14425
14426 $updateMap = array();
14427 $installMap = array();
14428 $uninstallMap = array();
14429
14430 foreach ($this->decisions as $i => $decision) {
14431 $literal = $decision[Decisions::DECISION_LITERAL];
14432 $reason = $decision[Decisions::DECISION_REASON];
14433
14434 $package = $this->pool->literalToPackage($literal);
14435
14436
14437  if (($literal > 0) == isset($this->installedMap[$package->id])) {
14438 continue;
14439 }
14440
14441 if ($literal > 0) {
14442 if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
14443 $source = $installMeansUpdateMap[abs($literal)];
14444
14445 $updateMap[$package->id] = array(
14446 'package' => $package,
14447 'source' => $source,
14448 'reason' => $reason,
14449 );
14450
14451
14452  unset($installMeansUpdateMap[abs($literal)]);
14453 $ignoreRemove[$source->id] = true;
14454 } else {
14455 $installMap[$package->id] = array(
14456 'package' => $package,
14457 'reason' => $reason,
14458 );
14459 }
14460 }
14461 }
14462
14463 foreach ($this->decisions as $i => $decision) {
14464 $literal = $decision[Decisions::DECISION_LITERAL];
14465 $reason = $decision[Decisions::DECISION_REASON];
14466 $package = $this->pool->literalToPackage($literal);
14467
14468 if ($literal <= 0 &&
14469 isset($this->installedMap[$package->id]) &&
14470 !isset($ignoreRemove[$package->id])) {
14471 $uninstallMap[$package->id] = array(
14472 'package' => $package,
14473 'reason' => $reason,
14474 );
14475 }
14476 }
14477
14478 $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
14479
14480 return $this->transaction;
14481 }
14482
14483 protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
14484 {
14485 $queue = array_map(
14486 function ($operation) {
14487 return $operation['package'];
14488 },
14489 $this->findRootPackages($installMap, $updateMap)
14490 );
14491
14492 $visited = array();
14493
14494 while (!empty($queue)) {
14495 $package = array_pop($queue);
14496 $packageId = $package->id;
14497
14498 if (!isset($visited[$packageId])) {
14499 $queue[] = $package;
14500
14501 if ($package instanceof AliasPackage) {
14502 $queue[] = $package->getAliasOf();
14503 } else {
14504 foreach ($package->getRequires() as $link) {
14505 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
14506
14507 foreach ($possibleRequires as $require) {
14508 $queue[] = $require;
14509 }
14510 }
14511 }
14512
14513 $visited[$package->id] = true;
14514 } else {
14515 if (isset($installMap[$packageId])) {
14516 $this->install(
14517 $installMap[$packageId]['package'],
14518 $installMap[$packageId]['reason']
14519 );
14520 unset($installMap[$packageId]);
14521 }
14522 if (isset($updateMap[$packageId])) {
14523 $this->update(
14524 $updateMap[$packageId]['source'],
14525 $updateMap[$packageId]['package'],
14526 $updateMap[$packageId]['reason']
14527 );
14528 unset($updateMap[$packageId]);
14529 }
14530 }
14531 }
14532
14533 foreach ($uninstallMap as $uninstall) {
14534 $this->uninstall($uninstall['package'], $uninstall['reason']);
14535 }
14536 }
14537
14538 protected function findRootPackages($installMap, $updateMap)
14539 {
14540 $packages = $installMap + $updateMap;
14541 $roots = $packages;
14542
14543 foreach ($packages as $packageId => $operation) {
14544 $package = $operation['package'];
14545
14546 if (!isset($roots[$packageId])) {
14547 continue;
14548 }
14549
14550 foreach ($package->getRequires() as $link) {
14551 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
14552
14553 foreach ($possibleRequires as $require) {
14554 if ($require !== $package) {
14555 unset($roots[$require->id]);
14556 }
14557 }
14558 }
14559 }
14560
14561 return $roots;
14562 }
14563
14564 protected function findUpdates()
14565 {
14566 $installMeansUpdateMap = array();
14567
14568 foreach ($this->decisions as $i => $decision) {
14569 $literal = $decision[Decisions::DECISION_LITERAL];
14570 $package = $this->pool->literalToPackage($literal);
14571
14572 if ($package instanceof AliasPackage) {
14573 continue;
14574 }
14575
14576
14577  if ($literal <= 0 && isset($this->installedMap[$package->id])) {
14578 $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
14579
14580 $literals = array($package->id);
14581
14582 foreach ($updates as $update) {
14583 $literals[] = $update->id;
14584 }
14585
14586 foreach ($literals as $updateLiteral) {
14587 if ($updateLiteral !== $literal) {
14588 $installMeansUpdateMap[abs($updateLiteral)] = $package;
14589 }
14590 }
14591 }
14592 }
14593
14594 return $installMeansUpdateMap;
14595 }
14596
14597 protected function install($package, $reason)
14598 {
14599 if ($package instanceof AliasPackage) {
14600 return $this->markAliasInstalled($package, $reason);
14601 }
14602
14603 $this->transaction[] = new Operation\InstallOperation($package, $reason);
14604 }
14605
14606 protected function update($from, $to, $reason)
14607 {
14608 $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
14609 }
14610
14611 protected function uninstall($package, $reason)
14612 {
14613 if ($package instanceof AliasPackage) {
14614 return $this->markAliasUninstalled($package, $reason);
14615 }
14616
14617 $this->transaction[] = new Operation\UninstallOperation($package, $reason);
14618 }
14619
14620 protected function markAliasInstalled($package, $reason)
14621 {
14622 $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
14623 }
14624
14625 protected function markAliasUninstalled($package, $reason)
14626 {
14627 $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
14628 }
14629 }
14630 <?php
14631
14632
14633
14634
14635
14636
14637
14638
14639
14640
14641
14642 namespace Composer\Downloader;
14643
14644 use Composer\Package\PackageInterface;
14645 use Symfony\Component\Finder\Finder;
14646 use Composer\IO\IOInterface;
14647
14648
14649
14650
14651
14652
14653
14654
14655 abstract class ArchiveDownloader extends FileDownloader
14656 {
14657
14658
14659
14660
14661
14662 public function download(PackageInterface $package, $path, $output = true)
14663 {
14664 $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
14665 $retries = 3;
14666 while ($retries--) {
14667 $fileName = parent::download($package, $path, $output);
14668
14669 if ($output) {
14670 $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
14671 }
14672
14673 try {
14674 $this->filesystem->ensureDirectoryExists($temporaryDir);
14675 try {
14676 $this->extract($fileName, $temporaryDir);
14677 } catch (\Exception $e) {
14678
14679  parent::clearLastCacheWrite($package);
14680 throw $e;
14681 }
14682
14683 $this->filesystem->unlink($fileName);
14684
14685 $contentDir = $this->getFolderContent($temporaryDir);
14686
14687
14688  if (1 === count($contentDir) && is_dir(reset($contentDir))) {
14689 $contentDir = $this->getFolderContent((string) reset($contentDir));
14690 }
14691
14692
14693  foreach ($contentDir as $file) {
14694 $file = (string) $file;
14695 $this->filesystem->rename($file, $path . '/' . basename($file));
14696 }
14697
14698 $this->filesystem->removeDirectory($temporaryDir);
14699 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
14700 $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
14701 }
14702 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
14703 $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
14704 }
14705 } catch (\Exception $e) {
14706
14707  $this->filesystem->removeDirectory($path);
14708 $this->filesystem->removeDirectory($temporaryDir);
14709
14710
14711  if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
14712 $this->io->writeError('');
14713 if ($this->io->isDebug()) {
14714 $this->io->writeError('    Invalid zip file ('.$e->getMessage().'), retrying...');
14715 } else {
14716 $this->io->writeError('    Invalid zip file, retrying...');
14717 }
14718 usleep(500000);
14719 continue;
14720 }
14721
14722 throw $e;
14723 }
14724
14725 break;
14726 }
14727 }
14728
14729
14730
14731
14732 protected function getFileName(PackageInterface $package, $path)
14733 {
14734 return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
14735 }
14736
14737
14738
14739
14740
14741
14742
14743
14744
14745 abstract protected function extract($file, $path);
14746
14747
14748
14749
14750
14751
14752
14753 private function getFolderContent($dir)
14754 {
14755 $finder = Finder::create()
14756 ->ignoreVCS(false)
14757 ->ignoreDotFiles(false)
14758 ->notName('.DS_Store')
14759 ->depth(0)
14760 ->in($dir);
14761
14762 return iterator_to_array($finder);
14763 }
14764 }
14765 <?php
14766
14767
14768
14769
14770
14771
14772
14773
14774
14775
14776
14777 namespace Composer\Downloader;
14778
14779 use Composer\Package\PackageInterface;
14780
14781
14782
14783
14784
14785
14786 interface ChangeReportInterface
14787 {
14788
14789
14790
14791
14792
14793
14794
14795 public function getLocalChanges(PackageInterface $package, $path);
14796 }
14797 <?php
14798
14799
14800
14801
14802
14803
14804
14805
14806
14807
14808
14809 namespace Composer\Downloader;
14810
14811 use Composer\Package\PackageInterface;
14812 use Composer\IO\IOInterface;
14813 use Composer\Util\Filesystem;
14814
14815
14816
14817
14818
14819
14820 class DownloadManager
14821 {
14822 private $io;
14823 private $preferDist = false;
14824 private $preferSource = false;
14825 private $packagePreferences = array();
14826 private $filesystem;
14827 private $downloaders = array();
14828
14829
14830
14831
14832
14833
14834
14835
14836 public function __construct(IOInterface $io, $preferSource = false, Filesystem $filesystem = null)
14837 {
14838 $this->io = $io;
14839 $this->preferSource = $preferSource;
14840 $this->filesystem = $filesystem ?: new Filesystem();
14841 }
14842
14843
14844
14845
14846
14847
14848
14849 public function setPreferSource($preferSource)
14850 {
14851 $this->preferSource = $preferSource;
14852
14853 return $this;
14854 }
14855
14856
14857
14858
14859
14860
14861
14862 public function setPreferDist($preferDist)
14863 {
14864 $this->preferDist = $preferDist;
14865
14866 return $this;
14867 }
14868
14869
14870
14871
14872
14873
14874
14875 public function setPreferences(array $preferences)
14876 {
14877 $this->packagePreferences = $preferences;
14878
14879 return $this;
14880 }
14881
14882
14883
14884
14885
14886
14887
14888
14889 public function setOutputProgress($outputProgress)
14890 {
14891 foreach ($this->downloaders as $downloader) {
14892 $downloader->setOutputProgress($outputProgress);
14893 }
14894
14895 return $this;
14896 }
14897
14898
14899
14900
14901
14902
14903
14904
14905 public function setDownloader($type, DownloaderInterface $downloader)
14906 {
14907 $type = strtolower($type);
14908 $this->downloaders[$type] = $downloader;
14909
14910 return $this;
14911 }
14912
14913
14914
14915
14916
14917
14918
14919
14920 public function getDownloader($type)
14921 {
14922 $type = strtolower($type);
14923 if (!isset($this->downloaders[$type])) {
14924 throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
14925 }
14926
14927 return $this->downloaders[$type];
14928 }
14929
14930
14931
14932
14933
14934
14935
14936
14937
14938
14939 public function getDownloaderForInstalledPackage(PackageInterface $package)
14940 {
14941 $installationSource = $package->getInstallationSource();
14942
14943 if ('metapackage' === $package->getType()) {
14944 return;
14945 }
14946
14947 if ('dist' === $installationSource) {
14948 $downloader = $this->getDownloader($package->getDistType());
14949 } elseif ('source' === $installationSource) {
14950 $downloader = $this->getDownloader($package->getSourceType());
14951 } else {
14952 throw new \InvalidArgumentException(
14953 'Package '.$package.' seems not been installed properly'
14954 );
14955 }
14956
14957 if ($installationSource !== $downloader->getInstallationSource()) {
14958 throw new \LogicException(sprintf(
14959 'Downloader "%s" is a %s type downloader and can not be used to download %s for package %s',
14960 get_class($downloader),
14961 $downloader->getInstallationSource(),
14962 $installationSource,
14963 $package
14964 ));
14965 }
14966
14967 return $downloader;
14968 }
14969
14970
14971
14972
14973
14974
14975
14976
14977
14978
14979
14980 public function download(PackageInterface $package, $targetDir, $preferSource = null)
14981 {
14982 $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
14983 $sourceType = $package->getSourceType();
14984 $distType = $package->getDistType();
14985
14986 $sources = array();
14987 if ($sourceType) {
14988 $sources[] = 'source';
14989 }
14990 if ($distType) {
14991 $sources[] = 'dist';
14992 }
14993
14994 if (empty($sources)) {
14995 throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
14996 }
14997
14998 if (!$preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
14999 $sources = array_reverse($sources);
15000 }
15001
15002 $this->filesystem->ensureDirectoryExists($targetDir);
15003
15004 foreach ($sources as $i => $source) {
15005 if (isset($e)) {
15006 $this->io->writeError('    <warning>Now trying to download from ' . $source . '</warning>');
15007 }
15008 $package->setInstallationSource($source);
15009 try {
15010 $downloader = $this->getDownloaderForInstalledPackage($package);
15011 if ($downloader) {
15012 $downloader->download($package, $targetDir);
15013 }
15014 break;
15015 } catch (\RuntimeException $e) {
15016 if ($i === count($sources) - 1) {
15017 throw $e;
15018 }
15019
15020 $this->io->writeError(
15021 '    <warning>Failed to download '.
15022 $package->getPrettyName().
15023 ' from ' . $source . ': '.
15024 $e->getMessage().'</warning>'
15025 );
15026 }
15027 }
15028 }
15029
15030
15031
15032
15033
15034
15035
15036
15037
15038
15039 public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
15040 {
15041 $downloader = $this->getDownloaderForInstalledPackage($initial);
15042 if (!$downloader) {
15043 return;
15044 }
15045
15046 $installationSource = $initial->getInstallationSource();
15047
15048 if ('dist' === $installationSource) {
15049 $initialType = $initial->getDistType();
15050 $targetType = $target->getDistType();
15051 } else {
15052 $initialType = $initial->getSourceType();
15053 $targetType = $target->getSourceType();
15054 }
15055
15056
15057  if ($target->isDev() && 'dist' === $installationSource) {
15058 $downloader->remove($initial, $targetDir);
15059 $this->download($target, $targetDir);
15060
15061 return;
15062 }
15063
15064 if ($initialType === $targetType) {
15065 $target->setInstallationSource($installationSource);
15066 try {
15067 $downloader->update($initial, $target, $targetDir);
15068
15069 return;
15070 } catch (\RuntimeException $e) {
15071 if (!$this->io->isInteractive()) {
15072 throw $e;
15073 }
15074 $this->io->writeError('<error>    Update failed ('.$e->getMessage().')</error>');
15075 if (!$this->io->askConfirmation('    Would you like to try reinstalling the package instead [<comment>yes</comment>]? ', true)) {
15076 throw $e;
15077 }
15078 }
15079 }
15080
15081 $downloader->remove($initial, $targetDir);
15082 $this->download($target, $targetDir, 'source' === $installationSource);
15083 }
15084
15085
15086
15087
15088
15089
15090
15091 public function remove(PackageInterface $package, $targetDir)
15092 {
15093 $downloader = $this->getDownloaderForInstalledPackage($package);
15094 if ($downloader) {
15095 $downloader->remove($package, $targetDir);
15096 }
15097 }
15098
15099
15100
15101
15102
15103
15104
15105
15106 protected function resolvePackageInstallPreference(PackageInterface $package)
15107 {
15108 foreach ($this->packagePreferences as $pattern => $preference) {
15109 $pattern = '{^'.str_replace('\\*', '.*', preg_quote($pattern)).'$}i';
15110 if (preg_match($pattern, $package->getName())) {
15111 if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) {
15112 return 'dist';
15113 }
15114
15115 return 'source';
15116 }
15117 }
15118
15119 return $package->isDev() ? 'source' : 'dist';
15120 }
15121 }
15122 <?php
15123
15124
15125
15126
15127
15128
15129
15130
15131
15132
15133
15134 namespace Composer\Downloader;
15135
15136 use Composer\Package\PackageInterface;
15137
15138
15139
15140
15141
15142
15143
15144 interface DownloaderInterface
15145 {
15146
15147
15148
15149
15150
15151 public function getInstallationSource();
15152
15153
15154
15155
15156
15157
15158
15159 public function download(PackageInterface $package, $path);
15160
15161
15162
15163
15164
15165
15166
15167
15168 public function update(PackageInterface $initial, PackageInterface $target, $path);
15169
15170
15171
15172
15173
15174
15175
15176 public function remove(PackageInterface $package, $path);
15177
15178
15179
15180
15181
15182
15183
15184 public function setOutputProgress($outputProgress);
15185 }
15186 <?php
15187
15188
15189
15190
15191
15192
15193
15194
15195
15196
15197
15198 namespace Composer\Downloader;
15199
15200 use Composer\Package\PackageInterface;
15201
15202
15203
15204
15205
15206
15207 interface DvcsDownloaderInterface
15208 {
15209
15210
15211
15212
15213
15214
15215
15216 public function getUnpushedChanges(PackageInterface $package, $path);
15217 }
15218 <?php
15219
15220
15221
15222
15223
15224
15225
15226
15227
15228
15229
15230 namespace Composer\Downloader;
15231
15232 use Composer\Config;
15233 use Composer\Cache;
15234 use Composer\Factory;
15235 use Composer\IO\IOInterface;
15236 use Composer\IO\NullIO;
15237 use Composer\Package\Comparer\Comparer;
15238 use Composer\Package\PackageInterface;
15239 use Composer\Package\Version\VersionParser;
15240 use Composer\Plugin\PluginEvents;
15241 use Composer\Plugin\PreFileDownloadEvent;
15242 use Composer\EventDispatcher\EventDispatcher;
15243 use Composer\Util\Filesystem;
15244 use Composer\Util\RemoteFilesystem;
15245 use Composer\Util\Url as UrlUtil;
15246
15247
15248
15249
15250
15251
15252
15253
15254
15255 class FileDownloader implements DownloaderInterface, ChangeReportInterface
15256 {
15257 protected $io;
15258 protected $config;
15259 protected $rfs;
15260 protected $filesystem;
15261 protected $cache;
15262 protected $outputProgress = true;
15263 private $lastCacheWrites = array();
15264 private $eventDispatcher;
15265
15266
15267
15268
15269
15270
15271
15272
15273
15274
15275
15276 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
15277 {
15278 $this->io = $io;
15279 $this->config = $config;
15280 $this->eventDispatcher = $eventDispatcher;
15281 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
15282 $this->filesystem = $filesystem ?: new Filesystem();
15283 $this->cache = $cache;
15284
15285 if ($this->cache && $this->cache->gcIsNecessary()) {
15286 $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
15287 }
15288 }
15289
15290
15291
15292
15293 public function getInstallationSource()
15294 {
15295 return 'dist';
15296 }
15297
15298
15299
15300
15301 public function download(PackageInterface $package, $path, $output = true)
15302 {
15303 if (!$package->getDistUrl()) {
15304 throw new \InvalidArgumentException('The given package is missing url information');
15305 }
15306
15307 if ($output) {
15308 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
15309 }
15310
15311 $urls = $package->getDistUrls();
15312 while ($url = array_shift($urls)) {
15313 try {
15314 $fileName = $this->doDownload($package, $path, $url);
15315 break;
15316 } catch (\Exception $e) {
15317 if ($this->io->isDebug()) {
15318 $this->io->writeError('');
15319 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
15320 } elseif (count($urls)) {
15321 $this->io->writeError('');
15322 $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
15323 }
15324
15325 if (!count($urls)) {
15326 throw $e;
15327 }
15328 }
15329 }
15330
15331 if ($output) {
15332 $this->io->writeError('');
15333 }
15334
15335 return $fileName;
15336 }
15337
15338 protected function doDownload(PackageInterface $package, $path, $url)
15339 {
15340 $this->filesystem->emptyDirectory($path);
15341
15342 $fileName = $this->getFileName($package, $path);
15343
15344 $processedUrl = $this->processUrl($package, $url);
15345 $hostname = parse_url($processedUrl, PHP_URL_HOST);
15346
15347 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
15348 if ($this->eventDispatcher) {
15349 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
15350 }
15351 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
15352
15353 try {
15354 $checksum = $package->getDistSha1Checksum();
15355 $cacheKey = $this->getCacheKey($package, $processedUrl);
15356
15357
15358  if ($this->cache && (!$checksum || $checksum === $this->cache->sha1($cacheKey)) && $this->cache->copyTo($cacheKey, $fileName)) {
15359 $this->io->writeError('Loading from cache', false);
15360 } else {
15361
15362  if (!$this->outputProgress) {
15363 $this->io->writeError('Downloading', false);
15364 }
15365
15366
15367  $retries = 3;
15368 while ($retries--) {
15369 try {
15370 $rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
15371 break;
15372 } catch (TransportException $e) {
15373
15374  if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
15375 throw $e;
15376 }
15377 $this->io->writeError('');
15378 $this->io->writeError('    Download failed, retrying...', true, IOInterface::VERBOSE);
15379 usleep(500000);
15380 }
15381 }
15382
15383 if (!$this->outputProgress) {
15384 $this->io->writeError(' (<comment>100%</comment>)', false);
15385 }
15386
15387 if ($this->cache) {
15388 $this->lastCacheWrites[$package->getName()] = $cacheKey;
15389 $this->cache->copyFrom($cacheKey, $fileName);
15390 }
15391 }
15392
15393 if (!file_exists($fileName)) {
15394 throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
15395 .' directory is writable and you have internet connectivity');
15396 }
15397
15398 if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
15399 throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
15400 }
15401 } catch (\Exception $e) {
15402
15403  $this->filesystem->removeDirectory($path);
15404 $this->clearLastCacheWrite($package);
15405 throw $e;
15406 }
15407
15408 return $fileName;
15409 }
15410
15411
15412
15413
15414 public function setOutputProgress($outputProgress)
15415 {
15416 $this->outputProgress = $outputProgress;
15417
15418 return $this;
15419 }
15420
15421 protected function clearLastCacheWrite(PackageInterface $package)
15422 {
15423 if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
15424 $this->cache->remove($this->lastCacheWrites[$package->getName()]);
15425 unset($this->lastCacheWrites[$package->getName()]);
15426 }
15427 }
15428
15429
15430
15431
15432 public function update(PackageInterface $initial, PackageInterface $target, $path)
15433 {
15434 $name = $target->getName();
15435 $from = $initial->getPrettyVersion();
15436 $to = $target->getPrettyVersion();
15437
15438 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
15439 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
15440
15441 $this->remove($initial, $path, false);
15442 $this->download($target, $path, false);
15443
15444 $this->io->writeError('');
15445 }
15446
15447
15448
15449
15450 public function remove(PackageInterface $package, $path, $output = true)
15451 {
15452 if ($output) {
15453 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
15454 }
15455 if (!$this->filesystem->removeDirectory($path)) {
15456 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
15457 }
15458 }
15459
15460
15461
15462
15463
15464
15465
15466
15467 protected function getFileName(PackageInterface $package, $path)
15468 {
15469 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
15470 }
15471
15472
15473
15474
15475
15476
15477
15478
15479
15480 protected function processUrl(PackageInterface $package, $url)
15481 {
15482 if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
15483 throw new \RuntimeException('You must enable the openssl extension to download files via https');
15484 }
15485
15486 if ($package->getDistReference()) {
15487 $url = UrlUtil::updateDistReference($this->config, $url, $package->getDistReference());
15488 }
15489
15490 return $url;
15491 }
15492
15493 private function getCacheKey(PackageInterface $package, $processedUrl)
15494 {
15495
15496  
15497  
15498  
15499  $cacheKey = sha1($processedUrl);
15500
15501 return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
15502 }
15503
15504
15505
15506
15507
15508 public function getLocalChanges(PackageInterface $package, $targetDir)
15509 {
15510 $prevIO = $this->io;
15511 $prevProgress = $this->outputProgress;
15512
15513 $this->io = new NullIO;
15514 $this->io->loadConfiguration($this->config);
15515 $this->outputProgress = false;
15516 $e = null;
15517
15518 try {
15519 $this->download($package, $targetDir.'_compare', false);
15520
15521 $comparer = new Comparer();
15522 $comparer->setSource($targetDir.'_compare');
15523 $comparer->setUpdate($targetDir);
15524 $comparer->doCompare();
15525 $output = $comparer->getChanged(true, true);
15526 $this->filesystem->removeDirectory($targetDir.'_compare');
15527 } catch (\Exception $e) {
15528 }
15529
15530 $this->io = $prevIO;
15531 $this->outputProgress = $prevProgress;
15532
15533 if ($e) {
15534 throw $e;
15535 }
15536
15537 return trim($output);
15538 }
15539 }
15540 <?php
15541
15542
15543
15544
15545
15546
15547
15548
15549
15550
15551
15552 namespace Composer\Downloader;
15553
15554
15555
15556
15557
15558
15559 class FilesystemException extends \Exception
15560 {
15561 public function __construct($message = '', $code = 0, \Exception $previous = null)
15562 {
15563 parent::__construct("Filesystem exception: \n".$message, $code, $previous);
15564 }
15565 }
15566 <?php
15567
15568
15569
15570
15571
15572
15573
15574
15575
15576
15577
15578 namespace Composer\Downloader;
15579
15580 use Composer\Package\PackageInterface;
15581 use Composer\Util\ProcessExecutor;
15582
15583
15584
15585
15586 class FossilDownloader extends VcsDownloader
15587 {
15588
15589
15590
15591 public function doDownload(PackageInterface $package, $path, $url)
15592 {
15593
15594  $this->config->prohibitUrlByConfig($url, $this->io);
15595
15596 $url = ProcessExecutor::escape($url);
15597 $ref = ProcessExecutor::escape($package->getSourceReference());
15598 $repoFile = $path . '.fossil';
15599 $this->io->writeError("Cloning ".$package->getSourceReference());
15600 $command = sprintf('fossil clone %s %s', $url, ProcessExecutor::escape($repoFile));
15601 if (0 !== $this->process->execute($command, $ignoredOutput)) {
15602 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15603 }
15604 $command = sprintf('fossil open %s --nested', ProcessExecutor::escape($repoFile));
15605 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15606 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15607 }
15608 $command = sprintf('fossil update %s', $ref);
15609 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15610 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15611 }
15612 }
15613
15614
15615
15616
15617 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15618 {
15619
15620  $this->config->prohibitUrlByConfig($url, $this->io);
15621
15622 $url = ProcessExecutor::escape($url);
15623 $ref = ProcessExecutor::escape($target->getSourceReference());
15624 $this->io->writeError(" Updating to ".$target->getSourceReference());
15625
15626 if (!$this->hasMetadataRepository($path)) {
15627 throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15628 }
15629
15630 $command = sprintf('fossil pull && fossil up %s', $ref);
15631 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15632 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15633 }
15634 }
15635
15636
15637
15638
15639 public function getLocalChanges(PackageInterface $package, $path)
15640 {
15641 if (!$this->hasMetadataRepository($path)) {
15642 return null;
15643 }
15644
15645 $this->process->execute('fossil changes', $output, realpath($path));
15646
15647 return trim($output) ?: null;
15648 }
15649
15650
15651
15652
15653 protected function getCommitLogs($fromReference, $toReference, $path)
15654 {
15655 $command = sprintf('fossil timeline -t ci -W 0 -n 0 before %s', ProcessExecutor::escape($toReference));
15656
15657 if (0 !== $this->process->execute($command, $output, realpath($path))) {
15658 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15659 }
15660
15661 $log = '';
15662 $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
15663
15664 foreach ($this->process->splitLines($output) as $line) {
15665 if (preg_match($match, $line)) {
15666 break;
15667 }
15668 $log .= $line;
15669 }
15670
15671 return $log;
15672 }
15673
15674
15675
15676
15677 protected function hasMetadataRepository($path)
15678 {
15679 return is_file($path . '/.fslckout') || is_file($path . '/_FOSSIL_');
15680 }
15681 }
15682 <?php
15683
15684
15685
15686
15687
15688
15689
15690
15691
15692
15693
15694 namespace Composer\Downloader;
15695
15696 use Composer\Config;
15697 use Composer\IO\IOInterface;
15698 use Composer\Package\PackageInterface;
15699 use Composer\Util\Filesystem;
15700 use Composer\Util\Git as GitUtil;
15701 use Composer\Util\Platform;
15702 use Composer\Util\ProcessExecutor;
15703
15704
15705
15706
15707 class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
15708 {
15709 private $hasStashedChanges = false;
15710 private $hasDiscardedChanges = false;
15711 private $gitUtil;
15712
15713 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
15714 {
15715 parent::__construct($io, $config, $process, $fs);
15716 $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
15717 }
15718
15719
15720
15721
15722 public function doDownload(PackageInterface $package, $path, $url)
15723 {
15724 GitUtil::cleanEnv();
15725 $path = $this->normalizePath($path);
15726 $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
15727 $ref = $package->getSourceReference();
15728 $flag = Platform::isWindows() ? '/D ' : '';
15729
15730
15731  $gitVersion = $this->gitUtil->getVersion();
15732 $msg = "Cloning ".$this->getShortHash($ref);
15733
15734 $command = 'git clone --no-checkout %url% %path% && cd '.$flag.'%path% && git remote add composer %url% && git fetch composer';
15735 if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=')) {
15736 $this->io->writeError('', true, IOInterface::DEBUG);
15737 $this->io->writeError(sprintf('    Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
15738 try {
15739 $this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref);
15740 if (is_dir($cachePath)) {
15741 $command =
15742 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% '
15743 . '&& cd '.$flag.'%path% '
15744 . '&& git remote set-url origin %url% && git remote add composer %url%';
15745 $msg = "Cloning ".$this->getShortHash($ref).' from cache';
15746 }
15747 } catch (\RuntimeException $e) {
15748 }
15749 }
15750 $this->io->writeError($msg);
15751
15752 $commandCallable = function ($url) use ($path, $command, $cachePath) {
15753 return str_replace(
15754 array('%url%', '%path%', '%cachePath%'),
15755 array(
15756 ProcessExecutor::escape($url),
15757 ProcessExecutor::escape($path),
15758 ProcessExecutor::escape($cachePath),
15759 ),
15760 $command
15761 );
15762 };
15763
15764 $this->gitUtil->runCommand($commandCallable, $url, $path, true);
15765 if ($url !== $package->getSourceUrl()) {
15766 $this->updateOriginUrl($path, $package->getSourceUrl());
15767 } else {
15768 $this->setPushUrl($path, $url);
15769 }
15770
15771 if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
15772 if ($package->getDistReference() === $package->getSourceReference()) {
15773 $package->setDistReference($newRef);
15774 }
15775 $package->setSourceReference($newRef);
15776 }
15777 }
15778
15779
15780
15781
15782 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15783 {
15784 GitUtil::cleanEnv();
15785 if (!$this->hasMetadataRepository($path)) {
15786 throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15787 }
15788
15789 $updateOriginUrl = false;
15790 if (
15791 0 === $this->process->execute('git remote -v', $output, $path)
15792 && preg_match('{^origin\s+(?P<url>\S+)}m', $output, $originMatch)
15793 && preg_match('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)
15794 ) {
15795 if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
15796 $updateOriginUrl = true;
15797 }
15798 }
15799
15800 $ref = $target->getSourceReference();
15801 $this->io->writeError(" Checking out ".$this->getShortHash($ref));
15802 $command = 'git remote set-url composer %s && git rev-parse --quiet --verify %s || (git fetch composer && git fetch --tags composer)';
15803
15804 $commandCallable = function ($url) use ($command, $ref) {
15805 return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($ref.'^{commit}'));
15806 };
15807
15808 $this->gitUtil->runCommand($commandCallable, $url, $path);
15809 if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
15810 if ($target->getDistReference() === $target->getSourceReference()) {
15811 $target->setDistReference($newRef);
15812 }
15813 $target->setSourceReference($newRef);
15814 }
15815
15816 if ($updateOriginUrl) {
15817 $this->updateOriginUrl($path, $target->getSourceUrl());
15818 }
15819 }
15820
15821
15822
15823
15824 public function getLocalChanges(PackageInterface $package, $path)
15825 {
15826 GitUtil::cleanEnv();
15827 if (!$this->hasMetadataRepository($path)) {
15828 return;
15829 }
15830
15831 $command = 'git status --porcelain --untracked-files=no';
15832 if (0 !== $this->process->execute($command, $output, $path)) {
15833 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15834 }
15835
15836 return trim($output) ?: null;
15837 }
15838
15839 public function getUnpushedChanges(PackageInterface $package, $path)
15840 {
15841 GitUtil::cleanEnv();
15842 $path = $this->normalizePath($path);
15843 if (!$this->hasMetadataRepository($path)) {
15844 return;
15845 }
15846
15847 $command = 'git show-ref --head -d';
15848 if (0 !== $this->process->execute($command, $output, $path)) {
15849 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15850 }
15851
15852 $refs = trim($output);
15853 if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
15854
15855  return;
15856 }
15857
15858 $headRef = $match[1];
15859 if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
15860
15861  return;
15862 }
15863
15864
15865  $branch = $matches[1][0];
15866 $unpushedChanges = null;
15867
15868
15869  for ($i = 0; $i <= 1; $i++) {
15870
15871  foreach ($matches[1] as $candidate) {
15872 if (preg_match('{^[a-f0-9]+ refs/remotes/((?:composer|origin)/'.preg_quote($candidate).')$}mi', $refs, $match)) {
15873 $branch = $candidate;
15874 $remoteBranch = $match[1];
15875 break;
15876 }
15877 }
15878
15879
15880  
15881  
15882  if (!isset($remoteBranch)) {
15883 $unpushedChanges = 'Branch ' . $branch . ' could not be found on the origin remote and appears to be unpushed';
15884 } else {
15885 $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
15886 if (0 !== $this->process->execute($command, $output, $path)) {
15887 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15888 }
15889
15890 $unpushedChanges = trim($output) ?: null;
15891 }
15892
15893
15894  
15895  if ($unpushedChanges && $i === 0) {
15896 $this->process->execute('git fetch composer && git fetch origin', $output, $path);
15897 }
15898
15899
15900  if (!$unpushedChanges) {
15901 break;
15902 }
15903 }
15904
15905 return $unpushedChanges;
15906 }
15907
15908
15909
15910
15911 protected function cleanChanges(PackageInterface $package, $path, $update)
15912 {
15913 GitUtil::cleanEnv();
15914 $path = $this->normalizePath($path);
15915
15916 $unpushed = $this->getUnpushedChanges($package, $path);
15917 if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== true)) {
15918 throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: '."\n".$unpushed);
15919 }
15920
15921 if (!$changes = $this->getLocalChanges($package, $path)) {
15922 return;
15923 }
15924
15925 if (!$this->io->isInteractive()) {
15926 $discardChanges = $this->config->get('discard-changes');
15927 if (true === $discardChanges) {
15928 return $this->discardChanges($path);
15929 }
15930 if ('stash' === $discardChanges) {
15931 if (!$update) {
15932 return parent::cleanChanges($package, $path, $update);
15933 }
15934
15935 return $this->stashChanges($path);
15936 }
15937
15938 return parent::cleanChanges($package, $path, $update);
15939 }
15940
15941 $changes = array_map(function ($elem) {
15942 return '    '.$elem;
15943 }, preg_split('{\s*\r?\n\s*}', $changes));
15944 $this->io->writeError('    <error>The package has modified files:</error>');
15945 $this->io->writeError(array_slice($changes, 0, 10));
15946 if (count($changes) > 10) {
15947 $this->io->writeError('    <info>' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list</info>');
15948 }
15949
15950 while (true) {
15951 switch ($this->io->ask('    <info>Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]?</info> ', '?')) {
15952 case 'y':
15953 $this->discardChanges($path);
15954 break 2;
15955
15956 case 's':
15957 if (!$update) {
15958 goto help;
15959 }
15960
15961 $this->stashChanges($path);
15962 break 2;
15963
15964 case 'n':
15965 throw new \RuntimeException('Update aborted');
15966
15967 case 'v':
15968 $this->io->writeError($changes);
15969 break;
15970
15971 case 'd':
15972 $this->viewDiff($path);
15973 break;
15974
15975 case '?':
15976 default:
15977 help:
15978 $this->io->writeError(array(
15979 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
15980 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
15981 '    v - view modified files',
15982 '    d - view local modifications (diff)',
15983 ));
15984 if ($update) {
15985 $this->io->writeError('    s - stash changes and try to reapply them after the update');
15986 }
15987 $this->io->writeError('    ? - print help');
15988 break;
15989 }
15990 }
15991 }
15992
15993
15994
15995
15996 protected function reapplyChanges($path)
15997 {
15998 $path = $this->normalizePath($path);
15999 if ($this->hasStashedChanges) {
16000 $this->hasStashedChanges = false;
16001 $this->io->writeError('    <info>Re-applying stashed changes</info>');
16002 if (0 !== $this->process->execute('git stash pop', $output, $path)) {
16003 throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
16004 }
16005 }
16006
16007 $this->hasDiscardedChanges = false;
16008 }
16009
16010
16011
16012
16013
16014
16015
16016
16017
16018
16019
16020 protected function updateToCommit($path, $reference, $branch, $date)
16021 {
16022 $force = $this->hasDiscardedChanges || $this->hasStashedChanges ? '-f ' : '';
16023
16024
16025  
16026  
16027  
16028  
16029  $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
16030 $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);
16031
16032 $branches = null;
16033 if (0 === $this->process->execute('git branch -r', $output, $path)) {
16034 $branches = $output;
16035 }
16036
16037
16038  $gitRef = $reference;
16039 if (!preg_match('{^[a-f0-9]{40}$}', $reference)
16040 && $branches
16041 && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
16042 ) {
16043 $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
16044 if (0 === $this->process->execute($command, $output, $path)) {
16045 return;
16046 }
16047 }
16048
16049
16050  if (preg_match('{^[a-f0-9]{40}$}', $reference)) {
16051
16052  if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) {
16053 $branch = 'v' . $branch;
16054 }
16055
16056 $command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
16057 $fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
16058 if (0 === $this->process->execute($command, $output, $path)
16059 || 0 === $this->process->execute($fallbackCommand, $output, $path)
16060 ) {
16061 $command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
16062 if (0 === $this->process->execute($command, $output, $path)) {
16063 return;
16064 }
16065 }
16066 }
16067
16068 $command = sprintf($template, ProcessExecutor::escape($gitRef));
16069 if (0 === $this->process->execute($command, $output, $path)) {
16070 return;
16071 }
16072
16073
16074  if (false !== strpos($this->process->getErrorOutput(), $reference)) {
16075 $this->io->writeError('    <warning>'.$reference.' is gone (history was rewritten?)</warning>');
16076 }
16077
16078 throw new \RuntimeException(GitUtil::sanitizeUrl('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
16079 }
16080
16081 protected function updateOriginUrl($path, $url)
16082 {
16083 $this->process->execute(sprintf('git remote set-url origin %s', ProcessExecutor::escape($url)), $output, $path);
16084 $this->setPushUrl($path, $url);
16085 }
16086
16087 protected function setPushUrl($path, $url)
16088 {
16089
16090  if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
16091 $protocols = $this->config->get('github-protocols');
16092 $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git';
16093 if (!in_array('ssh', $protocols, true)) {
16094 $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
16095 }
16096 $cmd = sprintf('git remote set-url --push origin %s', ProcessExecutor::escape($pushUrl));
16097 $this->process->execute($cmd, $ignoredOutput, $path);
16098 }
16099 }
16100
16101
16102
16103
16104 protected function getCommitLogs($fromReference, $toReference, $path)
16105 {
16106 $path = $this->normalizePath($path);
16107 $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
16108
16109 if (0 !== $this->process->execute($command, $output, $path)) {
16110 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16111 }
16112
16113 return $output;
16114 }
16115
16116
16117
16118
16119
16120 protected function discardChanges($path)
16121 {
16122 $path = $this->normalizePath($path);
16123 if (0 !== $this->process->execute('git reset --hard', $output, $path)) {
16124 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
16125 }
16126
16127 $this->hasDiscardedChanges = true;
16128 }
16129
16130
16131
16132
16133
16134 protected function stashChanges($path)
16135 {
16136 $path = $this->normalizePath($path);
16137 if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
16138 throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
16139 }
16140
16141 $this->hasStashedChanges = true;
16142 }
16143
16144
16145
16146
16147
16148 protected function viewDiff($path)
16149 {
16150 $path = $this->normalizePath($path);
16151 if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
16152 throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
16153 }
16154
16155 $this->io->writeError($output);
16156 }
16157
16158 protected function normalizePath($path)
16159 {
16160 if (Platform::isWindows() && strlen($path) > 0) {
16161 $basePath = $path;
16162 $removed = array();
16163
16164 while (!is_dir($basePath) && $basePath !== '\\') {
16165 array_unshift($removed, basename($basePath));
16166 $basePath = dirname($basePath);
16167 }
16168
16169 if ($basePath === '\\') {
16170 return $path;
16171 }
16172
16173 $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
16174 }
16175
16176 return $path;
16177 }
16178
16179
16180
16181
16182 protected function hasMetadataRepository($path)
16183 {
16184 $path = $this->normalizePath($path);
16185
16186 return is_dir($path.'/.git');
16187 }
16188
16189 protected function getShortHash($reference)
16190 {
16191 if (!$this->io->isVerbose() && preg_match('{^[0-9a-f]{40}$}', $reference)) {
16192 return substr($reference, 0, 10);
16193 }
16194
16195 return $reference;
16196 }
16197 }
16198 <?php
16199
16200
16201
16202
16203
16204
16205
16206
16207
16208
16209
16210 namespace Composer\Downloader;
16211
16212 use Composer\Config;
16213 use Composer\Cache;
16214 use Composer\EventDispatcher\EventDispatcher;
16215 use Composer\Package\PackageInterface;
16216 use Composer\Util\Platform;
16217 use Composer\Util\ProcessExecutor;
16218 use Composer\Util\RemoteFilesystem;
16219 use Composer\IO\IOInterface;
16220
16221
16222
16223
16224
16225
16226 class GzipDownloader extends ArchiveDownloader
16227 {
16228 protected $process;
16229
16230 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
16231 {
16232 $this->process = $process ?: new ProcessExecutor($io);
16233 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
16234 }
16235
16236 protected function extract($file, $path)
16237 {
16238 $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
16239
16240
16241  if (!Platform::isWindows()) {
16242 $command = 'gzip -cd ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
16243
16244 if (0 === $this->process->execute($command, $ignoredOutput)) {
16245 return;
16246 }
16247
16248 if (extension_loaded('zlib')) {
16249
16250  $this->extractUsingExt($file, $targetFilepath);
16251
16252 return;
16253 }
16254
16255 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
16256 throw new \RuntimeException($processError);
16257 }
16258
16259
16260  $this->extractUsingExt($file, $targetFilepath);
16261 }
16262
16263
16264
16265
16266 protected function getFileName(PackageInterface $package, $path)
16267 {
16268 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
16269 }
16270
16271 private function extractUsingExt($file, $targetFilepath)
16272 {
16273 $archiveFile = gzopen($file, 'rb');
16274 $targetFile = fopen($targetFilepath, 'wb');
16275 while ($string = gzread($archiveFile, 4096)) {
16276 fwrite($targetFile, $string, Platform::strlen($string));
16277 }
16278 gzclose($archiveFile);
16279 fclose($targetFile);
16280 }
16281 }
16282 <?php
16283
16284
16285
16286
16287
16288
16289
16290
16291
16292
16293
16294 namespace Composer\Downloader;
16295
16296 use Composer\Package\PackageInterface;
16297 use Composer\Util\ProcessExecutor;
16298 use Composer\Util\Hg as HgUtils;
16299
16300
16301
16302
16303 class HgDownloader extends VcsDownloader
16304 {
16305
16306
16307
16308 public function doDownload(PackageInterface $package, $path, $url)
16309 {
16310 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
16311
16312 $cloneCommand = function ($url) use ($path) {
16313 return sprintf('hg clone %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($path));
16314 };
16315
16316 $hgUtils->runCommand($cloneCommand, $url, $path);
16317
16318 $ref = ProcessExecutor::escape($package->getSourceReference());
16319 $command = sprintf('hg up %s', $ref);
16320 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16321 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16322 }
16323 }
16324
16325
16326
16327
16328 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16329 {
16330 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
16331
16332 $ref = $target->getSourceReference();
16333 $this->io->writeError(" Updating to ".$target->getSourceReference());
16334
16335 if (!$this->hasMetadataRepository($path)) {
16336 throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16337 }
16338
16339 $command = function ($url) use ($ref) {
16340 return sprintf('hg pull %s && hg up %s', ProcessExecutor::escape($url), ProcessExecutor::escape($ref));
16341 };
16342
16343 $hgUtils->runCommand($command, $url, $path);
16344 }
16345
16346
16347
16348
16349 public function getLocalChanges(PackageInterface $package, $path)
16350 {
16351 if (!is_dir($path.'/.hg')) {
16352 return null;
16353 }
16354
16355 $this->process->execute('hg st', $output, realpath($path));
16356
16357 return trim($output) ?: null;
16358 }
16359
16360
16361
16362
16363 protected function getCommitLogs($fromReference, $toReference, $path)
16364 {
16365 $command = sprintf('hg log -r %s:%s --style compact', ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
16366
16367 if (0 !== $this->process->execute($command, $output, realpath($path))) {
16368 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16369 }
16370
16371 return $output;
16372 }
16373
16374
16375
16376
16377 protected function hasMetadataRepository($path)
16378 {
16379 return is_dir($path . '/.hg');
16380 }
16381 }
16382 <?php
16383
16384
16385
16386
16387
16388
16389
16390
16391
16392
16393
16394 namespace Composer\Downloader;
16395
16396 use Composer\Package\Archiver\ArchivableFilesFinder;
16397 use Composer\Package\Dumper\ArrayDumper;
16398 use Composer\Package\PackageInterface;
16399 use Composer\Package\Version\VersionGuesser;
16400 use Composer\Package\Version\VersionParser;
16401 use Composer\Util\Platform;
16402 use Composer\Util\ProcessExecutor;
16403 use Composer\Util\Filesystem as ComposerFilesystem;
16404 use Symfony\Component\Filesystem\Exception\IOException;
16405 use Symfony\Component\Filesystem\Filesystem;
16406
16407
16408
16409
16410
16411
16412
16413 class PathDownloader extends FileDownloader implements VcsCapableDownloaderInterface
16414 {
16415 const STRATEGY_SYMLINK = 10;
16416 const STRATEGY_MIRROR = 20;
16417
16418
16419
16420
16421 public function download(PackageInterface $package, $path, $output = true)
16422 {
16423 $url = $package->getDistUrl();
16424 $realUrl = realpath($url);
16425 if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
16426 throw new \RuntimeException(sprintf(
16427 'Source path "%s" is not found for package %s',
16428 $url,
16429 $package->getName()
16430 ));
16431 }
16432
16433 if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
16434
16435  
16436  
16437  
16438  throw new \RuntimeException(sprintf(
16439 'Package %s cannot install to "%s" inside its source at "%s"',
16440 $package->getName(),
16441 realpath($path),
16442 $realUrl
16443 ));
16444 }
16445
16446
16447  $transportOptions = $package->getTransportOptions() + array('symlink' => null);
16448
16449
16450  $currentStrategy = self::STRATEGY_SYMLINK;
16451 $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
16452
16453 $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
16454 if ($mirrorPathRepos) {
16455 $currentStrategy = self::STRATEGY_MIRROR;
16456 }
16457
16458 if (true === $transportOptions['symlink']) {
16459 $currentStrategy = self::STRATEGY_SYMLINK;
16460 $allowedStrategies = array(self::STRATEGY_SYMLINK);
16461 } elseif (false === $transportOptions['symlink']) {
16462 $currentStrategy = self::STRATEGY_MIRROR;
16463 $allowedStrategies = array(self::STRATEGY_MIRROR);
16464 }
16465
16466 $fileSystem = new Filesystem();
16467 $this->filesystem->removeDirectory($path);
16468
16469 if ($output) {
16470 $this->io->writeError(sprintf(
16471 '  - Installing <info>%s</info> (<comment>%s</comment>): ',
16472 $package->getName(),
16473 $package->getFullPrettyVersion()
16474 ), false);
16475 }
16476
16477 $isFallback = false;
16478 if (self::STRATEGY_SYMLINK == $currentStrategy) {
16479 try {
16480 if (Platform::isWindows()) {
16481
16482  $this->io->writeError(sprintf('Junctioning from %s', $url), false);
16483 $this->filesystem->junction($realUrl, $path);
16484 } else {
16485 $absolutePath = $path;
16486 if (!$this->filesystem->isAbsolutePath($absolutePath)) {
16487 $absolutePath = getcwd() . DIRECTORY_SEPARATOR . $path;
16488 }
16489 $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
16490 $path = rtrim($path, "/");
16491 $this->io->writeError(sprintf('Symlinking from %s', $url), false);
16492 $fileSystem->symlink($shortestPath, $path);
16493 }
16494 } catch (IOException $e) {
16495 if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
16496 $this->io->writeError('');
16497 $this->io->writeError('    <error>Symlink failed, fallback to use mirroring!</error>');
16498 $currentStrategy = self::STRATEGY_MIRROR;
16499 $isFallback = true;
16500 } else {
16501 throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
16502 }
16503 }
16504 }
16505
16506
16507  if (self::STRATEGY_MIRROR == $currentStrategy) {
16508 $fs = new ComposerFilesystem();
16509 $realUrl = $fs->normalizePath($realUrl);
16510
16511 $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? '    ' : '', $url), false);
16512 $iterator = new ArchivableFilesFinder($realUrl, array());
16513 $fileSystem->mirror($realUrl, $path, $iterator);
16514 }
16515
16516 $this->io->writeError('');
16517 }
16518
16519
16520
16521
16522 public function remove(PackageInterface $package, $path, $output = true)
16523 {
16524
16525
16526
16527
16528
16529 if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
16530 if ($output) {
16531 $this->io->writeError("  - Removing junction for <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
16532 }
16533 if (!$this->filesystem->removeJunction($path)) {
16534 $this->io->writeError("    <warning>Could not remove junction at " . $path . " - is another process locking it?</warning>");
16535 throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
16536 }
16537 } else {
16538 parent::remove($package, $path, $output);
16539 }
16540 }
16541
16542
16543
16544
16545 public function getVcsReference(PackageInterface $package, $path)
16546 {
16547 $parser = new VersionParser;
16548 $guesser = new VersionGuesser($this->config, new ProcessExecutor($this->io), $parser);
16549 $dumper = new ArrayDumper;
16550
16551 $packageConfig = $dumper->dump($package);
16552 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
16553 return $packageVersion['commit'];
16554 }
16555 }
16556 }
16557 <?php
16558
16559
16560
16561
16562
16563
16564
16565
16566
16567
16568
16569 namespace Composer\Downloader;
16570
16571 use Composer\Util\Filesystem;
16572
16573
16574
16575
16576
16577
16578
16579
16580
16581
16582 class PearPackageExtractor
16583 {
16584 private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
16585
16586 private $filesystem;
16587 private $file;
16588
16589 public function __construct($file)
16590 {
16591 if (!is_file($file)) {
16592 throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
16593 }
16594
16595 $this->filesystem = new Filesystem();
16596 $this->file = $file;
16597 }
16598
16599
16600
16601
16602
16603
16604
16605
16606
16607
16608 public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
16609 {
16610 $extractionPath = $target.'/tarball';
16611
16612 try {
16613 $archive = new \PharData($this->file);
16614 $archive->extractTo($extractionPath, null, true);
16615
16616 if (!is_file($this->combine($extractionPath, '/package.xml'))) {
16617 throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
16618 }
16619
16620 $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
16621 $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
16622 $this->filesystem->removeDirectory($extractionPath);
16623 } catch (\Exception $exception) {
16624 throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
16625 }
16626 }
16627
16628
16629
16630
16631
16632
16633
16634
16635
16636
16637 private function copyFiles($files, $source, $target, $roles, $vars)
16638 {
16639 foreach ($files as $file) {
16640 $from = $this->combine($source, $file['from']);
16641 $to = $this->combine($target, $roles[$file['role']]);
16642 $to = $this->combine($to, $file['to']);
16643 $tasks = $file['tasks'];
16644 $this->copyFile($from, $to, $tasks, $vars);
16645 }
16646 }
16647
16648 private function copyFile($from, $to, $tasks, $vars)
16649 {
16650 if (!is_file($from)) {
16651 throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
16652 }
16653
16654 $this->filesystem->ensureDirectoryExists(dirname($to));
16655
16656 if (0 == count($tasks)) {
16657 $copied = copy($from, $to);
16658 } else {
16659 $content = file_get_contents($from);
16660 $replacements = array();
16661 foreach ($tasks as $task) {
16662 $pattern = $task['from'];
16663 $varName = $task['to'];
16664 if (isset($vars[$varName])) {
16665 if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
16666 $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
16667 } else {
16668 $replacements[$pattern] = $vars[$varName];
16669 }
16670 }
16671 }
16672 $content = strtr($content, $replacements);
16673
16674 $copied = file_put_contents($to, $content);
16675 }
16676
16677 if (false === $copied) {
16678 throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
16679 }
16680 }
16681
16682
16683
16684
16685
16686
16687
16688
16689
16690
16691
16692 private function buildCopyActions($source, array $roles, $vars)
16693 {
16694
16695 $package = simplexml_load_string(file_get_contents($this->combine($source, 'package.xml')));
16696 if (false === $package) {
16697 throw new \RuntimeException('Package definition file is not valid.');
16698 }
16699
16700 $packageSchemaVersion = $package['version'];
16701 if ('1.0' == $packageSchemaVersion) {
16702 $children = $package->release->filelist->children();
16703 $packageName = (string) $package->name;
16704 $packageVersion = (string) $package->release->version;
16705 $sourceDir = $packageName . '-' . $packageVersion;
16706 $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
16707 } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
16708 $children = $package->contents->children();
16709 $packageName = (string) $package->name;
16710 $packageVersion = (string) $package->version->release;
16711 $sourceDir = $packageName . '-' . $packageVersion;
16712 $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
16713
16714 $namespaces = $package->getNamespaces();
16715 $package->registerXPathNamespace('ns', $namespaces['']);
16716 $releaseNodes = $package->xpath('ns:phprelease');
16717 $this->applyRelease($result, $releaseNodes, $vars);
16718 } else {
16719 throw new \RuntimeException('Unsupported schema version of package definition file.');
16720 }
16721
16722 return $result;
16723 }
16724
16725 private function applyRelease(&$actions, $releaseNodes, $vars)
16726 {
16727 foreach ($releaseNodes as $releaseNode) {
16728 $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
16729 if ($requiredOs && $vars['os'] != $requiredOs) {
16730 continue;
16731 }
16732
16733 if ($releaseNode->filelist) {
16734 foreach ($releaseNode->filelist->children() as $action) {
16735 if ('install' == $action->getName()) {
16736 $name = (string) $action['name'];
16737 $as = (string) $action['as'];
16738 if (isset($actions[$name])) {
16739 $actions[$name]['to'] = $as;
16740 }
16741 } elseif ('ignore' == $action->getName()) {
16742 $name = (string) $action['name'];
16743 unset($actions[$name]);
16744 } else {
16745
16746  }
16747 }
16748 }
16749 break;
16750 }
16751 }
16752
16753 private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
16754 {
16755 $result = array();
16756
16757
16758  foreach ($children as $child) {
16759
16760 if ($child->getName() == 'dir') {
16761 $dirSource = $this->combine($source, (string) $child['name']);
16762 $dirTarget = $child['baseinstalldir'] ?: $target;
16763 $dirRole = $child['role'] ?: $role;
16764 $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16765 $result = array_merge($result, $dirFiles);
16766 } elseif ($child->getName() == 'file') {
16767 $fileRole = (string) $child['role'] ?: $role;
16768 if (isset($targetRoles[$fileRole])) {
16769 $fileName = (string) ($child['name'] ?: $child[0]); 
16770  $fileSource = $this->combine($source, $fileName);
16771 $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
16772 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16773 $fileTarget = $packageName . '/' . $fileTarget;
16774 }
16775 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
16776 }
16777 }
16778 }
16779
16780 return $result;
16781 }
16782
16783 private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
16784 {
16785 $result = array();
16786
16787
16788  foreach ($children as $child) {
16789
16790 if ('dir' == $child->getName()) {
16791 $dirSource = $this->combine($source, $child['name']);
16792 $dirTarget = $child['baseinstalldir'] ?: $target;
16793 $dirRole = $child['role'] ?: $role;
16794 $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16795 $result = array_merge($result, $dirFiles);
16796 } elseif ('file' == $child->getName()) {
16797 $fileRole = (string) $child['role'] ?: $role;
16798 if (isset($targetRoles[$fileRole])) {
16799 $fileSource = $this->combine($source, (string) $child['name']);
16800 $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
16801 $fileTasks = array();
16802 foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
16803 if ('replace' == $taskNode->getName()) {
16804 $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
16805 }
16806 }
16807 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16808 $fileTarget = $packageName . '/' . $fileTarget;
16809 }
16810 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
16811 }
16812 }
16813 }
16814
16815 return $result;
16816 }
16817
16818 private function combine($left, $right)
16819 {
16820 return rtrim($left, '/') . '/' . ltrim($right, '/');
16821 }
16822 }
16823 <?php
16824
16825
16826
16827
16828
16829
16830
16831
16832
16833
16834
16835 namespace Composer\Downloader;
16836
16837 use Composer\Package\PackageInterface;
16838 use Composer\Repository\VcsRepository;
16839 use Composer\Util\Perforce;
16840
16841
16842
16843
16844 class PerforceDownloader extends VcsDownloader
16845 {
16846
16847 protected $perforce;
16848
16849
16850
16851
16852 public function doDownload(PackageInterface $package, $path, $url)
16853 {
16854 $ref = $package->getSourceReference();
16855 $label = $this->getLabelFromSourceReference($ref);
16856
16857 $this->io->writeError('Cloning ' . $ref);
16858 $this->initPerforce($package, $path, $url);
16859 $this->perforce->setStream($ref);
16860 $this->perforce->p4Login();
16861 $this->perforce->writeP4ClientSpec();
16862 $this->perforce->connectClient();
16863 $this->perforce->syncCodeBase($label);
16864 $this->perforce->cleanupClientSpec();
16865 }
16866
16867 private function getLabelFromSourceReference($ref)
16868 {
16869 $pos = strpos($ref, '@');
16870 if (false !== $pos) {
16871 return substr($ref, $pos + 1);
16872 }
16873
16874 return null;
16875 }
16876
16877 public function initPerforce(PackageInterface $package, $path, $url)
16878 {
16879 if (!empty($this->perforce)) {
16880 $this->perforce->initializePath($path);
16881
16882 return;
16883 }
16884
16885 $repository = $package->getRepository();
16886 $repoConfig = null;
16887 if ($repository instanceof VcsRepository) {
16888 $repoConfig = $this->getRepoConfig($repository);
16889 }
16890 $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
16891 }
16892
16893 private function getRepoConfig(VcsRepository $repository)
16894 {
16895 return $repository->getRepoConfig();
16896 }
16897
16898
16899
16900
16901 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16902 {
16903 $this->doDownload($target, $path, $url);
16904 }
16905
16906
16907
16908
16909 public function getLocalChanges(PackageInterface $package, $path)
16910 {
16911 $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
16912
16913 return;
16914 }
16915
16916
16917
16918
16919 protected function getCommitLogs($fromReference, $toReference, $path)
16920 {
16921 return $this->perforce->getCommitLogs($fromReference, $toReference);
16922 }
16923
16924 public function setPerforce($perforce)
16925 {
16926 $this->perforce = $perforce;
16927 }
16928
16929
16930
16931
16932 protected function hasMetadataRepository($path)
16933 {
16934 return true;
16935 }
16936 }
16937 <?php
16938
16939
16940
16941
16942
16943
16944
16945
16946
16947
16948
16949 namespace Composer\Downloader;
16950
16951
16952
16953
16954
16955
16956 class PharDownloader extends ArchiveDownloader
16957 {
16958
16959
16960
16961 protected function extract($file, $path)
16962 {
16963
16964  $archive = new \Phar($file);
16965 $archive->extractTo($path, null, true);
16966
16967
16968
16969
16970
16971 }
16972 }
16973 <?php
16974
16975
16976
16977
16978
16979
16980
16981
16982
16983
16984
16985 namespace Composer\Downloader;
16986
16987 use Composer\Config;
16988 use Composer\Cache;
16989 use Composer\EventDispatcher\EventDispatcher;
16990 use Composer\Util\IniHelper;
16991 use Composer\Util\Platform;
16992 use Composer\Util\ProcessExecutor;
16993 use Composer\Util\RemoteFilesystem;
16994 use Composer\IO\IOInterface;
16995 use RarArchive;
16996
16997
16998
16999
17000
17001
17002
17003
17004 class RarDownloader extends ArchiveDownloader
17005 {
17006 protected $process;
17007
17008 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17009 {
17010 $this->process = $process ?: new ProcessExecutor($io);
17011 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17012 }
17013
17014 protected function extract($file, $path)
17015 {
17016 $processError = null;
17017
17018
17019  if (!Platform::isWindows()) {
17020 $command = 'unrar x ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
17021
17022 if (0 === $this->process->execute($command, $ignoredOutput)) {
17023 return;
17024 }
17025
17026 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
17027 }
17028
17029 if (!class_exists('RarArchive')) {
17030
17031  $iniMessage = IniHelper::getMessage();
17032
17033 $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n"
17034 . $iniMessage . "\n" . $processError;
17035
17036 if (!Platform::isWindows()) {
17037 $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
17038 }
17039
17040 throw new \RuntimeException($error);
17041 }
17042
17043 $rarArchive = RarArchive::open($file);
17044
17045 if (false === $rarArchive) {
17046 throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
17047 }
17048
17049 $entries = $rarArchive->getEntries();
17050
17051 if (false === $entries) {
17052 throw new \RuntimeException('Could not retrieve RAR archive entries');
17053 }
17054
17055 foreach ($entries as $entry) {
17056 if (false === $entry->extract($path)) {
17057 throw new \RuntimeException('Could not extract entry');
17058 }
17059 }
17060
17061 $rarArchive->close();
17062 }
17063 }
17064 <?php
17065
17066
17067
17068
17069
17070
17071
17072
17073
17074
17075
17076 namespace Composer\Downloader;
17077
17078 use Composer\Package\PackageInterface;
17079 use Composer\Util\Svn as SvnUtil;
17080 use Composer\Repository\VcsRepository;
17081 use Composer\Util\ProcessExecutor;
17082
17083
17084
17085
17086
17087 class SvnDownloader extends VcsDownloader
17088 {
17089 protected $cacheCredentials = true;
17090
17091
17092
17093
17094 public function doDownload(PackageInterface $package, $path, $url)
17095 {
17096 SvnUtil::cleanEnv();
17097 $ref = $package->getSourceReference();
17098
17099 $repo = $package->getRepository();
17100 if ($repo instanceof VcsRepository) {
17101 $repoConfig = $repo->getRepoConfig();
17102 if (array_key_exists('svn-cache-credentials', $repoConfig)) {
17103 $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials'];
17104 }
17105 }
17106
17107 $this->io->writeError(" Checking out ".$package->getSourceReference());
17108 $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
17109 }
17110
17111
17112
17113
17114 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
17115 {
17116 SvnUtil::cleanEnv();
17117 $ref = $target->getSourceReference();
17118
17119 if (!$this->hasMetadataRepository($path)) {
17120 throw new \RuntimeException('The .svn directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
17121 }
17122
17123 $util = new SvnUtil($url, $this->io, $this->config);
17124 $flags = "";
17125 if (version_compare($util->binaryVersion(), '1.7.0', '>=')) {
17126 $flags .= ' --ignore-ancestry';
17127 }
17128
17129 $this->io->writeError(" Checking out " . $ref);
17130 $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
17131 }
17132
17133
17134
17135
17136 public function getLocalChanges(PackageInterface $package, $path)
17137 {
17138 if (!$this->hasMetadataRepository($path)) {
17139 return null;
17140 }
17141
17142 $this->process->execute('svn status --ignore-externals', $output, $path);
17143
17144 return preg_match('{^ *[^X ] +}m', $output) ? $output : null;
17145 }
17146
17147
17148
17149
17150
17151
17152
17153
17154
17155
17156
17157
17158
17159 protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
17160 {
17161 $util = new SvnUtil($baseUrl, $this->io, $this->config);
17162 $util->setCacheCredentials($this->cacheCredentials);
17163 try {
17164 return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
17165 } catch (\RuntimeException $e) {
17166 throw new \RuntimeException(
17167 'Package could not be downloaded, '.$e->getMessage()
17168 );
17169 }
17170 }
17171
17172
17173
17174
17175 protected function cleanChanges(PackageInterface $package, $path, $update)
17176 {
17177 if (!$changes = $this->getLocalChanges($package, $path)) {
17178 return;
17179 }
17180
17181 if (!$this->io->isInteractive()) {
17182 if (true === $this->config->get('discard-changes')) {
17183 return $this->discardChanges($path);
17184 }
17185
17186 return parent::cleanChanges($package, $path, $update);
17187 }
17188
17189 $changes = array_map(function ($elem) {
17190 return '    '.$elem;
17191 }, preg_split('{\s*\r?\n\s*}', $changes));
17192 $countChanges = count($changes);
17193 $this->io->writeError(sprintf('    <error>The package has modified file%s:</error>', $countChanges === 1 ? '' : 's'));
17194 $this->io->writeError(array_slice($changes, 0, 10));
17195 if ($countChanges > 10) {
17196 $remaingChanges = $countChanges - 10;
17197 $this->io->writeError(
17198 sprintf(
17199 '    <info>'.$remaingChanges.' more file%s modified, choose "v" to view the full list</info>',
17200 $remaingChanges === 1 ? '' : 's'
17201 )
17202 );
17203 }
17204
17205 while (true) {
17206 switch ($this->io->ask('    <info>Discard changes [y,n,v,?]?</info> ', '?')) {
17207 case 'y':
17208 $this->discardChanges($path);
17209 break 2;
17210
17211 case 'n':
17212 throw new \RuntimeException('Update aborted');
17213
17214 case 'v':
17215 $this->io->writeError($changes);
17216 break;
17217
17218 case '?':
17219 default:
17220 $this->io->writeError(array(
17221 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
17222 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
17223 '    v - view modified files',
17224 '    ? - print help',
17225 ));
17226 break;
17227 }
17228 }
17229 }
17230
17231
17232
17233
17234 protected function getCommitLogs($fromReference, $toReference, $path)
17235 {
17236 if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
17237
17238  $command = sprintf('svn info --non-interactive --xml %s', ProcessExecutor::escape($path));
17239 if (0 !== $this->process->execute($command, $output, $path)) {
17240 throw new \RuntimeException(
17241 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
17242 );
17243 }
17244
17245 $urlPattern = '#<url>(.*)</url>#';
17246 if (preg_match($urlPattern, $output, $matches)) {
17247 $baseUrl = $matches[1];
17248 } else {
17249 throw new \RuntimeException(
17250 'Unable to determine svn url for path '. $path
17251 );
17252 }
17253
17254
17255  $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
17256 $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
17257
17258 $command = sprintf('svn log -r%s:%s --incremental', ProcessExecutor::escape($fromRevision), ProcessExecutor::escape($toRevision));
17259
17260 $util = new SvnUtil($baseUrl, $this->io, $this->config);
17261 $util->setCacheCredentials($this->cacheCredentials);
17262 try {
17263 return $util->executeLocal($command, $path, null, $this->io->isVerbose());
17264 } catch (\RuntimeException $e) {
17265 throw new \RuntimeException(
17266 'Failed to execute ' . $command . "\n\n".$e->getMessage()
17267 );
17268 }
17269 }
17270
17271 return "Could not retrieve changes between $fromReference and $toReference due to missing revision information";
17272 }
17273
17274 protected function discardChanges($path)
17275 {
17276 if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
17277 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
17278 }
17279 }
17280
17281
17282
17283
17284 protected function hasMetadataRepository($path)
17285 {
17286 return is_dir($path.'/.svn');
17287 }
17288 }
17289 <?php
17290
17291
17292
17293
17294
17295
17296
17297
17298
17299
17300
17301 namespace Composer\Downloader;
17302
17303
17304
17305
17306
17307
17308 class TarDownloader extends ArchiveDownloader
17309 {
17310
17311
17312
17313 protected function extract($file, $path)
17314 {
17315
17316  $archive = new \PharData($file);
17317 $archive->extractTo($path, null, true);
17318 }
17319 }
17320 <?php
17321
17322
17323
17324
17325
17326
17327
17328
17329
17330
17331
17332 namespace Composer\Downloader;
17333
17334
17335
17336
17337 class TransportException extends \RuntimeException
17338 {
17339 protected $headers;
17340 protected $response;
17341 protected $statusCode;
17342
17343 public function setHeaders($headers)
17344 {
17345 $this->headers = $headers;
17346 }
17347
17348 public function getHeaders()
17349 {
17350 return $this->headers;
17351 }
17352
17353 public function setResponse($response)
17354 {
17355 $this->response = $response;
17356 }
17357
17358 public function getResponse()
17359 {
17360 return $this->response;
17361 }
17362
17363 public function setStatusCode($statusCode)
17364 {
17365 $this->statusCode = $statusCode;
17366 }
17367
17368 public function getStatusCode()
17369 {
17370 return $this->statusCode;
17371 }
17372 }
17373 <?php
17374
17375
17376
17377
17378
17379
17380
17381
17382
17383
17384
17385 namespace Composer\Downloader;
17386
17387 use Composer\Package\PackageInterface;
17388
17389
17390
17391
17392
17393
17394 interface VcsCapableDownloaderInterface
17395 {
17396
17397
17398
17399
17400
17401
17402
17403 public function getVcsReference(PackageInterface $package, $path);
17404 }
17405 <?php
17406
17407
17408
17409
17410
17411
17412
17413
17414
17415
17416
17417 namespace Composer\Downloader;
17418
17419 use Composer\Config;
17420 use Composer\Package\Dumper\ArrayDumper;
17421 use Composer\Package\PackageInterface;
17422 use Composer\Package\Version\VersionGuesser;
17423 use Composer\Package\Version\VersionParser;
17424 use Composer\Util\ProcessExecutor;
17425 use Composer\IO\IOInterface;
17426 use Composer\Util\Filesystem;
17427
17428
17429
17430
17431 abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterface, VcsCapableDownloaderInterface
17432 {
17433
17434 protected $io;
17435
17436 protected $config;
17437
17438 protected $process;
17439
17440 protected $filesystem;
17441
17442 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
17443 {
17444 $this->io = $io;
17445 $this->config = $config;
17446 $this->process = $process ?: new ProcessExecutor($io);
17447 $this->filesystem = $fs ?: new Filesystem($this->process);
17448 }
17449
17450
17451
17452
17453 public function getInstallationSource()
17454 {
17455 return 'source';
17456 }
17457
17458
17459
17460
17461 public function download(PackageInterface $package, $path)
17462 {
17463 if (!$package->getSourceReference()) {
17464 throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
17465 }
17466
17467 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
17468 $this->filesystem->emptyDirectory($path);
17469
17470 $urls = $package->getSourceUrls();
17471 while ($url = array_shift($urls)) {
17472 try {
17473 if (Filesystem::isLocalPath($url)) {
17474
17475  
17476  $needle = 'file://';
17477 $isFileProtocol = false;
17478 if (0 === strpos($url, $needle)) {
17479 $url = substr($url, strlen($needle));
17480 $isFileProtocol = true;
17481 }
17482
17483
17484  if (false !== strpos($url, '%')) {
17485 $url = rawurldecode($url);
17486 }
17487
17488 $url = realpath($url);
17489
17490 if ($isFileProtocol) {
17491 $url = $needle . $url;
17492 }
17493 }
17494 $this->doDownload($package, $path, $url);
17495 break;
17496 } catch (\Exception $e) {
17497
17498  if ($e instanceof \PHPUnit_Framework_Exception) {
17499 throw $e;
17500 }
17501 if ($this->io->isDebug()) {
17502 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
17503 } elseif (count($urls)) {
17504 $this->io->writeError('    Failed, trying the next URL');
17505 }
17506 if (!count($urls)) {
17507 throw $e;
17508 }
17509 }
17510 }
17511 }
17512
17513
17514
17515
17516 public function update(PackageInterface $initial, PackageInterface $target, $path)
17517 {
17518 if (!$target->getSourceReference()) {
17519 throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
17520 }
17521
17522 $name = $target->getName();
17523 if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
17524 if ($target->getSourceType() === 'svn') {
17525 $from = $initial->getSourceReference();
17526 $to = $target->getSourceReference();
17527 } else {
17528 $from = substr($initial->getSourceReference(), 0, 7);
17529 $to = substr($target->getSourceReference(), 0, 7);
17530 }
17531 $name .= ' '.$initial->getPrettyVersion();
17532 } else {
17533 $from = $initial->getFullPrettyVersion();
17534 $to = $target->getFullPrettyVersion();
17535 }
17536
17537 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
17538 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
17539
17540 $this->cleanChanges($initial, $path, true);
17541 $urls = $target->getSourceUrls();
17542
17543 $exception = null;
17544 while ($url = array_shift($urls)) {
17545 try {
17546 if (Filesystem::isLocalPath($url)) {
17547 $url = realpath($url);
17548 }
17549 $this->doUpdate($initial, $target, $path, $url);
17550
17551 $exception = null;
17552 break;
17553 } catch (\Exception $exception) {
17554
17555  if ($exception instanceof \PHPUnit_Framework_Exception) {
17556 throw $exception;
17557 }
17558 if ($this->io->isDebug()) {
17559 $this->io->writeError('Failed: ['.get_class($exception).'] '.$exception->getMessage());
17560 } elseif (count($urls)) {
17561 $this->io->writeError('    Failed, trying the next URL');
17562 }
17563 }
17564 }
17565
17566 $this->reapplyChanges($path);
17567
17568
17569  
17570  if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
17571 $message = 'Pulling in changes:';
17572 $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
17573
17574 if (!trim($logs)) {
17575 $message = 'Rolling back changes:';
17576 $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
17577 }
17578
17579 if (trim($logs)) {
17580 $logs = implode("\n", array_map(function ($line) {
17581 return '      ' . $line;
17582 }, explode("\n", $logs)));
17583
17584
17585  $logs = str_replace('<', '\<', $logs);
17586
17587 $this->io->writeError('    '.$message);
17588 $this->io->writeError($logs);
17589 }
17590 }
17591
17592 if (!$urls && $exception) {
17593 throw $exception;
17594 }
17595 }
17596
17597
17598
17599
17600 public function remove(PackageInterface $package, $path)
17601 {
17602 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
17603 $this->cleanChanges($package, $path, false);
17604 if (!$this->filesystem->removeDirectory($path)) {
17605 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
17606 }
17607 }
17608
17609
17610
17611
17612
17613 public function setOutputProgress($outputProgress)
17614 {
17615 return $this;
17616 }
17617
17618
17619
17620
17621 public function getVcsReference(PackageInterface $package, $path)
17622 {
17623 $parser = new VersionParser;
17624 $guesser = new VersionGuesser($this->config, $this->process, $parser);
17625 $dumper = new ArrayDumper;
17626
17627 $packageConfig = $dumper->dump($package);
17628 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
17629 return $packageVersion['commit'];
17630 }
17631 }
17632
17633
17634
17635
17636
17637
17638
17639
17640
17641
17642 protected function cleanChanges(PackageInterface $package, $path, $update)
17643 {
17644
17645  if (null !== $this->getLocalChanges($package, $path)) {
17646 throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
17647 }
17648 }
17649
17650
17651
17652
17653
17654
17655
17656 protected function reapplyChanges($path)
17657 {
17658 }
17659
17660
17661
17662
17663
17664
17665
17666
17667 abstract protected function doDownload(PackageInterface $package, $path, $url);
17668
17669
17670
17671
17672
17673
17674
17675
17676
17677 abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
17678
17679
17680
17681
17682
17683
17684
17685
17686
17687 abstract protected function getCommitLogs($fromReference, $toReference, $path);
17688
17689
17690
17691
17692
17693
17694
17695
17696 abstract protected function hasMetadataRepository($path);
17697 }
17698 <?php
17699
17700
17701
17702
17703
17704
17705
17706
17707
17708
17709
17710 namespace Composer\Downloader;
17711
17712 use Composer\Config;
17713 use Composer\Cache;
17714 use Composer\EventDispatcher\EventDispatcher;
17715 use Composer\Package\PackageInterface;
17716 use Composer\Util\ProcessExecutor;
17717 use Composer\Util\RemoteFilesystem;
17718 use Composer\IO\IOInterface;
17719
17720
17721
17722
17723
17724
17725
17726 class XzDownloader extends ArchiveDownloader
17727 {
17728 protected $process;
17729
17730 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17731 {
17732 $this->process = $process ?: new ProcessExecutor($io);
17733
17734 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17735 }
17736
17737 protected function extract($file, $path)
17738 {
17739 $command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
17740
17741 if (0 === $this->process->execute($command, $ignoredOutput)) {
17742 return;
17743 }
17744
17745 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
17746
17747 throw new \RuntimeException($processError);
17748 }
17749
17750
17751
17752
17753 protected function getFileName(PackageInterface $package, $path)
17754 {
17755 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
17756 }
17757 }
17758 <?php
17759
17760
17761
17762
17763
17764
17765
17766
17767
17768
17769
17770 namespace Composer\Downloader;
17771
17772 use Composer\Config;
17773 use Composer\Cache;
17774 use Composer\EventDispatcher\EventDispatcher;
17775 use Composer\Package\PackageInterface;
17776 use Composer\Util\IniHelper;
17777 use Composer\Util\Platform;
17778 use Composer\Util\ProcessExecutor;
17779 use Composer\Util\RemoteFilesystem;
17780 use Composer\IO\IOInterface;
17781 use Symfony\Component\Process\ExecutableFinder;
17782 use ZipArchive;
17783
17784
17785
17786
17787 class ZipDownloader extends ArchiveDownloader
17788 {
17789 protected static $hasSystemUnzip;
17790 private static $hasZipArchive;
17791 private static $isWindows;
17792
17793 protected $process;
17794 private $zipArchiveObject;
17795
17796 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17797 {
17798 $this->process = $process ?: new ProcessExecutor($io);
17799 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17800 }
17801
17802
17803
17804
17805 public function download(PackageInterface $package, $path, $output = true)
17806 {
17807 if (null === self::$hasSystemUnzip) {
17808 $finder = new ExecutableFinder;
17809 self::$hasSystemUnzip = (bool) $finder->find('unzip');
17810 }
17811
17812 if (null === self::$hasZipArchive) {
17813 self::$hasZipArchive = class_exists('ZipArchive');
17814 }
17815
17816 if (!self::$hasZipArchive && !self::$hasSystemUnzip) {
17817
17818  $iniMessage = IniHelper::getMessage();
17819 $error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
17820
17821 throw new \RuntimeException($error);
17822 }
17823
17824 if (null === self::$isWindows) {
17825 self::$isWindows = Platform::isWindows();
17826
17827 if (!self::$isWindows && !self::$hasSystemUnzip) {
17828 $this->io->writeError("<warning>As there is no 'unzip' command installed zip files are being unpacked using the PHP zip extension.</warning>");
17829 $this->io->writeError("<warning>This may cause invalid reports of corrupted archives. Installing 'unzip' may remediate them.</warning>");
17830 }
17831 }
17832
17833 return parent::download($package, $path, $output);
17834 }
17835
17836
17837
17838
17839
17840
17841
17842
17843
17844 protected function extractWithSystemUnzip($file, $path, $isLastChance)
17845 {
17846 if (!self::$hasZipArchive) {
17847
17848  $isLastChance = true;
17849 }
17850
17851 if (!self::$hasSystemUnzip && !$isLastChance) {
17852
17853  
17854  return $this->extractWithZipArchive($file, $path, true);
17855 }
17856
17857 $processError = null;
17858
17859  $overwrite = $isLastChance ? '-o' : '';
17860
17861 $command = 'unzip -qq '.$overwrite.' '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
17862
17863 try {
17864 if (0 === $this->process->execute($command, $ignoredOutput)) {
17865 return true;
17866 }
17867
17868 $processError = new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17869 } catch (\Exception $e) {
17870 $processError = $e;
17871 }
17872
17873 if ($isLastChance) {
17874 throw $processError;
17875 }
17876
17877 $this->io->writeError('    '.$processError->getMessage());
17878 $this->io->writeError('    The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
17879 $this->io->writeError('    Unzip with unzip command failed, falling back to ZipArchive class');
17880
17881 return $this->extractWithZipArchive($file, $path, true);
17882 }
17883
17884
17885
17886
17887
17888
17889
17890
17891
17892 protected function extractWithZipArchive($file, $path, $isLastChance)
17893 {
17894 if (!self::$hasSystemUnzip) {
17895
17896  $isLastChance = true;
17897 }
17898
17899 if (!self::$hasZipArchive && !$isLastChance) {
17900
17901  
17902  return $this->extractWithSystemUnzip($file, $path, true);
17903 }
17904
17905 $processError = null;
17906 $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
17907
17908 try {
17909 if (true === ($retval = $zipArchive->open($file))) {
17910 $extractResult = $zipArchive->extractTo($path);
17911
17912 if (true === $extractResult) {
17913 $zipArchive->close();
17914
17915 return true;
17916 }
17917
17918 $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
17919 } else {
17920 $processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file)."\n"), $retval);
17921 }
17922 } catch (\ErrorException $e) {
17923 $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
17924 } catch (\Exception $e) {
17925 $processError = $e;
17926 }
17927
17928 if ($isLastChance) {
17929 throw $processError;
17930 }
17931
17932 $this->io->writeError('    '.$processError->getMessage());
17933 $this->io->writeError('    Unzip with ZipArchive class failed, falling back to unzip command');
17934
17935 return $this->extractWithSystemUnzip($file, $path, true);
17936 }
17937
17938
17939
17940
17941
17942
17943
17944 public function extract($file, $path)
17945 {
17946
17947  if (self::$isWindows) {
17948 $this->extractWithZipArchive($file, $path, false);
17949 } else {
17950 $this->extractWithSystemUnzip($file, $path, false);
17951 }
17952 }
17953
17954
17955
17956
17957
17958
17959
17960
17961 protected function getErrorMessage($retval, $file)
17962 {
17963 switch ($retval) {
17964 case ZipArchive::ER_EXISTS:
17965 return sprintf("File '%s' already exists.", $file);
17966 case ZipArchive::ER_INCONS:
17967 return sprintf("Zip archive '%s' is inconsistent.", $file);
17968 case ZipArchive::ER_INVAL:
17969 return sprintf("Invalid argument (%s)", $file);
17970 case ZipArchive::ER_MEMORY:
17971 return sprintf("Malloc failure (%s)", $file);
17972 case ZipArchive::ER_NOENT:
17973 return sprintf("No such zip file: '%s'", $file);
17974 case ZipArchive::ER_NOZIP:
17975 return sprintf("'%s' is not a zip archive.", $file);
17976 case ZipArchive::ER_OPEN:
17977 return sprintf("Can't open zip file: %s", $file);
17978 case ZipArchive::ER_READ:
17979 return sprintf("Zip read error (%s)", $file);
17980 case ZipArchive::ER_SEEK:
17981 return sprintf("Zip seek error (%s)", $file);
17982 default:
17983 return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
17984 }
17985 }
17986 }
17987 <?php
17988
17989
17990
17991
17992
17993
17994
17995
17996
17997
17998
17999 namespace Composer\EventDispatcher;
18000
18001
18002
18003
18004
18005
18006 class Event
18007 {
18008
18009
18010
18011 protected $name;
18012
18013
18014
18015
18016 protected $args;
18017
18018
18019
18020
18021 protected $flags;
18022
18023
18024
18025
18026 private $propagationStopped = false;
18027
18028
18029
18030
18031
18032
18033
18034
18035 public function __construct($name, array $args = array(), array $flags = array())
18036 {
18037 $this->name = $name;
18038 $this->args = $args;
18039 $this->flags = $flags;
18040 }
18041
18042
18043
18044
18045
18046
18047 public function getName()
18048 {
18049 return $this->name;
18050 }
18051
18052
18053
18054
18055
18056
18057 public function getArguments()
18058 {
18059 return $this->args;
18060 }
18061
18062
18063
18064
18065
18066
18067 public function getFlags()
18068 {
18069 return $this->flags;
18070 }
18071
18072
18073
18074
18075
18076
18077 public function isPropagationStopped()
18078 {
18079 return $this->propagationStopped;
18080 }
18081
18082
18083
18084
18085 public function stopPropagation()
18086 {
18087 $this->propagationStopped = true;
18088 }
18089 }
18090 <?php
18091
18092
18093
18094
18095
18096
18097
18098
18099
18100
18101
18102 namespace Composer\EventDispatcher;
18103
18104 use Composer\DependencyResolver\PolicyInterface;
18105 use Composer\DependencyResolver\Pool;
18106 use Composer\DependencyResolver\Request;
18107 use Composer\Installer\InstallerEvent;
18108 use Composer\IO\IOInterface;
18109 use Composer\Composer;
18110 use Composer\DependencyResolver\Operation\OperationInterface;
18111 use Composer\Repository\CompositeRepository;
18112 use Composer\Script;
18113 use Composer\Installer\PackageEvent;
18114 use Composer\Installer\BinaryInstaller;
18115 use Composer\Util\ProcessExecutor;
18116 use Composer\Script\Event as ScriptEvent;
18117 use Symfony\Component\Process\PhpExecutableFinder;
18118
18119
18120
18121
18122
18123
18124
18125
18126
18127
18128
18129
18130
18131
18132 class EventDispatcher
18133 {
18134 protected $composer;
18135 protected $io;
18136 protected $loader;
18137 protected $process;
18138 protected $listeners;
18139 private $eventStack;
18140
18141
18142
18143
18144
18145
18146
18147
18148 public function __construct(Composer $composer, IOInterface $io, ProcessExecutor $process = null)
18149 {
18150 $this->composer = $composer;
18151 $this->io = $io;
18152 $this->process = $process ?: new ProcessExecutor($io);
18153 $this->eventStack = array();
18154 }
18155
18156
18157
18158
18159
18160
18161
18162
18163
18164 public function dispatch($eventName, Event $event = null)
18165 {
18166 if (null === $event) {
18167 $event = new Event($eventName);
18168 }
18169
18170 return $this->doDispatch($event);
18171 }
18172
18173
18174
18175
18176
18177
18178
18179
18180
18181
18182
18183 public function dispatchScript($eventName, $devMode = false, $additionalArgs = array(), $flags = array())
18184 {
18185 return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
18186 }
18187
18188
18189
18190
18191
18192
18193
18194
18195
18196
18197
18198
18199
18200
18201
18202
18203 public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
18204 {
18205 return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
18206 }
18207
18208
18209
18210
18211
18212
18213
18214
18215
18216
18217
18218
18219
18220
18221
18222 public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
18223 {
18224 return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
18225 }
18226
18227
18228
18229
18230
18231
18232
18233
18234
18235 protected function doDispatch(Event $event)
18236 {
18237 $pathStr = 'PATH';
18238 if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
18239 $pathStr = 'Path';
18240 }
18241
18242
18243  $binDir = $this->composer->getConfig()->get('bin-dir');
18244 if (is_dir($binDir)) {
18245 $binDir = realpath($binDir);
18246 if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
18247 $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
18248 putenv($pathStr.'='.$_SERVER[$pathStr]);
18249 }
18250 }
18251
18252 $listeners = $this->getListeners($event);
18253
18254 $this->pushEvent($event);
18255
18256 $return = 0;
18257 foreach ($listeners as $callable) {
18258 if (!is_string($callable)) {
18259 if (!is_callable($callable)) {
18260 $className = is_object($callable[0]) ? get_class($callable[0]) : $callable[0];
18261
18262 throw new \RuntimeException('Subscriber '.$className.'::'.$callable[1].' for event '.$event->getName().' is not callable, make sure the function is defined and public');
18263 }
18264 $event = $this->checkListenerExpectedEvent($callable, $event);
18265 $return = false === call_user_func($callable, $event) ? 1 : 0;
18266 } elseif ($this->isComposerScript($callable)) {
18267 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
18268 $scriptName = substr($callable, 1);
18269 $args = $event->getArguments();
18270 $flags = $event->getFlags();
18271 if (substr($callable, 0, 10) === '@composer ') {
18272 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
18273 if (0 !== ($exitCode = $this->process->execute($exec))) {
18274 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
18275
18276 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
18277 }
18278 } else {
18279 if (!$this->getListeners(new Event($scriptName))) {
18280 $this->io->writeError(sprintf('<warning>You made a reference to a non-existent script %s</warning>', $callable), true, IOInterface::QUIET);
18281 }
18282
18283 try {
18284 $return = $this->dispatch($scriptName, new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags));
18285 } catch (ScriptExecutionException $e) {
18286 $this->io->writeError(sprintf('<error>Script %s was called via %s</error>', $callable, $event->getName()), true, IOInterface::QUIET);
18287 throw $e;
18288 }
18289 }
18290 } elseif ($this->isPhpScript($callable)) {
18291 $className = substr($callable, 0, strpos($callable, '::'));
18292 $methodName = substr($callable, strpos($callable, '::') + 2);
18293
18294 if (!class_exists($className)) {
18295 $this->io->writeError('<warning>Class '.$className.' is not autoloadable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
18296 continue;
18297 }
18298 if (!is_callable($callable)) {
18299 $this->io->writeError('<warning>Method '.$callable.' is not callable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
18300 continue;
18301 }
18302
18303 try {
18304 $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
18305 } catch (\Exception $e) {
18306 $message = "Script %s handling the %s event terminated with an exception";
18307 $this->io->writeError('<error>'.sprintf($message, $callable, $event->getName()).'</error>', true, IOInterface::QUIET);
18308 throw $e;
18309 }
18310 } else {
18311 $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
18312 $exec = $callable . ($args === '' ? '' : ' '.$args);
18313 if ($this->io->isVerbose()) {
18314 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
18315 } else {
18316 $this->io->writeError(sprintf('> %s', $exec));
18317 }
18318
18319 $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
18320 if ($possibleLocalBinaries) {
18321 foreach ($possibleLocalBinaries as $localExec) {
18322 if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
18323 $caller = BinaryInstaller::determineBinaryCaller($localExec);
18324 $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
18325 break;
18326 }
18327 }
18328 }
18329
18330 if (substr($exec, 0, 5) === '@php ') {
18331 $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
18332 }
18333
18334 if (0 !== ($exitCode = $this->process->execute($exec))) {
18335 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
18336
18337 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
18338 }
18339 }
18340
18341 if ($event->isPropagationStopped()) {
18342 break;
18343 }
18344 }
18345
18346 $this->popEvent();
18347
18348 return $return;
18349 }
18350
18351 protected function getPhpExecCommand()
18352 {
18353 $finder = new PhpExecutableFinder();
18354 $phpPath = $finder->find();
18355 if (!$phpPath) {
18356 throw new \RuntimeException('Failed to locate PHP binary to execute '.$scriptName);
18357 }
18358
18359 $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
18360 $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
18361 $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
18362
18363 return ProcessExecutor::escape($phpPath) . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag;
18364 }
18365
18366
18367
18368
18369
18370
18371 protected function executeEventPhpScript($className, $methodName, Event $event)
18372 {
18373 $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
18374
18375 if ($this->io->isVerbose()) {
18376 $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
18377 } else {
18378 $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
18379 }
18380
18381 return $className::$methodName($event);
18382 }
18383
18384
18385
18386
18387
18388
18389 protected function checkListenerExpectedEvent($target, Event $event)
18390 {
18391 if (in_array($event->getName(), array(
18392 'init',
18393 'command',
18394 'pre-file-download',
18395 ), true)) {
18396 return $event;
18397 }
18398
18399 try {
18400 $reflected = new \ReflectionParameter($target, 0);
18401 } catch (\Exception $e) {
18402 return $event;
18403 }
18404
18405 $typehint = $reflected->getClass();
18406
18407 if (!$typehint instanceof \ReflectionClass) {
18408 return $event;
18409 }
18410
18411 $expected = $typehint->getName();
18412
18413
18414  if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
18415 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);
18416 $event = new \Composer\Script\CommandEvent(
18417 $event->getName(),
18418 $event->getComposer(),
18419 $event->getIO(),
18420 $event->isDevMode(),
18421 $event->getArguments()
18422 );
18423 }
18424 if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
18425 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);
18426 $event = new \Composer\Script\PackageEvent(
18427 $event->getName(),
18428 $event->getComposer(),
18429 $event->getIO(),
18430 $event->isDevMode(),
18431 $event->getPolicy(),
18432 $event->getPool(),
18433 $event->getInstalledRepo(),
18434 $event->getRequest(),
18435 $event->getOperations(),
18436 $event->getOperation()
18437 );
18438 }
18439 if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
18440 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);
18441 $event = new \Composer\Script\Event(
18442 $event->getName(),
18443 $event->getComposer(),
18444 $event->getIO(),
18445 $event->isDevMode(),
18446 $event->getArguments(),
18447 $event->getFlags()
18448 );
18449 }
18450
18451 return $event;
18452 }
18453
18454 private function serializeCallback($cb)
18455 {
18456 if (is_array($cb) && count($cb) === 2) {
18457 if (is_object($cb[0])) {
18458 $cb[0] = get_class($cb[0]);
18459 }
18460 if (is_string($cb[0]) && is_string($cb[1])) {
18461 $cb = implode('::', $cb);
18462 }
18463 }
18464 if (is_string($cb)) {
18465 return $cb;
18466 }
18467
18468 return var_export($cb, true);
18469 }
18470
18471
18472
18473
18474
18475
18476
18477
18478 public function addListener($eventName, $listener, $priority = 0)
18479 {
18480 $this->listeners[$eventName][$priority][] = $listener;
18481 }
18482
18483
18484
18485
18486
18487
18488
18489
18490 public function addSubscriber(EventSubscriberInterface $subscriber)
18491 {
18492 foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
18493 if (is_string($params)) {
18494 $this->addListener($eventName, array($subscriber, $params));
18495 } elseif (is_string($params[0])) {
18496 $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
18497 } else {
18498 foreach ($params as $listener) {
18499 $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
18500 }
18501 }
18502 }
18503 }
18504
18505
18506
18507
18508
18509
18510
18511 protected function getListeners(Event $event)
18512 {
18513 $scriptListeners = $this->getScriptListeners($event);
18514
18515 if (!isset($this->listeners[$event->getName()][0])) {
18516 $this->listeners[$event->getName()][0] = array();
18517 }
18518 krsort($this->listeners[$event->getName()]);
18519
18520 $listeners = $this->listeners;
18521 $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
18522
18523 return call_user_func_array('array_merge', $listeners[$event->getName()]);
18524 }
18525
18526
18527
18528
18529
18530
18531
18532 public function hasEventListeners(Event $event)
18533 {
18534 $listeners = $this->getListeners($event);
18535
18536 return count($listeners) > 0;
18537 }
18538
18539
18540
18541
18542
18543
18544
18545 protected function getScriptListeners(Event $event)
18546 {
18547 $package = $this->composer->getPackage();
18548 $scripts = $package->getScripts();
18549
18550 if (empty($scripts[$event->getName()])) {
18551 return array();
18552 }
18553
18554 if ($this->loader) {
18555 $this->loader->unregister();
18556 }
18557
18558 $generator = $this->composer->getAutoloadGenerator();
18559 if ($event instanceof ScriptEvent) {
18560 $generator->setDevMode($event->isDevMode());
18561 }
18562
18563 $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
18564 $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
18565 $map = $generator->parseAutoloads($packageMap, $package);
18566 $this->loader = $generator->createLoader($map);
18567 $this->loader->register();
18568
18569 return $scripts[$event->getName()];
18570 }
18571
18572
18573
18574
18575
18576
18577
18578 protected function isPhpScript($callable)
18579 {
18580 return false === strpos($callable, ' ') && false !== strpos($callable, '::');
18581 }
18582
18583
18584
18585
18586
18587
18588
18589 protected function isComposerScript($callable)
18590 {
18591 return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5);
18592 }
18593
18594
18595
18596
18597
18598
18599
18600
18601 protected function pushEvent(Event $event)
18602 {
18603 $eventName = $event->getName();
18604 if (in_array($eventName, $this->eventStack)) {
18605 throw new \RuntimeException(sprintf("Circular call to script handler '%s' detected", $eventName));
18606 }
18607
18608 return array_push($this->eventStack, $eventName);
18609 }
18610
18611
18612
18613
18614
18615
18616 protected function popEvent()
18617 {
18618 return array_pop($this->eventStack);
18619 }
18620 }
18621 <?php
18622
18623
18624
18625
18626
18627
18628
18629
18630
18631
18632
18633 namespace Composer\EventDispatcher;
18634
18635
18636
18637
18638
18639
18640
18641
18642
18643
18644
18645
18646
18647 interface EventSubscriberInterface
18648 {
18649
18650
18651
18652
18653
18654
18655
18656
18657
18658
18659
18660
18661
18662
18663
18664
18665
18666
18667 public static function getSubscribedEvents();
18668 }
18669 <?php
18670
18671
18672
18673
18674
18675
18676
18677
18678
18679
18680
18681 namespace Composer\EventDispatcher;
18682
18683
18684
18685
18686 class ScriptExecutionException extends \RuntimeException
18687 {
18688 }
18689 <?php
18690
18691
18692
18693
18694
18695
18696
18697
18698
18699
18700
18701 namespace Composer\Exception;
18702
18703
18704
18705
18706 class NoSslException extends \RuntimeException
18707 {
18708 }
18709 <?php
18710
18711
18712
18713
18714
18715
18716
18717
18718
18719
18720
18721 namespace Composer;
18722
18723 use Composer\Config\JsonConfigSource;
18724 use Composer\Json\JsonFile;
18725 use Composer\IO\IOInterface;
18726 use Composer\Package\Archiver;
18727 use Composer\Package\Version\VersionGuesser;
18728 use Composer\Repository\RepositoryManager;
18729 use Composer\Repository\RepositoryFactory;
18730 use Composer\Repository\WritableRepositoryInterface;
18731 use Composer\Util\Filesystem;
18732 use Composer\Util\Platform;
18733 use Composer\Util\ProcessExecutor;
18734 use Composer\Util\RemoteFilesystem;
18735 use Composer\Util\Silencer;
18736 use Composer\Plugin\PluginEvents;
18737 use Composer\EventDispatcher\Event;
18738 use Seld\JsonLint\DuplicateKeyException;
18739 use Symfony\Component\Console\Formatter\OutputFormatter;
18740 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
18741 use Symfony\Component\Console\Output\ConsoleOutput;
18742 use Composer\EventDispatcher\EventDispatcher;
18743 use Composer\Autoload\AutoloadGenerator;
18744 use Composer\Package\Version\VersionParser;
18745 use Composer\Downloader\TransportException;
18746 use Seld\JsonLint\JsonParser;
18747
18748
18749
18750
18751
18752
18753
18754
18755
18756 class Factory
18757 {
18758
18759
18760
18761
18762 protected static function getHomeDir()
18763 {
18764 $home = getenv('COMPOSER_HOME');
18765 if ($home) {
18766 return $home;
18767 }
18768
18769 if (Platform::isWindows()) {
18770 if (!getenv('APPDATA')) {
18771 throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
18772 }
18773
18774 return rtrim(strtr(getenv('APPDATA'), '\\', '/'), '/') . '/Composer';
18775 }
18776
18777 $userDir = self::getUserDir();
18778 if (is_dir($userDir . '/.composer')) {
18779 return $userDir . '/.composer';
18780 }
18781
18782 if (self::useXdg()) {
18783
18784  $xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
18785
18786 return $xdgConfig . '/composer';
18787 }
18788
18789 return $userDir . '/.composer';
18790 }
18791
18792
18793
18794
18795
18796 protected static function getCacheDir($home)
18797 {
18798 $cacheDir = getenv('COMPOSER_CACHE_DIR');
18799 if ($cacheDir) {
18800 return $cacheDir;
18801 }
18802
18803 $homeEnv = getenv('COMPOSER_HOME');
18804 if ($homeEnv) {
18805 return $homeEnv . '/cache';
18806 }
18807
18808 if (Platform::isWindows()) {
18809 if ($cacheDir = getenv('LOCALAPPDATA')) {
18810 $cacheDir .= '/Composer';
18811 } else {
18812 $cacheDir = $home . '/cache';
18813 }
18814
18815 return rtrim(strtr($cacheDir, '\\', '/'), '/');
18816 }
18817
18818 $userDir = self::getUserDir();
18819 if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
18820 return $home . '/cache';
18821 }
18822
18823 if (self::useXdg()) {
18824 $xdgCache = getenv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
18825
18826 return $xdgCache . '/composer';
18827 }
18828
18829 return $home . '/cache';
18830 }
18831
18832
18833
18834
18835
18836 protected static function getDataDir($home)
18837 {
18838 $homeEnv = getenv('COMPOSER_HOME');
18839 if ($homeEnv) {
18840 return $homeEnv;
18841 }
18842
18843 if (Platform::isWindows()) {
18844 return strtr($home, '\\', '/');
18845 }
18846
18847 $userDir = self::getUserDir();
18848 if ($home !== $userDir . '/.composer' && self::useXdg()) {
18849 $xdgData = getenv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
18850
18851 return $xdgData . '/composer';
18852 }
18853
18854 return $home;
18855 }
18856
18857
18858
18859
18860
18861 public static function createConfig(IOInterface $io = null, $cwd = null)
18862 {
18863 $cwd = $cwd ?: getcwd();
18864
18865 $config = new Config(true, $cwd);
18866
18867
18868  $home = self::getHomeDir();
18869 $config->merge(array('config' => array(
18870 'home' => $home,
18871 'cache-dir' => self::getCacheDir($home),
18872 'data-dir' => self::getDataDir($home),
18873 )));
18874
18875 $htaccessProtect = (bool) $config->get('htaccess-protect');
18876 if ($htaccessProtect) {
18877
18878  
18879  
18880  $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
18881 foreach ($dirs as $dir) {
18882 if (!file_exists($dir . '/.htaccess')) {
18883 if (!is_dir($dir)) {
18884 Silencer::call('mkdir', $dir, 0777, true);
18885 }
18886 Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
18887 }
18888 }
18889 }
18890
18891
18892  $file = new JsonFile($config->get('home').'/config.json');
18893 if ($file->exists()) {
18894 if ($io && $io->isDebug()) {
18895 $io->writeError('Loading config file ' . $file->getPath());
18896 }
18897 $config->merge($file->read());
18898 }
18899 $config->setConfigSource(new JsonConfigSource($file));
18900
18901
18902  $file = new JsonFile($config->get('home').'/auth.json');
18903 if ($file->exists()) {
18904 if ($io && $io->isDebug()) {
18905 $io->writeError('Loading config file ' . $file->getPath());
18906 }
18907 $config->merge(array('config' => $file->read()));
18908 }
18909 $config->setAuthConfigSource(new JsonConfigSource($file, true));
18910
18911
18912  if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
18913 $authData = json_decode($composerAuthEnv, true);
18914
18915 if (null === $authData) {
18916 throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
18917 }
18918
18919 if ($io && $io->isDebug()) {
18920 $io->writeError('Loading auth config from COMPOSER_AUTH');
18921 }
18922 $config->merge(array('config' => $authData));
18923 }
18924
18925 return $config;
18926 }
18927
18928 public static function getComposerFile()
18929 {
18930 return trim(getenv('COMPOSER')) ?: './composer.json';
18931 }
18932
18933 public static function createAdditionalStyles()
18934 {
18935 return array(
18936 'highlight' => new OutputFormatterStyle('red'),
18937 'warning' => new OutputFormatterStyle('black', 'yellow'),
18938 );
18939 }
18940
18941
18942
18943
18944
18945
18946 public static function createOutput()
18947 {
18948 $styles = self::createAdditionalStyles();
18949 $formatter = new OutputFormatter(false, $styles);
18950
18951 return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
18952 }
18953
18954
18955
18956
18957 public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
18958 {
18959 return RepositoryFactory::defaultRepos($io, $config, $rm);
18960 }
18961
18962
18963
18964
18965
18966
18967
18968
18969
18970
18971
18972
18973
18974 public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
18975 {
18976 $cwd = $cwd ?: getcwd();
18977
18978
18979  if (null === $localConfig) {
18980 $localConfig = static::getComposerFile();
18981 }
18982
18983 if (is_string($localConfig)) {
18984 $composerFile = $localConfig;
18985
18986 $file = new JsonFile($localConfig, null, $io);
18987
18988 if (!$file->exists()) {
18989 if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
18990 $message = 'Composer could not find a composer.json file in '.$cwd;
18991 } else {
18992 $message = 'Composer could not find the config file: '.$localConfig;
18993 }
18994 $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section';
18995 throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
18996 }
18997
18998 $file->validateSchema(JsonFile::LAX_SCHEMA);
18999 $jsonParser = new JsonParser;
19000 try {
19001 $jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS);
19002 } catch (DuplicateKeyException $e) {
19003 $details = $e->getDetails();
19004 $io->writeError('<warning>Key '.$details['key'].' is a duplicate in '.$localConfig.' at line '.$details['line'].'</warning>');
19005 }
19006
19007 $localConfig = $file->read();
19008 }
19009
19010
19011  $config = static::createConfig($io, $cwd);
19012 $config->merge($localConfig);
19013 if (isset($composerFile)) {
19014 $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
19015 $config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
19016
19017 $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
19018 if ($localAuthFile->exists()) {
19019 $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
19020 $config->merge(array('config' => $localAuthFile->read()));
19021 $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
19022 }
19023 }
19024
19025 $vendorDir = $config->get('vendor-dir');
19026
19027
19028  $composer = new Composer();
19029 $composer->setConfig($config);
19030
19031 if ($fullLoad) {
19032
19033  $io->loadConfiguration($config);
19034 }
19035
19036 $rfs = self::createRemoteFilesystem($io, $config);
19037
19038
19039  $dispatcher = new EventDispatcher($composer, $io);
19040 $composer->setEventDispatcher($dispatcher);
19041
19042
19043  $rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
19044 $composer->setRepositoryManager($rm);
19045
19046
19047  $this->addLocalRepository($io, $rm, $vendorDir);
19048
19049
19050  
19051  if (!$fullLoad && !isset($localConfig['version'])) {
19052 $localConfig['version'] = '1.0.0';
19053 }
19054
19055
19056  $parser = new VersionParser;
19057 $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
19058 $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser);
19059 $package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
19060 $composer->setPackage($package);
19061
19062
19063  $im = $this->createInstallationManager();
19064 $composer->setInstallationManager($im);
19065
19066 if ($fullLoad) {
19067
19068  $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
19069 $composer->setDownloadManager($dm);
19070
19071
19072  $generator = new AutoloadGenerator($dispatcher, $io);
19073 $composer->setAutoloadGenerator($generator);
19074
19075
19076  $am = $this->createArchiveManager($config, $dm);
19077 $composer->setArchiveManager($am);
19078 }
19079
19080
19081  $this->createDefaultInstallers($im, $composer, $io);
19082
19083 if ($fullLoad) {
19084 $globalComposer = null;
19085 if (realpath($config->get('home')) !== $cwd) {
19086 $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
19087 }
19088
19089 $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
19090 $composer->setPluginManager($pm);
19091
19092 $pm->loadInstalledPlugins();
19093 }
19094
19095
19096  if ($fullLoad && isset($composerFile)) {
19097 $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
19098 ? substr($composerFile, 0, -4).'lock'
19099 : $composerFile . '.lock';
19100
19101 $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile));
19102 $composer->setLocker($locker);
19103 }
19104
19105 if ($fullLoad) {
19106 $initEvent = new Event(PluginEvents::INIT);
19107 $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent);
19108
19109
19110  
19111  if ($rm->getLocalRepository()) {
19112 $this->purgePackages($rm->getLocalRepository(), $im);
19113 }
19114 }
19115
19116 return $composer;
19117 }
19118
19119
19120
19121
19122
19123
19124 public static function createGlobal(IOInterface $io, $disablePlugins = false)
19125 {
19126 $factory = new static();
19127
19128 return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, true);
19129 }
19130
19131
19132
19133
19134
19135 protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir)
19136 {
19137 $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io)));
19138 }
19139
19140
19141
19142
19143
19144 protected function createGlobalComposer(IOInterface $io, Config $config, $disablePlugins, $fullLoad = false)
19145 {
19146 $composer = null;
19147 try {
19148 $composer = $this->createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad);
19149 } catch (\Exception $e) {
19150 $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
19151 }
19152
19153 return $composer;
19154 }
19155
19156
19157
19158
19159
19160
19161
19162 public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
19163 {
19164 $cache = null;
19165 if ($config->get('cache-files-ttl') > 0) {
19166 $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
19167 }
19168
19169 $dm = new Downloader\DownloadManager($io);
19170 switch ($preferred = $config->get('preferred-install')) {
19171 case 'dist':
19172 $dm->setPreferDist(true);
19173 break;
19174 case 'source':
19175 $dm->setPreferSource(true);
19176 break;
19177 case 'auto':
19178 default:
19179
19180  break;
19181 }
19182
19183 if (is_array($preferred)) {
19184 $dm->setPreferences($preferred);
19185 }
19186
19187 $executor = new ProcessExecutor($io);
19188 $fs = new Filesystem($executor);
19189
19190 $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs));
19191 $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs));
19192 $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $executor, $fs));
19193 $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs));
19194 $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
19195 $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19196 $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19197 $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19198 $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19199 $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19200 $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19201 $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19202 $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19203
19204 return $dm;
19205 }
19206
19207
19208
19209
19210
19211
19212 public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
19213 {
19214 if (null === $dm) {
19215 $io = new IO\NullIO();
19216 $io->loadConfiguration($config);
19217 $dm = $this->createDownloadManager($io, $config);
19218 }
19219
19220 $am = new Archiver\ArchiveManager($dm);
19221 $am->addArchiver(new Archiver\ZipArchiver);
19222 $am->addArchiver(new Archiver\PharArchiver);
19223
19224 return $am;
19225 }
19226
19227
19228
19229
19230
19231
19232
19233
19234 protected function createPluginManager(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
19235 {
19236 return new Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
19237 }
19238
19239
19240
19241
19242 protected function createInstallationManager()
19243 {
19244 return new Installer\InstallationManager();
19245 }
19246
19247
19248
19249
19250
19251
19252 protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
19253 {
19254 $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
19255 $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
19256 $im->addInstaller(new Installer\PluginInstaller($io, $composer));
19257 $im->addInstaller(new Installer\MetapackageInstaller());
19258 }
19259
19260
19261
19262
19263
19264 protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
19265 {
19266 foreach ($repo->getPackages() as $package) {
19267 if (!$im->isPackageInstalled($repo, $package)) {
19268 $repo->removePackage($package);
19269 }
19270 }
19271 }
19272
19273
19274
19275
19276
19277
19278
19279
19280 public static function create(IOInterface $io, $config = null, $disablePlugins = false)
19281 {
19282 $factory = new static();
19283
19284 return $factory->createComposer($io, $config, $disablePlugins);
19285 }
19286
19287
19288
19289
19290
19291
19292
19293 public static function createRemoteFilesystem(IOInterface $io, Config $config = null, $options = array())
19294 {
19295 static $warned = false;
19296 $disableTls = false;
19297 if ($config && $config->get('disable-tls') === true) {
19298 if (!$warned) {
19299 $io->write('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
19300 }
19301 $warned = true;
19302 $disableTls = true;
19303 } elseif (!extension_loaded('openssl')) {
19304 throw new Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. '
19305 . '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.');
19306 }
19307 $remoteFilesystemOptions = array();
19308 if ($disableTls === false) {
19309 if ($config && $config->get('cafile')) {
19310 $remoteFilesystemOptions['ssl']['cafile'] = $config->get('cafile');
19311 }
19312 if ($config && $config->get('capath')) {
19313 $remoteFilesystemOptions['ssl']['capath'] = $config->get('capath');
19314 }
19315 $remoteFilesystemOptions = array_replace_recursive($remoteFilesystemOptions, $options);
19316 }
19317 try {
19318 $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);
19319 } catch (TransportException $e) {
19320 if (false !== strpos($e->getMessage(), 'cafile')) {
19321 $io->write('<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>');
19322 $io->write('<error>A valid CA certificate file is required for SSL/TLS protection.</error>');
19323 if (PHP_VERSION_ID < 50600) {
19324 $io->write('<error>It is recommended you upgrade to PHP 5.6+ which can detect your system CA file automatically.</error>');
19325 }
19326 $io->write('<error>You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.</error>');
19327 }
19328 throw $e;
19329 }
19330
19331 return $remoteFilesystem;
19332 }
19333
19334
19335
19336
19337 private static function useXdg()
19338 {
19339 foreach (array_keys($_SERVER) as $key) {
19340 if (substr($key, 0, 4) === 'XDG_') {
19341 return true;
19342 }
19343 }
19344
19345 return false;
19346 }
19347
19348
19349
19350
19351
19352 private static function getUserDir()
19353 {
19354 $home = getenv('HOME');
19355 if (!$home) {
19356 throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
19357 }
19358
19359 return rtrim(strtr($home, '\\', '/'), '/');
19360 }
19361 }
19362 <?php
19363
19364
19365
19366
19367
19368
19369
19370
19371
19372
19373
19374 namespace Composer\IO;
19375
19376 use Composer\Config;
19377 use Composer\Util\ProcessExecutor;
19378 use Psr\Log\LoggerInterface;
19379 use Psr\Log\LogLevel;
19380
19381 abstract class BaseIO implements IOInterface, LoggerInterface
19382 {
19383 protected $authentications = array();
19384
19385
19386
19387
19388 public function getAuthentications()
19389 {
19390 return $this->authentications;
19391 }
19392
19393
19394
19395
19396 public function hasAuthentication($repositoryName)
19397 {
19398 return isset($this->authentications[$repositoryName]);
19399 }
19400
19401
19402
19403
19404 public function getAuthentication($repositoryName)
19405 {
19406 if (isset($this->authentications[$repositoryName])) {
19407 return $this->authentications[$repositoryName];
19408 }
19409
19410 return array('username' => null, 'password' => null);
19411 }
19412
19413
19414
19415
19416 public function setAuthentication($repositoryName, $username, $password = null)
19417 {
19418 $this->authentications[$repositoryName] = array('username' => $username, 'password' => $password);
19419 }
19420
19421
19422
19423
19424
19425
19426
19427
19428 protected function checkAndSetAuthentication($repositoryName, $username, $password = null)
19429 {
19430 if ($this->hasAuthentication($repositoryName)) {
19431 $auth = $this->getAuthentication($repositoryName);
19432 if ($auth['username'] === $username && $auth['password'] === $password) {
19433 return;
19434 }
19435
19436 $this->writeError(
19437 sprintf(
19438 "<warning>Warning: You should avoid overwriting already defined auth settings for %s.</warning>",
19439 $repositoryName
19440 )
19441 );
19442 }
19443 $this->setAuthentication($repositoryName, $username, $password);
19444 }
19445
19446
19447
19448
19449 public function loadConfiguration(Config $config)
19450 {
19451 $bitbucketOauth = $config->get('bitbucket-oauth') ?: array();
19452 $githubOauth = $config->get('github-oauth') ?: array();
19453 $gitlabOauth = $config->get('gitlab-oauth') ?: array();
19454 $gitlabToken = $config->get('gitlab-token') ?: array();
19455 $httpBasic = $config->get('http-basic') ?: array();
19456
19457
19458
19459 foreach ($bitbucketOauth as $domain => $cred) {
19460 $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']);
19461 }
19462
19463 foreach ($githubOauth as $domain => $token) {
19464 if (!preg_match('{^[.a-z0-9]+$}', $token)) {
19465 throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
19466 }
19467 $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic');
19468 }
19469
19470 foreach ($gitlabOauth as $domain => $token) {
19471 $this->checkAndSetAuthentication($domain, $token, 'oauth2');
19472 }
19473
19474 foreach ($gitlabToken as $domain => $token) {
19475 $this->checkAndSetAuthentication($domain, $token, 'private-token');
19476 }
19477
19478
19479  foreach ($httpBasic as $domain => $cred) {
19480 $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
19481 }
19482
19483
19484  ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
19485 }
19486
19487
19488
19489
19490
19491
19492
19493
19494 public function emergency($message, array $context = array())
19495 {
19496 return $this->log(LogLevel::EMERGENCY, $message, $context);
19497 }
19498
19499
19500
19501
19502
19503
19504
19505
19506
19507
19508
19509 public function alert($message, array $context = array())
19510 {
19511 return $this->log(LogLevel::ALERT, $message, $context);
19512 }
19513
19514
19515
19516
19517
19518
19519
19520
19521
19522
19523 public function critical($message, array $context = array())
19524 {
19525 return $this->log(LogLevel::CRITICAL, $message, $context);
19526 }
19527
19528
19529
19530
19531
19532
19533
19534
19535
19536 public function error($message, array $context = array())
19537 {
19538 return $this->log(LogLevel::ERROR, $message, $context);
19539 }
19540
19541
19542
19543
19544
19545
19546
19547
19548
19549
19550
19551 public function warning($message, array $context = array())
19552 {
19553 return $this->log(LogLevel::WARNING, $message, $context);
19554 }
19555
19556
19557
19558
19559
19560
19561
19562
19563 public function notice($message, array $context = array())
19564 {
19565 return $this->log(LogLevel::NOTICE, $message, $context);
19566 }
19567
19568
19569
19570
19571
19572
19573
19574
19575
19576
19577 public function info($message, array $context = array())
19578 {
19579 return $this->log(LogLevel::INFO, $message, $context);
19580 }
19581
19582
19583
19584
19585
19586
19587
19588
19589 public function debug($message, array $context = array())
19590 {
19591 return $this->log(LogLevel::DEBUG, $message, $context);
19592 }
19593
19594
19595
19596
19597
19598
19599
19600
19601
19602 public function log($level, $message, array $context = array())
19603 {
19604 if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
19605 $this->writeError('<error>'.$message.'</error>', true, self::NORMAL);
19606 } elseif ($level === LogLevel::WARNING) {
19607 $this->writeError('<warning>'.$message.'</warning>', true, self::NORMAL);
19608 } elseif ($level === LogLevel::NOTICE) {
19609 $this->writeError('<info>'.$message.'</info>', true, self::VERBOSE);
19610 } elseif ($level === LogLevel::INFO) {
19611 $this->writeError('<info>'.$message.'</info>', true, self::VERY_VERBOSE);
19612 } else {
19613 $this->writeError($message, true, self::DEBUG);
19614 }
19615 }
19616 }
19617 <?php
19618
19619
19620
19621
19622
19623
19624
19625
19626
19627
19628
19629 namespace Composer\IO;
19630
19631 use Symfony\Component\Console\Output\StreamOutput;
19632 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
19633 use Symfony\Component\Console\Input\StringInput;
19634 use Symfony\Component\Console\Helper\HelperSet;
19635
19636
19637
19638
19639 class BufferIO extends ConsoleIO
19640 {
19641
19642
19643
19644
19645
19646 public function __construct($input = '', $verbosity = StreamOutput::VERBOSITY_NORMAL, OutputFormatterInterface $formatter = null)
19647 {
19648 $input = new StringInput($input);
19649 $input->setInteractive(false);
19650
19651 $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
19652
19653 parent::__construct($input, $output, new HelperSet(array()));
19654 }
19655
19656 public function getOutput()
19657 {
19658 fseek($this->output->getStream(), 0);
19659
19660 $output = stream_get_contents($this->output->getStream());
19661
19662 $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) {
19663 $pre = strip_tags($matches[1]);
19664
19665 if (strlen($pre) === strlen($matches[2])) {
19666 return '';
19667 }
19668
19669
19670  return rtrim($matches[1])."\n";
19671 }, $output);
19672
19673 return $output;
19674 }
19675 }
19676 <?php
19677
19678
19679
19680
19681
19682
19683
19684
19685
19686
19687
19688 namespace Composer\IO;
19689
19690 use Composer\Question\StrictConfirmationQuestion;
19691 use Symfony\Component\Console\Helper\HelperSet;
19692 use Symfony\Component\Console\Input\InputInterface;
19693 use Symfony\Component\Console\Output\ConsoleOutputInterface;
19694 use Symfony\Component\Console\Output\OutputInterface;
19695 use Symfony\Component\Console\Question\ChoiceQuestion;
19696 use Symfony\Component\Console\Question\Question;
19697
19698
19699
19700
19701
19702
19703
19704 class ConsoleIO extends BaseIO
19705 {
19706
19707 protected $input;
19708
19709 protected $output;
19710
19711 protected $helperSet;
19712
19713 protected $lastMessage;
19714
19715 protected $lastMessageErr;
19716
19717
19718 private $startTime;
19719
19720 private $verbosityMap;
19721
19722
19723
19724
19725
19726
19727
19728
19729 public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
19730 {
19731 $this->input = $input;
19732 $this->output = $output;
19733 $this->helperSet = $helperSet;
19734 $this->verbosityMap = array(
19735 self::QUIET => OutputInterface::VERBOSITY_QUIET,
19736 self::NORMAL => OutputInterface::VERBOSITY_NORMAL,
19737 self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
19738 self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
19739 self::DEBUG => OutputInterface::VERBOSITY_DEBUG,
19740 );
19741 }
19742
19743
19744
19745
19746 public function enableDebugging($startTime)
19747 {
19748 $this->startTime = $startTime;
19749 }
19750
19751
19752
19753
19754 public function isInteractive()
19755 {
19756 return $this->input->isInteractive();
19757 }
19758
19759
19760
19761
19762 public function isDecorated()
19763 {
19764 return $this->output->isDecorated();
19765 }
19766
19767
19768
19769
19770 public function isVerbose()
19771 {
19772 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
19773 }
19774
19775
19776
19777
19778 public function isVeryVerbose()
19779 {
19780 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
19781 }
19782
19783
19784
19785
19786 public function isDebug()
19787 {
19788 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
19789 }
19790
19791
19792
19793
19794 public function write($messages, $newline = true, $verbosity = self::NORMAL)
19795 {
19796 $this->doWrite($messages, $newline, false, $verbosity);
19797 }
19798
19799
19800
19801
19802 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
19803 {
19804 $this->doWrite($messages, $newline, true, $verbosity);
19805 }
19806
19807
19808
19809
19810
19811
19812
19813 private function doWrite($messages, $newline, $stderr, $verbosity)
19814 {
19815 $sfVerbosity = $this->verbosityMap[$verbosity];
19816 if ($sfVerbosity > $this->output->getVerbosity()) {
19817 return;
19818 }
19819
19820
19821  
19822  
19823  if (OutputInterface::VERBOSITY_QUIET === 0) {
19824 $sfVerbosity = OutputInterface::OUTPUT_NORMAL;
19825 }
19826
19827 if (null !== $this->startTime) {
19828 $memoryUsage = memory_get_usage() / 1024 / 1024;
19829 $timeSpent = microtime(true) - $this->startTime;
19830 $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
19831 return sprintf('[%.1fMB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
19832 }, (array) $messages);
19833 }
19834
19835 if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
19836 $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
19837 $this->lastMessageErr = implode($newline ? "\n" : '', (array) $messages);
19838
19839 return;
19840 }
19841
19842 $this->output->write($messages, $newline, $sfVerbosity);
19843 $this->lastMessage = implode($newline ? "\n" : '', (array) $messages);
19844 }
19845
19846
19847
19848
19849 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19850 {
19851 $this->doOverwrite($messages, $newline, $size, false, $verbosity);
19852 }
19853
19854
19855
19856
19857 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19858 {
19859 $this->doOverwrite($messages, $newline, $size, true, $verbosity);
19860 }
19861
19862
19863
19864
19865
19866
19867
19868
19869 private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
19870 {
19871
19872  $messages = implode($newline ? "\n" : '', (array) $messages);
19873
19874
19875  if (!isset($size)) {
19876
19877  $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
19878 }
19879
19880  $this->doWrite(str_repeat("\x08", $size), false, $stderr, $verbosity);
19881
19882
19883  $this->doWrite($messages, false, $stderr, $verbosity);
19884
19885
19886  
19887  
19888  $fill = $size - strlen(strip_tags($messages));
19889 if ($fill > 0) {
19890
19891  $this->doWrite(str_repeat(' ', $fill), false, $stderr, $verbosity);
19892
19893  $this->doWrite(str_repeat("\x08", $fill), false, $stderr, $verbosity);
19894 }
19895
19896 if ($newline) {
19897 $this->doWrite('', true, $stderr, $verbosity);
19898 }
19899
19900 if ($stderr) {
19901 $this->lastMessageErr = $messages;
19902 } else {
19903 $this->lastMessage = $messages;
19904 }
19905 }
19906
19907
19908
19909
19910 public function ask($question, $default = null)
19911 {
19912
19913 $helper = $this->helperSet->get('question');
19914 $question = new Question($question, $default);
19915
19916 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19917 }
19918
19919
19920
19921
19922 public function askConfirmation($question, $default = true)
19923 {
19924
19925 $helper = $this->helperSet->get('question');
19926 $question = new StrictConfirmationQuestion($question, $default);
19927
19928 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19929 }
19930
19931
19932
19933
19934 public function askAndValidate($question, $validator, $attempts = null, $default = null)
19935 {
19936
19937 $helper = $this->helperSet->get('question');
19938 $question = new Question($question, $default);
19939 $question->setValidator($validator);
19940 $question->setMaxAttempts($attempts);
19941
19942 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19943 }
19944
19945
19946
19947
19948 public function askAndHideAnswer($question)
19949 {
19950
19951 $helper = $this->helperSet->get('question');
19952 $question = new Question($question);
19953 $question->setHidden(true);
19954
19955 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19956 }
19957
19958
19959
19960
19961 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
19962 {
19963
19964 $helper = $this->helperSet->get('question');
19965 $question = new ChoiceQuestion($question, $choices, $default);
19966 $question->setMaxAttempts($attempts ?: null); 
19967  $question->setErrorMessage($errorMessage);
19968 $question->setMultiselect($multiselect);
19969
19970 $result = $helper->ask($this->input, $this->getErrorOutput(), $question);
19971
19972 if (!is_array($result)) {
19973 return (string) array_search($result, $choices, true);
19974 }
19975
19976 $results = array();
19977 foreach ($choices as $index => $choice) {
19978 if (in_array($choice, $result, true)) {
19979 $results[] = (string) $index;
19980 }
19981 }
19982
19983 return $results;
19984 }
19985
19986
19987
19988
19989 private function getErrorOutput()
19990 {
19991 if ($this->output instanceof ConsoleOutputInterface) {
19992 return $this->output->getErrorOutput();
19993 }
19994
19995 return $this->output;
19996 }
19997 }
19998 <?php
19999
20000
20001
20002
20003
20004
20005
20006
20007
20008
20009
20010 namespace Composer\IO;
20011
20012 use Composer\Config;
20013
20014
20015
20016
20017
20018
20019 interface IOInterface
20020 {
20021 const QUIET = 1;
20022 const NORMAL = 2;
20023 const VERBOSE = 4;
20024 const VERY_VERBOSE = 8;
20025 const DEBUG = 16;
20026
20027
20028
20029
20030
20031
20032 public function isInteractive();
20033
20034
20035
20036
20037
20038
20039 public function isVerbose();
20040
20041
20042
20043
20044
20045
20046 public function isVeryVerbose();
20047
20048
20049
20050
20051
20052
20053 public function isDebug();
20054
20055
20056
20057
20058
20059
20060 public function isDecorated();
20061
20062
20063
20064
20065
20066
20067
20068
20069 public function write($messages, $newline = true, $verbosity = self::NORMAL);
20070
20071
20072
20073
20074
20075
20076
20077
20078 public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
20079
20080
20081
20082
20083
20084
20085
20086
20087
20088 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
20089
20090
20091
20092
20093
20094
20095
20096
20097
20098 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
20099
20100
20101
20102
20103
20104
20105
20106
20107
20108
20109 public function ask($question, $default = null);
20110
20111
20112
20113
20114
20115
20116
20117
20118
20119
20120
20121 public function askConfirmation($question, $default = true);
20122
20123
20124
20125
20126
20127
20128
20129
20130
20131
20132
20133
20134
20135
20136
20137
20138 public function askAndValidate($question, $validator, $attempts = null, $default = null);
20139
20140
20141
20142
20143
20144
20145
20146
20147 public function askAndHideAnswer($question);
20148
20149
20150
20151
20152
20153
20154
20155
20156
20157
20158
20159
20160
20161
20162 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
20163
20164
20165
20166
20167
20168
20169 public function getAuthentications();
20170
20171
20172
20173
20174
20175
20176
20177
20178 public function hasAuthentication($repositoryName);
20179
20180
20181
20182
20183
20184
20185
20186
20187 public function getAuthentication($repositoryName);
20188
20189
20190
20191
20192
20193
20194
20195
20196 public function setAuthentication($repositoryName, $username, $password = null);
20197
20198
20199
20200
20201
20202
20203 public function loadConfiguration(Config $config);
20204 }
20205 <?php
20206
20207
20208
20209
20210
20211
20212
20213
20214
20215
20216
20217 namespace Composer\IO;
20218
20219
20220
20221
20222
20223
20224 class NullIO extends BaseIO
20225 {
20226
20227
20228
20229 public function isInteractive()
20230 {
20231 return false;
20232 }
20233
20234
20235
20236
20237 public function isVerbose()
20238 {
20239 return false;
20240 }
20241
20242
20243
20244
20245 public function isVeryVerbose()
20246 {
20247 return false;
20248 }
20249
20250
20251
20252
20253 public function isDebug()
20254 {
20255 return false;
20256 }
20257
20258
20259
20260
20261 public function isDecorated()
20262 {
20263 return false;
20264 }
20265
20266
20267
20268
20269 public function write($messages, $newline = true, $verbosity = self::NORMAL)
20270 {
20271 }
20272
20273
20274
20275
20276 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
20277 {
20278 }
20279
20280
20281
20282
20283 public function overwrite($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
20284 {
20285 }
20286
20287
20288
20289
20290 public function overwriteError($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
20291 {
20292 }
20293
20294
20295
20296
20297 public function ask($question, $default = null)
20298 {
20299 return $default;
20300 }
20301
20302
20303
20304
20305 public function askConfirmation($question, $default = true)
20306 {
20307 return $default;
20308 }
20309
20310
20311
20312
20313 public function askAndValidate($question, $validator, $attempts = false, $default = null)
20314 {
20315 return $default;
20316 }
20317
20318
20319
20320
20321 public function askAndHideAnswer($question)
20322 {
20323 return null;
20324 }
20325
20326
20327
20328
20329 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
20330 {
20331 return $default;
20332 }
20333 }
20334 <?php
20335
20336
20337
20338
20339
20340
20341
20342
20343
20344
20345
20346 namespace Composer;
20347
20348 use Composer\Autoload\AutoloadGenerator;
20349 use Composer\DependencyResolver\DefaultPolicy;
20350 use Composer\DependencyResolver\Operation\UpdateOperation;
20351 use Composer\DependencyResolver\Operation\InstallOperation;
20352 use Composer\DependencyResolver\Operation\UninstallOperation;
20353 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
20354 use Composer\DependencyResolver\Operation\OperationInterface;
20355 use Composer\DependencyResolver\PolicyInterface;
20356 use Composer\DependencyResolver\Pool;
20357 use Composer\DependencyResolver\Request;
20358 use Composer\DependencyResolver\Rule;
20359 use Composer\DependencyResolver\Solver;
20360 use Composer\DependencyResolver\SolverProblemsException;
20361 use Composer\Downloader\DownloadManager;
20362 use Composer\EventDispatcher\EventDispatcher;
20363 use Composer\Installer\InstallationManager;
20364 use Composer\Installer\InstallerEvents;
20365 use Composer\Installer\NoopInstaller;
20366 use Composer\Installer\SuggestedPackagesReporter;
20367 use Composer\IO\IOInterface;
20368 use Composer\Package\AliasPackage;
20369 use Composer\Package\CompletePackage;
20370 use Composer\Package\Link;
20371 use Composer\Package\Loader\ArrayLoader;
20372 use Composer\Package\Dumper\ArrayDumper;
20373 use Composer\Semver\Constraint\Constraint;
20374 use Composer\Package\Locker;
20375 use Composer\Package\PackageInterface;
20376 use Composer\Package\RootPackageInterface;
20377 use Composer\Repository\CompositeRepository;
20378 use Composer\Repository\InstalledArrayRepository;
20379 use Composer\Repository\PlatformRepository;
20380 use Composer\Repository\RepositoryInterface;
20381 use Composer\Repository\RepositoryManager;
20382 use Composer\Repository\WritableRepositoryInterface;
20383 use Composer\Script\ScriptEvents;
20384
20385
20386
20387
20388
20389
20390
20391 class Installer
20392 {
20393
20394
20395
20396 protected $io;
20397
20398
20399
20400
20401 protected $config;
20402
20403
20404
20405
20406 protected $package;
20407
20408
20409
20410
20411 protected $downloadManager;
20412
20413
20414
20415
20416 protected $repositoryManager;
20417
20418
20419
20420
20421 protected $locker;
20422
20423
20424
20425
20426 protected $installationManager;
20427
20428
20429
20430
20431 protected $eventDispatcher;
20432
20433
20434
20435
20436 protected $autoloadGenerator;
20437
20438 protected $preferSource = false;
20439 protected $preferDist = false;
20440 protected $optimizeAutoloader = false;
20441 protected $classMapAuthoritative = false;
20442 protected $apcuAutoloader = false;
20443 protected $devMode = false;
20444 protected $dryRun = false;
20445 protected $verbose = false;
20446 protected $update = false;
20447 protected $dumpAutoloader = true;
20448 protected $runScripts = true;
20449 protected $ignorePlatformReqs = false;
20450 protected $preferStable = false;
20451 protected $preferLowest = false;
20452 protected $skipSuggest = false;
20453 protected $writeLock = true;
20454 protected $executeOperations = true;
20455
20456
20457
20458
20459
20460
20461 protected $updateWhitelist = null;
20462 protected $whitelistDependencies = false; 
20463  protected $whitelistAllDependencies = false;
20464
20465
20466
20467
20468 protected $suggestedPackagesReporter;
20469
20470
20471
20472
20473 protected $additionalInstalledRepository;
20474
20475
20476
20477
20478
20479
20480
20481
20482
20483
20484
20485
20486
20487
20488 public function __construct(IOInterface $io, Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
20489 {
20490 $this->io = $io;
20491 $this->config = $config;
20492 $this->package = $package;
20493 $this->downloadManager = $downloadManager;
20494 $this->repositoryManager = $repositoryManager;
20495 $this->locker = $locker;
20496 $this->installationManager = $installationManager;
20497 $this->eventDispatcher = $eventDispatcher;
20498 $this->autoloadGenerator = $autoloadGenerator;
20499 }
20500
20501
20502
20503
20504
20505
20506
20507 public function run()
20508 {
20509
20510  
20511  
20512  
20513  gc_collect_cycles();
20514 gc_disable();
20515
20516
20517  if (!$this->update && !$this->locker->isLocked()) {
20518 $this->update = true;
20519 }
20520
20521 if ($this->dryRun) {
20522 $this->verbose = true;
20523 $this->runScripts = false;
20524 $this->executeOperations = false;
20525 $this->writeLock = false;
20526 $this->dumpAutoloader = false;
20527 $this->installationManager->addInstaller(new NoopInstaller);
20528 $this->mockLocalRepositories($this->repositoryManager);
20529 }
20530
20531 if ($this->runScripts) {
20532 $devMode = (int) $this->devMode;
20533 putenv("COMPOSER_DEV_MODE=$devMode");
20534
20535
20536  $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
20537 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
20538 }
20539
20540 $this->downloadManager->setPreferSource($this->preferSource);
20541 $this->downloadManager->setPreferDist($this->preferDist);
20542
20543
20544  $localRepo = $this->repositoryManager->getLocalRepository();
20545 if ($this->update) {
20546 $platformOverrides = $this->config->get('platform') ?: array();
20547 } else {
20548 $platformOverrides = $this->locker->getPlatformOverrides();
20549 }
20550 $platformRepo = new PlatformRepository(array(), $platformOverrides);
20551 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
20552
20553 $aliases = $this->getRootAliases();
20554 $this->aliasPlatformPackages($platformRepo, $aliases);
20555
20556 if (!$this->suggestedPackagesReporter) {
20557 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
20558 }
20559
20560 try {
20561 list($res, $devPackages) = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases);
20562 if ($res !== 0) {
20563 return $res;
20564 }
20565 } catch (\Exception $e) {
20566 if ($this->executeOperations) {
20567 $this->installationManager->notifyInstalls($this->io);
20568 }
20569
20570 throw $e;
20571 }
20572 if ($this->executeOperations) {
20573 $this->installationManager->notifyInstalls($this->io);
20574 }
20575
20576
20577  if ($this->devMode && !$this->skipSuggest) {
20578 $this->suggestedPackagesReporter->output($installedRepo);
20579 }
20580
20581
20582  foreach ($localRepo->getPackages() as $package) {
20583 if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
20584 continue;
20585 }
20586
20587 $replacement = is_string($package->getReplacementPackage())
20588 ? 'Use ' . $package->getReplacementPackage() . ' instead'
20589 : 'No replacement was suggested';
20590
20591 $this->io->writeError(
20592 sprintf(
20593 "<warning>Package %s is abandoned, you should avoid using it. %s.</warning>",
20594 $package->getPrettyName(),
20595 $replacement
20596 )
20597 );
20598 }
20599
20600
20601  if ($this->update && $this->writeLock) {
20602 $localRepo->reload();
20603
20604 $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
20605 $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires());
20606
20607 $updatedLock = $this->locker->setLockData(
20608 array_diff($localRepo->getCanonicalPackages(), $devPackages),
20609 $devPackages,
20610 $platformReqs,
20611 $platformDevReqs,
20612 $aliases,
20613 $this->package->getMinimumStability(),
20614 $this->package->getStabilityFlags(),
20615 $this->preferStable || $this->package->getPreferStable(),
20616 $this->preferLowest,
20617 $this->config->get('platform') ?: array()
20618 );
20619 if ($updatedLock) {
20620 $this->io->writeError('<info>Writing lock file</info>');
20621 }
20622 }
20623
20624 if ($this->dumpAutoloader) {
20625
20626  if ($this->optimizeAutoloader) {
20627 $this->io->writeError('<info>Generating optimized autoload files</info>');
20628 } else {
20629 $this->io->writeError('<info>Generating autoload files</info>');
20630 }
20631
20632 $this->autoloadGenerator->setDevMode($this->devMode);
20633 $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
20634 $this->autoloadGenerator->setApcu($this->apcuAutoloader);
20635 $this->autoloadGenerator->setRunScripts($this->runScripts);
20636 $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
20637 }
20638
20639 if ($this->executeOperations) {
20640
20641  foreach ($localRepo->getPackages() as $package) {
20642 $this->installationManager->ensureBinariesPresence($package);
20643 }
20644
20645 $vendorDir = $this->config->get('vendor-dir');
20646 if (is_dir($vendorDir)) {
20647
20648  
20649  @touch($vendorDir);
20650 }
20651 }
20652
20653 if ($this->runScripts) {
20654
20655  $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
20656 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
20657 }
20658
20659
20660  if (!defined('HHVM_VERSION')) {
20661 gc_enable();
20662 }
20663
20664 return 0;
20665 }
20666
20667
20668
20669
20670
20671
20672
20673
20674 protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases)
20675 {
20676
20677  $lockedRepository = null;
20678 $repositories = null;
20679
20680
20681  
20682  
20683  if (!$this->update || (!empty($this->updateWhitelist) && $this->locker->isLocked())) {
20684 try {
20685 $lockedRepository = $this->locker->getLockedRepository($this->devMode);
20686 } catch (\RuntimeException $e) {
20687
20688  if ($this->package->getDevRequires()) {
20689 throw $e;
20690 }
20691
20692  $lockedRepository = $this->locker->getLockedRepository();
20693 }
20694 }
20695
20696 $this->whitelistUpdateDependencies(
20697 $lockedRepository ?: $localRepo,
20698 $this->package->getRequires(),
20699 $this->package->getDevRequires()
20700 );
20701
20702 $this->io->writeError('<info>Loading composer repositories with package information</info>');
20703
20704
20705  $policy = $this->createPolicy();
20706 $pool = $this->createPool($this->update ? null : $lockedRepository);
20707 $pool->addRepository($installedRepo, $aliases);
20708 if ($this->update) {
20709 $repositories = $this->repositoryManager->getRepositories();
20710 foreach ($repositories as $repository) {
20711 $pool->addRepository($repository, $aliases);
20712 }
20713 }
20714
20715  
20716  
20717  if ($lockedRepository) {
20718 $pool->addRepository($lockedRepository, $aliases);
20719 }
20720
20721
20722  $request = $this->createRequest($this->package, $platformRepo);
20723
20724 if ($this->update) {
20725
20726  $removedUnstablePackages = array();
20727 foreach ($localRepo->getPackages() as $package) {
20728 if (
20729 !$pool->isPackageAcceptable($package->getNames(), $package->getStability())
20730 && $this->installationManager->isPackageInstalled($localRepo, $package)
20731 ) {
20732 $removedUnstablePackages[$package->getName()] = true;
20733 $request->remove($package->getName(), new Constraint('=', $package->getVersion()));
20734 }
20735 }
20736
20737 $this->io->writeError('<info>Updating dependencies'.($this->devMode ? ' (including require-dev)' : '').'</info>');
20738
20739 $request->updateAll();
20740
20741 $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
20742
20743 foreach ($links as $link) {
20744 $request->install($link->getTarget(), $link->getConstraint());
20745 }
20746
20747
20748  
20749  if ($this->updateWhitelist) {
20750 $currentPackages = $this->getCurrentPackages($installedRepo);
20751
20752
20753  $candidates = array();
20754 foreach ($links as $link) {
20755 $candidates[$link->getTarget()] = true;
20756 $rootRequires[$link->getTarget()] = $link;
20757 }
20758 foreach ($currentPackages as $package) {
20759 $candidates[$package->getName()] = true;
20760 }
20761
20762
20763  foreach ($candidates as $candidate => $dummy) {
20764 foreach ($currentPackages as $curPackage) {
20765 if ($curPackage->getName() === $candidate) {
20766 if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
20767 $constraint = new Constraint('=', $curPackage->getVersion());
20768 $description = $this->locker->isLocked() ? '(locked at' : '(installed at';
20769 $requiredAt = isset($rootRequires[$candidate]) ? ', required as ' . $rootRequires[$candidate]->getPrettyConstraint() : '';
20770 $constraint->setPrettyString($description . ' ' . $curPackage->getPrettyVersion() . $requiredAt . ')');
20771 $request->install($curPackage->getName(), $constraint);
20772 }
20773 break;
20774 }
20775 }
20776 }
20777 }
20778 } else {
20779 $this->io->writeError('<info>Installing dependencies'.($this->devMode ? ' (including require-dev)' : '').' from lock file</info>');
20780
20781 if (!$this->locker->isFresh()) {
20782 $this->io->writeError('<warning>Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.</warning>', true, IOInterface::QUIET);
20783 }
20784
20785 foreach ($lockedRepository->getPackages() as $package) {
20786 $version = $package->getVersion();
20787 if (isset($aliases[$package->getName()][$version])) {
20788 $version = $aliases[$package->getName()][$version]['alias_normalized'];
20789 }
20790 $constraint = new Constraint('=', $version);
20791 $constraint->setPrettyString($package->getPrettyVersion());
20792 $request->install($package->getName(), $constraint);
20793 }
20794
20795 foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
20796 $request->install($link->getTarget(), $link->getConstraint());
20797 }
20798 }
20799
20800
20801  $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-links');
20802
20803
20804  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
20805 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
20806 try {
20807 $operations = $solver->solve($request, $this->ignorePlatformReqs);
20808 } catch (SolverProblemsException $e) {
20809 $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
20810 $this->io->writeError($e->getMessage());
20811 if ($this->update && !$this->devMode) {
20812 $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);
20813 }
20814
20815 return array(max(1, $e->getCode()), array());
20816 }
20817
20818
20819  $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-updates', $operations);
20820
20821 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
20822
20823 $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
20824 $this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies", true, IOInterface::VERBOSE);
20825
20826
20827  if (!$operations) {
20828 $this->io->writeError('Nothing to install or update');
20829 }
20830
20831 $operations = $this->movePluginsToFront($operations);
20832 $operations = $this->moveUninstallsToFront($operations);
20833
20834
20835  
20836  if ($this->update) {
20837 $devPackages = $this->extractDevPackages($operations, $localRepo, $platformRepo, $aliases);
20838 if (!$this->devMode) {
20839 $operations = $this->filterDevPackageOperations($devPackages, $operations, $localRepo);
20840 }
20841 } else {
20842 $devPackages = null;
20843 }
20844
20845 if ($operations) {
20846 $installs = $updates = $uninstalls = array();
20847 foreach ($operations as $operation) {
20848 if ($operation instanceof InstallOperation) {
20849 $installs[] = $operation->getPackage()->getPrettyName().':'.$operation->getPackage()->getFullPrettyVersion();
20850 } elseif ($operation instanceof UpdateOperation) {
20851 $updates[] = $operation->getTargetPackage()->getPrettyName().':'.$operation->getTargetPackage()->getFullPrettyVersion();
20852 } elseif ($operation instanceof UninstallOperation) {
20853 $uninstalls[] = $operation->getPackage()->getPrettyName();
20854 }
20855 }
20856
20857 $this->io->writeError(sprintf(
20858 "<info>Package operations: %d install%s, %d update%s, %d removal%s</info>",
20859 count($installs),
20860 1 === count($installs) ? '' : 's',
20861 count($updates),
20862 1 === count($updates) ? '' : 's',
20863 count($uninstalls),
20864 1 === count($uninstalls) ? '' : 's'
20865 ));
20866 if ($installs) {
20867 $this->io->writeError("Installs: ".implode(', ', $installs), true, IOInterface::VERBOSE);
20868 }
20869 if ($updates) {
20870 $this->io->writeError("Updates: ".implode(', ', $updates), true, IOInterface::VERBOSE);
20871 }
20872 if ($uninstalls) {
20873 $this->io->writeError("Removals: ".implode(', ', $uninstalls), true, IOInterface::VERBOSE);
20874 }
20875 }
20876
20877 foreach ($operations as $operation) {
20878
20879  $jobType = $operation->getJobType();
20880 if ('install' === $jobType) {
20881 $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
20882 }
20883
20884
20885  if ($this->update) {
20886 $package = null;
20887 if ('update' === $jobType) {
20888 $package = $operation->getTargetPackage();
20889 } elseif ('install' === $jobType) {
20890 $package = $operation->getPackage();
20891 }
20892 if ($package && $package->isDev()) {
20893 $references = $this->package->getReferences();
20894 if (isset($references[$package->getName()])) {
20895 $this->updateInstallReferences($package, $references[$package->getName()]);
20896 }
20897 }
20898 if ('update' === $jobType) {
20899 $targetPackage = $operation->getTargetPackage();
20900 if ($targetPackage->isDev()) {
20901 $initialPackage = $operation->getInitialPackage();
20902 if ($targetPackage->getVersion() === $initialPackage->getVersion()
20903 && (!$targetPackage->getSourceReference() || $targetPackage->getSourceReference() === $initialPackage->getSourceReference())
20904 && (!$targetPackage->getDistReference() || $targetPackage->getDistReference() === $initialPackage->getDistReference())
20905 ) {
20906 $this->io->writeError('  - Skipping update of ' . $targetPackage->getPrettyName() . ' to the same reference-locked version', true, IOInterface::DEBUG);
20907 $this->io->writeError('', true, IOInterface::DEBUG);
20908
20909 continue;
20910 }
20911 }
20912 }
20913 }
20914
20915 $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($jobType);
20916 if (defined($event) && $this->runScripts) {
20917 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20918 }
20919
20920
20921  if (!$this->executeOperations && false === strpos($operation->getJobType(), 'Alias')) {
20922 $this->io->writeError('  - ' . $operation);
20923 } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
20924 $this->io->writeError('  - ' . $operation);
20925 }
20926
20927 $this->installationManager->execute($localRepo, $operation);
20928
20929
20930  if ($this->verbose && $this->io->isVeryVerbose() && in_array($jobType, array('install', 'update'))) {
20931 $reason = $operation->getReason();
20932 if ($reason instanceof Rule) {
20933 switch ($reason->getReason()) {
20934 case Rule::RULE_JOB_INSTALL:
20935 $this->io->writeError('    REASON: Required by the root package: '.$reason->getPrettyString($pool));
20936 $this->io->writeError('');
20937 break;
20938 case Rule::RULE_PACKAGE_REQUIRES:
20939 $this->io->writeError('    REASON: '.$reason->getPrettyString($pool));
20940 $this->io->writeError('');
20941 break;
20942 }
20943 }
20944 }
20945
20946 $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($jobType);
20947 if (defined($event) && $this->runScripts) {
20948 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20949 }
20950
20951 if ($this->executeOperations || $this->writeLock) {
20952 $localRepo->write();
20953 }
20954 }
20955
20956 if ($this->executeOperations) {
20957
20958  $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
20959 $localRepo->write();
20960 }
20961
20962 return array(0, $devPackages);
20963 }
20964
20965
20966
20967
20968
20969
20970
20971
20972
20973
20974
20975 private function extractDevPackages(array $operations, RepositoryInterface $localRepo, PlatformRepository $platformRepo, array $aliases)
20976 {
20977 if (!$this->package->getDevRequires()) {
20978 return array();
20979 }
20980
20981
20982  $tempLocalRepo = clone $localRepo;
20983 foreach ($operations as $operation) {
20984 switch ($operation->getJobType()) {
20985 case 'install':
20986 case 'markAliasInstalled':
20987 if (!$tempLocalRepo->hasPackage($operation->getPackage())) {
20988 $tempLocalRepo->addPackage(clone $operation->getPackage());
20989 }
20990 break;
20991
20992 case 'uninstall':
20993 case 'markAliasUninstalled':
20994 $tempLocalRepo->removePackage($operation->getPackage());
20995 break;
20996
20997 case 'update':
20998 $tempLocalRepo->removePackage($operation->getInitialPackage());
20999 if (!$tempLocalRepo->hasPackage($operation->getTargetPackage())) {
21000 $tempLocalRepo->addPackage(clone $operation->getTargetPackage());
21001 }
21002 break;
21003
21004 default:
21005 throw new \LogicException('Unknown type: '.$operation->getJobType());
21006 }
21007 }
21008
21009
21010  
21011  
21012  $localRepo = new InstalledArrayRepository(array());
21013 $loader = new ArrayLoader(null, true);
21014 $dumper = new ArrayDumper();
21015 foreach ($tempLocalRepo->getCanonicalPackages() as $pkg) {
21016 $localRepo->addPackage($loader->load($dumper->dump($pkg)));
21017 }
21018 unset($tempLocalRepo, $loader, $dumper);
21019
21020 $policy = $this->createPolicy();
21021 $pool = $this->createPool();
21022 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
21023 $pool->addRepository($installedRepo, $aliases);
21024
21025
21026  $request = $this->createRequest($this->package, $platformRepo);
21027 $request->updateAll();
21028 foreach ($this->package->getRequires() as $link) {
21029 $request->install($link->getTarget(), $link->getConstraint());
21030 }
21031
21032
21033  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
21034 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
21035 $ops = $solver->solve($request, $this->ignorePlatformReqs);
21036 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
21037
21038 $devPackages = array();
21039 foreach ($ops as $op) {
21040 if ($op->getJobType() === 'uninstall') {
21041 $devPackages[] = $op->getPackage();
21042 }
21043 }
21044
21045 return $devPackages;
21046 }
21047
21048
21049
21050
21051 private function filterDevPackageOperations(array $devPackages, array $operations, RepositoryInterface $localRepo)
21052 {
21053 $finalOps = array();
21054 $packagesToSkip = array();
21055 foreach ($devPackages as $pkg) {
21056 $packagesToSkip[$pkg->getName()] = true;
21057 if ($installedDevPkg = $localRepo->findPackage($pkg->getName(), '*')) {
21058 if ($installedDevPkg instanceof AliasPackage) {
21059 $finalOps[] = new MarkAliasUninstalledOperation($installedDevPkg, 'non-dev install removing it');
21060 $installedDevPkg = $installedDevPkg->getAliasOf();
21061 }
21062 $finalOps[] = new UninstallOperation($installedDevPkg, 'non-dev install removing it');
21063 }
21064 }
21065
21066
21067  foreach ($operations as $op) {
21068 $package = $op->getJobType() === 'update' ? $op->getTargetPackage() : $op->getPackage();
21069 if (isset($packagesToSkip[$package->getName()])) {
21070 continue;
21071 }
21072
21073 $finalOps[] = $op;
21074 }
21075
21076 return $finalOps;
21077 }
21078
21079
21080
21081
21082
21083
21084
21085
21086
21087
21088
21089
21090
21091
21092 private function movePluginsToFront(array $operations)
21093 {
21094 $pluginsNoDeps = array();
21095 $pluginsWithDeps = array();
21096 $pluginRequires = array();
21097
21098 foreach (array_reverse($operations, true) as $idx => $op) {
21099 if ($op instanceof InstallOperation) {
21100 $package = $op->getPackage();
21101 } elseif ($op instanceof UpdateOperation) {
21102 $package = $op->getTargetPackage();
21103 } else {
21104 continue;
21105 }
21106
21107
21108  $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
21109
21110
21111  if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
21112
21113  $requires = array_filter(array_keys($package->getRequires()), function ($req) {
21114 return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
21115 });
21116
21117
21118  if ($isPlugin && !count($requires)) {
21119
21120  array_unshift($pluginsNoDeps, $op);
21121 } else {
21122
21123  $pluginRequires = array_merge($pluginRequires, $requires);
21124
21125  array_unshift($pluginsWithDeps, $op);
21126 }
21127
21128 unset($operations[$idx]);
21129 }
21130 }
21131
21132 return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
21133 }
21134
21135
21136
21137
21138
21139
21140
21141
21142 private function moveUninstallsToFront(array $operations)
21143 {
21144 $uninstOps = array();
21145 foreach ($operations as $idx => $op) {
21146 if ($op instanceof UninstallOperation) {
21147 $uninstOps[] = $op;
21148 unset($operations[$idx]);
21149 }
21150 }
21151
21152 return array_merge($uninstOps, $operations);
21153 }
21154
21155
21156
21157
21158 private function createInstalledRepo(RepositoryInterface $localRepo, PlatformRepository $platformRepo)
21159 {
21160
21161  
21162  
21163  $installedRootPackage = clone $this->package;
21164 $installedRootPackage->setRequires(array());
21165 $installedRootPackage->setDevRequires(array());
21166
21167 $repos = array(
21168 $localRepo,
21169 new InstalledArrayRepository(array($installedRootPackage)),
21170 $platformRepo,
21171 );
21172 $installedRepo = new CompositeRepository($repos);
21173 if ($this->additionalInstalledRepository) {
21174 $installedRepo->addRepository($this->additionalInstalledRepository);
21175 }
21176
21177 return $installedRepo;
21178 }
21179
21180
21181
21182
21183
21184 private function createPool(RepositoryInterface $lockedRepository = null)
21185 {
21186 if ($this->update) {
21187 $minimumStability = $this->package->getMinimumStability();
21188 $stabilityFlags = $this->package->getStabilityFlags();
21189
21190 $requires = array_merge($this->package->getRequires(), $this->package->getDevRequires());
21191 } else {
21192 $minimumStability = $this->locker->getMinimumStability();
21193 $stabilityFlags = $this->locker->getStabilityFlags();
21194
21195 $requires = array();
21196 foreach ($lockedRepository->getPackages() as $package) {
21197 $constraint = new Constraint('=', $package->getVersion());
21198 $constraint->setPrettyString($package->getPrettyVersion());
21199 $requires[$package->getName()] = $constraint;
21200 }
21201 }
21202
21203 $rootConstraints = array();
21204 foreach ($requires as $req => $constraint) {
21205
21206  if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
21207 continue;
21208 }
21209 if ($constraint instanceof Link) {
21210 $rootConstraints[$req] = $constraint->getConstraint();
21211 } else {
21212 $rootConstraints[$req] = $constraint;
21213 }
21214 }
21215
21216 return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
21217 }
21218
21219
21220
21221
21222 private function createPolicy()
21223 {
21224 $preferStable = null;
21225 $preferLowest = null;
21226 if (!$this->update) {
21227 $preferStable = $this->locker->getPreferStable();
21228 $preferLowest = $this->locker->getPreferLowest();
21229 }
21230
21231  
21232  if (null === $preferStable) {
21233 $preferStable = $this->preferStable || $this->package->getPreferStable();
21234 }
21235 if (null === $preferLowest) {
21236 $preferLowest = $this->preferLowest;
21237 }
21238
21239 return new DefaultPolicy($preferStable, $preferLowest);
21240 }
21241
21242
21243
21244
21245
21246
21247 private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
21248 {
21249 $request = new Request();
21250
21251 $constraint = new Constraint('=', $rootPackage->getVersion());
21252 $constraint->setPrettyString($rootPackage->getPrettyVersion());
21253 $request->install($rootPackage->getName(), $constraint);
21254
21255 $fixedPackages = $platformRepo->getPackages();
21256 if ($this->additionalInstalledRepository) {
21257 $additionalFixedPackages = $this->additionalInstalledRepository->getPackages();
21258 $fixedPackages = array_merge($fixedPackages, $additionalFixedPackages);
21259 }
21260
21261
21262  
21263  $provided = $rootPackage->getProvides();
21264 foreach ($fixedPackages as $package) {
21265 $constraint = new Constraint('=', $package->getVersion());
21266 $constraint->setPrettyString($package->getPrettyVersion());
21267
21268
21269  if ($package->getRepository() !== $platformRepo
21270 || !isset($provided[$package->getName()])
21271 || !$provided[$package->getName()]->getConstraint()->matches($constraint)
21272 ) {
21273 $request->fix($package->getName(), $constraint);
21274 }
21275 }
21276
21277 return $request;
21278 }
21279
21280
21281
21282
21283
21284
21285
21286
21287
21288
21289
21290
21291 private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $task, array $operations = null)
21292 {
21293 if ($task === 'force-updates' && null === $operations) {
21294 throw new \InvalidArgumentException('Missing operations argument');
21295 }
21296 if ($task === 'force-links') {
21297 $operations = array();
21298 }
21299
21300 if ($this->update && $this->updateWhitelist) {
21301 $currentPackages = $this->getCurrentPackages($installedRepo);
21302 }
21303
21304 foreach ($localRepo->getCanonicalPackages() as $package) {
21305
21306  if (!$package->isDev()) {
21307 continue;
21308 }
21309
21310
21311  foreach ($operations as $operation) {
21312 if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
21313 || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
21314 ) {
21315 continue 2;
21316 }
21317 }
21318
21319 if ($this->update) {
21320
21321  if ($this->updateWhitelist && !$this->isUpdateable($package)) {
21322
21323  foreach ($currentPackages as $curPackage) {
21324 if ($curPackage->isDev() && $curPackage->getName() === $package->getName() && $curPackage->getVersion() === $package->getVersion()) {
21325 if ($task === 'force-links') {
21326 $package->setRequires($curPackage->getRequires());
21327 $package->setConflicts($curPackage->getConflicts());
21328 $package->setProvides($curPackage->getProvides());
21329 $package->setReplaces($curPackage->getReplaces());
21330 } elseif ($task === 'force-updates') {
21331 if (($curPackage->getSourceReference() && $curPackage->getSourceReference() !== $package->getSourceReference())
21332 || ($curPackage->getDistReference() && $curPackage->getDistReference() !== $package->getDistReference())
21333 ) {
21334 $operations[] = new UpdateOperation($package, $curPackage);
21335 }
21336 }
21337
21338 break;
21339 }
21340 }
21341
21342 continue;
21343 }
21344
21345
21346  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
21347 foreach ($matches as $index => $match) {
21348
21349  if (!in_array($match->getRepository(), $repositories, true)) {
21350 unset($matches[$index]);
21351 continue;
21352 }
21353
21354
21355  if ($match->getName() !== $package->getName()) {
21356 unset($matches[$index]);
21357 continue;
21358 }
21359
21360 $matches[$index] = $match->getId();
21361 }
21362
21363
21364  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
21365 $newPackage = $pool->literalToPackage($matches[0]);
21366
21367 if ($task === 'force-links' && $newPackage) {
21368 $package->setRequires($newPackage->getRequires());
21369 $package->setConflicts($newPackage->getConflicts());
21370 $package->setProvides($newPackage->getProvides());
21371 $package->setReplaces($newPackage->getReplaces());
21372 }
21373
21374 if (
21375 $task === 'force-updates'
21376 && $newPackage
21377 && (
21378 ($newPackage->getSourceReference() && $newPackage->getSourceReference() !== $package->getSourceReference())
21379 || ($newPackage->getDistReference() && $newPackage->getDistReference() !== $package->getDistReference())
21380 )
21381 ) {
21382 $operations[] = new UpdateOperation($package, $newPackage);
21383
21384 continue;
21385 }
21386 }
21387
21388 if ($task === 'force-updates') {
21389
21390  $references = $this->package->getReferences();
21391
21392 if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
21393
21394  $operations[] = new UpdateOperation($package, clone $package);
21395 }
21396 }
21397 } else {
21398
21399  foreach ($lockedRepository->findPackages($package->getName()) as $lockedPackage) {
21400 if ($lockedPackage->isDev() && $lockedPackage->getVersion() === $package->getVersion()) {
21401 if ($task === 'force-links') {
21402 $package->setRequires($lockedPackage->getRequires());
21403 $package->setConflicts($lockedPackage->getConflicts());
21404 $package->setProvides($lockedPackage->getProvides());
21405 $package->setReplaces($lockedPackage->getReplaces());
21406 } elseif ($task === 'force-updates') {
21407 if (($lockedPackage->getSourceReference() && $lockedPackage->getSourceReference() !== $package->getSourceReference())
21408 || ($lockedPackage->getDistReference() && $lockedPackage->getDistReference() !== $package->getDistReference())
21409 ) {
21410 $operations[] = new UpdateOperation($package, $lockedPackage);
21411 }
21412 }
21413
21414 break;
21415 }
21416 }
21417 }
21418 }
21419
21420 return $operations;
21421 }
21422
21423
21424
21425
21426
21427
21428 private function getCurrentPackages($installedRepo)
21429 {
21430 if ($this->locker->isLocked()) {
21431 try {
21432 return $this->locker->getLockedRepository(true)->getPackages();
21433 } catch (\RuntimeException $e) {
21434
21435  return $this->locker->getLockedRepository()->getPackages();
21436 }
21437 }
21438
21439 return $installedRepo->getPackages();
21440 }
21441
21442
21443
21444
21445 private function getRootAliases()
21446 {
21447 if ($this->update) {
21448 $aliases = $this->package->getAliases();
21449 } else {
21450 $aliases = $this->locker->getAliases();
21451 }
21452
21453 $normalizedAliases = array();
21454
21455 foreach ($aliases as $alias) {
21456 $normalizedAliases[$alias['package']][$alias['version']] = array(
21457 'alias' => $alias['alias'],
21458 'alias_normalized' => $alias['alias_normalized'],
21459 );
21460 }
21461
21462 return $normalizedAliases;
21463 }
21464
21465
21466
21467
21468
21469
21470
21471 private function processPackageUrls($pool, $policy, $localRepo, $repositories)
21472 {
21473 if (!$this->update) {
21474 return;
21475 }
21476
21477 $rootRefs = $this->package->getReferences();
21478
21479 foreach ($localRepo->getCanonicalPackages() as $package) {
21480
21481  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
21482 foreach ($matches as $index => $match) {
21483
21484  if (!in_array($match->getRepository(), $repositories, true)) {
21485 unset($matches[$index]);
21486 continue;
21487 }
21488
21489
21490  if ($match->getName() !== $package->getName()) {
21491 unset($matches[$index]);
21492 continue;
21493 }
21494
21495 $matches[$index] = $match->getId();
21496 }
21497
21498
21499  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
21500 $newPackage = $pool->literalToPackage($matches[0]);
21501
21502
21503  $sourceUrl = $package->getSourceUrl();
21504 $newSourceUrl = $newPackage->getSourceUrl();
21505 $newReference = $newPackage->getSourceReference();
21506
21507 if ($package->isDev() && isset($rootRefs[$package->getName()]) && $package->getSourceReference() === $rootRefs[$package->getName()]) {
21508 $newReference = $rootRefs[$package->getName()];
21509 }
21510
21511 $this->updatePackageUrl($package, $newSourceUrl, $newPackage->getSourceType(), $newReference, $newPackage->getDistUrl());
21512
21513 if ($package instanceof CompletePackage && $newPackage instanceof CompletePackage) {
21514 $package->setAbandoned($newPackage->getReplacementPackage() ?: $newPackage->isAbandoned());
21515 }
21516
21517 $package->setDistMirrors($newPackage->getDistMirrors());
21518 $package->setSourceMirrors($newPackage->getSourceMirrors());
21519 }
21520 }
21521 }
21522
21523 private function updatePackageUrl(PackageInterface $package, $sourceUrl, $sourceType, $sourceReference, $distUrl)
21524 {
21525 $oldSourceRef = $package->getSourceReference();
21526
21527 if ($package->getSourceUrl() !== $sourceUrl) {
21528 $package->setSourceType($sourceType);
21529 $package->setSourceUrl($sourceUrl);
21530 $package->setSourceReference($sourceReference);
21531 }
21532
21533
21534  
21535  if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $distUrl)) {
21536 $package->setDistUrl($distUrl);
21537 $this->updateInstallReferences($package, $sourceReference);
21538 }
21539
21540 if ($this->updateWhitelist && !$this->isUpdateable($package)) {
21541 $this->updateInstallReferences($package, $oldSourceRef);
21542 }
21543 }
21544
21545 private function updateInstallReferences(PackageInterface $package, $reference)
21546 {
21547 if (!$reference) {
21548 return;
21549 }
21550
21551 $package->setSourceReference($reference);
21552
21553 if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $package->getDistUrl())) {
21554 $package->setDistReference($reference);
21555 $package->setDistUrl(preg_replace('{(?<=/|sha=)[a-f0-9]{40}(?=/|$)}i', $reference, $package->getDistUrl()));
21556 } elseif ($package->getDistReference()) { 
21557  $package->setDistReference($reference);
21558 }
21559 }
21560
21561
21562
21563
21564
21565 private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
21566 {
21567 foreach ($aliases as $package => $versions) {
21568 foreach ($versions as $version => $alias) {
21569 $packages = $platformRepo->findPackages($package, $version);
21570 foreach ($packages as $package) {
21571 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
21572 $aliasPackage->setRootPackageAlias(true);
21573 $platformRepo->addPackage($aliasPackage);
21574 }
21575 }
21576 }
21577 }
21578
21579
21580
21581
21582
21583 private function isUpdateable(PackageInterface $package)
21584 {
21585 if (!$this->updateWhitelist) {
21586 throw new \LogicException('isUpdateable should only be called when a whitelist is present');
21587 }
21588
21589 foreach ($this->updateWhitelist as $whiteListedPattern => $void) {
21590 $patternRegexp = $this->packageNameToRegexp($whiteListedPattern);
21591 if (preg_match($patternRegexp, $package->getName())) {
21592 return true;
21593 }
21594 }
21595
21596 return false;
21597 }
21598
21599
21600
21601
21602
21603
21604
21605 private function packageNameToRegexp($whiteListedPattern)
21606 {
21607 $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern));
21608
21609 return "{^" . $cleanedWhiteListedPattern . "$}i";
21610 }
21611
21612
21613
21614
21615
21616 private function extractPlatformRequirements($links)
21617 {
21618 $platformReqs = array();
21619 foreach ($links as $link) {
21620 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
21621 $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
21622 }
21623 }
21624
21625 return $platformReqs;
21626 }
21627
21628
21629
21630
21631
21632
21633
21634
21635
21636
21637
21638
21639
21640
21641 private function whitelistUpdateDependencies($localOrLockRepo, array $rootRequires, array $rootDevRequires)
21642 {
21643 if (!$this->updateWhitelist) {
21644 return;
21645 }
21646
21647 $rootRequires = array_merge($rootRequires, $rootDevRequires);
21648
21649 $requiredPackageNames = array();
21650 foreach ($rootRequires as $require) {
21651 $requiredPackageNames[] = $require->getTarget();
21652 }
21653
21654 $skipPackages = array();
21655 if (!$this->whitelistAllDependencies) {
21656 foreach ($rootRequires as $require) {
21657 $skipPackages[$require->getTarget()] = true;
21658 }
21659 }
21660
21661 $pool = new Pool('dev');
21662 $pool->addRepository($localOrLockRepo);
21663
21664 $seen = array();
21665
21666 $rootRequiredPackageNames = array_keys($rootRequires);
21667
21668 foreach ($this->updateWhitelist as $packageName => $void) {
21669 $packageQueue = new \SplQueue;
21670
21671 $depPackages = $pool->whatProvides($packageName);
21672
21673 $nameMatchesRequiredPackage = in_array($packageName, $requiredPackageNames, true);
21674
21675
21676  if (!$nameMatchesRequiredPackage) {
21677 $whitelistPatternRegexp = $this->packageNameToRegexp($packageName);
21678 foreach ($rootRequiredPackageNames as $rootRequiredPackageName) {
21679 if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) {
21680 $nameMatchesRequiredPackage = true;
21681 break;
21682 }
21683 }
21684 }
21685
21686 if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) {
21687 $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
21688 }
21689
21690 foreach ($depPackages as $depPackage) {
21691 $packageQueue->enqueue($depPackage);
21692 }
21693
21694 while (!$packageQueue->isEmpty()) {
21695 $package = $packageQueue->dequeue();
21696 if (isset($seen[$package->getId()])) {
21697 continue;
21698 }
21699
21700 $seen[$package->getId()] = true;
21701 $this->updateWhitelist[$package->getName()] = true;
21702
21703 if (!$this->whitelistDependencies && !$this->whitelistAllDependencies) {
21704 continue;
21705 }
21706
21707 $requires = $package->getRequires();
21708
21709 foreach ($requires as $require) {
21710 $requirePackages = $pool->whatProvides($require->getTarget());
21711
21712 foreach ($requirePackages as $requirePackage) {
21713 if (isset($this->updateWhitelist[$requirePackage->getName()])) {
21714 continue;
21715 }
21716
21717 if (isset($skipPackages[$requirePackage->getName()])) {
21718 $this->io->writeError('<warning>Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.</warning>');
21719 continue;
21720 }
21721
21722 $packageQueue->enqueue($requirePackage);
21723 }
21724 }
21725 }
21726 }
21727 }
21728
21729
21730
21731
21732
21733
21734
21735
21736 private function mockLocalRepositories(RepositoryManager $rm)
21737 {
21738 $packages = array();
21739 foreach ($rm->getLocalRepository()->getPackages() as $package) {
21740 $packages[(string) $package] = clone $package;
21741 }
21742 foreach ($packages as $key => $package) {
21743 if ($package instanceof AliasPackage) {
21744 $alias = (string) $package->getAliasOf();
21745 $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
21746 }
21747 }
21748 $rm->setLocalRepository(
21749 new InstalledArrayRepository($packages)
21750 );
21751 }
21752
21753
21754
21755
21756
21757
21758
21759
21760 public static function create(IOInterface $io, Composer $composer)
21761 {
21762 return new static(
21763 $io,
21764 $composer->getConfig(),
21765 $composer->getPackage(),
21766 $composer->getDownloadManager(),
21767 $composer->getRepositoryManager(),
21768 $composer->getLocker(),
21769 $composer->getInstallationManager(),
21770 $composer->getEventDispatcher(),
21771 $composer->getAutoloadGenerator()
21772 );
21773 }
21774
21775
21776
21777
21778
21779 public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
21780 {
21781 $this->additionalInstalledRepository = $additionalInstalledRepository;
21782
21783 return $this;
21784 }
21785
21786
21787
21788
21789
21790
21791
21792 public function setDryRun($dryRun = true)
21793 {
21794 $this->dryRun = (bool) $dryRun;
21795
21796 return $this;
21797 }
21798
21799
21800
21801
21802
21803
21804 public function isDryRun()
21805 {
21806 return $this->dryRun;
21807 }
21808
21809
21810
21811
21812
21813
21814
21815 public function setPreferSource($preferSource = true)
21816 {
21817 $this->preferSource = (bool) $preferSource;
21818
21819 return $this;
21820 }
21821
21822
21823
21824
21825
21826
21827
21828 public function setPreferDist($preferDist = true)
21829 {
21830 $this->preferDist = (bool) $preferDist;
21831
21832 return $this;
21833 }
21834
21835
21836
21837
21838
21839
21840
21841 public function setOptimizeAutoloader($optimizeAutoloader = false)
21842 {
21843 $this->optimizeAutoloader = (bool) $optimizeAutoloader;
21844 if (!$this->optimizeAutoloader) {
21845
21846  
21847  $this->setClassMapAuthoritative(false);
21848 }
21849
21850 return $this;
21851 }
21852
21853
21854
21855
21856
21857
21858
21859
21860 public function setClassMapAuthoritative($classMapAuthoritative = false)
21861 {
21862 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
21863 if ($this->classMapAuthoritative) {
21864
21865  $this->setOptimizeAutoloader(true);
21866 }
21867
21868 return $this;
21869 }
21870
21871
21872
21873
21874
21875
21876
21877 public function setApcuAutoloader($apcuAutoloader = false)
21878 {
21879 $this->apcuAutoloader = (bool) $apcuAutoloader;
21880
21881 return $this;
21882 }
21883
21884
21885
21886
21887
21888
21889
21890 public function setUpdate($update = true)
21891 {
21892 $this->update = (bool) $update;
21893
21894 return $this;
21895 }
21896
21897
21898
21899
21900
21901
21902
21903 public function setDevMode($devMode = true)
21904 {
21905 $this->devMode = (bool) $devMode;
21906
21907 return $this;
21908 }
21909
21910
21911
21912
21913
21914
21915
21916
21917
21918 public function setDumpAutoloader($dumpAutoloader = true)
21919 {
21920 $this->dumpAutoloader = (bool) $dumpAutoloader;
21921
21922 return $this;
21923 }
21924
21925
21926
21927
21928
21929
21930
21931
21932
21933 public function setRunScripts($runScripts = true)
21934 {
21935 $this->runScripts = (bool) $runScripts;
21936
21937 return $this;
21938 }
21939
21940
21941
21942
21943
21944
21945
21946 public function setConfig(Config $config)
21947 {
21948 $this->config = $config;
21949
21950 return $this;
21951 }
21952
21953
21954
21955
21956
21957
21958
21959 public function setVerbose($verbose = true)
21960 {
21961 $this->verbose = (bool) $verbose;
21962
21963 return $this;
21964 }
21965
21966
21967
21968
21969
21970
21971 public function isVerbose()
21972 {
21973 return $this->verbose;
21974 }
21975
21976
21977
21978
21979
21980
21981
21982 public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
21983 {
21984 $this->ignorePlatformReqs = (bool) $ignorePlatformReqs;
21985
21986 return $this;
21987 }
21988
21989
21990
21991
21992
21993
21994
21995
21996 public function setUpdateWhitelist(array $packages)
21997 {
21998 $this->updateWhitelist = array_flip(array_map('strtolower', $packages));
21999
22000 return $this;
22001 }
22002
22003
22004
22005
22006 public function setWhitelistDependencies($updateDependencies = true)
22007 {
22008 return $this->setWhitelistTransitiveDependencies($updateDependencies);
22009 }
22010
22011
22012
22013
22014
22015
22016
22017
22018
22019
22020 public function setWhitelistTransitiveDependencies($updateTransitiveDependencies = true)
22021 {
22022 $this->whitelistDependencies = (bool) $updateTransitiveDependencies;
22023
22024 return $this;
22025 }
22026
22027
22028
22029
22030
22031
22032
22033
22034
22035
22036 public function setWhitelistAllDependencies($updateAllDependencies = true)
22037 {
22038 $this->whitelistAllDependencies = (bool) $updateAllDependencies;
22039
22040 return $this;
22041 }
22042
22043
22044
22045
22046
22047
22048
22049 public function setPreferStable($preferStable = true)
22050 {
22051 $this->preferStable = (bool) $preferStable;
22052
22053 return $this;
22054 }
22055
22056
22057
22058
22059
22060
22061
22062 public function setPreferLowest($preferLowest = true)
22063 {
22064 $this->preferLowest = (bool) $preferLowest;
22065
22066 return $this;
22067 }
22068
22069
22070
22071
22072
22073
22074
22075
22076
22077 public function setWriteLock($writeLock = true)
22078 {
22079 $this->writeLock = (bool) $writeLock;
22080
22081 return $this;
22082 }
22083
22084
22085
22086
22087
22088
22089
22090
22091
22092 public function setExecuteOperations($executeOperations = true)
22093 {
22094 $this->executeOperations = (bool) $executeOperations;
22095
22096 return $this;
22097 }
22098
22099
22100
22101
22102
22103
22104
22105 public function setSkipSuggest($skipSuggest = true)
22106 {
22107 $this->skipSuggest = (bool) $skipSuggest;
22108
22109 return $this;
22110 }
22111
22112
22113
22114
22115
22116
22117
22118
22119
22120
22121 public function disablePlugins()
22122 {
22123 $this->installationManager->disablePlugins();
22124
22125 return $this;
22126 }
22127
22128
22129
22130
22131
22132 public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter)
22133 {
22134 $this->suggestedPackagesReporter = $suggestedPackagesReporter;
22135
22136 return $this;
22137 }
22138 }
22139 <?php
22140
22141
22142
22143
22144
22145
22146
22147
22148
22149
22150
22151 namespace Composer\Installer;
22152
22153 use Composer\IO\IOInterface;
22154 use Composer\Package\PackageInterface;
22155 use Composer\Util\Filesystem;
22156 use Composer\Util\Platform;
22157 use Composer\Util\ProcessExecutor;
22158 use Composer\Util\Silencer;
22159
22160
22161
22162
22163
22164
22165
22166
22167 class BinaryInstaller
22168 {
22169 protected $binDir;
22170 protected $binCompat;
22171 protected $io;
22172 protected $filesystem;
22173
22174
22175
22176
22177
22178
22179
22180 public function __construct(IOInterface $io, $binDir, $binCompat, Filesystem $filesystem = null)
22181 {
22182 $this->binDir = $binDir;
22183 $this->binCompat = $binCompat;
22184 $this->io = $io;
22185 $this->filesystem = $filesystem ?: new Filesystem();
22186 }
22187
22188 public function installBinaries(PackageInterface $package, $installPath, $warnOnOverwrite = true)
22189 {
22190 $binaries = $this->getBinaries($package);
22191 if (!$binaries) {
22192 return;
22193 }
22194 foreach ($binaries as $bin) {
22195 $binPath = $installPath.'/'.$bin;
22196 if (!file_exists($binPath)) {
22197 $this->io->writeError('    <warning>Skipped installation of bin '.$bin.' for package '.$package->getName().': file not found in package</warning>');
22198 continue;
22199 }
22200
22201
22202  
22203  
22204  
22205  $binPath = realpath($binPath);
22206
22207 $this->initializeBinDir();
22208 $link = $this->binDir.'/'.basename($bin);
22209 if (file_exists($link)) {
22210 if (is_link($link)) {
22211
22212  
22213  
22214  Silencer::call('chmod', $link, 0777 & ~umask());
22215 }
22216 if ($warnOnOverwrite) {
22217 $this->io->writeError('    Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
22218 }
22219 continue;
22220 }
22221
22222 if ($this->binCompat === "auto") {
22223 if (Platform::isWindows()) {
22224 $this->installFullBinaries($binPath, $link, $bin, $package);
22225 } else {
22226 $this->installSymlinkBinaries($binPath, $link);
22227 }
22228 } elseif ($this->binCompat === "full") {
22229 $this->installFullBinaries($binPath, $link, $bin, $package);
22230 }
22231 Silencer::call('chmod', $link, 0777 & ~umask());
22232 }
22233 }
22234
22235 public function removeBinaries(PackageInterface $package)
22236 {
22237 $this->initializeBinDir();
22238
22239 $binaries = $this->getBinaries($package);
22240 if (!$binaries) {
22241 return;
22242 }
22243 foreach ($binaries as $bin) {
22244 $link = $this->binDir.'/'.basename($bin);
22245 if (is_link($link) || file_exists($link)) {
22246 $this->filesystem->unlink($link);
22247 }
22248 if (file_exists($link.'.bat')) {
22249 $this->filesystem->unlink($link.'.bat');
22250 }
22251 }
22252
22253
22254  if (is_dir($this->binDir) && $this->filesystem->isDirEmpty($this->binDir)) {
22255 Silencer::call('rmdir', $this->binDir);
22256 }
22257 }
22258
22259 public static function determineBinaryCaller($bin)
22260 {
22261 if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
22262 return 'call';
22263 }
22264
22265 $handle = fopen($bin, 'r');
22266 $line = fgets($handle);
22267 fclose($handle);
22268 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
22269 return trim($match[1]);
22270 }
22271
22272 return 'php';
22273 }
22274
22275 protected function getBinaries(PackageInterface $package)
22276 {
22277 return $package->getBinaries();
22278 }
22279
22280 protected function installFullBinaries($binPath, $link, $bin, PackageInterface $package)
22281 {
22282
22283  if ('.bat' !== substr($binPath, -4)) {
22284 $this->installUnixyProxyBinaries($binPath, $link);
22285 @chmod($link, 0777 & ~umask());
22286 $link .= '.bat';
22287 if (file_exists($link)) {
22288 $this->io->writeError('    Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
22289 }
22290 }
22291 if (!file_exists($link)) {
22292 file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
22293 }
22294 }
22295
22296 protected function installSymlinkBinaries($binPath, $link)
22297 {
22298 if (!$this->filesystem->relativeSymlink($binPath, $link)) {
22299 $this->installUnixyProxyBinaries($binPath, $link);
22300 }
22301 }
22302
22303 protected function installUnixyProxyBinaries($binPath, $link)
22304 {
22305 file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
22306 }
22307
22308 protected function initializeBinDir()
22309 {
22310 $this->filesystem->ensureDirectoryExists($this->binDir);
22311 $this->binDir = realpath($this->binDir);
22312 }
22313
22314 protected function generateWindowsProxyCode($bin, $link)
22315 {
22316 $binPath = $this->filesystem->findShortestPath($link, $bin);
22317 $caller = self::determineBinaryCaller($bin);
22318
22319 return "@ECHO OFF\r\n".
22320 "setlocal DISABLEDELAYEDEXPANSION\r\n".
22321 "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"\'')."\r\n".
22322 "{$caller} \"%BIN_TARGET%\" %*\r\n";
22323 }
22324
22325 protected function generateUnixyProxyCode($bin, $link)
22326 {
22327 $binPath = $this->filesystem->findShortestPath($link, $bin);
22328
22329 $binDir = ProcessExecutor::escape(dirname($binPath));
22330 $binFile = basename($binPath);
22331
22332 $proxyCode = <<<PROXY
22333 #!/usr/bin/env sh
22334
22335 dir=\$(cd "\${0%[/\\\\]*}" > /dev/null; cd $binDir && pwd)
22336
22337 if [ -d /proc/cygdrive ] && [[ \$(which php) == \$(readlink -n /proc/cygdrive)/* ]]; then
22338    # We are in Cgywin using Windows php, so the path must be translated
22339    dir=\$(cygpath -m "\$dir");
22340 fi
22341
22342 "\${dir}/$binFile" "\$@"
22343
22344 PROXY;
22345
22346 return $proxyCode;
22347 }
22348 }
22349 <?php
22350
22351
22352
22353
22354
22355
22356
22357
22358
22359
22360
22361 namespace Composer\Installer;
22362
22363 use Composer\Package\PackageInterface;
22364
22365
22366
22367
22368
22369
22370 interface BinaryPresenceInterface
22371 {
22372
22373
22374
22375
22376
22377 public function ensureBinariesPresence(PackageInterface $package);
22378 }
22379 <?php
22380
22381
22382
22383
22384
22385
22386
22387
22388
22389
22390
22391 namespace Composer\Installer;
22392
22393 use Composer\IO\IOInterface;
22394 use Composer\Package\PackageInterface;
22395 use Composer\Package\AliasPackage;
22396 use Composer\Repository\RepositoryInterface;
22397 use Composer\Repository\InstalledRepositoryInterface;
22398 use Composer\DependencyResolver\Operation\OperationInterface;
22399 use Composer\DependencyResolver\Operation\InstallOperation;
22400 use Composer\DependencyResolver\Operation\UpdateOperation;
22401 use Composer\DependencyResolver\Operation\UninstallOperation;
22402 use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
22403 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
22404 use Composer\Util\StreamContextFactory;
22405
22406
22407
22408
22409
22410
22411
22412
22413 class InstallationManager
22414 {
22415 private $installers = array();
22416 private $cache = array();
22417 private $notifiablePackages = array();
22418
22419 public function reset()
22420 {
22421 $this->notifiablePackages = array();
22422 }
22423
22424
22425
22426
22427
22428
22429 public function addInstaller(InstallerInterface $installer)
22430 {
22431 array_unshift($this->installers, $installer);
22432 $this->cache = array();
22433 }
22434
22435
22436
22437
22438
22439
22440 public function removeInstaller(InstallerInterface $installer)
22441 {
22442 if (false !== ($key = array_search($installer, $this->installers, true))) {
22443 array_splice($this->installers, $key, 1);
22444 $this->cache = array();
22445 }
22446 }
22447
22448
22449
22450
22451
22452
22453
22454
22455 public function disablePlugins()
22456 {
22457 foreach ($this->installers as $i => $installer) {
22458 if (!$installer instanceof PluginInstaller) {
22459 continue;
22460 }
22461
22462 unset($this->installers[$i]);
22463 }
22464 }
22465
22466
22467
22468
22469
22470
22471
22472
22473
22474 public function getInstaller($type)
22475 {
22476 $type = strtolower($type);
22477
22478 if (isset($this->cache[$type])) {
22479 return $this->cache[$type];
22480 }
22481
22482 foreach ($this->installers as $installer) {
22483 if ($installer->supports($type)) {
22484 return $this->cache[$type] = $installer;
22485 }
22486 }
22487
22488 throw new \InvalidArgumentException('Unknown installer type: '.$type);
22489 }
22490
22491
22492
22493
22494
22495
22496
22497
22498
22499 public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22500 {
22501 if ($package instanceof AliasPackage) {
22502 return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
22503 }
22504
22505 return $this->getInstaller($package->getType())->isInstalled($repo, $package);
22506 }
22507
22508
22509
22510
22511
22512
22513
22514 public function ensureBinariesPresence(PackageInterface $package)
22515 {
22516 try {
22517 $installer = $this->getInstaller($package->getType());
22518 } catch (\InvalidArgumentException $e) {
22519
22520  return;
22521 }
22522
22523
22524  if ($installer instanceof BinaryPresenceInterface) {
22525 $installer->ensureBinariesPresence($package);
22526 }
22527 }
22528
22529
22530
22531
22532
22533
22534
22535 public function execute(RepositoryInterface $repo, OperationInterface $operation)
22536 {
22537 $method = $operation->getJobType();
22538 $this->$method($repo, $operation);
22539 }
22540
22541
22542
22543
22544
22545
22546
22547 public function install(RepositoryInterface $repo, InstallOperation $operation)
22548 {
22549 $package = $operation->getPackage();
22550 $installer = $this->getInstaller($package->getType());
22551 $installer->install($repo, $package);
22552 $this->markForNotification($package);
22553 }
22554
22555
22556
22557
22558
22559
22560
22561 public function update(RepositoryInterface $repo, UpdateOperation $operation)
22562 {
22563 $initial = $operation->getInitialPackage();
22564 $target = $operation->getTargetPackage();
22565
22566 $initialType = $initial->getType();
22567 $targetType = $target->getType();
22568
22569 if ($initialType === $targetType) {
22570 $installer = $this->getInstaller($initialType);
22571 $installer->update($repo, $initial, $target);
22572 $this->markForNotification($target);
22573 } else {
22574 $this->getInstaller($initialType)->uninstall($repo, $initial);
22575 $this->getInstaller($targetType)->install($repo, $target);
22576 }
22577 }
22578
22579
22580
22581
22582
22583
22584
22585 public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
22586 {
22587 $package = $operation->getPackage();
22588 $installer = $this->getInstaller($package->getType());
22589 $installer->uninstall($repo, $package);
22590 }
22591
22592
22593
22594
22595
22596
22597
22598 public function markAliasInstalled(RepositoryInterface $repo, MarkAliasInstalledOperation $operation)
22599 {
22600 $package = $operation->getPackage();
22601
22602 if (!$repo->hasPackage($package)) {
22603 $repo->addPackage(clone $package);
22604 }
22605 }
22606
22607
22608
22609
22610
22611
22612
22613 public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
22614 {
22615 $package = $operation->getPackage();
22616
22617 $repo->removePackage($package);
22618 }
22619
22620
22621
22622
22623
22624
22625
22626 public function getInstallPath(PackageInterface $package)
22627 {
22628 $installer = $this->getInstaller($package->getType());
22629
22630 return $installer->getInstallPath($package);
22631 }
22632
22633 public function notifyInstalls(IOInterface $io)
22634 {
22635 foreach ($this->notifiablePackages as $repoUrl => $packages) {
22636 $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
22637 if ($io->hasAuthentication($repositoryName)) {
22638 $auth = $io->getAuthentication($repositoryName);
22639 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
22640 $authHeader = 'Authorization: Basic '.$authStr;
22641 }
22642
22643
22644  if (strpos($repoUrl, '%package%')) {
22645 foreach ($packages as $package) {
22646 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
22647
22648 $params = array(
22649 'version' => $package->getPrettyVersion(),
22650 'version_normalized' => $package->getVersion(),
22651 );
22652 $opts = array('http' =>
22653 array(
22654 'method' => 'POST',
22655 'header' => array('Content-type: application/x-www-form-urlencoded'),
22656 'content' => http_build_query($params, '', '&'),
22657 'timeout' => 3,
22658 ),
22659 );
22660 if (isset($authHeader)) {
22661 $opts['http']['header'][] = $authHeader;
22662 }
22663
22664 $context = StreamContextFactory::getContext($url, $opts);
22665 @file_get_contents($url, false, $context);
22666 }
22667
22668 continue;
22669 }
22670
22671 $postData = array('downloads' => array());
22672 foreach ($packages as $package) {
22673 $postData['downloads'][] = array(
22674 'name' => $package->getPrettyName(),
22675 'version' => $package->getVersion(),
22676 );
22677 }
22678
22679 $opts = array('http' =>
22680 array(
22681 'method' => 'POST',
22682 'header' => array('Content-Type: application/json'),
22683 'content' => json_encode($postData),
22684 'timeout' => 6,
22685 ),
22686 );
22687 if (isset($authHeader)) {
22688 $opts['http']['header'][] = $authHeader;
22689 }
22690
22691 $context = StreamContextFactory::getContext($repoUrl, $opts);
22692 @file_get_contents($repoUrl, false, $context);
22693 }
22694
22695 $this->reset();
22696 }
22697
22698 private function markForNotification(PackageInterface $package)
22699 {
22700 if ($package->getNotificationUrl()) {
22701 $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
22702 }
22703 }
22704 }
22705 <?php
22706
22707
22708
22709
22710
22711
22712
22713
22714
22715
22716
22717 namespace Composer\Installer;
22718
22719 use Composer\Composer;
22720 use Composer\DependencyResolver\PolicyInterface;
22721 use Composer\DependencyResolver\Operation\OperationInterface;
22722 use Composer\DependencyResolver\Pool;
22723 use Composer\DependencyResolver\Request;
22724 use Composer\EventDispatcher\Event;
22725 use Composer\IO\IOInterface;
22726 use Composer\Repository\CompositeRepository;
22727
22728
22729
22730
22731
22732
22733 class InstallerEvent extends Event
22734 {
22735
22736
22737
22738 private $composer;
22739
22740
22741
22742
22743 private $io;
22744
22745
22746
22747
22748 private $devMode;
22749
22750
22751
22752
22753 private $policy;
22754
22755
22756
22757
22758 private $pool;
22759
22760
22761
22762
22763 private $installedRepo;
22764
22765
22766
22767
22768 private $request;
22769
22770
22771
22772
22773 private $operations;
22774
22775
22776
22777
22778
22779
22780
22781
22782
22783
22784
22785
22786
22787
22788 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
22789 {
22790 parent::__construct($eventName);
22791
22792 $this->composer = $composer;
22793 $this->io = $io;
22794 $this->devMode = $devMode;
22795 $this->policy = $policy;
22796 $this->pool = $pool;
22797 $this->installedRepo = $installedRepo;
22798 $this->request = $request;
22799 $this->operations = $operations;
22800 }
22801
22802
22803
22804
22805 public function getComposer()
22806 {
22807 return $this->composer;
22808 }
22809
22810
22811
22812
22813 public function getIO()
22814 {
22815 return $this->io;
22816 }
22817
22818
22819
22820
22821 public function isDevMode()
22822 {
22823 return $this->devMode;
22824 }
22825
22826
22827
22828
22829 public function getPolicy()
22830 {
22831 return $this->policy;
22832 }
22833
22834
22835
22836
22837 public function getPool()
22838 {
22839 return $this->pool;
22840 }
22841
22842
22843
22844
22845 public function getInstalledRepo()
22846 {
22847 return $this->installedRepo;
22848 }
22849
22850
22851
22852
22853 public function getRequest()
22854 {
22855 return $this->request;
22856 }
22857
22858
22859
22860
22861 public function getOperations()
22862 {
22863 return $this->operations;
22864 }
22865 }
22866 <?php
22867
22868
22869
22870
22871
22872
22873
22874
22875
22876
22877
22878 namespace Composer\Installer;
22879
22880
22881
22882
22883
22884
22885 class InstallerEvents
22886 {
22887
22888
22889
22890
22891
22892
22893
22894
22895
22896 const PRE_DEPENDENCIES_SOLVING = 'pre-dependencies-solving';
22897
22898
22899
22900
22901
22902
22903
22904
22905
22906
22907 const POST_DEPENDENCIES_SOLVING = 'post-dependencies-solving';
22908 }
22909 <?php
22910
22911
22912
22913
22914
22915
22916
22917
22918
22919
22920
22921 namespace Composer\Installer;
22922
22923 use Composer\Package\PackageInterface;
22924 use Composer\Repository\InstalledRepositoryInterface;
22925 use InvalidArgumentException;
22926
22927
22928
22929
22930
22931
22932
22933 interface InstallerInterface
22934 {
22935
22936
22937
22938
22939
22940
22941 public function supports($packageType);
22942
22943
22944
22945
22946
22947
22948
22949
22950
22951 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
22952
22953
22954
22955
22956
22957
22958
22959 public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
22960
22961
22962
22963
22964
22965
22966
22967
22968
22969
22970 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
22971
22972
22973
22974
22975
22976
22977
22978 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
22979
22980
22981
22982
22983
22984
22985
22986 public function getInstallPath(PackageInterface $package);
22987 }
22988 <?php
22989
22990
22991
22992
22993
22994
22995
22996
22997
22998
22999
23000 namespace Composer\Installer;
23001
23002 use Composer\Composer;
23003 use Composer\IO\IOInterface;
23004 use Composer\Repository\InstalledRepositoryInterface;
23005 use Composer\Package\PackageInterface;
23006 use Composer\Util\Filesystem;
23007 use Composer\Util\Silencer;
23008 use Composer\Util\Platform;
23009
23010
23011
23012
23013
23014
23015
23016 class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
23017 {
23018 protected $composer;
23019 protected $vendorDir;
23020 protected $binDir;
23021 protected $downloadManager;
23022 protected $io;
23023 protected $type;
23024 protected $filesystem;
23025 protected $binCompat;
23026 protected $binaryInstaller;
23027
23028
23029
23030
23031
23032
23033
23034
23035
23036
23037 public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null, BinaryInstaller $binaryInstaller = null)
23038 {
23039 $this->composer = $composer;
23040 $this->downloadManager = $composer->getDownloadManager();
23041 $this->io = $io;
23042 $this->type = $type;
23043
23044 $this->filesystem = $filesystem ?: new Filesystem();
23045 $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
23046 $this->binaryInstaller = $binaryInstaller ?: new BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem);
23047 }
23048
23049
23050
23051
23052 public function supports($packageType)
23053 {
23054 return $packageType === $this->type || null === $this->type;
23055 }
23056
23057
23058
23059
23060 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23061 {
23062 if (!$repo->hasPackage($package)) {
23063 return false;
23064 }
23065
23066 $installPath = $this->getInstallPath($package);
23067
23068 if (is_readable($installPath)) {
23069 return true;
23070 }
23071
23072 return (Platform::isWindows() && $this->filesystem->isJunction($installPath)) || is_link($installPath);
23073 }
23074
23075
23076
23077
23078 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23079 {
23080 $this->initializeVendorDir();
23081 $downloadPath = $this->getInstallPath($package);
23082
23083
23084  if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
23085 $this->binaryInstaller->removeBinaries($package);
23086 }
23087
23088 $this->installCode($package);
23089 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package));
23090 if (!$repo->hasPackage($package)) {
23091 $repo->addPackage(clone $package);
23092 }
23093 }
23094
23095
23096
23097
23098 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23099 {
23100 if (!$repo->hasPackage($initial)) {
23101 throw new \InvalidArgumentException('Package is not installed: '.$initial);
23102 }
23103
23104 $this->initializeVendorDir();
23105
23106 $this->binaryInstaller->removeBinaries($initial);
23107 $this->updateCode($initial, $target);
23108 $this->binaryInstaller->installBinaries($target, $this->getInstallPath($target));
23109 $repo->removePackage($initial);
23110 if (!$repo->hasPackage($target)) {
23111 $repo->addPackage(clone $target);
23112 }
23113 }
23114
23115
23116
23117
23118 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23119 {
23120 if (!$repo->hasPackage($package)) {
23121 throw new \InvalidArgumentException('Package is not installed: '.$package);
23122 }
23123
23124 $this->removeCode($package);
23125 $this->binaryInstaller->removeBinaries($package);
23126 $repo->removePackage($package);
23127
23128 $downloadPath = $this->getPackageBasePath($package);
23129 if (strpos($package->getName(), '/')) {
23130 $packageVendorDir = dirname($downloadPath);
23131 if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
23132 Silencer::call('rmdir', $packageVendorDir);
23133 }
23134 }
23135 }
23136
23137
23138
23139
23140 public function getInstallPath(PackageInterface $package)
23141 {
23142 $this->initializeVendorDir();
23143
23144 $basePath = ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
23145 $targetDir = $package->getTargetDir();
23146
23147 return $basePath . ($targetDir ? '/'.$targetDir : '');
23148 }
23149
23150
23151
23152
23153
23154
23155 public function ensureBinariesPresence(PackageInterface $package)
23156 {
23157 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), false);
23158 }
23159
23160
23161
23162
23163
23164
23165
23166
23167
23168
23169 protected function getPackageBasePath(PackageInterface $package)
23170 {
23171 $installPath = $this->getInstallPath($package);
23172 $targetDir = $package->getTargetDir();
23173
23174 if ($targetDir) {
23175 return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath);
23176 }
23177
23178 return $installPath;
23179 }
23180
23181 protected function installCode(PackageInterface $package)
23182 {
23183 $downloadPath = $this->getInstallPath($package);
23184 $this->downloadManager->download($package, $downloadPath);
23185 }
23186
23187 protected function updateCode(PackageInterface $initial, PackageInterface $target)
23188 {
23189 $initialDownloadPath = $this->getInstallPath($initial);
23190 $targetDownloadPath = $this->getInstallPath($target);
23191 if ($targetDownloadPath !== $initialDownloadPath) {
23192
23193  
23194  if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
23195 || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
23196 ) {
23197 $this->removeCode($initial);
23198 $this->installCode($target);
23199
23200 return;
23201 }
23202
23203 $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
23204 }
23205 $this->downloadManager->update($initial, $target, $targetDownloadPath);
23206 }
23207
23208 protected function removeCode(PackageInterface $package)
23209 {
23210 $downloadPath = $this->getPackageBasePath($package);
23211 $this->downloadManager->remove($package, $downloadPath);
23212 }
23213
23214 protected function initializeVendorDir()
23215 {
23216 $this->filesystem->ensureDirectoryExists($this->vendorDir);
23217 $this->vendorDir = realpath($this->vendorDir);
23218 }
23219 }
23220 <?php
23221
23222
23223
23224
23225
23226
23227
23228
23229
23230
23231
23232 namespace Composer\Installer;
23233
23234 use Composer\Repository\InstalledRepositoryInterface;
23235 use Composer\Package\PackageInterface;
23236
23237
23238
23239
23240
23241
23242 class MetapackageInstaller implements InstallerInterface
23243 {
23244
23245
23246
23247 public function supports($packageType)
23248 {
23249 return $packageType === 'metapackage';
23250 }
23251
23252
23253
23254
23255 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23256 {
23257 return $repo->hasPackage($package);
23258 }
23259
23260
23261
23262
23263 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23264 {
23265 $repo->addPackage(clone $package);
23266 }
23267
23268
23269
23270
23271 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23272 {
23273 if (!$repo->hasPackage($initial)) {
23274 throw new \InvalidArgumentException('Package is not installed: '.$initial);
23275 }
23276
23277 $repo->removePackage($initial);
23278 $repo->addPackage(clone $target);
23279 }
23280
23281
23282
23283
23284 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23285 {
23286 if (!$repo->hasPackage($package)) {
23287 throw new \InvalidArgumentException('Package is not installed: '.$package);
23288 }
23289
23290 $repo->removePackage($package);
23291 }
23292
23293
23294
23295
23296 public function getInstallPath(PackageInterface $package)
23297 {
23298 return '';
23299 }
23300 }
23301 <?php
23302
23303
23304
23305
23306
23307
23308
23309
23310
23311
23312
23313 namespace Composer\Installer;
23314
23315 use Composer\Repository\InstalledRepositoryInterface;
23316 use Composer\Package\PackageInterface;
23317
23318
23319
23320
23321
23322
23323
23324
23325 class NoopInstaller implements InstallerInterface
23326 {
23327
23328
23329
23330 public function supports($packageType)
23331 {
23332 return true;
23333 }
23334
23335
23336
23337
23338 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23339 {
23340 return $repo->hasPackage($package);
23341 }
23342
23343
23344
23345
23346 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23347 {
23348 if (!$repo->hasPackage($package)) {
23349 $repo->addPackage(clone $package);
23350 }
23351 }
23352
23353
23354
23355
23356 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23357 {
23358 if (!$repo->hasPackage($initial)) {
23359 throw new \InvalidArgumentException('Package is not installed: '.$initial);
23360 }
23361
23362 $repo->removePackage($initial);
23363 if (!$repo->hasPackage($target)) {
23364 $repo->addPackage(clone $target);
23365 }
23366 }
23367
23368
23369
23370
23371 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23372 {
23373 if (!$repo->hasPackage($package)) {
23374 throw new \InvalidArgumentException('Package is not installed: '.$package);
23375 }
23376 $repo->removePackage($package);
23377 }
23378
23379
23380
23381
23382 public function getInstallPath(PackageInterface $package)
23383 {
23384 $targetDir = $package->getTargetDir();
23385
23386 return $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
23387 }
23388 }
23389 <?php
23390
23391
23392
23393
23394
23395
23396
23397
23398
23399
23400
23401 namespace Composer\Installer;
23402
23403 use Composer\Composer;
23404 use Composer\IO\IOInterface;
23405 use Composer\DependencyResolver\Operation\OperationInterface;
23406 use Composer\DependencyResolver\PolicyInterface;
23407 use Composer\DependencyResolver\Pool;
23408 use Composer\DependencyResolver\Request;
23409 use Composer\Repository\CompositeRepository;
23410
23411
23412
23413
23414
23415
23416 class PackageEvent extends InstallerEvent
23417 {
23418
23419
23420
23421 private $operation;
23422
23423
23424
23425
23426
23427
23428
23429
23430
23431
23432
23433
23434
23435
23436
23437 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
23438 {
23439 parent::__construct($eventName, $composer, $io, $devMode, $policy, $pool, $installedRepo, $request, $operations);
23440
23441 $this->operation = $operation;
23442 }
23443
23444
23445
23446
23447
23448
23449 public function getOperation()
23450 {
23451 return $this->operation;
23452 }
23453 }
23454 <?php
23455
23456
23457
23458
23459
23460
23461
23462
23463
23464
23465
23466 namespace Composer\Installer;
23467
23468
23469
23470
23471
23472
23473 class PackageEvents
23474 {
23475
23476
23477
23478
23479
23480
23481
23482 const PRE_PACKAGE_INSTALL = 'pre-package-install';
23483
23484
23485
23486
23487
23488
23489
23490
23491 const POST_PACKAGE_INSTALL = 'post-package-install';
23492
23493
23494
23495
23496
23497
23498
23499
23500 const PRE_PACKAGE_UPDATE = 'pre-package-update';
23501
23502
23503
23504
23505
23506
23507
23508
23509 const POST_PACKAGE_UPDATE = 'post-package-update';
23510
23511
23512
23513
23514
23515
23516
23517
23518 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
23519
23520
23521
23522
23523
23524
23525
23526
23527 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
23528 }
23529 <?php
23530
23531
23532
23533
23534
23535
23536
23537
23538
23539
23540
23541 namespace Composer\Installer;
23542
23543 use Composer\IO\IOInterface;
23544 use Composer\Package\PackageInterface;
23545 use Composer\Util\Filesystem;
23546 use Composer\Util\ProcessExecutor;
23547
23548
23549
23550
23551
23552
23553 class PearBinaryInstaller extends BinaryInstaller
23554 {
23555 private $installer;
23556 private $vendorDir;
23557
23558
23559
23560
23561
23562
23563
23564
23565
23566 public function __construct(IOInterface $io, $binDir, $vendorDir, $binCompat, Filesystem $filesystem, PearInstaller $installer)
23567 {
23568 parent::__construct($io, $binDir, $binCompat, $filesystem);
23569 $this->installer = $installer;
23570 $this->vendorDir = $vendorDir;
23571 }
23572
23573 protected function getBinaries(PackageInterface $package)
23574 {
23575 $binariesPath = $this->installer->getInstallPath($package) . '/bin/';
23576 $binaries = array();
23577 if (file_exists($binariesPath)) {
23578 foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::CURRENT_AS_FILEINFO) as $fileName => $value) {
23579 if (!$value->isDir()) {
23580 $binaries[] = 'bin/'.$fileName;
23581 }
23582 }
23583 }
23584
23585 return $binaries;
23586 }
23587
23588 protected function initializeBinDir()
23589 {
23590 parent::initializeBinDir();
23591 file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode());
23592 @chmod($this->binDir.'/composer-php', 0777 & ~umask());
23593 file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode());
23594 @chmod($this->binDir.'/composer-php.bat', 0777 & ~umask());
23595 }
23596
23597 protected function generateWindowsProxyCode($bin, $link)
23598 {
23599 $binPath = $this->filesystem->findShortestPath($link, $bin);
23600 if ('.bat' === substr($bin, -4)) {
23601 $caller = 'call';
23602 } else {
23603 $handle = fopen($bin, 'r');
23604 $line = fgets($handle);
23605 fclose($handle);
23606 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
23607 $caller = trim($match[1]);
23608 } else {
23609 $caller = 'php';
23610 }
23611
23612 if ($caller === 'php') {
23613 return "@echo off\r\n".
23614 "pushd .\r\n".
23615 "cd %~dp0\r\n".
23616 "set PHP_PROXY=%CD%\\composer-php.bat\r\n".
23617 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
23618 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
23619 "popd\r\n".
23620 "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n";
23621 }
23622 }
23623
23624 return "@echo off\r\n".
23625 "pushd .\r\n".
23626 "cd %~dp0\r\n".
23627 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
23628 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
23629 "popd\r\n".
23630 $caller." \"%BIN_TARGET%\" %*\r\n";
23631 }
23632
23633 private function generateWindowsPhpProxyCode()
23634 {
23635 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
23636
23637 return
23638 "@echo off\r\n" .
23639 "setlocal enabledelayedexpansion\r\n" .
23640 "set BIN_DIR=%~dp0\r\n" .
23641 "set VENDOR_DIR=%BIN_DIR%\\".$binToVendor."\r\n" .
23642 "set DIRS=.\r\n" .
23643 "FOR /D %%V IN (%VENDOR_DIR%\\*) DO (\r\n" .
23644 "    FOR /D %%P IN (%%V\\*) DO (\r\n" .
23645 "        set DIRS=!DIRS!;%%~fP\r\n" .
23646 "    )\r\n" .
23647 ")\r\n" .
23648 "php.exe -d include_path=!DIRS! %*\r\n";
23649 }
23650
23651 private function generateUnixyPhpProxyCode()
23652 {
23653 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
23654
23655 return
23656 "#!/usr/bin/env sh\n".
23657 "SRC_DIR=`pwd`\n".
23658 "BIN_DIR=`dirname $0`\n".
23659 "VENDOR_DIR=\$BIN_DIR/".escapeshellarg($binToVendor)."\n".
23660 "DIRS=\"\"\n".
23661 "for vendor in \$VENDOR_DIR/*; do\n".
23662 "    if [ -d \"\$vendor\" ]; then\n".
23663 "        for package in \$vendor/*; do\n".
23664 "            if [ -d \"\$package\" ]; then\n".
23665 "                DIRS=\"\${DIRS}:\${package}\"\n".
23666 "            fi\n".
23667 "        done\n".
23668 "    fi\n".
23669 "done\n".
23670 "php -d include_path=\".\$DIRS\" $@\n";
23671 }
23672 }
23673 <?php
23674
23675
23676
23677
23678
23679
23680
23681
23682
23683
23684
23685 namespace Composer\Installer;
23686
23687 use Composer\IO\IOInterface;
23688 use Composer\Composer;
23689 use Composer\Downloader\PearPackageExtractor;
23690 use Composer\Repository\InstalledRepositoryInterface;
23691 use Composer\Package\PackageInterface;
23692 use Composer\Util\Platform;
23693 use Composer\Util\Filesystem;
23694
23695
23696
23697
23698
23699
23700
23701 class PearInstaller extends LibraryInstaller
23702 {
23703
23704
23705
23706
23707
23708
23709
23710 public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
23711 {
23712 $filesystem = new Filesystem();
23713 $binaryInstaller = new PearBinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), rtrim($composer->getConfig()->get('vendor-dir'), '/'), $composer->getConfig()->get('bin-compat'), $filesystem, $this);
23714
23715 parent::__construct($io, $composer, $type, $filesystem, $binaryInstaller);
23716 }
23717
23718
23719
23720
23721 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23722 {
23723 $this->uninstall($repo, $initial);
23724 $this->install($repo, $target);
23725 }
23726
23727 protected function installCode(PackageInterface $package)
23728 {
23729 parent::installCode($package);
23730
23731 $isWindows = Platform::isWindows();
23732 $php_bin = $this->binDir . ($isWindows ? '/composer-php.bat' : '/composer-php');
23733
23734 if (!$isWindows) {
23735 $php_bin = '/usr/bin/env ' . $php_bin;
23736 }
23737
23738 $installPath = $this->getInstallPath($package);
23739 $vars = array(
23740 'os' => $isWindows ? 'windows' : 'linux',
23741 'php_bin' => $php_bin,
23742 'pear_php' => $installPath,
23743 'php_dir' => $installPath,
23744 'bin_dir' => $installPath . '/bin',
23745 'data_dir' => $installPath . '/data',
23746 'version' => $package->getPrettyVersion(),
23747 );
23748
23749 $packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
23750 $pearExtractor = new PearPackageExtractor($packageArchive);
23751 $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
23752
23753 $this->io->writeError('    Cleaning up', true, IOInterface::VERBOSE);
23754 $this->filesystem->unlink($packageArchive);
23755 }
23756 }
23757 <?php
23758
23759
23760
23761
23762
23763
23764
23765
23766
23767
23768
23769 namespace Composer\Installer;
23770
23771 use Composer\Composer;
23772 use Composer\IO\IOInterface;
23773 use Composer\Repository\InstalledRepositoryInterface;
23774 use Composer\Package\PackageInterface;
23775
23776
23777
23778
23779
23780
23781
23782 class PluginInstaller extends LibraryInstaller
23783 {
23784 private $installationManager;
23785
23786
23787
23788
23789
23790
23791
23792 public function __construct(IOInterface $io, Composer $composer)
23793 {
23794 parent::__construct($io, $composer, 'composer-plugin');
23795 $this->installationManager = $composer->getInstallationManager();
23796 }
23797
23798
23799
23800
23801 public function supports($packageType)
23802 {
23803 return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
23804 }
23805
23806
23807
23808
23809 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23810 {
23811 $extra = $package->getExtra();
23812 if (empty($extra['class'])) {
23813 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
23814 }
23815
23816 parent::install($repo, $package);
23817 try {
23818 $this->composer->getPluginManager()->registerPackage($package, true);
23819 } catch (\Exception $e) {
23820
23821  $this->io->writeError('Plugin installation failed, rolling back');
23822 parent::uninstall($repo, $package);
23823 throw $e;
23824 }
23825 }
23826
23827
23828
23829
23830 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23831 {
23832 $extra = $target->getExtra();
23833 if (empty($extra['class'])) {
23834 throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
23835 }
23836
23837 parent::update($repo, $initial, $target);
23838 $this->composer->getPluginManager()->registerPackage($target, true);
23839 }
23840 }
23841 <?php
23842
23843
23844
23845
23846
23847
23848
23849
23850
23851
23852
23853 namespace Composer\Installer;
23854
23855 use Composer\Package\PackageInterface;
23856 use Composer\Downloader\DownloadManager;
23857 use Composer\Repository\InstalledRepositoryInterface;
23858 use Composer\Util\Filesystem;
23859
23860
23861
23862
23863
23864
23865
23866 class ProjectInstaller implements InstallerInterface
23867 {
23868 private $installPath;
23869 private $downloadManager;
23870 private $filesystem;
23871
23872 public function __construct($installPath, DownloadManager $dm)
23873 {
23874 $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/';
23875 $this->downloadManager = $dm;
23876 $this->filesystem = new Filesystem;
23877 }
23878
23879
23880
23881
23882
23883
23884
23885 public function supports($packageType)
23886 {
23887 return true;
23888 }
23889
23890
23891
23892
23893 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23894 {
23895 return false;
23896 }
23897
23898
23899
23900
23901 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23902 {
23903 $installPath = $this->installPath;
23904 if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
23905 throw new \InvalidArgumentException("Project directory $installPath is not empty.");
23906 }
23907 if (!is_dir($installPath)) {
23908 mkdir($installPath, 0777, true);
23909 }
23910 $this->downloadManager->download($package, $installPath);
23911 }
23912
23913
23914
23915
23916 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23917 {
23918 throw new \InvalidArgumentException("not supported");
23919 }
23920
23921
23922
23923
23924 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23925 {
23926 throw new \InvalidArgumentException("not supported");
23927 }
23928
23929
23930
23931
23932
23933
23934
23935 public function getInstallPath(PackageInterface $package)
23936 {
23937 return $this->installPath;
23938 }
23939 }
23940 <?php
23941
23942
23943
23944
23945
23946
23947
23948
23949
23950
23951
23952 namespace Composer\Installer;
23953
23954 use Composer\IO\IOInterface;
23955 use Composer\Package\PackageInterface;
23956 use Composer\Repository\RepositoryInterface;
23957 use Symfony\Component\Console\Formatter\OutputFormatter;
23958
23959
23960
23961
23962
23963
23964 class SuggestedPackagesReporter
23965 {
23966
23967
23968
23969 protected $suggestedPackages = array();
23970
23971
23972
23973
23974 private $io;
23975
23976 public function __construct(IOInterface $io)
23977 {
23978 $this->io = $io;
23979 }
23980
23981
23982
23983
23984 public function getPackages()
23985 {
23986 return $this->suggestedPackages;
23987 }
23988
23989
23990
23991
23992
23993
23994
23995
23996
23997
23998
23999
24000 public function addPackage($source, $target, $reason)
24001 {
24002 $this->suggestedPackages[] = array(
24003 'source' => $source,
24004 'target' => $target,
24005 'reason' => $reason,
24006 );
24007
24008 return $this;
24009 }
24010
24011
24012
24013
24014
24015
24016
24017 public function addSuggestionsFromPackage(PackageInterface $package)
24018 {
24019 $source = $package->getPrettyName();
24020 foreach ($package->getSuggests() as $target => $reason) {
24021 $this->addPackage(
24022 $source,
24023 $target,
24024 $reason
24025 );
24026 }
24027
24028 return $this;
24029 }
24030
24031
24032
24033
24034
24035
24036
24037
24038 public function output(RepositoryInterface $installedRepo = null)
24039 {
24040 $suggestedPackages = $this->getPackages();
24041 $installedPackages = array();
24042 if (null !== $installedRepo && ! empty($suggestedPackages)) {
24043 foreach ($installedRepo->getPackages() as $package) {
24044 $installedPackages = array_merge(
24045 $installedPackages,
24046 $package->getNames()
24047 );
24048 }
24049 }
24050
24051 foreach ($suggestedPackages as $suggestion) {
24052 if (in_array($suggestion['target'], $installedPackages)) {
24053 continue;
24054 }
24055
24056 $this->io->writeError(sprintf(
24057 '%s suggests installing %s%s',
24058 $suggestion['source'],
24059 $this->escapeOutput($suggestion['target']),
24060 $this->escapeOutput('' !== $suggestion['reason'] ? ' ('.$suggestion['reason'].')' : '')
24061 ));
24062 }
24063
24064 return $this;
24065 }
24066
24067
24068
24069
24070
24071 private function escapeOutput($string)
24072 {
24073 return OutputFormatter::escape(
24074 $this->removeControlCharacters($string)
24075 );
24076 }
24077
24078
24079
24080
24081
24082 private function removeControlCharacters($string)
24083 {
24084 return preg_replace(
24085 '/[[:cntrl:]]/',
24086 '',
24087 str_replace("\n", ' ', $string)
24088 );
24089 }
24090 }
24091 <?php
24092
24093
24094
24095
24096
24097
24098
24099
24100
24101
24102
24103 namespace Composer\Json;
24104
24105 use JsonSchema\Validator;
24106 use Seld\JsonLint\JsonParser;
24107 use Seld\JsonLint\ParsingException;
24108 use Composer\Util\RemoteFilesystem;
24109 use Composer\IO\IOInterface;
24110 use Composer\Downloader\TransportException;
24111
24112
24113
24114
24115
24116
24117
24118 class JsonFile
24119 {
24120 const LAX_SCHEMA = 1;
24121 const STRICT_SCHEMA = 2;
24122
24123 const JSON_UNESCAPED_SLASHES = 64;
24124 const JSON_PRETTY_PRINT = 128;
24125 const JSON_UNESCAPED_UNICODE = 256;
24126
24127 private $path;
24128 private $rfs;
24129 private $io;
24130
24131
24132
24133
24134
24135
24136
24137
24138
24139 public function __construct($path, RemoteFilesystem $rfs = null, IOInterface $io = null)
24140 {
24141 $this->path = $path;
24142
24143 if (null === $rfs && preg_match('{^https?://}i', $path)) {
24144 throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed');
24145 }
24146 $this->rfs = $rfs;
24147 $this->io = $io;
24148 }
24149
24150
24151
24152
24153 public function getPath()
24154 {
24155 return $this->path;
24156 }
24157
24158
24159
24160
24161
24162
24163 public function exists()
24164 {
24165 return is_file($this->path);
24166 }
24167
24168
24169
24170
24171
24172
24173
24174 public function read()
24175 {
24176 try {
24177 if ($this->rfs) {
24178 $json = $this->rfs->getContents($this->path, $this->path, false);
24179 } else {
24180 if ($this->io && $this->io->isDebug()) {
24181 $this->io->writeError('Reading ' . $this->path);
24182 }
24183 $json = file_get_contents($this->path);
24184 }
24185 } catch (TransportException $e) {
24186 throw new \RuntimeException($e->getMessage(), 0, $e);
24187 } catch (\Exception $e) {
24188 throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
24189 }
24190
24191 return static::parseJson($json, $this->path);
24192 }
24193
24194
24195
24196
24197
24198
24199
24200
24201 public function write(array $hash, $options = 448)
24202 {
24203 $dir = dirname($this->path);
24204 if (!is_dir($dir)) {
24205 if (file_exists($dir)) {
24206 throw new \UnexpectedValueException(
24207 $dir.' exists and is not a directory.'
24208 );
24209 }
24210 if (!@mkdir($dir, 0777, true)) {
24211 throw new \UnexpectedValueException(
24212 $dir.' does not exist and could not be created.'
24213 );
24214 }
24215 }
24216
24217 $retries = 3;
24218 while ($retries--) {
24219 try {
24220 file_put_contents($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : ''));
24221 break;
24222 } catch (\Exception $e) {
24223 if ($retries) {
24224 usleep(500000);
24225 continue;
24226 }
24227
24228 throw $e;
24229 }
24230 }
24231 }
24232
24233
24234
24235
24236
24237
24238
24239
24240 public function validateSchema($schema = self::STRICT_SCHEMA)
24241 {
24242 $content = file_get_contents($this->path);
24243 $data = json_decode($content);
24244
24245 if (null === $data && 'null' !== $content) {
24246 self::validateSyntax($content, $this->path);
24247 }
24248
24249 $schemaFile = __DIR__ . '/../../../res/composer-schema.json';
24250
24251
24252  if (false === strpos($schemaFile, '://')) {
24253 $schemaFile = 'file://' . $schemaFile;
24254 }
24255
24256 $schemaData = (object) array('$ref' => $schemaFile);
24257
24258 if ($schema === self::LAX_SCHEMA) {
24259 $schemaData->additionalProperties = true;
24260 $schemaData->required = array();
24261 }
24262
24263 $validator = new Validator();
24264 $validator->check($data, $schemaData);
24265
24266
24267
24268 if (!$validator->isValid()) {
24269 $errors = array();
24270 foreach ((array) $validator->getErrors() as $error) {
24271 $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
24272 }
24273 throw new JsonValidationException('"'.$this->path.'" does not match the expected JSON schema', $errors);
24274 }
24275
24276 return true;
24277 }
24278
24279
24280
24281
24282
24283
24284
24285
24286 public static function encode($data, $options = 448)
24287 {
24288 if (PHP_VERSION_ID >= 50400) {
24289 $json = json_encode($data, $options);
24290 if (false === $json) {
24291 self::throwEncodeError(json_last_error());
24292 }
24293
24294
24295  if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
24296 $json = preg_replace('/\[\s+\]/', '[]', $json);
24297 $json = preg_replace('/\{\s+\}/', '{}', $json);
24298 }
24299
24300 return $json;
24301 }
24302
24303 $json = json_encode($data);
24304 if (false === $json) {
24305 self::throwEncodeError(json_last_error());
24306 }
24307
24308 $prettyPrint = (bool) ($options & self::JSON_PRETTY_PRINT);
24309 $unescapeUnicode = (bool) ($options & self::JSON_UNESCAPED_UNICODE);
24310 $unescapeSlashes = (bool) ($options & self::JSON_UNESCAPED_SLASHES);
24311
24312 if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes) {
24313 return $json;
24314 }
24315
24316 return JsonFormatter::format($json, $unescapeUnicode, $unescapeSlashes);
24317 }
24318
24319
24320
24321
24322
24323
24324
24325 private static function throwEncodeError($code)
24326 {
24327 switch ($code) {
24328 case JSON_ERROR_DEPTH:
24329 $msg = 'Maximum stack depth exceeded';
24330 break;
24331 case JSON_ERROR_STATE_MISMATCH:
24332 $msg = 'Underflow or the modes mismatch';
24333 break;
24334 case JSON_ERROR_CTRL_CHAR:
24335 $msg = 'Unexpected control character found';
24336 break;
24337 case JSON_ERROR_UTF8:
24338 $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
24339 break;
24340 default:
24341 $msg = 'Unknown error';
24342 }
24343
24344 throw new \RuntimeException('JSON encoding failed: '.$msg);
24345 }
24346
24347
24348
24349
24350
24351
24352
24353
24354
24355 public static function parseJson($json, $file = null)
24356 {
24357 if (null === $json) {
24358 return;
24359 }
24360 $data = json_decode($json, true);
24361 if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
24362 self::validateSyntax($json, $file);
24363 }
24364
24365 return $data;
24366 }
24367
24368
24369
24370
24371
24372
24373
24374
24375
24376
24377 protected static function validateSyntax($json, $file = null)
24378 {
24379 $parser = new JsonParser();
24380 $result = $parser->lint($json);
24381 if (null === $result) {
24382 if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
24383 throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
24384 }
24385
24386 return true;
24387 }
24388
24389 throw new ParsingException('"'.$file.'" does not contain valid JSON'."\n".$result->getMessage(), $result->getDetails());
24390 }
24391 }
24392 <?php
24393
24394
24395
24396
24397
24398
24399
24400
24401
24402
24403
24404 namespace Composer\Json;
24405
24406
24407
24408
24409
24410
24411
24412
24413
24414 class JsonFormatter
24415 {
24416
24417
24418
24419
24420
24421
24422
24423
24424
24425
24426
24427
24428 public static function format($json, $unescapeUnicode, $unescapeSlashes)
24429 {
24430 $result = '';
24431 $pos = 0;
24432 $strLen = strlen($json);
24433 $indentStr = '    ';
24434 $newLine = "\n";
24435 $outOfQuotes = true;
24436 $buffer = '';
24437 $noescape = true;
24438
24439 for ($i = 0; $i < $strLen; $i++) {
24440
24441  $char = substr($json, $i, 1);
24442
24443
24444  if ('"' === $char && $noescape) {
24445 $outOfQuotes = !$outOfQuotes;
24446 }
24447
24448 if (!$outOfQuotes) {
24449 $buffer .= $char;
24450 $noescape = '\\' === $char ? !$noescape : true;
24451 continue;
24452 } elseif ('' !== $buffer) {
24453 if ($unescapeSlashes) {
24454 $buffer = str_replace('\\/', '/', $buffer);
24455 }
24456
24457 if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
24458
24459  $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) {
24460 $l = strlen($match[1]);
24461
24462 if ($l % 2) {
24463 $code = hexdec($match[2]);
24464
24465  
24466  if (0xD800 <= $code && 0xDFFF >= $code) {
24467 return $match[0];
24468 }
24469
24470 return str_repeat('\\', $l - 1) . mb_convert_encoding(
24471 pack('H*', $match[2]),
24472 'UTF-8',
24473 'UCS-2BE'
24474 );
24475 }
24476
24477 return $match[0];
24478 }, $buffer);
24479 }
24480
24481 $result .= $buffer.$char;
24482 $buffer = '';
24483 continue;
24484 }
24485
24486 if (':' === $char) {
24487
24488  $char .= ' ';
24489 } elseif ('}' === $char || ']' === $char) {
24490 $pos--;
24491 $prevChar = substr($json, $i - 1, 1);
24492
24493 if ('{' !== $prevChar && '[' !== $prevChar) {
24494
24495  
24496  $result .= $newLine;
24497 for ($j = 0; $j < $pos; $j++) {
24498 $result .= $indentStr;
24499 }
24500 } else {
24501
24502  $result = rtrim($result);
24503 }
24504 }
24505
24506 $result .= $char;
24507
24508
24509  
24510  if (',' === $char || '{' === $char || '[' === $char) {
24511 $result .= $newLine;
24512
24513 if ('{' === $char || '[' === $char) {
24514 $pos++;
24515 }
24516
24517 for ($j = 0; $j < $pos; $j++) {
24518 $result .= $indentStr;
24519 }
24520 }
24521 }
24522
24523 return $result;
24524 }
24525 }
24526 <?php
24527
24528
24529
24530
24531
24532
24533
24534
24535
24536
24537
24538 namespace Composer\Json;
24539
24540 use Composer\Repository\PlatformRepository;
24541
24542
24543
24544
24545 class JsonManipulator
24546 {
24547 private static $DEFINES = '(?(DEFINE)
24548        (?<number>   -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
24549        (?<boolean>   true | false | null )
24550        (?<string>    " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
24551        (?<array>     \[  (?:  (?&json) \s* (?: , (?&json) \s* )*  )?  \s* \] )
24552        (?<pair>      \s* (?&string) \s* : (?&json) \s* )
24553        (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
24554        (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
24555     )';
24556
24557 private $contents;
24558 private $newline;
24559 private $indent;
24560
24561 public function __construct($contents)
24562 {
24563 $contents = trim($contents);
24564 if ($contents === '') {
24565 $contents = '{}';
24566 }
24567 if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) {
24568 throw new \InvalidArgumentException('The json file must be an object ({})');
24569 }
24570 $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
24571 $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
24572 $this->detectIndenting();
24573 }
24574
24575 public function getContents()
24576 {
24577 return $this->contents . $this->newline;
24578 }
24579
24580 public function addLink($type, $package, $constraint, $sortPackages = false)
24581 {
24582 $decoded = JsonFile::parseJson($this->contents);
24583
24584
24585  if (!isset($decoded[$type])) {
24586 return $this->addMainKey($type, array($package => $constraint));
24587 }
24588
24589 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24590 '(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
24591 if (!$this->pregMatch($regex, $this->contents, $matches)) {
24592 return false;
24593 }
24594
24595 $links = $matches['value'];
24596
24597
24598  $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
24599 $regex = '{'.self::$DEFINES.'"(?P<package>'.$packageRegex.')"(\s*:\s*)(?&string)}ix';
24600 if ($this->pregMatch($regex, $links, $packageMatches)) {
24601
24602  $existingPackage = $packageMatches['package'];
24603 $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage));
24604 $links = preg_replace_callback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P<separator>\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) {
24605 return JsonFile::encode(str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"';
24606 }, $links);
24607 } else {
24608 if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
24609
24610  $links = preg_replace(
24611 '{'.preg_quote($match[1]).'$}',
24612
24613  addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
24614 $links
24615 );
24616 } else {
24617
24618  $links = '{' . $this->newline .
24619 $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
24620 $this->indent . '}';
24621 }
24622 }
24623
24624 if (true === $sortPackages) {
24625 $requirements = json_decode($links, true);
24626 $this->sortPackages($requirements);
24627 $links = $this->format($requirements);
24628 }
24629
24630 $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end'];
24631
24632 return true;
24633 }
24634
24635
24636
24637
24638
24639
24640
24641
24642 private function sortPackages(array &$packages = array())
24643 {
24644 $prefix = function ($requirement) {
24645 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) {
24646 return preg_replace(
24647 array(
24648 '/^php/',
24649 '/^hhvm/',
24650 '/^ext/',
24651 '/^lib/',
24652 '/^\D/',
24653 ),
24654 array(
24655 '0-$0',
24656 '1-$0',
24657 '2-$0',
24658 '3-$0',
24659 '4-$0',
24660 ),
24661 $requirement
24662 );
24663 }
24664
24665 return '5-'.$requirement;
24666 };
24667
24668 uksort($packages, function ($a, $b) use ($prefix) {
24669 return strnatcmp($prefix($a), $prefix($b));
24670 });
24671 }
24672
24673 public function addRepository($name, $config)
24674 {
24675 return $this->addSubNode('repositories', $name, $config);
24676 }
24677
24678 public function removeRepository($name)
24679 {
24680 return $this->removeSubNode('repositories', $name);
24681 }
24682
24683 public function addConfigSetting($name, $value)
24684 {
24685 return $this->addSubNode('config', $name, $value);
24686 }
24687
24688 public function removeConfigSetting($name)
24689 {
24690 return $this->removeSubNode('config', $name);
24691 }
24692
24693 public function addProperty($name, $value)
24694 {
24695 if (substr($name, 0, 6) === 'extra.') {
24696 return $this->addSubNode('extra', substr($name, 6), $value);
24697 }
24698
24699 if (substr($name, 0, 8) === 'scripts.') {
24700 return $this->addSubNode('scripts', substr($name, 8), $value);
24701 }
24702
24703 return $this->addMainKey($name, $value);
24704 }
24705
24706 public function removeProperty($name)
24707 {
24708 if (substr($name, 0, 6) === 'extra.') {
24709 return $this->removeSubNode('extra', substr($name, 6));
24710 }
24711
24712 if (substr($name, 0, 8) === 'scripts.') {
24713 return $this->removeSubNode('scripts', substr($name, 8));
24714 }
24715
24716 return $this->removeMainKey($name);
24717 }
24718
24719 public function addSubNode($mainNode, $name, $value)
24720 {
24721 $decoded = JsonFile::parseJson($this->contents);
24722
24723 $subName = null;
24724 if (in_array($mainNode, array('config', 'extra', 'scripts')) && false !== strpos($name, '.')) {
24725 list($name, $subName) = explode('.', $name, 2);
24726 }
24727
24728
24729  if (!isset($decoded[$mainNode])) {
24730 if ($subName !== null) {
24731 $this->addMainKey($mainNode, array($name => array($subName => $value)));
24732 } else {
24733 $this->addMainKey($mainNode, array($name => $value));
24734 }
24735
24736 return true;
24737 }
24738
24739
24740  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
24741 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
24742
24743 try {
24744 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
24745 return false;
24746 }
24747 } catch (\RuntimeException $e) {
24748 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
24749 return false;
24750 }
24751 throw $e;
24752 }
24753
24754 $children = $match['content'];
24755
24756  if (!@json_decode($children)) {
24757 return false;
24758 }
24759
24760 $that = $this;
24761
24762
24763  $childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
24764 if ($this->pregMatch($childRegex, $children, $matches)) {
24765 $children = preg_replace_callback($childRegex, function ($matches) use ($subName, $value, $that) {
24766 if ($subName !== null) {
24767 $curVal = json_decode($matches['content'], true);
24768 if (!is_array($curVal)) {
24769 $curVal = array();
24770 }
24771 $curVal[$subName] = $value;
24772 $value = $curVal;
24773 }
24774
24775 return $matches['start'] . $that->format($value, 1) . $matches['end'];
24776 }, $children);
24777 } else {
24778 $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
24779
24780 $whitespace = '';
24781 if (!empty($match['trailingspace'])) {
24782 $whitespace = $match['trailingspace'];
24783 }
24784
24785 if (!empty($match['content'])) {
24786 if ($subName !== null) {
24787 $value = array($subName => $value);
24788 }
24789
24790
24791  $children = preg_replace(
24792 '#'.$whitespace.'}$#',
24793 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}', '\\$'),
24794 $children
24795 );
24796 } else {
24797 if ($subName !== null) {
24798 $value = array($subName => $value);
24799 }
24800
24801
24802  $children = '{' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}';
24803 }
24804 }
24805
24806 $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) {
24807 return $m['start'] . $children . $m['end'];
24808 }, $this->contents);
24809
24810 return true;
24811 }
24812
24813 public function removeSubNode($mainNode, $name)
24814 {
24815 $decoded = JsonFile::parseJson($this->contents);
24816
24817
24818  if (empty($decoded[$mainNode])) {
24819 return true;
24820 }
24821
24822
24823  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
24824 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
24825 try {
24826 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
24827 return false;
24828 }
24829 } catch (\RuntimeException $e) {
24830 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
24831 return false;
24832 }
24833 throw $e;
24834 }
24835
24836 $children = $match['content'];
24837
24838
24839  if (!@json_decode($children, true)) {
24840 return false;
24841 }
24842
24843 $subName = null;
24844 if (in_array($mainNode, array('config', 'extra', 'scripts')) && false !== strpos($name, '.')) {
24845 list($name, $subName) = explode('.', $name, 2);
24846 }
24847
24848
24849  if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
24850 return true;
24851 }
24852
24853
24854  if ($this->pregMatch('{"'.preg_quote($name).'"\s*:}i', $children)) {
24855
24856  if (preg_match_all('{'.self::$DEFINES.'"'.preg_quote($name).'"\s*:\s*(?:(?&json))}x', $children, $matches)) {
24857 $bestMatch = '';
24858 foreach ($matches[0] as $match) {
24859 if (strlen($bestMatch) < strlen($match)) {
24860 $bestMatch = $match;
24861 }
24862 }
24863 $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count);
24864 if (1 !== $count) {
24865 $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count);
24866 if (1 !== $count) {
24867 return false;
24868 }
24869 }
24870 }
24871 } else {
24872 $childrenClean = $children;
24873 }
24874
24875
24876  $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $childrenClean, $match);
24877 if (empty($match['content'])) {
24878 $newline = $this->newline;
24879 $indent = $this->indent;
24880
24881 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($indent, $newline) {
24882 return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
24883 }, $this->contents);
24884
24885
24886  if ($subName !== null) {
24887 $curVal = json_decode($children, true);
24888 unset($curVal[$name][$subName]);
24889 $this->addSubNode($mainNode, $name, $curVal[$name]);
24890 }
24891
24892 return true;
24893 }
24894
24895 $that = $this;
24896 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
24897 if ($subName !== null) {
24898 $curVal = json_decode($matches['content'], true);
24899 unset($curVal[$name][$subName]);
24900 $childrenClean = $that->format($curVal, 0);
24901 }
24902
24903 return $matches['start'] . $childrenClean . $matches['end'];
24904 }, $this->contents);
24905
24906 return true;
24907 }
24908
24909 public function addMainKey($key, $content)
24910 {
24911 $decoded = JsonFile::parseJson($this->contents);
24912 $content = $this->format($content);
24913
24914
24915  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24916 '(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}sx';
24917 if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
24918
24919  if (!@json_decode('{'.$matches['key'].'}')) {
24920 return false;
24921 }
24922
24923 $this->contents = $matches['start'] . JsonFile::encode($key).': '.$content . $matches['end'];
24924
24925 return true;
24926 }
24927
24928
24929  if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
24930 $this->contents = preg_replace(
24931 '#'.$match[1].'\}$#',
24932 addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'),
24933 $this->contents
24934 );
24935
24936 return true;
24937 }
24938
24939
24940  $this->contents = preg_replace(
24941 '#\}$#',
24942 addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'),
24943 $this->contents
24944 );
24945
24946 return true;
24947 }
24948
24949 public function removeMainKey($key)
24950 {
24951 $decoded = JsonFile::parseJson($this->contents);
24952
24953 if (!array_key_exists($key, $decoded)) {
24954 return true;
24955 }
24956
24957
24958  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24959 '(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
24960 if ($this->pregMatch($regex, $this->contents, $matches)) {
24961
24962  if (!@json_decode('{'.$matches['removal'].'}')) {
24963 return false;
24964 }
24965
24966
24967  if (preg_match('#,\s*$#', $matches['start']) && preg_match('#^\}$#', $matches['end'])) {
24968 $matches['start'] = rtrim(preg_replace('#,(\s*)$#', '$1', $matches['start']), $this->indent);
24969 }
24970
24971 $this->contents = $matches['start'] . $matches['end'];
24972 if (preg_match('#^\{\s*\}\s*$#', $this->contents)) {
24973 $this->contents = "{\n}";
24974 }
24975
24976 return true;
24977 }
24978
24979 return false;
24980 }
24981
24982 public function format($data, $depth = 0)
24983 {
24984 if (is_array($data)) {
24985 reset($data);
24986
24987 if (is_numeric(key($data))) {
24988 foreach ($data as $key => $val) {
24989 $data[$key] = $this->format($val, $depth + 1);
24990 }
24991
24992 return '['.implode(', ', $data).']';
24993 }
24994
24995 $out = '{' . $this->newline;
24996 $elems = array();
24997 foreach ($data as $key => $val) {
24998 $elems[] = str_repeat($this->indent, $depth + 2) . JsonFile::encode($key). ': '.$this->format($val, $depth + 1);
24999 }
25000
25001 return $out . implode(','.$this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
25002 }
25003
25004 return JsonFile::encode($data);
25005 }
25006
25007 protected function detectIndenting()
25008 {
25009 if ($this->pregMatch('{^([ \t]+)"}m', $this->contents, $match)) {
25010 $this->indent = $match[1];
25011 } else {
25012 $this->indent = '    ';
25013 }
25014 }
25015
25016 protected function pregMatch($re, $str, &$matches = array())
25017 {
25018 $count = preg_match($re, $str, $matches);
25019
25020 if ($count === false) {
25021 switch (preg_last_error()) {
25022 case PREG_NO_ERROR:
25023 throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR);
25024 case PREG_INTERNAL_ERROR:
25025 throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR);
25026 case PREG_BACKTRACK_LIMIT_ERROR:
25027 throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR);
25028 case PREG_RECURSION_LIMIT_ERROR:
25029 throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR);
25030 case PREG_BAD_UTF8_ERROR:
25031 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR);
25032 case PREG_BAD_UTF8_OFFSET_ERROR:
25033 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR);
25034 case 6: 
25035  if (PHP_VERSION_ID > 70000) {
25036 throw new \RuntimeException('Failed to execute regex: PREG_JIT_STACKLIMIT_ERROR', 6);
25037 }
25038
25039  default:
25040 throw new \RuntimeException('Failed to execute regex: Unknown error');
25041 }
25042 }
25043
25044 return $count;
25045 }
25046 }
25047 <?php
25048
25049
25050
25051
25052
25053
25054
25055
25056
25057
25058
25059 namespace Composer\Json;
25060
25061 use Exception;
25062
25063
25064
25065
25066 class JsonValidationException extends Exception
25067 {
25068 protected $errors;
25069
25070 public function __construct($message, $errors = array(), Exception $previous = null)
25071 {
25072 $this->errors = $errors;
25073 parent::__construct($message, 0, $previous);
25074 }
25075
25076 public function getErrors()
25077 {
25078 return $this->errors;
25079 }
25080 }
25081 <?php
25082
25083
25084
25085
25086
25087
25088
25089
25090
25091
25092
25093 namespace Composer\Package;
25094
25095 use Composer\Semver\Constraint\Constraint;
25096 use Composer\Package\Version\VersionParser;
25097
25098
25099
25100
25101 class AliasPackage extends BasePackage implements CompletePackageInterface
25102 {
25103 protected $version;
25104 protected $prettyVersion;
25105 protected $dev;
25106 protected $rootPackageAlias = false;
25107 protected $stability;
25108
25109
25110 protected $aliasOf;
25111
25112 protected $requires;
25113
25114 protected $devRequires;
25115
25116 protected $conflicts;
25117
25118 protected $provides;
25119
25120 protected $replaces;
25121
25122
25123
25124
25125
25126
25127
25128
25129 public function __construct(PackageInterface $aliasOf, $version, $prettyVersion)
25130 {
25131 parent::__construct($aliasOf->getName());
25132
25133 $this->version = $version;
25134 $this->prettyVersion = $prettyVersion;
25135 $this->aliasOf = $aliasOf;
25136 $this->stability = VersionParser::parseStability($version);
25137 $this->dev = $this->stability === 'dev';
25138
25139 foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) {
25140 $links = $aliasOf->{'get' . ucfirst($type)}();
25141 $this->$type = $this->replaceSelfVersionDependencies($links, $type);
25142 }
25143 }
25144
25145
25146
25147
25148 public function getAliasOf()
25149 {
25150 return $this->aliasOf;
25151 }
25152
25153
25154
25155
25156 public function getVersion()
25157 {
25158 return $this->version;
25159 }
25160
25161
25162
25163
25164 public function getStability()
25165 {
25166 return $this->stability;
25167 }
25168
25169
25170
25171
25172 public function getPrettyVersion()
25173 {
25174 return $this->prettyVersion;
25175 }
25176
25177
25178
25179
25180 public function isDev()
25181 {
25182 return $this->dev;
25183 }
25184
25185
25186
25187
25188 public function getRequires()
25189 {
25190 return $this->requires;
25191 }
25192
25193
25194
25195
25196 public function getConflicts()
25197 {
25198 return $this->conflicts;
25199 }
25200
25201
25202
25203
25204 public function getProvides()
25205 {
25206 return $this->provides;
25207 }
25208
25209
25210
25211
25212 public function getReplaces()
25213 {
25214 return $this->replaces;
25215 }
25216
25217
25218
25219
25220 public function getDevRequires()
25221 {
25222 return $this->devRequires;
25223 }
25224
25225
25226
25227
25228
25229
25230
25231
25232
25233
25234 public function setRootPackageAlias($value)
25235 {
25236 return $this->rootPackageAlias = $value;
25237 }
25238
25239
25240
25241
25242
25243 public function isRootPackageAlias()
25244 {
25245 return $this->rootPackageAlias;
25246 }
25247
25248
25249
25250
25251
25252
25253
25254 protected function replaceSelfVersionDependencies(array $links, $linkType)
25255 {
25256 if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
25257 $newLinks = array();
25258 foreach ($links as $link) {
25259
25260  if ('self.version' === $link->getPrettyConstraint()) {
25261 $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
25262 }
25263 }
25264 $links = array_merge($links, $newLinks);
25265 } else {
25266 foreach ($links as $index => $link) {
25267 if ('self.version' === $link->getPrettyConstraint()) {
25268 $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
25269 }
25270 }
25271 }
25272
25273 return $links;
25274 }
25275
25276
25277
25278
25279
25280 public function getType()
25281 {
25282 return $this->aliasOf->getType();
25283 }
25284
25285 public function getTargetDir()
25286 {
25287 return $this->aliasOf->getTargetDir();
25288 }
25289
25290 public function getExtra()
25291 {
25292 return $this->aliasOf->getExtra();
25293 }
25294
25295 public function setInstallationSource($type)
25296 {
25297 $this->aliasOf->setInstallationSource($type);
25298 }
25299
25300 public function getInstallationSource()
25301 {
25302 return $this->aliasOf->getInstallationSource();
25303 }
25304
25305 public function getSourceType()
25306 {
25307 return $this->aliasOf->getSourceType();
25308 }
25309
25310 public function getSourceUrl()
25311 {
25312 return $this->aliasOf->getSourceUrl();
25313 }
25314
25315 public function getSourceUrls()
25316 {
25317 return $this->aliasOf->getSourceUrls();
25318 }
25319
25320 public function getSourceReference()
25321 {
25322 return $this->aliasOf->getSourceReference();
25323 }
25324
25325 public function setSourceReference($reference)
25326 {
25327 return $this->aliasOf->setSourceReference($reference);
25328 }
25329
25330 public function setSourceMirrors($mirrors)
25331 {
25332 return $this->aliasOf->setSourceMirrors($mirrors);
25333 }
25334
25335 public function getSourceMirrors()
25336 {
25337 return $this->aliasOf->getSourceMirrors();
25338 }
25339
25340 public function getDistType()
25341 {
25342 return $this->aliasOf->getDistType();
25343 }
25344
25345 public function getDistUrl()
25346 {
25347 return $this->aliasOf->getDistUrl();
25348 }
25349
25350 public function getDistUrls()
25351 {
25352 return $this->aliasOf->getDistUrls();
25353 }
25354
25355 public function getDistReference()
25356 {
25357 return $this->aliasOf->getDistReference();
25358 }
25359
25360 public function setDistReference($reference)
25361 {
25362 return $this->aliasOf->setDistReference($reference);
25363 }
25364
25365 public function getDistSha1Checksum()
25366 {
25367 return $this->aliasOf->getDistSha1Checksum();
25368 }
25369
25370 public function setTransportOptions(array $options)
25371 {
25372 return $this->aliasOf->setTransportOptions($options);
25373 }
25374
25375 public function getTransportOptions()
25376 {
25377 return $this->aliasOf->getTransportOptions();
25378 }
25379
25380 public function setDistMirrors($mirrors)
25381 {
25382 return $this->aliasOf->setDistMirrors($mirrors);
25383 }
25384
25385 public function getDistMirrors()
25386 {
25387 return $this->aliasOf->getDistMirrors();
25388 }
25389
25390 public function getScripts()
25391 {
25392 return $this->aliasOf->getScripts();
25393 }
25394
25395 public function getLicense()
25396 {
25397 return $this->aliasOf->getLicense();
25398 }
25399
25400 public function getAutoload()
25401 {
25402 return $this->aliasOf->getAutoload();
25403 }
25404
25405 public function getDevAutoload()
25406 {
25407 return $this->aliasOf->getDevAutoload();
25408 }
25409
25410 public function getIncludePaths()
25411 {
25412 return $this->aliasOf->getIncludePaths();
25413 }
25414
25415 public function getRepositories()
25416 {
25417 return $this->aliasOf->getRepositories();
25418 }
25419
25420 public function getReleaseDate()
25421 {
25422 return $this->aliasOf->getReleaseDate();
25423 }
25424
25425 public function getBinaries()
25426 {
25427 return $this->aliasOf->getBinaries();
25428 }
25429
25430 public function getKeywords()
25431 {
25432 return $this->aliasOf->getKeywords();
25433 }
25434
25435 public function getDescription()
25436 {
25437 return $this->aliasOf->getDescription();
25438 }
25439
25440 public function getHomepage()
25441 {
25442 return $this->aliasOf->getHomepage();
25443 }
25444
25445 public function getSuggests()
25446 {
25447 return $this->aliasOf->getSuggests();
25448 }
25449
25450 public function getAuthors()
25451 {
25452 return $this->aliasOf->getAuthors();
25453 }
25454
25455 public function getSupport()
25456 {
25457 return $this->aliasOf->getSupport();
25458 }
25459
25460 public function getNotificationUrl()
25461 {
25462 return $this->aliasOf->getNotificationUrl();
25463 }
25464
25465 public function getArchiveExcludes()
25466 {
25467 return $this->aliasOf->getArchiveExcludes();
25468 }
25469
25470 public function isAbandoned()
25471 {
25472 return $this->aliasOf->isAbandoned();
25473 }
25474
25475 public function getReplacementPackage()
25476 {
25477 return $this->aliasOf->getReplacementPackage();
25478 }
25479
25480 public function __toString()
25481 {
25482 return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
25483 }
25484 }
25485 <?php
25486
25487
25488
25489
25490
25491
25492
25493
25494
25495
25496
25497 namespace Composer\Package\Archiver;
25498
25499 use FilterIterator;
25500 use PharData;
25501
25502 class ArchivableFilesFilter extends FilterIterator
25503 {
25504 private $dirs = array();
25505
25506
25507
25508
25509 public function accept()
25510 {
25511 $file = $this->getInnerIterator()->current();
25512 if ($file->isDir()) {
25513 $this->dirs[] = (string) $file;
25514
25515 return false;
25516 }
25517
25518 return true;
25519 }
25520
25521 public function addEmptyDir(PharData $phar, $sources)
25522 {
25523 foreach ($this->dirs as $filepath) {
25524 $localname = str_replace($sources . "/", '', $filepath);
25525 $phar->addEmptyDir($localname);
25526 }
25527 }
25528 }
25529 <?php
25530
25531
25532
25533
25534
25535
25536
25537
25538
25539
25540
25541 namespace Composer\Package\Archiver;
25542
25543 use Composer\Util\Filesystem;
25544 use FilesystemIterator;
25545 use Symfony\Component\Finder\Finder;
25546 use Symfony\Component\Finder\SplFileInfo;
25547
25548
25549
25550
25551
25552
25553
25554
25555
25556 class ArchivableFilesFinder extends \FilterIterator
25557 {
25558
25559
25560
25561 protected $finder;
25562
25563
25564
25565
25566
25567
25568
25569
25570 public function __construct($sources, array $excludes, $ignoreFilters = false)
25571 {
25572 $fs = new Filesystem();
25573
25574 $sources = $fs->normalizePath($sources);
25575
25576 if ($ignoreFilters) {
25577 $filters = array();
25578 } else {
25579 $filters = array(
25580 new HgExcludeFilter($sources),
25581 new GitExcludeFilter($sources),
25582 new ComposerExcludeFilter($sources, $excludes),
25583 );
25584 }
25585
25586 $this->finder = new Finder();
25587
25588 $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
25589 if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) {
25590 return false;
25591 }
25592
25593 $relativePath = preg_replace(
25594 '#^'.preg_quote($sources, '#').'#',
25595 '',
25596 $fs->normalizePath($file->getRealPath())
25597 );
25598
25599 $exclude = false;
25600 foreach ($filters as $filter) {
25601 $exclude = $filter->filter($relativePath, $exclude);
25602 }
25603
25604 return !$exclude;
25605 };
25606
25607 if (method_exists($filter, 'bindTo')) {
25608 $filter = $filter->bindTo(null);
25609 }
25610
25611 $this->finder
25612 ->in($sources)
25613 ->filter($filter)
25614 ->ignoreVCS(true)
25615 ->ignoreDotFiles(false);
25616
25617 parent::__construct($this->finder->getIterator());
25618 }
25619
25620 public function accept()
25621 {
25622
25623 $current = $this->getInnerIterator()->current();
25624
25625 if (!$current->isDir()) {
25626 return true;
25627 }
25628
25629 $iterator = new FilesystemIterator($current, FilesystemIterator::SKIP_DOTS);
25630
25631 return !$iterator->valid();
25632 }
25633 }
25634 <?php
25635
25636
25637
25638
25639
25640
25641
25642
25643
25644
25645
25646 namespace Composer\Package\Archiver;
25647
25648 use Composer\Downloader\DownloadManager;
25649 use Composer\Package\PackageInterface;
25650 use Composer\Package\RootPackageInterface;
25651 use Composer\Util\Filesystem;
25652 use Composer\Json\JsonFile;
25653
25654
25655
25656
25657
25658 class ArchiveManager
25659 {
25660 protected $downloadManager;
25661
25662 protected $archivers = array();
25663
25664
25665
25666
25667 protected $overwriteFiles = true;
25668
25669
25670
25671
25672 public function __construct(DownloadManager $downloadManager)
25673 {
25674 $this->downloadManager = $downloadManager;
25675 }
25676
25677
25678
25679
25680 public function addArchiver(ArchiverInterface $archiver)
25681 {
25682 $this->archivers[] = $archiver;
25683 }
25684
25685
25686
25687
25688
25689
25690
25691
25692 public function setOverwriteFiles($overwriteFiles)
25693 {
25694 $this->overwriteFiles = $overwriteFiles;
25695
25696 return $this;
25697 }
25698
25699
25700
25701
25702
25703
25704
25705
25706 public function getPackageFilename(PackageInterface $package)
25707 {
25708 $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
25709
25710 if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
25711 array_push($nameParts, $package->getDistReference(), $package->getDistType());
25712 } else {
25713 array_push($nameParts, $package->getPrettyVersion(), $package->getDistReference());
25714 }
25715
25716 if ($package->getSourceReference()) {
25717 $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
25718 }
25719
25720 $name = implode('-', array_filter($nameParts, function ($p) {
25721 return !empty($p);
25722 }));
25723
25724 return str_replace('/', '-', $name);
25725 }
25726
25727
25728
25729
25730
25731
25732
25733
25734
25735
25736
25737
25738
25739
25740 public function archive(PackageInterface $package, $format, $targetDir, $fileName = null, $ignoreFilters = false)
25741 {
25742 if (empty($format)) {
25743 throw new \InvalidArgumentException('Format must be specified');
25744 }
25745
25746
25747  $usableArchiver = null;
25748 foreach ($this->archivers as $archiver) {
25749 if ($archiver->supports($format, $package->getSourceType())) {
25750 $usableArchiver = $archiver;
25751 break;
25752 }
25753 }
25754
25755
25756  if (null === $usableArchiver) {
25757 throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
25758 }
25759
25760 $filesystem = new Filesystem();
25761 if (null === $fileName) {
25762 $packageName = $this->getPackageFilename($package);
25763 } else {
25764 $packageName = $fileName;
25765 }
25766
25767
25768  $filesystem->ensureDirectoryExists($targetDir);
25769 $target = realpath($targetDir).'/'.$packageName.'.'.$format;
25770 $filesystem->ensureDirectoryExists(dirname($target));
25771
25772 if (!$this->overwriteFiles && file_exists($target)) {
25773 return $target;
25774 }
25775
25776 if ($package instanceof RootPackageInterface) {
25777 $sourcePath = realpath('.');
25778 } else {
25779
25780  $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
25781 $filesystem->ensureDirectoryExists($sourcePath);
25782
25783
25784  $this->downloadManager->download($package, $sourcePath);
25785
25786
25787  if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
25788 $jsonFile = new JsonFile($composerJsonPath);
25789 $jsonData = $jsonFile->read();
25790 if (!empty($jsonData['archive']['exclude'])) {
25791 $package->setArchiveExcludes($jsonData['archive']['exclude']);
25792 }
25793 }
25794 }
25795
25796
25797  $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
25798 $filesystem->ensureDirectoryExists(dirname($tempTarget));
25799
25800 $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes(), $ignoreFilters);
25801 $filesystem->rename($archivePath, $target);
25802
25803
25804  if (!$package instanceof RootPackageInterface) {
25805 $filesystem->removeDirectory($sourcePath);
25806 }
25807 $filesystem->remove($tempTarget);
25808
25809 return $target;
25810 }
25811 }
25812 <?php
25813
25814
25815
25816
25817
25818
25819
25820
25821
25822
25823
25824 namespace Composer\Package\Archiver;
25825
25826
25827
25828
25829
25830
25831 interface ArchiverInterface
25832 {
25833
25834
25835
25836
25837
25838
25839
25840
25841
25842
25843 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false);
25844
25845
25846
25847
25848
25849
25850
25851
25852
25853 public function supports($format, $sourceType);
25854 }
25855 <?php
25856
25857
25858
25859
25860
25861
25862
25863
25864
25865
25866
25867 namespace Composer\Package\Archiver;
25868
25869 use Symfony\Component\Finder;
25870
25871
25872
25873
25874 abstract class BaseExcludeFilter
25875 {
25876
25877
25878
25879 protected $sourcePath;
25880
25881
25882
25883
25884 protected $excludePatterns;
25885
25886
25887
25888
25889 public function __construct($sourcePath)
25890 {
25891 $this->sourcePath = $sourcePath;
25892 $this->excludePatterns = array();
25893 }
25894
25895
25896
25897
25898
25899
25900
25901
25902
25903
25904
25905 public function filter($relativePath, $exclude)
25906 {
25907 foreach ($this->excludePatterns as $patternData) {
25908 list($pattern, $negate, $stripLeadingSlash) = $patternData;
25909
25910 if ($stripLeadingSlash) {
25911 $path = substr($relativePath, 1);
25912 } else {
25913 $path = $relativePath;
25914 }
25915
25916 if (preg_match($pattern, $path)) {
25917 $exclude = !$negate;
25918 }
25919 }
25920
25921 return $exclude;
25922 }
25923
25924
25925
25926
25927
25928
25929
25930
25931
25932 protected function parseLines(array $lines, $lineParser)
25933 {
25934 return array_filter(
25935 array_map(
25936 function ($line) use ($lineParser) {
25937 $line = trim($line);
25938
25939 if (!$line || 0 === strpos($line, '#')) {
25940 return null;
25941 }
25942
25943 return call_user_func($lineParser, $line);
25944 },
25945 $lines
25946 ),
25947 function ($pattern) {
25948 return $pattern !== null;
25949 }
25950 );
25951 }
25952
25953
25954
25955
25956
25957
25958
25959
25960 protected function generatePatterns($rules)
25961 {
25962 $patterns = array();
25963 foreach ($rules as $rule) {
25964 $patterns[] = $this->generatePattern($rule);
25965 }
25966
25967 return $patterns;
25968 }
25969
25970
25971
25972
25973
25974
25975
25976
25977 protected function generatePattern($rule)
25978 {
25979 $negate = false;
25980 $pattern = '{';
25981
25982 if (strlen($rule) && $rule[0] === '!') {
25983 $negate = true;
25984 $rule = substr($rule, 1);
25985 }
25986
25987 if (strlen($rule) && $rule[0] === '/') {
25988 $pattern .= '^/';
25989 $rule = substr($rule, 1);
25990 } elseif (strlen($rule) - 1 === strpos($rule, '/')) {
25991 $pattern .= '/';
25992 $rule = substr($rule, 0, -1);
25993 } elseif (false === strpos($rule, '/')) {
25994 $pattern .= '/';
25995 }
25996
25997
25998  $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
25999
26000 return array($pattern . '}', $negate, false);
26001 }
26002 }
26003 <?php
26004
26005
26006
26007
26008
26009
26010
26011
26012
26013
26014
26015 namespace Composer\Package\Archiver;
26016
26017
26018
26019
26020
26021
26022 class ComposerExcludeFilter extends BaseExcludeFilter
26023 {
26024
26025
26026
26027
26028 public function __construct($sourcePath, array $excludeRules)
26029 {
26030 parent::__construct($sourcePath);
26031 $this->excludePatterns = $this->generatePatterns($excludeRules);
26032 }
26033 }
26034 <?php
26035
26036
26037
26038
26039
26040
26041
26042
26043
26044
26045
26046 namespace Composer\Package\Archiver;
26047
26048
26049
26050
26051
26052
26053
26054
26055 class GitExcludeFilter extends BaseExcludeFilter
26056 {
26057
26058
26059
26060
26061
26062 public function __construct($sourcePath)
26063 {
26064 parent::__construct($sourcePath);
26065
26066 if (file_exists($sourcePath.'/.gitignore')) {
26067 $this->excludePatterns = $this->parseLines(
26068 file($sourcePath.'/.gitignore'),
26069 array($this, 'parseGitIgnoreLine')
26070 );
26071 }
26072 if (file_exists($sourcePath.'/.gitattributes')) {
26073 $this->excludePatterns = array_merge(
26074 $this->excludePatterns,
26075 $this->parseLines(
26076 file($sourcePath.'/.gitattributes'),
26077 array($this, 'parseGitAttributesLine')
26078 )
26079 );
26080 }
26081 }
26082
26083
26084
26085
26086
26087
26088
26089
26090 public function parseGitIgnoreLine($line)
26091 {
26092 return $this->generatePattern($line);
26093 }
26094
26095
26096
26097
26098
26099
26100
26101
26102 public function parseGitAttributesLine($line)
26103 {
26104 $parts = preg_split('#\s+#', $line);
26105
26106 if (count($parts) == 2 && $parts[1] === 'export-ignore') {
26107 return $this->generatePattern($parts[0]);
26108 }
26109
26110 return null;
26111 }
26112 }
26113 <?php
26114
26115
26116
26117
26118
26119
26120
26121
26122
26123
26124
26125 namespace Composer\Package\Archiver;
26126
26127 use Symfony\Component\Finder;
26128
26129
26130
26131
26132
26133
26134 class HgExcludeFilter extends BaseExcludeFilter
26135 {
26136 const HG_IGNORE_REGEX = 1;
26137 const HG_IGNORE_GLOB = 2;
26138
26139
26140
26141
26142
26143 protected $patternMode;
26144
26145
26146
26147
26148
26149
26150 public function __construct($sourcePath)
26151 {
26152 parent::__construct($sourcePath);
26153
26154 $this->patternMode = self::HG_IGNORE_REGEX;
26155
26156 if (file_exists($sourcePath.'/.hgignore')) {
26157 $this->excludePatterns = $this->parseLines(
26158 file($sourcePath.'/.hgignore'),
26159 array($this, 'parseHgIgnoreLine')
26160 );
26161 }
26162 }
26163
26164
26165
26166
26167
26168
26169
26170
26171 public function parseHgIgnoreLine($line)
26172 {
26173 if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) {
26174 if ($matches[1] === 'glob') {
26175 $this->patternMode = self::HG_IGNORE_GLOB;
26176 } else {
26177 $this->patternMode = self::HG_IGNORE_REGEX;
26178 }
26179
26180 return null;
26181 }
26182
26183 if ($this->patternMode == self::HG_IGNORE_GLOB) {
26184 return $this->patternFromGlob($line);
26185 }
26186
26187 return $this->patternFromRegex($line);
26188 }
26189
26190
26191
26192
26193
26194
26195
26196
26197 protected function patternFromGlob($line)
26198 {
26199 $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#';
26200 $pattern = str_replace('[^/]*', '.*', $pattern);
26201
26202 return array($pattern, false, true);
26203 }
26204
26205
26206
26207
26208
26209
26210
26211
26212 public function patternFromRegex($line)
26213 {
26214
26215  $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#';
26216
26217 return array($pattern, false, true);
26218 }
26219 }
26220 <?php
26221
26222
26223
26224
26225
26226
26227
26228
26229
26230
26231
26232 namespace Composer\Package\Archiver;
26233
26234
26235
26236
26237
26238
26239 class PharArchiver implements ArchiverInterface
26240 {
26241 protected static $formats = array(
26242 'zip' => \Phar::ZIP,
26243 'tar' => \Phar::TAR,
26244 'tar.gz' => \Phar::TAR,
26245 'tar.bz2' => \Phar::TAR,
26246 );
26247
26248 protected static $compressFormats = array(
26249 'tar.gz' => \Phar::GZ,
26250 'tar.bz2' => \Phar::BZ2,
26251 );
26252
26253
26254
26255
26256 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
26257 {
26258 $sources = realpath($sources);
26259
26260
26261  if (file_exists($target)) {
26262 unlink($target);
26263 }
26264
26265 try {
26266 $filename = substr($target, 0, strrpos($target, $format) - 1);
26267
26268
26269  if (isset(static::$compressFormats[$format])) {
26270
26271  $target = $filename . '.tar';
26272 }
26273
26274 $phar = new \PharData($target, null, null, static::$formats[$format]);
26275 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
26276 $filesOnly = new ArchivableFilesFilter($files);
26277 $phar->buildFromIterator($filesOnly, $sources);
26278 $filesOnly->addEmptyDir($phar, $sources);
26279
26280 if (isset(static::$compressFormats[$format])) {
26281
26282  if (!$phar->canCompress(static::$compressFormats[$format])) {
26283 throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
26284 }
26285
26286
26287  unlink($target);
26288
26289
26290  $phar->compress(static::$compressFormats[$format]);
26291
26292
26293  $target = $filename . '.' . $format;
26294 }
26295
26296 return $target;
26297 } catch (\UnexpectedValueException $e) {
26298 $message = sprintf(
26299 "Could not create archive '%s' from '%s': %s",
26300 $target,
26301 $sources,
26302 $e->getMessage()
26303 );
26304
26305 throw new \RuntimeException($message, $e->getCode(), $e);
26306 }
26307 }
26308
26309
26310
26311
26312 public function supports($format, $sourceType)
26313 {
26314 return isset(static::$formats[$format]);
26315 }
26316 }
26317 <?php
26318
26319
26320
26321
26322
26323
26324
26325
26326
26327
26328
26329 namespace Composer\Package\Archiver;
26330
26331 use ZipArchive;
26332 use Composer\Util\Filesystem;
26333
26334
26335
26336
26337 class ZipArchiver implements ArchiverInterface
26338 {
26339 protected static $formats = array(
26340 'zip' => 1,
26341 );
26342
26343
26344
26345
26346 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
26347 {
26348 $fs = new Filesystem();
26349 $sources = $fs->normalizePath($sources);
26350
26351 $zip = new ZipArchive();
26352 $res = $zip->open($target, ZipArchive::CREATE);
26353 if ($res === true) {
26354 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
26355 foreach ($files as $file) {
26356
26357 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
26358 $localname = str_replace($sources.'/', '', $filepath);
26359 if ($file->isDir()) {
26360 $zip->addEmptyDir($localname);
26361 } else {
26362 $zip->addFile($filepath, $localname);
26363 }
26364 }
26365 if ($zip->close()) {
26366 return $target;
26367 }
26368 }
26369 $message = sprintf(
26370 "Could not create archive '%s' from '%s': %s",
26371 $target,
26372 $sources,
26373 $zip->getStatusString()
26374 );
26375 throw new \RuntimeException($message);
26376 }
26377
26378
26379
26380
26381 public function supports($format, $sourceType)
26382 {
26383 return isset(static::$formats[$format]) && $this->compressionAvailable();
26384 }
26385
26386 private function compressionAvailable()
26387 {
26388 return class_exists('ZipArchive');
26389 }
26390 }
26391 <?php
26392
26393
26394
26395
26396
26397
26398
26399
26400
26401
26402
26403 namespace Composer\Package;
26404
26405 use Composer\Repository\RepositoryInterface;
26406 use Composer\Repository\PlatformRepository;
26407
26408
26409
26410
26411
26412
26413 abstract class BasePackage implements PackageInterface
26414 {
26415 public static $supportedLinkTypes = array(
26416 'require' => array('description' => 'requires', 'method' => 'requires'),
26417 'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
26418 'provide' => array('description' => 'provides', 'method' => 'provides'),
26419 'replace' => array('description' => 'replaces', 'method' => 'replaces'),
26420 'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
26421 );
26422
26423 const STABILITY_STABLE = 0;
26424 const STABILITY_RC = 5;
26425 const STABILITY_BETA = 10;
26426 const STABILITY_ALPHA = 15;
26427 const STABILITY_DEV = 20;
26428
26429 public static $stabilities = array(
26430 'stable' => self::STABILITY_STABLE,
26431 'RC' => self::STABILITY_RC,
26432 'beta' => self::STABILITY_BETA,
26433 'alpha' => self::STABILITY_ALPHA,
26434 'dev' => self::STABILITY_DEV,
26435 );
26436
26437
26438
26439
26440
26441 public $id;
26442
26443 protected $name;
26444
26445 protected $prettyName;
26446
26447 protected $repository;
26448
26449 protected $transportOptions = array();
26450
26451
26452
26453
26454
26455
26456 public function __construct($name)
26457 {
26458 $this->prettyName = $name;
26459 $this->name = strtolower($name);
26460 $this->id = -1;
26461 }
26462
26463
26464
26465
26466 public function getName()
26467 {
26468 return $this->name;
26469 }
26470
26471
26472
26473
26474 public function getPrettyName()
26475 {
26476 return $this->prettyName;
26477 }
26478
26479
26480
26481
26482 public function getNames()
26483 {
26484 $names = array(
26485 $this->getName() => true,
26486 );
26487
26488 foreach ($this->getProvides() as $link) {
26489 $names[$link->getTarget()] = true;
26490 }
26491
26492 foreach ($this->getReplaces() as $link) {
26493 $names[$link->getTarget()] = true;
26494 }
26495
26496 return array_keys($names);
26497 }
26498
26499
26500
26501
26502 public function setId($id)
26503 {
26504 $this->id = $id;
26505 }
26506
26507
26508
26509
26510 public function getId()
26511 {
26512 return $this->id;
26513 }
26514
26515
26516
26517
26518 public function setRepository(RepositoryInterface $repository)
26519 {
26520 if ($this->repository && $repository !== $this->repository) {
26521 throw new \LogicException('A package can only be added to one repository');
26522 }
26523 $this->repository = $repository;
26524 }
26525
26526
26527
26528
26529 public function getRepository()
26530 {
26531 return $this->repository;
26532 }
26533
26534
26535
26536
26537 public function getTransportOptions()
26538 {
26539 return $this->transportOptions;
26540 }
26541
26542
26543
26544
26545
26546
26547 public function setTransportOptions(array $options)
26548 {
26549 $this->transportOptions = $options;
26550 }
26551
26552
26553
26554
26555
26556
26557 public function isPlatform()
26558 {
26559 return $this->getRepository() instanceof PlatformRepository;
26560 }
26561
26562
26563
26564
26565
26566
26567 public function getUniqueName()
26568 {
26569 return $this->getName().'-'.$this->getVersion();
26570 }
26571
26572 public function equals(PackageInterface $package)
26573 {
26574 $self = $this;
26575 if ($this instanceof AliasPackage) {
26576 $self = $this->getAliasOf();
26577 }
26578 if ($package instanceof AliasPackage) {
26579 $package = $package->getAliasOf();
26580 }
26581
26582 return $package === $self;
26583 }
26584
26585
26586
26587
26588
26589
26590 public function __toString()
26591 {
26592 return $this->getUniqueName();
26593 }
26594
26595 public function getPrettyString()
26596 {
26597 return $this->getPrettyName().' '.$this->getPrettyVersion();
26598 }
26599
26600
26601
26602
26603 public function getFullPrettyVersion($truncate = true)
26604 {
26605 if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
26606 return $this->getPrettyVersion();
26607 }
26608
26609
26610  if ($truncate && strlen($this->getSourceReference()) === 40) {
26611 return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
26612 }
26613
26614 return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
26615 }
26616
26617 public function getStabilityPriority()
26618 {
26619 return self::$stabilities[$this->getStability()];
26620 }
26621
26622 public function __clone()
26623 {
26624 $this->repository = null;
26625 $this->id = -1;
26626 }
26627 }
26628 <?php
26629
26630
26631
26632
26633
26634
26635
26636
26637
26638
26639
26640 namespace Composer\Package\Comparer;
26641
26642
26643
26644
26645
26646
26647 class Comparer
26648 {
26649 private $source;
26650 private $update;
26651 private $changed;
26652
26653 public function setSource($source)
26654 {
26655 $this->source = $source;
26656 }
26657
26658 public function setUpdate($update)
26659 {
26660 $this->update = $update;
26661 }
26662
26663 public function getChanged($toString = false, $explicated = false)
26664 {
26665 $changed = $this->changed;
26666 if (!count($changed)) {
26667 return false;
26668 }
26669 if ($explicated) {
26670 foreach ($changed as $sectionKey => $itemSection) {
26671 foreach ($itemSection as $itemKey => $item) {
26672 $changed[$sectionKey][$itemKey] = $item.' ('.$sectionKey.')';
26673 }
26674 }
26675 }
26676
26677 if ($toString) {
26678 foreach ($changed as $sectionKey => $itemSection) {
26679 foreach ($itemSection as $itemKey => $item) {
26680 $changed['string'][] = $item."\r\n";
26681 }
26682 }
26683 $changed = implode("\r\n", $changed['string']);
26684 }
26685
26686 return $changed;
26687 }
26688
26689 public function doCompare()
26690 {
26691 $source = array();
26692 $destination = array();
26693 $this->changed = array();
26694 $currentDirectory = getcwd();
26695 chdir($this->source);
26696 $source = $this->doTree('.', $source);
26697 if (!is_array($source)) {
26698 return;
26699 }
26700 chdir($this->update);
26701 $destination = $this->doTree('.', $destination);
26702 if (!is_array($destination)) {
26703 exit;
26704 }
26705 chdir($currentDirectory);
26706 foreach ($source as $dir => $value) {
26707 foreach ($value as $file => $hash) {
26708 if (isset($destination[$dir][$file])) {
26709 if ($hash !== $destination[$dir][$file]) {
26710 $this->changed['changed'][] = $dir.'/'.$file;
26711 }
26712 } else {
26713 $this->changed['removed'][] = $dir.'/'.$file;
26714 }
26715 }
26716 }
26717 foreach ($destination as $dir => $value) {
26718 foreach ($value as $file => $hash) {
26719 if (!isset($source[$dir][$file])) {
26720 $this->changed['added'][] = $dir.'/'.$file;
26721 }
26722 }
26723 }
26724 }
26725
26726 private function doTree($dir, &$array)
26727 {
26728 if ($dh = opendir($dir)) {
26729 while ($file = readdir($dh)) {
26730 if ($file !== '.' && $file !== '..') {
26731 if (is_dir($dir.'/'.$file)) {
26732 if (!count($array)) {
26733 $array[0] = 'Temp';
26734 }
26735 if (!$this->doTree($dir.'/'.$file, $array)) {
26736 return false;
26737 }
26738 } else {
26739 if (filesize($dir.'/'.$file)) {
26740 set_time_limit(30);
26741 $array[$dir][$file] = md5_file($dir.'/'.$file);
26742 }
26743 }
26744 }
26745 }
26746 if (count($array) > 1 && isset($array['0'])) {
26747 unset($array['0']);
26748 }
26749
26750 return $array;
26751 }
26752
26753 return false;
26754 }
26755 }
26756 <?php
26757
26758
26759
26760
26761
26762
26763
26764
26765
26766
26767
26768 namespace Composer\Package;
26769
26770
26771
26772
26773
26774
26775 class CompletePackage extends Package implements CompletePackageInterface
26776 {
26777 protected $repositories;
26778 protected $license = array();
26779 protected $keywords;
26780 protected $authors;
26781 protected $description;
26782 protected $homepage;
26783 protected $scripts = array();
26784 protected $support = array();
26785 protected $abandoned = false;
26786
26787
26788
26789
26790 public function setScripts(array $scripts)
26791 {
26792 $this->scripts = $scripts;
26793 }
26794
26795
26796
26797
26798 public function getScripts()
26799 {
26800 return $this->scripts;
26801 }
26802
26803
26804
26805
26806
26807
26808 public function setRepositories($repositories)
26809 {
26810 $this->repositories = $repositories;
26811 }
26812
26813
26814
26815
26816 public function getRepositories()
26817 {
26818 return $this->repositories;
26819 }
26820
26821
26822
26823
26824
26825
26826 public function setLicense(array $license)
26827 {
26828 $this->license = $license;
26829 }
26830
26831
26832
26833
26834 public function getLicense()
26835 {
26836 return $this->license;
26837 }
26838
26839
26840
26841
26842
26843
26844 public function setKeywords(array $keywords)
26845 {
26846 $this->keywords = $keywords;
26847 }
26848
26849
26850
26851
26852 public function getKeywords()
26853 {
26854 return $this->keywords;
26855 }
26856
26857
26858
26859
26860
26861
26862 public function setAuthors(array $authors)
26863 {
26864 $this->authors = $authors;
26865 }
26866
26867
26868
26869
26870 public function getAuthors()
26871 {
26872 return $this->authors;
26873 }
26874
26875
26876
26877
26878
26879
26880 public function setDescription($description)
26881 {
26882 $this->description = $description;
26883 }
26884
26885
26886
26887
26888 public function getDescription()
26889 {
26890 return $this->description;
26891 }
26892
26893
26894
26895
26896
26897
26898 public function setHomepage($homepage)
26899 {
26900 $this->homepage = $homepage;
26901 }
26902
26903
26904
26905
26906 public function getHomepage()
26907 {
26908 return $this->homepage;
26909 }
26910
26911
26912
26913
26914
26915
26916 public function setSupport(array $support)
26917 {
26918 $this->support = $support;
26919 }
26920
26921
26922
26923
26924 public function getSupport()
26925 {
26926 return $this->support;
26927 }
26928
26929
26930
26931
26932 public function isAbandoned()
26933 {
26934 return (bool) $this->abandoned;
26935 }
26936
26937
26938
26939
26940 public function setAbandoned($abandoned)
26941 {
26942 $this->abandoned = $abandoned;
26943 }
26944
26945
26946
26947
26948
26949
26950 public function getReplacementPackage()
26951 {
26952 return is_string($this->abandoned) ? $this->abandoned : null;
26953 }
26954 }
26955 <?php
26956
26957
26958
26959
26960
26961
26962
26963
26964
26965
26966
26967 namespace Composer\Package;
26968
26969
26970
26971
26972
26973
26974 interface CompletePackageInterface extends PackageInterface
26975 {
26976
26977
26978
26979
26980
26981 public function getScripts();
26982
26983
26984
26985
26986
26987
26988
26989
26990 public function getRepositories();
26991
26992
26993
26994
26995
26996
26997 public function getLicense();
26998
26999
27000
27001
27002
27003
27004 public function getKeywords();
27005
27006
27007
27008
27009
27010
27011 public function getDescription();
27012
27013
27014
27015
27016
27017
27018 public function getHomepage();
27019
27020
27021
27022
27023
27024
27025
27026
27027 public function getAuthors();
27028
27029
27030
27031
27032
27033
27034 public function getSupport();
27035
27036
27037
27038
27039
27040
27041 public function isAbandoned();
27042
27043
27044
27045
27046
27047
27048 public function getReplacementPackage();
27049 }
27050 <?php
27051
27052
27053
27054
27055
27056
27057
27058
27059
27060
27061
27062 namespace Composer\Package\Dumper;
27063
27064 use Composer\Package\BasePackage;
27065 use Composer\Package\PackageInterface;
27066 use Composer\Package\CompletePackageInterface;
27067 use Composer\Package\RootPackageInterface;
27068
27069
27070
27071
27072
27073 class ArrayDumper
27074 {
27075 public function dump(PackageInterface $package)
27076 {
27077 $keys = array(
27078 'binaries' => 'bin',
27079 'type',
27080 'extra',
27081 'installationSource' => 'installation-source',
27082 'autoload',
27083 'devAutoload' => 'autoload-dev',
27084 'notificationUrl' => 'notification-url',
27085 'includePaths' => 'include-path',
27086 );
27087
27088 $data = array();
27089 $data['name'] = $package->getPrettyName();
27090 $data['version'] = $package->getPrettyVersion();
27091 $data['version_normalized'] = $package->getVersion();
27092
27093 if ($package->getTargetDir()) {
27094 $data['target-dir'] = $package->getTargetDir();
27095 }
27096
27097 if ($package->getSourceType() && $package->getType() !== 'metapackage') {
27098 $data['source']['type'] = $package->getSourceType();
27099 $data['source']['url'] = $package->getSourceUrl();
27100 $data['source']['reference'] = $package->getSourceReference();
27101 if ($mirrors = $package->getSourceMirrors()) {
27102 $data['source']['mirrors'] = $mirrors;
27103 }
27104 }
27105
27106 if ($package->getDistType() && $package->getType() !== 'metapackage') {
27107 $data['dist']['type'] = $package->getDistType();
27108 $data['dist']['url'] = $package->getDistUrl();
27109 $data['dist']['reference'] = $package->getDistReference();
27110 $data['dist']['shasum'] = $package->getDistSha1Checksum();
27111 if ($mirrors = $package->getDistMirrors()) {
27112 $data['dist']['mirrors'] = $mirrors;
27113 }
27114 }
27115
27116 if ($package->getArchiveExcludes()) {
27117 $data['archive']['exclude'] = $package->getArchiveExcludes();
27118 }
27119
27120 foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
27121 if ($links = $package->{'get'.ucfirst($opts['method'])}()) {
27122 foreach ($links as $link) {
27123 $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
27124 }
27125 ksort($data[$type]);
27126 }
27127 }
27128
27129 if ($packages = $package->getSuggests()) {
27130 ksort($packages);
27131 $data['suggest'] = $packages;
27132 }
27133
27134 if ($package->getReleaseDate()) {
27135 $data['time'] = $package->getReleaseDate()->format(DATE_RFC3339);
27136 }
27137
27138 $data = $this->dumpValues($package, $keys, $data);
27139
27140 if ($package instanceof CompletePackageInterface) {
27141 $keys = array(
27142 'scripts',
27143 'license',
27144 'authors',
27145 'description',
27146 'homepage',
27147 'keywords',
27148 'repositories',
27149 'support',
27150 );
27151
27152 $data = $this->dumpValues($package, $keys, $data);
27153
27154 if (isset($data['keywords']) && is_array($data['keywords'])) {
27155 sort($data['keywords']);
27156 }
27157
27158 if ($package->isAbandoned()) {
27159 $data['abandoned'] = $package->getReplacementPackage() ?: true;
27160 }
27161 }
27162
27163 if ($package instanceof RootPackageInterface) {
27164 $minimumStability = $package->getMinimumStability();
27165 if ($minimumStability) {
27166 $data['minimum-stability'] = $minimumStability;
27167 }
27168 }
27169
27170 if (count($package->getTransportOptions()) > 0) {
27171 $data['transport-options'] = $package->getTransportOptions();
27172 }
27173
27174 return $data;
27175 }
27176
27177 private function dumpValues(PackageInterface $package, array $keys, array $data)
27178 {
27179 foreach ($keys as $method => $key) {
27180 if (is_numeric($method)) {
27181 $method = $key;
27182 }
27183
27184 $getter = 'get'.ucfirst($method);
27185 $value = $package->$getter();
27186
27187 if (null !== $value && !(is_array($value) && 0 === count($value))) {
27188 $data[$key] = $value;
27189 }
27190 }
27191
27192 return $data;
27193 }
27194 }
27195 <?php
27196
27197
27198
27199
27200
27201
27202
27203
27204
27205
27206
27207 namespace Composer\Package;
27208
27209 use Composer\Semver\Constraint\ConstraintInterface;
27210
27211
27212
27213
27214
27215
27216 class Link
27217 {
27218
27219
27220
27221 protected $source;
27222
27223
27224
27225
27226 protected $target;
27227
27228
27229
27230
27231 protected $constraint;
27232
27233
27234
27235
27236 protected $description;
27237
27238
27239
27240
27241 protected $prettyConstraint;
27242
27243
27244
27245
27246
27247
27248
27249
27250
27251
27252 public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
27253 {
27254 $this->source = strtolower($source);
27255 $this->target = strtolower($target);
27256 $this->constraint = $constraint;
27257 $this->description = $description;
27258 $this->prettyConstraint = $prettyConstraint;
27259 }
27260
27261
27262
27263
27264 public function getDescription()
27265 {
27266 return $this->description;
27267 }
27268
27269
27270
27271
27272 public function getSource()
27273 {
27274 return $this->source;
27275 }
27276
27277
27278
27279
27280 public function getTarget()
27281 {
27282 return $this->target;
27283 }
27284
27285
27286
27287
27288 public function getConstraint()
27289 {
27290 return $this->constraint;
27291 }
27292
27293
27294
27295
27296
27297 public function getPrettyConstraint()
27298 {
27299 if (null === $this->prettyConstraint) {
27300 throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
27301 }
27302
27303 return $this->prettyConstraint;
27304 }
27305
27306
27307
27308
27309 public function __toString()
27310 {
27311 return $this->source.' '.$this->description.' '.$this->target.' ('.$this->constraint.')';
27312 }
27313
27314
27315
27316
27317
27318 public function getPrettyString(PackageInterface $sourcePackage)
27319 {
27320 return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
27321 }
27322 }
27323 <?php
27324
27325
27326
27327
27328
27329
27330
27331
27332
27333
27334
27335 namespace Composer\Package\LinkConstraint;
27336
27337 use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint;
27338
27339 trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
27340
27341
27342
27343
27344 class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
27345 {
27346 }
27347 <?php
27348
27349
27350
27351
27352
27353
27354
27355
27356
27357
27358
27359 namespace Composer\Package\LinkConstraint;
27360
27361 use Composer\Semver\Constraint\ConstraintInterface;
27362
27363 trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
27364
27365
27366
27367
27368 interface LinkConstraintInterface extends ConstraintInterface
27369 {
27370 }
27371 <?php
27372
27373
27374
27375
27376
27377
27378
27379
27380
27381
27382
27383 namespace Composer\Package\LinkConstraint;
27384
27385 use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint;
27386
27387 trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
27388
27389
27390
27391
27392 class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface
27393 {
27394 }
27395 <?php
27396
27397
27398
27399
27400
27401
27402
27403
27404
27405
27406
27407 namespace Composer\Package\LinkConstraint;
27408
27409 use Composer\Semver\Constraint\AbstractConstraint;
27410
27411 trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, there is no replacement for it.', E_USER_DEPRECATED);
27412
27413
27414
27415
27416 abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
27417 {
27418 }
27419 <?php
27420
27421
27422
27423
27424
27425
27426
27427
27428
27429
27430
27431 namespace Composer\Package\LinkConstraint;
27432
27433 use Composer\Semver\Constraint\Constraint;
27434
27435 trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
27436
27437
27438
27439
27440 class VersionConstraint extends Constraint implements LinkConstraintInterface
27441 {
27442 }
27443 <?php
27444
27445
27446
27447
27448
27449
27450
27451
27452
27453
27454
27455 namespace Composer\Package\Loader;
27456
27457 use Composer\Package;
27458 use Composer\Package\AliasPackage;
27459 use Composer\Package\Link;
27460 use Composer\Package\RootAliasPackage;
27461 use Composer\Package\RootPackageInterface;
27462 use Composer\Package\Version\VersionParser;
27463 use Composer\Semver\VersionParser as SemverVersionParser;
27464
27465
27466
27467
27468
27469 class ArrayLoader implements LoaderInterface
27470 {
27471 protected $versionParser;
27472 protected $loadOptions;
27473
27474 public function __construct(SemverVersionParser $parser = null, $loadOptions = false)
27475 {
27476 if (!$parser) {
27477 $parser = new VersionParser;
27478 }
27479 $this->versionParser = $parser;
27480 $this->loadOptions = $loadOptions;
27481 }
27482
27483 public function load(array $config, $class = 'Composer\Package\CompletePackage')
27484 {
27485 if (!isset($config['name'])) {
27486 throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
27487 }
27488 if (!isset($config['version'])) {
27489 throw new \UnexpectedValueException('Package '.$config['name'].' has no version defined.');
27490 }
27491
27492
27493  if (isset($config['version_normalized'])) {
27494 $version = $config['version_normalized'];
27495 } else {
27496 $version = $this->versionParser->normalize($config['version']);
27497 }
27498 $package = new $class($config['name'], $version, $config['version']);
27499 $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
27500
27501 if (isset($config['target-dir'])) {
27502 $package->setTargetDir($config['target-dir']);
27503 }
27504
27505 if (isset($config['extra']) && is_array($config['extra'])) {
27506 $package->setExtra($config['extra']);
27507 }
27508
27509 if (isset($config['bin'])) {
27510 foreach ((array) $config['bin'] as $key => $bin) {
27511 $config['bin'][$key] = ltrim($bin, '/');
27512 }
27513 $package->setBinaries((array) $config['bin']);
27514 }
27515
27516 if (isset($config['installation-source'])) {
27517 $package->setInstallationSource($config['installation-source']);
27518 }
27519
27520 if (isset($config['source'])) {
27521 if (!isset($config['source']['type']) || !isset($config['source']['url']) || !isset($config['source']['reference'])) {
27522 throw new \UnexpectedValueException(sprintf(
27523 "Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.",
27524 $config['name'],
27525 json_encode($config['source'])
27526 ));
27527 }
27528 $package->setSourceType($config['source']['type']);
27529 $package->setSourceUrl($config['source']['url']);
27530 $package->setSourceReference($config['source']['reference']);
27531 if (isset($config['source']['mirrors'])) {
27532 $package->setSourceMirrors($config['source']['mirrors']);
27533 }
27534 }
27535
27536 if (isset($config['dist'])) {
27537 if (!isset($config['dist']['type'])
27538 || !isset($config['dist']['url'])) {
27539 throw new \UnexpectedValueException(sprintf(
27540 "Package %s's dist key should be specified as ".
27541 "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.",
27542 $config['name'],
27543 json_encode($config['dist'])
27544 ));
27545 }
27546 $package->setDistType($config['dist']['type']);
27547 $package->setDistUrl($config['dist']['url']);
27548 $package->setDistReference(isset($config['dist']['reference']) ? $config['dist']['reference'] : null);
27549 $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
27550 if (isset($config['dist']['mirrors'])) {
27551 $package->setDistMirrors($config['dist']['mirrors']);
27552 }
27553 }
27554
27555 foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
27556 if (isset($config[$type])) {
27557 $method = 'set'.ucfirst($opts['method']);
27558 $package->{$method}(
27559 $this->parseLinks(
27560 $package->getName(),
27561 $package->getPrettyVersion(),
27562 $opts['description'],
27563 $config[$type]
27564 )
27565 );
27566 }
27567 }
27568
27569 if (isset($config['suggest']) && is_array($config['suggest'])) {
27570 foreach ($config['suggest'] as $target => $reason) {
27571 if ('self.version' === trim($reason)) {
27572 $config['suggest'][$target] = $package->getPrettyVersion();
27573 }
27574 }
27575 $package->setSuggests($config['suggest']);
27576 }
27577
27578 if (isset($config['autoload'])) {
27579 $package->setAutoload($config['autoload']);
27580 }
27581
27582 if (isset($config['autoload-dev'])) {
27583 $package->setDevAutoload($config['autoload-dev']);
27584 }
27585
27586 if (isset($config['include-path'])) {
27587 $package->setIncludePaths($config['include-path']);
27588 }
27589
27590 if (!empty($config['time'])) {
27591 $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
27592
27593 try {
27594 $date = new \DateTime($time, new \DateTimeZone('UTC'));
27595 $package->setReleaseDate($date);
27596 } catch (\Exception $e) {
27597 }
27598 }
27599
27600 if (!empty($config['notification-url'])) {
27601 $package->setNotificationUrl($config['notification-url']);
27602 }
27603
27604 if (!empty($config['archive']['exclude'])) {
27605 $package->setArchiveExcludes($config['archive']['exclude']);
27606 }
27607
27608 if ($package instanceof Package\CompletePackageInterface) {
27609 if (isset($config['scripts']) && is_array($config['scripts'])) {
27610 foreach ($config['scripts'] as $event => $listeners) {
27611 $config['scripts'][$event] = (array) $listeners;
27612 }
27613 if (isset($config['scripts']['composer'])) {
27614 trigger_error('The `composer` script name is reserved for internal use, please avoid defining it', E_USER_DEPRECATED);
27615 }
27616 $package->setScripts($config['scripts']);
27617 }
27618
27619 if (!empty($config['description']) && is_string($config['description'])) {
27620 $package->setDescription($config['description']);
27621 }
27622
27623 if (!empty($config['homepage']) && is_string($config['homepage'])) {
27624 $package->setHomepage($config['homepage']);
27625 }
27626
27627 if (!empty($config['keywords']) && is_array($config['keywords'])) {
27628 $package->setKeywords($config['keywords']);
27629 }
27630
27631 if (!empty($config['license'])) {
27632 $package->setLicense(is_array($config['license']) ? $config['license'] : array($config['license']));
27633 }
27634
27635 if (!empty($config['authors']) && is_array($config['authors'])) {
27636 $package->setAuthors($config['authors']);
27637 }
27638
27639 if (isset($config['support'])) {
27640 $package->setSupport($config['support']);
27641 }
27642
27643 if (isset($config['abandoned'])) {
27644 $package->setAbandoned($config['abandoned']);
27645 }
27646 }
27647
27648 if ($aliasNormalized = $this->getBranchAlias($config)) {
27649 if ($package instanceof RootPackageInterface) {
27650 $package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
27651 } else {
27652 $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
27653 }
27654 }
27655
27656 if ($this->loadOptions && isset($config['transport-options'])) {
27657 $package->setTransportOptions($config['transport-options']);
27658 }
27659
27660 return $package;
27661 }
27662
27663
27664
27665
27666
27667
27668
27669
27670 public function parseLinks($source, $sourceVersion, $description, $links)
27671 {
27672 $res = array();
27673 foreach ($links as $target => $constraint) {
27674 if (!is_string($constraint)) {
27675 throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($constraint) . ' (' . var_export($constraint, true) . ')');
27676 }
27677 if ('self.version' === $constraint) {
27678 $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
27679 } else {
27680 $parsedConstraint = $this->versionParser->parseConstraints($constraint);
27681 }
27682
27683 $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
27684 }
27685
27686 return $res;
27687 }
27688
27689
27690
27691
27692
27693
27694
27695 public function getBranchAlias(array $config)
27696 {
27697 if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
27698 || !isset($config['extra']['branch-alias'])
27699 || !is_array($config['extra']['branch-alias'])
27700 ) {
27701 return;
27702 }
27703
27704 foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
27705
27706  if ('-dev' !== substr($targetBranch, -4)) {
27707 continue;
27708 }
27709
27710
27711  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
27712 if ('-dev' !== substr($validatedTargetBranch, -4)) {
27713 continue;
27714 }
27715
27716
27717  if (strtolower($config['version']) !== strtolower($sourceBranch)) {
27718 continue;
27719 }
27720
27721
27722  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
27723 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
27724 && (stripos($targetPrefix, $sourcePrefix) !== 0)
27725 ) {
27726 continue;
27727 }
27728
27729 return $validatedTargetBranch;
27730 }
27731 }
27732 }
27733 <?php
27734
27735
27736
27737
27738
27739
27740
27741
27742
27743
27744
27745 namespace Composer\Package\Loader;
27746
27747
27748
27749
27750 class InvalidPackageException extends \Exception
27751 {
27752 private $errors;
27753 private $warnings;
27754 private $data;
27755
27756 public function __construct(array $errors, array $warnings, array $data)
27757 {
27758 $this->errors = $errors;
27759 $this->warnings = $warnings;
27760 $this->data = $data;
27761 parent::__construct("Invalid package information: \n".implode("\n", array_merge($errors, $warnings)));
27762 }
27763
27764 public function getData()
27765 {
27766 return $this->data;
27767 }
27768
27769 public function getErrors()
27770 {
27771 return $this->errors;
27772 }
27773
27774 public function getWarnings()
27775 {
27776 return $this->warnings;
27777 }
27778 }
27779 <?php
27780
27781
27782
27783
27784
27785
27786
27787
27788
27789
27790
27791 namespace Composer\Package\Loader;
27792
27793 use Composer\Json\JsonFile;
27794
27795
27796
27797
27798 class JsonLoader
27799 {
27800 private $loader;
27801
27802 public function __construct(LoaderInterface $loader)
27803 {
27804 $this->loader = $loader;
27805 }
27806
27807
27808
27809
27810
27811 public function load($json)
27812 {
27813 if ($json instanceof JsonFile) {
27814 $config = $json->read();
27815 } elseif (file_exists($json)) {
27816 $config = JsonFile::parseJson(file_get_contents($json), $json);
27817 } elseif (is_string($json)) {
27818 $config = JsonFile::parseJson($json);
27819 }
27820
27821 return $this->loader->load($config);
27822 }
27823 }
27824 <?php
27825
27826
27827
27828
27829
27830
27831
27832
27833
27834
27835
27836 namespace Composer\Package\Loader;
27837
27838
27839
27840
27841
27842
27843 interface LoaderInterface
27844 {
27845
27846
27847
27848
27849
27850
27851
27852 public function load(array $package, $class = 'Composer\Package\CompletePackage');
27853 }
27854 <?php
27855
27856
27857
27858
27859
27860
27861
27862
27863
27864
27865
27866 namespace Composer\Package\Loader;
27867
27868 use Composer\Package\BasePackage;
27869 use Composer\Package\AliasPackage;
27870 use Composer\Config;
27871 use Composer\Package\RootPackageInterface;
27872 use Composer\Repository\RepositoryFactory;
27873 use Composer\Package\Version\VersionGuesser;
27874 use Composer\Package\Version\VersionParser;
27875 use Composer\Repository\RepositoryManager;
27876 use Composer\Util\ProcessExecutor;
27877
27878
27879
27880
27881
27882
27883
27884
27885 class RootPackageLoader extends ArrayLoader
27886 {
27887
27888
27889
27890 private $manager;
27891
27892
27893
27894
27895 private $config;
27896
27897
27898
27899
27900 private $versionGuesser;
27901
27902 public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null)
27903 {
27904 parent::__construct($parser);
27905
27906 $this->manager = $manager;
27907 $this->config = $config;
27908 $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
27909 }
27910
27911
27912
27913
27914
27915
27916
27917 public function load(array $config, $class = 'Composer\Package\RootPackage', $cwd = null)
27918 {
27919 if (!isset($config['name'])) {
27920 $config['name'] = '__root__';
27921 }
27922 $autoVersioned = false;
27923 if (!isset($config['version'])) {
27924 $commit = null;
27925
27926
27927  if (getenv('COMPOSER_ROOT_VERSION')) {
27928 $config['version'] = getenv('COMPOSER_ROOT_VERSION');
27929 } else {
27930 $versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
27931 if ($versionData) {
27932 $config['version'] = $versionData['pretty_version'];
27933 $config['version_normalized'] = $versionData['version'];
27934 $commit = $versionData['commit'];
27935 }
27936 }
27937
27938 if (!isset($config['version'])) {
27939 $config['version'] = '1.0.0';
27940 $autoVersioned = true;
27941 }
27942
27943 if ($commit) {
27944 $config['source'] = array(
27945 'type' => '',
27946 'url' => '',
27947 'reference' => $commit,
27948 );
27949 $config['dist'] = array(
27950 'type' => '',
27951 'url' => '',
27952 'reference' => $commit,
27953 );
27954 }
27955 }
27956
27957 $realPackage = $package = parent::load($config, $class);
27958 if ($realPackage instanceof AliasPackage) {
27959 $realPackage = $package->getAliasOf();
27960 }
27961
27962 if ($autoVersioned) {
27963 $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
27964 }
27965
27966 if (isset($config['minimum-stability'])) {
27967 $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
27968 }
27969
27970 $aliases = array();
27971 $stabilityFlags = array();
27972 $references = array();
27973 foreach (array('require', 'require-dev') as $linkType) {
27974 if (isset($config[$linkType])) {
27975 $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
27976 $method = 'get'.ucfirst($linkInfo['method']);
27977 $links = array();
27978 foreach ($realPackage->$method() as $link) {
27979 $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
27980 }
27981 $aliases = $this->extractAliases($links, $aliases);
27982 $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
27983 $references = $this->extractReferences($links, $references);
27984 }
27985 }
27986
27987 if (isset($links[$config['name']])) {
27988 throw new \InvalidArgumentException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL .
27989 'Did you accidentally name your root package after an external package?', $config['name']));
27990 }
27991
27992 $realPackage->setAliases($aliases);
27993 $realPackage->setStabilityFlags($stabilityFlags);
27994 $realPackage->setReferences($references);
27995
27996 if (isset($config['prefer-stable'])) {
27997 $realPackage->setPreferStable((bool) $config['prefer-stable']);
27998 }
27999
28000 if (isset($config['config'])) {
28001 $realPackage->setConfig($config['config']);
28002 }
28003
28004 $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
28005 foreach ($repos as $repo) {
28006 $this->manager->addRepository($repo);
28007 }
28008 $realPackage->setRepositories($this->config->getRepositories());
28009
28010 return $package;
28011 }
28012
28013 private function extractAliases(array $requires, array $aliases)
28014 {
28015 foreach ($requires as $reqName => $reqVersion) {
28016 if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
28017 $aliases[] = array(
28018 'package' => strtolower($reqName),
28019 'version' => $this->versionParser->normalize($match[1], $reqVersion),
28020 'alias' => $match[2],
28021 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
28022 );
28023 }
28024 }
28025
28026 return $aliases;
28027 }
28028
28029 private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
28030 {
28031 $stabilities = BasePackage::$stabilities;
28032 $minimumStability = $stabilities[$minimumStability];
28033 foreach ($requires as $reqName => $reqVersion) {
28034 $constraints = array();
28035
28036
28037  $orSplit = preg_split('{\s*\|\|?\s*}', trim($reqVersion));
28038 foreach ($orSplit as $orConstraint) {
28039 $andSplit = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
28040 foreach ($andSplit as $andConstraint) {
28041 $constraints[] = $andConstraint;
28042 }
28043 }
28044
28045
28046  $match = false;
28047 foreach ($constraints as $constraint) {
28048 if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
28049 $name = strtolower($reqName);
28050 $stability = $stabilities[VersionParser::normalizeStability($match[1])];
28051
28052 if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
28053 continue;
28054 }
28055 $stabilityFlags[$name] = $stability;
28056 $match = true;
28057 }
28058 }
28059
28060 if ($match) {
28061 continue;
28062 }
28063
28064 foreach ($constraints as $constraint) {
28065
28066  
28067  $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
28068 if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
28069 $name = strtolower($reqName);
28070 $stability = $stabilities[$stabilityName];
28071 if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
28072 continue;
28073 }
28074 $stabilityFlags[$name] = $stability;
28075 }
28076 }
28077 }
28078
28079 return $stabilityFlags;
28080 }
28081
28082 private function extractReferences(array $requires, array $references)
28083 {
28084 foreach ($requires as $reqName => $reqVersion) {
28085 $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
28086 if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === VersionParser::parseStability($reqVersion)) {
28087 $name = strtolower($reqName);
28088 $references[$name] = $match[1];
28089 }
28090 }
28091
28092 return $references;
28093 }
28094 }
28095 <?php
28096
28097
28098
28099
28100
28101
28102
28103
28104
28105
28106
28107 namespace Composer\Package\Loader;
28108
28109 use Composer\Package\BasePackage;
28110 use Composer\Semver\Constraint\Constraint;
28111 use Composer\Package\Version\VersionParser;
28112 use Composer\Repository\PlatformRepository;
28113 use Composer\Spdx\SpdxLicenses;
28114
28115
28116
28117
28118 class ValidatingArrayLoader implements LoaderInterface
28119 {
28120 const CHECK_ALL = 3;
28121 const CHECK_UNBOUND_CONSTRAINTS = 1;
28122 const CHECK_STRICT_CONSTRAINTS = 2;
28123
28124 private $loader;
28125 private $versionParser;
28126 private $errors;
28127 private $warnings;
28128 private $config;
28129 private $strictName;
28130 private $flags;
28131
28132 public function __construct(LoaderInterface $loader, $strictName = true, VersionParser $parser = null, $flags = 0)
28133 {
28134 $this->loader = $loader;
28135 $this->versionParser = $parser ?: new VersionParser();
28136 $this->strictName = $strictName;
28137 $this->flags = $flags;
28138 }
28139
28140 public function load(array $config, $class = 'Composer\Package\CompletePackage')
28141 {
28142 $this->errors = array();
28143 $this->warnings = array();
28144 $this->config = $config;
28145
28146 if ($this->strictName) {
28147 $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
28148 } else {
28149 $this->validateString('name', true);
28150 }
28151
28152 if (!empty($this->config['version'])) {
28153 try {
28154 $this->versionParser->normalize($this->config['version']);
28155 } catch (\Exception $e) {
28156 $this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
28157 unset($this->config['version']);
28158 }
28159 }
28160
28161 if (!empty($this->config['config']['platform'])) {
28162 foreach ((array) $this->config['config']['platform'] as $key => $platform) {
28163 try {
28164 $this->versionParser->normalize($platform);
28165 } catch (\Exception $e) {
28166 $this->errors[] = 'config.platform.' . $key . ' : invalid value ('.$platform.'): '.$e->getMessage();
28167 }
28168 }
28169 }
28170
28171 $this->validateRegex('type', '[A-Za-z0-9-]+');
28172 $this->validateString('target-dir');
28173 $this->validateArray('extra');
28174
28175 if (isset($this->config['bin'])) {
28176 if (is_string($this->config['bin'])) {
28177 $this->validateString('bin');
28178 } else {
28179 $this->validateFlatArray('bin');
28180 }
28181 }
28182
28183 $this->validateArray('scripts'); 
28184  $this->validateString('description');
28185 $this->validateUrl('homepage');
28186 $this->validateFlatArray('keywords', '[\p{N}\p{L} ._-]+');
28187
28188 $releaseDate = null;
28189 $this->validateString('time');
28190 if (!empty($this->config['time'])) {
28191 try {
28192 $releaseDate = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
28193 } catch (\Exception $e) {
28194 $this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
28195 unset($this->config['time']);
28196 }
28197 }
28198
28199
28200  if (isset($this->config['license']) && (!$releaseDate || $releaseDate->getTimestamp() >= strtotime('-8days'))) {
28201 if (is_array($this->config['license']) || is_string($this->config['license'])) {
28202 $licenses = (array) $this->config['license'];
28203
28204
28205  foreach ($licenses as $key => $license) {
28206 if ('proprietary' === $license) {
28207 unset($licenses[$key]);
28208 }
28209 }
28210
28211 $licenseValidator = new SpdxLicenses();
28212 if (count($licenses) === 1 && !$licenseValidator->validate($licenses) && $licenseValidator->validate(trim($licenses[0]))) {
28213 $this->warnings[] = sprintf(
28214 'License %s must not contain extra spaces, make sure to trim it.',
28215 json_encode($this->config['license'])
28216 );
28217 } elseif (array() !== $licenses && !$licenseValidator->validate($licenses)) {
28218 $this->warnings[] = sprintf(
28219 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.' . PHP_EOL .
28220 'If the software is closed-source, you may use "proprietary" as license.',
28221 json_encode($this->config['license'])
28222 );
28223 }
28224 }
28225 }
28226
28227 if ($this->validateArray('authors') && !empty($this->config['authors'])) {
28228 foreach ($this->config['authors'] as $key => $author) {
28229 if (!is_array($author)) {
28230 $this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
28231 unset($this->config['authors'][$key]);
28232 continue;
28233 }
28234 foreach (array('homepage', 'email', 'name', 'role') as $authorData) {
28235 if (isset($author[$authorData]) && !is_string($author[$authorData])) {
28236 $this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
28237 unset($this->config['authors'][$key][$authorData]);
28238 }
28239 }
28240 if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
28241 $this->warnings[] = 'authors.'.$key.'.homepage : invalid value ('.$author['homepage'].'), must be an http/https URL';
28242 unset($this->config['authors'][$key]['homepage']);
28243 }
28244 if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
28245 $this->warnings[] = 'authors.'.$key.'.email : invalid value ('.$author['email'].'), must be a valid email address';
28246 unset($this->config['authors'][$key]['email']);
28247 }
28248 if (empty($this->config['authors'][$key])) {
28249 unset($this->config['authors'][$key]);
28250 }
28251 }
28252 if (empty($this->config['authors'])) {
28253 unset($this->config['authors']);
28254 }
28255 }
28256
28257 if ($this->validateArray('support') && !empty($this->config['support'])) {
28258 foreach (array('issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss') as $key) {
28259 if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
28260 $this->errors[] = 'support.'.$key.' : invalid value, must be a string';
28261 unset($this->config['support'][$key]);
28262 }
28263 }
28264
28265 if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], FILTER_VALIDATE_EMAIL)) {
28266 $this->warnings[] = 'support.email : invalid value ('.$this->config['support']['email'].'), must be a valid email address';
28267 unset($this->config['support']['email']);
28268 }
28269
28270 if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) {
28271 $this->warnings[] = 'support.irc : invalid value ('.$this->config['support']['irc'].'), must be a irc://<server>/<channel> URL';
28272 unset($this->config['support']['irc']);
28273 }
28274
28275 foreach (array('issues', 'forum', 'wiki', 'source', 'docs') as $key) {
28276 if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
28277 $this->warnings[] = 'support.'.$key.' : invalid value ('.$this->config['support'][$key].'), must be an http/https URL';
28278 unset($this->config['support'][$key]);
28279 }
28280 }
28281 if (empty($this->config['support'])) {
28282 unset($this->config['support']);
28283 }
28284 }
28285
28286 $unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master'));
28287 $stableConstraint = new Constraint('=', '1.0.0');
28288
28289 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
28290 if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
28291 foreach ($this->config[$linkType] as $package => $constraint) {
28292 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
28293 $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
28294 }
28295 if (!is_string($constraint)) {
28296 $this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
28297 unset($this->config[$linkType][$package]);
28298 } elseif ('self.version' !== $constraint) {
28299 try {
28300 $linkConstraint = $this->versionParser->parseConstraints($constraint);
28301 } catch (\Exception $e) {
28302 $this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
28303 unset($this->config[$linkType][$package]);
28304 continue;
28305 }
28306
28307
28308  if (
28309 ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS)
28310 && 'require' === $linkType
28311 && $linkConstraint->matches($unboundConstraint)
28312 && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $package)
28313 ) {
28314 $this->warnings[] = $linkType.'.'.$package.' : unbound version constraints ('.$constraint.') should be avoided';
28315 } elseif (
28316
28317  ($this->flags & self::CHECK_STRICT_CONSTRAINTS)
28318 && 'require' === $linkType
28319 && substr($linkConstraint, 0, 1) === '='
28320 && $stableConstraint->versionCompare($stableConstraint, $linkConstraint, '<=')
28321 ) {
28322 $this->warnings[] = $linkType.'.'.$package.' : exact version constraints ('.$constraint.') should be avoided if the package follows semantic versioning';
28323 }
28324 }
28325 }
28326 }
28327 }
28328
28329 if ($this->validateArray('suggest') && !empty($this->config['suggest'])) {
28330 foreach ($this->config['suggest'] as $package => $description) {
28331 if (!is_string($description)) {
28332 $this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
28333 unset($this->config['suggest'][$package]);
28334 }
28335 }
28336 }
28337
28338 if ($this->validateString('minimum-stability') && !empty($this->config['minimum-stability'])) {
28339 if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
28340 $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
28341 unset($this->config['minimum-stability']);
28342 }
28343 }
28344
28345 if ($this->validateArray('autoload') && !empty($this->config['autoload'])) {
28346 $types = array('psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap');
28347 foreach ($this->config['autoload'] as $type => $typeConfig) {
28348 if (!in_array($type, $types)) {
28349 $this->errors[] = 'autoload : invalid value ('.$type.'), must be one of '.implode(', ', $types);
28350 unset($this->config['autoload'][$type]);
28351 }
28352 if ($type === 'psr-4') {
28353 foreach ($typeConfig as $namespace => $dirs) {
28354 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
28355 $this->errors[] = 'autoload.psr-4 : invalid value ('.$namespace.'), namespaces must end with a namespace separator, should be '.$namespace.'\\\\';
28356 }
28357 }
28358 }
28359 }
28360 }
28361
28362 if (!empty($this->config['autoload']['psr-4']) && !empty($this->config['target-dir'])) {
28363 $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
28364
28365  
28366  unset($this->config['autoload']['psr-4']);
28367 }
28368
28369
28370  
28371
28372
28373  
28374
28375 $this->validateFlatArray('include-path');
28376 $this->validateArray('transport-options');
28377
28378
28379  if (isset($this->config['extra']['branch-alias'])) {
28380 if (!is_array($this->config['extra']['branch-alias'])) {
28381 $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
28382 } else {
28383 foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
28384
28385  if ('-dev' !== substr($targetBranch, -4)) {
28386 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must end in -dev';
28387 unset($this->config['extra']['branch-alias'][$sourceBranch]);
28388
28389 continue;
28390 }
28391
28392
28393  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
28394 if ('-dev' !== substr($validatedTargetBranch, -4)) {
28395 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
28396 unset($this->config['extra']['branch-alias'][$sourceBranch]);
28397
28398 continue;
28399 }
28400
28401
28402  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
28403 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
28404 && (stripos($targetPrefix, $sourcePrefix) !== 0)
28405 ) {
28406 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
28407 unset($this->config['extra']['branch-alias'][$sourceBranch]);
28408 }
28409 }
28410 }
28411 }
28412
28413 if ($this->errors) {
28414 throw new InvalidPackageException($this->errors, $this->warnings, $config);
28415 }
28416
28417 $package = $this->loader->load($this->config, $class);
28418 $this->config = null;
28419
28420 return $package;
28421 }
28422
28423 public function getWarnings()
28424 {
28425 return $this->warnings;
28426 }
28427
28428 public function getErrors()
28429 {
28430 return $this->errors;
28431 }
28432
28433 private function validateRegex($property, $regex, $mandatory = false)
28434 {
28435 if (!$this->validateString($property, $mandatory)) {
28436 return false;
28437 }
28438
28439 if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) {
28440 $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex;
28441 if ($mandatory) {
28442 $this->errors[] = $message;
28443 } else {
28444 $this->warnings[] = $message;
28445 }
28446 unset($this->config[$property]);
28447
28448 return false;
28449 }
28450
28451 return true;
28452 }
28453
28454 private function validateString($property, $mandatory = false)
28455 {
28456 if (isset($this->config[$property]) && !is_string($this->config[$property])) {
28457 $this->errors[] = $property.' : should be a string, '.gettype($this->config[$property]).' given';
28458 unset($this->config[$property]);
28459
28460 return false;
28461 }
28462
28463 if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
28464 if ($mandatory) {
28465 $this->errors[] = $property.' : must be present';
28466 }
28467 unset($this->config[$property]);
28468
28469 return false;
28470 }
28471
28472 return true;
28473 }
28474
28475 private function validateArray($property, $mandatory = false)
28476 {
28477 if (isset($this->config[$property]) && !is_array($this->config[$property])) {
28478 $this->errors[] = $property.' : should be an array, '.gettype($this->config[$property]).' given';
28479 unset($this->config[$property]);
28480
28481 return false;
28482 }
28483
28484 if (!isset($this->config[$property]) || !count($this->config[$property])) {
28485 if ($mandatory) {
28486 $this->errors[] = $property.' : must be present and contain at least one element';
28487 }
28488 unset($this->config[$property]);
28489
28490 return false;
28491 }
28492
28493 return true;
28494 }
28495
28496 private function validateFlatArray($property, $regex = null, $mandatory = false)
28497 {
28498 if (!$this->validateArray($property, $mandatory)) {
28499 return false;
28500 }
28501
28502 $pass = true;
28503 foreach ($this->config[$property] as $key => $value) {
28504 if (!is_string($value) && !is_numeric($value)) {
28505 $this->errors[] = $property.'.'.$key.' : must be a string or int, '.gettype($value).' given';
28506 unset($this->config[$property][$key]);
28507 $pass = false;
28508
28509 continue;
28510 }
28511
28512 if ($regex && !preg_match('{^'.$regex.'$}u', $value)) {
28513 $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex;
28514 unset($this->config[$property][$key]);
28515 $pass = false;
28516 }
28517 }
28518
28519 return $pass;
28520 }
28521
28522 private function validateUrl($property, $mandatory = false)
28523 {
28524 if (!$this->validateString($property, $mandatory)) {
28525 return false;
28526 }
28527
28528 if (!$this->filterUrl($this->config[$property])) {
28529 $this->warnings[] = $property.' : invalid value ('.$this->config[$property].'), must be an http/https URL';
28530 unset($this->config[$property]);
28531
28532 return false;
28533 }
28534
28535 return true;
28536 }
28537
28538 private function filterUrl($value, array $schemes = array('http', 'https'))
28539 {
28540 if ($value === '') {
28541 return true;
28542 }
28543
28544 $bits = parse_url($value);
28545 if (empty($bits['scheme']) || empty($bits['host'])) {
28546 return false;
28547 }
28548
28549 if (!in_array($bits['scheme'], $schemes, true)) {
28550 return false;
28551 }
28552
28553 return true;
28554 }
28555 }
28556 <?php
28557
28558
28559
28560
28561
28562
28563
28564
28565
28566
28567
28568 namespace Composer\Package;
28569
28570 use Composer\Json\JsonFile;
28571 use Composer\Installer\InstallationManager;
28572 use Composer\Repository\RepositoryManager;
28573 use Composer\Util\ProcessExecutor;
28574 use Composer\Repository\ArrayRepository;
28575 use Composer\Package\Dumper\ArrayDumper;
28576 use Composer\Package\Loader\ArrayLoader;
28577 use Composer\Util\Git as GitUtil;
28578 use Composer\IO\IOInterface;
28579 use Seld\JsonLint\ParsingException;
28580
28581
28582
28583
28584
28585
28586
28587 class Locker
28588 {
28589 private $lockFile;
28590 private $repositoryManager;
28591 private $installationManager;
28592 private $hash;
28593 private $contentHash;
28594 private $loader;
28595 private $dumper;
28596 private $process;
28597 private $lockDataCache;
28598
28599
28600
28601
28602
28603
28604
28605
28606
28607
28608 public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
28609 {
28610 $this->lockFile = $lockFile;
28611 $this->repositoryManager = $repositoryManager;
28612 $this->installationManager = $installationManager;
28613 $this->hash = md5($composerFileContents);
28614 $this->contentHash = self::getContentHash($composerFileContents);
28615 $this->loader = new ArrayLoader(null, true);
28616 $this->dumper = new ArrayDumper();
28617 $this->process = new ProcessExecutor($io);
28618 }
28619
28620
28621
28622
28623
28624
28625
28626
28627 public static function getContentHash($composerFileContents)
28628 {
28629 $content = json_decode($composerFileContents, true);
28630
28631 $relevantKeys = array(
28632 'name',
28633 'version',
28634 'require',
28635 'require-dev',
28636 'conflict',
28637 'replace',
28638 'provide',
28639 'minimum-stability',
28640 'prefer-stable',
28641 'repositories',
28642 'extra',
28643 );
28644
28645 $relevantContent = array();
28646
28647 foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
28648 $relevantContent[$key] = $content[$key];
28649 }
28650 if (isset($content['config']['platform'])) {
28651 $relevantContent['config']['platform'] = $content['config']['platform'];
28652 }
28653
28654 ksort($relevantContent);
28655
28656 return md5(json_encode($relevantContent));
28657 }
28658
28659
28660
28661
28662
28663
28664 public function isLocked()
28665 {
28666 if (!$this->lockFile->exists()) {
28667 return false;
28668 }
28669
28670 $data = $this->getLockData();
28671
28672 return isset($data['packages']);
28673 }
28674
28675
28676
28677
28678
28679
28680 public function isFresh()
28681 {
28682 $lock = $this->lockFile->read();
28683
28684 if (!empty($lock['content-hash'])) {
28685
28686  return $this->contentHash === $lock['content-hash'];
28687 }
28688
28689
28690  if (!empty($lock['hash'])) {
28691 return $this->hash === $lock['hash'];
28692 }
28693
28694
28695  return false;
28696 }
28697
28698
28699
28700
28701
28702
28703
28704
28705 public function getLockedRepository($withDevReqs = false)
28706 {
28707 $lockData = $this->getLockData();
28708 $packages = new ArrayRepository();
28709
28710 $lockedPackages = $lockData['packages'];
28711 if ($withDevReqs) {
28712 if (isset($lockData['packages-dev'])) {
28713 $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
28714 } else {
28715 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.');
28716 }
28717 }
28718
28719 if (empty($lockedPackages)) {
28720 return $packages;
28721 }
28722
28723 if (isset($lockedPackages[0]['name'])) {
28724 foreach ($lockedPackages as $info) {
28725 $packages->addPackage($this->loader->load($info));
28726 }
28727
28728 return $packages;
28729 }
28730
28731 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.');
28732 }
28733
28734
28735
28736
28737
28738
28739
28740 public function getPlatformRequirements($withDevReqs = false)
28741 {
28742 $lockData = $this->getLockData();
28743 $requirements = array();
28744
28745 if (!empty($lockData['platform'])) {
28746 $requirements = $this->loader->parseLinks(
28747 '__ROOT__',
28748 '1.0.0',
28749 'requires',
28750 isset($lockData['platform']) ? $lockData['platform'] : array()
28751 );
28752 }
28753
28754 if ($withDevReqs && !empty($lockData['platform-dev'])) {
28755 $devRequirements = $this->loader->parseLinks(
28756 '__ROOT__',
28757 '1.0.0',
28758 'requires',
28759 isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
28760 );
28761
28762 $requirements = array_merge($requirements, $devRequirements);
28763 }
28764
28765 return $requirements;
28766 }
28767
28768 public function getMinimumStability()
28769 {
28770 $lockData = $this->getLockData();
28771
28772 return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'stable';
28773 }
28774
28775 public function getStabilityFlags()
28776 {
28777 $lockData = $this->getLockData();
28778
28779 return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
28780 }
28781
28782 public function getPreferStable()
28783 {
28784 $lockData = $this->getLockData();
28785
28786
28787  
28788  return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null;
28789 }
28790
28791 public function getPreferLowest()
28792 {
28793 $lockData = $this->getLockData();
28794
28795
28796  
28797  return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
28798 }
28799
28800 public function getPlatformOverrides()
28801 {
28802 $lockData = $this->getLockData();
28803
28804 return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
28805 }
28806
28807 public function getAliases()
28808 {
28809 $lockData = $this->getLockData();
28810
28811 return isset($lockData['aliases']) ? $lockData['aliases'] : array();
28812 }
28813
28814 public function getLockData()
28815 {
28816 if (null !== $this->lockDataCache) {
28817 return $this->lockDataCache;
28818 }
28819
28820 if (!$this->lockFile->exists()) {
28821 throw new \LogicException('No lockfile found. Unable to read locked packages');
28822 }
28823
28824 return $this->lockDataCache = $this->lockFile->read();
28825 }
28826
28827
28828
28829
28830
28831
28832
28833
28834
28835
28836
28837
28838
28839
28840
28841
28842
28843 public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest, array $platformOverrides)
28844 {
28845 $lock = array(
28846 '_readme' => array('This file locks the dependencies of your project to a known state',
28847 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies',
28848 'This file is @gener'.'ated automatically', ),
28849 'content-hash' => $this->contentHash,
28850 'packages' => null,
28851 'packages-dev' => null,
28852 'aliases' => array(),
28853 'minimum-stability' => $minimumStability,
28854 'stability-flags' => $stabilityFlags,
28855 'prefer-stable' => $preferStable,
28856 'prefer-lowest' => $preferLowest,
28857 );
28858
28859 foreach ($aliases as $package => $versions) {
28860 foreach ($versions as $version => $alias) {
28861 $lock['aliases'][] = array(
28862 'alias' => $alias['alias'],
28863 'alias_normalized' => $alias['alias_normalized'],
28864 'version' => $version,
28865 'package' => $package,
28866 );
28867 }
28868 }
28869
28870 $lock['packages'] = $this->lockPackages($packages);
28871 if (null !== $devPackages) {
28872 $lock['packages-dev'] = $this->lockPackages($devPackages);
28873 }
28874
28875 $lock['platform'] = $platformReqs;
28876 $lock['platform-dev'] = $platformDevReqs;
28877 if ($platformOverrides) {
28878 $lock['platform-overrides'] = $platformOverrides;
28879 }
28880
28881 if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
28882 if ($this->lockFile->exists()) {
28883 unlink($this->lockFile->getPath());
28884 }
28885
28886 return false;
28887 }
28888
28889 try {
28890 $isLocked = $this->isLocked();
28891 } catch (ParsingException $e) {
28892 $isLocked = false;
28893 }
28894 if (!$isLocked || $lock !== $this->getLockData()) {
28895 $this->lockFile->write($lock);
28896 $this->lockDataCache = null;
28897
28898 return true;
28899 }
28900
28901 return false;
28902 }
28903
28904 private function lockPackages(array $packages)
28905 {
28906 $locked = array();
28907
28908 foreach ($packages as $package) {
28909 if ($package instanceof AliasPackage) {
28910 continue;
28911 }
28912
28913 $name = $package->getPrettyName();
28914 $version = $package->getPrettyVersion();
28915
28916 if (!$name || !$version) {
28917 throw new \LogicException(sprintf(
28918 'Package "%s" has no version or name and can not be locked',
28919 $package
28920 ));
28921 }
28922
28923 $spec = $this->dumper->dump($package);
28924 unset($spec['version_normalized']);
28925
28926
28927  $time = isset($spec['time']) ? $spec['time'] : null;
28928 unset($spec['time']);
28929 if ($package->isDev() && $package->getInstallationSource() === 'source') {
28930
28931  $time = $this->getPackageTime($package) ?: $time;
28932 }
28933 if (null !== $time) {
28934 $spec['time'] = $time;
28935 }
28936
28937 unset($spec['installation-source']);
28938
28939 $locked[] = $spec;
28940 }
28941
28942 usort($locked, function ($a, $b) {
28943 $comparison = strcmp($a['name'], $b['name']);
28944
28945 if (0 !== $comparison) {
28946 return $comparison;
28947 }
28948
28949
28950  return strcmp($a['version'], $b['version']);
28951 });
28952
28953 return $locked;
28954 }
28955
28956
28957
28958
28959
28960
28961
28962 private function getPackageTime(PackageInterface $package)
28963 {
28964 if (!function_exists('proc_open')) {
28965 return null;
28966 }
28967
28968 $path = realpath($this->installationManager->getInstallPath($package));
28969 $sourceType = $package->getSourceType();
28970 $datetime = null;
28971
28972 if ($path && in_array($sourceType, array('git', 'hg'))) {
28973 $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
28974 switch ($sourceType) {
28975 case 'git':
28976 GitUtil::cleanEnv();
28977
28978 if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
28979 $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
28980 }
28981 break;
28982
28983 case 'hg':
28984 if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
28985 $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
28986 }
28987 break;
28988 }
28989 }
28990
28991 return $datetime ? $datetime->format(DATE_RFC3339) : null;
28992 }
28993 }
28994 <?php
28995
28996
28997
28998
28999
29000
29001
29002
29003
29004
29005
29006 namespace Composer\Package;
29007
29008 use Composer\Package\Version\VersionParser;
29009 use Composer\Util\ComposerMirror;
29010
29011
29012
29013
29014
29015
29016 class Package extends BasePackage
29017 {
29018 protected $type;
29019 protected $targetDir;
29020 protected $installationSource;
29021 protected $sourceType;
29022 protected $sourceUrl;
29023 protected $sourceReference;
29024 protected $sourceMirrors;
29025 protected $distType;
29026 protected $distUrl;
29027 protected $distReference;
29028 protected $distSha1Checksum;
29029 protected $distMirrors;
29030 protected $version;
29031 protected $prettyVersion;
29032 protected $releaseDate;
29033 protected $extra = array();
29034 protected $binaries = array();
29035 protected $dev;
29036 protected $stability;
29037 protected $notificationUrl;
29038
29039
29040 protected $requires = array();
29041
29042 protected $conflicts = array();
29043
29044 protected $provides = array();
29045
29046 protected $replaces = array();
29047
29048 protected $devRequires = array();
29049 protected $suggests = array();
29050 protected $autoload = array();
29051 protected $devAutoload = array();
29052 protected $includePaths = array();
29053 protected $archiveExcludes = array();
29054
29055
29056
29057
29058
29059
29060
29061
29062 public function __construct($name, $version, $prettyVersion)
29063 {
29064 parent::__construct($name);
29065
29066 $this->version = $version;
29067 $this->prettyVersion = $prettyVersion;
29068
29069 $this->stability = VersionParser::parseStability($version);
29070 $this->dev = $this->stability === 'dev';
29071 }
29072
29073
29074
29075
29076 public function isDev()
29077 {
29078 return $this->dev;
29079 }
29080
29081
29082
29083
29084 public function setType($type)
29085 {
29086 $this->type = $type;
29087 }
29088
29089
29090
29091
29092 public function getType()
29093 {
29094 return $this->type ?: 'library';
29095 }
29096
29097
29098
29099
29100 public function getStability()
29101 {
29102 return $this->stability;
29103 }
29104
29105
29106
29107
29108 public function setTargetDir($targetDir)
29109 {
29110 $this->targetDir = $targetDir;
29111 }
29112
29113
29114
29115
29116 public function getTargetDir()
29117 {
29118 if (null === $this->targetDir) {
29119 return;
29120 }
29121
29122 return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
29123 }
29124
29125
29126
29127
29128 public function setExtra(array $extra)
29129 {
29130 $this->extra = $extra;
29131 }
29132
29133
29134
29135
29136 public function getExtra()
29137 {
29138 return $this->extra;
29139 }
29140
29141
29142
29143
29144 public function setBinaries(array $binaries)
29145 {
29146 $this->binaries = $binaries;
29147 }
29148
29149
29150
29151
29152 public function getBinaries()
29153 {
29154 return $this->binaries;
29155 }
29156
29157
29158
29159
29160 public function setInstallationSource($type)
29161 {
29162 $this->installationSource = $type;
29163 }
29164
29165
29166
29167
29168 public function getInstallationSource()
29169 {
29170 return $this->installationSource;
29171 }
29172
29173
29174
29175
29176 public function setSourceType($type)
29177 {
29178 $this->sourceType = $type;
29179 }
29180
29181
29182
29183
29184 public function getSourceType()
29185 {
29186 return $this->sourceType;
29187 }
29188
29189
29190
29191
29192 public function setSourceUrl($url)
29193 {
29194 $this->sourceUrl = $url;
29195 }
29196
29197
29198
29199
29200 public function getSourceUrl()
29201 {
29202 return $this->sourceUrl;
29203 }
29204
29205
29206
29207
29208 public function setSourceReference($reference)
29209 {
29210 $this->sourceReference = $reference;
29211 }
29212
29213
29214
29215
29216 public function getSourceReference()
29217 {
29218 return $this->sourceReference;
29219 }
29220
29221
29222
29223
29224 public function setSourceMirrors($mirrors)
29225 {
29226 $this->sourceMirrors = $mirrors;
29227 }
29228
29229
29230
29231
29232 public function getSourceMirrors()
29233 {
29234 return $this->sourceMirrors;
29235 }
29236
29237
29238
29239
29240 public function getSourceUrls()
29241 {
29242 return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
29243 }
29244
29245
29246
29247
29248 public function setDistType($type)
29249 {
29250 $this->distType = $type;
29251 }
29252
29253
29254
29255
29256 public function getDistType()
29257 {
29258 return $this->distType;
29259 }
29260
29261
29262
29263
29264 public function setDistUrl($url)
29265 {
29266 $this->distUrl = $url;
29267 }
29268
29269
29270
29271
29272 public function getDistUrl()
29273 {
29274 return $this->distUrl;
29275 }
29276
29277
29278
29279
29280 public function setDistReference($reference)
29281 {
29282 $this->distReference = $reference;
29283 }
29284
29285
29286
29287
29288 public function getDistReference()
29289 {
29290 return $this->distReference;
29291 }
29292
29293
29294
29295
29296 public function setDistSha1Checksum($sha1checksum)
29297 {
29298 $this->distSha1Checksum = $sha1checksum;
29299 }
29300
29301
29302
29303
29304 public function getDistSha1Checksum()
29305 {
29306 return $this->distSha1Checksum;
29307 }
29308
29309
29310
29311
29312 public function setDistMirrors($mirrors)
29313 {
29314 $this->distMirrors = $mirrors;
29315 }
29316
29317
29318
29319
29320 public function getDistMirrors()
29321 {
29322 return $this->distMirrors;
29323 }
29324
29325
29326
29327
29328 public function getDistUrls()
29329 {
29330 return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
29331 }
29332
29333
29334
29335
29336 public function getVersion()
29337 {
29338 return $this->version;
29339 }
29340
29341
29342
29343
29344 public function getPrettyVersion()
29345 {
29346 return $this->prettyVersion;
29347 }
29348
29349
29350
29351
29352
29353
29354 public function setReleaseDate(\DateTime $releaseDate)
29355 {
29356 $this->releaseDate = $releaseDate;
29357 }
29358
29359
29360
29361
29362 public function getReleaseDate()
29363 {
29364 return $this->releaseDate;
29365 }
29366
29367
29368
29369
29370
29371
29372 public function setRequires(array $requires)
29373 {
29374 $this->requires = $requires;
29375 }
29376
29377
29378
29379
29380 public function getRequires()
29381 {
29382 return $this->requires;
29383 }
29384
29385
29386
29387
29388
29389
29390 public function setConflicts(array $conflicts)
29391 {
29392 $this->conflicts = $conflicts;
29393 }
29394
29395
29396
29397
29398 public function getConflicts()
29399 {
29400 return $this->conflicts;
29401 }
29402
29403
29404
29405
29406
29407
29408 public function setProvides(array $provides)
29409 {
29410 $this->provides = $provides;
29411 }
29412
29413
29414
29415
29416 public function getProvides()
29417 {
29418 return $this->provides;
29419 }
29420
29421
29422
29423
29424
29425
29426 public function setReplaces(array $replaces)
29427 {
29428 $this->replaces = $replaces;
29429 }
29430
29431
29432
29433
29434 public function getReplaces()
29435 {
29436 return $this->replaces;
29437 }
29438
29439
29440
29441
29442
29443
29444 public function setDevRequires(array $devRequires)
29445 {
29446 $this->devRequires = $devRequires;
29447 }
29448
29449
29450
29451
29452 public function getDevRequires()
29453 {
29454 return $this->devRequires;
29455 }
29456
29457
29458
29459
29460
29461
29462 public function setSuggests(array $suggests)
29463 {
29464 $this->suggests = $suggests;
29465 }
29466
29467
29468
29469
29470 public function getSuggests()
29471 {
29472 return $this->suggests;
29473 }
29474
29475
29476
29477
29478
29479
29480 public function setAutoload(array $autoload)
29481 {
29482 $this->autoload = $autoload;
29483 }
29484
29485
29486
29487
29488 public function getAutoload()
29489 {
29490 return $this->autoload;
29491 }
29492
29493
29494
29495
29496
29497
29498 public function setDevAutoload(array $devAutoload)
29499 {
29500 $this->devAutoload = $devAutoload;
29501 }
29502
29503
29504
29505
29506 public function getDevAutoload()
29507 {
29508 return $this->devAutoload;
29509 }
29510
29511
29512
29513
29514
29515
29516 public function setIncludePaths(array $includePaths)
29517 {
29518 $this->includePaths = $includePaths;
29519 }
29520
29521
29522
29523
29524 public function getIncludePaths()
29525 {
29526 return $this->includePaths;
29527 }
29528
29529
29530
29531
29532
29533
29534 public function setNotificationUrl($notificationUrl)
29535 {
29536 $this->notificationUrl = $notificationUrl;
29537 }
29538
29539
29540
29541
29542 public function getNotificationUrl()
29543 {
29544 return $this->notificationUrl;
29545 }
29546
29547
29548
29549
29550
29551
29552 public function setArchiveExcludes(array $excludes)
29553 {
29554 $this->archiveExcludes = $excludes;
29555 }
29556
29557
29558
29559
29560 public function getArchiveExcludes()
29561 {
29562 return $this->archiveExcludes;
29563 }
29564
29565
29566
29567
29568
29569
29570
29571
29572 public function replaceVersion($version, $prettyVersion)
29573 {
29574 $this->version = $version;
29575 $this->prettyVersion = $prettyVersion;
29576
29577 $this->stability = VersionParser::parseStability($version);
29578 $this->dev = $this->stability === 'dev';
29579 }
29580
29581 protected function getUrls($url, $mirrors, $ref, $type, $urlType)
29582 {
29583 if (!$url) {
29584 return array();
29585 }
29586 $urls = array($url);
29587 if ($mirrors) {
29588 foreach ($mirrors as $mirror) {
29589 if ($urlType === 'dist') {
29590 $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type);
29591 } elseif ($urlType === 'source' && $type === 'git') {
29592 $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
29593 } elseif ($urlType === 'source' && $type === 'hg') {
29594 $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
29595 }
29596 if (!in_array($mirrorUrl, $urls)) {
29597 $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
29598 $func($urls, $mirrorUrl);
29599 }
29600 }
29601 }
29602
29603 return $urls;
29604 }
29605 }
29606 <?php
29607
29608
29609
29610
29611
29612
29613
29614
29615
29616
29617
29618 namespace Composer\Package;
29619
29620 use Composer\Repository\RepositoryInterface;
29621
29622
29623
29624
29625
29626
29627 interface PackageInterface
29628 {
29629
29630
29631
29632
29633
29634 public function getName();
29635
29636
29637
29638
29639
29640
29641 public function getPrettyName();
29642
29643
29644
29645
29646
29647
29648
29649
29650
29651 public function getNames();
29652
29653
29654
29655
29656
29657
29658 public function setId($id);
29659
29660
29661
29662
29663
29664
29665 public function getId();
29666
29667
29668
29669
29670
29671
29672 public function isDev();
29673
29674
29675
29676
29677
29678
29679 public function getType();
29680
29681
29682
29683
29684
29685
29686 public function getTargetDir();
29687
29688
29689
29690
29691
29692
29693 public function getExtra();
29694
29695
29696
29697
29698
29699
29700 public function setInstallationSource($type);
29701
29702
29703
29704
29705
29706
29707 public function getInstallationSource();
29708
29709
29710
29711
29712
29713
29714 public function getSourceType();
29715
29716
29717
29718
29719
29720
29721 public function getSourceUrl();
29722
29723
29724
29725
29726
29727
29728 public function getSourceUrls();
29729
29730
29731
29732
29733
29734
29735 public function getSourceReference();
29736
29737
29738
29739
29740
29741
29742 public function getSourceMirrors();
29743
29744
29745
29746
29747
29748
29749 public function getDistType();
29750
29751
29752
29753
29754
29755
29756 public function getDistUrl();
29757
29758
29759
29760
29761
29762
29763 public function getDistUrls();
29764
29765
29766
29767
29768
29769
29770 public function getDistReference();
29771
29772
29773
29774
29775
29776
29777 public function getDistSha1Checksum();
29778
29779
29780
29781
29782
29783
29784 public function getDistMirrors();
29785
29786
29787
29788
29789
29790
29791 public function getVersion();
29792
29793
29794
29795
29796
29797
29798 public function getPrettyVersion();
29799
29800
29801
29802
29803
29804
29805
29806
29807
29808 public function getFullPrettyVersion($truncate = true);
29809
29810
29811
29812
29813
29814
29815 public function getReleaseDate();
29816
29817
29818
29819
29820
29821
29822 public function getStability();
29823
29824
29825
29826
29827
29828
29829
29830 public function getRequires();
29831
29832
29833
29834
29835
29836
29837
29838 public function getConflicts();
29839
29840
29841
29842
29843
29844
29845
29846 public function getProvides();
29847
29848
29849
29850
29851
29852
29853
29854 public function getReplaces();
29855
29856
29857
29858
29859
29860
29861
29862 public function getDevRequires();
29863
29864
29865
29866
29867
29868
29869
29870 public function getSuggests();
29871
29872
29873
29874
29875
29876
29877
29878
29879
29880
29881
29882 public function getAutoload();
29883
29884
29885
29886
29887
29888
29889
29890
29891
29892
29893
29894 public function getDevAutoload();
29895
29896
29897
29898
29899
29900
29901
29902 public function getIncludePaths();
29903
29904
29905
29906
29907
29908
29909 public function setRepository(RepositoryInterface $repository);
29910
29911
29912
29913
29914
29915
29916 public function getRepository();
29917
29918
29919
29920
29921
29922
29923 public function getBinaries();
29924
29925
29926
29927
29928
29929
29930 public function getUniqueName();
29931
29932
29933
29934
29935
29936
29937 public function getNotificationUrl();
29938
29939
29940
29941
29942
29943
29944 public function __toString();
29945
29946
29947
29948
29949
29950
29951 public function getPrettyString();
29952
29953
29954
29955
29956
29957
29958 public function getArchiveExcludes();
29959
29960
29961
29962
29963
29964
29965 public function getTransportOptions();
29966 }
29967 <?php
29968
29969
29970
29971
29972
29973
29974
29975
29976
29977
29978
29979 namespace Composer\Package;
29980
29981
29982
29983
29984 class RootAliasPackage extends AliasPackage implements RootPackageInterface
29985 {
29986 public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
29987 {
29988 parent::__construct($aliasOf, $version, $prettyVersion);
29989 }
29990
29991
29992
29993
29994 public function getAliases()
29995 {
29996 return $this->aliasOf->getAliases();
29997 }
29998
29999
30000
30001
30002 public function getMinimumStability()
30003 {
30004 return $this->aliasOf->getMinimumStability();
30005 }
30006
30007
30008
30009
30010 public function getStabilityFlags()
30011 {
30012 return $this->aliasOf->getStabilityFlags();
30013 }
30014
30015
30016
30017
30018 public function getReferences()
30019 {
30020 return $this->aliasOf->getReferences();
30021 }
30022
30023
30024
30025
30026 public function getPreferStable()
30027 {
30028 return $this->aliasOf->getPreferStable();
30029 }
30030
30031
30032
30033
30034 public function getConfig()
30035 {
30036 return $this->aliasOf->getConfig();
30037 }
30038
30039
30040
30041
30042 public function setRequires(array $require)
30043 {
30044 $this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
30045
30046 $this->aliasOf->setRequires($require);
30047 }
30048
30049
30050
30051
30052 public function setDevRequires(array $devRequire)
30053 {
30054 $this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
30055
30056 $this->aliasOf->setDevRequires($devRequire);
30057 }
30058
30059
30060
30061
30062 public function setConflicts(array $conflicts)
30063 {
30064 $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, 'conflicts');
30065 $this->aliasOf->setConflicts($conflicts);
30066 }
30067
30068
30069
30070
30071 public function setProvides(array $provides)
30072 {
30073 $this->provides = $this->replaceSelfVersionDependencies($provides, 'provides');
30074 $this->aliasOf->setProvides($provides);
30075 }
30076
30077
30078
30079
30080 public function setReplaces(array $replaces)
30081 {
30082 $this->replaces = $this->replaceSelfVersionDependencies($replaces, 'replaces');
30083 $this->aliasOf->setReplaces($replaces);
30084 }
30085
30086
30087
30088
30089 public function setRepositories($repositories)
30090 {
30091 $this->aliasOf->setRepositories($repositories);
30092 }
30093
30094
30095
30096
30097 public function setAutoload(array $autoload)
30098 {
30099 $this->aliasOf->setAutoload($autoload);
30100 }
30101
30102
30103
30104
30105 public function setDevAutoload(array $devAutoload)
30106 {
30107 $this->aliasOf->setDevAutoload($devAutoload);
30108 }
30109
30110
30111
30112
30113 public function setStabilityFlags(array $stabilityFlags)
30114 {
30115 $this->aliasOf->setStabilityFlags($stabilityFlags);
30116 }
30117
30118
30119
30120
30121 public function setSuggests(array $suggests)
30122 {
30123 $this->aliasOf->setSuggests($suggests);
30124 }
30125
30126
30127
30128
30129 public function setExtra(array $extra)
30130 {
30131 $this->aliasOf->setExtra($extra);
30132 }
30133
30134 public function __clone()
30135 {
30136 parent::__clone();
30137 $this->aliasOf = clone $this->aliasOf;
30138 }
30139 }
30140 <?php
30141
30142
30143
30144
30145
30146
30147
30148
30149
30150
30151
30152 namespace Composer\Package;
30153
30154
30155
30156
30157
30158
30159 class RootPackage extends CompletePackage implements RootPackageInterface
30160 {
30161 protected $minimumStability = 'stable';
30162 protected $preferStable = false;
30163 protected $stabilityFlags = array();
30164 protected $config = array();
30165 protected $references = array();
30166 protected $aliases = array();
30167
30168
30169
30170
30171
30172
30173 public function setMinimumStability($minimumStability)
30174 {
30175 $this->minimumStability = $minimumStability;
30176 }
30177
30178
30179
30180
30181 public function getMinimumStability()
30182 {
30183 return $this->minimumStability;
30184 }
30185
30186
30187
30188
30189
30190
30191 public function setStabilityFlags(array $stabilityFlags)
30192 {
30193 $this->stabilityFlags = $stabilityFlags;
30194 }
30195
30196
30197
30198
30199 public function getStabilityFlags()
30200 {
30201 return $this->stabilityFlags;
30202 }
30203
30204
30205
30206
30207
30208
30209 public function setPreferStable($preferStable)
30210 {
30211 $this->preferStable = $preferStable;
30212 }
30213
30214
30215
30216
30217 public function getPreferStable()
30218 {
30219 return $this->preferStable;
30220 }
30221
30222
30223
30224
30225
30226
30227 public function setConfig(array $config)
30228 {
30229 $this->config = $config;
30230 }
30231
30232
30233
30234
30235 public function getConfig()
30236 {
30237 return $this->config;
30238 }
30239
30240
30241
30242
30243
30244
30245 public function setReferences(array $references)
30246 {
30247 $this->references = $references;
30248 }
30249
30250
30251
30252
30253 public function getReferences()
30254 {
30255 return $this->references;
30256 }
30257
30258
30259
30260
30261
30262
30263 public function setAliases(array $aliases)
30264 {
30265 $this->aliases = $aliases;
30266 }
30267
30268
30269
30270
30271 public function getAliases()
30272 {
30273 return $this->aliases;
30274 }
30275 }
30276 <?php
30277
30278
30279
30280
30281
30282
30283
30284
30285
30286
30287
30288 namespace Composer\Package;
30289
30290
30291
30292
30293
30294
30295 interface RootPackageInterface extends CompletePackageInterface
30296 {
30297
30298
30299
30300
30301
30302 public function getAliases();
30303
30304
30305
30306
30307
30308
30309 public function getMinimumStability();
30310
30311
30312
30313
30314
30315
30316
30317
30318 public function getStabilityFlags();
30319
30320
30321
30322
30323
30324
30325
30326
30327 public function getReferences();
30328
30329
30330
30331
30332
30333
30334 public function getPreferStable();
30335
30336
30337
30338
30339
30340
30341 public function getConfig();
30342
30343
30344
30345
30346
30347
30348 public function setRequires(array $requires);
30349
30350
30351
30352
30353
30354
30355 public function setDevRequires(array $devRequires);
30356
30357
30358
30359
30360
30361
30362 public function setConflicts(array $conflicts);
30363
30364
30365
30366
30367
30368
30369 public function setProvides(array $provides);
30370
30371
30372
30373
30374
30375
30376 public function setReplaces(array $replaces);
30377
30378
30379
30380
30381
30382
30383 public function setRepositories($repositories);
30384
30385
30386
30387
30388
30389
30390 public function setAutoload(array $autoload);
30391
30392
30393
30394
30395
30396
30397 public function setDevAutoload(array $devAutoload);
30398
30399
30400
30401
30402
30403
30404 public function setStabilityFlags(array $stabilityFlags);
30405
30406
30407
30408
30409
30410
30411 public function setSuggests(array $suggests);
30412
30413
30414
30415
30416 public function setExtra(array $extra);
30417 }
30418 <?php
30419
30420
30421
30422
30423
30424
30425
30426
30427
30428
30429
30430 namespace Composer\Package\Version;
30431
30432 use Composer\Config;
30433 use Composer\Repository\Vcs\HgDriver;
30434 use Composer\IO\NullIO;
30435 use Composer\Semver\VersionParser as SemverVersionParser;
30436 use Composer\Util\Git as GitUtil;
30437 use Composer\Util\ProcessExecutor;
30438 use Composer\Util\Svn as SvnUtil;
30439
30440
30441
30442
30443
30444
30445
30446 class VersionGuesser
30447 {
30448
30449
30450
30451 private $config;
30452
30453
30454
30455
30456 private $process;
30457
30458
30459
30460
30461 private $versionParser;
30462
30463
30464
30465
30466
30467
30468 public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
30469 {
30470 $this->config = $config;
30471 $this->process = $process;
30472 $this->versionParser = $versionParser;
30473 }
30474
30475
30476
30477
30478
30479
30480
30481 public function guessVersion(array $packageConfig, $path)
30482 {
30483 if (function_exists('proc_open')) {
30484 $versionData = $this->guessGitVersion($packageConfig, $path);
30485 if (null !== $versionData && null !== $versionData['version']) {
30486 return $this->postprocess($versionData);
30487 }
30488
30489 $versionData = $this->guessHgVersion($packageConfig, $path);
30490 if (null !== $versionData && null !== $versionData['version']) {
30491 return $this->postprocess($versionData);
30492 }
30493
30494 $versionData = $this->guessFossilVersion($packageConfig, $path);
30495 if (null !== $versionData && null !== $versionData['version']) {
30496 return $this->postprocess($versionData);
30497 }
30498
30499 $versionData = $this->guessSvnVersion($packageConfig, $path);
30500 if (null !== $versionData && null !== $versionData['version']) {
30501 return $this->postprocess($versionData);
30502 }
30503 }
30504 }
30505
30506 private function postprocess(array $versionData)
30507 {
30508 if ('-dev' === substr($versionData['version'], -4) && preg_match('{\.9{7}}', $versionData['version'])) {
30509 $versionData['pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['version']);
30510 }
30511
30512 return $versionData;
30513 }
30514
30515 private function guessGitVersion(array $packageConfig, $path)
30516 {
30517 GitUtil::cleanEnv();
30518 $commit = null;
30519 $version = null;
30520 $prettyVersion = null;
30521 $isDetached = false;
30522
30523
30524  if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
30525 $branches = array();
30526 $isFeatureBranch = false;
30527
30528
30529  foreach ($this->process->splitLines($output) as $branch) {
30530 if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
30531 if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ' || substr($match[1], 0, 17) === '(HEAD detached at') {
30532 $version = 'dev-' . $match[2];
30533 $prettyVersion = $version;
30534 $isFeatureBranch = true;
30535 $isDetached = true;
30536 } else {
30537 $version = $this->versionParser->normalizeBranch($match[1]);
30538 $prettyVersion = 'dev-' . $match[1];
30539 $isFeatureBranch = 0 === strpos($version, 'dev-');
30540 }
30541
30542 if ($match[2]) {
30543 $commit = $match[2];
30544 }
30545 }
30546
30547 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
30548 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
30549 $branches[] = $match[1];
30550 }
30551 }
30552 }
30553
30554 if ($isFeatureBranch) {
30555
30556  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
30557 $version = $result['version'];
30558 $prettyVersion = $result['pretty_version'];
30559 }
30560 }
30561
30562 if (!$version || $isDetached) {
30563 $result = $this->versionFromGitTags($path);
30564 if ($result) {
30565 $version = $result['version'];
30566 $prettyVersion = $result['pretty_version'];
30567 }
30568 }
30569
30570 if (!$commit) {
30571 $command = 'git log --pretty="%H" -n1 HEAD';
30572 if (0 === $this->process->execute($command, $output, $path)) {
30573 $commit = trim($output) ?: null;
30574 }
30575 }
30576
30577 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion);
30578 }
30579
30580 private function versionFromGitTags($path)
30581 {
30582
30583  if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
30584 try {
30585 $version = $this->versionParser->normalize(trim($output));
30586
30587 return array('version' => $version, 'pretty_version' => trim($output));
30588 } catch (\Exception $e) {
30589 }
30590 }
30591
30592 return null;
30593 }
30594
30595 private function guessHgVersion(array $packageConfig, $path)
30596 {
30597
30598  if (0 === $this->process->execute('hg branch', $output, $path)) {
30599 $branch = trim($output);
30600 $version = $this->versionParser->normalizeBranch($branch);
30601 $isFeatureBranch = 0 === strpos($version, 'dev-');
30602
30603 if ('9999999-dev' === $version) {
30604 return array('version' => $version, 'commit' => null, 'pretty_version' => 'dev-'.$branch);
30605 }
30606
30607 if (!$isFeatureBranch) {
30608 return array('version' => $version, 'commit' => null, 'pretty_version' => $version);
30609 }
30610
30611
30612  $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process);
30613 $branches = array_keys($driver->getBranches());
30614
30615
30616  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
30617 $result['commit'] = '';
30618
30619 return $result;
30620 }
30621 }
30622
30623 private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path)
30624 {
30625 $prettyVersion = $version;
30626
30627
30628  
30629  if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version]))
30630 || strpos(json_encode($packageConfig), '"self.version"')
30631 ) {
30632 $branch = preg_replace('{^dev-}', '', $version);
30633 $length = PHP_INT_MAX;
30634
30635 $nonFeatureBranches = '';
30636 if (!empty($packageConfig['non-feature-branches'])) {
30637 $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
30638 }
30639
30640 foreach ($branches as $candidate) {
30641
30642  if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
30643 break;
30644 }
30645
30646
30647  if ($candidate === $branch || !preg_match('{^(' . $nonFeatureBranches . '|master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
30648 continue;
30649 }
30650
30651 $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
30652 if (0 !== $this->process->execute($cmdLine, $output, $path)) {
30653 continue;
30654 }
30655
30656 if (strlen($output) < $length) {
30657 $length = strlen($output);
30658 $version = $this->versionParser->normalizeBranch($candidate);
30659 $prettyVersion = 'dev-' . $match[1];
30660 }
30661 }
30662 }
30663
30664 return array('version' => $version, 'pretty_version' => $prettyVersion);
30665 }
30666
30667 private function guessFossilVersion(array $packageConfig, $path)
30668 {
30669 $version = null;
30670 $prettyVersion = null;
30671
30672
30673  if (0 === $this->process->execute('fossil branch list', $output, $path)) {
30674 $branch = trim($output);
30675 $version = $this->versionParser->normalizeBranch($branch);
30676 $prettyVersion = 'dev-' . $branch;
30677 }
30678
30679
30680  if (0 === $this->process->execute('fossil tag list', $output, $path)) {
30681 try {
30682 $version = $this->versionParser->normalize(trim($output));
30683 $prettyVersion = trim($output);
30684 } catch (\Exception $e) {
30685 }
30686 }
30687
30688 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
30689 }
30690
30691 private function guessSvnVersion(array $packageConfig, $path)
30692 {
30693 SvnUtil::cleanEnv();
30694
30695
30696  if (0 === $this->process->execute('svn info --xml', $output, $path)) {
30697 $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
30698 $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
30699 $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
30700
30701 $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
30702
30703 if (preg_match($urlPattern, $output, $matches)) {
30704 if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
30705
30706  $version = $this->versionParser->normalizeBranch($matches[3]);
30707 $prettyVersion = 'dev-' . $matches[3];
30708
30709 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
30710 }
30711
30712 $prettyVersion = trim($matches[1]);
30713 $version = $this->versionParser->normalize($prettyVersion);
30714
30715 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
30716 }
30717 }
30718 }
30719 }
30720 <?php
30721
30722
30723
30724
30725
30726
30727
30728
30729
30730
30731
30732 namespace Composer\Package\Version;
30733
30734 use Composer\Repository\PlatformRepository;
30735 use Composer\Semver\VersionParser as SemverVersionParser;
30736 use Composer\Semver\Semver;
30737
30738 class VersionParser extends SemverVersionParser
30739 {
30740 private static $constraints = array();
30741
30742
30743
30744
30745 public function parseConstraints($constraints)
30746 {
30747 if (!isset(self::$constraints[$constraints])) {
30748 self::$constraints[$constraints] = parent::parseConstraints($constraints);
30749 }
30750
30751 return self::$constraints[$constraints];
30752 }
30753
30754
30755
30756
30757
30758
30759
30760
30761
30762
30763
30764 public function parseNameVersionPairs(array $pairs)
30765 {
30766 $pairs = array_values($pairs);
30767 $result = array();
30768
30769 for ($i = 0, $count = count($pairs); $i < $count; $i++) {
30770 $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
30771 if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/') && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $pairs[$i + 1])) {
30772 $pair .= ' '.$pairs[$i + 1];
30773 $i++;
30774 }
30775
30776 if (strpos($pair, ' ')) {
30777 list($name, $version) = explode(' ', $pair, 2);
30778 $result[] = array('name' => $name, 'version' => $version);
30779 } else {
30780 $result[] = array('name' => $pair);
30781 }
30782 }
30783
30784 return $result;
30785 }
30786
30787
30788
30789
30790 public static function isUpgrade($normalizedFrom, $normalizedTo)
30791 {
30792 if (substr($normalizedFrom, 0, 4) === 'dev-' || substr($normalizedTo, 0, 4) === 'dev-') {
30793 return true;
30794 }
30795
30796 $sorted = Semver::sort(array($normalizedTo, $normalizedFrom));
30797
30798 return $sorted[0] === $normalizedFrom;
30799 }
30800 }
30801 <?php
30802
30803
30804
30805
30806
30807
30808
30809
30810
30811
30812
30813 namespace Composer\Package\Version;
30814
30815 use Composer\DependencyResolver\Pool;
30816 use Composer\Package\BasePackage;
30817 use Composer\Package\PackageInterface;
30818 use Composer\Package\Loader\ArrayLoader;
30819 use Composer\Package\Dumper\ArrayDumper;
30820 use Composer\Semver\Constraint\Constraint;
30821
30822
30823
30824
30825
30826
30827
30828 class VersionSelector
30829 {
30830 private $pool;
30831
30832 private $parser;
30833
30834 public function __construct(Pool $pool)
30835 {
30836 $this->pool = $pool;
30837 }
30838
30839
30840
30841
30842
30843
30844
30845
30846
30847
30848
30849 public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
30850 {
30851 $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
30852 $candidates = $this->pool->whatProvides(strtolower($packageName), $constraint, true);
30853
30854 if ($targetPhpVersion) {
30855 $phpConstraint = new Constraint('==', $this->getParser()->normalize($targetPhpVersion));
30856 $candidates = array_filter($candidates, function ($pkg) use ($phpConstraint) {
30857 $reqs = $pkg->getRequires();
30858
30859 return !isset($reqs['php']) || $reqs['php']->getConstraint()->matches($phpConstraint);
30860 });
30861 }
30862
30863 if (!$candidates) {
30864 return false;
30865 }
30866
30867
30868  $package = reset($candidates);
30869 $minPriority = BasePackage::$stabilities[$preferredStability];
30870 foreach ($candidates as $candidate) {
30871 $candidatePriority = $candidate->getStabilityPriority();
30872 $currentPriority = $package->getStabilityPriority();
30873
30874
30875  
30876  if ($minPriority < $candidatePriority && $currentPriority < $candidatePriority) {
30877 continue;
30878 }
30879
30880
30881  
30882  if ($minPriority < $candidatePriority && $candidatePriority < $currentPriority) {
30883 $package = $candidate;
30884 continue;
30885 }
30886
30887
30888  
30889  if ($minPriority >= $candidatePriority && $minPriority < $currentPriority) {
30890 $package = $candidate;
30891 continue;
30892 }
30893
30894
30895  if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) {
30896 $package = $candidate;
30897 }
30898 }
30899
30900 return $package;
30901 }
30902
30903
30904
30905
30906
30907
30908
30909
30910
30911
30912
30913
30914
30915
30916
30917
30918 public function findRecommendedRequireVersion(PackageInterface $package)
30919 {
30920 $version = $package->getVersion();
30921 if (!$package->isDev()) {
30922 return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
30923 }
30924
30925 $loader = new ArrayLoader($this->getParser());
30926 $dumper = new ArrayDumper();
30927 $extra = $loader->getBranchAlias($dumper->dump($package));
30928 if ($extra) {
30929 $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
30930 if ($count) {
30931 $extra = str_replace('.9999999', '.0', $extra);
30932
30933 return $this->transformVersion($extra, $extra, 'dev');
30934 }
30935 }
30936
30937 return $package->getPrettyVersion();
30938 }
30939
30940 private function transformVersion($version, $prettyVersion, $stability)
30941 {
30942
30943  
30944  $semanticVersionParts = explode('.', $version);
30945
30946
30947  if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
30948
30949  if ($semanticVersionParts[0] === '0') {
30950 unset($semanticVersionParts[3]);
30951 } else {
30952 unset($semanticVersionParts[2], $semanticVersionParts[3]);
30953 }
30954 $version = implode('.', $semanticVersionParts);
30955 } else {
30956 return $prettyVersion;
30957 }
30958
30959
30960  if ($stability != 'stable') {
30961 $version .= '@'.$stability;
30962 }
30963
30964
30965  return '^' . $version;
30966 }
30967
30968 private function getParser()
30969 {
30970 if ($this->parser === null) {
30971 $this->parser = new VersionParser();
30972 }
30973
30974 return $this->parser;
30975 }
30976 }
30977 <?php
30978
30979
30980
30981
30982
30983
30984
30985
30986
30987
30988
30989 namespace Composer\Plugin\Capability;
30990
30991
30992
30993
30994
30995
30996
30997 interface Capability
30998 {
30999 }
31000 <?php
31001
31002
31003
31004
31005
31006
31007
31008
31009
31010
31011
31012 namespace Composer\Plugin\Capability;
31013
31014
31015
31016
31017
31018
31019
31020
31021
31022
31023
31024 interface CommandProvider extends Capability
31025 {
31026
31027
31028
31029
31030
31031 public function getCommands();
31032 }
31033 <?php
31034
31035
31036
31037
31038
31039
31040
31041
31042
31043
31044
31045 namespace Composer\Plugin;
31046
31047
31048
31049
31050
31051
31052
31053
31054 interface Capable
31055 {
31056
31057
31058
31059
31060
31061
31062
31063
31064
31065
31066
31067
31068
31069
31070
31071
31072
31073
31074 public function getCapabilities();
31075 }
31076 <?php
31077
31078
31079
31080
31081
31082
31083
31084
31085
31086
31087
31088 namespace Composer\Plugin;
31089
31090 use Composer\EventDispatcher\Event;
31091 use Symfony\Component\Console\Input\InputInterface;
31092 use Symfony\Component\Console\Output\OutputInterface;
31093
31094
31095
31096
31097
31098
31099 class CommandEvent extends Event
31100 {
31101
31102
31103
31104 private $commandName;
31105
31106
31107
31108
31109 private $input;
31110
31111
31112
31113
31114 private $output;
31115
31116
31117
31118
31119
31120
31121
31122
31123
31124
31125
31126 public function __construct($name, $commandName, $input, $output, array $args = array(), array $flags = array())
31127 {
31128 parent::__construct($name, $args, $flags);
31129 $this->commandName = $commandName;
31130 $this->input = $input;
31131 $this->output = $output;
31132 }
31133
31134
31135
31136
31137
31138
31139 public function getInput()
31140 {
31141 return $this->input;
31142 }
31143
31144
31145
31146
31147
31148
31149 public function getOutput()
31150 {
31151 return $this->output;
31152 }
31153
31154
31155
31156
31157
31158
31159 public function getCommandName()
31160 {
31161 return $this->commandName;
31162 }
31163 }
31164 <?php
31165
31166
31167
31168
31169
31170
31171
31172
31173
31174
31175
31176 namespace Composer\Plugin;
31177
31178
31179
31180
31181
31182
31183 class PluginEvents
31184 {
31185
31186
31187
31188
31189
31190
31191
31192
31193 const INIT = 'init';
31194
31195
31196
31197
31198
31199
31200
31201
31202
31203 const COMMAND = 'command';
31204
31205
31206
31207
31208
31209
31210
31211
31212
31213 const PRE_FILE_DOWNLOAD = 'pre-file-download';
31214
31215
31216
31217
31218
31219
31220
31221
31222
31223 const PRE_COMMAND_RUN = 'pre-command-run';
31224 }
31225 <?php
31226
31227
31228
31229
31230
31231
31232
31233
31234
31235
31236
31237 namespace Composer\Plugin;
31238
31239 use Composer\Composer;
31240 use Composer\IO\IOInterface;
31241
31242
31243
31244
31245
31246
31247 interface PluginInterface
31248 {
31249
31250
31251
31252
31253
31254 const PLUGIN_API_VERSION = '1.1.0';
31255
31256
31257
31258
31259
31260
31261
31262 public function activate(Composer $composer, IOInterface $io);
31263 }
31264 <?php
31265
31266
31267
31268
31269
31270
31271
31272
31273
31274
31275
31276 namespace Composer\Plugin;
31277
31278 use Composer\Composer;
31279 use Composer\EventDispatcher\EventSubscriberInterface;
31280 use Composer\IO\IOInterface;
31281 use Composer\Package\Package;
31282 use Composer\Package\Version\VersionParser;
31283 use Composer\Repository\RepositoryInterface;
31284 use Composer\Package\AliasPackage;
31285 use Composer\Package\PackageInterface;
31286 use Composer\Package\Link;
31287 use Composer\Semver\Constraint\Constraint;
31288 use Composer\DependencyResolver\Pool;
31289 use Composer\Plugin\Capability\Capability;
31290
31291
31292
31293
31294
31295
31296
31297 class PluginManager
31298 {
31299 protected $composer;
31300 protected $io;
31301 protected $globalComposer;
31302 protected $versionParser;
31303 protected $disablePlugins = false;
31304
31305 protected $plugins = array();
31306 protected $registeredPlugins = array();
31307
31308 private static $classCounter = 0;
31309
31310
31311
31312
31313
31314
31315
31316
31317
31318 public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
31319 {
31320 $this->io = $io;
31321 $this->composer = $composer;
31322 $this->globalComposer = $globalComposer;
31323 $this->versionParser = new VersionParser();
31324 $this->disablePlugins = $disablePlugins;
31325 }
31326
31327
31328
31329
31330 public function loadInstalledPlugins()
31331 {
31332 if ($this->disablePlugins) {
31333 return;
31334 }
31335
31336 $repo = $this->composer->getRepositoryManager()->getLocalRepository();
31337 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
31338 if ($repo) {
31339 $this->loadRepository($repo);
31340 }
31341 if ($globalRepo) {
31342 $this->loadRepository($globalRepo);
31343 }
31344 }
31345
31346
31347
31348
31349
31350
31351 public function getPlugins()
31352 {
31353 return $this->plugins;
31354 }
31355
31356
31357
31358
31359
31360
31361 public function getGlobalComposer()
31362 {
31363 return $this->globalComposer;
31364 }
31365
31366
31367
31368
31369
31370
31371
31372
31373
31374
31375
31376
31377 public function registerPackage(PackageInterface $package, $failOnMissingClasses = false)
31378 {
31379 if ($this->disablePlugins) {
31380 return;
31381 }
31382
31383 if ($package->getType() === 'composer-plugin') {
31384 $requiresComposer = null;
31385 foreach ($package->getRequires() as $link) { 
31386 if ('composer-plugin-api' === $link->getTarget()) {
31387 $requiresComposer = $link->getConstraint();
31388 break;
31389 }
31390 }
31391
31392 if (!$requiresComposer) {
31393 throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
31394 }
31395
31396 $currentPluginApiVersion = $this->getPluginApiVersion();
31397 $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
31398
31399 if ($requiresComposer->getPrettyString() === '1.0.0' && $this->getPluginApiVersion() === '1.0.0') {
31400 $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>');
31401 } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) {
31402 $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>');
31403
31404 return;
31405 }
31406 }
31407
31408 $oldInstallerPlugin = ($package->getType() === 'composer-installer');
31409
31410 if (in_array($package->getName(), $this->registeredPlugins)) {
31411 return;
31412 }
31413
31414 $extra = $package->getExtra();
31415 if (empty($extra['class'])) {
31416 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
31417 }
31418 $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
31419
31420 $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
31421 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
31422
31423 $pool = new Pool('dev');
31424 $pool->addRepository($localRepo);
31425 if ($globalRepo) {
31426 $pool->addRepository($globalRepo);
31427 }
31428
31429 $autoloadPackages = array($package->getName() => $package);
31430 $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package);
31431
31432 $generator = $this->composer->getAutoloadGenerator();
31433 $autoloads = array();
31434 foreach ($autoloadPackages as $autoloadPackage) {
31435 $downloadPath = $this->getInstallPath($autoloadPackage, $globalRepo && $globalRepo->hasPackage($autoloadPackage));
31436 $autoloads[] = array($autoloadPackage, $downloadPath);
31437 }
31438
31439 $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0'));
31440 $classLoader = $generator->createLoader($map);
31441 $classLoader->register();
31442
31443 foreach ($classes as $class) {
31444 if (class_exists($class, false)) {
31445 $class = trim($class, '\\');
31446 $path = $classLoader->findFile($class);
31447 $code = file_get_contents($path);
31448 $separatorPos = strrpos($class, '\\');
31449 $className = $class;
31450 if ($separatorPos) {
31451 $className = substr($class, $separatorPos + 1);
31452 }
31453 $code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
31454 $code = str_replace('__FILE__', var_export($path, true), $code);
31455 $code = str_replace('__DIR__', var_export(dirname($path), true), $code);
31456 $code = str_replace('__CLASS__', var_export($class, true), $code);
31457 $code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
31458 eval($code);
31459 $class .= '_composer_tmp'.self::$classCounter;
31460 self::$classCounter++;
31461 }
31462
31463 if ($oldInstallerPlugin) {
31464 $installer = new $class($this->io, $this->composer);
31465 $this->composer->getInstallationManager()->addInstaller($installer);
31466 } elseif (class_exists($class)) {
31467 $plugin = new $class();
31468 $this->addPlugin($plugin);
31469 $this->registeredPlugins[] = $package->getName();
31470 } elseif ($failOnMissingClasses) {
31471 throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
31472 }
31473 }
31474 }
31475
31476
31477
31478
31479
31480
31481 protected function getPluginApiVersion()
31482 {
31483 return PluginInterface::PLUGIN_API_VERSION;
31484 }
31485
31486
31487
31488
31489
31490
31491
31492
31493
31494
31495 public function addPlugin(PluginInterface $plugin)
31496 {
31497 $this->io->writeError('Loading plugin '.get_class($plugin), true, IOInterface::DEBUG);
31498 $this->plugins[] = $plugin;
31499 $plugin->activate($this->composer, $this->io);
31500
31501 if ($plugin instanceof EventSubscriberInterface) {
31502 $this->composer->getEventDispatcher()->addSubscriber($plugin);
31503 }
31504 }
31505
31506
31507
31508
31509
31510
31511
31512
31513
31514
31515
31516
31517 private function loadRepository(RepositoryInterface $repo)
31518 {
31519 foreach ($repo->getPackages() as $package) { 
31520 if ($package instanceof AliasPackage) {
31521 continue;
31522 }
31523 if ('composer-plugin' === $package->getType()) {
31524 $this->registerPackage($package);
31525
31526  } elseif ('composer-installer' === $package->getType()) {
31527 $this->registerPackage($package);
31528 }
31529 }
31530 }
31531
31532
31533
31534
31535
31536
31537
31538
31539
31540
31541 private function collectDependencies(Pool $pool, array $collected, PackageInterface $package)
31542 {
31543 $requires = array_merge(
31544 $package->getRequires(),
31545 $package->getDevRequires()
31546 );
31547
31548 foreach ($requires as $requireLink) {
31549 $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink);
31550 if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) {
31551 $collected[$requiredPackage->getName()] = $requiredPackage;
31552 $collected = $this->collectDependencies($pool, $collected, $requiredPackage);
31553 }
31554 }
31555
31556 return $collected;
31557 }
31558
31559
31560
31561
31562
31563
31564
31565
31566
31567
31568
31569 private function lookupInstalledPackage(Pool $pool, Link $link)
31570 {
31571 $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint());
31572
31573 return !empty($packages) ? $packages[0] : null;
31574 }
31575
31576
31577
31578
31579
31580
31581
31582
31583
31584 private function getInstallPath(PackageInterface $package, $global = false)
31585 {
31586 if (!$global) {
31587 return $this->composer->getInstallationManager()->getInstallPath($package);
31588 }
31589
31590 return $this->globalComposer->getInstallationManager()->getInstallPath($package);
31591 }
31592
31593
31594
31595
31596
31597
31598
31599 protected function getCapabilityImplementationClassName(PluginInterface $plugin, $capability)
31600 {
31601 if (!($plugin instanceof Capable)) {
31602 return null;
31603 }
31604
31605 $capabilities = (array) $plugin->getCapabilities();
31606
31607 if (!empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability])) {
31608 return trim($capabilities[$capability]);
31609 }
31610
31611 if (
31612 array_key_exists($capability, $capabilities)
31613 && (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))
31614 ) {
31615 throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], 1));
31616 }
31617 }
31618
31619
31620
31621
31622
31623
31624
31625
31626
31627 public function getPluginCapability(PluginInterface $plugin, $capabilityClassName, array $ctorArgs = array())
31628 {
31629 if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) {
31630 if (!class_exists($capabilityClass)) {
31631 throw new \RuntimeException("Cannot instantiate Capability, as class $capabilityClass from plugin ".get_class($plugin)." does not exist.");
31632 }
31633
31634 $ctorArgs['plugin'] = $plugin;
31635 $capabilityObj = new $capabilityClass($ctorArgs);
31636
31637
31638  if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) {
31639 throw new \RuntimeException(
31640 'Class ' . $capabilityClass . ' must implement both Composer\Plugin\Capability\Capability and '. $capabilityClassName . '.'
31641 );
31642 }
31643
31644 return $capabilityObj;
31645 }
31646 }
31647
31648
31649
31650
31651
31652
31653
31654
31655 public function getPluginCapabilities($capabilityClassName, array $ctorArgs = array())
31656 {
31657 $capabilities = array();
31658 foreach ($this->getPlugins() as $plugin) {
31659 if ($capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs)) {
31660 $capabilities[] = $capability;
31661 }
31662 }
31663
31664 return $capabilities;
31665 }
31666 }
31667 <?php
31668
31669
31670
31671
31672
31673
31674
31675
31676
31677
31678
31679 namespace Composer\Plugin;
31680
31681 use Composer\EventDispatcher\Event;
31682 use Symfony\Component\Console\Input\InputInterface;
31683
31684
31685
31686
31687
31688
31689 class PreCommandRunEvent extends Event
31690 {
31691
31692
31693
31694 private $input;
31695
31696
31697
31698
31699 private $command;
31700
31701
31702
31703
31704
31705
31706
31707
31708 public function __construct($name, InputInterface $input, $command)
31709 {
31710 parent::__construct($name);
31711 $this->input = $input;
31712 $this->command = $command;
31713 }
31714
31715
31716
31717
31718
31719
31720 public function getInput()
31721 {
31722 return $this->input;
31723 }
31724
31725
31726
31727
31728
31729
31730 public function getCommand()
31731 {
31732 return $this->command;
31733 }
31734 }
31735 <?php
31736
31737
31738
31739
31740
31741
31742
31743
31744
31745
31746
31747 namespace Composer\Plugin;
31748
31749 use Composer\EventDispatcher\Event;
31750 use Composer\Util\RemoteFilesystem;
31751
31752
31753
31754
31755
31756
31757 class PreFileDownloadEvent extends Event
31758 {
31759
31760
31761
31762 private $rfs;
31763
31764
31765
31766
31767 private $processedUrl;
31768
31769
31770
31771
31772
31773
31774
31775
31776 public function __construct($name, RemoteFilesystem $rfs, $processedUrl)
31777 {
31778 parent::__construct($name);
31779 $this->rfs = $rfs;
31780 $this->processedUrl = $processedUrl;
31781 }
31782
31783
31784
31785
31786
31787
31788 public function getRemoteFilesystem()
31789 {
31790 return $this->rfs;
31791 }
31792
31793
31794
31795
31796
31797
31798 public function setRemoteFilesystem(RemoteFilesystem $rfs)
31799 {
31800 $this->rfs = $rfs;
31801 }
31802
31803
31804
31805
31806
31807
31808 public function getProcessedUrl()
31809 {
31810 return $this->processedUrl;
31811 }
31812 }
31813 <?php
31814
31815
31816
31817
31818
31819
31820
31821
31822
31823
31824
31825 namespace Composer\Question;
31826
31827 use Symfony\Component\Console\Exception\InvalidArgumentException;
31828 use Symfony\Component\Console\Question\Question;
31829
31830
31831
31832
31833
31834
31835
31836
31837 class StrictConfirmationQuestion extends Question
31838 {
31839 private $trueAnswerRegex;
31840 private $falseAnswerRegex;
31841
31842
31843
31844
31845
31846
31847
31848
31849
31850 public function __construct($question, $default = true, $trueAnswerRegex = '/^y(?:es)?$/i', $falseAnswerRegex = '/^no?$/i')
31851 {
31852 parent::__construct($question, (bool) $default);
31853
31854 $this->trueAnswerRegex = $trueAnswerRegex;
31855 $this->falseAnswerRegex = $falseAnswerRegex;
31856 $this->setNormalizer($this->getDefaultNormalizer());
31857 $this->setValidator($this->getDefaultValidator());
31858 }
31859
31860
31861
31862
31863
31864
31865 private function getDefaultNormalizer()
31866 {
31867 $default = $this->getDefault();
31868 $trueRegex = $this->trueAnswerRegex;
31869 $falseRegex = $this->falseAnswerRegex;
31870
31871 return function ($answer) use ($default, $trueRegex, $falseRegex) {
31872 if (is_bool($answer)) {
31873 return $answer;
31874 }
31875 if (empty($answer) && !empty($default)) {
31876 return $default;
31877 }
31878
31879 if (preg_match($trueRegex, $answer)) {
31880 return true;
31881 }
31882
31883 if (preg_match($falseRegex, $answer)) {
31884 return false;
31885 }
31886
31887 return null;
31888 };
31889 }
31890
31891
31892
31893
31894
31895
31896 private function getDefaultValidator()
31897 {
31898 return function ($answer) {
31899 if (!is_bool($answer)) {
31900 throw new InvalidArgumentException('Please answer yes, y, no, or n.');
31901 }
31902
31903 return $answer;
31904 };
31905 }
31906 }
31907 <?php
31908
31909
31910
31911
31912
31913
31914
31915
31916
31917
31918
31919 namespace Composer\Repository;
31920
31921 use Composer\Package\AliasPackage;
31922 use Composer\Package\PackageInterface;
31923 use Composer\Package\CompletePackageInterface;
31924 use Composer\Package\Version\VersionParser;
31925 use Composer\Semver\Constraint\ConstraintInterface;
31926 use Composer\Semver\Constraint\Constraint;
31927
31928
31929
31930
31931
31932
31933 class ArrayRepository extends BaseRepository
31934 {
31935
31936 protected $packages;
31937
31938 public function __construct(array $packages = array())
31939 {
31940 foreach ($packages as $package) {
31941 $this->addPackage($package);
31942 }
31943 }
31944
31945
31946
31947
31948 public function findPackage($name, $constraint)
31949 {
31950 $name = strtolower($name);
31951
31952 if (!$constraint instanceof ConstraintInterface) {
31953 $versionParser = new VersionParser();
31954 $constraint = $versionParser->parseConstraints($constraint);
31955 }
31956
31957 foreach ($this->getPackages() as $package) {
31958 if ($name === $package->getName()) {
31959 $pkgConstraint = new Constraint('==', $package->getVersion());
31960 if ($constraint->matches($pkgConstraint)) {
31961 return $package;
31962 }
31963 }
31964 }
31965
31966 return null;
31967 }
31968
31969
31970
31971
31972 public function findPackages($name, $constraint = null)
31973 {
31974
31975  $name = strtolower($name);
31976 $packages = array();
31977
31978 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
31979 $versionParser = new VersionParser();
31980 $constraint = $versionParser->parseConstraints($constraint);
31981 }
31982
31983 foreach ($this->getPackages() as $package) {
31984 if ($name === $package->getName()) {
31985 $pkgConstraint = new Constraint('==', $package->getVersion());
31986 if (null === $constraint || $constraint->matches($pkgConstraint)) {
31987 $packages[] = $package;
31988 }
31989 }
31990 }
31991
31992 return $packages;
31993 }
31994
31995
31996
31997
31998 public function search($query, $mode = 0, $type = null)
31999 {
32000 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
32001
32002 $matches = array();
32003 foreach ($this->getPackages() as $package) {
32004 $name = $package->getName();
32005 if (isset($matches[$name])) {
32006 continue;
32007 }
32008 if (preg_match($regex, $name)
32009 || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
32010 ) {
32011 if (null !== $type && $package->getType() !== $type) {
32012 continue;
32013 }
32014
32015 $matches[$name] = array(
32016 'name' => $package->getPrettyName(),
32017 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null,
32018 );
32019 }
32020 }
32021
32022 return array_values($matches);
32023 }
32024
32025
32026
32027
32028 public function hasPackage(PackageInterface $package)
32029 {
32030 $packageId = $package->getUniqueName();
32031
32032 foreach ($this->getPackages() as $repoPackage) {
32033 if ($packageId === $repoPackage->getUniqueName()) {
32034 return true;
32035 }
32036 }
32037
32038 return false;
32039 }
32040
32041
32042
32043
32044
32045
32046 public function addPackage(PackageInterface $package)
32047 {
32048 if (null === $this->packages) {
32049 $this->initialize();
32050 }
32051 $package->setRepository($this);
32052 $this->packages[] = $package;
32053
32054 if ($package instanceof AliasPackage) {
32055 $aliasedPackage = $package->getAliasOf();
32056 if (null === $aliasedPackage->getRepository()) {
32057 $this->addPackage($aliasedPackage);
32058 }
32059 }
32060 }
32061
32062 protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
32063 {
32064 return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
32065 }
32066
32067
32068
32069
32070
32071
32072 public function removePackage(PackageInterface $package)
32073 {
32074 $packageId = $package->getUniqueName();
32075
32076 foreach ($this->getPackages() as $key => $repoPackage) {
32077 if ($packageId === $repoPackage->getUniqueName()) {
32078 array_splice($this->packages, $key, 1);
32079
32080 return;
32081 }
32082 }
32083 }
32084
32085
32086
32087
32088 public function getPackages()
32089 {
32090 if (null === $this->packages) {
32091 $this->initialize();
32092 }
32093
32094 return $this->packages;
32095 }
32096
32097
32098
32099
32100
32101
32102 public function count()
32103 {
32104 return count($this->packages);
32105 }
32106
32107
32108
32109
32110 protected function initialize()
32111 {
32112 $this->packages = array();
32113 }
32114 }
32115 <?php
32116
32117
32118
32119
32120
32121
32122
32123
32124
32125
32126
32127 namespace Composer\Repository;
32128
32129 use Composer\IO\IOInterface;
32130 use Composer\Json\JsonFile;
32131 use Composer\Package\Loader\ArrayLoader;
32132 use Composer\Package\Loader\LoaderInterface;
32133
32134
32135
32136
32137 class ArtifactRepository extends ArrayRepository implements ConfigurableRepositoryInterface
32138 {
32139
32140 protected $loader;
32141
32142 protected $lookup;
32143 protected $repoConfig;
32144 private $io;
32145
32146 public function __construct(array $repoConfig, IOInterface $io)
32147 {
32148 parent::__construct();
32149 if (!extension_loaded('zip')) {
32150 throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
32151 }
32152
32153 $this->loader = new ArrayLoader();
32154 $this->lookup = $repoConfig['url'];
32155 $this->io = $io;
32156 $this->repoConfig = $repoConfig;
32157 }
32158
32159 public function getRepoConfig()
32160 {
32161 return $this->repoConfig;
32162 }
32163
32164 protected function initialize()
32165 {
32166 parent::initialize();
32167
32168 $this->scanDirectory($this->lookup);
32169 }
32170
32171 private function scanDirectory($path)
32172 {
32173 $io = $this->io;
32174
32175 $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
32176 $iterator = new \RecursiveIteratorIterator($directory);
32177 $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i');
32178 foreach ($regex as $file) {
32179
32180 if (!$file->isFile()) {
32181 continue;
32182 }
32183
32184 $package = $this->getComposerInformation($file);
32185 if (!$package) {
32186 $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", true, IOInterface::VERBOSE);
32187 continue;
32188 }
32189
32190 $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
32191 $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), true, IOInterface::VERBOSE);
32192
32193 $this->addPackage($package);
32194 }
32195 }
32196
32197
32198
32199
32200
32201
32202
32203
32204 private function locateFile(\ZipArchive $zip, $filename)
32205 {
32206 $indexOfShortestMatch = false;
32207 $lengthOfShortestMatch = -1;
32208
32209 for ($i = 0; $i < $zip->numFiles; $i++) {
32210 $stat = $zip->statIndex($i);
32211 if (strcmp(basename($stat['name']), $filename) === 0) {
32212 $directoryName = dirname($stat['name']);
32213 if ($directoryName == '.') {
32214
32215  
32216  return $i;
32217 }
32218
32219 if (strpos($directoryName, '\\') !== false ||
32220 strpos($directoryName, '/') !== false) {
32221
32222  continue;
32223 }
32224
32225 $length = strlen($stat['name']);
32226 if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) {
32227
32228  $contents = $zip->getFromIndex($i);
32229 if ($contents !== false) {
32230 $indexOfShortestMatch = $i;
32231 $lengthOfShortestMatch = $length;
32232 }
32233 }
32234 }
32235 }
32236
32237 return $indexOfShortestMatch;
32238 }
32239
32240 private function getComposerInformation(\SplFileInfo $file)
32241 {
32242 $zip = new \ZipArchive();
32243 $zip->open($file->getPathname());
32244
32245 if (0 == $zip->numFiles) {
32246 $zip->close();
32247
32248 return false;
32249 }
32250
32251 $foundFileIndex = $this->locateFile($zip, 'composer.json');
32252 if (false === $foundFileIndex) {
32253 $zip->close();
32254
32255 return false;
32256 }
32257
32258 $configurationFileName = $zip->getNameIndex($foundFileIndex);
32259 $zip->close();
32260
32261 $composerFile = "zip://{$file->getPathname()}#$configurationFileName";
32262 $json = file_get_contents($composerFile);
32263
32264 $package = JsonFile::parseJson($json, $composerFile);
32265 $package['dist'] = array(
32266 'type' => 'zip',
32267 'url' => strtr($file->getPathname(), '\\', '/'),
32268 'shasum' => sha1_file($file->getRealPath()),
32269 );
32270
32271 try {
32272 $package = $this->loader->load($package);
32273 } catch (\UnexpectedValueException $e) {
32274 throw new \UnexpectedValueException('Failed loading package in '.$file.': '.$e->getMessage(), 0, $e);
32275 }
32276
32277 return $package;
32278 }
32279 }
32280 <?php
32281
32282
32283
32284
32285
32286
32287
32288
32289
32290
32291
32292 namespace Composer\Repository;
32293
32294 use Composer\Package\RootPackageInterface;
32295 use Composer\Semver\Constraint\ConstraintInterface;
32296 use Composer\Semver\Constraint\Constraint;
32297 use Composer\Package\Link;
32298
32299
32300
32301
32302
32303
32304 abstract class BaseRepository implements RepositoryInterface
32305 {
32306
32307
32308
32309
32310
32311
32312
32313
32314
32315
32316
32317
32318
32319 public function getDependents($needle, $constraint = null, $invert = false, $recurse = true, $packagesFound = null)
32320 {
32321 $needles = array_map('strtolower', (array) $needle);
32322 $results = array();
32323
32324
32325  if (null === $packagesFound) {
32326 $packagesFound = $needles;
32327 }
32328
32329
32330  $rootPackage = null;
32331 foreach ($this->getPackages() as $package) {
32332 if ($package instanceof RootPackageInterface) {
32333 $rootPackage = $package;
32334 break;
32335 }
32336 }
32337
32338
32339  foreach ($this->getPackages() as $package) {
32340 $links = $package->getRequires();
32341
32342
32343  
32344  $packagesInTree = $packagesFound;
32345
32346
32347  if (!$invert) {
32348 $links += $package->getReplaces();
32349 }
32350
32351
32352  if ($package instanceof RootPackageInterface) {
32353 $links += $package->getDevRequires();
32354 }
32355
32356
32357  foreach ($links as $link) {
32358 foreach ($needles as $needle) {
32359 if ($link->getTarget() === $needle) {
32360 if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
32361
32362  if (in_array($link->getSource(), $packagesInTree)) {
32363 $results[$link->getSource()] = array($package, $link, false);
32364 continue;
32365 }
32366 $packagesInTree[] = $link->getSource();
32367 $dependents = $recurse ? $this->getDependents($link->getSource(), null, false, true, $packagesInTree) : array();
32368 $results[$link->getSource()] = array($package, $link, $dependents);
32369 }
32370 }
32371 }
32372 }
32373
32374
32375  if ($invert && in_array($package->getName(), $needles)) {
32376 foreach ($package->getConflicts() as $link) {
32377 foreach ($this->findPackages($link->getTarget()) as $pkg) {
32378 $version = new Constraint('=', $pkg->getVersion());
32379 if ($link->getConstraint()->matches($version) === $invert) {
32380 $results[] = array($package, $link, false);
32381 }
32382 }
32383 }
32384 }
32385
32386
32387  if ($invert && $constraint && in_array($package->getName(), $needles) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
32388 foreach ($package->getRequires() as $link) {
32389 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
32390 if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
32391 continue;
32392 }
32393
32394 $platformPkg = $this->findPackage($link->getTarget(), '*');
32395 $description = $platformPkg ? 'but '.$platformPkg->getPrettyVersion().' is installed' : 'but it is missing';
32396 $results[] = array($package, new Link($package->getName(), $link->getTarget(), null, 'requires', $link->getPrettyConstraint().' '.$description), false);
32397
32398 continue;
32399 }
32400
32401 foreach ($this->getPackages() as $pkg) {
32402 if (!in_array($link->getTarget(), $pkg->getNames())) {
32403 continue;
32404 }
32405
32406 $version = new Constraint('=', $pkg->getVersion());
32407 if (!$link->getConstraint()->matches($version)) {
32408
32409  
32410  if ($rootPackage) {
32411 foreach (array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) {
32412 if (in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) {
32413 $results[] = array($package, $link, false);
32414 $results[] = array($rootPackage, $rootReq, false);
32415 continue 3;
32416 }
32417 }
32418 $results[] = array($package, $link, false);
32419 $results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), null, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
32420 } else {
32421
32422  $results[] = array($package, $link, false);
32423 }
32424 }
32425
32426 continue 2;
32427 }
32428 }
32429 }
32430 }
32431
32432 ksort($results);
32433
32434 return $results;
32435 }
32436 }
32437 <?php
32438
32439
32440
32441
32442
32443
32444
32445
32446
32447
32448
32449 namespace Composer\Repository;
32450
32451 use Composer\Package\Loader\ArrayLoader;
32452 use Composer\Package\PackageInterface;
32453 use Composer\Package\AliasPackage;
32454 use Composer\Package\Version\VersionParser;
32455 use Composer\DependencyResolver\Pool;
32456 use Composer\Json\JsonFile;
32457 use Composer\Cache;
32458 use Composer\Config;
32459 use Composer\Factory;
32460 use Composer\IO\IOInterface;
32461 use Composer\Util\RemoteFilesystem;
32462 use Composer\Plugin\PluginEvents;
32463 use Composer\Plugin\PreFileDownloadEvent;
32464 use Composer\EventDispatcher\EventDispatcher;
32465 use Composer\Downloader\TransportException;
32466 use Composer\Semver\Constraint\ConstraintInterface;
32467 use Composer\Semver\Constraint\Constraint;
32468
32469
32470
32471
32472 class ComposerRepository extends ArrayRepository implements ConfigurableRepositoryInterface
32473 {
32474 protected $config;
32475 protected $repoConfig;
32476 protected $options;
32477 protected $url;
32478 protected $baseUrl;
32479 protected $io;
32480 protected $rfs;
32481 protected $cache;
32482 protected $notifyUrl;
32483 protected $searchUrl;
32484 protected $hasProviders = false;
32485 protected $providersUrl;
32486 protected $lazyProvidersUrl;
32487 protected $providerListing;
32488 protected $providers = array();
32489 protected $providersByUid = array();
32490 protected $loader;
32491 protected $rootAliases;
32492 protected $allowSslDowngrade = false;
32493 protected $eventDispatcher;
32494 protected $sourceMirrors;
32495 protected $distMirrors;
32496 private $degradedMode = false;
32497 private $rootData;
32498 private $hasPartialPackages;
32499 private $partialPackagesByName;
32500
32501 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
32502 {
32503 parent::__construct();
32504 if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) {
32505
32506  $repoConfig['url'] = 'http://'.$repoConfig['url'];
32507 }
32508 $repoConfig['url'] = rtrim($repoConfig['url'], '/');
32509
32510 if ('https?' === substr($repoConfig['url'], 0, 6)) {
32511 $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
32512 }
32513
32514 $urlBits = parse_url($repoConfig['url']);
32515 if ($urlBits === false || empty($urlBits['scheme'])) {
32516 throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
32517 }
32518
32519 if (!isset($repoConfig['options'])) {
32520 $repoConfig['options'] = array();
32521 }
32522 if (isset($repoConfig['allow_ssl_downgrade']) && true === $repoConfig['allow_ssl_downgrade']) {
32523 $this->allowSslDowngrade = true;
32524 }
32525
32526 $this->config = $config;
32527 $this->options = $repoConfig['options'];
32528 $this->url = $repoConfig['url'];
32529
32530
32531  if (preg_match('{^(?P<proto>https?)://packagist\.org/?$}i', $this->url, $match)) {
32532 $this->url = $match['proto'].'://repo.packagist.org';
32533 }
32534
32535 $this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
32536 $this->io = $io;
32537 $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
32538 $this->loader = new ArrayLoader();
32539 if ($rfs && $this->options) {
32540 $rfs = clone $rfs;
32541 $rfs->setOptions($this->options);
32542 }
32543 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $this->config, $this->options);
32544 $this->eventDispatcher = $eventDispatcher;
32545 $this->repoConfig = $repoConfig;
32546 }
32547
32548 public function getRepoConfig()
32549 {
32550 return $this->repoConfig;
32551 }
32552
32553 public function setRootAliases(array $rootAliases)
32554 {
32555 $this->rootAliases = $rootAliases;
32556 }
32557
32558
32559
32560
32561 public function findPackage($name, $constraint)
32562 {
32563 if (!$this->hasProviders()) {
32564 return parent::findPackage($name, $constraint);
32565 }
32566
32567 $name = strtolower($name);
32568 if (!$constraint instanceof ConstraintInterface) {
32569 $versionParser = new VersionParser();
32570 $constraint = $versionParser->parseConstraints($constraint);
32571 }
32572
32573 foreach ($this->getProviderNames() as $providerName) {
32574 if ($name === $providerName) {
32575 $packages = $this->whatProvides(new Pool('dev'), $providerName);
32576 foreach ($packages as $package) {
32577 if ($name === $package->getName()) {
32578 $pkgConstraint = new Constraint('==', $package->getVersion());
32579 if ($constraint->matches($pkgConstraint)) {
32580 return $package;
32581 }
32582 }
32583 }
32584 break;
32585 }
32586 }
32587 }
32588
32589
32590
32591
32592 public function findPackages($name, $constraint = null)
32593 {
32594 if (!$this->hasProviders()) {
32595 return parent::findPackages($name, $constraint);
32596 }
32597
32598  $name = strtolower($name);
32599
32600 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
32601 $versionParser = new VersionParser();
32602 $constraint = $versionParser->parseConstraints($constraint);
32603 }
32604
32605 $packages = array();
32606
32607 foreach ($this->getProviderNames() as $providerName) {
32608 if ($name === $providerName) {
32609 $candidates = $this->whatProvides(new Pool('dev'), $providerName);
32610 foreach ($candidates as $package) {
32611 if ($name === $package->getName()) {
32612 $pkgConstraint = new Constraint('==', $package->getVersion());
32613 if (null === $constraint || $constraint->matches($pkgConstraint)) {
32614 $packages[] = $package;
32615 }
32616 }
32617 }
32618 break;
32619 }
32620 }
32621
32622 return $packages;
32623 }
32624
32625 public function getPackages()
32626 {
32627 if ($this->hasProviders()) {
32628 throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.');
32629 }
32630
32631 return parent::getPackages();
32632 }
32633
32634
32635
32636
32637 public function search($query, $mode = 0, $type = null)
32638 {
32639 $this->loadRootServerFile();
32640
32641 if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
32642 $url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl);
32643
32644 $hostname = parse_url($url, PHP_URL_HOST) ?: $url;
32645 $json = $this->rfs->getContents($hostname, $url, false);
32646 $search = JsonFile::parseJson($json, $url);
32647
32648 if (empty($search['results'])) {
32649 return array();
32650 }
32651
32652 $results = array();
32653 foreach ($search['results'] as $result) {
32654
32655  if (empty($result['virtual'])) {
32656 $results[] = $result;
32657 }
32658 }
32659
32660 return $results;
32661 }
32662
32663 if ($this->hasProviders()) {
32664 $results = array();
32665 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
32666
32667 foreach ($this->getProviderNames() as $name) {
32668 if (preg_match($regex, $name)) {
32669 $results[] = array('name' => $name);
32670 }
32671 }
32672
32673 return $results;
32674 }
32675
32676 return parent::search($query, $mode);
32677 }
32678
32679 public function getProviderNames()
32680 {
32681 $this->loadRootServerFile();
32682
32683 if (null === $this->providerListing) {
32684 $this->loadProviderListings($this->loadRootServerFile());
32685 }
32686
32687 if ($this->lazyProvidersUrl) {
32688
32689  return array();
32690 }
32691
32692 if ($this->providersUrl) {
32693 return array_keys($this->providerListing);
32694 }
32695
32696 return array();
32697 }
32698
32699 protected function configurePackageTransportOptions(PackageInterface $package)
32700 {
32701 foreach ($package->getDistUrls() as $url) {
32702 if (strpos($url, $this->baseUrl) === 0) {
32703 $package->setTransportOptions($this->options);
32704
32705 return;
32706 }
32707 }
32708 }
32709
32710 public function hasProviders()
32711 {
32712 $this->loadRootServerFile();
32713
32714 return $this->hasProviders;
32715 }
32716
32717 public function resetPackageIds()
32718 {
32719 foreach ($this->providersByUid as $package) {
32720 if ($package instanceof AliasPackage) {
32721 $package->getAliasOf()->setId(-1);
32722 }
32723 $package->setId(-1);
32724 }
32725 }
32726
32727
32728
32729
32730
32731
32732
32733 public function whatProvides(Pool $pool, $name, $bypassFilters = false)
32734 {
32735 if (isset($this->providers[$name]) && !$bypassFilters) {
32736 return $this->providers[$name];
32737 }
32738
32739 if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
32740 $this->initializePartialPackages();
32741 }
32742
32743 if (!$this->hasPartialPackages || !isset($this->partialPackagesByName[$name])) {
32744
32745  if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) {
32746 return array();
32747 }
32748
32749 if (null === $this->providerListing) {
32750 $this->loadProviderListings($this->loadRootServerFile());
32751 }
32752
32753 $useLastModifiedCheck = false;
32754 if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
32755 $hash = null;
32756 $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
32757 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
32758 $useLastModifiedCheck = true;
32759 } elseif ($this->providersUrl) {
32760
32761  if (!isset($this->providerListing[$name])) {
32762 return array();
32763 }
32764
32765 $hash = $this->providerListing[$name]['sha256'];
32766 $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
32767 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
32768 } else {
32769 return array();
32770 }
32771
32772 $packages = null;
32773 if ($cacheKey) {
32774 if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) {
32775 $packages = json_decode($this->cache->read($cacheKey), true);
32776 } elseif ($useLastModifiedCheck) {
32777 if ($contents = $this->cache->read($cacheKey)) {
32778 $contents = json_decode($contents, true);
32779 if (isset($contents['last-modified'])) {
32780 $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']);
32781 if (true === $response) {
32782 $packages = $contents;
32783 } elseif ($response) {
32784 $packages = $response;
32785 }
32786 }
32787 }
32788 }
32789 }
32790
32791 if (!$packages) {
32792 try {
32793 $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck);
32794 } catch (TransportException $e) {
32795
32796  if ($e->getStatusCode() === 404 && $this->lazyProvidersUrl) {
32797 $packages = array('packages' => array());
32798 } else {
32799 throw $e;
32800 }
32801 }
32802 }
32803
32804 $loadingPartialPackage = false;
32805 } else {
32806 $packages = array('packages' => array('versions' => $this->partialPackagesByName[$name]));
32807 $loadingPartialPackage = true;
32808 }
32809
32810 $this->providers[$name] = array();
32811 foreach ($packages['packages'] as $versions) {
32812 foreach ($versions as $version) {
32813 if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
32814 continue;
32815 }
32816
32817
32818  if (isset($this->providersByUid[$version['uid']])) {
32819
32820  if (!isset($this->providers[$name][$version['uid']])) {
32821
32822  if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
32823 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
32824 $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
32825 } else {
32826 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
32827 }
32828
32829  if (isset($this->providersByUid[$version['uid'].'-root'])) {
32830 $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
32831 }
32832 }
32833 } else {
32834 if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
32835 continue;
32836 }
32837
32838
32839  $package = $this->createPackage($version, 'Composer\Package\CompletePackage');
32840 $package->setRepository($this);
32841
32842 if ($package instanceof AliasPackage) {
32843 $aliased = $package->getAliasOf();
32844 $aliased->setRepository($this);
32845
32846 $this->providers[$name][$version['uid']] = $aliased;
32847 $this->providers[$name][$version['uid'].'-alias'] = $package;
32848
32849
32850  $this->providersByUid[$version['uid']] = $package;
32851 } else {
32852 $this->providers[$name][$version['uid']] = $package;
32853 $this->providersByUid[$version['uid']] = $package;
32854 }
32855
32856
32857  unset($rootAliasData);
32858
32859 if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
32860 $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
32861 } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
32862 $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
32863 }
32864
32865 if (isset($rootAliasData)) {
32866 $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
32867 $alias->setRepository($this);
32868
32869 $this->providers[$name][$version['uid'].'-root'] = $alias;
32870 $this->providersByUid[$version['uid'].'-root'] = $alias;
32871 }
32872 }
32873 }
32874 }
32875
32876 $result = $this->providers[$name];
32877
32878
32879  
32880  if ($bypassFilters) {
32881 foreach ($this->providers[$name] as $uid => $provider) {
32882 unset($this->providersByUid[$uid]);
32883 }
32884 unset($this->providers[$name]);
32885 }
32886
32887 return $result;
32888 }
32889
32890
32891
32892
32893 protected function initialize()
32894 {
32895 parent::initialize();
32896
32897 $repoData = $this->loadDataFromServer();
32898
32899 foreach ($repoData as $package) {
32900 $this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
32901 }
32902 }
32903
32904
32905
32906
32907
32908
32909 public function addPackage(PackageInterface $package)
32910 {
32911 parent::addPackage($package);
32912 $this->configurePackageTransportOptions($package);
32913 }
32914
32915 protected function loadRootServerFile()
32916 {
32917 if (null !== $this->rootData) {
32918 return $this->rootData;
32919 }
32920
32921 if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
32922 throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
32923 }
32924
32925 $jsonUrlParts = parse_url($this->url);
32926
32927 if (isset($jsonUrlParts['path']) && false !== strpos($jsonUrlParts['path'], '.json')) {
32928 $jsonUrl = $this->url;
32929 } else {
32930 $jsonUrl = $this->url . '/packages.json';
32931 }
32932
32933 $data = $this->fetchFile($jsonUrl, 'packages.json');
32934
32935 if (!empty($data['notify-batch'])) {
32936 $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
32937 } elseif (!empty($data['notify'])) {
32938 $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
32939 }
32940
32941 if (!empty($data['search'])) {
32942 $this->searchUrl = $this->canonicalizeUrl($data['search']);
32943 }
32944
32945 if (!empty($data['mirrors'])) {
32946 foreach ($data['mirrors'] as $mirror) {
32947 if (!empty($mirror['git-url'])) {
32948 $this->sourceMirrors['git'][] = array('url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred']));
32949 }
32950 if (!empty($mirror['hg-url'])) {
32951 $this->sourceMirrors['hg'][] = array('url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred']));
32952 }
32953 if (!empty($mirror['dist-url'])) {
32954 $this->distMirrors[] = array(
32955 'url' => $this->canonicalizeUrl($mirror['dist-url']),
32956 'preferred' => !empty($mirror['preferred']),
32957 );
32958 }
32959 }
32960 }
32961
32962 if (!empty($data['providers-lazy-url'])) {
32963 $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
32964 $this->hasProviders = true;
32965
32966 $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
32967 }
32968
32969 if ($this->allowSslDowngrade) {
32970 $this->url = str_replace('https://', 'http://', $this->url);
32971 $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
32972 }
32973
32974 if (!empty($data['providers-url'])) {
32975 $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
32976 $this->hasProviders = true;
32977 }
32978
32979 if (!empty($data['providers']) || !empty($data['providers-includes'])) {
32980 $this->hasProviders = true;
32981 }
32982
32983
32984  if (preg_match('{^https?://repo\.packagist\.org/?$}i', $this->url) && !empty($this->repoConfig['force-lazy-providers'])) {
32985 $this->url = 'https://repo.packagist.org';
32986 $this->baseUrl = 'https://repo.packagist.org';
32987 $this->lazyProvidersUrl = $this->canonicalizeUrl('https://repo.packagist.org/p/%package%.json');
32988 $this->providersUrl = null;
32989 } elseif (!empty($this->repoConfig['force-lazy-providers'])) {
32990 $this->lazyProvidersUrl = $this->canonicalizeUrl('/p/%package%.json');
32991 $this->providersUrl = null;
32992 }
32993
32994 return $this->rootData = $data;
32995 }
32996
32997 protected function canonicalizeUrl($url)
32998 {
32999 if ('/' === $url[0]) {
33000 return preg_replace('{(https?://[^/]+).*}i', '$1' . $url, $this->url);
33001 }
33002
33003 return $url;
33004 }
33005
33006 protected function loadDataFromServer()
33007 {
33008 $data = $this->loadRootServerFile();
33009
33010 return $this->loadIncludes($data);
33011 }
33012
33013 protected function loadProviderListings($data)
33014 {
33015 if (isset($data['providers'])) {
33016 if (!is_array($this->providerListing)) {
33017 $this->providerListing = array();
33018 }
33019 $this->providerListing = array_merge($this->providerListing, $data['providers']);
33020 }
33021
33022 if ($this->providersUrl && isset($data['provider-includes'])) {
33023 $includes = $data['provider-includes'];
33024 foreach ($includes as $include => $metadata) {
33025 $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
33026 $cacheKey = str_replace(array('%hash%','$'), '', $include);
33027 if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
33028 $includedData = json_decode($this->cache->read($cacheKey), true);
33029 } else {
33030 $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
33031 }
33032
33033 $this->loadProviderListings($includedData);
33034 }
33035 }
33036 }
33037
33038 protected function loadIncludes($data)
33039 {
33040 $packages = array();
33041
33042
33043  if (!isset($data['packages']) && !isset($data['includes'])) {
33044 foreach ($data as $pkg) {
33045 foreach ($pkg['versions'] as $metadata) {
33046 $packages[] = $metadata;
33047 }
33048 }
33049
33050 return $packages;
33051 }
33052
33053 if (isset($data['packages'])) {
33054 foreach ($data['packages'] as $package => $versions) {
33055 foreach ($versions as $version => $metadata) {
33056 $packages[] = $metadata;
33057 }
33058 }
33059 }
33060
33061 if (isset($data['includes'])) {
33062 foreach ($data['includes'] as $include => $metadata) {
33063 if ($this->cache->sha1($include) === $metadata['sha1']) {
33064 $includedData = json_decode($this->cache->read($include), true);
33065 } else {
33066 $includedData = $this->fetchFile($include);
33067 }
33068 $packages = array_merge($packages, $this->loadIncludes($includedData));
33069 }
33070 }
33071
33072 return $packages;
33073 }
33074
33075 protected function createPackage(array $data, $class = 'Composer\Package\CompletePackage')
33076 {
33077 try {
33078 if (!isset($data['notification-url'])) {
33079 $data['notification-url'] = $this->notifyUrl;
33080 }
33081
33082 $package = $this->loader->load($data, $class);
33083 if (isset($this->sourceMirrors[$package->getSourceType()])) {
33084 $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
33085 }
33086 $package->setDistMirrors($this->distMirrors);
33087 $this->configurePackageTransportOptions($package);
33088
33089 return $package;
33090 } catch (\Exception $e) {
33091 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);
33092 }
33093 }
33094
33095 protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)
33096 {
33097 if (null === $cacheKey) {
33098 $cacheKey = $filename;
33099 $filename = $this->baseUrl.'/'.$filename;
33100 }
33101
33102
33103  if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) {
33104 $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
33105 }
33106
33107 $retries = 3;
33108 while ($retries--) {
33109 try {
33110 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
33111 if ($this->eventDispatcher) {
33112 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
33113 }
33114
33115 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
33116 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
33117
33118 $json = $rfs->getContents($hostname, $filename, false);
33119 if ($sha256 && $sha256 !== hash('sha256', $json)) {
33120
33121  if ($this->allowSslDowngrade) {
33122 $this->url = str_replace('http://', 'https://', $this->url);
33123 $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
33124 $filename = str_replace('http://', 'https://', $filename);
33125 }
33126
33127 if ($retries) {
33128 usleep(100000);
33129
33130 continue;
33131 }
33132
33133
33134  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.');
33135 }
33136
33137 $data = JsonFile::parseJson($json, $filename);
33138 if (!empty($data['warning'])) {
33139 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
33140 }
33141 if (!empty($data['info'])) {
33142 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
33143 }
33144
33145 if ($cacheKey) {
33146 if ($storeLastModifiedTime) {
33147 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
33148 if ($lastModifiedDate) {
33149 $data['last-modified'] = $lastModifiedDate;
33150 $json = json_encode($data);
33151 }
33152 }
33153 $this->cache->write($cacheKey, $json);
33154 }
33155
33156 break;
33157 } catch (\Exception $e) {
33158 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
33159 throw $e;
33160 }
33161
33162 if ($retries) {
33163 usleep(100000);
33164 continue;
33165 }
33166
33167 if ($e instanceof RepositorySecurityException) {
33168 throw $e;
33169 }
33170
33171 if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
33172 if (!$this->degradedMode) {
33173 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
33174 $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>');
33175 }
33176 $this->degradedMode = true;
33177 $data = JsonFile::parseJson($contents, $this->cache->getRoot().$cacheKey);
33178
33179 break;
33180 }
33181
33182 throw $e;
33183 }
33184 }
33185
33186 return $data;
33187 }
33188
33189 protected function fetchFileIfLastModified($filename, $cacheKey, $lastModifiedTime)
33190 {
33191 $retries = 3;
33192 while ($retries--) {
33193 try {
33194 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
33195 if ($this->eventDispatcher) {
33196 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
33197 }
33198
33199 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
33200 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
33201 $options = array('http' => array('header' => array('If-Modified-Since: '.$lastModifiedTime)));
33202 $json = $rfs->getContents($hostname, $filename, false, $options);
33203 if ($json === '' && $rfs->findStatusCode($rfs->getLastHeaders()) === 304) {
33204 return true;
33205 }
33206
33207 $data = JsonFile::parseJson($json, $filename);
33208 if (!empty($data['warning'])) {
33209 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
33210 }
33211 if (!empty($data['info'])) {
33212 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
33213 }
33214
33215 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
33216 if ($lastModifiedDate) {
33217 $data['last-modified'] = $lastModifiedDate;
33218 $json = json_encode($data);
33219 }
33220 $this->cache->write($cacheKey, $json);
33221
33222 return $data;
33223 } catch (\Exception $e) {
33224 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
33225 throw $e;
33226 }
33227
33228 if ($retries) {
33229 usleep(100000);
33230 continue;
33231 }
33232
33233 if (!$this->degradedMode) {
33234 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
33235 $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>');
33236 }
33237 $this->degradedMode = true;
33238
33239 return true;
33240 }
33241 }
33242 }
33243
33244
33245
33246
33247
33248
33249 private function initializePartialPackages()
33250 {
33251 $rootData = $this->loadRootServerFile();
33252
33253 $this->partialPackagesByName = array();
33254 foreach ($rootData['packages'] as $package => $versions) {
33255 $package = strtolower($package);
33256 foreach ($versions as $version) {
33257 $this->partialPackagesByName[$package][] = $version;
33258 if (!empty($version['provide']) && is_array($version['provide'])) {
33259 foreach ($version['provide'] as $provided => $providedVersion) {
33260 $this->partialPackagesByName[strtolower($provided)][] = $version;
33261 }
33262 }
33263 if (!empty($version['replace']) && is_array($version['replace'])) {
33264 foreach ($version['replace'] as $provided => $providedVersion) {
33265 $this->partialPackagesByName[strtolower($provided)][] = $version;
33266 }
33267 }
33268 }
33269 }
33270
33271
33272  $this->rootData = true;
33273 }
33274 }
33275 <?php
33276
33277
33278
33279
33280
33281
33282
33283
33284
33285
33286
33287 namespace Composer\Repository;
33288
33289 use Composer\Package\PackageInterface;
33290
33291
33292
33293
33294
33295
33296 class CompositeRepository extends BaseRepository
33297 {
33298
33299
33300
33301
33302 private $repositories;
33303
33304
33305
33306
33307
33308 public function __construct(array $repositories)
33309 {
33310 $this->repositories = array();
33311 foreach ($repositories as $repo) {
33312 $this->addRepository($repo);
33313 }
33314 }
33315
33316
33317
33318
33319
33320
33321 public function getRepositories()
33322 {
33323 return $this->repositories;
33324 }
33325
33326
33327
33328
33329 public function hasPackage(PackageInterface $package)
33330 {
33331 foreach ($this->repositories as $repository) {
33332
33333 if ($repository->hasPackage($package)) {
33334 return true;
33335 }
33336 }
33337
33338 return false;
33339 }
33340
33341
33342
33343
33344 public function findPackage($name, $constraint)
33345 {
33346 foreach ($this->repositories as $repository) {
33347
33348 $package = $repository->findPackage($name, $constraint);
33349 if (null !== $package) {
33350 return $package;
33351 }
33352 }
33353
33354 return null;
33355 }
33356
33357
33358
33359
33360 public function findPackages($name, $constraint = null)
33361 {
33362 $packages = array();
33363 foreach ($this->repositories as $repository) {
33364
33365 $packages[] = $repository->findPackages($name, $constraint);
33366 }
33367
33368 return $packages ? call_user_func_array('array_merge', $packages) : array();
33369 }
33370
33371
33372
33373
33374 public function search($query, $mode = 0, $type = null)
33375 {
33376 $matches = array();
33377 foreach ($this->repositories as $repository) {
33378
33379 $matches[] = $repository->search($query, $mode, $type);
33380 }
33381
33382 return $matches ? call_user_func_array('array_merge', $matches) : array();
33383 }
33384
33385
33386
33387
33388 public function getPackages()
33389 {
33390 $packages = array();
33391 foreach ($this->repositories as $repository) {
33392
33393 $packages[] = $repository->getPackages();
33394 }
33395
33396 return $packages ? call_user_func_array('array_merge', $packages) : array();
33397 }
33398
33399
33400
33401
33402 public function removePackage(PackageInterface $package)
33403 {
33404 foreach ($this->repositories as $repository) {
33405
33406 $repository->removePackage($package);
33407 }
33408 }
33409
33410
33411
33412
33413 public function count()
33414 {
33415 $total = 0;
33416 foreach ($this->repositories as $repository) {
33417
33418 $total += $repository->count();
33419 }
33420
33421 return $total;
33422 }
33423
33424
33425
33426
33427
33428 public function addRepository(RepositoryInterface $repository)
33429 {
33430 if ($repository instanceof self) {
33431 foreach ($repository->getRepositories() as $repo) {
33432 $this->addRepository($repo);
33433 }
33434 } else {
33435 $this->repositories[] = $repository;
33436 }
33437 }
33438 }
33439 <?php
33440
33441
33442
33443
33444
33445
33446
33447
33448
33449
33450
33451 namespace Composer\Repository;
33452
33453
33454
33455
33456
33457
33458 interface ConfigurableRepositoryInterface
33459 {
33460 public function getRepoConfig();
33461 }
33462 <?php
33463
33464
33465
33466
33467
33468
33469
33470
33471
33472
33473
33474 namespace Composer\Repository;
33475
33476 use Composer\Json\JsonFile;
33477 use Composer\Package\Loader\ArrayLoader;
33478 use Composer\Package\Dumper\ArrayDumper;
33479
33480
33481
33482
33483
33484
33485
33486 class FilesystemRepository extends WritableArrayRepository
33487 {
33488 private $file;
33489
33490
33491
33492
33493
33494
33495 public function __construct(JsonFile $repositoryFile)
33496 {
33497 parent::__construct();
33498 $this->file = $repositoryFile;
33499 }
33500
33501
33502
33503
33504 protected function initialize()
33505 {
33506 parent::initialize();
33507
33508 if (!$this->file->exists()) {
33509 return;
33510 }
33511
33512 try {
33513 $packages = $this->file->read();
33514
33515 if (!is_array($packages)) {
33516 throw new \UnexpectedValueException('Could not parse package list from the repository');
33517 }
33518 } catch (\Exception $e) {
33519 throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.get_class($e).'] '.$e->getMessage());
33520 }
33521
33522 $loader = new ArrayLoader(null, true);
33523 foreach ($packages as $packageData) {
33524 $package = $loader->load($packageData);
33525 $this->addPackage($package);
33526 }
33527 }
33528
33529 public function reload()
33530 {
33531 $this->packages = null;
33532 $this->initialize();
33533 }
33534
33535
33536
33537
33538 public function write()
33539 {
33540 $data = array();
33541 $dumper = new ArrayDumper();
33542
33543 foreach ($this->getCanonicalPackages() as $package) {
33544 $data[] = $dumper->dump($package);
33545 }
33546
33547 usort($data, function ($a, $b) {
33548 return strcmp($a['name'], $b['name']);
33549 });
33550
33551 $this->file->write($data);
33552 }
33553 }
33554 <?php
33555
33556
33557
33558
33559
33560
33561
33562
33563
33564
33565
33566 namespace Composer\Repository;
33567
33568
33569
33570
33571
33572
33573
33574
33575 class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
33576 {
33577 }
33578 <?php
33579
33580
33581
33582
33583
33584
33585
33586
33587
33588
33589
33590 namespace Composer\Repository;
33591
33592
33593
33594
33595
33596
33597 class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
33598 {
33599 }
33600 <?php
33601
33602
33603
33604
33605
33606
33607
33608
33609
33610
33611
33612 namespace Composer\Repository;
33613
33614
33615
33616
33617
33618
33619
33620
33621 interface InstalledRepositoryInterface extends WritableRepositoryInterface
33622 {
33623 }
33624 <?php
33625
33626
33627
33628
33629
33630
33631
33632
33633
33634
33635
33636 namespace Composer\Repository;
33637
33638
33639
33640
33641
33642
33643 class InvalidRepositoryException extends \Exception
33644 {
33645 }
33646 <?php
33647
33648
33649
33650
33651
33652
33653
33654
33655
33656
33657
33658 namespace Composer\Repository;
33659
33660 use Composer\Package\Loader\ArrayLoader;
33661 use Composer\Package\Loader\ValidatingArrayLoader;
33662
33663
33664
33665
33666
33667
33668 class PackageRepository extends ArrayRepository
33669 {
33670 private $config;
33671
33672
33673
33674
33675
33676
33677 public function __construct(array $config)
33678 {
33679 parent::__construct();
33680 $this->config = $config['package'];
33681
33682
33683  if (!is_numeric(key($this->config))) {
33684 $this->config = array($this->config);
33685 }
33686 }
33687
33688
33689
33690
33691 protected function initialize()
33692 {
33693 parent::initialize();
33694
33695 $loader = new ValidatingArrayLoader(new ArrayLoader(null, true), false);
33696 foreach ($this->config as $package) {
33697 try {
33698 $package = $loader->load($package);
33699 } catch (\Exception $e) {
33700 throw new InvalidRepositoryException('A repository of type "package" contains an invalid package definition: '.$e->getMessage()."\n\nInvalid package definition:\n".json_encode($package));
33701 }
33702
33703 $this->addPackage($package);
33704 }
33705 }
33706 }
33707 <?php
33708
33709
33710
33711
33712
33713
33714
33715
33716
33717
33718
33719 namespace Composer\Repository;
33720
33721 use Composer\Config;
33722 use Composer\IO\IOInterface;
33723 use Composer\Json\JsonFile;
33724 use Composer\Package\Loader\ArrayLoader;
33725 use Composer\Package\Version\VersionGuesser;
33726 use Composer\Package\Version\VersionParser;
33727 use Composer\Util\Platform;
33728 use Composer\Util\ProcessExecutor;
33729
33730
33731
33732
33733
33734
33735
33736
33737
33738
33739
33740
33741
33742
33743
33744
33745
33746
33747
33748
33749
33750
33751
33752
33753
33754
33755
33756
33757
33758
33759
33760
33761
33762
33763
33764
33765 class PathRepository extends ArrayRepository implements ConfigurableRepositoryInterface
33766 {
33767
33768
33769
33770 private $loader;
33771
33772
33773
33774
33775 private $versionGuesser;
33776
33777
33778
33779
33780 private $url;
33781
33782
33783
33784
33785 private $repoConfig;
33786
33787
33788
33789
33790 private $process;
33791
33792
33793
33794
33795 private $options;
33796
33797
33798
33799
33800
33801
33802
33803
33804 public function __construct(array $repoConfig, IOInterface $io, Config $config)
33805 {
33806 if (!isset($repoConfig['url'])) {
33807 throw new \RuntimeException('You must specify the `url` configuration for the path repository');
33808 }
33809
33810 $this->loader = new ArrayLoader(null, true);
33811 $this->url = Platform::expandPath($repoConfig['url']);
33812 $this->process = new ProcessExecutor($io);
33813 $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
33814 $this->repoConfig = $repoConfig;
33815 $this->options = isset($repoConfig['options']) ? $repoConfig['options'] : array();
33816
33817 parent::__construct();
33818 }
33819
33820 public function getRepoConfig()
33821 {
33822 return $this->repoConfig;
33823 }
33824
33825
33826
33827
33828
33829
33830 protected function initialize()
33831 {
33832 parent::initialize();
33833
33834 foreach ($this->getUrlMatches() as $url) {
33835 $path = realpath($url) . DIRECTORY_SEPARATOR;
33836 $composerFilePath = $path.'composer.json';
33837
33838 if (!file_exists($composerFilePath)) {
33839 continue;
33840 }
33841
33842 $json = file_get_contents($composerFilePath);
33843 $package = JsonFile::parseJson($json, $composerFilePath);
33844 $package['dist'] = array(
33845 'type' => 'path',
33846 'url' => $url,
33847 'reference' => sha1($json . serialize($this->options)),
33848 );
33849 $package['transport-options'] = $this->options;
33850
33851
33852  if (!isset($package['version']) && ($rootVersion = getenv('COMPOSER_ROOT_VERSION'))) {
33853 if (
33854 0 === $this->process->execute('git rev-parse HEAD', $ref1, $path)
33855 && 0 === $this->process->execute('git rev-parse HEAD', $ref2)
33856 && $ref1 === $ref2
33857 ) {
33858 $package['version'] = $rootVersion;
33859 }
33860 }
33861
33862 if (!isset($package['version'])) {
33863 $versionData = $this->versionGuesser->guessVersion($package, $path);
33864 $package['version'] = $versionData['pretty_version'] ?: 'dev-master';
33865 }
33866
33867 $output = '';
33868 if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
33869 $package['dist']['reference'] = trim($output);
33870 }
33871 $package = $this->loader->load($package);
33872 $this->addPackage($package);
33873 }
33874 }
33875
33876
33877
33878
33879
33880
33881 private function getUrlMatches()
33882 {
33883 $flags = GLOB_MARK | GLOB_ONLYDIR;
33884
33885 if (defined('GLOB_BRACE')) {
33886 $flags |= GLOB_BRACE;
33887 } elseif (strpos($this->url, '{') !== false || strpos($this->url, '}') !== false) {
33888 throw new \RuntimeException('The operating system does not support GLOB_BRACE which is required for the url '. $this->url);
33889 }
33890
33891
33892  return array_map(function ($val) {
33893 return rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $val), '/');
33894 }, glob($this->url, $flags));
33895 }
33896 }
33897 <?php
33898
33899
33900
33901
33902
33903
33904
33905
33906
33907
33908
33909 namespace Composer\Repository\Pear;
33910
33911 use Composer\Util\RemoteFilesystem;
33912
33913
33914
33915
33916
33917
33918
33919
33920 abstract class BaseChannelReader
33921 {
33922
33923
33924
33925 const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
33926 const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
33927 const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
33928 const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
33929 const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
33930 const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
33931
33932
33933 private $rfs;
33934
33935 protected function __construct(RemoteFilesystem $rfs)
33936 {
33937 $this->rfs = $rfs;
33938 }
33939
33940
33941
33942
33943
33944
33945
33946
33947
33948 protected function requestContent($origin, $path)
33949 {
33950 $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
33951 $content = $this->rfs->getContents($origin, $url, false);
33952 if (!$content) {
33953 throw new \UnexpectedValueException('The PEAR channel at ' . $url . ' did not respond.');
33954 }
33955
33956 return str_replace('http://pear.php.net/rest/', 'https://pear.php.net/rest/', $content);
33957 }
33958
33959
33960
33961
33962
33963
33964
33965
33966
33967 protected function requestXml($origin, $path)
33968 {
33969
33970  $xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
33971
33972 if (false === $xml) {
33973 throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
33974 }
33975
33976 return $xml;
33977 }
33978 }
33979 <?php
33980
33981
33982
33983
33984
33985
33986
33987
33988
33989
33990
33991 namespace Composer\Repository\Pear;
33992
33993
33994
33995
33996
33997
33998 class ChannelInfo
33999 {
34000 private $name;
34001 private $alias;
34002 private $packages;
34003
34004
34005
34006
34007
34008
34009 public function __construct($name, $alias, array $packages)
34010 {
34011 $this->name = $name;
34012 $this->alias = $alias;
34013 $this->packages = $packages;
34014 }
34015
34016
34017
34018
34019
34020
34021 public function getName()
34022 {
34023 return $this->name;
34024 }
34025
34026
34027
34028
34029
34030
34031 public function getAlias()
34032 {
34033 return $this->alias;
34034 }
34035
34036
34037
34038
34039
34040
34041 public function getPackages()
34042 {
34043 return $this->packages;
34044 }
34045 }
34046 <?php
34047
34048
34049
34050
34051
34052
34053
34054
34055
34056
34057
34058 namespace Composer\Repository\Pear;
34059
34060 use Composer\Util\RemoteFilesystem;
34061
34062
34063
34064
34065
34066
34067
34068
34069 class ChannelReader extends BaseChannelReader
34070 {
34071
34072 private $readerMap;
34073
34074 public function __construct(RemoteFilesystem $rfs)
34075 {
34076 parent::__construct($rfs);
34077
34078 $rest10reader = new ChannelRest10Reader($rfs);
34079 $rest11reader = new ChannelRest11Reader($rfs);
34080
34081 $this->readerMap = array(
34082 'REST1.3' => $rest11reader,
34083 'REST1.2' => $rest11reader,
34084 'REST1.1' => $rest11reader,
34085 'REST1.0' => $rest10reader,
34086 );
34087 }
34088
34089
34090
34091
34092
34093
34094
34095
34096 public function read($url)
34097 {
34098 $xml = $this->requestXml($url, "/channel.xml");
34099
34100 $channelName = (string) $xml->name;
34101 $channelAlias = (string) $xml->suggestedalias;
34102
34103 $supportedVersions = array_keys($this->readerMap);
34104 $selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
34105 if (!$selectedRestVersion) {
34106 throw new \UnexpectedValueException(sprintf('PEAR repository %s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
34107 }
34108
34109 $reader = $this->readerMap[$selectedRestVersion['version']];
34110 $packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
34111
34112 return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
34113 }
34114
34115
34116
34117
34118
34119
34120
34121
34122 private function selectRestVersion($channelXml, $supportedVersions)
34123 {
34124 $channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
34125
34126 foreach ($supportedVersions as $version) {
34127 $xpathTest = "ns:servers/ns:*/ns:rest/ns:baseurl[@type='{$version}']";
34128 $testResult = $channelXml->xpath($xpathTest);
34129
34130 foreach ($testResult as $result) {
34131
34132  $result = (string) $result;
34133 if (preg_match('{^https://}i', $result)) {
34134 return array('version' => $version, 'baseUrl' => $result);
34135 }
34136 }
34137
34138
34139  if (count($testResult) > 0) {
34140 return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
34141 }
34142 }
34143
34144 return null;
34145 }
34146 }
34147 <?php
34148
34149
34150
34151
34152
34153
34154
34155
34156
34157
34158
34159 namespace Composer\Repository\Pear;
34160
34161 use Composer\Downloader\TransportException;
34162
34163
34164
34165
34166
34167
34168
34169
34170
34171
34172
34173
34174 class ChannelRest10Reader extends BaseChannelReader
34175 {
34176 private $dependencyReader;
34177
34178 public function __construct($rfs)
34179 {
34180 parent::__construct($rfs);
34181
34182 $this->dependencyReader = new PackageDependencyParser();
34183 }
34184
34185
34186
34187
34188
34189
34190
34191
34192 public function read($baseUrl)
34193 {
34194 return $this->readPackages($baseUrl);
34195 }
34196
34197
34198
34199
34200
34201
34202
34203
34204 private function readPackages($baseUrl)
34205 {
34206 $result = array();
34207
34208 $xmlPath = '/p/packages.xml';
34209 $xml = $this->requestXml($baseUrl, $xmlPath);
34210 $xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
34211 foreach ($xml->xpath('ns:p') as $node) {
34212 $packageName = (string) $node;
34213 $packageInfo = $this->readPackage($baseUrl, $packageName);
34214 $result[] = $packageInfo;
34215 }
34216
34217 return $result;
34218 }
34219
34220
34221
34222
34223
34224
34225
34226
34227
34228 private function readPackage($baseUrl, $packageName)
34229 {
34230 $xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
34231 $xml = $this->requestXml($baseUrl, $xmlPath);
34232 $xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
34233
34234 $channelName = (string) $xml->c;
34235 $packageName = (string) $xml->n;
34236 $license = (string) $xml->l;
34237 $shortDescription = (string) $xml->s;
34238 $description = (string) $xml->d;
34239
34240 return new PackageInfo(
34241 $channelName,
34242 $packageName,
34243 $license,
34244 $shortDescription,
34245 $description,
34246 $this->readPackageReleases($baseUrl, $packageName)
34247 );
34248 }
34249
34250
34251
34252
34253
34254
34255
34256
34257
34258
34259 private function readPackageReleases($baseUrl, $packageName)
34260 {
34261 $result = array();
34262
34263 try {
34264 $xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
34265 $xml = $this->requestXml($baseUrl, $xmlPath);
34266 $xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
34267 foreach ($xml->xpath('ns:r') as $node) {
34268 $releaseVersion = (string) $node->v;
34269 $releaseStability = (string) $node->s;
34270
34271 try {
34272 $result[$releaseVersion] = new ReleaseInfo(
34273 $releaseStability,
34274 $this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
34275 );
34276 } catch (TransportException $exception) {
34277 if ($exception->getCode() != 404) {
34278 throw $exception;
34279 }
34280 }
34281 }
34282 } catch (TransportException $exception) {
34283 if ($exception->getCode() != 404) {
34284 throw $exception;
34285 }
34286 }
34287
34288 return $result;
34289 }
34290
34291
34292
34293
34294
34295
34296
34297
34298
34299
34300 private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
34301 {
34302 $dependencyReader = new PackageDependencyParser();
34303
34304 $depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
34305 $content = $this->requestContent($baseUrl, $depthPath);
34306 $dependencyArray = unserialize($content);
34307
34308 return $dependencyReader->buildDependencyInfo($dependencyArray);
34309 }
34310 }
34311 <?php
34312
34313
34314
34315
34316
34317
34318
34319
34320
34321
34322
34323 namespace Composer\Repository\Pear;
34324
34325
34326
34327
34328
34329
34330
34331
34332
34333
34334 class ChannelRest11Reader extends BaseChannelReader
34335 {
34336 private $dependencyReader;
34337
34338 public function __construct($rfs)
34339 {
34340 parent::__construct($rfs);
34341
34342 $this->dependencyReader = new PackageDependencyParser();
34343 }
34344
34345
34346
34347
34348
34349
34350
34351
34352 public function read($baseUrl)
34353 {
34354 return $this->readChannelPackages($baseUrl);
34355 }
34356
34357
34358
34359
34360
34361
34362
34363
34364 private function readChannelPackages($baseUrl)
34365 {
34366 $result = array();
34367
34368 $xml = $this->requestXml($baseUrl, "/c/categories.xml");
34369 $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
34370 foreach ($xml->xpath('ns:c') as $node) {
34371 $categoryName = (string) $node;
34372 $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
34373 $result = array_merge($result, $categoryPackages);
34374 }
34375
34376 return $result;
34377 }
34378
34379
34380
34381
34382
34383
34384
34385
34386
34387 private function readCategoryPackages($baseUrl, $categoryName)
34388 {
34389 $result = array();
34390
34391 $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
34392 $xml = $this->requestXml($baseUrl, $categoryPath);
34393 $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
34394 foreach ($xml->xpath('ns:pi') as $node) {
34395 $packageInfo = $this->parsePackage($node);
34396 $result[] = $packageInfo;
34397 }
34398
34399 return $result;
34400 }
34401
34402
34403
34404
34405
34406
34407
34408 private function parsePackage($packageInfo)
34409 {
34410 $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
34411 $channelName = (string) $packageInfo->p->c;
34412 $packageName = (string) $packageInfo->p->n;
34413 $license = (string) $packageInfo->p->l;
34414 $shortDescription = (string) $packageInfo->p->s;
34415 $description = (string) $packageInfo->p->d;
34416
34417 $dependencies = array();
34418 foreach ($packageInfo->xpath('ns:deps') as $node) {
34419 $dependencyVersion = (string) $node->v;
34420 $dependencyArray = unserialize((string) $node->d);
34421
34422 $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
34423
34424 $dependencies[$dependencyVersion] = $dependencyInfo;
34425 }
34426
34427 $releases = array();
34428 $releasesInfo = $packageInfo->xpath('ns:a/ns:r');
34429 if ($releasesInfo) {
34430 foreach ($releasesInfo as $node) {
34431 $releaseVersion = (string) $node->v;
34432 $releaseStability = (string) $node->s;
34433 $releases[$releaseVersion] = new ReleaseInfo(
34434 $releaseStability,
34435 isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
34436 );
34437 }
34438 }
34439
34440 return new PackageInfo(
34441 $channelName,
34442 $packageName,
34443 $license,
34444 $shortDescription,
34445 $description,
34446 $releases
34447 );
34448 }
34449 }
34450 <?php
34451
34452
34453
34454
34455
34456
34457
34458
34459
34460
34461
34462 namespace Composer\Repository\Pear;
34463
34464
34465
34466
34467
34468
34469 class DependencyConstraint
34470 {
34471 private $type;
34472 private $constraint;
34473 private $channelName;
34474 private $packageName;
34475
34476
34477
34478
34479
34480
34481
34482 public function __construct($type, $constraint, $channelName, $packageName)
34483 {
34484 $this->type = $type;
34485 $this->constraint = $constraint;
34486 $this->channelName = $channelName;
34487 $this->packageName = $packageName;
34488 }
34489
34490 public function getChannelName()
34491 {
34492 return $this->channelName;
34493 }
34494
34495 public function getConstraint()
34496 {
34497 return $this->constraint;
34498 }
34499
34500 public function getPackageName()
34501 {
34502 return $this->packageName;
34503 }
34504
34505 public function getType()
34506 {
34507 return $this->type;
34508 }
34509 }
34510 <?php
34511
34512
34513
34514
34515
34516
34517
34518
34519
34520
34521
34522 namespace Composer\Repository\Pear;
34523
34524
34525
34526
34527
34528
34529 class DependencyInfo
34530 {
34531 private $requires;
34532 private $optionals;
34533
34534
34535
34536
34537
34538 public function __construct($requires, $optionals)
34539 {
34540 $this->requires = $requires;
34541 $this->optionals = $optionals;
34542 }
34543
34544
34545
34546
34547 public function getRequires()
34548 {
34549 return $this->requires;
34550 }
34551
34552
34553
34554
34555 public function getOptionals()
34556 {
34557 return $this->optionals;
34558 }
34559 }
34560 <?php
34561
34562
34563
34564
34565
34566
34567
34568
34569
34570
34571
34572 namespace Composer\Repository\Pear;
34573
34574
34575
34576
34577
34578
34579 class PackageDependencyParser
34580 {
34581
34582
34583
34584
34585
34586
34587 public function buildDependencyInfo($depArray)
34588 {
34589 if (!is_array($depArray)) {
34590 return new DependencyInfo(array(), array());
34591 }
34592 if (!$this->isHash($depArray)) {
34593 return new DependencyInfo($this->buildDependency10Info($depArray), array());
34594 }
34595
34596 return $this->buildDependency20Info($depArray);
34597 }
34598
34599
34600
34601
34602
34603
34604
34605
34606
34607
34608
34609
34610
34611 private function buildDependency10Info($depArray)
34612 {
34613 static $dep10toOperatorMap = array('has' => '==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
34614
34615 $result = array();
34616
34617 foreach ($depArray as $depItem) {
34618 if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
34619
34620  continue;
34621 }
34622
34623 $depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
34624 ? 'optional'
34625 : 'required';
34626 $depType = 'not' == $depItem['rel']
34627 ? 'conflicts'
34628 : $depType;
34629
34630 $depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
34631
34632
34633  $depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
34634 ? '*'
34635 : $dep10toOperatorMap[$depItem['rel']] . $depVersion;
34636
34637 switch ($depItem['type']) {
34638 case 'php':
34639 $depChannelName = 'php';
34640 $depPackageName = '';
34641 break;
34642 case 'pkg':
34643 $depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
34644 $depPackageName = $depItem['name'];
34645 break;
34646 case 'ext':
34647 $depChannelName = 'ext';
34648 $depPackageName = $depItem['name'];
34649 break;
34650 case 'os':
34651 case 'sapi':
34652 $depChannelName = '';
34653 $depPackageName = '';
34654 break;
34655 default:
34656 $depChannelName = '';
34657 $depPackageName = '';
34658 break;
34659 }
34660
34661 if ('' != $depChannelName) {
34662 $result[] = new DependencyConstraint(
34663 $depType,
34664 $depVersionConstraint,
34665 $depChannelName,
34666 $depPackageName
34667 );
34668 }
34669 }
34670
34671 return $result;
34672 }
34673
34674
34675
34676
34677
34678
34679
34680 private function buildDependency20Info($depArray)
34681 {
34682 $result = array();
34683 $optionals = array();
34684 $defaultOptionals = array();
34685 foreach ($depArray as $depType => $depTypeGroup) {
34686 if (!is_array($depTypeGroup)) {
34687 continue;
34688 }
34689 if ('required' == $depType || 'optional' == $depType) {
34690 foreach ($depTypeGroup as $depItemType => $depItem) {
34691 switch ($depItemType) {
34692 case 'php':
34693 $result[] = new DependencyConstraint(
34694 $depType,
34695 $this->parse20VersionConstraint($depItem),
34696 'php',
34697 ''
34698 );
34699 break;
34700 case 'package':
34701 $deps = $this->buildDepPackageConstraints($depItem, $depType);
34702 $result = array_merge($result, $deps);
34703 break;
34704 case 'extension':
34705 $deps = $this->buildDepExtensionConstraints($depItem, $depType);
34706 $result = array_merge($result, $deps);
34707 break;
34708 case 'subpackage':
34709 $deps = $this->buildDepPackageConstraints($depItem, 'replaces');
34710 $defaultOptionals += $deps;
34711 break;
34712 case 'os':
34713 case 'pearinstaller':
34714 break;
34715 default:
34716 break;
34717 }
34718 }
34719 } elseif ('group' == $depType) {
34720 if ($this->isHash($depTypeGroup)) {
34721 $depTypeGroup = array($depTypeGroup);
34722 }
34723
34724 foreach ($depTypeGroup as $depItem) {
34725 $groupName = $depItem['attribs']['name'];
34726 if (!isset($optionals[$groupName])) {
34727 $optionals[$groupName] = array();
34728 }
34729
34730 if (isset($depItem['subpackage'])) {
34731 $optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
34732 } else {
34733 $result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
34734 }
34735 }
34736 }
34737 }
34738
34739 if (count($defaultOptionals) > 0) {
34740 $optionals['*'] = $defaultOptionals;
34741 }
34742
34743 return new DependencyInfo($result, $optionals);
34744 }
34745
34746
34747
34748
34749
34750
34751
34752
34753 private function buildDepExtensionConstraints($depItem, $depType)
34754 {
34755 if ($this->isHash($depItem)) {
34756 $depItem = array($depItem);
34757 }
34758
34759 $result = array();
34760 foreach ($depItem as $subDepItem) {
34761 $depChannelName = 'ext';
34762 $depPackageName = $subDepItem['name'];
34763 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
34764
34765 $result[] = new DependencyConstraint(
34766 $depType,
34767 $depVersionConstraint,
34768 $depChannelName,
34769 $depPackageName
34770 );
34771 }
34772
34773 return $result;
34774 }
34775
34776
34777
34778
34779
34780
34781
34782
34783 private function buildDepPackageConstraints($depItem, $depType)
34784 {
34785 if ($this->isHash($depItem)) {
34786 $depItem = array($depItem);
34787 }
34788
34789 $result = array();
34790 foreach ($depItem as $subDepItem) {
34791 if (!array_key_exists('channel', $subDepItem)) {
34792 $subDepItem['channel'] = $subDepItem['uri'];
34793 }
34794 $depChannelName = $subDepItem['channel'];
34795 $depPackageName = $subDepItem['name'];
34796 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
34797 if (isset($subDepItem['conflicts'])) {
34798 $depType = 'conflicts';
34799 }
34800
34801 $result[] = new DependencyConstraint(
34802 $depType,
34803 $depVersionConstraint,
34804 $depChannelName,
34805 $depPackageName
34806 );
34807 }
34808
34809 return $result;
34810 }
34811
34812
34813
34814
34815
34816
34817
34818 private function parse20VersionConstraint(array $data)
34819 {
34820 static $dep20toOperatorMap = array('has' => '==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
34821
34822 $versions = array();
34823 $values = array_intersect_key($data, $dep20toOperatorMap);
34824 if (0 == count($values)) {
34825 return '*';
34826 }
34827 if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
34828 $versions[] = '>' . $this->parseVersion($values['min']);
34829 } elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
34830 $versions[] = '<' . $this->parseVersion($values['max']);
34831 } else {
34832 foreach ($values as $op => $version) {
34833 if ('exclude' == $op && is_array($version)) {
34834 foreach ($version as $versionPart) {
34835 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
34836 }
34837 } else {
34838 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
34839 }
34840 }
34841 }
34842
34843 return implode(',', $versions);
34844 }
34845
34846
34847
34848
34849
34850
34851
34852 private function parseVersion($version)
34853 {
34854 if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
34855 $version = $matches[1]
34856 .(!empty($matches[2]) ? $matches[2] : '.0')
34857 .(!empty($matches[3]) ? $matches[3] : '.0')
34858 .(!empty($matches[4]) ? $matches[4] : '.0');
34859
34860 return $version;
34861 }
34862
34863 return null;
34864 }
34865
34866
34867
34868
34869
34870
34871
34872 private function isHash(array $array)
34873 {
34874 return !array_key_exists(1, $array) && !array_key_exists(0, $array);
34875 }
34876 }
34877 <?php
34878
34879
34880
34881
34882
34883
34884
34885
34886
34887
34888
34889 namespace Composer\Repository\Pear;
34890
34891
34892
34893
34894
34895
34896 class PackageInfo
34897 {
34898 private $channelName;
34899 private $packageName;
34900 private $license;
34901 private $shortDescription;
34902 private $description;
34903 private $releases;
34904
34905
34906
34907
34908
34909
34910
34911
34912
34913 public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
34914 {
34915 $this->channelName = $channelName;
34916 $this->packageName = $packageName;
34917 $this->license = $license;
34918 $this->shortDescription = $shortDescription;
34919 $this->description = $description;
34920 $this->releases = $releases;
34921 }
34922
34923
34924
34925
34926 public function getChannelName()
34927 {
34928 return $this->channelName;
34929 }
34930
34931
34932
34933
34934 public function getPackageName()
34935 {
34936 return $this->packageName;
34937 }
34938
34939
34940
34941
34942 public function getDescription()
34943 {
34944 return $this->description;
34945 }
34946
34947
34948
34949
34950 public function getShortDescription()
34951 {
34952 return $this->shortDescription;
34953 }
34954
34955
34956
34957
34958 public function getLicense()
34959 {
34960 return $this->license;
34961 }
34962
34963
34964
34965
34966 public function getReleases()
34967 {
34968 return $this->releases;
34969 }
34970 }
34971 <?php
34972
34973
34974
34975
34976
34977
34978
34979
34980
34981
34982
34983 namespace Composer\Repository\Pear;
34984
34985
34986
34987
34988
34989
34990 class ReleaseInfo
34991 {
34992 private $stability;
34993 private $dependencyInfo;
34994
34995
34996
34997
34998
34999 public function __construct($stability, $dependencyInfo)
35000 {
35001 $this->stability = $stability;
35002 $this->dependencyInfo = $dependencyInfo;
35003 }
35004
35005
35006
35007
35008 public function getDependencyInfo()
35009 {
35010 return $this->dependencyInfo;
35011 }
35012
35013
35014
35015
35016 public function getStability()
35017 {
35018 return $this->stability;
35019 }
35020 }
35021 <?php
35022
35023
35024
35025
35026
35027
35028
35029
35030
35031
35032
35033 namespace Composer\Repository;
35034
35035 use Composer\IO\IOInterface;
35036 use Composer\Semver\VersionParser as SemverVersionParser;
35037 use Composer\Package\Version\VersionParser;
35038 use Composer\Repository\Pear\ChannelReader;
35039 use Composer\Package\CompletePackage;
35040 use Composer\Repository\Pear\ChannelInfo;
35041 use Composer\EventDispatcher\EventDispatcher;
35042 use Composer\Package\Link;
35043 use Composer\Semver\Constraint\Constraint;
35044 use Composer\Util\RemoteFilesystem;
35045 use Composer\Config;
35046 use Composer\Factory;
35047
35048
35049
35050
35051
35052
35053
35054
35055
35056
35057 class PearRepository extends ArrayRepository implements ConfigurableRepositoryInterface
35058 {
35059 private $url;
35060 private $io;
35061 private $rfs;
35062 private $versionParser;
35063 private $repoConfig;
35064
35065
35066
35067
35068 private $vendorAlias;
35069
35070 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null)
35071 {
35072 parent::__construct();
35073 if (!preg_match('{^https?://}', $repoConfig['url'])) {
35074 $repoConfig['url'] = 'http://'.$repoConfig['url'];
35075 }
35076
35077 $urlBits = parse_url($repoConfig['url']);
35078 if (empty($urlBits['scheme']) || empty($urlBits['host'])) {
35079 throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']);
35080 }
35081
35082 $this->url = rtrim($repoConfig['url'], '/');
35083 $this->io = $io;
35084 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
35085 $this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
35086 $this->versionParser = new VersionParser();
35087 $this->repoConfig = $repoConfig;
35088 }
35089
35090 public function getRepoConfig()
35091 {
35092 return $this->repoConfig;
35093 }
35094
35095 protected function initialize()
35096 {
35097 parent::initialize();
35098
35099 $this->io->writeError('Initializing PEAR repository '.$this->url);
35100
35101 $reader = new ChannelReader($this->rfs);
35102 try {
35103 $channelInfo = $reader->read($this->url);
35104 } catch (\Exception $e) {
35105 $this->io->writeError('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
35106
35107 return;
35108 }
35109 $packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
35110 foreach ($packages as $package) {
35111 $this->addPackage($package);
35112 }
35113 }
35114
35115
35116
35117
35118
35119
35120
35121
35122 private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
35123 {
35124 $result = array();
35125 foreach ($channelInfo->getPackages() as $packageDefinition) {
35126 foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
35127 try {
35128 $normalizedVersion = $versionParser->normalize($version);
35129 } catch (\UnexpectedValueException $e) {
35130 $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage(), true, IOInterface::VERBOSE);
35131 continue;
35132 }
35133
35134 $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
35135
35136
35137  
35138  $urlBits = parse_url($this->url);
35139 $scheme = (isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl')) ? 'https' : 'http';
35140 $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
35141
35142 $requires = array();
35143 $suggests = array();
35144 $conflicts = array();
35145 $replaces = array();
35146
35147
35148  
35149  if ($channelInfo->getName() == $packageDefinition->getChannelName()) {
35150 $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
35151 $aliasConstraint = new Constraint('==', $normalizedVersion);
35152 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
35153 }
35154
35155
35156  if (!empty($this->vendorAlias)
35157 && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())
35158 ) {
35159 $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
35160 $aliasConstraint = new Constraint('==', $normalizedVersion);
35161 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
35162 }
35163
35164 foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) {
35165 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
35166 $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
35167 $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
35168 switch ($dependencyConstraint->getType()) {
35169 case 'required':
35170 $requires[] = $link;
35171 break;
35172 case 'conflicts':
35173 $conflicts[] = $link;
35174 break;
35175 case 'replaces':
35176 $replaces[] = $link;
35177 break;
35178 }
35179 }
35180
35181 foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
35182 foreach ($dependencyConstraints as $dependencyConstraint) {
35183 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
35184 $suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
35185 }
35186 }
35187
35188 $package = new CompletePackage($composerPackageName, $normalizedVersion, $version);
35189 $package->setType('pear-library');
35190 $package->setDescription($packageDefinition->getDescription());
35191 $package->setLicense(array($packageDefinition->getLicense()));
35192 $package->setDistType('file');
35193 $package->setDistUrl($distUrl);
35194 $package->setAutoload(array('classmap' => array('')));
35195 $package->setIncludePaths(array('/'));
35196 $package->setRequires($requires);
35197 $package->setConflicts($conflicts);
35198 $package->setSuggests($suggests);
35199 $package->setReplaces($replaces);
35200 $result[] = $package;
35201 }
35202 }
35203
35204 return $result;
35205 }
35206
35207 private function buildComposerPackageName($channelName, $packageName)
35208 {
35209 if ('php' === $channelName) {
35210 return "php";
35211 }
35212 if ('ext' === $channelName) {
35213 return "ext-{$packageName}";
35214 }
35215
35216 return "pear-{$channelName}/{$packageName}";
35217 }
35218 }
35219 <?php
35220
35221
35222
35223
35224
35225
35226
35227
35228
35229
35230
35231 namespace Composer\Repository;
35232
35233 use Composer\Package\CompletePackage;
35234 use Composer\Package\PackageInterface;
35235 use Composer\Package\Version\VersionParser;
35236 use Composer\Plugin\PluginInterface;
35237 use Composer\Util\Silencer;
35238 use Composer\XdebugHandler\XdebugHandler;
35239
35240
35241
35242
35243 class PlatformRepository extends ArrayRepository
35244 {
35245 const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[^/ ]+)$}i';
35246
35247 private $versionParser;
35248
35249
35250
35251
35252
35253
35254
35255
35256 private $overrides = array();
35257
35258 public function __construct(array $packages = array(), array $overrides = array())
35259 {
35260 foreach ($overrides as $name => $version) {
35261 $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
35262 }
35263 parent::__construct($packages);
35264 }
35265
35266 protected function initialize()
35267 {
35268 parent::initialize();
35269
35270 $this->versionParser = new VersionParser();
35271
35272
35273  
35274  foreach ($this->overrides as $override) {
35275
35276  if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
35277 throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
35278 }
35279
35280 $this->addOverriddenPackage($override);
35281 }
35282
35283 $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
35284 $version = $this->versionParser->normalize($prettyVersion);
35285 $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
35286 $composerPluginApi->setDescription('The Composer Plugin API');
35287 $this->addPackage($composerPluginApi);
35288
35289 try {
35290 $prettyVersion = PHP_VERSION;
35291 $version = $this->versionParser->normalize($prettyVersion);
35292 } catch (\UnexpectedValueException $e) {
35293 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
35294 $version = $this->versionParser->normalize($prettyVersion);
35295 }
35296
35297 $php = new CompletePackage('php', $version, $prettyVersion);
35298 $php->setDescription('The PHP interpreter');
35299 $this->addPackage($php);
35300
35301 if (PHP_DEBUG) {
35302 $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion);
35303 $phpdebug->setDescription('The PHP interpreter, with debugging symbols');
35304 $this->addPackage($phpdebug);
35305 }
35306
35307 if (defined('PHP_ZTS') && PHP_ZTS) {
35308 $phpzts = new CompletePackage('php-zts', $version, $prettyVersion);
35309 $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety');
35310 $this->addPackage($phpzts);
35311 }
35312
35313 if (PHP_INT_SIZE === 8) {
35314 $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
35315 $php64->setDescription('The PHP interpreter, 64bit');
35316 $this->addPackage($php64);
35317 }
35318
35319
35320  
35321  if (defined('AF_INET6') || Silencer::call('inet_pton', '::') !== false) {
35322 $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion);
35323 $phpIpv6->setDescription('The PHP interpreter, with IPv6 support');
35324 $this->addPackage($phpIpv6);
35325 }
35326
35327 $loadedExtensions = get_loaded_extensions();
35328
35329
35330  foreach ($loadedExtensions as $name) {
35331 if (in_array($name, array('standard', 'Core'))) {
35332 continue;
35333 }
35334
35335 $reflExt = new \ReflectionExtension($name);
35336 $prettyVersion = $reflExt->getVersion();
35337 $this->addExtension($name, $prettyVersion);
35338 }
35339
35340
35341  if (!in_array('xdebug', $loadedExtensions, true) && ($prettyVersion = XdebugHandler::getSkippedVersion())) {
35342 $this->addExtension('xdebug', $prettyVersion);
35343 }
35344
35345
35346  
35347  
35348  foreach ($loadedExtensions as $name) {
35349 $prettyVersion = null;
35350 $description = 'The '.$name.' PHP library';
35351 switch ($name) {
35352 case 'curl':
35353 $curlVersion = curl_version();
35354 $prettyVersion = $curlVersion['version'];
35355 break;
35356
35357 case 'iconv':
35358 $prettyVersion = ICONV_VERSION;
35359 break;
35360
35361 case 'intl':
35362 $name = 'ICU';
35363 if (defined('INTL_ICU_VERSION')) {
35364 $prettyVersion = INTL_ICU_VERSION;
35365 } else {
35366 $reflector = new \ReflectionExtension('intl');
35367
35368 ob_start();
35369 $reflector->info();
35370 $output = ob_get_clean();
35371
35372 preg_match('/^ICU version => (.*)$/m', $output, $matches);
35373 $prettyVersion = $matches[1];
35374 }
35375
35376 break;
35377
35378 case 'libxml':
35379 $prettyVersion = LIBXML_DOTTED_VERSION;
35380 break;
35381
35382 case 'openssl':
35383 $prettyVersion = preg_replace_callback('{^(?:OpenSSL|LibreSSL)?\s*([0-9.]+)([a-z]*).*}i', function ($match) {
35384 if (empty($match[2])) {
35385 return $match[1];
35386 }
35387
35388
35389  
35390
35391 if (!preg_match('{^z*[a-z]$}', $match[2])) {
35392
35393  return 0;
35394 }
35395
35396 $len = strlen($match[2]);
35397 $patchVersion = ($len - 1) * 26; 
35398  $patchVersion += ord($match[2][$len - 1]) - 96;
35399
35400 return $match[1].'.'.$patchVersion;
35401 }, OPENSSL_VERSION_TEXT);
35402
35403 $description = OPENSSL_VERSION_TEXT;
35404 break;
35405
35406 case 'pcre':
35407 $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION);
35408 break;
35409
35410 case 'uuid':
35411 $prettyVersion = phpversion('uuid');
35412 break;
35413
35414 case 'xsl':
35415 $prettyVersion = LIBXSLT_DOTTED_VERSION;
35416 break;
35417
35418 default:
35419
35420  continue 2;
35421 }
35422
35423 try {
35424 $version = $this->versionParser->normalize($prettyVersion);
35425 } catch (\UnexpectedValueException $e) {
35426 continue;
35427 }
35428
35429 $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
35430 $lib->setDescription($description);
35431 $this->addPackage($lib);
35432 }
35433
35434 if (defined('HHVM_VERSION')) {
35435 try {
35436 $prettyVersion = HHVM_VERSION;
35437 $version = $this->versionParser->normalize($prettyVersion);
35438 } catch (\UnexpectedValueException $e) {
35439 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION);
35440 $version = $this->versionParser->normalize($prettyVersion);
35441 }
35442
35443 $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
35444 $hhvm->setDescription('The HHVM Runtime (64bit)');
35445 $this->addPackage($hhvm);
35446 }
35447 }
35448
35449
35450
35451
35452 public function addPackage(PackageInterface $package)
35453 {
35454
35455  if (isset($this->overrides[$package->getName()])) {
35456 $overrider = $this->findPackage($package->getName(), '*');
35457 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
35458
35459 return;
35460 }
35461
35462
35463  if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
35464 $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
35465 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
35466
35467 return;
35468 }
35469
35470 parent::addPackage($package);
35471 }
35472
35473 private function addOverriddenPackage(array $override, $name = null)
35474 {
35475 $version = $this->versionParser->normalize($override['version']);
35476 $package = new CompletePackage($name ?: $override['name'], $version, $override['version']);
35477 $package->setDescription('Package overridden via config.platform');
35478 $package->setExtra(array('config.platform' => true));
35479 parent::addPackage($package);
35480
35481 return $package;
35482 }
35483
35484
35485
35486
35487
35488
35489
35490 private function addExtension($name, $prettyVersion)
35491 {
35492 $extraDescription = null;
35493
35494 try {
35495 $version = $this->versionParser->normalize($prettyVersion);
35496 } catch (\UnexpectedValueException $e) {
35497 $extraDescription = ' (actual version: '.$prettyVersion.')';
35498 if (preg_match('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) {
35499 $prettyVersion = $match[1];
35500 } else {
35501 $prettyVersion = '0';
35502 }
35503 $version = $this->versionParser->normalize($prettyVersion);
35504 }
35505
35506 $packageName = $this->buildPackageName($name);
35507 $ext = new CompletePackage($packageName, $version, $prettyVersion);
35508 $ext->setDescription('The '.$name.' PHP extension'.$extraDescription);
35509 $this->addPackage($ext);
35510 }
35511
35512 private function buildPackageName($name)
35513 {
35514 return 'ext-' . str_replace(' ', '-', $name);
35515 }
35516 }
35517 <?php
35518
35519
35520
35521
35522
35523
35524
35525
35526
35527
35528
35529 namespace Composer\Repository;
35530
35531 use Composer\Factory;
35532 use Composer\IO\IOInterface;
35533 use Composer\Config;
35534 use Composer\EventDispatcher\EventDispatcher;
35535 use Composer\Util\RemoteFilesystem;
35536 use Composer\Json\JsonFile;
35537
35538
35539
35540
35541 class RepositoryFactory
35542 {
35543
35544
35545
35546
35547
35548
35549
35550 public static function configFromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
35551 {
35552 if (0 === strpos($repository, 'http')) {
35553 $repoConfig = array('type' => 'composer', 'url' => $repository);
35554 } elseif ("json" === pathinfo($repository, PATHINFO_EXTENSION)) {
35555 $json = new JsonFile($repository, Factory::createRemoteFilesystem($io, $config));
35556 $data = $json->read();
35557 if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
35558 $repoConfig = array('type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/'));
35559 } elseif ($allowFilesystem) {
35560 $repoConfig = array('type' => 'filesystem', 'json' => $json);
35561 } else {
35562 throw new \InvalidArgumentException("Invalid repository URL ($repository) given. This file does not contain a valid composer repository.");
35563 }
35564 } elseif ('{' === substr($repository, 0, 1)) {
35565
35566  $repoConfig = JsonFile::parseJson($repository);
35567 } else {
35568 throw new \InvalidArgumentException("Invalid repository url ($repository) given. Has to be a .json file, an http url or a JSON object.");
35569 }
35570
35571 return $repoConfig;
35572 }
35573
35574
35575
35576
35577
35578
35579
35580
35581 public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
35582 {
35583 $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
35584
35585 return static::createRepo($io, $config, $repoConfig);
35586 }
35587
35588
35589
35590
35591
35592
35593
35594 public static function createRepo(IOInterface $io, Config $config, array $repoConfig)
35595 {
35596 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
35597 $repos = static::createRepos($rm, array($repoConfig));
35598
35599 return reset($repos);
35600 }
35601
35602
35603
35604
35605
35606
35607
35608 public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
35609 {
35610 if (!$config) {
35611 $config = Factory::createConfig($io);
35612 }
35613 if (!$rm) {
35614 if (!$io) {
35615 throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
35616 }
35617 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
35618 }
35619
35620 return static::createRepos($rm, $config->getRepositories());
35621 }
35622
35623
35624
35625
35626
35627
35628
35629
35630 public static function manager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
35631 {
35632 $rm = new RepositoryManager($io, $config, $eventDispatcher, $rfs);
35633 $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
35634 $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
35635 $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
35636 $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
35637 $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
35638 $rm->setRepositoryClass('git-bitbucket', 'Composer\Repository\VcsRepository');
35639 $rm->setRepositoryClass('github', 'Composer\Repository\VcsRepository');
35640 $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
35641 $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
35642 $rm->setRepositoryClass('fossil', 'Composer\Repository\VcsRepository');
35643 $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
35644 $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
35645 $rm->setRepositoryClass('hg-bitbucket', 'Composer\Repository\VcsRepository');
35646 $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
35647 $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
35648
35649 return $rm;
35650 }
35651
35652
35653
35654
35655 private static function createRepos(RepositoryManager $rm, array $repoConfigs)
35656 {
35657 $repos = array();
35658
35659 foreach ($repoConfigs as $index => $repo) {
35660 if (is_string($repo)) {
35661 throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
35662 }
35663 if (!is_array($repo)) {
35664 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') should be an array, '.gettype($repo).' given');
35665 }
35666 if (!isset($repo['type'])) {
35667 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') must have a type defined');
35668 }
35669 $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
35670 while (isset($repos[$name])) {
35671 $name .= '2';
35672 }
35673 if ($repo['type'] === 'filesystem') {
35674 $repos[$name] = new FilesystemRepository($repo['json']);
35675 } else {
35676 $repos[$name] = $rm->createRepository($repo['type'], $repo, $index);
35677 }
35678 }
35679
35680 return $repos;
35681 }
35682 }
35683 <?php
35684
35685
35686
35687
35688
35689
35690
35691
35692
35693
35694
35695 namespace Composer\Repository;
35696
35697 use Composer\Package\PackageInterface;
35698
35699
35700
35701
35702
35703
35704
35705
35706 interface RepositoryInterface extends \Countable
35707 {
35708 const SEARCH_FULLTEXT = 0;
35709 const SEARCH_NAME = 1;
35710
35711
35712
35713
35714
35715
35716
35717
35718 public function hasPackage(PackageInterface $package);
35719
35720
35721
35722
35723
35724
35725
35726
35727
35728 public function findPackage($name, $constraint);
35729
35730
35731
35732
35733
35734
35735
35736
35737
35738 public function findPackages($name, $constraint = null);
35739
35740
35741
35742
35743
35744
35745 public function getPackages();
35746
35747
35748
35749
35750
35751
35752
35753
35754
35755 public function search($query, $mode = 0);
35756 }
35757 <?php
35758
35759
35760
35761
35762
35763
35764
35765
35766
35767
35768
35769 namespace Composer\Repository;
35770
35771 use Composer\IO\IOInterface;
35772 use Composer\Config;
35773 use Composer\EventDispatcher\EventDispatcher;
35774 use Composer\Package\PackageInterface;
35775 use Composer\Util\RemoteFilesystem;
35776
35777
35778
35779
35780
35781
35782
35783
35784 class RepositoryManager
35785 {
35786 private $localRepository;
35787 private $repositories = array();
35788 private $repositoryClasses = array();
35789 private $io;
35790 private $config;
35791 private $eventDispatcher;
35792 private $rfs;
35793
35794 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
35795 {
35796 $this->io = $io;
35797 $this->config = $config;
35798 $this->eventDispatcher = $eventDispatcher;
35799 $this->rfs = $rfs;
35800 }
35801
35802
35803
35804
35805
35806
35807
35808
35809
35810 public function findPackage($name, $constraint)
35811 {
35812 foreach ($this->repositories as $repository) {
35813
35814 if ($package = $repository->findPackage($name, $constraint)) {
35815 return $package;
35816 }
35817 }
35818
35819 return null;
35820 }
35821
35822
35823
35824
35825
35826
35827
35828
35829
35830 public function findPackages($name, $constraint)
35831 {
35832 $packages = array();
35833
35834 foreach ($this->getRepositories() as $repository) {
35835 $packages = array_merge($packages, $repository->findPackages($name, $constraint));
35836 }
35837
35838 return $packages;
35839 }
35840
35841
35842
35843
35844
35845
35846 public function addRepository(RepositoryInterface $repository)
35847 {
35848 $this->repositories[] = $repository;
35849 }
35850
35851
35852
35853
35854
35855
35856
35857
35858 public function prependRepository(RepositoryInterface $repository)
35859 {
35860 array_unshift($this->repositories, $repository);
35861 }
35862
35863
35864
35865
35866
35867
35868
35869
35870
35871
35872 public function createRepository($type, $config, $name = null)
35873 {
35874 if (!isset($this->repositoryClasses[$type])) {
35875 throw new \InvalidArgumentException('Repository type is not registered: '.$type);
35876 }
35877
35878 if (isset($config['packagist']) && false === $config['packagist']) {
35879 $this->io->writeError('<warning>Repository "'.$name.'" ('.json_encode($config).') has a packagist key which should be in its own repository definition</warning>');
35880 }
35881
35882 $class = $this->repositoryClasses[$type];
35883
35884 $reflMethod = new \ReflectionMethod($class, '__construct');
35885 $params = $reflMethod->getParameters();
35886 if (isset($params[4]) && $params[4]->getClass() && $params[4]->getClass()->getName() === 'Composer\Util\RemoteFilesystem') {
35887 return new $class($config, $this->io, $this->config, $this->eventDispatcher, $this->rfs);
35888 }
35889
35890 return new $class($config, $this->io, $this->config, $this->eventDispatcher);
35891 }
35892
35893
35894
35895
35896
35897
35898
35899 public function setRepositoryClass($type, $class)
35900 {
35901 $this->repositoryClasses[$type] = $class;
35902 }
35903
35904
35905
35906
35907
35908
35909 public function getRepositories()
35910 {
35911 return $this->repositories;
35912 }
35913
35914
35915
35916
35917
35918
35919 public function setLocalRepository(WritableRepositoryInterface $repository)
35920 {
35921 $this->localRepository = $repository;
35922 }
35923
35924
35925
35926
35927
35928
35929 public function getLocalRepository()
35930 {
35931 return $this->localRepository;
35932 }
35933 }
35934 <?php
35935
35936
35937
35938
35939
35940
35941
35942
35943
35944
35945
35946 namespace Composer\Repository;
35947
35948
35949
35950
35951
35952
35953 class RepositorySecurityException extends \Exception
35954 {
35955 }
35956 <?php
35957
35958
35959
35960
35961
35962
35963
35964
35965
35966
35967
35968 namespace Composer\Repository\Vcs;
35969
35970 use Composer\Cache;
35971 use Composer\Downloader\TransportException;
35972 use Composer\Json\JsonFile;
35973 use Composer\Util\Bitbucket;
35974
35975 abstract class BitbucketDriver extends VcsDriver
35976 {
35977
35978 protected $cache;
35979 protected $owner;
35980 protected $repository;
35981 protected $hasIssues;
35982 protected $rootIdentifier;
35983 protected $tags;
35984 protected $branches;
35985 protected $infoCache = array();
35986 protected $branchesUrl = '';
35987 protected $tagsUrl = '';
35988 protected $homeUrl = '';
35989 protected $website = '';
35990 protected $cloneHttpsUrl = '';
35991
35992
35993
35994
35995 protected $fallbackDriver;
35996
35997 protected $vcsType;
35998
35999
36000
36001
36002 public function initialize()
36003 {
36004 preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#', $this->url, $match);
36005 $this->owner = $match[1];
36006 $this->repository = $match[2];
36007 $this->originUrl = 'bitbucket.org';
36008 $this->cache = new Cache(
36009 $this->io,
36010 implode('/', array(
36011 $this->config->get('cache-repo-dir'),
36012 $this->originUrl,
36013 $this->owner,
36014 $this->repository,
36015 ))
36016 );
36017 }
36018
36019
36020
36021
36022 public function getUrl()
36023 {
36024 if ($this->fallbackDriver) {
36025 return $this->fallbackDriver->getUrl();
36026 }
36027
36028 return $this->cloneHttpsUrl;
36029 }
36030
36031
36032
36033
36034
36035
36036
36037 protected function getRepoData()
36038 {
36039 $resource = sprintf(
36040 'https://api.bitbucket.org/2.0/repositories/%s/%s?%s',
36041 $this->owner,
36042 $this->repository,
36043 http_build_query(
36044 array('fields' => '-project,-owner'),
36045 null,
36046 '&'
36047 )
36048 );
36049
36050 $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource);
36051 if ($this->fallbackDriver) {
36052 return false;
36053 }
36054 $this->parseCloneUrls($repoData['links']['clone']);
36055
36056 $this->hasIssues = !empty($repoData['has_issues']);
36057 $this->branchesUrl = $repoData['links']['branches']['href'];
36058 $this->tagsUrl = $repoData['links']['tags']['href'];
36059 $this->homeUrl = $repoData['links']['html']['href'];
36060 $this->website = $repoData['website'];
36061 $this->vcsType = $repoData['scm'];
36062
36063 return true;
36064 }
36065
36066
36067
36068
36069 public function getComposerInformation($identifier)
36070 {
36071 if ($this->fallbackDriver) {
36072 return $this->fallbackDriver->getComposerInformation($identifier);
36073 }
36074
36075 if (!isset($this->infoCache[$identifier])) {
36076 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
36077 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
36078 }
36079
36080 $composer = $this->getBaseComposerInformation($identifier);
36081
36082
36083  if (!isset($composer['support']['source'])) {
36084 $label = array_search(
36085 $identifier,
36086 $this->getTags()
36087 ) ?: array_search(
36088 $identifier,
36089 $this->getBranches()
36090 ) ?: $identifier;
36091
36092 if (array_key_exists($label, $tags = $this->getTags())) {
36093 $hash = $tags[$label];
36094 } elseif (array_key_exists($label, $branches = $this->getBranches())) {
36095 $hash = $branches[$label];
36096 }
36097
36098 if (! isset($hash)) {
36099 $composer['support']['source'] = sprintf(
36100 'https://%s/%s/%s/src',
36101 $this->originUrl,
36102 $this->owner,
36103 $this->repository
36104 );
36105 } else {
36106 $composer['support']['source'] = sprintf(
36107 'https://%s/%s/%s/src/%s/?at=%s',
36108 $this->originUrl,
36109 $this->owner,
36110 $this->repository,
36111 $hash,
36112 $label
36113 );
36114 }
36115 }
36116 if (!isset($composer['support']['issues']) && $this->hasIssues) {
36117 $composer['support']['issues'] = sprintf(
36118 'https://%s/%s/%s/issues',
36119 $this->originUrl,
36120 $this->owner,
36121 $this->repository
36122 );
36123 }
36124 if (!isset($composer['homepage'])) {
36125 $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
36126 }
36127
36128 $this->infoCache[$identifier] = $composer;
36129
36130 if ($this->shouldCache($identifier)) {
36131 $this->cache->write($identifier, json_encode($composer));
36132 }
36133 }
36134
36135 return $this->infoCache[$identifier];
36136 }
36137
36138
36139
36140
36141 public function getFileContent($file, $identifier)
36142 {
36143 if ($this->fallbackDriver) {
36144 return $this->fallbackDriver->getFileContent($file, $identifier);
36145 }
36146
36147 $resource = sprintf(
36148 'https://api.bitbucket.org/1.0/repositories/%s/%s/raw/%s/%s',
36149 $this->owner,
36150 $this->repository,
36151 $identifier,
36152 $file
36153 );
36154
36155 return $this->getContentsWithOAuthCredentials($resource);
36156 }
36157
36158
36159
36160
36161 public function getChangeDate($identifier)
36162 {
36163 if ($this->fallbackDriver) {
36164 return $this->fallbackDriver->getChangeDate($identifier);
36165 }
36166
36167 $resource = sprintf(
36168 'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
36169 $this->owner,
36170 $this->repository,
36171 $identifier
36172 );
36173 $commit = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
36174
36175 return new \DateTime($commit['date']);
36176 }
36177
36178
36179
36180
36181 public function getSource($identifier)
36182 {
36183 if ($this->fallbackDriver) {
36184 return $this->fallbackDriver->getSource($identifier);
36185 }
36186
36187 return array('type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier);
36188 }
36189
36190
36191
36192
36193 public function getDist($identifier)
36194 {
36195 if ($this->fallbackDriver) {
36196 return $this->fallbackDriver->getDist($identifier);
36197 }
36198
36199 $url = sprintf(
36200 'https://bitbucket.org/%s/%s/get/%s.zip',
36201 $this->owner,
36202 $this->repository,
36203 $identifier
36204 );
36205
36206 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
36207 }
36208
36209
36210
36211
36212 public function getTags()
36213 {
36214 if ($this->fallbackDriver) {
36215 return $this->fallbackDriver->getTags();
36216 }
36217
36218 if (null === $this->tags) {
36219 $this->tags = array();
36220 $resource = sprintf(
36221 '%s?%s',
36222 $this->tagsUrl,
36223 http_build_query(
36224 array(
36225 'pagelen' => 100,
36226 'fields' => 'values.name,values.target.hash,next',
36227 'sort' => '-target.date',
36228 ),
36229 null,
36230 '&'
36231 )
36232 );
36233 $hasNext = true;
36234 while ($hasNext) {
36235 $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
36236 foreach ($tagsData['values'] as $data) {
36237 $this->tags[$data['name']] = $data['target']['hash'];
36238 }
36239 if (empty($tagsData['next'])) {
36240 $hasNext = false;
36241 } else {
36242 $resource = $tagsData['next'];
36243 }
36244 }
36245 if ($this->vcsType === 'hg') {
36246 unset($this->tags['tip']);
36247 }
36248 }
36249
36250 return $this->tags;
36251 }
36252
36253
36254
36255
36256 public function getBranches()
36257 {
36258 if ($this->fallbackDriver) {
36259 return $this->fallbackDriver->getBranches();
36260 }
36261
36262 if (null === $this->branches) {
36263 $this->branches = array();
36264 $resource = sprintf(
36265 '%s?%s',
36266 $this->branchesUrl,
36267 http_build_query(
36268 array(
36269 'pagelen' => 100,
36270 'fields' => 'values.name,values.target.hash,values.heads,next',
36271 'sort' => '-target.date',
36272 ),
36273 null,
36274 '&'
36275 )
36276 );
36277 $hasNext = true;
36278 while ($hasNext) {
36279 $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
36280 foreach ($branchData['values'] as $data) {
36281
36282  if ($this->vcsType === 'hg' && empty($data['heads'])) {
36283 continue;
36284 }
36285
36286 $this->branches[$data['name']] = $data['target']['hash'];
36287 }
36288 if (empty($branchData['next'])) {
36289 $hasNext = false;
36290 } else {
36291 $resource = $branchData['next'];
36292 }
36293 }
36294 }
36295
36296 return $this->branches;
36297 }
36298
36299
36300
36301
36302
36303
36304
36305
36306
36307 protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false)
36308 {
36309 try {
36310 return parent::getContents($url);
36311 } catch (TransportException $e) {
36312 $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem);
36313
36314 if (403 === $e->getCode() || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) {
36315 if (!$this->io->hasAuthentication($this->originUrl)
36316 && $bitbucketUtil->authorizeOAuth($this->originUrl)
36317 ) {
36318 return parent::getContents($url);
36319 }
36320
36321 if (!$this->io->isInteractive() && $fetchingRepoData) {
36322 return $this->attemptCloneFallback();
36323 }
36324 }
36325
36326 throw $e;
36327 }
36328 }
36329
36330
36331
36332
36333
36334
36335 abstract protected function generateSshUrl();
36336
36337 protected function attemptCloneFallback()
36338 {
36339 try {
36340 $this->setupFallbackDriver($this->generateSshUrl());
36341 } catch (\RuntimeException $e) {
36342 $this->fallbackDriver = null;
36343
36344 $this->io->writeError(
36345 '<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode'
36346 . ' so that you can enter your Bitbucket OAuth consumer credentials</error>'
36347 );
36348 throw $e;
36349 }
36350 }
36351
36352
36353
36354
36355
36356 abstract protected function setupFallbackDriver($url);
36357
36358
36359
36360
36361
36362 protected function parseCloneUrls(array $cloneLinks)
36363 {
36364 foreach ($cloneLinks as $cloneLink) {
36365 if ($cloneLink['name'] === 'https') {
36366
36367  
36368  $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']);
36369 }
36370 }
36371 }
36372
36373
36374
36375
36376 protected function getMainBranchData()
36377 {
36378 $resource = sprintf(
36379 'https://api.bitbucket.org/1.0/repositories/%s/%s/main-branch',
36380 $this->owner,
36381 $this->repository
36382 );
36383
36384 return JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
36385 }
36386 }
36387 <?php
36388
36389
36390
36391
36392
36393
36394
36395
36396
36397
36398
36399 namespace Composer\Repository\Vcs;
36400
36401 use Composer\Config;
36402 use Composer\Util\ProcessExecutor;
36403 use Composer\Util\Filesystem;
36404 use Composer\IO\IOInterface;
36405
36406
36407
36408
36409 class FossilDriver extends VcsDriver
36410 {
36411 protected $tags;
36412 protected $branches;
36413 protected $rootIdentifier;
36414 protected $repoFile;
36415 protected $checkoutDir;
36416 protected $infoCache = array();
36417
36418
36419
36420
36421 public function initialize()
36422 {
36423
36424  $this->checkFossil();
36425
36426
36427  $this->config->prohibitUrlByConfig($this->url, $this->io);
36428
36429
36430  
36431  if (Filesystem::isLocalPath($this->url) && is_dir($this->url)) {
36432 $this->checkoutDir = $this->url;
36433 } else {
36434 $localName = preg_replace('{[^a-z0-9]}i', '-', $this->url);
36435 $this->repoFile = $this->config->get('cache-repo-dir') . '/' . $localName . '.fossil';
36436 $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . $localName . '/';
36437
36438 $this->updateLocalRepo();
36439 }
36440
36441 $this->getTags();
36442 $this->getBranches();
36443 }
36444
36445
36446
36447
36448 protected function checkFossil()
36449 {
36450 if (0 !== $this->process->execute('fossil version', $ignoredOutput)) {
36451 throw new \RuntimeException("fossil was not found, check that it is installed and in your PATH env.\n\n" . $this->process->getErrorOutput());
36452 }
36453 }
36454
36455
36456
36457
36458 protected function updateLocalRepo()
36459 {
36460 $fs = new Filesystem();
36461 $fs->ensureDirectoryExists($this->checkoutDir);
36462
36463 if (!is_writable(dirname($this->checkoutDir))) {
36464 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.');
36465 }
36466
36467
36468  if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) {
36469 if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) {
36470 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
36471 }
36472 } else {
36473
36474  $fs->removeDirectory($this->checkoutDir);
36475 $fs->remove($this->repoFile);
36476
36477 $fs->ensureDirectoryExists($this->checkoutDir);
36478
36479 if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
36480 $output = $this->process->getErrorOutput();
36481
36482 throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output);
36483 }
36484
36485 if (0 !== $this->process->execute(sprintf('fossil open %s --nested', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
36486 $output = $this->process->getErrorOutput();
36487
36488 throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output);
36489 }
36490 }
36491 }
36492
36493
36494
36495
36496 public function getRootIdentifier()
36497 {
36498 if (null === $this->rootIdentifier) {
36499 $this->rootIdentifier = 'trunk';
36500 }
36501
36502 return $this->rootIdentifier;
36503 }
36504
36505
36506
36507
36508 public function getUrl()
36509 {
36510 return $this->url;
36511 }
36512
36513
36514
36515
36516 public function getSource($identifier)
36517 {
36518 return array('type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier);
36519 }
36520
36521
36522
36523
36524 public function getDist($identifier)
36525 {
36526 return null;
36527 }
36528
36529
36530
36531
36532 public function getFileContent($file, $identifier)
36533 {
36534 $command = sprintf('fossil cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
36535 $this->process->execute($command, $content, $this->checkoutDir);
36536
36537 if (!trim($content)) {
36538 return null;
36539 }
36540
36541 return $content;
36542 }
36543
36544
36545
36546
36547 public function getChangeDate($identifier)
36548 {
36549 $this->process->execute('fossil finfo -b -n 1 composer.json', $output, $this->checkoutDir);
36550 list($ckout, $date, $message) = explode(' ', trim($output), 3);
36551
36552 return new \DateTime($date, new \DateTimeZone('UTC'));
36553 }
36554
36555
36556
36557
36558 public function getTags()
36559 {
36560 if (null === $this->tags) {
36561 $tags = array();
36562
36563 $this->process->execute('fossil tag list', $output, $this->checkoutDir);
36564 foreach ($this->process->splitLines($output) as $tag) {
36565 $tags[$tag] = $tag;
36566 }
36567
36568 $this->tags = $tags;
36569 }
36570
36571 return $this->tags;
36572 }
36573
36574
36575
36576
36577 public function getBranches()
36578 {
36579 if (null === $this->branches) {
36580 $branches = array();
36581 $bookmarks = array();
36582
36583 $this->process->execute('fossil branch list', $output, $this->checkoutDir);
36584 foreach ($this->process->splitLines($output) as $branch) {
36585 $branch = trim(preg_replace('/^\*/', '', trim($branch)));
36586 $branches[$branch] = $branch;
36587 }
36588
36589 $this->branches = $branches;
36590 }
36591
36592 return $this->branches;
36593 }
36594
36595
36596
36597
36598 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36599 {
36600 if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) {
36601 return true;
36602 }
36603
36604 if (preg_match('!/fossil/|\.fossil!', $url)) {
36605 return true;
36606 }
36607
36608
36609  if (Filesystem::isLocalPath($url)) {
36610 $url = Filesystem::getPlatformPath($url);
36611 if (!is_dir($url)) {
36612 return false;
36613 }
36614
36615 $process = new ProcessExecutor();
36616
36617  if ($process->execute('fossil info', $output, $url) === 0) {
36618 return true;
36619 }
36620 }
36621
36622 return false;
36623 }
36624 }
36625 <?php
36626
36627
36628
36629
36630
36631
36632
36633
36634
36635
36636
36637 namespace Composer\Repository\Vcs;
36638
36639 use Composer\Config;
36640 use Composer\IO\IOInterface;
36641
36642
36643
36644
36645 class GitBitbucketDriver extends BitbucketDriver
36646 {
36647
36648
36649
36650 public function getRootIdentifier()
36651 {
36652 if ($this->fallbackDriver) {
36653 return $this->fallbackDriver->getRootIdentifier();
36654 }
36655
36656 if (null === $this->rootIdentifier) {
36657 if (! $this->getRepoData()) {
36658 return $this->fallbackDriver->getRootIdentifier();
36659 }
36660
36661 if ($this->vcsType !== 'git') {
36662 throw new \RuntimeException(
36663 $this->url.' does not appear to be a git repository, use '.
36664 $this->cloneHttpsUrl.' if this is a mercurial bitbucket repository'
36665 );
36666 }
36667
36668 $mainBranchData = $this->getMainBranchData();
36669 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'master';
36670 }
36671
36672 return $this->rootIdentifier;
36673 }
36674
36675
36676
36677
36678 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36679 {
36680 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url)) {
36681 return false;
36682 }
36683
36684 if (!extension_loaded('openssl')) {
36685 $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36686
36687 return false;
36688 }
36689
36690 return true;
36691 }
36692
36693
36694
36695
36696 protected function setupFallbackDriver($url)
36697 {
36698 $this->fallbackDriver = new GitDriver(
36699 array('url' => $url),
36700 $this->io,
36701 $this->config,
36702 $this->process,
36703 $this->remoteFilesystem
36704 );
36705 $this->fallbackDriver->initialize();
36706 }
36707
36708
36709
36710
36711 protected function generateSshUrl()
36712 {
36713 return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git';
36714 }
36715 }
36716 <?php
36717
36718
36719
36720
36721
36722
36723
36724
36725
36726
36727
36728 namespace Composer\Repository\Vcs;
36729
36730 use Composer\Util\ProcessExecutor;
36731 use Composer\Util\Filesystem;
36732 use Composer\Util\Git as GitUtil;
36733 use Composer\IO\IOInterface;
36734 use Composer\Cache;
36735 use Composer\Config;
36736
36737
36738
36739
36740 class GitDriver extends VcsDriver
36741 {
36742 protected $cache;
36743 protected $tags;
36744 protected $branches;
36745 protected $rootIdentifier;
36746 protected $repoDir;
36747 protected $infoCache = array();
36748
36749
36750
36751
36752 public function initialize()
36753 {
36754 if (Filesystem::isLocalPath($this->url)) {
36755 $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
36756 $this->repoDir = $this->url;
36757 $cacheUrl = realpath($this->url);
36758 } else {
36759 $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
36760
36761 GitUtil::cleanEnv();
36762
36763 $fs = new Filesystem();
36764 $fs->ensureDirectoryExists(dirname($this->repoDir));
36765
36766 if (!is_writable(dirname($this->repoDir))) {
36767 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
36768 }
36769
36770 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
36771 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.');
36772 }
36773
36774 $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
36775 if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
36776 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
36777 }
36778
36779 $cacheUrl = $this->url;
36780 }
36781
36782 $this->getTags();
36783 $this->getBranches();
36784
36785 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
36786 }
36787
36788
36789
36790
36791 public function getRootIdentifier()
36792 {
36793 if (null === $this->rootIdentifier) {
36794 $this->rootIdentifier = 'master';
36795
36796
36797  $this->process->execute('git branch --no-color', $output, $this->repoDir);
36798 $branches = $this->process->splitLines($output);
36799 if (!in_array('* master', $branches)) {
36800 foreach ($branches as $branch) {
36801 if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) {
36802 $this->rootIdentifier = $match[1];
36803 break;
36804 }
36805 }
36806 }
36807 }
36808
36809 return $this->rootIdentifier;
36810 }
36811
36812
36813
36814
36815 public function getUrl()
36816 {
36817 return $this->url;
36818 }
36819
36820
36821
36822
36823 public function getSource($identifier)
36824 {
36825 return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
36826 }
36827
36828
36829
36830
36831 public function getDist($identifier)
36832 {
36833 return null;
36834 }
36835
36836
36837
36838
36839 public function getFileContent($file, $identifier)
36840 {
36841 $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
36842 $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir);
36843
36844 if (!trim($content)) {
36845 return null;
36846 }
36847
36848 return $content;
36849 }
36850
36851
36852
36853
36854 public function getChangeDate($identifier)
36855 {
36856 $this->process->execute(sprintf(
36857 'git log -1 --format=%%at %s',
36858 ProcessExecutor::escape($identifier)
36859 ), $output, $this->repoDir);
36860
36861 return new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
36862 }
36863
36864
36865
36866
36867 public function getTags()
36868 {
36869 if (null === $this->tags) {
36870 $this->tags = array();
36871
36872 $this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir);
36873 foreach ($output = $this->process->splitLines($output) as $tag) {
36874 if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
36875 $this->tags[$match[2]] = $match[1];
36876 }
36877 }
36878 }
36879
36880 return $this->tags;
36881 }
36882
36883
36884
36885
36886 public function getBranches()
36887 {
36888 if (null === $this->branches) {
36889 $branches = array();
36890
36891 $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
36892 foreach ($this->process->splitLines($output) as $branch) {
36893 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
36894 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) {
36895 $branches[$match[1]] = $match[2];
36896 }
36897 }
36898 }
36899
36900 $this->branches = $branches;
36901 }
36902
36903 return $this->branches;
36904 }
36905
36906
36907
36908
36909 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36910 {
36911 if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
36912 return true;
36913 }
36914
36915
36916  if (Filesystem::isLocalPath($url)) {
36917 $url = Filesystem::getPlatformPath($url);
36918 if (!is_dir($url)) {
36919 return false;
36920 }
36921
36922 $process = new ProcessExecutor($io);
36923
36924  if ($process->execute('git tag', $output, $url) === 0) {
36925 return true;
36926 }
36927 }
36928
36929 if (!$deep) {
36930 return false;
36931 }
36932
36933 $process = new ProcessExecutor($io);
36934
36935 return $process->execute('git ls-remote --heads ' . ProcessExecutor::escape($url), $output) === 0;
36936 }
36937 }
36938 <?php
36939
36940
36941
36942
36943
36944
36945
36946
36947
36948
36949
36950 namespace Composer\Repository\Vcs;
36951
36952 use Composer\Config;
36953 use Composer\Downloader\TransportException;
36954 use Composer\Json\JsonFile;
36955 use Composer\Cache;
36956 use Composer\IO\IOInterface;
36957 use Composer\Util\GitHub;
36958
36959
36960
36961
36962 class GitHubDriver extends VcsDriver
36963 {
36964 protected $cache;
36965 protected $owner;
36966 protected $repository;
36967 protected $tags;
36968 protected $branches;
36969 protected $rootIdentifier;
36970 protected $repoData;
36971 protected $hasIssues;
36972 protected $infoCache = array();
36973 protected $isPrivate = false;
36974
36975
36976
36977
36978
36979
36980 protected $gitDriver;
36981
36982
36983
36984
36985 public function initialize()
36986 {
36987 preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
36988 $this->owner = $match[3];
36989 $this->repository = $match[4];
36990 $this->originUrl = !empty($match[1]) ? $match[1] : $match[2];
36991 if ($this->originUrl === 'www.github.com') {
36992 $this->originUrl = 'github.com';
36993 }
36994 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
36995
36996 if (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api']) {
36997 $this->setupGitDriver($this->url);
36998
36999 return;
37000 }
37001
37002 $this->fetchRootIdentifier();
37003 }
37004
37005 public function getRepositoryUrl()
37006 {
37007 return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
37008 }
37009
37010
37011
37012
37013 public function getRootIdentifier()
37014 {
37015 if ($this->gitDriver) {
37016 return $this->gitDriver->getRootIdentifier();
37017 }
37018
37019 return $this->rootIdentifier;
37020 }
37021
37022
37023
37024
37025 public function getUrl()
37026 {
37027 if ($this->gitDriver) {
37028 return $this->gitDriver->getUrl();
37029 }
37030
37031 return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
37032 }
37033
37034
37035
37036
37037 protected function getApiUrl()
37038 {
37039 if ('github.com' === $this->originUrl) {
37040 $apiUrl = 'api.github.com';
37041 } else {
37042 $apiUrl = $this->originUrl . '/api/v3';
37043 }
37044
37045 return 'https://' . $apiUrl;
37046 }
37047
37048
37049
37050
37051 public function getSource($identifier)
37052 {
37053 if ($this->gitDriver) {
37054 return $this->gitDriver->getSource($identifier);
37055 }
37056 if ($this->isPrivate) {
37057
37058  
37059  $url = $this->generateSshUrl();
37060 } else {
37061 $url = $this->getUrl();
37062 }
37063
37064 return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
37065 }
37066
37067
37068
37069
37070 public function getDist($identifier)
37071 {
37072 $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
37073
37074 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
37075 }
37076
37077
37078
37079
37080 public function getComposerInformation($identifier)
37081 {
37082 if ($this->gitDriver) {
37083 return $this->gitDriver->getComposerInformation($identifier);
37084 }
37085
37086 if (!isset($this->infoCache[$identifier])) {
37087 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
37088 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37089 }
37090
37091 $composer = $this->getBaseComposerInformation($identifier);
37092 if ($composer) {
37093
37094
37095  if (!isset($composer['support']['source'])) {
37096 $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
37097 $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
37098 }
37099 if (!isset($composer['support']['issues']) && $this->hasIssues) {
37100 $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
37101 }
37102 }
37103
37104 if ($this->shouldCache($identifier)) {
37105 $this->cache->write($identifier, json_encode($composer));
37106 }
37107
37108 $this->infoCache[$identifier] = $composer;
37109 }
37110
37111 return $this->infoCache[$identifier];
37112 }
37113
37114
37115
37116
37117 public function getFileContent($file, $identifier)
37118 {
37119 if ($this->gitDriver) {
37120 return $this->gitDriver->getFileContent($file, $identifier);
37121 }
37122
37123 $notFoundRetries = 2;
37124 while ($notFoundRetries) {
37125 try {
37126 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
37127 $resource = JsonFile::parseJson($this->getContents($resource));
37128 if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
37129 throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
37130 }
37131
37132 return $content;
37133 } catch (TransportException $e) {
37134 if (404 !== $e->getCode()) {
37135 throw $e;
37136 }
37137
37138
37139  
37140  $notFoundRetries--;
37141
37142 return null;
37143 }
37144 }
37145
37146 return null;
37147 }
37148
37149
37150
37151
37152 public function getChangeDate($identifier)
37153 {
37154 if ($this->gitDriver) {
37155 return $this->gitDriver->getChangeDate($identifier);
37156 }
37157
37158 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
37159 $commit = JsonFile::parseJson($this->getContents($resource), $resource);
37160
37161 return new \DateTime($commit['commit']['committer']['date']);
37162 }
37163
37164
37165
37166
37167 public function getTags()
37168 {
37169 if ($this->gitDriver) {
37170 return $this->gitDriver->getTags();
37171 }
37172 if (null === $this->tags) {
37173 $this->tags = array();
37174 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
37175
37176 do {
37177 $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
37178 foreach ($tagsData as $tag) {
37179 $this->tags[$tag['name']] = $tag['commit']['sha'];
37180 }
37181
37182 $resource = $this->getNextPage();
37183 } while ($resource);
37184 }
37185
37186 return $this->tags;
37187 }
37188
37189
37190
37191
37192 public function getBranches()
37193 {
37194 if ($this->gitDriver) {
37195 return $this->gitDriver->getBranches();
37196 }
37197 if (null === $this->branches) {
37198 $this->branches = array();
37199 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
37200
37201 $branchBlacklist = array('gh-pages');
37202
37203 do {
37204 $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
37205 foreach ($branchData as $branch) {
37206 $name = substr($branch['ref'], 11);
37207 if (!in_array($name, $branchBlacklist)) {
37208 $this->branches[$name] = $branch['object']['sha'];
37209 }
37210 }
37211
37212 $resource = $this->getNextPage();
37213 } while ($resource);
37214 }
37215
37216 return $this->branches;
37217 }
37218
37219
37220
37221
37222 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37223 {
37224 if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
37225 return false;
37226 }
37227
37228 $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
37229 if (!in_array(preg_replace('{^www\.}i', '', $originUrl), $config->get('github-domains'))) {
37230 return false;
37231 }
37232
37233 if (!extension_loaded('openssl')) {
37234 $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
37235
37236 return false;
37237 }
37238
37239 return true;
37240 }
37241
37242
37243
37244
37245
37246
37247 public function getRepoData()
37248 {
37249 $this->fetchRootIdentifier();
37250
37251 return $this->repoData;
37252 }
37253
37254
37255
37256
37257
37258
37259 protected function generateSshUrl()
37260 {
37261 return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
37262 }
37263
37264
37265
37266
37267 protected function getContents($url, $fetchingRepoData = false)
37268 {
37269 try {
37270 return parent::getContents($url);
37271 } catch (TransportException $e) {
37272 $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
37273
37274 switch ($e->getCode()) {
37275 case 401:
37276 case 404:
37277
37278  if (!$fetchingRepoData) {
37279 throw $e;
37280 }
37281
37282 if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
37283 return parent::getContents($url);
37284 }
37285
37286 if (!$this->io->isInteractive()) {
37287 return $this->attemptCloneFallback();
37288 }
37289
37290 $scopesIssued = array();
37291 $scopesNeeded = array();
37292 if ($headers = $e->getHeaders()) {
37293 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-OAuth-Scopes')) {
37294 $scopesIssued = explode(' ', $scopes);
37295 }
37296 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
37297 $scopesNeeded = explode(' ', $scopes);
37298 }
37299 }
37300 $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
37301
37302  
37303  if (!$headers || !count($scopesNeeded) || count($scopesFailed)) {
37304 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
37305 }
37306
37307 return parent::getContents($url);
37308
37309 case 403:
37310 if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
37311 return parent::getContents($url);
37312 }
37313
37314 if (!$this->io->isInteractive() && $fetchingRepoData) {
37315 return $this->attemptCloneFallback();
37316 }
37317
37318 $rateLimited = $githubUtil->isRateLimited($e->getHeaders());
37319
37320 if (!$this->io->hasAuthentication($this->originUrl)) {
37321 if (!$this->io->isInteractive()) {
37322 $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>');
37323 throw $e;
37324 }
37325
37326 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>'.$this->url.'</info>)');
37327
37328 return parent::getContents($url);
37329 }
37330
37331 if ($rateLimited) {
37332 $rateLimit = $githubUtil->getRateLimit($e->getHeaders());
37333 $this->io->writeError(sprintf(
37334 '<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>',
37335 $rateLimit['limit'],
37336 $rateLimit['reset']
37337 ));
37338 }
37339
37340 throw $e;
37341
37342 default:
37343 throw $e;
37344 }
37345 }
37346 }
37347
37348
37349
37350
37351
37352
37353 protected function fetchRootIdentifier()
37354 {
37355 if ($this->repoData) {
37356 return;
37357 }
37358
37359 $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
37360
37361 $this->repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
37362 if (null === $this->repoData && null !== $this->gitDriver) {
37363 return;
37364 }
37365
37366 $this->owner = $this->repoData['owner']['login'];
37367 $this->repository = $this->repoData['name'];
37368
37369 $this->isPrivate = !empty($this->repoData['private']);
37370 if (isset($this->repoData['default_branch'])) {
37371 $this->rootIdentifier = $this->repoData['default_branch'];
37372 } elseif (isset($this->repoData['master_branch'])) {
37373 $this->rootIdentifier = $this->repoData['master_branch'];
37374 } else {
37375 $this->rootIdentifier = 'master';
37376 }
37377 $this->hasIssues = !empty($this->repoData['has_issues']);
37378 }
37379
37380 protected function attemptCloneFallback()
37381 {
37382 $this->isPrivate = true;
37383
37384 try {
37385
37386  
37387  
37388  
37389  $this->setupGitDriver($this->generateSshUrl());
37390
37391 return;
37392 } catch (\RuntimeException $e) {
37393 $this->gitDriver = null;
37394
37395 $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>');
37396 throw $e;
37397 }
37398 }
37399
37400 protected function setupGitDriver($url)
37401 {
37402 $this->gitDriver = new GitDriver(
37403 array('url' => $url),
37404 $this->io,
37405 $this->config,
37406 $this->process,
37407 $this->remoteFilesystem
37408 );
37409 $this->gitDriver->initialize();
37410 }
37411
37412 protected function getNextPage()
37413 {
37414 $headers = $this->remoteFilesystem->getLastHeaders();
37415 foreach ($headers as $header) {
37416 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
37417 $links = explode(',', $match[1]);
37418 foreach ($links as $link) {
37419 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
37420 return $match[1];
37421 }
37422 }
37423 }
37424 }
37425 }
37426 }
37427 <?php
37428
37429
37430
37431
37432
37433
37434
37435
37436
37437
37438
37439 namespace Composer\Repository\Vcs;
37440
37441 use Composer\Config;
37442 use Composer\Cache;
37443 use Composer\IO\IOInterface;
37444 use Composer\Json\JsonFile;
37445 use Composer\Downloader\TransportException;
37446 use Composer\Util\RemoteFilesystem;
37447 use Composer\Util\GitLab;
37448
37449
37450
37451
37452
37453
37454
37455 class GitLabDriver extends VcsDriver
37456 {
37457 private $scheme;
37458 private $namespace;
37459 private $repository;
37460
37461
37462
37463
37464 private $project;
37465
37466
37467
37468
37469 private $commits = array();
37470
37471
37472
37473
37474 private $tags;
37475
37476
37477
37478
37479 private $branches;
37480
37481
37482
37483
37484
37485
37486 protected $gitDriver;
37487
37488
37489
37490
37491
37492
37493 private $isPrivate = true;
37494
37495
37496
37497
37498 protected $portNumber;
37499
37500 const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)(?::(?P<port>[0-9]+))?/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
37501
37502
37503
37504
37505
37506
37507
37508
37509 public function initialize()
37510 {
37511 if (!preg_match(self::URL_REGEX, $this->url, $match)) {
37512 throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
37513 }
37514
37515 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
37516 $configuredDomains = $this->config->get('gitlab-domains');
37517 $urlParts = explode('/', $match['parts']);
37518
37519 $this->scheme = !empty($match['scheme'])
37520 ? $match['scheme']
37521 : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https')
37522 ;
37523 $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts);
37524
37525 if (!empty($match['port']) && true === is_numeric($match['port'])) {
37526
37527  $this->portNumber = (int) $match['port'];
37528 }
37529
37530 $this->namespace = implode('/', $urlParts);
37531 $this->repository = preg_replace('#(\.git)$#', '', $match['repo']);
37532
37533 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository);
37534
37535 $this->fetchProject();
37536 }
37537
37538
37539
37540
37541
37542
37543
37544 public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
37545 {
37546 $this->remoteFilesystem = $remoteFilesystem;
37547 }
37548
37549
37550
37551
37552 public function getFileContent($file, $identifier)
37553 {
37554 if ($this->gitDriver) {
37555 return $this->gitDriver->getFileContent($file, $identifier);
37556 }
37557
37558
37559  if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
37560 $branches = $this->getBranches();
37561 if (isset($branches[$identifier])) {
37562 $identifier = $branches[$identifier];
37563 }
37564 }
37565
37566 $resource = $this->getApiUrl().'/repository/files/'.$this->urlEncodeAll($file).'/raw?ref='.$identifier;
37567
37568 try {
37569 $content = $this->getContents($resource);
37570 } catch (TransportException $e) {
37571 if ($e->getCode() !== 404) {
37572 throw $e;
37573 }
37574
37575 return null;
37576 }
37577
37578 return $content;
37579 }
37580
37581
37582
37583
37584 public function getChangeDate($identifier)
37585 {
37586 if ($this->gitDriver) {
37587 return $this->gitDriver->getChangeDate($identifier);
37588 }
37589
37590 if (isset($this->commits[$identifier])) {
37591 return new \DateTime($this->commits[$identifier]['committed_date']);
37592 }
37593
37594 return new \DateTime();
37595 }
37596
37597
37598
37599
37600 public function getRepositoryUrl()
37601 {
37602 return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
37603 }
37604
37605
37606
37607
37608 public function getUrl()
37609 {
37610 if ($this->gitDriver) {
37611 return $this->gitDriver->getUrl();
37612 }
37613
37614 return $this->project['web_url'];
37615 }
37616
37617
37618
37619
37620 public function getDist($identifier)
37621 {
37622 $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
37623
37624 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
37625 }
37626
37627
37628
37629
37630 public function getSource($identifier)
37631 {
37632 if ($this->gitDriver) {
37633 return $this->gitDriver->getSource($identifier);
37634 }
37635
37636 return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
37637 }
37638
37639
37640
37641
37642 public function getRootIdentifier()
37643 {
37644 if ($this->gitDriver) {
37645 return $this->gitDriver->getRootIdentifier();
37646 }
37647
37648 return $this->project['default_branch'];
37649 }
37650
37651
37652
37653
37654 public function getBranches()
37655 {
37656 if ($this->gitDriver) {
37657 return $this->gitDriver->getBranches();
37658 }
37659
37660 if (!$this->branches) {
37661 $this->branches = $this->getReferences('branches');
37662 }
37663
37664 return $this->branches;
37665 }
37666
37667
37668
37669
37670 public function getTags()
37671 {
37672 if ($this->gitDriver) {
37673 return $this->gitDriver->getTags();
37674 }
37675
37676 if (!$this->tags) {
37677 $this->tags = $this->getReferences('tags');
37678 }
37679
37680 return $this->tags;
37681 }
37682
37683
37684
37685
37686 public function getApiUrl()
37687 {
37688 $domainName = $this->originUrl;
37689 $portNumber = (true === is_numeric($this->portNumber)) ? sprintf(':%s', $this->portNumber) : '';
37690
37691 return $this->scheme.'://'.$domainName.$portNumber.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository);
37692 }
37693
37694
37695
37696
37697
37698
37699
37700 private function urlEncodeAll($string)
37701 {
37702 $encoded = '';
37703 for ($i = 0; isset($string[$i]); $i++) {
37704 $character = $string[$i];
37705 if (!ctype_alnum($character) && !in_array($character, array('-', '_'), true)) {
37706 $character = '%' . sprintf('%02X', ord($character));
37707 }
37708 $encoded .= $character;
37709 }
37710
37711 return $encoded;
37712 }
37713
37714
37715
37716
37717
37718
37719 protected function getReferences($type)
37720 {
37721 $perPage = 100;
37722 $resource = $this->getApiUrl().'/repository/'.$type.'?per_page='.$perPage;
37723
37724 $references = array();
37725 do {
37726 $data = JsonFile::parseJson($this->getContents($resource), $resource);
37727
37728 foreach ($data as $datum) {
37729 $references[$datum['name']] = $datum['commit']['id'];
37730
37731
37732  
37733  $this->commits[$datum['commit']['id']] = $datum['commit'];
37734 }
37735
37736 if (count($data) >= $perPage) {
37737 $resource = $this->getNextPage();
37738 } else {
37739 $resource = false;
37740 }
37741 } while ($resource);
37742
37743 return $references;
37744 }
37745
37746 protected function fetchProject()
37747 {
37748
37749  $resource = $this->getApiUrl();
37750 $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
37751 if (isset($this->project['visibility'])) {
37752 $this->isPrivate = $this->project['visibility'] !== 'public';
37753 } else {
37754
37755  $this->isPrivate = false;
37756 }
37757 }
37758
37759 protected function attemptCloneFallback()
37760 {
37761 try {
37762 if ($this->isPrivate === false) {
37763 $url = $this->generatePublicUrl();
37764 } else {
37765 $url = $this->generateSshUrl();
37766 }
37767
37768
37769  
37770  
37771  $this->setupGitDriver($url);
37772
37773 return;
37774 } catch (\RuntimeException $e) {
37775 $this->gitDriver = null;
37776
37777 $this->io->writeError('<error>Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials</error>');
37778 throw $e;
37779 }
37780 }
37781
37782
37783
37784
37785
37786
37787 protected function generateSshUrl()
37788 {
37789 return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git';
37790 }
37791
37792 protected function generatePublicUrl()
37793 {
37794 return $this->scheme . '://' . $this->originUrl . '/'.$this->namespace.'/'.$this->repository.'.git';
37795 }
37796
37797 protected function setupGitDriver($url)
37798 {
37799 $this->gitDriver = new GitDriver(
37800 array('url' => $url),
37801 $this->io,
37802 $this->config,
37803 $this->process,
37804 $this->remoteFilesystem
37805 );
37806 $this->gitDriver->initialize();
37807 }
37808
37809
37810
37811
37812 protected function getContents($url, $fetchingRepoData = false)
37813 {
37814 try {
37815 $res = parent::getContents($url);
37816
37817 if ($fetchingRepoData) {
37818 $json = JsonFile::parseJson($res, $url);
37819
37820
37821  if (!isset($json['default_branch'])) {
37822 if (!empty($json['id'])) {
37823 $this->isPrivate = false;
37824 }
37825
37826 throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
37827 }
37828 }
37829
37830 return $res;
37831 } catch (TransportException $e) {
37832 $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);
37833
37834 switch ($e->getCode()) {
37835 case 401:
37836 case 404:
37837
37838  if (!$fetchingRepoData) {
37839 throw $e;
37840 }
37841
37842 if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
37843 return parent::getContents($url);
37844 }
37845
37846 if (!$this->io->isInteractive()) {
37847 return $this->attemptCloneFallback();
37848 }
37849 $this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
37850 $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
37851
37852 return parent::getContents($url);
37853
37854 case 403:
37855 if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
37856 return parent::getContents($url);
37857 }
37858
37859 if (!$this->io->isInteractive() && $fetchingRepoData) {
37860 return $this->attemptCloneFallback();
37861 }
37862
37863 throw $e;
37864
37865 default:
37866 throw $e;
37867 }
37868 }
37869 }
37870
37871
37872
37873
37874
37875
37876
37877 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37878 {
37879 if (!preg_match(self::URL_REGEX, $url, $match)) {
37880 return false;
37881 }
37882
37883 $scheme = !empty($match['scheme']) ? $match['scheme'] : null;
37884 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
37885 $urlParts = explode('/', $match['parts']);
37886
37887 if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts)) {
37888 return false;
37889 }
37890
37891 if ('https' === $scheme && !extension_loaded('openssl')) {
37892 $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
37893
37894 return false;
37895 }
37896
37897 return true;
37898 }
37899
37900 private function getNextPage()
37901 {
37902 $headers = $this->remoteFilesystem->getLastHeaders();
37903 foreach ($headers as $header) {
37904 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
37905 $links = explode(',', $match[1]);
37906 foreach ($links as $link) {
37907 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
37908 return $match[1];
37909 }
37910 }
37911 }
37912 }
37913 }
37914
37915
37916
37917
37918
37919
37920
37921 private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts)
37922 {
37923 if (in_array($guessedDomain, $configuredDomains)) {
37924 return $guessedDomain;
37925 }
37926
37927 while (null !== ($part = array_shift($urlParts))) {
37928 $guessedDomain .= '/' . $part;
37929
37930 if (in_array($guessedDomain, $configuredDomains)) {
37931 return $guessedDomain;
37932 }
37933 }
37934
37935 return false;
37936 }
37937 }
37938 <?php
37939
37940
37941
37942
37943
37944
37945
37946
37947
37948
37949
37950 namespace Composer\Repository\Vcs;
37951
37952 use Composer\Config;
37953 use Composer\IO\IOInterface;
37954
37955
37956
37957
37958 class HgBitbucketDriver extends BitbucketDriver
37959 {
37960
37961
37962
37963 public function getRootIdentifier()
37964 {
37965 if ($this->fallbackDriver) {
37966 return $this->fallbackDriver->getRootIdentifier();
37967 }
37968
37969 if (null === $this->rootIdentifier) {
37970 if (! $this->getRepoData()) {
37971 return $this->fallbackDriver->getRootIdentifier();
37972 }
37973
37974 if ($this->vcsType !== 'hg') {
37975 throw new \RuntimeException(
37976 $this->url.' does not appear to be a mercurial repository, use '.
37977 $this->cloneHttpsUrl.' if this is a git bitbucket repository'
37978 );
37979 }
37980
37981 $mainBranchData = $this->getMainBranchData();
37982 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'default';
37983 }
37984
37985 return $this->rootIdentifier;
37986 }
37987
37988
37989
37990
37991 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37992 {
37993 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url)) {
37994 return false;
37995 }
37996
37997 if (!extension_loaded('openssl')) {
37998 $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
37999
38000 return false;
38001 }
38002
38003 return true;
38004 }
38005
38006
38007
38008
38009 protected function setupFallbackDriver($url)
38010 {
38011 $this->fallbackDriver = new HgDriver(
38012 array('url' => $url),
38013 $this->io,
38014 $this->config,
38015 $this->process,
38016 $this->remoteFilesystem
38017 );
38018 $this->fallbackDriver->initialize();
38019 }
38020
38021
38022
38023
38024 protected function generateSshUrl()
38025 {
38026 return 'ssh://hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository;
38027 }
38028 }
38029 <?php
38030
38031
38032
38033
38034
38035
38036
38037
38038
38039
38040
38041 namespace Composer\Repository\Vcs;
38042
38043 use Composer\Config;
38044 use Composer\Util\Hg as HgUtils;
38045 use Composer\Util\ProcessExecutor;
38046 use Composer\Util\Filesystem;
38047 use Composer\IO\IOInterface;
38048
38049
38050
38051
38052 class HgDriver extends VcsDriver
38053 {
38054 protected $tags;
38055 protected $branches;
38056 protected $rootIdentifier;
38057 protected $repoDir;
38058 protected $infoCache = array();
38059
38060
38061
38062
38063 public function initialize()
38064 {
38065 if (Filesystem::isLocalPath($this->url)) {
38066 $this->repoDir = $this->url;
38067 } else {
38068 $cacheDir = $this->config->get('cache-vcs-dir');
38069 $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
38070
38071 $fs = new Filesystem();
38072 $fs->ensureDirectoryExists($cacheDir);
38073
38074 if (!is_writable(dirname($this->repoDir))) {
38075 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.');
38076 }
38077
38078
38079  $this->config->prohibitUrlByConfig($this->url, $this->io);
38080
38081 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
38082
38083
38084  if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) {
38085 if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) {
38086 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
38087 }
38088 } else {
38089
38090  $fs->removeDirectory($this->repoDir);
38091
38092 $command = function ($url) {
38093 return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($this->repoDir));
38094 };
38095
38096 $hgUtils->runCommand($command, $this->url, $this->repoDir);
38097 }
38098 }
38099
38100 $this->getTags();
38101 $this->getBranches();
38102 }
38103
38104
38105
38106
38107 public function getRootIdentifier()
38108 {
38109 if (null === $this->rootIdentifier) {
38110 $this->process->execute(sprintf('hg tip --template "{node}"'), $output, $this->repoDir);
38111 $output = $this->process->splitLines($output);
38112 $this->rootIdentifier = $output[0];
38113 }
38114
38115 return $this->rootIdentifier;
38116 }
38117
38118
38119
38120
38121 public function getUrl()
38122 {
38123 return $this->url;
38124 }
38125
38126
38127
38128
38129 public function getSource($identifier)
38130 {
38131 return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
38132 }
38133
38134
38135
38136
38137 public function getDist($identifier)
38138 {
38139 return null;
38140 }
38141
38142
38143
38144
38145 public function getFileContent($file, $identifier)
38146 {
38147 $resource = sprintf('hg cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
38148 $this->process->execute($resource, $content, $this->repoDir);
38149
38150 if (!trim($content)) {
38151 return;
38152 }
38153
38154 return $content;
38155 }
38156
38157
38158
38159
38160 public function getChangeDate($identifier)
38161 {
38162 $this->process->execute(
38163 sprintf(
38164 'hg log --template "{date|rfc3339date}" -r %s',
38165 ProcessExecutor::escape($identifier)
38166 ),
38167 $output,
38168 $this->repoDir
38169 );
38170
38171 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
38172 }
38173
38174
38175
38176
38177 public function getTags()
38178 {
38179 if (null === $this->tags) {
38180 $tags = array();
38181
38182 $this->process->execute('hg tags', $output, $this->repoDir);
38183 foreach ($this->process->splitLines($output) as $tag) {
38184 if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
38185 $tags[$match[1]] = $match[2];
38186 }
38187 }
38188 unset($tags['tip']);
38189
38190 $this->tags = $tags;
38191 }
38192
38193 return $this->tags;
38194 }
38195
38196
38197
38198
38199 public function getBranches()
38200 {
38201 if (null === $this->branches) {
38202 $branches = array();
38203 $bookmarks = array();
38204
38205 $this->process->execute('hg branches', $output, $this->repoDir);
38206 foreach ($this->process->splitLines($output) as $branch) {
38207 if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) {
38208 $branches[$match[1]] = $match[2];
38209 }
38210 }
38211
38212 $this->process->execute('hg bookmarks', $output, $this->repoDir);
38213 foreach ($this->process->splitLines($output) as $branch) {
38214 if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) {
38215 $bookmarks[$match[1]] = $match[2];
38216 }
38217 }
38218
38219
38220  $this->branches = array_merge($bookmarks, $branches);
38221 }
38222
38223 return $this->branches;
38224 }
38225
38226
38227
38228
38229 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38230 {
38231 if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
38232 return true;
38233 }
38234
38235
38236  if (Filesystem::isLocalPath($url)) {
38237 $url = Filesystem::getPlatformPath($url);
38238 if (!is_dir($url)) {
38239 return false;
38240 }
38241
38242 $process = new ProcessExecutor();
38243
38244  if ($process->execute('hg summary', $output, $url) === 0) {
38245 return true;
38246 }
38247 }
38248
38249 if (!$deep) {
38250 return false;
38251 }
38252
38253 $processExecutor = new ProcessExecutor();
38254 $exit = $processExecutor->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);
38255
38256 return $exit === 0;
38257 }
38258 }
38259 <?php
38260
38261
38262
38263
38264
38265
38266
38267
38268
38269
38270
38271 namespace Composer\Repository\Vcs;
38272
38273 use Composer\Config;
38274 use Composer\IO\IOInterface;
38275 use Composer\Util\ProcessExecutor;
38276 use Composer\Util\Perforce;
38277
38278
38279
38280
38281 class PerforceDriver extends VcsDriver
38282 {
38283 protected $depot;
38284 protected $branch;
38285
38286 protected $perforce;
38287
38288
38289
38290
38291 public function initialize()
38292 {
38293 $this->depot = $this->repoConfig['depot'];
38294 $this->branch = '';
38295 if (!empty($this->repoConfig['branch'])) {
38296 $this->branch = $this->repoConfig['branch'];
38297 }
38298
38299 $this->initPerforce($this->repoConfig);
38300 $this->perforce->p4Login();
38301 $this->perforce->checkStream();
38302
38303 $this->perforce->writeP4ClientSpec();
38304 $this->perforce->connectClient();
38305
38306 return true;
38307 }
38308
38309 private function initPerforce($repoConfig)
38310 {
38311 if (!empty($this->perforce)) {
38312 return;
38313 }
38314
38315 $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
38316 $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
38317 }
38318
38319
38320
38321
38322 public function getFileContent($file, $identifier)
38323 {
38324 return $this->perforce->getFileContent($file, $identifier);
38325 }
38326
38327
38328
38329
38330 public function getChangeDate($identifier)
38331 {
38332 return null;
38333 }
38334
38335
38336
38337
38338 public function getRootIdentifier()
38339 {
38340 return $this->branch;
38341 }
38342
38343
38344
38345
38346 public function getBranches()
38347 {
38348 return $this->perforce->getBranches();
38349 }
38350
38351
38352
38353
38354 public function getTags()
38355 {
38356 return $this->perforce->getTags();
38357 }
38358
38359
38360
38361
38362 public function getDist($identifier)
38363 {
38364 return null;
38365 }
38366
38367
38368
38369
38370 public function getSource($identifier)
38371 {
38372 $source = array(
38373 'type' => 'perforce',
38374 'url' => $this->repoConfig['url'],
38375 'reference' => $identifier,
38376 'p4user' => $this->perforce->getUser(),
38377 );
38378
38379 return $source;
38380 }
38381
38382
38383
38384
38385 public function getUrl()
38386 {
38387 return $this->url;
38388 }
38389
38390
38391
38392
38393 public function hasComposerFile($identifier)
38394 {
38395 $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
38396 $composerInfoIdentifier = $identifier;
38397
38398 return !empty($composerInfo);
38399 }
38400
38401
38402
38403
38404 public function getContents($url)
38405 {
38406 return false;
38407 }
38408
38409
38410
38411
38412 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38413 {
38414 if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) {
38415 return Perforce::checkServerExists($url, new ProcessExecutor($io));
38416 }
38417
38418 return false;
38419 }
38420
38421
38422
38423
38424 public function cleanup()
38425 {
38426 $this->perforce->cleanupClientSpec();
38427 $this->perforce = null;
38428 }
38429
38430 public function getDepot()
38431 {
38432 return $this->depot;
38433 }
38434
38435 public function getBranch()
38436 {
38437 return $this->branch;
38438 }
38439 }
38440 <?php
38441
38442
38443
38444
38445
38446
38447
38448
38449
38450
38451
38452 namespace Composer\Repository\Vcs;
38453
38454 use Composer\Cache;
38455 use Composer\Config;
38456 use Composer\Json\JsonFile;
38457 use Composer\Util\ProcessExecutor;
38458 use Composer\Util\Filesystem;
38459 use Composer\Util\Svn as SvnUtil;
38460 use Composer\IO\IOInterface;
38461 use Composer\Downloader\TransportException;
38462
38463
38464
38465
38466
38467 class SvnDriver extends VcsDriver
38468 {
38469
38470
38471
38472 protected $cache;
38473 protected $baseUrl;
38474 protected $tags;
38475 protected $branches;
38476 protected $rootIdentifier;
38477 protected $infoCache = array();
38478
38479 protected $trunkPath = 'trunk';
38480 protected $branchesPath = 'branches';
38481 protected $tagsPath = 'tags';
38482 protected $packagePath = '';
38483 protected $cacheCredentials = true;
38484
38485
38486
38487
38488 private $util;
38489
38490
38491
38492
38493 public function initialize()
38494 {
38495 $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
38496
38497 SvnUtil::cleanEnv();
38498
38499 if (isset($this->repoConfig['trunk-path'])) {
38500 $this->trunkPath = $this->repoConfig['trunk-path'];
38501 }
38502 if (isset($this->repoConfig['branches-path'])) {
38503 $this->branchesPath = $this->repoConfig['branches-path'];
38504 }
38505 if (isset($this->repoConfig['tags-path'])) {
38506 $this->tagsPath = $this->repoConfig['tags-path'];
38507 }
38508 if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
38509 $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
38510 }
38511 if (isset($this->repoConfig['package-path'])) {
38512 $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
38513 }
38514
38515 if (false !== ($pos = strrpos($this->url, '/' . $this->trunkPath))) {
38516 $this->baseUrl = substr($this->url, 0, $pos);
38517 }
38518
38519 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl));
38520
38521 $this->getBranches();
38522 $this->getTags();
38523 }
38524
38525
38526
38527
38528 public function getRootIdentifier()
38529 {
38530 return $this->rootIdentifier ?: $this->trunkPath;
38531 }
38532
38533
38534
38535
38536 public function getUrl()
38537 {
38538 return $this->url;
38539 }
38540
38541
38542
38543
38544 public function getSource($identifier)
38545 {
38546 return array('type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier);
38547 }
38548
38549
38550
38551
38552 public function getDist($identifier)
38553 {
38554 return null;
38555 }
38556
38557
38558
38559
38560 protected function shouldCache($identifier)
38561 {
38562 return $this->cache && preg_match('{@\d+$}', $identifier);
38563 }
38564
38565
38566
38567
38568 public function getComposerInformation($identifier)
38569 {
38570 if (!isset($this->infoCache[$identifier])) {
38571 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier.'.json')) {
38572 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
38573 }
38574
38575 try {
38576 $composer = $this->getBaseComposerInformation($identifier);
38577 } catch (TransportException $e) {
38578 $message = $e->getMessage();
38579 if (stripos($message, 'path not found') === false && stripos($message, 'svn: warning: W160013') === false) {
38580 throw $e;
38581 }
38582
38583  $composer = '';
38584 }
38585
38586 if ($this->shouldCache($identifier)) {
38587 $this->cache->write($identifier.'.json', json_encode($composer));
38588 }
38589
38590 $this->infoCache[$identifier] = $composer;
38591 }
38592
38593 return $this->infoCache[$identifier];
38594 }
38595
38596
38597
38598
38599
38600 public function getFileContent($file, $identifier)
38601 {
38602 $identifier = '/' . trim($identifier, '/') . '/';
38603
38604 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
38605 if (!empty($match[2])) {
38606 $path = $match[1];
38607 $rev = $match[2];
38608 } else {
38609 $path = $identifier;
38610 $rev = '';
38611 }
38612
38613 try {
38614 $resource = $path.$file;
38615 $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
38616 if (!trim($output)) {
38617 return null;
38618 }
38619 } catch (\RuntimeException $e) {
38620 throw new TransportException($e->getMessage());
38621 }
38622
38623 return $output;
38624 }
38625
38626
38627
38628
38629 public function getChangeDate($identifier)
38630 {
38631 $identifier = '/' . trim($identifier, '/') . '/';
38632
38633 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
38634 if (!empty($match[2])) {
38635 $path = $match[1];
38636 $rev = $match[2];
38637 } else {
38638 $path = $identifier;
38639 $rev = '';
38640 }
38641
38642 $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
38643 foreach ($this->process->splitLines($output) as $line) {
38644 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
38645 return new \DateTime($match[1], new \DateTimeZone('UTC'));
38646 }
38647 }
38648
38649 return null;
38650 }
38651
38652
38653
38654
38655 public function getTags()
38656 {
38657 if (null === $this->tags) {
38658 $this->tags = array();
38659
38660 if ($this->tagsPath !== false) {
38661 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
38662 if ($output) {
38663 foreach ($this->process->splitLines($output) as $line) {
38664 $line = trim($line);
38665 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
38666 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
38667 $this->tags[rtrim($match[2], '/')] = $this->buildIdentifier(
38668 '/' . $this->tagsPath . '/' . $match[2],
38669 $match[1]
38670 );
38671 }
38672 }
38673 }
38674 }
38675 }
38676 }
38677
38678 return $this->tags;
38679 }
38680
38681
38682
38683
38684 public function getBranches()
38685 {
38686 if (null === $this->branches) {
38687 $this->branches = array();
38688
38689 if (false === $this->trunkPath) {
38690 $trunkParent = $this->baseUrl . '/';
38691 } else {
38692 $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
38693 }
38694
38695 $output = $this->execute('svn ls --verbose', $trunkParent);
38696 if ($output) {
38697 foreach ($this->process->splitLines($output) as $line) {
38698 $line = trim($line);
38699 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
38700 if (isset($match[1]) && isset($match[2]) && $match[2] === './') {
38701 $this->branches['trunk'] = $this->buildIdentifier(
38702 '/' . $this->trunkPath,
38703 $match[1]
38704 );
38705 $this->rootIdentifier = $this->branches['trunk'];
38706 break;
38707 }
38708 }
38709 }
38710 }
38711 unset($output);
38712
38713 if ($this->branchesPath !== false) {
38714 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
38715 if ($output) {
38716 foreach ($this->process->splitLines(trim($output)) as $line) {
38717 $line = trim($line);
38718 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
38719 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
38720 $this->branches[rtrim($match[2], '/')] = $this->buildIdentifier(
38721 '/' . $this->branchesPath . '/' . $match[2],
38722 $match[1]
38723 );
38724 }
38725 }
38726 }
38727 }
38728 }
38729 }
38730
38731 return $this->branches;
38732 }
38733
38734
38735
38736
38737 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38738 {
38739 $url = self::normalizeUrl($url);
38740 if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
38741 return true;
38742 }
38743
38744
38745  if (!$deep && !Filesystem::isLocalPath($url)) {
38746 return false;
38747 }
38748
38749 $processExecutor = new ProcessExecutor();
38750
38751 $exit = $processExecutor->execute(
38752 "svn info --non-interactive {$url}",
38753 $ignoredOutput
38754 );
38755
38756 if ($exit === 0) {
38757
38758  return true;
38759 }
38760
38761
38762  if (false !== stripos($processExecutor->getErrorOutput(), 'authorization failed:')) {
38763
38764  
38765  return true;
38766 }
38767
38768
38769  if (false !== stripos($processExecutor->getErrorOutput(), 'Authentication failed')) {
38770
38771  
38772  return true;
38773 }
38774
38775 return false;
38776 }
38777
38778
38779
38780
38781
38782
38783
38784
38785 protected static function normalizeUrl($url)
38786 {
38787 $fs = new Filesystem();
38788 if ($fs->isAbsolutePath($url)) {
38789 return 'file://' . strtr($url, '\\', '/');
38790 }
38791
38792 return $url;
38793 }
38794
38795
38796
38797
38798
38799
38800
38801
38802
38803
38804 protected function execute($command, $url)
38805 {
38806 if (null === $this->util) {
38807 $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
38808 $this->util->setCacheCredentials($this->cacheCredentials);
38809 }
38810
38811 try {
38812 return $this->util->execute($command, $url);
38813 } catch (\RuntimeException $e) {
38814 if (null === $this->util->binaryVersion()) {
38815 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());
38816 }
38817
38818 throw new \RuntimeException(
38819 'Repository '.$this->url.' could not be processed, '.$e->getMessage()
38820 );
38821 }
38822 }
38823
38824
38825
38826
38827
38828
38829
38830
38831
38832 protected function buildIdentifier($baseDir, $revision)
38833 {
38834 return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
38835 }
38836 }
38837 <?php
38838
38839
38840
38841
38842
38843
38844
38845
38846
38847
38848
38849 namespace Composer\Repository\Vcs;
38850
38851 use Composer\Cache;
38852 use Composer\Downloader\TransportException;
38853 use Composer\Config;
38854 use Composer\Factory;
38855 use Composer\IO\IOInterface;
38856 use Composer\Json\JsonFile;
38857 use Composer\Util\ProcessExecutor;
38858 use Composer\Util\RemoteFilesystem;
38859 use Composer\Util\Filesystem;
38860
38861
38862
38863
38864
38865
38866 abstract class VcsDriver implements VcsDriverInterface
38867 {
38868
38869 protected $url;
38870
38871 protected $originUrl;
38872
38873 protected $repoConfig;
38874
38875 protected $io;
38876
38877 protected $config;
38878
38879 protected $process;
38880
38881 protected $remoteFilesystem;
38882
38883 protected $infoCache = array();
38884
38885 protected $cache;
38886
38887
38888
38889
38890
38891
38892
38893
38894
38895
38896 final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
38897 {
38898 if (Filesystem::isLocalPath($repoConfig['url'])) {
38899 $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
38900 }
38901
38902 $this->url = $repoConfig['url'];
38903 $this->originUrl = $repoConfig['url'];
38904 $this->repoConfig = $repoConfig;
38905 $this->io = $io;
38906 $this->config = $config;
38907 $this->process = $process ?: new ProcessExecutor($io);
38908 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
38909 }
38910
38911
38912
38913
38914
38915
38916
38917 protected function shouldCache($identifier)
38918 {
38919 return $this->cache && preg_match('{[a-f0-9]{40}}i', $identifier);
38920 }
38921
38922
38923
38924
38925 public function getComposerInformation($identifier)
38926 {
38927 if (!isset($this->infoCache[$identifier])) {
38928 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
38929 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
38930 }
38931
38932 $composer = $this->getBaseComposerInformation($identifier);
38933
38934 if ($this->shouldCache($identifier)) {
38935 $this->cache->write($identifier, json_encode($composer));
38936 }
38937
38938 $this->infoCache[$identifier] = $composer;
38939 }
38940
38941 return $this->infoCache[$identifier];
38942 }
38943
38944 protected function getBaseComposerInformation($identifier)
38945 {
38946 $composerFileContent = $this->getFileContent('composer.json', $identifier);
38947
38948 if (!$composerFileContent) {
38949 return null;
38950 }
38951
38952 $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json');
38953
38954 if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) {
38955 $composer['time'] = $changeDate->format(DATE_RFC3339);
38956 }
38957
38958 return $composer;
38959 }
38960
38961
38962
38963
38964 public function hasComposerFile($identifier)
38965 {
38966 try {
38967 return (bool) $this->getComposerInformation($identifier);
38968 } catch (TransportException $e) {
38969 }
38970
38971 return false;
38972 }
38973
38974
38975
38976
38977
38978
38979
38980
38981 protected function getScheme()
38982 {
38983 if (extension_loaded('openssl')) {
38984 return 'https';
38985 }
38986
38987 return 'http';
38988 }
38989
38990
38991
38992
38993
38994
38995
38996
38997 protected function getContents($url)
38998 {
38999 $options = isset($this->repoConfig['options']) ? $this->repoConfig['options'] : array();
39000
39001 return $this->remoteFilesystem->getContents($this->originUrl, $url, false, $options);
39002 }
39003
39004
39005
39006
39007 public function cleanup()
39008 {
39009 return;
39010 }
39011 }
39012 <?php
39013
39014
39015
39016
39017
39018
39019
39020
39021
39022
39023
39024 namespace Composer\Repository\Vcs;
39025
39026 use Composer\Config;
39027 use Composer\IO\IOInterface;
39028
39029
39030
39031
39032 interface VcsDriverInterface
39033 {
39034
39035
39036
39037 public function initialize();
39038
39039
39040
39041
39042
39043
39044
39045 public function getComposerInformation($identifier);
39046
39047
39048
39049
39050
39051
39052
39053
39054 public function getFileContent($file, $identifier);
39055
39056
39057
39058
39059
39060
39061
39062 public function getChangeDate($identifier);
39063
39064
39065
39066
39067
39068
39069 public function getRootIdentifier();
39070
39071
39072
39073
39074
39075
39076 public function getBranches();
39077
39078
39079
39080
39081
39082
39083 public function getTags();
39084
39085
39086
39087
39088
39089 public function getDist($identifier);
39090
39091
39092
39093
39094
39095 public function getSource($identifier);
39096
39097
39098
39099
39100
39101
39102 public function getUrl();
39103
39104
39105
39106
39107
39108
39109
39110
39111 public function hasComposerFile($identifier);
39112
39113
39114
39115
39116 public function cleanup();
39117
39118
39119
39120
39121
39122
39123
39124
39125
39126
39127 public static function supports(IOInterface $io, Config $config, $url, $deep = false);
39128 }
39129 <?php
39130
39131
39132
39133
39134
39135
39136
39137
39138
39139
39140
39141 namespace Composer\Repository;
39142
39143 use Composer\Downloader\TransportException;
39144 use Composer\Repository\Vcs\VcsDriverInterface;
39145 use Composer\Package\Version\VersionParser;
39146 use Composer\Package\Loader\ArrayLoader;
39147 use Composer\Package\Loader\ValidatingArrayLoader;
39148 use Composer\Package\Loader\InvalidPackageException;
39149 use Composer\Package\Loader\LoaderInterface;
39150 use Composer\EventDispatcher\EventDispatcher;
39151 use Composer\IO\IOInterface;
39152 use Composer\Config;
39153
39154
39155
39156
39157 class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInterface
39158 {
39159 protected $url;
39160 protected $packageName;
39161 protected $verbose;
39162 protected $io;
39163 protected $config;
39164 protected $versionParser;
39165 protected $type;
39166 protected $loader;
39167 protected $repoConfig;
39168 protected $branchErrorOccurred = false;
39169 private $drivers;
39170
39171 private $driver;
39172
39173 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null)
39174 {
39175 parent::__construct();
39176 $this->drivers = $drivers ?: array(
39177 'github' => 'Composer\Repository\Vcs\GitHubDriver',
39178 'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
39179 'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
39180 'git' => 'Composer\Repository\Vcs\GitDriver',
39181 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver',
39182 'hg' => 'Composer\Repository\Vcs\HgDriver',
39183 'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
39184 'fossil' => 'Composer\Repository\Vcs\FossilDriver',
39185
39186  'svn' => 'Composer\Repository\Vcs\SvnDriver',
39187 );
39188
39189 $this->url = $repoConfig['url'];
39190 $this->io = $io;
39191 $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
39192 $this->verbose = $io->isVeryVerbose();
39193 $this->config = $config;
39194 $this->repoConfig = $repoConfig;
39195 }
39196
39197 public function getRepoConfig()
39198 {
39199 return $this->repoConfig;
39200 }
39201
39202 public function setLoader(LoaderInterface $loader)
39203 {
39204 $this->loader = $loader;
39205 }
39206
39207 public function getDriver()
39208 {
39209 if ($this->driver) {
39210 return $this->driver;
39211 }
39212
39213 if (isset($this->drivers[$this->type])) {
39214 $class = $this->drivers[$this->type];
39215 $this->driver = new $class($this->repoConfig, $this->io, $this->config);
39216 $this->driver->initialize();
39217
39218 return $this->driver;
39219 }
39220
39221 foreach ($this->drivers as $driver) {
39222 if ($driver::supports($this->io, $this->config, $this->url)) {
39223 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
39224 $this->driver->initialize();
39225
39226 return $this->driver;
39227 }
39228 }
39229
39230 foreach ($this->drivers as $driver) {
39231 if ($driver::supports($this->io, $this->config, $this->url, true)) {
39232 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
39233 $this->driver->initialize();
39234
39235 return $this->driver;
39236 }
39237 }
39238 }
39239
39240 public function hadInvalidBranches()
39241 {
39242 return $this->branchErrorOccurred;
39243 }
39244
39245 protected function initialize()
39246 {
39247 parent::initialize();
39248
39249 $verbose = $this->verbose;
39250
39251 $driver = $this->getDriver();
39252 if (!$driver) {
39253 throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url);
39254 }
39255
39256 $this->versionParser = new VersionParser;
39257 if (!$this->loader) {
39258 $this->loader = new ArrayLoader($this->versionParser);
39259 }
39260
39261 try {
39262 if ($driver->hasComposerFile($driver->getRootIdentifier())) {
39263 $data = $driver->getComposerInformation($driver->getRootIdentifier());
39264 $this->packageName = !empty($data['name']) ? $data['name'] : null;
39265 }
39266 } catch (\Exception $e) {
39267 if ($verbose) {
39268 $this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
39269 }
39270 }
39271
39272 foreach ($driver->getTags() as $tag => $identifier) {
39273 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
39274 if ($verbose) {
39275 $this->io->writeError($msg);
39276 } else {
39277 $this->io->overwriteError($msg, false);
39278 }
39279
39280
39281  $tag = str_replace('release-', '', $tag);
39282
39283 if (!$parsedTag = $this->validateTag($tag)) {
39284 if ($verbose) {
39285 $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
39286 }
39287 continue;
39288 }
39289
39290 try {
39291 if (!$data = $driver->getComposerInformation($identifier)) {
39292 if ($verbose) {
39293 $this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
39294 }
39295 continue;
39296 }
39297
39298
39299  if (isset($data['version'])) {
39300 $data['version_normalized'] = $this->versionParser->normalize($data['version']);
39301 } else {
39302
39303  $data['version'] = $tag;
39304 $data['version_normalized'] = $parsedTag;
39305 }
39306
39307
39308  $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']);
39309 $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
39310
39311
39312  if ($data['version_normalized'] !== $parsedTag) {
39313 if ($verbose) {
39314 $this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
39315 }
39316 continue;
39317 }
39318
39319 if ($existingPackage = $this->findPackage($data['name'], $data['version_normalized'])) {
39320 if ($verbose) {
39321 $this->io->writeError('<warning>Skipped tag '.$tag.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$data['version_normalized'].' internally</warning>');
39322 }
39323 continue;
39324 }
39325
39326 if ($verbose) {
39327 $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
39328 }
39329
39330 $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
39331 } catch (\Exception $e) {
39332 if ($verbose) {
39333 $this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
39334 }
39335 continue;
39336 }
39337 }
39338
39339 if (!$verbose) {
39340 $this->io->overwriteError('', false);
39341 }
39342
39343 $branches = $driver->getBranches();
39344 foreach ($branches as $branch => $identifier) {
39345 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
39346 if ($verbose) {
39347 $this->io->writeError($msg);
39348 } else {
39349 $this->io->overwriteError($msg, false);
39350 }
39351
39352 if ($branch === 'trunk' && isset($branches['master'])) {
39353 if ($verbose) {
39354 $this->io->writeError('<warning>Skipped branch '.$branch.', can not parse both master and trunk branches as they both resolve to 9999999-dev internally</warning>');
39355 }
39356 continue;
39357 }
39358
39359 if (!$parsedBranch = $this->validateBranch($branch)) {
39360 if ($verbose) {
39361 $this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
39362 }
39363 continue;
39364 }
39365
39366 try {
39367 if (!$data = $driver->getComposerInformation($identifier)) {
39368 if ($verbose) {
39369 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
39370 }
39371 continue;
39372 }
39373
39374
39375  $data['version'] = $branch;
39376 $data['version_normalized'] = $parsedBranch;
39377
39378
39379  if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
39380 $data['version'] = 'dev-' . $data['version'];
39381 } else {
39382 $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
39383 $data['version'] = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
39384 }
39385
39386 if ($verbose) {
39387 $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
39388 }
39389
39390 $packageData = $this->preProcess($driver, $data, $identifier);
39391 $package = $this->loader->load($packageData);
39392 if ($this->loader instanceof ValidatingArrayLoader && $this->loader->getWarnings()) {
39393 throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
39394 }
39395 $this->addPackage($package);
39396 } catch (TransportException $e) {
39397 if ($verbose) {
39398 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
39399 }
39400 continue;
39401 } catch (\Exception $e) {
39402 if (!$verbose) {
39403 $this->io->writeError('');
39404 }
39405 $this->branchErrorOccurred = true;
39406 $this->io->writeError('<error>Skipped branch '.$branch.', '.$e->getMessage().'</error>');
39407 $this->io->writeError('');
39408 continue;
39409 }
39410 }
39411 $driver->cleanup();
39412
39413 if (!$verbose) {
39414 $this->io->overwriteError('', false);
39415 }
39416
39417 if (!$this->getPackages()) {
39418 throw new InvalidRepositoryException('No valid composer.json was found in any branch or tag of '.$this->url.', could not load a package from it.');
39419 }
39420 }
39421
39422 protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
39423 {
39424
39425  $data['name'] = $this->packageName ?: $data['name'];
39426
39427 if (!isset($data['dist'])) {
39428 $data['dist'] = $driver->getDist($identifier);
39429 }
39430 if (!isset($data['source'])) {
39431 $data['source'] = $driver->getSource($identifier);
39432 }
39433
39434 return $data;
39435 }
39436
39437 private function validateBranch($branch)
39438 {
39439 try {
39440 return $this->versionParser->normalizeBranch($branch);
39441 } catch (\Exception $e) {
39442 }
39443
39444 return false;
39445 }
39446
39447 private function validateTag($version)
39448 {
39449 try {
39450 return $this->versionParser->normalize($version);
39451 } catch (\Exception $e) {
39452 }
39453
39454 return false;
39455 }
39456 }
39457 <?php
39458
39459
39460
39461
39462
39463
39464
39465
39466
39467
39468
39469 namespace Composer\Repository;
39470
39471 use Composer\Package\AliasPackage;
39472
39473
39474
39475
39476
39477
39478 class WritableArrayRepository extends ArrayRepository implements WritableRepositoryInterface
39479 {
39480
39481
39482
39483 public function write()
39484 {
39485 }
39486
39487
39488
39489
39490 public function reload()
39491 {
39492 }
39493
39494
39495
39496
39497 public function getCanonicalPackages()
39498 {
39499 $packages = $this->getPackages();
39500
39501
39502  $packagesByName = array();
39503 foreach ($packages as $package) {
39504 if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
39505 $packagesByName[$package->getName()] = $package;
39506 }
39507 }
39508
39509 $canonicalPackages = array();
39510
39511
39512  foreach ($packagesByName as $package) {
39513 while ($package instanceof AliasPackage) {
39514 $package = $package->getAliasOf();
39515 }
39516
39517 $canonicalPackages[] = $package;
39518 }
39519
39520 return $canonicalPackages;
39521 }
39522 }
39523 <?php
39524
39525
39526
39527
39528
39529
39530
39531
39532
39533
39534
39535 namespace Composer\Repository;
39536
39537 use Composer\Package\PackageInterface;
39538
39539
39540
39541
39542
39543
39544 interface WritableRepositoryInterface extends RepositoryInterface
39545 {
39546
39547
39548
39549 public function write();
39550
39551
39552
39553
39554
39555
39556 public function addPackage(PackageInterface $package);
39557
39558
39559
39560
39561
39562
39563 public function removePackage(PackageInterface $package);
39564
39565
39566
39567
39568
39569
39570 public function getCanonicalPackages();
39571
39572
39573
39574
39575 public function reload();
39576 }
39577 <?php
39578
39579
39580
39581
39582
39583
39584
39585
39586
39587
39588
39589 namespace Composer\Script;
39590
39591
39592
39593
39594
39595
39596 class CommandEvent extends Event
39597 {
39598 }
39599 <?php
39600
39601
39602
39603
39604
39605
39606
39607
39608
39609
39610
39611 namespace Composer\Script;
39612
39613 use Composer\Composer;
39614 use Composer\IO\IOInterface;
39615 use Composer\EventDispatcher\Event as BaseEvent;
39616
39617
39618
39619
39620
39621
39622
39623 class Event extends BaseEvent
39624 {
39625
39626
39627
39628 private $composer;
39629
39630
39631
39632
39633 private $io;
39634
39635
39636
39637
39638 private $devMode;
39639
39640
39641
39642
39643
39644
39645
39646
39647
39648
39649
39650 public function __construct($name, Composer $composer, IOInterface $io, $devMode = false, array $args = array(), array $flags = array())
39651 {
39652 parent::__construct($name, $args, $flags);
39653 $this->composer = $composer;
39654 $this->io = $io;
39655 $this->devMode = $devMode;
39656 }
39657
39658
39659
39660
39661
39662
39663 public function getComposer()
39664 {
39665 return $this->composer;
39666 }
39667
39668
39669
39670
39671
39672
39673 public function getIO()
39674 {
39675 return $this->io;
39676 }
39677
39678
39679
39680
39681
39682
39683 public function isDevMode()
39684 {
39685 return $this->devMode;
39686 }
39687 }
39688 <?php
39689
39690
39691
39692
39693
39694
39695
39696
39697
39698
39699
39700 namespace Composer\Script;
39701
39702 use Composer\Installer\PackageEvent as BasePackageEvent;
39703
39704
39705
39706
39707
39708
39709 class PackageEvent extends BasePackageEvent
39710 {
39711 }
39712 <?php
39713
39714
39715
39716
39717
39718
39719
39720
39721
39722
39723
39724 namespace Composer\Script;
39725
39726
39727
39728
39729
39730
39731
39732 class ScriptEvents
39733 {
39734
39735
39736
39737
39738
39739
39740
39741 const PRE_INSTALL_CMD = 'pre-install-cmd';
39742
39743
39744
39745
39746
39747
39748
39749
39750 const POST_INSTALL_CMD = 'post-install-cmd';
39751
39752
39753
39754
39755
39756
39757
39758
39759 const PRE_UPDATE_CMD = 'pre-update-cmd';
39760
39761
39762
39763
39764
39765
39766
39767
39768 const POST_UPDATE_CMD = 'post-update-cmd';
39769
39770
39771
39772
39773
39774
39775
39776
39777 const PRE_STATUS_CMD = 'pre-status-cmd';
39778
39779
39780
39781
39782
39783
39784
39785
39786 const POST_STATUS_CMD = 'post-status-cmd';
39787
39788
39789
39790
39791
39792
39793
39794
39795 const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
39796
39797
39798
39799
39800
39801
39802
39803
39804 const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
39805
39806
39807
39808
39809
39810
39811
39812
39813 const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
39814
39815
39816
39817
39818
39819
39820
39821
39822
39823 const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
39824
39825
39826
39827
39828
39829
39830
39831
39832 const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
39833
39834
39835
39836
39837
39838
39839
39840
39841 const POST_ARCHIVE_CMD = 'post-archive-cmd';
39842
39843
39844
39845
39846
39847
39848
39849
39850
39851
39852
39853 const PRE_PACKAGE_INSTALL = 'pre-package-install';
39854
39855
39856
39857
39858
39859
39860
39861
39862
39863 const POST_PACKAGE_INSTALL = 'post-package-install';
39864
39865
39866
39867
39868
39869
39870
39871
39872
39873 const PRE_PACKAGE_UPDATE = 'pre-package-update';
39874
39875
39876
39877
39878
39879
39880
39881
39882
39883 const POST_PACKAGE_UPDATE = 'post-package-update';
39884
39885
39886
39887
39888
39889
39890
39891
39892
39893 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
39894
39895
39896
39897
39898
39899
39900
39901
39902
39903 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
39904 }
39905 <?php
39906
39907
39908
39909
39910
39911
39912
39913
39914
39915
39916
39917 namespace Composer\SelfUpdate;
39918
39919
39920
39921
39922 class Keys
39923 {
39924 public static function fingerprint($path)
39925 {
39926 $hash = strtoupper(hash('sha256', preg_replace('{\s}', '', file_get_contents($path))));
39927
39928 return implode(' ', array(
39929 substr($hash, 0, 8),
39930 substr($hash, 8, 8),
39931 substr($hash, 16, 8),
39932 substr($hash, 24, 8),
39933 '', 
39934  substr($hash, 32, 8),
39935 substr($hash, 40, 8),
39936 substr($hash, 48, 8),
39937 substr($hash, 56, 8),
39938 ));
39939 }
39940 }
39941 <?php
39942
39943
39944
39945
39946
39947
39948
39949
39950
39951
39952
39953 namespace Composer\SelfUpdate;
39954
39955 use Composer\Util\RemoteFilesystem;
39956 use Composer\Config;
39957 use Composer\Json\JsonFile;
39958
39959
39960
39961
39962 class Versions
39963 {
39964 private $rfs;
39965 private $config;
39966 private $channel;
39967
39968 public function __construct(Config $config, RemoteFilesystem $rfs)
39969 {
39970 $this->rfs = $rfs;
39971 $this->config = $config;
39972 }
39973
39974 public function getChannel()
39975 {
39976 if ($this->channel) {
39977 return $this->channel;
39978 }
39979
39980 $channelFile = $this->config->get('home').'/update-channel';
39981 if (file_exists($channelFile)) {
39982 $channel = trim(file_get_contents($channelFile));
39983 if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
39984 return $this->channel = $channel;
39985 }
39986 }
39987
39988 return $this->channel = 'stable';
39989 }
39990
39991 public function setChannel($channel)
39992 {
39993 if (!in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
39994 throw new \InvalidArgumentException('Invalid channel '.$channel.', must be one of: stable, preview, snapshot');
39995 }
39996
39997 $channelFile = $this->config->get('home').'/update-channel';
39998 $this->channel = $channel;
39999 file_put_contents($channelFile, $channel.PHP_EOL);
40000 }
40001
40002 public function getLatest()
40003 {
40004 $protocol = extension_loaded('openssl') ? 'https' : 'http';
40005 $versions = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false));
40006
40007 foreach ($versions[$this->getChannel()] as $version) {
40008 if ($version['min-php'] <= PHP_VERSION_ID) {
40009 return $version;
40010 }
40011 }
40012
40013 throw new \LogicException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')');
40014 }
40015 }
40016 <?php
40017
40018
40019
40020
40021
40022
40023
40024
40025
40026
40027
40028 namespace Composer\Util;
40029
40030 use Composer\Config;
40031 use Composer\IO\IOInterface;
40032
40033
40034
40035
40036 class AuthHelper
40037 {
40038 protected $io;
40039 protected $config;
40040
40041 public function __construct(IOInterface $io, Config $config)
40042 {
40043 $this->io = $io;
40044 $this->config = $config;
40045 }
40046
40047 public function storeAuth($originUrl, $storeAuth)
40048 {
40049 $store = false;
40050 $configSource = $this->config->getAuthConfigSource();
40051 if ($storeAuth === true) {
40052 $store = $configSource;
40053 } elseif ($storeAuth === 'prompt') {
40054 $answer = $this->io->askAndValidate(
40055 'Do you want to store credentials for '.$originUrl.' in '.$configSource->getName().' ? [Yn] ',
40056 function ($value) {
40057 $input = strtolower(substr(trim($value), 0, 1));
40058 if (in_array($input, array('y','n'))) {
40059 return $input;
40060 }
40061 throw new \RuntimeException('Please answer (y)es or (n)o');
40062 },
40063 null,
40064 'y'
40065 );
40066
40067 if ($answer === 'y') {
40068 $store = $configSource;
40069 }
40070 }
40071 if ($store) {
40072 $store->addConfigSetting(
40073 'http-basic.'.$originUrl,
40074 $this->io->getAuthentication($originUrl)
40075 );
40076 }
40077 }
40078 }
40079 <?php
40080
40081
40082
40083
40084
40085
40086
40087
40088
40089
40090
40091 namespace Composer\Util;
40092
40093 use Composer\Factory;
40094 use Composer\IO\IOInterface;
40095 use Composer\Config;
40096 use Composer\Downloader\TransportException;
40097
40098
40099
40100
40101 class Bitbucket
40102 {
40103 private $io;
40104 private $config;
40105 private $process;
40106 private $remoteFilesystem;
40107 private $token = array();
40108 private $time;
40109
40110 const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
40111
40112
40113
40114
40115
40116
40117
40118
40119
40120
40121 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null, $time = null)
40122 {
40123 $this->io = $io;
40124 $this->config = $config;
40125 $this->process = $process ?: new ProcessExecutor;
40126 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
40127 $this->time = $time;
40128 }
40129
40130
40131
40132
40133 public function getToken()
40134 {
40135 if (!isset($this->token['access_token'])) {
40136 return '';
40137 }
40138
40139 return $this->token['access_token'];
40140 }
40141
40142
40143
40144
40145
40146
40147
40148 public function authorizeOAuth($originUrl)
40149 {
40150 if ($originUrl !== 'bitbucket.org') {
40151 return false;
40152 }
40153
40154
40155  if (0 === $this->process->execute('git config bitbucket.accesstoken', $output)) {
40156 $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));
40157
40158 return true;
40159 }
40160
40161 return false;
40162 }
40163
40164
40165
40166
40167
40168 private function requestAccessToken($originUrl)
40169 {
40170 try {
40171 $json = $this->remoteFilesystem->getContents($originUrl, self::OAUTH2_ACCESS_TOKEN_URL, false, array(
40172 'retry-auth-failure' => false,
40173 'http' => array(
40174 'method' => 'POST',
40175 'content' => 'grant_type=client_credentials',
40176 ),
40177 ));
40178
40179 $this->token = json_decode($json, true);
40180 } catch (TransportException $e) {
40181 if ($e->getCode() === 400) {
40182 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
40183 $this->io->writeError('This can have two reasons:');
40184 $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
40185 $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
40186
40187 return false;
40188 } elseif (in_array($e->getCode(), array(403, 401))) {
40189 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
40190 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
40191
40192 return false;
40193 }
40194
40195 throw $e;
40196 }
40197
40198 return true;
40199 }
40200
40201
40202
40203
40204
40205
40206
40207
40208
40209
40210 public function authorizeOAuthInteractively($originUrl, $message = null)
40211 {
40212 if ($message) {
40213 $this->io->writeError($message);
40214 }
40215
40216 $url = 'https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html';
40217 $this->io->writeError(sprintf('Follow the instructions on %s', $url));
40218 $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
40219 $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)');
40220
40221 $consumerKey = trim($this->io->askAndHideAnswer('Consumer Key (hidden): '));
40222
40223 if (!$consumerKey) {
40224 $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
40225 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
40226
40227 return false;
40228 }
40229
40230 $consumerSecret = trim($this->io->askAndHideAnswer('Consumer Secret (hidden): '));
40231
40232 if (!$consumerSecret) {
40233 $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
40234 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
40235
40236 return false;
40237 }
40238
40239 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
40240
40241 if (!$this->requestAccessToken($originUrl)) {
40242 return false;
40243 }
40244
40245
40246  $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
40247
40248
40249  $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
40250
40251 $this->io->writeError('<info>Consumer stored successfully.</info>');
40252
40253 return true;
40254 }
40255
40256
40257
40258
40259
40260
40261
40262
40263
40264 public function requestToken($originUrl, $consumerKey, $consumerSecret)
40265 {
40266 if (!empty($this->token) || $this->getTokenFromConfig($originUrl)) {
40267 return $this->token['access_token'];
40268 }
40269
40270 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
40271 if (!$this->requestAccessToken($originUrl)) {
40272 return '';
40273 }
40274
40275 $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
40276
40277 return $this->token['access_token'];
40278 }
40279
40280
40281
40282
40283
40284
40285
40286 private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret)
40287 {
40288 $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
40289
40290 $time = null === $this->time ? time() : $this->time;
40291 $consumer = array(
40292 "consumer-key" => $consumerKey,
40293 "consumer-secret" => $consumerSecret,
40294 "access-token" => $this->token['access_token'],
40295 "access-token-expiration" => $time + $this->token['expires_in'],
40296 );
40297
40298 $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.'.$originUrl, $consumer);
40299 }
40300
40301
40302
40303
40304
40305 private function getTokenFromConfig($originUrl)
40306 {
40307 $authConfig = $this->config->get('bitbucket-oauth');
40308
40309 if (
40310 !isset($authConfig[$originUrl]['access-token'])
40311 || !isset($authConfig[$originUrl]['access-token-expiration'])
40312 || time() > $authConfig[$originUrl]['access-token-expiration']
40313 ) {
40314 return false;
40315 }
40316
40317 $this->token = array(
40318 'access_token' => $authConfig[$originUrl]['access-token'],
40319 );
40320
40321 return true;
40322 }
40323 }
40324 <?php
40325
40326
40327
40328
40329
40330
40331
40332
40333
40334
40335
40336 namespace Composer\Util;
40337
40338
40339
40340
40341
40342
40343 class ComposerMirror
40344 {
40345 public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type)
40346 {
40347 if ($reference) {
40348 $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference);
40349 }
40350 $version = strpos($version, '/') === false ? $version : md5($version);
40351
40352 return str_replace(
40353 array('%package%', '%version%', '%reference%', '%type%'),
40354 array($packageName, $version, $reference, $type),
40355 $mirrorUrl
40356 );
40357 }
40358
40359 public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
40360 {
40361 if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
40362 $url = 'gh-'.$match[1].'/'.$match[2];
40363 } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
40364 $url = 'bb-'.$match[1].'/'.$match[2];
40365 } else {
40366 $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
40367 }
40368
40369 return str_replace(
40370 array('%package%', '%normalizedUrl%', '%type%'),
40371 array($packageName, $url, $type),
40372 $mirrorUrl
40373 );
40374 }
40375
40376 public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
40377 {
40378 return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
40379 }
40380 }
40381 <?php
40382
40383
40384
40385
40386
40387
40388
40389
40390
40391
40392
40393 namespace Composer\Util;
40394
40395 use Composer\Package\Loader\ArrayLoader;
40396 use Composer\Package\Loader\ValidatingArrayLoader;
40397 use Composer\Package\Loader\InvalidPackageException;
40398 use Composer\Json\JsonValidationException;
40399 use Composer\IO\IOInterface;
40400 use Composer\Json\JsonFile;
40401 use Composer\Spdx\SpdxLicenses;
40402
40403
40404
40405
40406
40407
40408
40409 class ConfigValidator
40410 {
40411 private $io;
40412
40413 public function __construct(IOInterface $io)
40414 {
40415 $this->io = $io;
40416 }
40417
40418
40419
40420
40421
40422
40423
40424
40425
40426 public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL)
40427 {
40428 $errors = array();
40429 $publishErrors = array();
40430 $warnings = array();
40431
40432
40433  $laxValid = false;
40434 try {
40435 $json = new JsonFile($file, null, $this->io);
40436 $manifest = $json->read();
40437
40438 $json->validateSchema(JsonFile::LAX_SCHEMA);
40439 $laxValid = true;
40440 $json->validateSchema();
40441 } catch (JsonValidationException $e) {
40442 foreach ($e->getErrors() as $message) {
40443 if ($laxValid) {
40444 $publishErrors[] = $message;
40445 } else {
40446 $errors[] = $message;
40447 }
40448 }
40449 } catch (\Exception $e) {
40450 $errors[] = $e->getMessage();
40451
40452 return array($errors, $publishErrors, $warnings);
40453 }
40454
40455
40456  if (empty($manifest['license'])) {
40457 $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
40458 } else {
40459 $licenses = (array) $manifest['license'];
40460
40461
40462  foreach ($licenses as $key => $license) {
40463 if ('proprietary' === $license) {
40464 unset($licenses[$key]);
40465 }
40466 }
40467
40468 $licenseValidator = new SpdxLicenses();
40469 foreach ($licenses as $license) {
40470 $spdxLicense = $licenseValidator->getLicenseByIdentifier($license);
40471 if ($spdxLicense && $spdxLicense[3]) {
40472 if (preg_match('{^[AL]?GPL-[123](\.[01])?\+$}i', $license)) {
40473 $warnings[] = sprintf(
40474 'License "%s" is a deprecated SPDX license identifier, use "'.str_replace('+', '', $license).'-or-later" instead',
40475 $license
40476 );
40477 } elseif (preg_match('{^[AL]?GPL-[123](\.[01])?$}i', $license)) {
40478 $warnings[] = sprintf(
40479 'License "%s" is a deprecated SPDX license identifier, use "'.$license.'-only" or "'.$license.'-or-later" instead',
40480 $license
40481 );
40482 } else {
40483 $warnings[] = sprintf(
40484 'License "%s" is a deprecated SPDX license identifier, see https://spdx.org/licenses/',
40485 $license
40486 );
40487 }
40488 }
40489 }
40490 }
40491
40492 if (isset($manifest['version'])) {
40493 $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
40494 }
40495
40496 if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) {
40497 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']);
40498 $suggestName = strtolower($suggestName);
40499
40500 $publishErrors[] = sprintf(
40501 '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.',
40502 $manifest['name'],
40503 $suggestName
40504 );
40505 }
40506
40507 if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') {
40508 $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.";
40509 }
40510
40511
40512  if (isset($manifest['require']) && isset($manifest['require-dev'])) {
40513 $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
40514
40515 if (!empty($requireOverrides)) {
40516 $plural = (count($requireOverrides) > 1) ? 'are' : 'is';
40517 $warnings[] = implode(', ', array_keys($requireOverrides)). " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
40518 }
40519 }
40520
40521
40522  $require = isset($manifest['require']) ? $manifest['require'] : array();
40523 $requireDev = isset($manifest['require-dev']) ? $manifest['require-dev'] : array();
40524 $packages = array_merge($require, $requireDev);
40525 foreach ($packages as $package => $version) {
40526 if (preg_match('/#/', $version) === 1) {
40527 $warnings[] = sprintf(
40528 'The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.',
40529 $package
40530 );
40531 }
40532 }
40533
40534
40535  $scriptsDescriptions = isset($manifest['scripts-descriptions']) ? $manifest['scripts-descriptions'] : array();
40536 $scripts = isset($manifest['scripts']) ? $manifest['scripts'] : array();
40537 foreach ($scriptsDescriptions as $scriptName => $scriptDescription) {
40538 if (!array_key_exists($scriptName, $scripts)) {
40539 $warnings[] = sprintf(
40540 'Description for non-existent script "%s" found in "scripts-descriptions"',
40541 $scriptName
40542 );
40543 }
40544 }
40545
40546
40547  if (isset($manifest['autoload']['psr-0'][''])) {
40548 $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
40549 }
40550 if (isset($manifest['autoload']['psr-4'][''])) {
40551 $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
40552 }
40553
40554 try {
40555 $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags);
40556 if (!isset($manifest['version'])) {
40557 $manifest['version'] = '1.0.0';
40558 }
40559 if (!isset($manifest['name'])) {
40560 $manifest['name'] = 'dummy/dummy';
40561 }
40562 $loader->load($manifest);
40563 } catch (InvalidPackageException $e) {
40564 $errors = array_merge($errors, $e->getErrors());
40565 }
40566
40567 $warnings = array_merge($warnings, $loader->getWarnings());
40568
40569 return array($errors, $publishErrors, $warnings);
40570 }
40571 }
40572 <?php
40573
40574
40575
40576
40577
40578
40579
40580
40581
40582
40583
40584 namespace Composer\Util;
40585
40586 use Composer\IO\IOInterface;
40587
40588
40589
40590
40591
40592
40593 class ErrorHandler
40594 {
40595 private static $io;
40596
40597
40598
40599
40600
40601
40602
40603
40604
40605
40606
40607
40608 public static function handle($level, $message, $file, $line)
40609 {
40610
40611  if (!(error_reporting() & $level)) {
40612 return;
40613 }
40614
40615 if (ini_get('xdebug.scream')) {
40616 $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
40617 "\na legitimately suppressed error that you were not supposed to see.";
40618 }
40619
40620 if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
40621 throw new \ErrorException($message, 0, $level, $file, $line);
40622 }
40623
40624 if (self::$io) {
40625 self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
40626 if (self::$io->isVerbose()) {
40627 self::$io->writeError('<warning>Stack trace:</warning>');
40628 self::$io->writeError(array_filter(array_map(function ($a) {
40629 if (isset($a['line'], $a['file'])) {
40630 return '<warning> '.$a['file'].':'.$a['line'].'</warning>';
40631 }
40632
40633 return null;
40634 }, array_slice(debug_backtrace(), 2))));
40635 }
40636 }
40637 }
40638
40639
40640
40641
40642
40643
40644 public static function register(IOInterface $io = null)
40645 {
40646 set_error_handler(array(__CLASS__, 'handle'));
40647 error_reporting(E_ALL | E_STRICT);
40648 self::$io = $io;
40649 }
40650 }
40651 <?php
40652
40653
40654
40655
40656
40657
40658
40659
40660
40661
40662
40663 namespace Composer\Util;
40664
40665 use RecursiveDirectoryIterator;
40666 use RecursiveIteratorIterator;
40667 use Symfony\Component\Filesystem\Exception\IOException;
40668 use Symfony\Component\Finder\Finder;
40669
40670
40671
40672
40673
40674 class Filesystem
40675 {
40676 private $processExecutor;
40677
40678 public function __construct(ProcessExecutor $executor = null)
40679 {
40680 $this->processExecutor = $executor ?: new ProcessExecutor();
40681 }
40682
40683 public function remove($file)
40684 {
40685 if (is_dir($file)) {
40686 return $this->removeDirectory($file);
40687 }
40688
40689 if (file_exists($file)) {
40690 return $this->unlink($file);
40691 }
40692
40693 return false;
40694 }
40695
40696
40697
40698
40699
40700
40701
40702 public function isDirEmpty($dir)
40703 {
40704 $finder = Finder::create()
40705 ->ignoreVCS(false)
40706 ->ignoreDotFiles(false)
40707 ->depth(0)
40708 ->in($dir);
40709
40710 return count($finder) === 0;
40711 }
40712
40713 public function emptyDirectory($dir, $ensureDirectoryExists = true)
40714 {
40715 if (file_exists($dir) && is_link($dir)) {
40716 $this->unlink($dir);
40717 }
40718
40719 if ($ensureDirectoryExists) {
40720 $this->ensureDirectoryExists($dir);
40721 }
40722
40723 if (is_dir($dir)) {
40724 $finder = Finder::create()
40725 ->ignoreVCS(false)
40726 ->ignoreDotFiles(false)
40727 ->depth(0)
40728 ->in($dir);
40729
40730 foreach ($finder as $path) {
40731 $this->remove((string) $path);
40732 }
40733 }
40734 }
40735
40736
40737
40738
40739
40740
40741
40742
40743
40744
40745
40746 public function removeDirectory($directory)
40747 {
40748 if ($this->isSymlinkedDirectory($directory)) {
40749 return $this->unlinkSymlinkedDirectory($directory);
40750 }
40751
40752 if ($this->isJunction($directory)) {
40753 return $this->removeJunction($directory);
40754 }
40755
40756 if (is_link($directory)) {
40757 return unlink($directory);
40758 }
40759
40760 if (!file_exists($directory) || !is_dir($directory)) {
40761 return true;
40762 }
40763
40764 if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
40765 throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.');
40766 }
40767
40768 if (!function_exists('proc_open')) {
40769 return $this->removeDirectoryPhp($directory);
40770 }
40771
40772 if (Platform::isWindows()) {
40773 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape(realpath($directory)));
40774 } else {
40775 $cmd = sprintf('rm -rf %s', ProcessExecutor::escape($directory));
40776 }
40777
40778 $result = $this->getProcess()->execute($cmd, $output) === 0;
40779
40780
40781  clearstatcache();
40782
40783 if ($result && !file_exists($directory)) {
40784 return true;
40785 }
40786
40787 return $this->removeDirectoryPhp($directory);
40788 }
40789
40790
40791
40792
40793
40794
40795
40796
40797
40798
40799
40800 public function removeDirectoryPhp($directory)
40801 {
40802 try {
40803 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
40804 } catch (\UnexpectedValueException $e) {
40805
40806  
40807  clearstatcache();
40808 usleep(100000);
40809 if (!is_dir($directory)) {
40810 return true;
40811 }
40812 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
40813 }
40814 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
40815
40816 foreach ($ri as $file) {
40817 if ($file->isDir()) {
40818 $this->rmdir($file->getPathname());
40819 } else {
40820 $this->unlink($file->getPathname());
40821 }
40822 }
40823
40824 return $this->rmdir($directory);
40825 }
40826
40827 public function ensureDirectoryExists($directory)
40828 {
40829 if (!is_dir($directory)) {
40830 if (file_exists($directory)) {
40831 throw new \RuntimeException(
40832 $directory.' exists and is not a directory.'
40833 );
40834 }
40835 if (!@mkdir($directory, 0777, true)) {
40836 throw new \RuntimeException(
40837 $directory.' does not exist and could not be created.'
40838 );
40839 }
40840 }
40841 }
40842
40843
40844
40845
40846
40847
40848
40849
40850 public function unlink($path)
40851 {
40852 if (!@$this->unlinkImplementation($path)) {
40853
40854  if (!Platform::isWindows() || (usleep(350000) && !@$this->unlinkImplementation($path))) {
40855 $error = error_get_last();
40856 $message = 'Could not delete '.$path.': ' . @$error['message'];
40857 if (Platform::isWindows()) {
40858 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
40859 }
40860
40861 throw new \RuntimeException($message);
40862 }
40863 }
40864
40865 return true;
40866 }
40867
40868
40869
40870
40871
40872
40873
40874
40875 public function rmdir($path)
40876 {
40877 if (!@rmdir($path)) {
40878
40879  if (!Platform::isWindows() || (usleep(350000) && !@rmdir($path))) {
40880 $error = error_get_last();
40881 $message = 'Could not delete '.$path.': ' . @$error['message'];
40882 if (Platform::isWindows()) {
40883 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
40884 }
40885
40886 throw new \RuntimeException($message);
40887 }
40888 }
40889
40890 return true;
40891 }
40892
40893
40894
40895
40896
40897
40898
40899
40900
40901
40902 public function copyThenRemove($source, $target)
40903 {
40904 $this->copy($source, $target);
40905 if (!is_dir($source)) {
40906 $this->unlink($source);
40907
40908 return;
40909 }
40910
40911 $this->removeDirectoryPhp($source);
40912 }
40913
40914
40915
40916
40917
40918
40919
40920
40921 public function copy($source, $target)
40922 {
40923 if (!is_dir($source)) {
40924 return copy($source, $target);
40925 }
40926
40927 $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
40928 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
40929 $this->ensureDirectoryExists($target);
40930
40931 $result = true;
40932 foreach ($ri as $file) {
40933 $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
40934 if ($file->isDir()) {
40935 $this->ensureDirectoryExists($targetPath);
40936 } else {
40937 $result = $result && copy($file->getPathname(), $targetPath);
40938 }
40939 }
40940
40941 return $result;
40942 }
40943
40944 public function rename($source, $target)
40945 {
40946 if (true === @rename($source, $target)) {
40947 return;
40948 }
40949
40950 if (!function_exists('proc_open')) {
40951 return $this->copyThenRemove($source, $target);
40952 }
40953
40954 if (Platform::isWindows()) {
40955
40956  $command = sprintf('xcopy %s %s /E /I /Q /Y', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
40957 $result = $this->processExecutor->execute($command, $output);
40958
40959
40960  clearstatcache();
40961
40962 if (0 === $result) {
40963 $this->remove($source);
40964
40965 return;
40966 }
40967 } else {
40968
40969  
40970  $command = sprintf('mv %s %s', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
40971 $result = $this->processExecutor->execute($command, $output);
40972
40973
40974  clearstatcache();
40975
40976 if (0 === $result) {
40977 return;
40978 }
40979 }
40980
40981 return $this->copyThenRemove($source, $target);
40982 }
40983
40984
40985
40986
40987
40988
40989
40990
40991
40992
40993 public function findShortestPath($from, $to, $directories = false)
40994 {
40995 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
40996 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
40997 }
40998
40999 $from = lcfirst($this->normalizePath($from));
41000 $to = lcfirst($this->normalizePath($to));
41001
41002 if ($directories) {
41003 $from = rtrim($from, '/') . '/dummy_file';
41004 }
41005
41006 if (dirname($from) === dirname($to)) {
41007 return './'.basename($to);
41008 }
41009
41010 $commonPath = $to;
41011 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) {
41012 $commonPath = strtr(dirname($commonPath), '\\', '/');
41013 }
41014
41015 if (0 !== strpos($from, $commonPath) || '/' === $commonPath) {
41016 return $to;
41017 }
41018
41019 $commonPath = rtrim($commonPath, '/') . '/';
41020 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/');
41021 $commonPathCode = str_repeat('../', $sourcePathDepth);
41022
41023 return ($commonPathCode . substr($to, strlen($commonPath))) ?: './';
41024 }
41025
41026
41027
41028
41029
41030
41031
41032
41033
41034
41035
41036 public function findShortestPathCode($from, $to, $directories = false, $staticCode = false)
41037 {
41038 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
41039 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
41040 }
41041
41042 $from = lcfirst($this->normalizePath($from));
41043 $to = lcfirst($this->normalizePath($to));
41044
41045 if ($from === $to) {
41046 return $directories ? '__DIR__' : '__FILE__';
41047 }
41048
41049 $commonPath = $to;
41050 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) {
41051 $commonPath = strtr(dirname($commonPath), '\\', '/');
41052 }
41053
41054 if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) {
41055 return var_export($to, true);
41056 }
41057
41058 $commonPath = rtrim($commonPath, '/') . '/';
41059 if (strpos($to, $from.'/') === 0) {
41060 return '__DIR__ . '.var_export(substr($to, strlen($from)), true);
41061 }
41062 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/') + $directories;
41063 if ($staticCode) {
41064 $commonPathCode = "__DIR__ . '".str_repeat('/..', $sourcePathDepth)."'";
41065 } else {
41066 $commonPathCode = str_repeat('dirname(', $sourcePathDepth).'__DIR__'.str_repeat(')', $sourcePathDepth);
41067 }
41068 $relTarget = substr($to, strlen($commonPath));
41069
41070 return $commonPathCode . (strlen($relTarget) ? '.' . var_export('/' . $relTarget, true) : '');
41071 }
41072
41073
41074
41075
41076
41077
41078
41079 public function isAbsolutePath($path)
41080 {
41081 return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':';
41082 }
41083
41084
41085
41086
41087
41088
41089
41090
41091
41092 public function size($path)
41093 {
41094 if (!file_exists($path)) {
41095 throw new \RuntimeException("$path does not exist.");
41096 }
41097 if (is_dir($path)) {
41098 return $this->directorySize($path);
41099 }
41100
41101 return filesize($path);
41102 }
41103
41104
41105
41106
41107
41108
41109
41110
41111 public function normalizePath($path)
41112 {
41113 $parts = array();
41114 $path = strtr($path, '\\', '/');
41115 $prefix = '';
41116 $absolute = false;
41117
41118
41119  if (preg_match('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
41120 $prefix = $match[1];
41121 $path = substr($path, strlen($prefix));
41122 }
41123
41124 if (substr($path, 0, 1) === '/') {
41125 $absolute = true;
41126 $path = substr($path, 1);
41127 }
41128
41129 $up = false;
41130 foreach (explode('/', $path) as $chunk) {
41131 if ('..' === $chunk && ($absolute || $up)) {
41132 array_pop($parts);
41133 $up = !(empty($parts) || '..' === end($parts));
41134 } elseif ('.' !== $chunk && '' !== $chunk) {
41135 $parts[] = $chunk;
41136 $up = '..' !== $chunk;
41137 }
41138 }
41139
41140 return $prefix.($absolute ? '/' : '').implode('/', $parts);
41141 }
41142
41143
41144
41145
41146
41147
41148
41149 public static function isLocalPath($path)
41150 {
41151 return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
41152 }
41153
41154 public static function getPlatformPath($path)
41155 {
41156 if (Platform::isWindows()) {
41157 $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
41158 }
41159
41160 return preg_replace('{^file://}i', '', $path);
41161 }
41162
41163 protected function directorySize($directory)
41164 {
41165 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
41166 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
41167
41168 $size = 0;
41169 foreach ($ri as $file) {
41170 if ($file->isFile()) {
41171 $size += $file->getSize();
41172 }
41173 }
41174
41175 return $size;
41176 }
41177
41178 protected function getProcess()
41179 {
41180 return new ProcessExecutor;
41181 }
41182
41183
41184
41185
41186
41187
41188
41189
41190
41191
41192 private function unlinkImplementation($path)
41193 {
41194 if (Platform::isWindows() && is_dir($path) && is_link($path)) {
41195 return rmdir($path);
41196 }
41197
41198 return unlink($path);
41199 }
41200
41201
41202
41203
41204
41205
41206
41207
41208 public function relativeSymlink($target, $link)
41209 {
41210 $cwd = getcwd();
41211
41212 $relativePath = $this->findShortestPath($link, $target);
41213 chdir(dirname($link));
41214 $result = @symlink($relativePath, $link);
41215
41216 chdir($cwd);
41217
41218 return $result;
41219 }
41220
41221
41222
41223
41224
41225
41226
41227
41228 public function isSymlinkedDirectory($directory)
41229 {
41230 if (!is_dir($directory)) {
41231 return false;
41232 }
41233
41234 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
41235
41236 return is_link($resolved);
41237 }
41238
41239
41240
41241
41242
41243
41244 private function unlinkSymlinkedDirectory($directory)
41245 {
41246 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
41247
41248 return $this->unlink($resolved);
41249 }
41250
41251
41252
41253
41254
41255
41256
41257
41258 private function resolveSymlinkedDirectorySymlink($pathname)
41259 {
41260 if (!is_dir($pathname)) {
41261 return $pathname;
41262 }
41263
41264 $resolved = rtrim($pathname, '/');
41265
41266 if (!strlen($resolved)) {
41267 return $pathname;
41268 }
41269
41270 return $resolved;
41271 }
41272
41273
41274
41275
41276
41277
41278
41279 public function junction($target, $junction)
41280 {
41281 if (!Platform::isWindows()) {
41282 throw new \LogicException(sprintf('Function %s is not available on non-Windows platform', __CLASS__));
41283 }
41284 if (!is_dir($target)) {
41285 throw new IOException(sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target);
41286 }
41287 $cmd = sprintf(
41288 'mklink /J %s %s',
41289 ProcessExecutor::escape(str_replace('/', DIRECTORY_SEPARATOR, $junction)),
41290 ProcessExecutor::escape(realpath($target))
41291 );
41292 if ($this->getProcess()->execute($cmd, $output) !== 0) {
41293 throw new IOException(sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target);
41294 }
41295 clearstatcache(true, $junction);
41296 }
41297
41298
41299
41300
41301
41302
41303
41304 public function isJunction($junction)
41305 {
41306 if (!Platform::isWindows()) {
41307 return false;
41308 }
41309 if (!is_dir($junction) || is_link($junction)) {
41310 return false;
41311 }
41312
41313
41314
41315
41316
41317
41318
41319
41320
41321
41322
41323 clearstatcache(true, $junction);
41324 clearstatcache(false);
41325 $stat = lstat($junction);
41326
41327 return !($stat['mode'] & 0xC000);
41328 }
41329
41330
41331
41332
41333
41334
41335
41336 public function removeJunction($junction)
41337 {
41338 if (!Platform::isWindows()) {
41339 return false;
41340 }
41341 $junction = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $junction), DIRECTORY_SEPARATOR);
41342 if (!$this->isJunction($junction)) {
41343 throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
41344 }
41345 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape($junction));
41346 clearstatcache(true, $junction);
41347
41348 return ($this->getProcess()->execute($cmd, $output) === 0);
41349 }
41350 }
41351 <?php
41352
41353
41354
41355
41356
41357
41358
41359
41360
41361
41362
41363 namespace Composer\Util;
41364
41365 use Composer\Config;
41366 use Composer\IO\IOInterface;
41367
41368
41369
41370
41371 class Git
41372 {
41373 private static $version;
41374
41375
41376 protected $io;
41377
41378 protected $config;
41379
41380 protected $process;
41381
41382 protected $filesystem;
41383
41384 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process, Filesystem $fs)
41385 {
41386 $this->io = $io;
41387 $this->config = $config;
41388 $this->process = $process;
41389 $this->filesystem = $fs;
41390 }
41391
41392 public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
41393 {
41394
41395  $this->config->prohibitUrlByConfig($url, $this->io);
41396
41397 if ($initialClone) {
41398 $origCwd = $cwd;
41399 $cwd = null;
41400 }
41401
41402 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
41403 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.');
41404 }
41405
41406 if (!$initialClone) {
41407
41408  $this->process->execute('git remote -v', $output, $cwd);
41409 if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match)) {
41410 $this->io->setAuthentication($match[3], rawurldecode($match[1]), rawurldecode($match[2]));
41411 }
41412 }
41413
41414 $protocols = $this->config->get('github-protocols');
41415 if (!is_array($protocols)) {
41416 throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols));
41417 }
41418
41419  if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
41420 $messages = array();
41421 foreach ($protocols as $protocol) {
41422 if ('ssh' === $protocol) {
41423 $protoUrl = "git@" . $match[1] . ":" . $match[2];
41424 } else {
41425 $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
41426 }
41427
41428 if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) {
41429 return;
41430 }
41431 $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', '  ', $this->process->getErrorOutput());
41432 if ($initialClone) {
41433 $this->filesystem->removeDirectory($origCwd);
41434 }
41435 }
41436
41437
41438  $this->throwException('Failed to clone ' . $url . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
41439 }
41440
41441
41442  $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
41443
41444 $command = call_user_func($commandCallable, $url);
41445
41446 $auth = null;
41447 if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
41448
41449  if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)) {
41450 if (!$this->io->hasAuthentication($match[1])) {
41451 $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
41452 $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
41453
41454 if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
41455 $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
41456 }
41457 }
41458
41459 if ($this->io->hasAuthentication($match[1])) {
41460 $auth = $this->io->getAuthentication($match[1]);
41461 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
41462 $command = call_user_func($commandCallable, $authUrl);
41463 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
41464 return;
41465 }
41466 }
41467 } elseif (preg_match('{^https://(bitbucket\.org)/(.*)(\.git)?$}U', $url, $match)) { 
41468  $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process);
41469
41470 if (!$this->io->hasAuthentication($match[1])) {
41471 $message = 'Enter your Bitbucket credentials to access private repos';
41472
41473 if (!$bitbucketUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
41474 $bitbucketUtil->authorizeOAuthInteractively($match[1], $message);
41475 $accessToken = $bitbucketUtil->getToken();
41476 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
41477 }
41478 } else { 
41479  $auth = $this->io->getAuthentication($match[1]);
41480
41481
41482  if ($auth['username'] !== 'x-token-auth') {
41483 $accessToken = $bitbucketUtil->requestToken($match[1], $auth['username'], $auth['password']);
41484 if (! empty($accessToken)) {
41485 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
41486 }
41487 }
41488 }
41489
41490 if ($this->io->hasAuthentication($match[1])) {
41491 $auth = $this->io->getAuthentication($match[1]);
41492 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
41493
41494 $command = call_user_func($commandCallable, $authUrl);
41495 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
41496 return;
41497 }
41498 } else { 
41499  $sshUrl = 'git@bitbucket.org:' . $match[2] . '.git';
41500 $this->io->writeError('    No bitbucket authentication configured. Falling back to ssh.');
41501 $command = call_user_func($commandCallable, $sshUrl);
41502 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
41503 return;
41504 }
41505 }
41506 } elseif ($this->isAuthenticationFailure($url, $match)) { 
41507  if (strpos($match[2], '@')) {
41508 list($authParts, $match[2]) = explode('@', $match[2], 2);
41509 }
41510
41511 $storeAuth = false;
41512 if ($this->io->hasAuthentication($match[2])) {
41513 $auth = $this->io->getAuthentication($match[2]);
41514 } elseif ($this->io->isInteractive()) {
41515 $defaultUsername = null;
41516 if (isset($authParts) && $authParts) {
41517 if (false !== strpos($authParts, ':')) {
41518 list($defaultUsername, ) = explode(':', $authParts, 2);
41519 } else {
41520 $defaultUsername = $authParts;
41521 }
41522 }
41523
41524 $this->io->writeError('    Authentication required (<info>' . parse_url($url, PHP_URL_HOST) . '</info>):');
41525 $auth = array(
41526 'username' => $this->io->ask('      Username: ', $defaultUsername),
41527 'password' => $this->io->askAndHideAnswer('      Password: '),
41528 );
41529 $storeAuth = $this->config->get('store-auths');
41530 }
41531
41532 if ($auth) {
41533 $authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
41534
41535 $command = call_user_func($commandCallable, $authUrl);
41536 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
41537 $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
41538 $authHelper = new AuthHelper($this->io, $this->config);
41539 $authHelper->storeAuth($match[2], $storeAuth);
41540
41541 return;
41542 }
41543 }
41544 }
41545
41546 if ($initialClone) {
41547 $this->filesystem->removeDirectory($origCwd);
41548 }
41549 $this->throwException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput(), $url);
41550 }
41551 }
41552
41553 public function syncMirror($url, $dir)
41554 {
41555
41556  if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
41557 try {
41558 $commandCallable = function ($url) {
41559 return sprintf('git remote set-url origin %s && git remote update --prune origin', ProcessExecutor::escape($url));
41560 };
41561 $this->runCommand($commandCallable, $url, $dir);
41562 } catch (\Exception $e) {
41563 return false;
41564 }
41565
41566 return true;
41567 }
41568
41569
41570  $this->filesystem->removeDirectory($dir);
41571
41572 $commandCallable = function ($url) use ($dir) {
41573 return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
41574 };
41575
41576 $this->runCommand($commandCallable, $url, $dir, true);
41577
41578 return true;
41579 }
41580
41581 public function fetchRefOrSyncMirror($url, $dir, $ref)
41582 {
41583 if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
41584 $escapedRef = ProcessExecutor::escape($ref.'^{commit}');
41585 $exitCode = $this->process->execute(sprintf('git rev-parse --quiet --verify %s', $escapedRef), $output, $dir);
41586 if ($exitCode === 0) {
41587 return true;
41588 }
41589 }
41590
41591 $this->syncMirror($url, $dir);
41592
41593 return false;
41594 }
41595
41596 private function isAuthenticationFailure($url, &$match)
41597 {
41598 if (!preg_match('{^(https?://)([^/]+)(.*)$}i', $url, $match)) {
41599 return false;
41600 }
41601
41602 $authFailures = array(
41603 'fatal: Authentication failed',
41604 'remote error: Invalid username or password.',
41605 'error: 401 Unauthorized',
41606 'fatal: unable to access',
41607 'fatal: could not read Username',
41608 );
41609
41610 $errorOutput = $this->process->getErrorOutput();
41611 foreach ($authFailures as $authFailure) {
41612 if (strpos($errorOutput, $authFailure) !== false) {
41613 return true;
41614 }
41615 }
41616
41617 return false;
41618 }
41619
41620 public static function cleanEnv()
41621 {
41622 if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
41623 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');
41624 }
41625
41626
41627  if (getenv('GIT_ASKPASS') !== 'echo') {
41628 putenv('GIT_ASKPASS=echo');
41629 unset($_SERVER['GIT_ASKPASS']);
41630 }
41631
41632
41633  if (getenv('GIT_DIR')) {
41634 putenv('GIT_DIR');
41635 unset($_SERVER['GIT_DIR']);
41636 }
41637 if (getenv('GIT_WORK_TREE')) {
41638 putenv('GIT_WORK_TREE');
41639 unset($_SERVER['GIT_WORK_TREE']);
41640 }
41641
41642
41643  if (getenv('LANGUAGE') !== 'C') {
41644 putenv('LANGUAGE=C');
41645 }
41646
41647
41648  putenv("DYLD_LIBRARY_PATH");
41649 unset($_SERVER['DYLD_LIBRARY_PATH']);
41650 }
41651
41652 public static function getGitHubDomainsRegex(Config $config)
41653 {
41654 return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
41655 }
41656
41657 public static function sanitizeUrl($message)
41658 {
41659 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
41660 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
41661 return '://***:***@';
41662 }
41663
41664 return '://' . $m[1] . ':***@';
41665 }, $message);
41666 }
41667
41668 private function throwException($message, $url)
41669 {
41670
41671  clearstatcache();
41672
41673 if (0 !== $this->process->execute('git --version', $ignoredOutput)) {
41674 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()));
41675 }
41676
41677 throw new \RuntimeException(self::sanitizeUrl($message));
41678 }
41679
41680
41681
41682
41683
41684
41685 public function getVersion()
41686 {
41687 if (isset(self::$version)) {
41688 return self::$version;
41689 }
41690 if (0 !== $this->process->execute('git --version', $output)) {
41691 return;
41692 }
41693 if (preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
41694 return self::$version = $matches[1];
41695 }
41696 }
41697 }
41698 <?php
41699
41700
41701
41702
41703
41704
41705
41706
41707
41708
41709
41710 namespace Composer\Util;
41711
41712 use Composer\Factory;
41713 use Composer\IO\IOInterface;
41714 use Composer\Config;
41715 use Composer\Downloader\TransportException;
41716
41717
41718
41719
41720 class GitHub
41721 {
41722 protected $io;
41723 protected $config;
41724 protected $process;
41725 protected $remoteFilesystem;
41726
41727
41728
41729
41730
41731
41732
41733
41734
41735 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
41736 {
41737 $this->io = $io;
41738 $this->config = $config;
41739 $this->process = $process ?: new ProcessExecutor;
41740 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
41741 }
41742
41743
41744
41745
41746
41747
41748
41749 public function authorizeOAuth($originUrl)
41750 {
41751 if (!in_array($originUrl, $this->config->get('github-domains'))) {
41752 return false;
41753 }
41754
41755
41756  if (0 === $this->process->execute('git config github.accesstoken', $output)) {
41757 $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
41758
41759 return true;
41760 }
41761
41762 return false;
41763 }
41764
41765
41766
41767
41768
41769
41770
41771
41772
41773
41774 public function authorizeOAuthInteractively($originUrl, $message = null)
41775 {
41776 if ($message) {
41777 $this->io->writeError($message);
41778 }
41779
41780 $note = 'Composer';
41781 if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
41782 $note .= ' on ' . trim($output);
41783 }
41784 $note .= ' ' . date('Y-m-d Hi');
41785
41786 $url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
41787 $this->io->writeError(sprintf('Head to %s', $url));
41788 $this->io->writeError(sprintf('to retrieve a token. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
41789
41790 $token = trim($this->io->askAndHideAnswer('Token (hidden): '));
41791
41792 if (!$token) {
41793 $this->io->writeError('<warning>No token given, aborting.</warning>');
41794 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
41795
41796 return false;
41797 }
41798
41799 $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
41800
41801 try {
41802 $apiUrl = ('github.com' === $originUrl) ? 'api.github.com/' : $originUrl . '/api/v3/';
41803
41804 $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl, false, array(
41805 'retry-auth-failure' => false,
41806 ));
41807 } catch (TransportException $e) {
41808 if (in_array($e->getCode(), array(403, 401))) {
41809 $this->io->writeError('<error>Invalid token provided.</error>');
41810 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
41811
41812 return false;
41813 }
41814
41815 throw $e;
41816 }
41817
41818
41819  $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
41820 $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
41821
41822 $this->io->writeError('<info>Token stored successfully.</info>');
41823
41824 return true;
41825 }
41826
41827
41828
41829
41830
41831
41832
41833
41834 public function getRateLimit(array $headers)
41835 {
41836 $rateLimit = array(
41837 'limit' => '?',
41838 'reset' => '?',
41839 );
41840
41841 foreach ($headers as $header) {
41842 $header = trim($header);
41843 if (false === strpos($header, 'X-RateLimit-')) {
41844 continue;
41845 }
41846 list($type, $value) = explode(':', $header, 2);
41847 switch ($type) {
41848 case 'X-RateLimit-Limit':
41849 $rateLimit['limit'] = (int) trim($value);
41850 break;
41851 case 'X-RateLimit-Reset':
41852 $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
41853 break;
41854 }
41855 }
41856
41857 return $rateLimit;
41858 }
41859
41860
41861
41862
41863
41864
41865
41866
41867 public function isRateLimited(array $headers)
41868 {
41869 foreach ($headers as $header) {
41870 if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
41871 return true;
41872 }
41873 }
41874
41875 return false;
41876 }
41877 }
41878 <?php
41879
41880
41881
41882
41883
41884
41885
41886
41887
41888
41889
41890 namespace Composer\Util;
41891
41892 use Composer\IO\IOInterface;
41893 use Composer\Config;
41894 use Composer\Factory;
41895 use Composer\Downloader\TransportException;
41896 use Composer\Json\JsonFile;
41897
41898
41899
41900
41901 class GitLab
41902 {
41903 protected $io;
41904 protected $config;
41905 protected $process;
41906 protected $remoteFilesystem;
41907
41908
41909
41910
41911
41912
41913
41914
41915
41916 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
41917 {
41918 $this->io = $io;
41919 $this->config = $config;
41920 $this->process = $process ?: new ProcessExecutor();
41921 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
41922 }
41923
41924
41925
41926
41927
41928
41929
41930
41931 public function authorizeOAuth($originUrl)
41932 {
41933 if (!in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
41934 return false;
41935 }
41936
41937
41938  if (0 === $this->process->execute('git config gitlab.accesstoken', $output)) {
41939 $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
41940
41941 return true;
41942 }
41943
41944
41945  $authTokens = $this->config->get('gitlab-token');
41946
41947 if (isset($authTokens[$originUrl])) {
41948 $this->io->setAuthentication($originUrl, $authTokens[$originUrl], 'private-token');
41949
41950 return true;
41951 }
41952
41953 return false;
41954 }
41955
41956
41957
41958
41959
41960
41961
41962
41963
41964
41965
41966
41967
41968 public function authorizeOAuthInteractively($scheme, $originUrl, $message = null)
41969 {
41970 if ($message) {
41971 $this->io->writeError($message);
41972 }
41973
41974 $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
41975 $this->io->writeError('To revoke access to this token you can visit '.$originUrl.'/profile/applications');
41976
41977 $attemptCounter = 0;
41978
41979 while ($attemptCounter++ < 5) {
41980 try {
41981 $response = $this->createToken($scheme, $originUrl);
41982 } catch (TransportException $e) {
41983
41984  
41985  if (in_array($e->getCode(), array(403, 401))) {
41986 if (401 === $e->getCode()) {
41987 $this->io->writeError('Bad credentials.');
41988 } else {
41989 $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
41990 }
41991
41992 $this->io->writeError('You can also manually create a personal token at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
41993 $this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
41994
41995 continue;
41996 }
41997
41998 throw $e;
41999 }
42000
42001 $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
42002
42003
42004  $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
42005
42006 return true;
42007 }
42008
42009 throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
42010 }
42011
42012 private function createToken($scheme, $originUrl)
42013 {
42014 $username = $this->io->ask('Username: ');
42015 $password = $this->io->askAndHideAnswer('Password: ');
42016
42017 $headers = array('Content-Type: application/x-www-form-urlencoded');
42018
42019 $apiUrl = $originUrl;
42020 $data = http_build_query(array(
42021 'username' => $username,
42022 'password' => $password,
42023 'grant_type' => 'password',
42024 ), null, '&');
42025 $options = array(
42026 'retry-auth-failure' => false,
42027 'http' => array(
42028 'method' => 'POST',
42029 'header' => $headers,
42030 'content' => $data,
42031 ),
42032 );
42033
42034 $json = $this->remoteFilesystem->getContents($originUrl, $scheme.'://'.$apiUrl.'/oauth/token', false, $options);
42035
42036 $this->io->writeError('Token successfully created');
42037
42038 return JsonFile::parseJson($json);
42039 }
42040 }
42041 <?php
42042
42043
42044
42045
42046
42047
42048
42049
42050
42051
42052
42053 namespace Composer\Util;
42054
42055 use Composer\Config;
42056 use Composer\IO\IOInterface;
42057
42058
42059
42060
42061 class Hg
42062 {
42063
42064
42065
42066 private $io;
42067
42068
42069
42070
42071 private $config;
42072
42073
42074
42075
42076 private $process;
42077
42078 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process)
42079 {
42080 $this->io = $io;
42081 $this->config = $config;
42082 $this->process = $process;
42083 }
42084
42085 public function runCommand($commandCallable, $url, $cwd)
42086 {
42087 $this->config->prohibitUrlByConfig($url, $this->io);
42088
42089
42090  $command = call_user_func($commandCallable, $url);
42091
42092 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42093 return;
42094 }
42095
42096
42097  if (preg_match('{^(https?)://((.+)(?:\:(.+))?@)?([^/]+)(/.*)?}mi', $url, $match) && $this->io->hasAuthentication($match[5])) {
42098 $auth = $this->io->getAuthentication($match[5]);
42099 $authenticatedUrl = $match[1] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[5] . (!empty($match[6]) ? $match[6] : null);
42100
42101 $command = call_user_func($commandCallable, $authenticatedUrl);
42102
42103 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42104 return;
42105 }
42106
42107 $error = $this->process->getErrorOutput();
42108 } else {
42109 $error = 'The given URL (' . $url . ') does not match the required format (http(s)://(username:password@)example.com/path-to-repository)';
42110 }
42111
42112 $this->throwException('Failed to clone ' . $url . ', ' . "\n\n" . $error, $url);
42113 }
42114
42115 public static function sanitizeUrl($message)
42116 {
42117 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
42118 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
42119 return '://***:***@';
42120 }
42121
42122 return '://' . $m[1] . ':***@';
42123 }, $message);
42124 }
42125
42126 private function throwException($message, $url)
42127 {
42128 if (0 !== $this->process->execute('hg --version', $ignoredOutput)) {
42129 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()));
42130 }
42131
42132 throw new \RuntimeException(self::sanitizeUrl($message));
42133 }
42134 }
42135 <?php
42136
42137
42138
42139
42140
42141
42142
42143
42144
42145
42146
42147 namespace Composer\Util;
42148
42149 use Composer\XdebugHandler\XdebugHandler;
42150
42151
42152
42153
42154
42155
42156
42157
42158 class IniHelper
42159 {
42160
42161
42162
42163
42164
42165
42166
42167
42168 public static function getAll()
42169 {
42170 return XdebugHandler::getAllIniFiles();
42171 }
42172
42173
42174
42175
42176
42177
42178 public static function getMessage()
42179 {
42180 $paths = self::getAll();
42181
42182 if (empty($paths[0])) {
42183 array_shift($paths);
42184 }
42185
42186 $ini = array_shift($paths);
42187
42188 if (empty($ini)) {
42189 return 'A php.ini file does not exist. You will have to create one.';
42190 }
42191
42192 if (!empty($paths)) {
42193 return 'Your command-line PHP is using multiple ini files. Run `php --ini` to show them.';
42194 }
42195
42196 return 'The php.ini used by your command-line PHP is: '.$ini;
42197 }
42198 }
42199 <?php
42200
42201
42202
42203
42204
42205
42206
42207
42208
42209
42210
42211 namespace Composer\Util;
42212
42213
42214
42215
42216 class NoProxyPattern
42217 {
42218
42219
42220
42221 protected $rules = array();
42222
42223
42224
42225
42226 public function __construct($pattern)
42227 {
42228 $this->rules = preg_split("/[\s,]+/", $pattern);
42229 }
42230
42231
42232
42233
42234
42235
42236
42237
42238 public function test($url)
42239 {
42240 $host = parse_url($url, PHP_URL_HOST);
42241 $port = parse_url($url, PHP_URL_PORT);
42242
42243 if (empty($port)) {
42244 switch (parse_url($url, PHP_URL_SCHEME)) {
42245 case 'http':
42246 $port = 80;
42247 break;
42248 case 'https':
42249 $port = 443;
42250 break;
42251 }
42252 }
42253
42254 foreach ($this->rules as $rule) {
42255 if ($rule == '*') {
42256 return true;
42257 }
42258
42259 $match = false;
42260
42261 list($ruleHost) = explode(':', $rule);
42262 list($base) = explode('/', $ruleHost);
42263
42264 if (filter_var($base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
42265
42266
42267 if (!isset($ip)) {
42268 $ip = gethostbyname($host);
42269 }
42270
42271 if (strpos($ruleHost, '/') === false) {
42272 $match = $ip === $ruleHost;
42273 } else {
42274
42275  
42276  if ($ip === $host) {
42277 $match = false;
42278 } else {
42279
42280  $match = self::inCIDRBlock($ruleHost, $ip);
42281 }
42282 }
42283 } else {
42284
42285
42286 $haystack = '.' . trim($host, '.') . '.';
42287 $needle = '.'. trim($ruleHost, '.') .'.';
42288 $match = stripos(strrev($haystack), strrev($needle)) === 0;
42289 }
42290
42291
42292  if ($match && strpos($rule, ':') !== false) {
42293 list(, $rulePort) = explode(':', $rule);
42294 if (!empty($rulePort) && $port != $rulePort) {
42295 $match = false;
42296 }
42297 }
42298
42299 if ($match) {
42300 return true;
42301 }
42302 }
42303
42304 return false;
42305 }
42306
42307
42308
42309
42310
42311
42312
42313
42314
42315
42316
42317 private static function inCIDRBlock($cidr, $ip)
42318 {
42319
42320  list($base, $bits) = explode('/', $cidr);
42321
42322
42323  list($a, $b, $c, $d) = explode('.', $base);
42324
42325
42326  $i = ($a << 24) + ($b << 16) + ($c << 8) + $d;
42327 $mask = $bits == 0 ? 0 : (~0 << (32 - $bits));
42328
42329
42330  $low = $i & $mask;
42331
42332
42333  $high = $i | (~$mask & 0xFFFFFFFF);
42334
42335
42336  list($a, $b, $c, $d) = explode('.', $ip);
42337
42338
42339  $check = ($a << 24) + ($b << 16) + ($c << 8) + $d;
42340
42341
42342  
42343  return $check >= $low && $check <= $high;
42344 }
42345 }
42346 <?php
42347
42348
42349
42350
42351
42352
42353
42354
42355
42356
42357
42358 namespace Composer\Util;
42359
42360 use Composer\IO\IOInterface;
42361 use Symfony\Component\Process\Process;
42362
42363
42364
42365
42366 class Perforce
42367 {
42368 protected $path;
42369 protected $p4Depot;
42370 protected $p4Client;
42371 protected $p4User;
42372 protected $p4Password;
42373 protected $p4Port;
42374 protected $p4Stream;
42375 protected $p4ClientSpec;
42376 protected $p4DepotType;
42377 protected $p4Branch;
42378 protected $process;
42379 protected $uniquePerforceClientName;
42380 protected $windowsFlag;
42381 protected $commandResult;
42382
42383 protected $io;
42384
42385 protected $filesystem;
42386
42387 public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
42388 {
42389 $this->windowsFlag = $isWindows;
42390 $this->p4Port = $port;
42391 $this->initializePath($path);
42392 $this->process = $process;
42393 $this->initialize($repoConfig);
42394 $this->io = $io;
42395 }
42396
42397 public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
42398 {
42399 return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io);
42400 }
42401
42402 public static function checkServerExists($url, ProcessExecutor $processExecutor)
42403 {
42404 $output = null;
42405
42406 return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s', $output);
42407 }
42408
42409 public function initialize($repoConfig)
42410 {
42411 $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
42412 if (!$repoConfig) {
42413 return;
42414 }
42415 if (isset($repoConfig['unique_perforce_client_name'])) {
42416 $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
42417 }
42418
42419 if (isset($repoConfig['depot'])) {
42420 $this->p4Depot = $repoConfig['depot'];
42421 }
42422 if (isset($repoConfig['branch'])) {
42423 $this->p4Branch = $repoConfig['branch'];
42424 }
42425 if (isset($repoConfig['p4user'])) {
42426 $this->p4User = $repoConfig['p4user'];
42427 } else {
42428 $this->p4User = $this->getP4variable('P4USER');
42429 }
42430 if (isset($repoConfig['p4password'])) {
42431 $this->p4Password = $repoConfig['p4password'];
42432 }
42433 }
42434
42435 public function initializeDepotAndBranch($depot, $branch)
42436 {
42437 if (isset($depot)) {
42438 $this->p4Depot = $depot;
42439 }
42440 if (isset($branch)) {
42441 $this->p4Branch = $branch;
42442 }
42443 }
42444
42445 public function generateUniquePerforceClientName()
42446 {
42447 return gethostname() . "_" . time();
42448 }
42449
42450 public function cleanupClientSpec()
42451 {
42452 $client = $this->getClient();
42453 $task = 'client -d ' . $client;
42454 $useP4Client = false;
42455 $command = $this->generateP4Command($task, $useP4Client);
42456 $this->executeCommand($command);
42457 $clientSpec = $this->getP4ClientSpec();
42458 $fileSystem = $this->getFilesystem();
42459 $fileSystem->remove($clientSpec);
42460 }
42461
42462 protected function executeCommand($command)
42463 {
42464 $this->commandResult = '';
42465
42466 return $this->process->execute($command, $this->commandResult);
42467 }
42468
42469 public function getClient()
42470 {
42471 if (!isset($this->p4Client)) {
42472 $cleanStreamName = str_replace(array('//', '/', '@'), array('', '_', ''), $this->getStream());
42473 $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
42474 }
42475
42476 return $this->p4Client;
42477 }
42478
42479 protected function getPath()
42480 {
42481 return $this->path;
42482 }
42483
42484 public function initializePath($path)
42485 {
42486 $this->path = $path;
42487 $fs = $this->getFilesystem();
42488 $fs->ensureDirectoryExists($path);
42489 }
42490
42491 protected function getPort()
42492 {
42493 return $this->p4Port;
42494 }
42495
42496 public function setStream($stream)
42497 {
42498 $this->p4Stream = $stream;
42499 $index = strrpos($stream, '/');
42500
42501  if ($index > 2) {
42502 $this->p4DepotType = 'stream';
42503 }
42504 }
42505
42506 public function isStream()
42507 {
42508 return (strcmp($this->p4DepotType, 'stream') === 0);
42509 }
42510
42511 public function getStream()
42512 {
42513 if (!isset($this->p4Stream)) {
42514 if ($this->isStream()) {
42515 $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
42516 } else {
42517 $this->p4Stream = '//' . $this->p4Depot;
42518 }
42519 }
42520
42521 return $this->p4Stream;
42522 }
42523
42524 public function getStreamWithoutLabel($stream)
42525 {
42526 $index = strpos($stream, '@');
42527 if ($index === false) {
42528 return $stream;
42529 }
42530
42531 return substr($stream, 0, $index);
42532 }
42533
42534 public function getP4ClientSpec()
42535 {
42536 return $this->path . '/' . $this->getClient() . '.p4.spec';
42537 }
42538
42539 public function getUser()
42540 {
42541 return $this->p4User;
42542 }
42543
42544 public function setUser($user)
42545 {
42546 $this->p4User = $user;
42547 }
42548
42549 public function queryP4User()
42550 {
42551 $this->getUser();
42552 if (strlen($this->p4User) > 0) {
42553 return;
42554 }
42555 $this->p4User = $this->getP4variable('P4USER');
42556 if (strlen($this->p4User) > 0) {
42557 return;
42558 }
42559 $this->p4User = $this->io->ask('Enter P4 User:');
42560 if ($this->windowsFlag) {
42561 $command = 'p4 set P4USER=' . $this->p4User;
42562 } else {
42563 $command = 'export P4USER=' . $this->p4User;
42564 }
42565 $this->executeCommand($command);
42566 }
42567
42568 protected function getP4variable($name)
42569 {
42570 if ($this->windowsFlag) {
42571 $command = 'p4 set';
42572 $this->executeCommand($command);
42573 $result = trim($this->commandResult);
42574 $resArray = explode(PHP_EOL, $result);
42575 foreach ($resArray as $line) {
42576 $fields = explode('=', $line);
42577 if (strcmp($name, $fields[0]) == 0) {
42578 $index = strpos($fields[1], ' ');
42579 if ($index === false) {
42580 $value = $fields[1];
42581 } else {
42582 $value = substr($fields[1], 0, $index);
42583 }
42584 $value = trim($value);
42585
42586 return $value;
42587 }
42588 }
42589
42590 return null;
42591 }
42592
42593 $command = 'echo $' . $name;
42594 $this->executeCommand($command);
42595 $result = trim($this->commandResult);
42596
42597 return $result;
42598 }
42599
42600 public function queryP4Password()
42601 {
42602 if (isset($this->p4Password)) {
42603 return $this->p4Password;
42604 }
42605 $password = $this->getP4variable('P4PASSWD');
42606 if (strlen($password) <= 0) {
42607 $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
42608 }
42609 $this->p4Password = $password;
42610
42611 return $password;
42612 }
42613
42614 public function generateP4Command($command, $useClient = true)
42615 {
42616 $p4Command = 'p4 ';
42617 $p4Command = $p4Command . '-u ' . $this->getUser() . ' ';
42618 if ($useClient) {
42619 $p4Command = $p4Command . '-c ' . $this->getClient() . ' ';
42620 }
42621 $p4Command = $p4Command . '-p ' . $this->getPort() . ' ' . $command;
42622
42623 return $p4Command;
42624 }
42625
42626 public function isLoggedIn()
42627 {
42628 $command = $this->generateP4Command('login -s', false);
42629 $exitCode = $this->executeCommand($command);
42630 if ($exitCode) {
42631 $errorOutput = $this->process->getErrorOutput();
42632 $index = strpos($errorOutput, $this->getUser());
42633 if ($index === false) {
42634 $index = strpos($errorOutput, 'p4');
42635 if ($index === false) {
42636 return false;
42637 }
42638 throw new \Exception('p4 command not found in path: ' . $errorOutput);
42639 }
42640 throw new \Exception('Invalid user name: ' . $this->getUser());
42641 }
42642
42643 return true;
42644 }
42645
42646 public function connectClient()
42647 {
42648 $p4CreateClientCommand = $this->generateP4Command(
42649 'client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())
42650 );
42651 $this->executeCommand($p4CreateClientCommand);
42652 }
42653
42654 public function syncCodeBase($sourceReference)
42655 {
42656 $prevDir = getcwd();
42657 chdir($this->path);
42658 $p4SyncCommand = $this->generateP4Command('sync -f ');
42659 if (null !== $sourceReference) {
42660 $p4SyncCommand = $p4SyncCommand . '@' . $sourceReference;
42661 }
42662 $this->executeCommand($p4SyncCommand);
42663 chdir($prevDir);
42664 }
42665
42666 public function writeClientSpecToFile($spec)
42667 {
42668 fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
42669 fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL);
42670 fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL);
42671 fwrite($spec, 'Owner:  ' . $this->getUser() . PHP_EOL . PHP_EOL);
42672 fwrite($spec, 'Description:' . PHP_EOL);
42673 fwrite($spec, '  Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL);
42674 fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL);
42675 fwrite($spec, 'Options:  noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL);
42676 fwrite($spec, 'SubmitOptions:  revertunchanged' . PHP_EOL . PHP_EOL);
42677 fwrite($spec, 'LineEnd:  local' . PHP_EOL . PHP_EOL);
42678 if ($this->isStream()) {
42679 fwrite($spec, 'Stream:' . PHP_EOL);
42680 fwrite($spec, '  ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL);
42681 } else {
42682 fwrite(
42683 $spec,
42684 'View:  ' . $this->getStream() . '/...  //' . $this->getClient() . '/... ' . PHP_EOL
42685 );
42686 }
42687 }
42688
42689 public function writeP4ClientSpec()
42690 {
42691 $clientSpec = $this->getP4ClientSpec();
42692 $spec = fopen($clientSpec, 'w');
42693 try {
42694 $this->writeClientSpecToFile($spec);
42695 } catch (\Exception $e) {
42696 fclose($spec);
42697 throw $e;
42698 }
42699 fclose($spec);
42700 }
42701
42702 protected function read($pipe, $name)
42703 {
42704 if (feof($pipe)) {
42705 return;
42706 }
42707 $line = fgets($pipe);
42708 while ($line !== false) {
42709 $line = fgets($pipe);
42710 }
42711
42712 return;
42713 }
42714
42715 public function windowsLogin($password)
42716 {
42717 $command = $this->generateP4Command(' login -a');
42718 $process = new Process($command, null, null, $password);
42719
42720 return $process->run();
42721 }
42722
42723 public function p4Login()
42724 {
42725 $this->queryP4User();
42726 if (!$this->isLoggedIn()) {
42727 $password = $this->queryP4Password();
42728 if ($this->windowsFlag) {
42729 $this->windowsLogin($password);
42730 } else {
42731 $command = 'echo ' . $password . ' | ' . $this->generateP4Command(' login -a', false);
42732 $exitCode = $this->executeCommand($command);
42733 $result = trim($this->commandResult);
42734 if ($exitCode) {
42735 throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
42736 }
42737 }
42738 }
42739 }
42740
42741 public function getComposerInformation($identifier)
42742 {
42743 $composerFileContent = $this->getFileContent('composer.json', $identifier);
42744
42745 if (!$composerFileContent) {
42746 return;
42747 }
42748
42749 return json_decode($composerFileContent, true);
42750 }
42751
42752 public function getFileContent($file, $identifier)
42753 {
42754 $path = $this->getFilePath($file, $identifier);
42755
42756 $command = $this->generateP4Command(' print ' . $path);
42757 $this->executeCommand($command);
42758 $result = $this->commandResult;
42759
42760 if (!trim($result)) {
42761 return null;
42762 }
42763
42764 return $result;
42765 }
42766
42767 public function getFilePath($file, $identifier)
42768 {
42769 $index = strpos($identifier, '@');
42770 if ($index === false) {
42771 $path = $identifier. '/' . $file;
42772
42773 return $path;
42774 }
42775
42776 $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index);
42777 $command = $this->generateP4Command(' files ' . $path, false);
42778 $this->executeCommand($command);
42779 $result = $this->commandResult;
42780 $index2 = strpos($result, 'no such file(s).');
42781 if ($index2 === false) {
42782 $index3 = strpos($result, 'change');
42783 if ($index3 !== false) {
42784 $phrase = trim(substr($result, $index3));
42785 $fields = explode(' ', $phrase);
42786
42787 return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1];
42788 }
42789 }
42790
42791 return null;
42792 }
42793
42794 public function getBranches()
42795 {
42796 $possibleBranches = array();
42797 if (!$this->isStream()) {
42798 $possibleBranches[$this->p4Branch] = $this->getStream();
42799 } else {
42800 $command = $this->generateP4Command('streams //' . $this->p4Depot . '/...');
42801 $this->executeCommand($command);
42802 $result = $this->commandResult;
42803 $resArray = explode(PHP_EOL, $result);
42804 foreach ($resArray as $line) {
42805 $resBits = explode(' ', $line);
42806 if (count($resBits) > 4) {
42807 $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
42808 $possibleBranches[$branch] = $resBits[1];
42809 }
42810 }
42811 }
42812 $command = $this->generateP4Command('changes '. $this->getStream() . '/...', false);
42813 $this->executeCommand($command);
42814 $result = $this->commandResult;
42815 $resArray = explode(PHP_EOL, $result);
42816 $lastCommit = $resArray[0];
42817 $lastCommitArr = explode(' ', $lastCommit);
42818 $lastCommitNum = $lastCommitArr[1];
42819
42820 $branches = array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
42821
42822 return $branches;
42823 }
42824
42825 public function getTags()
42826 {
42827 $command = $this->generateP4Command('labels');
42828 $this->executeCommand($command);
42829 $result = $this->commandResult;
42830 $resArray = explode(PHP_EOL, $result);
42831 $tags = array();
42832 foreach ($resArray as $line) {
42833 $index = strpos($line, 'Label');
42834 if (!($index === false)) {
42835 $fields = explode(' ', $line);
42836 $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
42837 }
42838 }
42839
42840 return $tags;
42841 }
42842
42843 public function checkStream()
42844 {
42845 $command = $this->generateP4Command('depots', false);
42846 $this->executeCommand($command);
42847 $result = $this->commandResult;
42848 $resArray = explode(PHP_EOL, $result);
42849 foreach ($resArray as $line) {
42850 $index = strpos($line, 'Depot');
42851 if (!($index === false)) {
42852 $fields = explode(' ', $line);
42853 if (strcmp($this->p4Depot, $fields[1]) === 0) {
42854 $this->p4DepotType = $fields[3];
42855
42856 return $this->isStream();
42857 }
42858 }
42859 }
42860
42861 return false;
42862 }
42863
42864
42865
42866
42867
42868 protected function getChangeList($reference)
42869 {
42870 $index = strpos($reference, '@');
42871 if ($index === false) {
42872 return null;
42873 }
42874 $label = substr($reference, $index);
42875 $command = $this->generateP4Command(' changes -m1 ' . $label);
42876 $this->executeCommand($command);
42877 $changes = $this->commandResult;
42878 if (strpos($changes, 'Change') !== 0) {
42879 return null;
42880 }
42881 $fields = explode(' ', $changes);
42882
42883 return $fields[1];
42884 }
42885
42886
42887
42888
42889
42890
42891 public function getCommitLogs($fromReference, $toReference)
42892 {
42893 $fromChangeList = $this->getChangeList($fromReference);
42894 if ($fromChangeList === null) {
42895 return null;
42896 }
42897 $toChangeList = $this->getChangeList($toReference);
42898 if ($toChangeList === null) {
42899 return null;
42900 }
42901 $index = strpos($fromReference, '@');
42902 $main = substr($fromReference, 0, $index) . '/...';
42903 $command = $this->generateP4Command('filelog ' . $main . '@' . $fromChangeList. ',' . $toChangeList);
42904 $this->executeCommand($command);
42905
42906 return $this->commandResult;
42907 }
42908
42909 public function getFilesystem()
42910 {
42911 if (empty($this->filesystem)) {
42912 $this->filesystem = new Filesystem($this->process);
42913 }
42914
42915 return $this->filesystem;
42916 }
42917
42918 public function setFilesystem(Filesystem $fs)
42919 {
42920 $this->filesystem = $fs;
42921 }
42922 }
42923 <?php
42924
42925
42926
42927
42928
42929
42930
42931
42932
42933
42934
42935 namespace Composer\Util;
42936
42937
42938
42939
42940
42941
42942 class Platform
42943 {
42944
42945
42946
42947
42948
42949
42950 public static function expandPath($path)
42951 {
42952 if (preg_match('#^~[\\/]#', $path)) {
42953 return self::getUserDirectory() . substr($path, 1);
42954 }
42955
42956 return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
42957
42958  if (Platform::isWindows() && $matches['var'] == 'HOME') {
42959 return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches['path'];
42960 }
42961
42962 return getenv($matches['var']) . $matches['path'];
42963 }, $path);
42964 }
42965
42966
42967
42968
42969
42970 public static function getUserDirectory()
42971 {
42972 if (false !== ($home = getenv('HOME'))) {
42973 return $home;
42974 }
42975
42976 if (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) {
42977 return $home;
42978 }
42979
42980 if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
42981 $info = posix_getpwuid(posix_getuid());
42982
42983 return $info['dir'];
42984 }
42985
42986 throw new \RuntimeException('Could not determine user directory');
42987 }
42988
42989
42990
42991
42992 public static function isWindows()
42993 {
42994 return defined('PHP_WINDOWS_VERSION_BUILD');
42995 }
42996
42997
42998
42999
43000
43001 public static function strlen($str)
43002 {
43003 static $useMbString = null;
43004 if (null === $useMbString) {
43005 $useMbString = function_exists('mb_strlen') && ini_get('mbstring.func_overload');
43006 }
43007
43008 if ($useMbString) {
43009 return mb_strlen($str, '8bit');
43010 }
43011
43012 return strlen($str);
43013 }
43014 }
43015 <?php
43016
43017
43018
43019
43020
43021
43022
43023
43024
43025
43026
43027 namespace Composer\Util;
43028
43029 use Composer\IO\IOInterface;
43030 use Symfony\Component\Process\Process;
43031 use Symfony\Component\Process\ProcessUtils;
43032
43033
43034
43035
43036 class ProcessExecutor
43037 {
43038 protected static $timeout = 300;
43039
43040 protected $captureOutput;
43041 protected $errorOutput;
43042 protected $io;
43043
43044 public function __construct(IOInterface $io = null)
43045 {
43046 $this->io = $io;
43047 }
43048
43049
43050
43051
43052
43053
43054
43055
43056
43057
43058 public function execute($command, &$output = null, $cwd = null)
43059 {
43060 if ($this->io && $this->io->isDebug()) {
43061 $safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
43062 if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) {
43063 return '://***:***@';
43064 }
43065
43066 return '://'.$m['user'].':***@';
43067 }, $command);
43068 $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
43069 }
43070
43071
43072  
43073  if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) {
43074 $cwd = realpath(getcwd());
43075 }
43076
43077 $this->captureOutput = count(func_get_args()) > 1;
43078 $this->errorOutput = null;
43079 $process = new Process($command, $cwd, null, null, static::getTimeout());
43080
43081 $callback = is_callable($output) ? $output : array($this, 'outputHandler');
43082 $process->run($callback);
43083
43084 if ($this->captureOutput && !is_callable($output)) {
43085 $output = $process->getOutput();
43086 }
43087
43088 $this->errorOutput = $process->getErrorOutput();
43089
43090 return $process->getExitCode();
43091 }
43092
43093 public function splitLines($output)
43094 {
43095 $output = trim($output);
43096
43097 return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output);
43098 }
43099
43100
43101
43102
43103
43104
43105 public function getErrorOutput()
43106 {
43107 return $this->errorOutput;
43108 }
43109
43110 public function outputHandler($type, $buffer)
43111 {
43112 if ($this->captureOutput) {
43113 return;
43114 }
43115
43116 if (null === $this->io) {
43117 echo $buffer;
43118
43119 return;
43120 }
43121
43122 if (Process::ERR === $type) {
43123 $this->io->writeError($buffer, false);
43124 } else {
43125 $this->io->write($buffer, false);
43126 }
43127 }
43128
43129 public static function getTimeout()
43130 {
43131 return static::$timeout;
43132 }
43133
43134 public static function setTimeout($timeout)
43135 {
43136 static::$timeout = $timeout;
43137 }
43138
43139
43140
43141
43142
43143
43144
43145
43146 public static function escape($argument)
43147 {
43148 if (method_exists('Symfony\Component\Process\ProcessUtils', 'escapeArgument')) {
43149 return ProcessUtils::escapeArgument($argument);
43150 }
43151
43152 return self::escapeArgument($argument);
43153 }
43154
43155
43156
43157
43158
43159
43160
43161
43162 private static function escapeArgument($argument)
43163 {
43164
43165  
43166  
43167  
43168  if ('\\' === DIRECTORY_SEPARATOR) {
43169 if ('' === $argument) {
43170 return escapeshellarg($argument);
43171 }
43172
43173 $escapedArgument = '';
43174 $quote = false;
43175 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
43176 if ('"' === $part) {
43177 $escapedArgument .= '\\"';
43178 } elseif (self::isSurroundedBy($part, '%')) {
43179
43180  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
43181 } else {
43182
43183  if ('\\' === substr($part, -1)) {
43184 $part .= '\\';
43185 }
43186 $quote = true;
43187 $escapedArgument .= $part;
43188 }
43189 }
43190 if ($quote) {
43191 $escapedArgument = '"'.$escapedArgument.'"';
43192 }
43193
43194 return $escapedArgument;
43195 }
43196
43197 return "'".str_replace("'", "'\\''", $argument)."'";
43198 }
43199
43200 private static function isSurroundedBy($arg, $char)
43201 {
43202 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
43203 }
43204 }
43205 <?php
43206
43207
43208
43209
43210
43211
43212
43213
43214
43215
43216
43217 namespace Composer\Util;
43218
43219 use Composer\Config;
43220 use Composer\IO\IOInterface;
43221 use Composer\Downloader\TransportException;
43222 use Composer\CaBundle\CaBundle;
43223 use Psr\Log\LoggerInterface;
43224
43225
43226
43227
43228
43229
43230 class RemoteFilesystem
43231 {
43232 private $io;
43233 private $config;
43234 private $scheme;
43235 private $bytesMax;
43236 private $originUrl;
43237 private $fileUrl;
43238 private $fileName;
43239 private $retry;
43240 private $progress;
43241 private $lastProgress;
43242 private $options = array();
43243 private $peerCertificateMap = array();
43244 private $disableTls = false;
43245 private $retryAuthFailure;
43246 private $lastHeaders;
43247 private $storeAuth;
43248 private $degradedMode = false;
43249 private $redirects;
43250 private $maxRedirects = 20;
43251
43252
43253
43254
43255
43256
43257
43258
43259
43260 public function __construct(IOInterface $io, Config $config = null, array $options = array(), $disableTls = false)
43261 {
43262 $this->io = $io;
43263
43264
43265  
43266  if ($disableTls === false) {
43267 $this->options = $this->getTlsDefaults($options);
43268 } else {
43269 $this->disableTls = true;
43270 }
43271
43272
43273  $this->options = array_replace_recursive($this->options, $options);
43274 $this->config = $config;
43275 }
43276
43277
43278
43279
43280
43281
43282
43283
43284
43285
43286
43287
43288 public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array())
43289 {
43290 return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
43291 }
43292
43293
43294
43295
43296
43297
43298
43299
43300
43301
43302
43303 public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
43304 {
43305 return $this->get($originUrl, $fileUrl, $options, null, $progress);
43306 }
43307
43308
43309
43310
43311
43312
43313 public function getOptions()
43314 {
43315 return $this->options;
43316 }
43317
43318
43319
43320
43321
43322
43323 public function setOptions(array $options)
43324 {
43325 $this->options = array_replace_recursive($this->options, $options);
43326 }
43327
43328 public function isTlsDisabled()
43329 {
43330 return $this->disableTls === true;
43331 }
43332
43333
43334
43335
43336
43337
43338 public function getLastHeaders()
43339 {
43340 return $this->lastHeaders;
43341 }
43342
43343
43344
43345
43346
43347
43348 public function findHeaderValue(array $headers, $name)
43349 {
43350 $value = null;
43351 foreach ($headers as $header) {
43352 if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
43353 $value = $match[1];
43354 } elseif (preg_match('{^HTTP/}i', $header)) {
43355
43356  
43357  $value = null;
43358 }
43359 }
43360
43361 return $value;
43362 }
43363
43364
43365
43366
43367
43368 public function findStatusCode(array $headers)
43369 {
43370 $value = null;
43371 foreach ($headers as $header) {
43372 if (preg_match('{^HTTP/\S+ (\d+)}i', $header, $match)) {
43373
43374  
43375  $value = (int) $match[1];
43376 }
43377 }
43378
43379 return $value;
43380 }
43381
43382
43383
43384
43385
43386 public function findStatusMessage(array $headers)
43387 {
43388 $value = null;
43389 foreach ($headers as $header) {
43390 if (preg_match('{^HTTP/\S+ \d+}i', $header)) {
43391
43392  
43393  $value = $header;
43394 }
43395 }
43396
43397 return $value;
43398 }
43399
43400
43401
43402
43403
43404
43405
43406
43407
43408
43409
43410
43411
43412
43413
43414 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
43415 {
43416 if (strpos($originUrl, '.github.com') === (strlen($originUrl) - 11)) {
43417 $originUrl = 'github.com';
43418 }
43419
43420
43421  
43422  if (
43423 $this->config
43424 && is_array($this->config->get('gitlab-domains'))
43425 && false === strpos($originUrl, '/')
43426 && !in_array($originUrl, $this->config->get('gitlab-domains'))
43427 ) {
43428 foreach ($this->config->get('gitlab-domains') as $gitlabDomain) {
43429 if (0 === strpos($gitlabDomain, $originUrl)) {
43430 $originUrl = $gitlabDomain;
43431 break;
43432 }
43433 }
43434 unset($gitlabDomain);
43435 }
43436
43437 $this->scheme = parse_url($fileUrl, PHP_URL_SCHEME);
43438 $this->bytesMax = 0;
43439 $this->originUrl = $originUrl;
43440 $this->fileUrl = $fileUrl;
43441 $this->fileName = $fileName;
43442 $this->progress = $progress;
43443 $this->lastProgress = null;
43444 $this->retryAuthFailure = true;
43445 $this->lastHeaders = array();
43446 $this->redirects = 1; 
43447
43448
43449  if (preg_match('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $fileUrl, $match)) {
43450 $this->io->setAuthentication($originUrl, rawurldecode($match[1]), rawurldecode($match[2]));
43451 }
43452
43453 $tempAdditionalOptions = $additionalOptions;
43454 if (isset($tempAdditionalOptions['retry-auth-failure'])) {
43455 $this->retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure'];
43456
43457 unset($tempAdditionalOptions['retry-auth-failure']);
43458 }
43459
43460 $isRedirect = false;
43461 if (isset($tempAdditionalOptions['redirects'])) {
43462 $this->redirects = $tempAdditionalOptions['redirects'];
43463 $isRedirect = true;
43464
43465 unset($tempAdditionalOptions['redirects']);
43466 }
43467
43468 $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions);
43469 unset($tempAdditionalOptions);
43470
43471 $origFileUrl = $fileUrl;
43472
43473 if (isset($options['github-token'])) {
43474
43475  if (preg_match('{^https?://([a-z0-9-]+\.)*github\.com/}', $fileUrl)) {
43476 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['github-token'];
43477 }
43478 unset($options['github-token']);
43479 }
43480
43481 if (isset($options['gitlab-token'])) {
43482 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['gitlab-token'];
43483 unset($options['gitlab-token']);
43484 }
43485
43486 if (isset($options['http'])) {
43487 $options['http']['ignore_errors'] = true;
43488 }
43489
43490 if ($this->degradedMode && substr($fileUrl, 0, 26) === 'http://repo.packagist.org/') {
43491
43492  $fileUrl = 'http://' . gethostbyname('repo.packagist.org') . substr($fileUrl, 20);
43493 $degradedPackagist = true;
43494 }
43495
43496 $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
43497
43498 $actualContextOptions = stream_context_get_options($ctx);
43499 $usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : '';
43500 $this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $origFileUrl . $usingProxy, true, IOInterface::DEBUG);
43501 unset($origFileUrl, $actualContextOptions);
43502
43503
43504  if ((!preg_match('{^http://(repo\.)?packagist\.org/p/}', $fileUrl) || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist) && $this->config) {
43505 $this->config->prohibitUrlByConfig($fileUrl, $this->io);
43506 }
43507
43508 if ($this->progress && !$isRedirect) {
43509 $this->io->writeError("Downloading (<comment>connecting...</comment>)", false);
43510 }
43511
43512 $errorMessage = '';
43513 $errorCode = 0;
43514 $result = false;
43515 set_error_handler(function ($code, $msg) use (&$errorMessage) {
43516 if ($errorMessage) {
43517 $errorMessage .= "\n";
43518 }
43519 $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg);
43520 });
43521 try {
43522 $result = $this->getRemoteContents($originUrl, $fileUrl, $ctx, $http_response_header);
43523
43524 if (!empty($http_response_header[0])) {
43525 $statusCode = $this->findStatusCode($http_response_header);
43526 if (in_array($statusCode, array(401, 403)) && $this->retryAuthFailure) {
43527 $warning = null;
43528 if ($this->findHeaderValue($http_response_header, 'content-type') === 'application/json') {
43529 $data = json_decode($result, true);
43530 if (!empty($data['warning'])) {
43531 $warning = $data['warning'];
43532 }
43533 }
43534 $this->promptAuthAndRetry($statusCode, $this->findStatusMessage($http_response_header), $warning, $http_response_header);
43535 }
43536 }
43537
43538 $contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
43539 if ($contentLength && Platform::strlen($result) < $contentLength) {
43540
43541  $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength);
43542 $e->setHeaders($http_response_header);
43543 $e->setStatusCode($this->findStatusCode($http_response_header));
43544 $e->setResponse($result);
43545 $this->io->writeError('Content-Length mismatch, received '.Platform::strlen($result).' out of '.$contentLength.' bytes: (' . base64_encode($result).')', true, IOInterface::DEBUG);
43546
43547 throw $e;
43548 }
43549
43550 if (PHP_VERSION_ID < 50600 && !empty($options['ssl']['peer_fingerprint'])) {
43551
43552  $params = stream_context_get_params($ctx);
43553 $expectedPeerFingerprint = $options['ssl']['peer_fingerprint'];
43554 $peerFingerprint = TlsHelper::getCertificateFingerprint($params['options']['ssl']['peer_certificate']);
43555
43556
43557  if ($expectedPeerFingerprint !== $peerFingerprint) {
43558 throw new TransportException('Peer fingerprint did not match');
43559 }
43560 }
43561 } catch (\Exception $e) {
43562 if ($e instanceof TransportException && !empty($http_response_header[0])) {
43563 $e->setHeaders($http_response_header);
43564 $e->setStatusCode($this->findStatusCode($http_response_header));
43565 }
43566 if ($e instanceof TransportException && $result !== false) {
43567 $e->setResponse($result);
43568 }
43569 $result = false;
43570 }
43571 if ($errorMessage && !ini_get('allow_url_fopen')) {
43572 $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
43573 }
43574 restore_error_handler();
43575 if (isset($e) && !$this->retry) {
43576 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
43577 $this->degradedMode = true;
43578 $this->io->writeError('');
43579 $this->io->writeError(array(
43580 '<error>'.$e->getMessage().'</error>',
43581 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
43582 ));
43583
43584 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
43585 }
43586
43587 throw $e;
43588 }
43589
43590 $statusCode = null;
43591 $contentType = null;
43592 if (!empty($http_response_header[0])) {
43593 $statusCode = $this->findStatusCode($http_response_header);
43594 $contentType = $this->findHeaderValue($http_response_header, 'content-type');
43595 }
43596
43597
43598  if ($originUrl === 'bitbucket.org'
43599 && !$this->isPublicBitBucketDownload($fileUrl)
43600 && substr($fileUrl, -4) === '.zip'
43601 && $contentType && preg_match('{^text/html\b}i', $contentType)
43602 ) {
43603 $result = false;
43604 if ($this->retryAuthFailure) {
43605 $this->promptAuthAndRetry(401);
43606 }
43607 }
43608
43609
43610  if ($statusCode === 404
43611 && $this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)
43612 && false !== strpos($fileUrl, 'archive.zip')
43613 ) {
43614 $result = false;
43615 if ($this->retryAuthFailure) {
43616 $this->promptAuthAndRetry(401);
43617 }
43618 }
43619
43620
43621  $hasFollowedRedirect = false;
43622 if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
43623 $hasFollowedRedirect = true;
43624 $result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
43625 }
43626
43627
43628  if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
43629 if (!$this->retry) {
43630 if ($this->progress && !$this->retry && !$isRedirect) {
43631 $this->io->overwriteError("Downloading (<error>failed</error>)", false);
43632 }
43633
43634 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $statusCode);
43635 $e->setHeaders($http_response_header);
43636 $e->setResponse($result);
43637 $e->setStatusCode($statusCode);
43638 throw $e;
43639 }
43640 $result = false;
43641 }
43642
43643 if ($this->progress && !$this->retry && !$isRedirect) {
43644 $this->io->overwriteError("Downloading (".($result === false ? '<error>failed</error>' : '<comment>100%</comment>').")", false);
43645 }
43646
43647
43648  if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) {
43649 $contentEncoding = $this->findHeaderValue($http_response_header, 'content-encoding');
43650 $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
43651
43652 if ($decode) {
43653 try {
43654 if (PHP_VERSION_ID >= 50400) {
43655 $result = zlib_decode($result);
43656 } else {
43657
43658  $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
43659 }
43660
43661 if (!$result) {
43662 throw new TransportException('Failed to decode zlib stream');
43663 }
43664 } catch (\Exception $e) {
43665 if ($this->degradedMode) {
43666 throw $e;
43667 }
43668
43669 $this->degradedMode = true;
43670 $this->io->writeError(array(
43671 '',
43672 '<error>Failed to decode response: '.$e->getMessage().'</error>',
43673 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
43674 ));
43675
43676 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
43677 }
43678 }
43679 }
43680
43681
43682  if (false !== $result && null !== $fileName && !$isRedirect) {
43683 if ('' === $result) {
43684 throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
43685 }
43686
43687 $errorMessage = '';
43688 set_error_handler(function ($code, $msg) use (&$errorMessage) {
43689 if ($errorMessage) {
43690 $errorMessage .= "\n";
43691 }
43692 $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg);
43693 });
43694 $result = (bool) file_put_contents($fileName, $result);
43695 restore_error_handler();
43696 if (false === $result) {
43697 throw new TransportException('The "'.$this->fileUrl.'" file could not be written to '.$fileName.': '.$errorMessage);
43698 }
43699 }
43700
43701
43702  if (false === $result && false !== strpos($errorMessage, 'Peer certificate') && PHP_VERSION_ID < 50600) {
43703
43704  
43705  
43706  
43707  
43708  
43709  
43710  
43711  
43712  
43713  
43714  
43715  
43716  
43717  
43718  
43719  if (CaBundle::isOpensslParseSafe()) {
43720 $certDetails = $this->getCertificateCnAndFp($this->fileUrl, $options);
43721
43722 if ($certDetails) {
43723 $this->peerCertificateMap[$this->getUrlAuthority($this->fileUrl)] = $certDetails;
43724
43725 $this->retry = true;
43726 }
43727 } else {
43728 $this->io->writeError('');
43729 $this->io->writeError(sprintf(
43730 '<error>Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.</error>',
43731 PHP_VERSION
43732 ));
43733 }
43734 }
43735
43736 if ($this->retry) {
43737 $this->retry = false;
43738
43739 $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
43740
43741 if ($this->storeAuth && $this->config) {
43742 $authHelper = new AuthHelper($this->io, $this->config);
43743 $authHelper->storeAuth($this->originUrl, $this->storeAuth);
43744 $this->storeAuth = false;
43745 }
43746
43747 return $result;
43748 }
43749
43750 if (false === $result) {
43751 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded: '.$errorMessage, $errorCode);
43752 if (!empty($http_response_header[0])) {
43753 $e->setHeaders($http_response_header);
43754 }
43755
43756 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
43757 $this->degradedMode = true;
43758 $this->io->writeError('');
43759 $this->io->writeError(array(
43760 '<error>'.$e->getMessage().'</error>',
43761 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
43762 ));
43763
43764 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
43765 }
43766
43767 throw $e;
43768 }
43769
43770 if (!empty($http_response_header[0])) {
43771 $this->lastHeaders = $http_response_header;
43772 }
43773
43774 return $result;
43775 }
43776
43777
43778
43779
43780
43781
43782
43783
43784
43785
43786 protected function getRemoteContents($originUrl, $fileUrl, $context, array &$responseHeaders = null)
43787 {
43788 try {
43789 $e = null;
43790 $result = file_get_contents($fileUrl, false, $context);
43791 } catch (\Throwable $e) {
43792 } catch (\Exception $e) {
43793 }
43794
43795 $responseHeaders = isset($http_response_header) ? $http_response_header : array();
43796
43797 if (null !== $e) {
43798 throw $e;
43799 }
43800
43801 return $result;
43802 }
43803
43804
43805
43806
43807
43808
43809
43810
43811
43812
43813
43814
43815 protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
43816 {
43817 switch ($notificationCode) {
43818 case STREAM_NOTIFY_FAILURE:
43819 if (400 === $messageCode) {
43820
43821  
43822  throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
43823 }
43824 break;
43825
43826 case STREAM_NOTIFY_FILE_SIZE_IS:
43827 $this->bytesMax = $bytesMax;
43828 break;
43829
43830 case STREAM_NOTIFY_PROGRESS:
43831 if ($this->bytesMax > 0 && $this->progress) {
43832 $progression = min(100, round($bytesTransferred / $this->bytesMax * 100));
43833
43834 if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) {
43835 $this->lastProgress = $progression;
43836 $this->io->overwriteError("Downloading (<comment>$progression%</comment>)", false);
43837 }
43838 }
43839 break;
43840
43841 default:
43842 break;
43843 }
43844 }
43845
43846 protected function promptAuthAndRetry($httpStatus, $reason = null, $warning = null, $headers = array())
43847 {
43848 if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
43849 $gitHubUtil = new GitHub($this->io, $this->config, null);
43850 $message = "\n";
43851
43852 $rateLimited = $gitHubUtil->isRateLimited($headers);
43853 if ($rateLimited) {
43854 $rateLimit = $gitHubUtil->getRateLimit($headers);
43855 if ($this->io->hasAuthentication($this->originUrl)) {
43856 $message = 'Review your configured GitHub OAuth token or enter a new one to go over the API rate limit.';
43857 } else {
43858 $message = 'Create a GitHub OAuth token to go over the API rate limit.';
43859 }
43860
43861 $message = sprintf(
43862 '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.',
43863 $rateLimit['limit'],
43864 $rateLimit['reset']
43865 )."\n";
43866 } else {
43867 $message .= 'Could not fetch '.$this->fileUrl.', please ';
43868 if ($this->io->hasAuthentication($this->originUrl)) {
43869 $message .= 'review your configured GitHub OAuth token or enter a new one to access private repos';
43870 } else {
43871 $message .= 'create a GitHub OAuth token to access private repos';
43872 }
43873 }
43874
43875 if (!$gitHubUtil->authorizeOAuth($this->originUrl)
43876 && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($this->originUrl, $message))
43877 ) {
43878 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
43879 }
43880 } elseif ($this->config && in_array($this->originUrl, $this->config->get('gitlab-domains'), true)) {
43881 $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');
43882 $gitLabUtil = new GitLab($this->io, $this->config, null);
43883
43884 if ($this->io->hasAuthentication($this->originUrl) && ($auth = $this->io->getAuthentication($this->originUrl)) && $auth['password'] === 'private-token') {
43885 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
43886 }
43887
43888 if (!$gitLabUtil->authorizeOAuth($this->originUrl)
43889 && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, $message))
43890 ) {
43891 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
43892 }
43893 } elseif ($this->config && $this->originUrl === 'bitbucket.org') {
43894 $askForOAuthToken = true;
43895 if ($this->io->hasAuthentication($this->originUrl)) {
43896 $auth = $this->io->getAuthentication($this->originUrl);
43897 if ($auth['username'] !== 'x-token-auth') {
43898 $bitbucketUtil = new Bitbucket($this->io, $this->config);
43899 $accessToken = $bitbucketUtil->requestToken($this->originUrl, $auth['username'], $auth['password']);
43900 if (!empty($accessToken)) {
43901 $this->io->setAuthentication($this->originUrl, 'x-token-auth', $accessToken);
43902 $askForOAuthToken = false;
43903 }
43904 } else {
43905 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
43906 }
43907 }
43908
43909 if ($askForOAuthToken) {
43910 $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');
43911 $bitBucketUtil = new Bitbucket($this->io, $this->config);
43912 if (! $bitBucketUtil->authorizeOAuth($this->originUrl)
43913 && (! $this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($this->originUrl, $message))
43914 ) {
43915 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
43916 }
43917 }
43918 } else {
43919
43920  if ($httpStatus === 404) {
43921 return;
43922 }
43923
43924
43925  if (!$this->io->isInteractive()) {
43926 if ($httpStatus === 401) {
43927 $message = "The '" . $this->fileUrl . "' URL required authentication.\nYou must be using the interactive console to authenticate";
43928 }
43929 if ($httpStatus === 403) {
43930 $message = "The '" . $this->fileUrl . "' URL could not be accessed: " . $reason;
43931 }
43932
43933 throw new TransportException($message, $httpStatus);
43934 }
43935
43936  if ($this->io->hasAuthentication($this->originUrl)) {
43937 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
43938 }
43939
43940 $this->io->overwriteError('');
43941 if ($warning) {
43942 $this->io->writeError('    <warning>'.$warning.'</warning>');
43943 }
43944 $this->io->writeError('    Authentication required (<info>'.parse_url($this->fileUrl, PHP_URL_HOST).'</info>):');
43945 $username = $this->io->ask('      Username: ');
43946 $password = $this->io->askAndHideAnswer('      Password: ');
43947 $this->io->setAuthentication($this->originUrl, $username, $password);
43948 $this->storeAuth = $this->config->get('store-auths');
43949 }
43950
43951 $this->retry = true;
43952 throw new TransportException('RETRY');
43953 }
43954
43955 protected function getOptionsForUrl($originUrl, $additionalOptions)
43956 {
43957 $tlsOptions = array();
43958
43959
43960  if ($this->disableTls === false && PHP_VERSION_ID < 50600 && !stream_is_local($this->fileUrl)) {
43961 $host = parse_url($this->fileUrl, PHP_URL_HOST);
43962
43963 if (PHP_VERSION_ID < 50304) {
43964
43965  
43966  
43967  
43968
43969 if ($host === 'github.com' || $host === 'api.github.com') {
43970 $host = '*.github.com';
43971 }
43972 }
43973
43974 $tlsOptions['ssl']['CN_match'] = $host;
43975 $tlsOptions['ssl']['SNI_server_name'] = $host;
43976
43977 $urlAuthority = $this->getUrlAuthority($this->fileUrl);
43978
43979 if (isset($this->peerCertificateMap[$urlAuthority])) {
43980
43981  $certMap = $this->peerCertificateMap[$urlAuthority];
43982
43983 $this->io->writeError('', true, IOInterface::DEBUG);
43984 $this->io->writeError(sprintf(
43985 'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
43986 $certMap['cn'],
43987 $urlAuthority
43988 ), true, IOInterface::DEBUG);
43989
43990 $tlsOptions['ssl']['CN_match'] = $certMap['cn'];
43991 $tlsOptions['ssl']['peer_fingerprint'] = $certMap['fp'];
43992 } elseif (!CaBundle::isOpensslParseSafe() && $host === 'repo.packagist.org') {
43993
43994  $tlsOptions['ssl']['CN_match'] = 'packagist.org';
43995 }
43996 }
43997
43998 $headers = array();
43999
44000 if (extension_loaded('zlib')) {
44001 $headers[] = 'Accept-Encoding: gzip';
44002 }
44003
44004 $options = array_replace_recursive($this->options, $tlsOptions, $additionalOptions);
44005 if (!$this->degradedMode) {
44006
44007  
44008  $options['http']['protocol_version'] = 1.1;
44009 $headers[] = 'Connection: close';
44010 }
44011
44012 if ($this->io->hasAuthentication($originUrl)) {
44013 $auth = $this->io->getAuthentication($originUrl);
44014 if ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
44015 $options['github-token'] = $auth['username'];
44016 } elseif ($this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
44017 if ($auth['password'] === 'oauth2') {
44018 $headers[] = 'Authorization: Bearer '.$auth['username'];
44019 } elseif ($auth['password'] === 'private-token') {
44020 $headers[] = 'PRIVATE-TOKEN: '.$auth['username'];
44021 }
44022 } elseif ('bitbucket.org' === $originUrl
44023 && $this->fileUrl !== Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']
44024 ) {
44025 if (!$this->isPublicBitBucketDownload($this->fileUrl)) {
44026 $headers[] = 'Authorization: Bearer ' . $auth['password'];
44027 }
44028 } else {
44029 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
44030 $headers[] = 'Authorization: Basic '.$authStr;
44031 }
44032 }
44033
44034 $options['http']['follow_location'] = 0;
44035
44036 if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
44037 $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
44038 }
44039 foreach ($headers as $header) {
44040 $options['http']['header'][] = $header;
44041 }
44042
44043 return $options;
44044 }
44045
44046 private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
44047 {
44048 if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
44049 if (parse_url($locationHeader, PHP_URL_SCHEME)) {
44050
44051  $targetUrl = $locationHeader;
44052 } elseif (parse_url($locationHeader, PHP_URL_HOST)) {
44053
44054  $targetUrl = $this->scheme.':'.$locationHeader;
44055 } elseif ('/' === $locationHeader[0]) {
44056
44057  $urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
44058
44059
44060  $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
44061 } else {
44062
44063  
44064  $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
44065 }
44066 }
44067
44068 if (!empty($targetUrl)) {
44069 $this->redirects++;
44070
44071 $this->io->writeError('', true, IOInterface::DEBUG);
44072 $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $targetUrl), true, IOInterface::DEBUG);
44073
44074 $additionalOptions['redirects'] = $this->redirects;
44075
44076 return $this->get(parse_url($targetUrl, PHP_URL_HOST), $targetUrl, $additionalOptions, $this->fileName, $this->progress);
44077 }
44078
44079 if (!$this->retry) {
44080 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
44081 $e->setHeaders($http_response_header);
44082 $e->setResponse($result);
44083
44084 throw $e;
44085 }
44086
44087 return false;
44088 }
44089
44090
44091
44092
44093
44094
44095 private function getTlsDefaults(array $options)
44096 {
44097 $ciphers = implode(':', array(
44098 'ECDHE-RSA-AES128-GCM-SHA256',
44099 'ECDHE-ECDSA-AES128-GCM-SHA256',
44100 'ECDHE-RSA-AES256-GCM-SHA384',
44101 'ECDHE-ECDSA-AES256-GCM-SHA384',
44102 'DHE-RSA-AES128-GCM-SHA256',
44103 'DHE-DSS-AES128-GCM-SHA256',
44104 'kEDH+AESGCM',
44105 'ECDHE-RSA-AES128-SHA256',
44106 'ECDHE-ECDSA-AES128-SHA256',
44107 'ECDHE-RSA-AES128-SHA',
44108 'ECDHE-ECDSA-AES128-SHA',
44109 'ECDHE-RSA-AES256-SHA384',
44110 'ECDHE-ECDSA-AES256-SHA384',
44111 'ECDHE-RSA-AES256-SHA',
44112 'ECDHE-ECDSA-AES256-SHA',
44113 'DHE-RSA-AES128-SHA256',
44114 'DHE-RSA-AES128-SHA',
44115 'DHE-DSS-AES128-SHA256',
44116 'DHE-RSA-AES256-SHA256',
44117 'DHE-DSS-AES256-SHA',
44118 'DHE-RSA-AES256-SHA',
44119 'AES128-GCM-SHA256',
44120 'AES256-GCM-SHA384',
44121 'AES128-SHA256',
44122 'AES256-SHA256',
44123 'AES128-SHA',
44124 'AES256-SHA',
44125 'AES',
44126 'CAMELLIA',
44127 'DES-CBC3-SHA',
44128 '!aNULL',
44129 '!eNULL',
44130 '!EXPORT',
44131 '!DES',
44132 '!RC4',
44133 '!MD5',
44134 '!PSK',
44135 '!aECDH',
44136 '!EDH-DSS-DES-CBC3-SHA',
44137 '!EDH-RSA-DES-CBC3-SHA',
44138 '!KRB5-DES-CBC3-SHA',
44139 ));
44140
44141
44142
44143
44144
44145
44146
44147 $defaults = array(
44148 'ssl' => array(
44149 'ciphers' => $ciphers,
44150 'verify_peer' => true,
44151 'verify_depth' => 7,
44152 'SNI_enabled' => true,
44153 'capture_peer_cert' => true,
44154 ),
44155 );
44156
44157 if (isset($options['ssl'])) {
44158 $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
44159 }
44160
44161 $caBundleLogger = $this->io instanceof LoggerInterface ? $this->io : null;
44162
44163
44164
44165
44166
44167 if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
44168 $result = CaBundle::getSystemCaRootBundlePath($caBundleLogger);
44169
44170 if (is_dir($result)) {
44171 $defaults['ssl']['capath'] = $result;
44172 } else {
44173 $defaults['ssl']['cafile'] = $result;
44174 }
44175 }
44176
44177 if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $caBundleLogger))) {
44178 throw new TransportException('The configured cafile was not valid or could not be read.');
44179 }
44180
44181 if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !is_readable($defaults['ssl']['capath']))) {
44182 throw new TransportException('The configured capath was not valid or could not be read.');
44183 }
44184
44185
44186
44187
44188 if (PHP_VERSION_ID >= 50413) {
44189 $defaults['ssl']['disable_compression'] = true;
44190 }
44191
44192 return $defaults;
44193 }
44194
44195
44196
44197
44198
44199
44200 private function getCertificateCnAndFp($url, $options)
44201 {
44202 if (PHP_VERSION_ID >= 50600) {
44203 throw new \BadMethodCallException(sprintf(
44204 '%s must not be used on PHP >= 5.6',
44205 __METHOD__
44206 ));
44207 }
44208
44209 $context = StreamContextFactory::getContext($url, $options, array('options' => array(
44210 'ssl' => array(
44211 'capture_peer_cert' => true,
44212 'verify_peer' => false, 
44213  ), ),
44214 ));
44215
44216
44217  
44218  if (false === $handle = @fopen($url, 'rb', false, $context)) {
44219 return;
44220 }
44221
44222
44223  fclose($handle);
44224 $handle = null;
44225
44226 $params = stream_context_get_params($context);
44227
44228 if (!empty($params['options']['ssl']['peer_certificate'])) {
44229 $peerCertificate = $params['options']['ssl']['peer_certificate'];
44230
44231 if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) {
44232 return array(
44233 'cn' => $commonName,
44234 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate),
44235 );
44236 }
44237 }
44238 }
44239
44240 private function getUrlAuthority($url)
44241 {
44242 $defaultPorts = array(
44243 'ftp' => 21,
44244 'http' => 80,
44245 'https' => 443,
44246 'ssh2.sftp' => 22,
44247 'ssh2.scp' => 22,
44248 );
44249
44250 $scheme = parse_url($url, PHP_URL_SCHEME);
44251
44252 if (!isset($defaultPorts[$scheme])) {
44253 throw new \InvalidArgumentException(sprintf(
44254 'Could not get default port for unknown scheme: %s',
44255 $scheme
44256 ));
44257 }
44258
44259 $defaultPort = $defaultPorts[$scheme];
44260 $port = parse_url($url, PHP_URL_PORT) ?: $defaultPort;
44261
44262 return parse_url($url, PHP_URL_HOST).':'.$port;
44263 }
44264
44265
44266
44267
44268
44269
44270
44271
44272 private function isPublicBitBucketDownload($urlToBitBucketFile)
44273 {
44274 $domain = parse_url($urlToBitBucketFile, PHP_URL_HOST);
44275 if (strpos($domain, 'bitbucket.org') === false) {
44276
44277  
44278  return true;
44279 }
44280
44281 $path = parse_url($urlToBitBucketFile, PHP_URL_PATH);
44282
44283
44284  
44285  $pathParts = explode('/', $path);
44286
44287 return count($pathParts) >= 4 && $pathParts[3] == 'downloads';
44288 }
44289 }
44290 <?php
44291
44292
44293
44294
44295
44296
44297
44298
44299
44300
44301
44302 namespace Composer\Util;
44303
44304
44305
44306
44307
44308
44309 class Silencer
44310 {
44311
44312
44313
44314 private static $stack = array();
44315
44316
44317
44318
44319
44320
44321
44322 public static function suppress($mask = null)
44323 {
44324 if (!isset($mask)) {
44325 $mask = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT;
44326 }
44327 $old = error_reporting();
44328 self::$stack[] = $old;
44329 error_reporting($old & ~$mask);
44330
44331 return $old;
44332 }
44333
44334
44335
44336
44337 public static function restore()
44338 {
44339 if (!empty(self::$stack)) {
44340 error_reporting(array_pop(self::$stack));
44341 }
44342 }
44343
44344
44345
44346
44347
44348
44349
44350
44351
44352
44353 public static function call($callable )
44354 {
44355 try {
44356 self::suppress();
44357 $result = call_user_func_array($callable, array_slice(func_get_args(), 1));
44358 self::restore();
44359
44360 return $result;
44361 } catch (\Exception $e) {
44362
44363  self::restore();
44364 throw $e;
44365 }
44366 }
44367 }
44368 <?php
44369
44370
44371
44372
44373
44374
44375
44376
44377
44378
44379
44380 namespace Composer\Util;
44381
44382 use Composer\Spdx\SpdxLicenses;
44383
44384 trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED);
44385
44386
44387
44388
44389 class SpdxLicense extends SpdxLicenses
44390 {
44391 }
44392 <?php
44393
44394
44395
44396
44397
44398
44399
44400
44401
44402
44403
44404 namespace Composer\Util;
44405
44406 use Composer\Composer;
44407
44408
44409
44410
44411
44412
44413
44414 final class StreamContextFactory
44415 {
44416
44417
44418
44419
44420
44421
44422
44423
44424
44425 public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
44426 {
44427 $options = array('http' => array(
44428
44429  'follow_location' => 1,
44430 'max_redirects' => 20,
44431 ));
44432
44433
44434  if (PHP_SAPI === 'cli' && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) {
44435 $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
44436 }
44437
44438
44439  if (!empty($_SERVER['CGI_HTTP_PROXY'])) {
44440 $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']);
44441 }
44442
44443
44444  if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
44445 $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
44446 }
44447
44448
44449  if (!empty($_SERVER['NO_PROXY']) || !empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
44450 $pattern = new NoProxyPattern(!empty($_SERVER['no_proxy']) ? $_SERVER['no_proxy'] : $_SERVER['NO_PROXY']);
44451 if ($pattern->test($url)) {
44452 unset($proxy);
44453 }
44454 }
44455
44456 if (!empty($proxy)) {
44457 $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
44458 $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
44459
44460 if (isset($proxy['port'])) {
44461 $proxyURL .= ":" . $proxy['port'];
44462 } elseif ('http://' == substr($proxyURL, 0, 7)) {
44463 $proxyURL .= ":80";
44464 } elseif ('https://' == substr($proxyURL, 0, 8)) {
44465 $proxyURL .= ":443";
44466 }
44467
44468
44469  $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
44470
44471 if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) {
44472 throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
44473 }
44474
44475 $options['http']['proxy'] = $proxyURL;
44476
44477
44478  switch (parse_url($url, PHP_URL_SCHEME)) {
44479 case 'http': 
44480  $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
44481 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
44482 $options['http']['request_fulluri'] = true;
44483 }
44484 break;
44485 case 'https': 
44486  $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
44487 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
44488 $options['http']['request_fulluri'] = true;
44489 }
44490 break;
44491 }
44492
44493
44494  if ('https' === parse_url($url, PHP_URL_SCHEME)) {
44495 $options['ssl']['SNI_enabled'] = true;
44496 if (PHP_VERSION_ID < 50600) {
44497 $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST);
44498 }
44499 }
44500
44501
44502  if (isset($proxy['user'])) {
44503 $auth = rawurldecode($proxy['user']);
44504 if (isset($proxy['pass'])) {
44505 $auth .= ':' . rawurldecode($proxy['pass']);
44506 }
44507 $auth = base64_encode($auth);
44508
44509
44510  if (isset($defaultOptions['http']['header'])) {
44511 if (is_string($defaultOptions['http']['header'])) {
44512 $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
44513 }
44514 $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
44515 } else {
44516 $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
44517 }
44518 }
44519 }
44520
44521 $options = array_replace_recursive($options, $defaultOptions);
44522
44523 if (isset($options['http']['header'])) {
44524 $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
44525 }
44526
44527 if (defined('HHVM_VERSION')) {
44528 $phpVersion = 'HHVM ' . HHVM_VERSION;
44529 } else {
44530 $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
44531 }
44532
44533 if (!isset($options['http']['header']) || false === stripos(implode('', $options['http']['header']), 'user-agent')) {
44534 $options['http']['header'][] = sprintf(
44535 'User-Agent: Composer/%s (%s; %s; %s%s)',
44536 Composer::VERSION === '@package_version@' ? 'source' : Composer::VERSION,
44537 function_exists('php_uname') ? php_uname('s') : 'Unknown',
44538 function_exists('php_uname') ? php_uname('r') : 'Unknown',
44539 $phpVersion,
44540 getenv('CI') ? '; CI' : ''
44541 );
44542 }
44543
44544 return stream_context_create($options, $defaultParams);
44545 }
44546
44547
44548
44549
44550
44551
44552
44553
44554
44555
44556
44557 private static function fixHttpHeaderField($header)
44558 {
44559 if (!is_array($header)) {
44560 $header = explode("\r\n", $header);
44561 }
44562 uasort($header, function ($el) {
44563 return stripos($el, 'content-type') === 0 ? 1 : -1;
44564 });
44565
44566 return $header;
44567 }
44568 }
44569 <?php
44570
44571
44572
44573
44574
44575
44576
44577
44578
44579
44580
44581 namespace Composer\Util;
44582
44583 use Composer\Config;
44584 use Composer\IO\IOInterface;
44585
44586
44587
44588
44589
44590 class Svn
44591 {
44592 const MAX_QTY_AUTH_TRIES = 5;
44593
44594
44595
44596
44597 protected $credentials;
44598
44599
44600
44601
44602 protected $hasAuth;
44603
44604
44605
44606
44607 protected $io;
44608
44609
44610
44611
44612 protected $url;
44613
44614
44615
44616
44617 protected $cacheCredentials = true;
44618
44619
44620
44621
44622 protected $process;
44623
44624
44625
44626
44627 protected $qtyAuthTries = 0;
44628
44629
44630
44631
44632 protected $config;
44633
44634
44635
44636
44637 private static $version;
44638
44639
44640
44641
44642
44643
44644
44645 public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null)
44646 {
44647 $this->url = $url;
44648 $this->io = $io;
44649 $this->config = $config;
44650 $this->process = $process ?: new ProcessExecutor;
44651 }
44652
44653 public static function cleanEnv()
44654 {
44655
44656  putenv("DYLD_LIBRARY_PATH");
44657 unset($_SERVER['DYLD_LIBRARY_PATH']);
44658 }
44659
44660
44661
44662
44663
44664
44665
44666
44667
44668
44669
44670
44671
44672
44673 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
44674 {
44675
44676  $this->config->prohibitUrlByConfig($url, $this->io);
44677
44678 return $this->executeWithAuthRetry($command, $cwd, $url, $path, $verbose);
44679 }
44680
44681
44682
44683
44684
44685
44686
44687
44688
44689
44690
44691
44692
44693 public function executeLocal($command, $path, $cwd = null, $verbose = false)
44694 {
44695
44696  return $this->executeWithAuthRetry($command, $cwd, '', $path, $verbose);
44697 }
44698
44699 private function executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose)
44700 {
44701
44702  $command = $this->getCommand($svnCommand, $url, $path);
44703
44704 $output = null;
44705 $io = $this->io;
44706 $handler = function ($type, $buffer) use (&$output, $io, $verbose) {
44707 if ($type !== 'out') {
44708 return;
44709 }
44710 if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
44711 return;
44712 }
44713 $output .= $buffer;
44714 if ($verbose) {
44715 $io->writeError($buffer, false);
44716 }
44717 };
44718 $status = $this->process->execute($command, $handler, $cwd);
44719 if (0 === $status) {
44720 return $output;
44721 }
44722
44723 $errorOutput = $this->process->getErrorOutput();
44724 $fullOutput = implode("\n", array($output, $errorOutput));
44725
44726
44727  if (false === stripos($fullOutput, 'Could not authenticate to server:')
44728 && false === stripos($fullOutput, 'authorization failed')
44729 && false === stripos($fullOutput, 'svn: E170001:')
44730 && false === stripos($fullOutput, 'svn: E215004:')) {
44731 throw new \RuntimeException($fullOutput);
44732 }
44733
44734 if (!$this->hasAuth()) {
44735 $this->doAuthDance();
44736 }
44737
44738
44739  if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
44740
44741  return $this->executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose);
44742 }
44743
44744 throw new \RuntimeException(
44745 'wrong credentials provided ('.$fullOutput.')'
44746 );
44747 }
44748
44749
44750
44751
44752 public function setCacheCredentials($cacheCredentials)
44753 {
44754 $this->cacheCredentials = $cacheCredentials;
44755 }
44756
44757
44758
44759
44760
44761
44762
44763 protected function doAuthDance()
44764 {
44765
44766  if (!$this->io->isInteractive()) {
44767 throw new \RuntimeException(
44768 'can not ask for authentication in non interactive mode'
44769 );
44770 }
44771
44772 $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
44773
44774 $this->hasAuth = true;
44775 $this->credentials['username'] = $this->io->ask("Username: ");
44776 $this->credentials['password'] = $this->io->askAndHideAnswer("Password: ");
44777
44778 $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ", true);
44779
44780 return $this;
44781 }
44782
44783
44784
44785
44786
44787
44788
44789
44790
44791
44792 protected function getCommand($cmd, $url, $path = null)
44793 {
44794 $cmd = sprintf(
44795 '%s %s%s %s',
44796 $cmd,
44797 '--non-interactive ',
44798 $this->getCredentialString(),
44799 ProcessExecutor::escape($url)
44800 );
44801
44802 if ($path) {
44803 $cmd .= ' ' . ProcessExecutor::escape($path);
44804 }
44805
44806 return $cmd;
44807 }
44808
44809
44810
44811
44812
44813
44814
44815
44816 protected function getCredentialString()
44817 {
44818 if (!$this->hasAuth()) {
44819 return '';
44820 }
44821
44822 return sprintf(
44823 ' %s--username %s --password %s ',
44824 $this->getAuthCache(),
44825 ProcessExecutor::escape($this->getUsername()),
44826 ProcessExecutor::escape($this->getPassword())
44827 );
44828 }
44829
44830
44831
44832
44833
44834
44835
44836 protected function getPassword()
44837 {
44838 if ($this->credentials === null) {
44839 throw new \LogicException("No svn auth detected.");
44840 }
44841
44842 return isset($this->credentials['password']) ? $this->credentials['password'] : '';
44843 }
44844
44845
44846
44847
44848
44849
44850
44851 protected function getUsername()
44852 {
44853 if ($this->credentials === null) {
44854 throw new \LogicException("No svn auth detected.");
44855 }
44856
44857 return $this->credentials['username'];
44858 }
44859
44860
44861
44862
44863
44864
44865 protected function hasAuth()
44866 {
44867 if (null !== $this->hasAuth) {
44868 return $this->hasAuth;
44869 }
44870
44871 if (false === $this->createAuthFromConfig()) {
44872 $this->createAuthFromUrl();
44873 }
44874
44875 return $this->hasAuth;
44876 }
44877
44878
44879
44880
44881
44882
44883 protected function getAuthCache()
44884 {
44885 return $this->cacheCredentials ? '' : '--no-auth-cache ';
44886 }
44887
44888
44889
44890
44891
44892
44893 private function createAuthFromConfig()
44894 {
44895 if (!$this->config->has('http-basic')) {
44896 return $this->hasAuth = false;
44897 }
44898
44899 $authConfig = $this->config->get('http-basic');
44900
44901 $host = parse_url($this->url, PHP_URL_HOST);
44902 if (isset($authConfig[$host])) {
44903 $this->credentials['username'] = $authConfig[$host]['username'];
44904 $this->credentials['password'] = $authConfig[$host]['password'];
44905
44906 return $this->hasAuth = true;
44907 }
44908
44909 return $this->hasAuth = false;
44910 }
44911
44912
44913
44914
44915
44916
44917 private function createAuthFromUrl()
44918 {
44919 $uri = parse_url($this->url);
44920 if (empty($uri['user'])) {
44921 return $this->hasAuth = false;
44922 }
44923
44924 $this->credentials['username'] = $uri['user'];
44925 if (!empty($uri['pass'])) {
44926 $this->credentials['password'] = $uri['pass'];
44927 }
44928
44929 return $this->hasAuth = true;
44930 }
44931
44932
44933
44934
44935
44936
44937 public function binaryVersion()
44938 {
44939 if (!self::$version) {
44940 if (0 === $this->process->execute('svn --version', $output)) {
44941 if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match)) {
44942 self::$version = $match[1];
44943 }
44944 }
44945 }
44946
44947 return self::$version;
44948 }
44949 }
44950 <?php
44951
44952
44953
44954
44955
44956
44957
44958
44959
44960
44961
44962 namespace Composer\Util;
44963
44964 use Composer\CaBundle\CaBundle;
44965
44966
44967
44968
44969 final class TlsHelper
44970 {
44971 private static $useOpensslParse;
44972
44973
44974
44975
44976
44977
44978
44979
44980
44981
44982 public static function checkCertificateHost($certificate, $hostname, &$cn = null)
44983 {
44984 $names = self::getCertificateNames($certificate);
44985
44986 if (empty($names)) {
44987 return false;
44988 }
44989
44990 $combinedNames = array_merge($names['san'], array($names['cn']));
44991 $hostname = strtolower($hostname);
44992
44993 foreach ($combinedNames as $certName) {
44994 $matcher = self::certNameMatcher($certName);
44995
44996 if ($matcher && $matcher($hostname)) {
44997 $cn = $names['cn'];
44998
44999 return true;
45000 }
45001 }
45002
45003 return false;
45004 }
45005
45006
45007
45008
45009
45010
45011
45012
45013 public static function getCertificateNames($certificate)
45014 {
45015 if (is_array($certificate)) {
45016 $info = $certificate;
45017 } elseif (CaBundle::isOpensslParseSafe()) {
45018 $info = openssl_x509_parse($certificate, false);
45019 }
45020
45021 if (!isset($info['subject']['commonName'])) {
45022 return null;
45023 }
45024
45025 $commonName = strtolower($info['subject']['commonName']);
45026 $subjectAltNames = array();
45027
45028 if (isset($info['extensions']['subjectAltName'])) {
45029 $subjectAltNames = preg_split('{\s*,\s*}', $info['extensions']['subjectAltName']);
45030 $subjectAltNames = array_filter(array_map(function ($name) {
45031 if (0 === strpos($name, 'DNS:')) {
45032 return strtolower(ltrim(substr($name, 4)));
45033 }
45034
45035 return null;
45036 }, $subjectAltNames));
45037 $subjectAltNames = array_values($subjectAltNames);
45038 }
45039
45040 return array(
45041 'cn' => $commonName,
45042 'san' => $subjectAltNames,
45043 );
45044 }
45045
45046
45047
45048
45049
45050
45051
45052
45053
45054
45055
45056
45057
45058
45059
45060
45061
45062
45063
45064
45065
45066
45067
45068
45069
45070
45071
45072
45073
45074
45075
45076
45077
45078
45079
45080
45081
45082
45083
45084
45085 public static function getCertificateFingerprint($certificate)
45086 {
45087 $pubkeydetails = openssl_pkey_get_details(openssl_get_publickey($certificate));
45088 $pubkeypem = $pubkeydetails['key'];
45089
45090  $start = '-----BEGIN PUBLIC KEY-----';
45091 $end = '-----END PUBLIC KEY-----';
45092 $pemtrim = substr($pubkeypem, strpos($pubkeypem, $start) + strlen($start), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
45093 $der = base64_decode($pemtrim);
45094
45095 return sha1($der);
45096 }
45097
45098
45099
45100
45101
45102
45103
45104
45105
45106 public static function isOpensslParseSafe()
45107 {
45108 return CaBundle::isOpensslParseSafe();
45109 }
45110
45111
45112
45113
45114
45115
45116
45117
45118 private static function certNameMatcher($certName)
45119 {
45120 $wildcards = substr_count($certName, '*');
45121
45122 if (0 === $wildcards) {
45123
45124  return function ($hostname) use ($certName) {
45125 return $hostname === $certName;
45126 };
45127 }
45128
45129 if (1 === $wildcards) {
45130 $components = explode('.', $certName);
45131
45132 if (3 > count($components)) {
45133
45134  return;
45135 }
45136
45137 $firstComponent = $components[0];
45138
45139
45140  if ('*' !== $firstComponent[strlen($firstComponent) - 1]) {
45141 return;
45142 }
45143
45144 $wildcardRegex = preg_quote($certName);
45145 $wildcardRegex = str_replace('\\*', '[a-z0-9-]+', $wildcardRegex);
45146 $wildcardRegex = "{^{$wildcardRegex}$}";
45147
45148 return function ($hostname) use ($wildcardRegex) {
45149 return 1 === preg_match($wildcardRegex, $hostname);
45150 };
45151 }
45152 }
45153 }
45154 <?php
45155
45156
45157
45158
45159
45160
45161
45162
45163
45164
45165
45166 namespace Composer\Util;
45167
45168 use Composer\Config;
45169
45170
45171
45172
45173 class Url
45174 {
45175 public static function updateDistReference(Config $config, $url, $ref)
45176 {
45177 $host = parse_url($url, PHP_URL_HOST);
45178
45179 if ($host === 'api.github.com' || $host === 'github.com' || $host === 'www.github.com') {
45180 if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
45181
45182  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
45183 } elseif (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
45184
45185  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
45186 } elseif (preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
45187
45188  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
45189 }
45190 } elseif ($host === 'bitbucket.org' || $host === 'www.bitbucket.org') {
45191 if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
45192
45193  $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $ref . '.' . $match[4];
45194 }
45195 } elseif ($host === 'gitlab.com' || $host === 'www.gitlab.com') {
45196 if (preg_match('{^https?://(?:www\.)?gitlab\.com/api/v[34]/projects/([^/]+)/repository/archive\.(zip|tar\.gz|tar\.bz2|tar)\?sha=.+$}i', $url, $match)) {
45197
45198  $url = 'https://gitlab.com/api/v4/projects/' . $match[1] . '/repository/archive.' . $match[2] . '?sha=' . $ref;
45199 }
45200 } elseif (in_array($host, $config->get('github-domains'), true)) {
45201 $url = preg_replace('{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i', '$1/'.$ref, $url);
45202 } elseif (in_array($host, $config->get('gitlab-domains'), true)) {
45203 $url = preg_replace('{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i', '${1}'.$ref, $url);
45204 }
45205
45206 return $url;
45207 }
45208 }
45209 <?php
45210
45211
45212
45213
45214
45215
45216
45217
45218
45219
45220
45221 namespace Composer;
45222
45223 use Symfony\Component\Console\Output\OutputInterface;
45224
45225 trigger_error('The ' . __NAMESPACE__ . '\XdebugHandler class is deprecated, use Composer\XdebugHandler\XdebugHandler instead,', E_USER_DEPRECATED);
45226
45227
45228
45229
45230 class XdebugHandler extends XdebugHandler\XdebugHandler
45231 {
45232 const ENV_ALLOW = 'COMPOSER_ALLOW_XDEBUG';
45233 const ENV_VERSION = 'COMPOSER_XDEBUG_VERSION';
45234
45235 public function __construct(OutputInterface $output)
45236 {
45237 parent::__construct('composer', '--ansi');
45238 }
45239 }
45240 <?php
45241
45242
45243
45244
45245
45246
45247
45248
45249
45250
45251
45252 function includeIfExists($file)
45253 {
45254 return file_exists($file) ? include $file : false;
45255 }
45256
45257 if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
45258 echo 'You must set up the project dependencies using `composer install`'.PHP_EOL.
45259 'See https://getcomposer.org/download/ for instructions on installing Composer'.PHP_EOL;
45260 exit(1);
45261 }
45262
45263 return $loader;
45264 <?php
45265
45266 /*
45267  * This file is part of Composer.
45268  *
45269  * (c) Nils Adermann <naderman@naderman.de>
45270  *     Jordi Boggiano <j.boggiano@seld.be>
45271  *
45272  * For the full copyright and license information, please view the LICENSE
45273  * file that was distributed with this source code.
45274  */
45275
45276 namespace Composer\Autoload;
45277
45278 /**
45279  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
45280  *
45281  *     $loader = new \Composer\Autoload\ClassLoader();
45282  *
45283  *     // register classes with namespaces
45284  *     $loader->add('Symfony\Component', __DIR__.'/component');
45285  *     $loader->add('Symfony',           __DIR__.'/framework');
45286  *
45287  *     // activate the autoloader
45288  *     $loader->register();
45289  *
45290  *     // to enable searching the include path (eg. for PEAR packages)
45291  *     $loader->setUseIncludePath(true);
45292  *
45293  * In this example, if you try to use a class in the Symfony\Component
45294  * namespace or one of its children (Symfony\Component\Console for instance),
45295  * the autoloader will first look for the class under the component/
45296  * directory, and it will then fallback to the framework/ directory if not
45297  * found before giving up.
45298  *
45299  * This class is loosely based on the Symfony UniversalClassLoader.
45300  *
45301  * @author Fabien Potencier <fabien@symfony.com>
45302  * @author Jordi Boggiano <j.boggiano@seld.be>
45303  * @see    http://www.php-fig.org/psr/psr-0/
45304  * @see    http://www.php-fig.org/psr/psr-4/
45305  */
45306 class ClassLoader
45307 {
45308     // PSR-4
45309     private $prefixLengthsPsr4 = array();
45310     private $prefixDirsPsr4 = array();
45311     private $fallbackDirsPsr4 = array();
45312
45313     // PSR-0
45314     private $prefixesPsr0 = array();
45315     private $fallbackDirsPsr0 = array();
45316
45317     private $useIncludePath = false;
45318     private $classMap = array();
45319     private $classMapAuthoritative = false;
45320     private $missingClasses = array();
45321     private $apcuPrefix;
45322
45323     public function getPrefixes()
45324     {
45325         if (!empty($this->prefixesPsr0)) {
45326             return call_user_func_array('array_merge', $this->prefixesPsr0);
45327         }
45328
45329         return array();
45330     }
45331
45332     public function getPrefixesPsr4()
45333     {
45334         return $this->prefixDirsPsr4;
45335     }
45336
45337     public function getFallbackDirs()
45338     {
45339         return $this->fallbackDirsPsr0;
45340     }
45341
45342     public function getFallbackDirsPsr4()
45343     {
45344         return $this->fallbackDirsPsr4;
45345     }
45346
45347     public function getClassMap()
45348     {
45349         return $this->classMap;
45350     }
45351
45352     /**
45353      * @param array $classMap Class to filename map
45354      */
45355     public function addClassMap(array $classMap)
45356     {
45357         if ($this->classMap) {
45358             $this->classMap = array_merge($this->classMap, $classMap);
45359         } else {
45360             $this->classMap = $classMap;
45361         }
45362     }
45363
45364     /**
45365      * Registers a set of PSR-0 directories for a given prefix, either
45366      * appending or prepending to the ones previously set for this prefix.
45367      *
45368      * @param string       $prefix  The prefix
45369      * @param array|string $paths   The PSR-0 root directories
45370      * @param bool         $prepend Whether to prepend the directories
45371      */
45372     public function add($prefix, $paths, $prepend = false)
45373     {
45374         if (!$prefix) {
45375             if ($prepend) {
45376                 $this->fallbackDirsPsr0 = array_merge(
45377                     (array) $paths,
45378                     $this->fallbackDirsPsr0
45379                 );
45380             } else {
45381                 $this->fallbackDirsPsr0 = array_merge(
45382                     $this->fallbackDirsPsr0,
45383                     (array) $paths
45384                 );
45385             }
45386
45387             return;
45388         }
45389
45390         $first = $prefix[0];
45391         if (!isset($this->prefixesPsr0[$first][$prefix])) {
45392             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
45393
45394             return;
45395         }
45396         if ($prepend) {
45397             $this->prefixesPsr0[$first][$prefix] = array_merge(
45398                 (array) $paths,
45399                 $this->prefixesPsr0[$first][$prefix]
45400             );
45401         } else {
45402             $this->prefixesPsr0[$first][$prefix] = array_merge(
45403                 $this->prefixesPsr0[$first][$prefix],
45404                 (array) $paths
45405             );
45406         }
45407     }
45408
45409     /**
45410      * Registers a set of PSR-4 directories for a given namespace, either
45411      * appending or prepending to the ones previously set for this namespace.
45412      *
45413      * @param string       $prefix  The prefix/namespace, with trailing '\\'
45414      * @param array|string $paths   The PSR-4 base directories
45415      * @param bool         $prepend Whether to prepend the directories
45416      *
45417      * @throws \InvalidArgumentException
45418      */
45419     public function addPsr4($prefix, $paths, $prepend = false)
45420     {
45421         if (!$prefix) {
45422             // Register directories for the root namespace.
45423             if ($prepend) {
45424                 $this->fallbackDirsPsr4 = array_merge(
45425                     (array) $paths,
45426                     $this->fallbackDirsPsr4
45427                 );
45428             } else {
45429                 $this->fallbackDirsPsr4 = array_merge(
45430                     $this->fallbackDirsPsr4,
45431                     (array) $paths
45432                 );
45433             }
45434         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
45435             // Register directories for a new namespace.
45436             $length = strlen($prefix);
45437             if ('\\' !== $prefix[$length - 1]) {
45438                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
45439             }
45440             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
45441             $this->prefixDirsPsr4[$prefix] = (array) $paths;
45442         } elseif ($prepend) {
45443             // Prepend directories for an already registered namespace.
45444             $this->prefixDirsPsr4[$prefix] = array_merge(
45445                 (array) $paths,
45446                 $this->prefixDirsPsr4[$prefix]
45447             );
45448         } else {
45449             // Append directories for an already registered namespace.
45450             $this->prefixDirsPsr4[$prefix] = array_merge(
45451                 $this->prefixDirsPsr4[$prefix],
45452                 (array) $paths
45453             );
45454         }
45455     }
45456
45457     /**
45458      * Registers a set of PSR-0 directories for a given prefix,
45459      * replacing any others previously set for this prefix.
45460      *
45461      * @param string       $prefix The prefix
45462      * @param array|string $paths  The PSR-0 base directories
45463      */
45464     public function set($prefix, $paths)
45465     {
45466         if (!$prefix) {
45467             $this->fallbackDirsPsr0 = (array) $paths;
45468         } else {
45469             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
45470         }
45471     }
45472
45473     /**
45474      * Registers a set of PSR-4 directories for a given namespace,
45475      * replacing any others previously set for this namespace.
45476      *
45477      * @param string       $prefix The prefix/namespace, with trailing '\\'
45478      * @param array|string $paths  The PSR-4 base directories
45479      *
45480      * @throws \InvalidArgumentException
45481      */
45482     public function setPsr4($prefix, $paths)
45483     {
45484         if (!$prefix) {
45485             $this->fallbackDirsPsr4 = (array) $paths;
45486         } else {
45487             $length = strlen($prefix);
45488             if ('\\' !== $prefix[$length - 1]) {
45489                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
45490             }
45491             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
45492             $this->prefixDirsPsr4[$prefix] = (array) $paths;
45493         }
45494     }
45495
45496     /**
45497      * Turns on searching the include path for class files.
45498      *
45499      * @param bool $useIncludePath
45500      */
45501     public function setUseIncludePath($useIncludePath)
45502     {
45503         $this->useIncludePath = $useIncludePath;
45504     }
45505
45506     /**
45507      * Can be used to check if the autoloader uses the include path to check
45508      * for classes.
45509      *
45510      * @return bool
45511      */
45512     public function getUseIncludePath()
45513     {
45514         return $this->useIncludePath;
45515     }
45516
45517     /**
45518      * Turns off searching the prefix and fallback directories for classes
45519      * that have not been registered with the class map.
45520      *
45521      * @param bool $classMapAuthoritative
45522      */
45523     public function setClassMapAuthoritative($classMapAuthoritative)
45524     {
45525         $this->classMapAuthoritative = $classMapAuthoritative;
45526     }
45527
45528     /**
45529      * Should class lookup fail if not found in the current class map?
45530      *
45531      * @return bool
45532      */
45533     public function isClassMapAuthoritative()
45534     {
45535         return $this->classMapAuthoritative;
45536     }
45537
45538     /**
45539      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
45540      *
45541      * @param string|null $apcuPrefix
45542      */
45543     public function setApcuPrefix($apcuPrefix)
45544     {
45545         $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
45546     }
45547
45548     /**
45549      * The APCu prefix in use, or null if APCu caching is not enabled.
45550      *
45551      * @return string|null
45552      */
45553     public function getApcuPrefix()
45554     {
45555         return $this->apcuPrefix;
45556     }
45557
45558     /**
45559      * Registers this instance as an autoloader.
45560      *
45561      * @param bool $prepend Whether to prepend the autoloader or not
45562      */
45563     public function register($prepend = false)
45564     {
45565         spl_autoload_register(array($this, 'loadClass'), true, $prepend);
45566     }
45567
45568     /**
45569      * Unregisters this instance as an autoloader.
45570      */
45571     public function unregister()
45572     {
45573         spl_autoload_unregister(array($this, 'loadClass'));
45574     }
45575
45576     /**
45577      * Loads the given class or interface.
45578      *
45579      * @param  string    $class The name of the class
45580      * @return bool|null True if loaded, null otherwise
45581      */
45582     public function loadClass($class)
45583     {
45584         if ($file = $this->findFile($class)) {
45585             includeFile($file);
45586
45587             return true;
45588         }
45589     }
45590
45591     /**
45592      * Finds the path to the file where the class is defined.
45593      *
45594      * @param string $class The name of the class
45595      *
45596      * @return string|false The path if found, false otherwise
45597      */
45598     public function findFile($class)
45599     {
45600         // class map lookup
45601         if (isset($this->classMap[$class])) {
45602             return $this->classMap[$class];
45603         }
45604         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
45605             return false;
45606         }
45607         if (null !== $this->apcuPrefix) {
45608             $file = apcu_fetch($this->apcuPrefix.$class, $hit);
45609             if ($hit) {
45610                 return $file;
45611             }
45612         }
45613
45614         $file = $this->findFileWithExtension($class, '.php');
45615
45616         // Search for Hack files if we are running on HHVM
45617         if (false === $file && defined('HHVM_VERSION')) {
45618             $file = $this->findFileWithExtension($class, '.hh');
45619         }
45620
45621         if (null !== $this->apcuPrefix) {
45622             apcu_add($this->apcuPrefix.$class, $file);
45623         }
45624
45625         if (false === $file) {
45626             // Remember that this class does not exist.
45627             $this->missingClasses[$class] = true;
45628         }
45629
45630         return $file;
45631     }
45632
45633     private function findFileWithExtension($class, $ext)
45634     {
45635         // PSR-4 lookup
45636         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
45637
45638         $first = $class[0];
45639         if (isset($this->prefixLengthsPsr4[$first])) {
45640             $subPath = $class;
45641             while (false !== $lastPos = strrpos($subPath, '\\')) {
45642                 $subPath = substr($subPath, 0, $lastPos);
45643                 $search = $subPath . '\\';
45644                 if (isset($this->prefixDirsPsr4[$search])) {
45645                     $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
45646                     foreach ($this->prefixDirsPsr4[$search] as $dir) {
45647                         if (file_exists($file = $dir . $pathEnd)) {
45648                             return $file;
45649                         }
45650                     }
45651                 }
45652             }
45653         }
45654
45655         // PSR-4 fallback dirs
45656         foreach ($this->fallbackDirsPsr4 as $dir) {
45657             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
45658                 return $file;
45659             }
45660         }
45661
45662         // PSR-0 lookup
45663         if (false !== $pos = strrpos($class, '\\')) {
45664             // namespaced class name
45665             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
45666                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
45667         } else {
45668             // PEAR-like class name
45669             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
45670         }
45671
45672         if (isset($this->prefixesPsr0[$first])) {
45673             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
45674                 if (0 === strpos($class, $prefix)) {
45675                     foreach ($dirs as $dir) {
45676                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
45677                             return $file;
45678                         }
45679                     }
45680                 }
45681             }
45682         }
45683
45684         // PSR-0 fallback dirs
45685         foreach ($this->fallbackDirsPsr0 as $dir) {
45686             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
45687                 return $file;
45688             }
45689         }
45690
45691         // PSR-0 include paths.
45692         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
45693             return $file;
45694         }
45695
45696         return false;
45697     }
45698 }
45699
45700 /**
45701  * Scope isolated include.
45702  *
45703  * Prevents access to $this/self from included files.
45704  */
45705 function includeFile($file)
45706 {
45707     include $file;
45708 }
45709 {
45710     "$schema": "http://json-schema.org/draft-04/schema#",
45711     "description": "A representation of packages metadata.",
45712     "type": "object",
45713     "oneOf": [
45714         { "required": [ "packages" ] },
45715         { "required": [ "providers" ] },
45716         { "required": [ "provider-includes", "providers-url" ] }
45717     ],
45718     "properties": {
45719         "packages": {
45720             "type": ["object", "array"],
45721             "description": "A hashmap of package names in the form of <vendor>/<name>.",
45722             "additionalProperties": { "$ref": "#/definitions/versions" }
45723         },
45724         "providers-url": {
45725             "type": "string",
45726             "description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
45727         },
45728         "provider-includes": {
45729             "type": "object",
45730             "description": "A hashmap of provider listings.",
45731             "additionalProperties": { "$ref": "#/definitions/provider" }
45732         },
45733         "providers": {
45734             "type": "object",
45735             "description": "A hashmap of package names in the form of <vendor>/<name>.",
45736             "additionalProperties": { "$ref": "#/definitions/provider" }
45737         },
45738         "notify-batch": {
45739             "type": "string",
45740             "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
45741         },
45742         "search": {
45743             "type": "string",
45744             "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
45745         },
45746         "warning": {
45747             "type": "string",
45748             "description": "A message that will be output by Composer as a warning when this source is consulted."
45749         }
45750     },
45751     "definitions": {
45752         "versions": {
45753             "type": "object",
45754             "description": "A hashmap of versions and their metadata.",
45755             "additionalProperties": { "$ref": "#/definitions/version" }
45756         },
45757         "version": {
45758             "type": "object",
45759             "oneOf": [
45760                 { "$ref": "#/definitions/package" },
45761                 { "$ref": "#/definitions/metapackage" }
45762             ]
45763         },
45764         "package-base": {
45765             "properties": {
45766                 "name": { "type": "string" },
45767                 "type": { "type": "string" },
45768                 "version": { "type": "string" },
45769                 "version_normalized": {
45770                     "type": "string",
45771                     "description": "Normalized version, optional but can save computational time on client side."
45772                 },
45773                 "autoload": { "type": "object" },
45774                 "require": { "type": "object" },
45775                 "replace": { "type": "object" },
45776                 "conflict": { "type": "object" },
45777                 "provide": { "type": "object" },
45778                 "time": { "type": "string" }
45779             },
45780             "additionalProperties": true
45781         },
45782         "package": {
45783             "allOf": [
45784                 { "$ref": "#/definitions/package-base" },
45785                 {
45786                     "properties": {
45787                         "dist": { "type": "object" },
45788                         "source": { "type": "object" }
45789                     }
45790                 },
45791                 { "oneOf": [
45792                     { "required": [ "name", "version", "source" ] },
45793                     { "required": [ "name", "version", "dist" ] }
45794                 ] }
45795             ]
45796         },
45797         "metapackage": {
45798             "allOf": [
45799                 { "$ref": "#/definitions/package-base" },
45800                 {
45801                     "properties": {
45802                         "type": { "type": "string", "enum": [ "metapackage" ] }
45803                     },
45804                     "required": [ "name", "version", "type" ]
45805                 }
45806             ]
45807         },
45808         "provider": {
45809             "type": "object",
45810             "properties": {
45811                 "sha256": {
45812                     "type": "string",
45813                     "description": "Hash value that can be used to validate the resource."
45814                 }
45815             }
45816         }
45817     }
45818 }
45819 {
45820     "$schema": "http://json-schema.org/draft-04/schema#",
45821     "name": "Package",
45822     "type": "object",
45823     "additionalProperties": false,
45824     "required": [ "name", "description" ],
45825     "properties": {
45826         "name": {
45827             "type": "string",
45828             "description": "Package name, including 'vendor-name/' prefix."
45829         },
45830         "type": {
45831             "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.",
45832             "type": "string"
45833         },
45834         "target-dir": {
45835             "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.",
45836             "type": "string"
45837         },
45838         "description": {
45839             "type": "string",
45840             "description": "Short package description."
45841         },
45842         "keywords": {
45843             "type": "array",
45844             "items": {
45845                 "type": "string",
45846                 "description": "A tag/keyword that this package relates to."
45847             }
45848         },
45849         "homepage": {
45850             "type": "string",
45851             "description": "Homepage URL for the project.",
45852             "format": "uri"
45853         },
45854         "readme": {
45855             "type": "string",
45856             "description": "Relative path to the readme document."
45857         },
45858         "version": {
45859             "type": "string",
45860             "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes."
45861         },
45862         "time": {
45863             "type": "string",
45864             "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
45865         },
45866         "license": {
45867             "type": ["string", "array"],
45868             "description": "License name. Or an array of license names."
45869         },
45870         "authors": {
45871             "$ref": "#/definitions/authors"
45872         },
45873         "require": {
45874             "type": "object",
45875             "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
45876             "additionalProperties": {
45877                 "type": "string"
45878             }
45879         },
45880         "replace": {
45881             "type": "object",
45882             "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
45883             "additionalProperties": {
45884                 "type": "string"
45885             }
45886         },
45887         "conflict": {
45888             "type": "object",
45889             "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
45890             "additionalProperties": {
45891                 "type": "string"
45892             }
45893         },
45894         "provide": {
45895             "type": "object",
45896             "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
45897             "additionalProperties": {
45898                 "type": "string"
45899             }
45900         },
45901         "require-dev": {
45902             "type": "object",
45903             "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
45904             "additionalProperties": {
45905                 "type": "string"
45906             }
45907         },
45908         "suggest": {
45909             "type": "object",
45910             "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).",
45911             "additionalProperties": {
45912                 "type": "string"
45913             }
45914         },
45915         "config": {
45916             "type": "object",
45917             "description": "Composer options.",
45918             "properties": {
45919                 "process-timeout": {
45920                     "type": "integer",
45921                     "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
45922                 },
45923                 "use-include-path": {
45924                     "type": "boolean",
45925                     "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
45926                 },
45927                 "preferred-install": {
45928                     "type": ["string", "object"],
45929                     "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\"}."
45930                 },
45931                 "notify-on-install": {
45932                     "type": "boolean",
45933                     "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."
45934                 },
45935                 "github-protocols": {
45936                     "type": "array",
45937                     "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].",
45938                     "items": {
45939                         "type": "string"
45940                     }
45941                 },
45942                 "github-oauth": {
45943                     "type": "object",
45944                     "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
45945                     "additionalProperties": {
45946                         "type": "string"
45947                     }
45948                 },
45949                 "gitlab-oauth": {
45950                     "type": "object",
45951                     "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"<token>\"}.",
45952                     "additionalProperties": {
45953                         "type": "string"
45954                     }
45955                 },
45956                 "gitlab-token": {
45957                     "type": "object",
45958                     "description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}.",
45959                     "additionalProperties": true
45960                 },
45961                 "disable-tls": {
45962                     "type": "boolean",
45963                     "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."
45964                 },
45965                 "secure-http": {
45966                     "type": "boolean",
45967                     "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."
45968                 },
45969                 "cafile": {
45970                     "type": "string",
45971                     "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."
45972                 },
45973                 "capath": {
45974                     "type": "string",
45975                     "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."
45976                 },
45977                 "http-basic": {
45978                     "type": "object",
45979                     "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
45980                     "additionalProperties": {
45981                         "type": "object",
45982                         "required": ["username", "password"],
45983                         "properties": {
45984                             "username": {
45985                                 "type": "string",
45986                                 "description": "The username used for HTTP Basic authentication"
45987                             },
45988                             "password": {
45989                                 "type": "string",
45990                                 "description": "The password used for HTTP Basic authentication"
45991                             }
45992                         }
45993                     }
45994                 },
45995                 "store-auths": {
45996                     "type": ["string", "boolean"],
45997                     "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
45998                 },
45999                 "platform": {
46000                     "type": "object",
46001                     "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
46002                     "additionalProperties": {
46003                         "type": "string"
46004                     }
46005                 },
46006                 "vendor-dir": {
46007                     "type": "string",
46008                     "description": "The location where all packages are installed, defaults to \"vendor\"."
46009                 },
46010                 "bin-dir": {
46011                     "type": "string",
46012                     "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
46013                 },
46014                 "data-dir": {
46015                     "type": "string",
46016                     "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes."
46017                 },
46018                 "cache-dir": {
46019                     "type": "string",
46020                     "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
46021                 },
46022                 "cache-files-dir": {
46023                     "type": "string",
46024                     "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
46025                 },
46026                 "cache-repo-dir": {
46027                     "type": "string",
46028                     "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
46029                 },
46030                 "cache-vcs-dir": {
46031                     "type": "string",
46032                     "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
46033                 },
46034                 "cache-ttl": {
46035                     "type": "integer",
46036                     "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
46037                 },
46038                 "cache-files-ttl": {
46039                     "type": "integer",
46040                     "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
46041                 },
46042                 "cache-files-maxsize": {
46043                     "type": ["string", "integer"],
46044                     "description": "The cache max size for the files cache, defaults to \"300MiB\"."
46045                 },
46046                 "bin-compat": {
46047                     "enum": ["auto", "full"],
46048                     "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)."
46049                 },
46050                 "discard-changes": {
46051                     "type": ["string", "boolean"],
46052                     "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
46053                 },
46054                 "autoloader-suffix": {
46055                     "type": "string",
46056                     "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
46057                 },
46058                 "optimize-autoloader": {
46059                     "type": "boolean",
46060                     "description": "Always optimize when dumping the autoloader."
46061                 },
46062                 "prepend-autoloader": {
46063                     "type": "boolean",
46064                     "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
46065                 },
46066                 "classmap-authoritative": {
46067                     "type": "boolean",
46068                     "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
46069                 },
46070                 "apcu-autoloader": {
46071                     "type": "boolean",
46072                     "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."
46073                 },
46074                 "github-domains": {
46075                     "type": "array",
46076                     "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
46077                     "items": {
46078                         "type": "string"
46079                     }
46080                 },
46081                 "github-expose-hostname": {
46082                     "type": "boolean",
46083                     "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."
46084                 },
46085                 "gitlab-domains": {
46086                     "type": "array",
46087                     "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].",
46088                     "items": {
46089                         "type": "string"
46090                     }
46091                 },
46092                 "archive-format": {
46093                     "type": "string",
46094                     "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
46095                 },
46096                 "archive-dir": {
46097                     "type": "string",
46098                     "description": "The default archive path when not provided on cli, defaults to \".\"."
46099                 },
46100                 "htaccess-protect": {
46101                     "type": "boolean",
46102                     "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
46103                 },
46104                 "sort-packages": {
46105                     "type": "boolean",
46106                     "description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency."
46107                 }
46108             }
46109         },
46110         "extra": {
46111             "type": ["object", "array"],
46112             "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.",
46113             "additionalProperties": true
46114         },
46115         "autoload": {
46116             "$ref": "#/definitions/autoload"
46117         },
46118         "autoload-dev": {
46119             "type": "object",
46120             "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
46121             "properties": {
46122                 "psr-0": {
46123                     "type": "object",
46124                     "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.",
46125                     "additionalProperties": {
46126                         "type": ["string", "array"],
46127                         "items": {
46128                             "type": "string"
46129                         }
46130                     }
46131                 },
46132                 "psr-4": {
46133                     "type": "object",
46134                     "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.",
46135                     "additionalProperties": {
46136                         "type": ["string", "array"],
46137                         "items": {
46138                             "type": "string"
46139                         }
46140                     }
46141                 },
46142                 "classmap": {
46143                     "type": "array",
46144                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
46145                 },
46146                 "files": {
46147                     "type": "array",
46148                     "description": "This is an array of files that are always required on every request."
46149                 }
46150             }
46151         },
46152         "archive": {
46153             "type": ["object"],
46154             "description": "Options for creating package archives for distribution.",
46155             "properties": {
46156                 "exclude": {
46157                     "type": "array",
46158                     "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
46159                 }
46160             }
46161         },
46162         "repositories": {
46163             "type": ["object", "array"],
46164             "description": "A set of additional repositories where packages can be found.",
46165             "additionalProperties": {
46166                 "oneOf": [
46167                     { "$ref": "#/definitions/repository" },
46168                     { "type": "boolean", "enum": [false] }
46169                 ]
46170             },
46171             "items": {
46172                 "oneOf": [
46173                     { "$ref": "#/definitions/repository" },
46174                     {
46175                         "type": "object",
46176                         "additionalProperties": { "type": "boolean", "enum": [false] },
46177                         "minProperties": 1,
46178                         "maxProperties": 1
46179                     }
46180                 ]
46181             }
46182         },
46183         "minimum-stability": {
46184             "type": ["string"],
46185             "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
46186             "pattern": "^dev|alpha|beta|rc|RC|stable$"
46187         },
46188         "prefer-stable": {
46189             "type": ["boolean"],
46190             "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages."
46191         },
46192         "bin": {
46193             "type": ["string", "array"],
46194             "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
46195             "items": {
46196                 "type": "string"
46197             }
46198         },
46199         "include-path": {
46200             "type": ["array"],
46201             "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.",
46202             "items": {
46203                 "type": "string"
46204             }
46205         },
46206         "scripts": {
46207             "type": ["object"],
46208             "description": "Script listeners that will be executed before/after some events.",
46209             "properties": {
46210                 "pre-install-cmd": {
46211                     "type": ["array", "string"],
46212                     "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
46213                 },
46214                 "post-install-cmd": {
46215                     "type": ["array", "string"],
46216                     "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
46217                 },
46218                 "pre-update-cmd": {
46219                     "type": ["array", "string"],
46220                     "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
46221                 },
46222                 "post-update-cmd": {
46223                     "type": ["array", "string"],
46224                     "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
46225                 },
46226                 "pre-status-cmd": {
46227                     "type": ["array", "string"],
46228                     "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
46229                 },
46230                 "post-status-cmd": {
46231                     "type": ["array", "string"],
46232                     "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
46233                 },
46234                 "pre-package-install": {
46235                     "type": ["array", "string"],
46236                     "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
46237                 },
46238                 "post-package-install": {
46239                     "type": ["array", "string"],
46240                     "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
46241                 },
46242                 "pre-package-update": {
46243                     "type": ["array", "string"],
46244                     "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
46245                 },
46246                 "post-package-update": {
46247                     "type": ["array", "string"],
46248                     "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
46249                 },
46250                 "pre-package-uninstall": {
46251                     "type": ["array", "string"],
46252                     "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
46253                 },
46254                 "post-package-uninstall": {
46255                     "type": ["array", "string"],
46256                     "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
46257                 },
46258                 "pre-autoload-dump": {
46259                     "type": ["array", "string"],
46260                     "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
46261                 },
46262                 "post-autoload-dump": {
46263                     "type": ["array", "string"],
46264                     "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
46265                 },
46266                 "post-root-package-install": {
46267                     "type": ["array", "string"],
46268                     "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
46269                 },
46270                 "post-create-project-cmd": {
46271                     "type": ["array", "string"],
46272                     "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
46273                 }
46274             }
46275         },
46276         "scripts-descriptions": {
46277             "type": ["object"],
46278             "description": "Descriptions for custom commands, shown in console help.",
46279             "additionalProperties": {
46280                 "type": "string"
46281             }
46282         },
46283         "support": {
46284             "type": "object",
46285             "properties": {
46286                 "email": {
46287                     "type": "string",
46288                     "description": "Email address for support.",
46289                     "format": "email"
46290                 },
46291                 "issues": {
46292                     "type": "string",
46293                     "description": "URL to the issue tracker.",
46294                     "format": "uri"
46295                 },
46296                 "forum": {
46297                     "type": "string",
46298                     "description": "URL to the forum.",
46299                     "format": "uri"
46300                 },
46301                 "wiki": {
46302                     "type": "string",
46303                     "description": "URL to the wiki.",
46304                     "format": "uri"
46305                 },
46306                 "irc": {
46307                     "type": "string",
46308                     "description": "IRC channel for support, as irc://server/channel.",
46309                     "format": "uri"
46310                 },
46311                 "source": {
46312                     "type": "string",
46313                     "description": "URL to browse or download the sources.",
46314                     "format": "uri"
46315                 },
46316                 "docs": {
46317                     "type": "string",
46318                     "description": "URL to the documentation.",
46319                     "format": "uri"
46320                 },
46321                 "rss": {
46322                     "type": "string",
46323                     "description": "URL to the RSS feed.",
46324                     "format": "uri"
46325                 }
46326             }
46327         },
46328         "non-feature-branches": {
46329             "type": ["array"],
46330             "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
46331             "items": {
46332                 "type": "string"
46333             }
46334         },
46335         "abandoned": {
46336             "type": ["boolean", "string"],
46337             "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."
46338         },
46339         "_comment": {
46340             "type": ["array", "string"],
46341             "description": "A key to store comments in"
46342         }
46343     },
46344     "definitions": {
46345         "authors": {
46346             "type": "array",
46347             "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
46348             "items": {
46349                 "type": "object",
46350                 "additionalProperties": false,
46351                 "required": [ "name"],
46352                 "properties": {
46353                     "name": {
46354                         "type": "string",
46355                         "description": "Full name of the author."
46356                     },
46357                     "email": {
46358                         "type": "string",
46359                         "description": "Email address of the author.",
46360                         "format": "email"
46361                     },
46362                     "homepage": {
46363                         "type": "string",
46364                         "description": "Homepage URL for the author.",
46365                         "format": "uri"
46366                     },
46367                     "role": {
46368                         "type": "string",
46369                         "description": "Author's role in the project."
46370                     }
46371                 }
46372             }
46373         },
46374         "autoload": {
46375             "type": "object",
46376             "description": "Description of how the package can be autoloaded.",
46377             "properties": {
46378                 "psr-0": {
46379                     "type": "object",
46380                     "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.",
46381                     "additionalProperties": {
46382                         "type": ["string", "array"],
46383                         "items": {
46384                             "type": "string"
46385                         }
46386                     }
46387                 },
46388                 "psr-4": {
46389                     "type": "object",
46390                     "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.",
46391                     "additionalProperties": {
46392                         "type": ["string", "array"],
46393                         "items": {
46394                             "type": "string"
46395                         }
46396                     }
46397                 },
46398                 "classmap": {
46399                     "type": "array",
46400                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
46401                 },
46402                 "files": {
46403                     "type": "array",
46404                     "description": "This is an array of files that are always required on every request."
46405                 },
46406                 "exclude-from-classmap": {
46407                     "type": "array",
46408                     "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
46409                 }
46410             }
46411         },
46412         "repository": {
46413             "type": "object",
46414             "oneOf": [
46415                 { "$ref": "#/definitions/composer-repository" },
46416                 { "$ref": "#/definitions/vcs-repository" },
46417                 { "$ref": "#/definitions/path-repository" },
46418                 { "$ref": "#/definitions/artifact-repository" },
46419                 { "$ref": "#/definitions/pear-repository" },
46420                 { "$ref": "#/definitions/package-repository" }
46421             ]
46422         },
46423         "composer-repository": {
46424             "type": "object",
46425             "required": ["type", "url"],
46426             "properties": {
46427                 "type": { "type": "string", "enum": ["composer"] },
46428                 "url": { "type": "string" },
46429                 "options": {
46430                     "type": "object",
46431                     "additionalProperties": true
46432                 },
46433                 "allow_ssl_downgrade": { "type": "boolean" },
46434                 "force-lazy-providers": { "type": "boolean" }
46435             }
46436         },
46437         "vcs-repository": {
46438             "type": "object",
46439             "required": ["type", "url"],
46440             "properties": {
46441                 "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] },
46442                 "url": { "type": "string" },
46443                 "no-api": { "type": "boolean" },
46444                 "secure-http": { "type": "boolean" },
46445                 "svn-cache-credentials": { "type": "boolean" },
46446                 "trunk-path": { "type": ["string", "boolean"] },
46447                 "branches-path": { "type": ["string", "boolean"] },
46448                 "tags-path": { "type": ["string", "boolean"] },
46449                 "package-path": { "type": "string" },
46450                 "depot": { "type": "string" },
46451                 "branch": { "type": "string" },
46452                 "unique_perforce_client_name": { "type": "string" },
46453                 "p4user": { "type": "string" },
46454                 "p4password": { "type": "string" }
46455             }
46456         },
46457         "path-repository": {
46458             "type": "object",
46459             "required": ["type", "url"],
46460             "properties": {
46461                 "type": { "type": "string", "enum": ["path"] },
46462                 "url": { "type": "string" },
46463                 "options": {
46464                     "type": "object",
46465                     "properties": {
46466                         "symlink": { "type": ["boolean", "null"] }
46467                     },
46468                     "additionalProperties": true
46469                 }
46470             }
46471         },
46472         "artifact-repository": {
46473             "type": "object",
46474             "required": ["type", "url"],
46475             "properties": {
46476                 "type": { "type": "string", "enum": ["artifact"] },
46477                 "url": { "type": "string" }
46478             }
46479         },
46480         "pear-repository": {
46481             "type": "object",
46482             "required": ["type", "url"],
46483             "properties": {
46484                 "type": { "type": "string", "enum": ["pear"] },
46485                 "url": { "type": "string" },
46486                 "vendor-alias": { "type": "string" }
46487             }
46488         },
46489         "package-repository": {
46490             "type": "object",
46491             "required": ["type", "package"],
46492             "properties": {
46493                 "type": { "type": "string", "enum": ["package"] },
46494                 "package": {
46495                     "oneOf": [
46496                         { "$ref": "#/definitions/inline-package" },
46497                         {
46498                             "type": "array",
46499                             "items": { "$ref": "#/definitions/inline-package" }
46500                         }
46501                     ]
46502                 }
46503             }
46504         },
46505         "inline-package": {
46506             "type": "object",
46507             "required": ["name", "version"],
46508             "properties": {
46509                 "name": {
46510                     "type": "string",
46511                     "description": "Package name, including 'vendor-name/' prefix."
46512                 },
46513                 "type": {
46514                     "type": "string"
46515                 },
46516                 "target-dir": {
46517                     "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.",
46518                     "type": "string"
46519                 },
46520                 "description": {
46521                     "type": "string"
46522                 },
46523                 "keywords": {
46524                     "type": "array",
46525                     "items": {
46526                         "type": "string"
46527                     }
46528                 },
46529                 "homepage": {
46530                     "type": "string",
46531                     "format": "uri"
46532                 },
46533                 "version": {
46534                     "type": "string"
46535                 },
46536                 "time": {
46537                     "type": "string"
46538                 },
46539                 "license": {
46540                     "type": [
46541                         "string",
46542                         "array"
46543                     ]
46544                 },
46545                 "authors": {
46546                     "$ref": "#/definitions/authors"
46547                 },
46548                 "require": {
46549                     "type": "object",
46550                     "additionalProperties": {
46551                         "type": "string"
46552                     }
46553                 },
46554                 "replace": {
46555                     "type": "object",
46556                     "additionalProperties": {
46557                         "type": "string"
46558                     }
46559                 },
46560                 "conflict": {
46561                     "type": "object",
46562                     "additionalProperties": {
46563                         "type": "string"
46564                     }
46565                 },
46566                 "provide": {
46567                     "type": "object",
46568                     "additionalProperties": {
46569                         "type": "string"
46570                     }
46571                 },
46572                 "require-dev": {
46573                     "type": "object",
46574                     "additionalProperties": {
46575                         "type": "string"
46576                     }
46577                 },
46578                 "suggest": {
46579                     "type": "object",
46580                     "additionalProperties": {
46581                         "type": "string"
46582                     }
46583                 },
46584                 "extra": {
46585                     "type": ["object", "array"],
46586                     "additionalProperties": true
46587                 },
46588                 "autoload": {
46589                     "$ref": "#/definitions/autoload"
46590                 },
46591                 "archive": {
46592                     "type": ["object"],
46593                     "properties": {
46594                         "exclude": {
46595                             "type": "array"
46596                         }
46597                     }
46598                 },
46599                 "bin": {
46600                     "type": ["string", "array"],
46601                     "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
46602                     "items": {
46603                         "type": "string"
46604                     }
46605                 },
46606                 "include-path": {
46607                     "type": ["array"],
46608                     "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.",
46609                     "items": {
46610                         "type": "string"
46611                     }
46612                 },
46613                 "source": {
46614                     "type": "object",
46615                     "required": ["type", "url", "reference"],
46616                     "properties": {
46617                         "type": {
46618                             "type": "string"
46619                         },
46620                         "url": {
46621                             "type": "string"
46622                         },
46623                         "reference": {
46624                             "type": "string"
46625                         },
46626                         "mirrors": {
46627                             "type": "array"
46628                         }
46629                     }
46630                 },
46631                 "dist": {
46632                     "type": "object",
46633                     "required": ["type", "url"],
46634                     "properties": {
46635                         "type": {
46636                             "type": "string"
46637                         },
46638                         "url": {
46639                             "type": "string"
46640                         },
46641                         "reference": {
46642                             "type": "string"
46643                         },
46644                         "shasum": {
46645                             "type": "string"
46646                         },
46647                         "mirrors": {
46648                             "type": "array"
46649                         }
46650                     }
46651                 }
46652             },
46653             "additionalProperties": true
46654         }
46655     }
46656 }
46657 {
46658     "389-exception": [
46659         "389 Directory Server Exception"
46660     ],
46661     "Autoconf-exception-2.0": [
46662         "Autoconf exception 2.0"
46663     ],
46664     "Autoconf-exception-3.0": [
46665         "Autoconf exception 3.0"
46666     ],
46667     "Bison-exception-2.2": [
46668         "Bison exception 2.2"
46669     ],
46670     "Bootloader-exception": [
46671         "Bootloader Distribution Exception"
46672     ],
46673     "Classpath-exception-2.0": [
46674         "Classpath exception 2.0"
46675     ],
46676     "CLISP-exception-2.0": [
46677         "CLISP exception 2.0"
46678     ],
46679     "DigiRule-FOSS-exception": [
46680         "DigiRule FOSS License Exception"
46681     ],
46682     "eCos-exception-2.0": [
46683         "eCos exception 2.0"
46684     ],
46685     "Fawkes-Runtime-exception": [
46686         "Fawkes Runtime Exception"
46687     ],
46688     "FLTK-exception": [
46689         "FLTK exception"
46690     ],
46691     "Font-exception-2.0": [
46692         "Font exception 2.0"
46693     ],
46694     "freertos-exception-2.0": [
46695         "FreeRTOS Exception 2.0"
46696     ],
46697     "GCC-exception-2.0": [
46698         "GCC Runtime Library exception 2.0"
46699     ],
46700     "GCC-exception-3.1": [
46701         "GCC Runtime Library exception 3.1"
46702     ],
46703     "gnu-javamail-exception": [
46704         "GNU JavaMail exception"
46705     ],
46706     "i2p-gpl-java-exception": [
46707         "i2p GPL+Java Exception"
46708     ],
46709     "Libtool-exception": [
46710         "Libtool Exception"
46711     ],
46712     "Linux-syscall-note": [
46713         "Linux Syscall Note"
46714     ],
46715     "LLVM-exception": [
46716         "LLVM Exception"
46717     ],
46718     "LZMA-exception": [
46719         "LZMA exception"
46720     ],
46721     "mif-exception": [
46722         "Macros and Inline Functions Exception"
46723     ],
46724     "Nokia-Qt-exception-1.1": [
46725         "Nokia Qt LGPL exception 1.1"
46726     ],
46727     "OCCT-exception-1.0": [
46728         "Open CASCADE Exception 1.0"
46729     ],
46730     "OpenJDK-assembly-exception-1.0": [
46731         "OpenJDK Assembly exception 1.0"
46732     ],
46733     "openvpn-openssl-exception": [
46734         "OpenVPN OpenSSL Exception"
46735     ],
46736     "Qwt-exception-1.0": [
46737         "Qwt exception 1.0"
46738     ],
46739     "u-boot-exception-2.0": [
46740         "U-Boot exception 2.0"
46741     ],
46742     "WxWindows-exception-3.1": [
46743         "WxWindows Library Exception 3.1"
46744     ]
46745 }{
46746     "0BSD": [
46747         "BSD Zero Clause License",
46748         false,
46749         false
46750     ],
46751     "AAL": [
46752         "Attribution Assurance License",
46753         true,
46754         false
46755     ],
46756     "Abstyles": [
46757         "Abstyles License",
46758         false,
46759         false
46760     ],
46761     "Adobe-2006": [
46762         "Adobe Systems Incorporated Source Code License Agreement",
46763         false,
46764         false
46765     ],
46766     "Adobe-Glyph": [
46767         "Adobe Glyph List License",
46768         false,
46769         false
46770     ],
46771     "ADSL": [
46772         "Amazon Digital Services License",
46773         false,
46774         false
46775     ],
46776     "AFL-1.1": [
46777         "Academic Free License v1.1",
46778         true,
46779         false
46780     ],
46781     "AFL-1.2": [
46782         "Academic Free License v1.2",
46783         true,
46784         false
46785     ],
46786     "AFL-2.0": [
46787         "Academic Free License v2.0",
46788         true,
46789         false
46790     ],
46791     "AFL-2.1": [
46792         "Academic Free License v2.1",
46793         true,
46794         false
46795     ],
46796     "AFL-3.0": [
46797         "Academic Free License v3.0",
46798         true,
46799         false
46800     ],
46801     "Afmparse": [
46802         "Afmparse License",
46803         false,
46804         false
46805     ],
46806     "AGPL-1.0": [
46807         "Affero General Public License v1.0",
46808         false,
46809         true
46810     ],
46811     "AGPL-1.0-only": [
46812         "Affero General Public License v1.0 only",
46813         false,
46814         false
46815     ],
46816     "AGPL-1.0-or-later": [
46817         "Affero General Public License v1.0 or later",
46818         false,
46819         false
46820     ],
46821     "AGPL-3.0": [
46822         "GNU Affero General Public License v3.0",
46823         true,
46824         true
46825     ],
46826     "AGPL-3.0-only": [
46827         "GNU Affero General Public License v3.0 only",
46828         true,
46829         false
46830     ],
46831     "AGPL-3.0-or-later": [
46832         "GNU Affero General Public License v3.0 or later",
46833         true,
46834         false
46835     ],
46836     "Aladdin": [
46837         "Aladdin Free Public License",
46838         false,
46839         false
46840     ],
46841     "AMDPLPA": [
46842         "AMD's plpa_map.c License",
46843         false,
46844         false
46845     ],
46846     "AML": [
46847         "Apple MIT License",
46848         false,
46849         false
46850     ],
46851     "AMPAS": [
46852         "Academy of Motion Picture Arts and Sciences BSD",
46853         false,
46854         false
46855     ],
46856     "ANTLR-PD": [
46857         "ANTLR Software Rights Notice",
46858         false,
46859         false
46860     ],
46861     "Apache-1.0": [
46862         "Apache License 1.0",
46863         false,
46864         false
46865     ],
46866     "Apache-1.1": [
46867         "Apache License 1.1",
46868         true,
46869         false
46870     ],
46871     "Apache-2.0": [
46872         "Apache License 2.0",
46873         true,
46874         false
46875     ],
46876     "APAFML": [
46877         "Adobe Postscript AFM License",
46878         false,
46879         false
46880     ],
46881     "APL-1.0": [
46882         "Adaptive Public License 1.0",
46883         true,
46884         false
46885     ],
46886     "APSL-1.0": [
46887         "Apple Public Source License 1.0",
46888         true,
46889         false
46890     ],
46891     "APSL-1.1": [
46892         "Apple Public Source License 1.1",
46893         true,
46894         false
46895     ],
46896     "APSL-1.2": [
46897         "Apple Public Source License 1.2",
46898         true,
46899         false
46900     ],
46901     "APSL-2.0": [
46902         "Apple Public Source License 2.0",
46903         true,
46904         false
46905     ],
46906     "Artistic-1.0": [
46907         "Artistic License 1.0",
46908         true,
46909         false
46910     ],
46911     "Artistic-1.0-cl8": [
46912         "Artistic License 1.0 w/clause 8",
46913         true,
46914         false
46915     ],
46916     "Artistic-1.0-Perl": [
46917         "Artistic License 1.0 (Perl)",
46918         true,
46919         false
46920     ],
46921     "Artistic-2.0": [
46922         "Artistic License 2.0",
46923         true,
46924         false
46925     ],
46926     "Bahyph": [
46927         "Bahyph License",
46928         false,
46929         false
46930     ],
46931     "Barr": [
46932         "Barr License",
46933         false,
46934         false
46935     ],
46936     "Beerware": [
46937         "Beerware License",
46938         false,
46939         false
46940     ],
46941     "BitTorrent-1.0": [
46942         "BitTorrent Open Source License v1.0",
46943         false,
46944         false
46945     ],
46946     "BitTorrent-1.1": [
46947         "BitTorrent Open Source License v1.1",
46948         false,
46949         false
46950     ],
46951     "Borceux": [
46952         "Borceux license",
46953         false,
46954         false
46955     ],
46956     "BSD-1-Clause": [
46957         "BSD 1-Clause License",
46958         false,
46959         false
46960     ],
46961     "BSD-2-Clause": [
46962         "BSD 2-Clause \"Simplified\" License",
46963         true,
46964         false
46965     ],
46966     "BSD-2-Clause-FreeBSD": [
46967         "BSD 2-Clause FreeBSD License",
46968         false,
46969         false
46970     ],
46971     "BSD-2-Clause-NetBSD": [
46972         "BSD 2-Clause NetBSD License",
46973         false,
46974         false
46975     ],
46976     "BSD-2-Clause-Patent": [
46977         "BSD-2-Clause Plus Patent License",
46978         true,
46979         false
46980     ],
46981     "BSD-3-Clause": [
46982         "BSD 3-Clause \"New\" or \"Revised\" License",
46983         true,
46984         false
46985     ],
46986     "BSD-3-Clause-Attribution": [
46987         "BSD with attribution",
46988         false,
46989         false
46990     ],
46991     "BSD-3-Clause-Clear": [
46992         "BSD 3-Clause Clear License",
46993         false,
46994         false
46995     ],
46996     "BSD-3-Clause-LBNL": [
46997         "Lawrence Berkeley National Labs BSD variant license",
46998         false,
46999         false
47000     ],
47001     "BSD-3-Clause-No-Nuclear-License": [
47002         "BSD 3-Clause No Nuclear License",
47003         false,
47004         false
47005     ],
47006     "BSD-3-Clause-No-Nuclear-License-2014": [
47007         "BSD 3-Clause No Nuclear License 2014",
47008         false,
47009         false
47010     ],
47011     "BSD-3-Clause-No-Nuclear-Warranty": [
47012         "BSD 3-Clause No Nuclear Warranty",
47013         false,
47014         false
47015     ],
47016     "BSD-4-Clause": [
47017         "BSD 4-Clause \"Original\" or \"Old\" License",
47018         false,
47019         false
47020     ],
47021     "BSD-4-Clause-UC": [
47022         "BSD-4-Clause (University of California-Specific)",
47023         false,
47024         false
47025     ],
47026     "BSD-Protection": [
47027         "BSD Protection License",
47028         false,
47029         false
47030     ],
47031     "BSD-Source-Code": [
47032         "BSD Source Code Attribution",
47033         false,
47034         false
47035     ],
47036     "BSL-1.0": [
47037         "Boost Software License 1.0",
47038         true,
47039         false
47040     ],
47041     "bzip2-1.0.5": [
47042         "bzip2 and libbzip2 License v1.0.5",
47043         false,
47044         false
47045     ],
47046     "bzip2-1.0.6": [
47047         "bzip2 and libbzip2 License v1.0.6",
47048         false,
47049         false
47050     ],
47051     "Caldera": [
47052         "Caldera License",
47053         false,
47054         false
47055     ],
47056     "CATOSL-1.1": [
47057         "Computer Associates Trusted Open Source License 1.1",
47058         true,
47059         false
47060     ],
47061     "CC-BY-1.0": [
47062         "Creative Commons Attribution 1.0 Generic",
47063         false,
47064         false
47065     ],
47066     "CC-BY-2.0": [
47067         "Creative Commons Attribution 2.0 Generic",
47068         false,
47069         false
47070     ],
47071     "CC-BY-2.5": [
47072         "Creative Commons Attribution 2.5 Generic",
47073         false,
47074         false
47075     ],
47076     "CC-BY-3.0": [
47077         "Creative Commons Attribution 3.0 Unported",
47078         false,
47079         false
47080     ],
47081     "CC-BY-4.0": [
47082         "Creative Commons Attribution 4.0 International",
47083         false,
47084         false
47085     ],
47086     "CC-BY-NC-1.0": [
47087         "Creative Commons Attribution Non Commercial 1.0 Generic",
47088         false,
47089         false
47090     ],
47091     "CC-BY-NC-2.0": [
47092         "Creative Commons Attribution Non Commercial 2.0 Generic",
47093         false,
47094         false
47095     ],
47096     "CC-BY-NC-2.5": [
47097         "Creative Commons Attribution Non Commercial 2.5 Generic",
47098         false,
47099         false
47100     ],
47101     "CC-BY-NC-3.0": [
47102         "Creative Commons Attribution Non Commercial 3.0 Unported",
47103         false,
47104         false
47105     ],
47106     "CC-BY-NC-4.0": [
47107         "Creative Commons Attribution Non Commercial 4.0 International",
47108         false,
47109         false
47110     ],
47111     "CC-BY-NC-ND-1.0": [
47112         "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic",
47113         false,
47114         false
47115     ],
47116     "CC-BY-NC-ND-2.0": [
47117         "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic",
47118         false,
47119         false
47120     ],
47121     "CC-BY-NC-ND-2.5": [
47122         "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic",
47123         false,
47124         false
47125     ],
47126     "CC-BY-NC-ND-3.0": [
47127         "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported",
47128         false,
47129         false
47130     ],
47131     "CC-BY-NC-ND-4.0": [
47132         "Creative Commons Attribution Non Commercial No Derivatives 4.0 International",
47133         false,
47134         false
47135     ],
47136     "CC-BY-NC-SA-1.0": [
47137         "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic",
47138         false,
47139         false
47140     ],
47141     "CC-BY-NC-SA-2.0": [
47142         "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic",
47143         false,
47144         false
47145     ],
47146     "CC-BY-NC-SA-2.5": [
47147         "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic",
47148         false,
47149         false
47150     ],
47151     "CC-BY-NC-SA-3.0": [
47152         "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported",
47153         false,
47154         false
47155     ],
47156     "CC-BY-NC-SA-4.0": [
47157         "Creative Commons Attribution Non Commercial Share Alike 4.0 International",
47158         false,
47159         false
47160     ],
47161     "CC-BY-ND-1.0": [
47162         "Creative Commons Attribution No Derivatives 1.0 Generic",
47163         false,
47164         false
47165     ],
47166     "CC-BY-ND-2.0": [
47167         "Creative Commons Attribution No Derivatives 2.0 Generic",
47168         false,
47169         false
47170     ],
47171     "CC-BY-ND-2.5": [
47172         "Creative Commons Attribution No Derivatives 2.5 Generic",
47173         false,
47174         false
47175     ],
47176     "CC-BY-ND-3.0": [
47177         "Creative Commons Attribution No Derivatives 3.0 Unported",
47178         false,
47179         false
47180     ],
47181     "CC-BY-ND-4.0": [
47182         "Creative Commons Attribution No Derivatives 4.0 International",
47183         false,
47184         false
47185     ],
47186     "CC-BY-SA-1.0": [
47187         "Creative Commons Attribution Share Alike 1.0 Generic",
47188         false,
47189         false
47190     ],
47191     "CC-BY-SA-2.0": [
47192         "Creative Commons Attribution Share Alike 2.0 Generic",
47193         false,
47194         false
47195     ],
47196     "CC-BY-SA-2.5": [
47197         "Creative Commons Attribution Share Alike 2.5 Generic",
47198         false,
47199         false
47200     ],
47201     "CC-BY-SA-3.0": [
47202         "Creative Commons Attribution Share Alike 3.0 Unported",
47203         false,
47204         false
47205     ],
47206     "CC-BY-SA-4.0": [
47207         "Creative Commons Attribution Share Alike 4.0 International",
47208         false,
47209         false
47210     ],
47211     "CC0-1.0": [
47212         "Creative Commons Zero v1.0 Universal",
47213         false,
47214         false
47215     ],
47216     "CDDL-1.0": [
47217         "Common Development and Distribution License 1.0",
47218         true,
47219         false
47220     ],
47221     "CDDL-1.1": [
47222         "Common Development and Distribution License 1.1",
47223         false,
47224         false
47225     ],
47226     "CDLA-Permissive-1.0": [
47227         "Community Data License Agreement Permissive 1.0",
47228         false,
47229         false
47230     ],
47231     "CDLA-Sharing-1.0": [
47232         "Community Data License Agreement Sharing 1.0",
47233         false,
47234         false
47235     ],
47236     "CECILL-1.0": [
47237         "CeCILL Free Software License Agreement v1.0",
47238         false,
47239         false
47240     ],
47241     "CECILL-1.1": [
47242         "CeCILL Free Software License Agreement v1.1",
47243         false,
47244         false
47245     ],
47246     "CECILL-2.0": [
47247         "CeCILL Free Software License Agreement v2.0",
47248         false,
47249         false
47250     ],
47251     "CECILL-2.1": [
47252         "CeCILL Free Software License Agreement v2.1",
47253         true,
47254         false
47255     ],
47256     "CECILL-B": [
47257         "CeCILL-B Free Software License Agreement",
47258         false,
47259         false
47260     ],
47261     "CECILL-C": [
47262         "CeCILL-C Free Software License Agreement",
47263         false,
47264         false
47265     ],
47266     "ClArtistic": [
47267         "Clarified Artistic License",
47268         false,
47269         false
47270     ],
47271     "CNRI-Jython": [
47272         "CNRI Jython License",
47273         false,
47274         false
47275     ],
47276     "CNRI-Python": [
47277         "CNRI Python License",
47278         true,
47279         false
47280     ],
47281     "CNRI-Python-GPL-Compatible": [
47282         "CNRI Python Open Source GPL Compatible License Agreement",
47283         false,
47284         false
47285     ],
47286     "Condor-1.1": [
47287         "Condor Public License v1.1",
47288         false,
47289         false
47290     ],
47291     "CPAL-1.0": [
47292         "Common Public Attribution License 1.0",
47293         true,
47294         false
47295     ],
47296     "CPL-1.0": [
47297         "Common Public License 1.0",
47298         true,
47299         false
47300     ],
47301     "CPOL-1.02": [
47302         "Code Project Open License 1.02",
47303         false,
47304         false
47305     ],
47306     "Crossword": [
47307         "Crossword License",
47308         false,
47309         false
47310     ],
47311     "CrystalStacker": [
47312         "CrystalStacker License",
47313         false,
47314         false
47315     ],
47316     "CUA-OPL-1.0": [
47317         "CUA Office Public License v1.0",
47318         true,
47319         false
47320     ],
47321     "Cube": [
47322         "Cube License",
47323         false,
47324         false
47325     ],
47326     "curl": [
47327         "curl License",
47328         false,
47329         false
47330     ],
47331     "D-FSL-1.0": [
47332         "Deutsche Freie Software Lizenz",
47333         false,
47334         false
47335     ],
47336     "diffmark": [
47337         "diffmark license",
47338         false,
47339         false
47340     ],
47341     "DOC": [
47342         "DOC License",
47343         false,
47344         false
47345     ],
47346     "Dotseqn": [
47347         "Dotseqn License",
47348         false,
47349         false
47350     ],
47351     "DSDP": [
47352         "DSDP License",
47353         false,
47354         false
47355     ],
47356     "dvipdfm": [
47357         "dvipdfm License",
47358         false,
47359         false
47360     ],
47361     "ECL-1.0": [
47362         "Educational Community License v1.0",
47363         true,
47364         false
47365     ],
47366     "ECL-2.0": [
47367         "Educational Community License v2.0",
47368         true,
47369         false
47370     ],
47371     "eCos-2.0": [
47372         "eCos license version 2.0",
47373         false,
47374         true
47375     ],
47376     "EFL-1.0": [
47377         "Eiffel Forum License v1.0",
47378         true,
47379         false
47380     ],
47381     "EFL-2.0": [
47382         "Eiffel Forum License v2.0",
47383         true,
47384         false
47385     ],
47386     "eGenix": [
47387         "eGenix.com Public License 1.1.0",
47388         false,
47389         false
47390     ],
47391     "Entessa": [
47392         "Entessa Public License v1.0",
47393         true,
47394         false
47395     ],
47396     "EPL-1.0": [
47397         "Eclipse Public License 1.0",
47398         true,
47399         false
47400     ],
47401     "EPL-2.0": [
47402         "Eclipse Public License 2.0",
47403         true,
47404         false
47405     ],
47406     "ErlPL-1.1": [
47407         "Erlang Public License v1.1",
47408         false,
47409         false
47410     ],
47411     "EUDatagrid": [
47412         "EU DataGrid Software License",
47413         true,
47414         false
47415     ],
47416     "EUPL-1.0": [
47417         "European Union Public License 1.0",
47418         false,
47419         false
47420     ],
47421     "EUPL-1.1": [
47422         "European Union Public License 1.1",
47423         true,
47424         false
47425     ],
47426     "EUPL-1.2": [
47427         "European Union Public License 1.2",
47428         true,
47429         false
47430     ],
47431     "Eurosym": [
47432         "Eurosym License",
47433         false,
47434         false
47435     ],
47436     "Fair": [
47437         "Fair License",
47438         true,
47439         false
47440     ],
47441     "Frameworx-1.0": [
47442         "Frameworx Open License 1.0",
47443         true,
47444         false
47445     ],
47446     "FreeImage": [
47447         "FreeImage Public License v1.0",
47448         false,
47449         false
47450     ],
47451     "FSFAP": [
47452         "FSF All Permissive License",
47453         false,
47454         false
47455     ],
47456     "FSFUL": [
47457         "FSF Unlimited License",
47458         false,
47459         false
47460     ],
47461     "FSFULLR": [
47462         "FSF Unlimited License (with License Retention)",
47463         false,
47464         false
47465     ],
47466     "FTL": [
47467         "Freetype Project License",
47468         false,
47469         false
47470     ],
47471     "GFDL-1.1": [
47472         "GNU Free Documentation License v1.1",
47473         false,
47474         true
47475     ],
47476     "GFDL-1.1-only": [
47477         "GNU Free Documentation License v1.1 only",
47478         false,
47479         false
47480     ],
47481     "GFDL-1.1-or-later": [
47482         "GNU Free Documentation License v1.1 or later",
47483         false,
47484         false
47485     ],
47486     "GFDL-1.2": [
47487         "GNU Free Documentation License v1.2",
47488         false,
47489         true
47490     ],
47491     "GFDL-1.2-only": [
47492         "GNU Free Documentation License v1.2 only",
47493         false,
47494         false
47495     ],
47496     "GFDL-1.2-or-later": [
47497         "GNU Free Documentation License v1.2 or later",
47498         false,
47499         false
47500     ],
47501     "GFDL-1.3": [
47502         "GNU Free Documentation License v1.3",
47503         false,
47504         true
47505     ],
47506     "GFDL-1.3-only": [
47507         "GNU Free Documentation License v1.3 only",
47508         false,
47509         false
47510     ],
47511     "GFDL-1.3-or-later": [
47512         "GNU Free Documentation License v1.3 or later",
47513         false,
47514         false
47515     ],
47516     "Giftware": [
47517         "Giftware License",
47518         false,
47519         false
47520     ],
47521     "GL2PS": [
47522         "GL2PS License",
47523         false,
47524         false
47525     ],
47526     "Glide": [
47527         "3dfx Glide License",
47528         false,
47529         false
47530     ],
47531     "Glulxe": [
47532         "Glulxe License",
47533         false,
47534         false
47535     ],
47536     "gnuplot": [
47537         "gnuplot License",
47538         false,
47539         false
47540     ],
47541     "GPL-1.0": [
47542         "GNU General Public License v1.0 only",
47543         false,
47544         true
47545     ],
47546     "GPL-1.0+": [
47547         "GNU General Public License v1.0 or later",
47548         false,
47549         true
47550     ],
47551     "GPL-1.0-only": [
47552         "GNU General Public License v1.0 only",
47553         false,
47554         false
47555     ],
47556     "GPL-1.0-or-later": [
47557         "GNU General Public License v1.0 or later",
47558         false,
47559         false
47560     ],
47561     "GPL-2.0": [
47562         "GNU General Public License v2.0 only",
47563         true,
47564         true
47565     ],
47566     "GPL-2.0+": [
47567         "GNU General Public License v2.0 or later",
47568         true,
47569         true
47570     ],
47571     "GPL-2.0-only": [
47572         "GNU General Public License v2.0 only",
47573         true,
47574         false
47575     ],
47576     "GPL-2.0-or-later": [
47577         "GNU General Public License v2.0 or later",
47578         true,
47579         false
47580     ],
47581     "GPL-2.0-with-autoconf-exception": [
47582         "GNU General Public License v2.0 w/Autoconf exception",
47583         false,
47584         true
47585     ],
47586     "GPL-2.0-with-bison-exception": [
47587         "GNU General Public License v2.0 w/Bison exception",
47588         false,
47589         true
47590     ],
47591     "GPL-2.0-with-classpath-exception": [
47592         "GNU General Public License v2.0 w/Classpath exception",
47593         false,
47594         true
47595     ],
47596     "GPL-2.0-with-font-exception": [
47597         "GNU General Public License v2.0 w/Font exception",
47598         false,
47599         true
47600     ],
47601     "GPL-2.0-with-GCC-exception": [
47602         "GNU General Public License v2.0 w/GCC Runtime Library exception",
47603         false,
47604         true
47605     ],
47606     "GPL-3.0": [
47607         "GNU General Public License v3.0 only",
47608         true,
47609         true
47610     ],
47611     "GPL-3.0+": [
47612         "GNU General Public License v3.0 or later",
47613         true,
47614         true
47615     ],
47616     "GPL-3.0-only": [
47617         "GNU General Public License v3.0 only",
47618         true,
47619         false
47620     ],
47621     "GPL-3.0-or-later": [
47622         "GNU General Public License v3.0 or later",
47623         true,
47624         false
47625     ],
47626     "GPL-3.0-with-autoconf-exception": [
47627         "GNU General Public License v3.0 w/Autoconf exception",
47628         false,
47629         true
47630     ],
47631     "GPL-3.0-with-GCC-exception": [
47632         "GNU General Public License v3.0 w/GCC Runtime Library exception",
47633         true,
47634         true
47635     ],
47636     "gSOAP-1.3b": [
47637         "gSOAP Public License v1.3b",
47638         false,
47639         false
47640     ],
47641     "HaskellReport": [
47642         "Haskell Language Report License",
47643         false,
47644         false
47645     ],
47646     "HPND": [
47647         "Historical Permission Notice and Disclaimer",
47648         true,
47649         false
47650     ],
47651     "IBM-pibs": [
47652         "IBM PowerPC Initialization and Boot Software",
47653         false,
47654         false
47655     ],
47656     "ICU": [
47657         "ICU License",
47658         false,
47659         false
47660     ],
47661     "IJG": [
47662         "Independent JPEG Group License",
47663         false,
47664         false
47665     ],
47666     "ImageMagick": [
47667         "ImageMagick License",
47668         false,
47669         false
47670     ],
47671     "iMatix": [
47672         "iMatix Standard Function Library Agreement",
47673         false,
47674         false
47675     ],
47676     "Imlib2": [
47677         "Imlib2 License",
47678         false,
47679         false
47680     ],
47681     "Info-ZIP": [
47682         "Info-ZIP License",
47683         false,
47684         false
47685     ],
47686     "Intel": [
47687         "Intel Open Source License",
47688         true,
47689         false
47690     ],
47691     "Intel-ACPI": [
47692         "Intel ACPI Software License Agreement",
47693         false,
47694         false
47695     ],
47696     "Interbase-1.0": [
47697         "Interbase Public License v1.0",
47698         false,
47699         false
47700     ],
47701     "IPA": [
47702         "IPA Font License",
47703         true,
47704         false
47705     ],
47706     "IPL-1.0": [
47707         "IBM Public License v1.0",
47708         true,
47709         false
47710     ],
47711     "ISC": [
47712         "ISC License",
47713         true,
47714         false
47715     ],
47716     "JasPer-2.0": [
47717         "JasPer License",
47718         false,
47719         false
47720     ],
47721     "JSON": [
47722         "JSON License",
47723         false,
47724         false
47725     ],
47726     "LAL-1.2": [
47727         "Licence Art Libre 1.2",
47728         false,
47729         false
47730     ],
47731     "LAL-1.3": [
47732         "Licence Art Libre 1.3",
47733         false,
47734         false
47735     ],
47736     "Latex2e": [
47737         "Latex2e License",
47738         false,
47739         false
47740     ],
47741     "Leptonica": [
47742         "Leptonica License",
47743         false,
47744         false
47745     ],
47746     "LGPL-2.0": [
47747         "GNU Library General Public License v2 only",
47748         true,
47749         true
47750     ],
47751     "LGPL-2.0+": [
47752         "GNU Library General Public License v2 or later",
47753         true,
47754         true
47755     ],
47756     "LGPL-2.0-only": [
47757         "GNU Library General Public License v2 only",
47758         true,
47759         false
47760     ],
47761     "LGPL-2.0-or-later": [
47762         "GNU Library General Public License v2 or later",
47763         true,
47764         false
47765     ],
47766     "LGPL-2.1": [
47767         "GNU Lesser General Public License v2.1 only",
47768         true,
47769         true
47770     ],
47771     "LGPL-2.1+": [
47772         "GNU Library General Public License v2.1 or later",
47773         true,
47774         true
47775     ],
47776     "LGPL-2.1-only": [
47777         "GNU Lesser General Public License v2.1 only",
47778         true,
47779         false
47780     ],
47781     "LGPL-2.1-or-later": [
47782         "GNU Lesser General Public License v2.1 or later",
47783         true,
47784         false
47785     ],
47786     "LGPL-3.0": [
47787         "GNU Lesser General Public License v3.0 only",
47788         true,
47789         true
47790     ],
47791     "LGPL-3.0+": [
47792         "GNU Lesser General Public License v3.0 or later",
47793         true,
47794         true
47795     ],
47796     "LGPL-3.0-only": [
47797         "GNU Lesser General Public License v3.0 only",
47798         true,
47799         false
47800     ],
47801     "LGPL-3.0-or-later": [
47802         "GNU Lesser General Public License v3.0 or later",
47803         true,
47804         false
47805     ],
47806     "LGPLLR": [
47807         "Lesser General Public License For Linguistic Resources",
47808         false,
47809         false
47810     ],
47811     "Libpng": [
47812         "libpng License",
47813         false,
47814         false
47815     ],
47816     "libtiff": [
47817         "libtiff License",
47818         false,
47819         false
47820     ],
47821     "LiLiQ-P-1.1": [
47822         "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1",
47823         true,
47824         false
47825     ],
47826     "LiLiQ-R-1.1": [
47827         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1",
47828         true,
47829         false
47830     ],
47831     "LiLiQ-Rplus-1.1": [
47832         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1",
47833         true,
47834         false
47835     ],
47836     "Linux-OpenIB": [
47837         "Linux Kernel Variant of OpenIB.org license",
47838         false,
47839         false
47840     ],
47841     "LPL-1.0": [
47842         "Lucent Public License Version 1.0",
47843         true,
47844         false
47845     ],
47846     "LPL-1.02": [
47847         "Lucent Public License v1.02",
47848         true,
47849         false
47850     ],
47851     "LPPL-1.0": [
47852         "LaTeX Project Public License v1.0",
47853         false,
47854         false
47855     ],
47856     "LPPL-1.1": [
47857         "LaTeX Project Public License v1.1",
47858         false,
47859         false
47860     ],
47861     "LPPL-1.2": [
47862         "LaTeX Project Public License v1.2",
47863         false,
47864         false
47865     ],
47866     "LPPL-1.3a": [
47867         "LaTeX Project Public License v1.3a",
47868         false,
47869         false
47870     ],
47871     "LPPL-1.3c": [
47872         "LaTeX Project Public License v1.3c",
47873         true,
47874         false
47875     ],
47876     "MakeIndex": [
47877         "MakeIndex License",
47878         false,
47879         false
47880     ],
47881     "MirOS": [
47882         "MirOS License",
47883         true,
47884         false
47885     ],
47886     "MIT": [
47887         "MIT License",
47888         true,
47889         false
47890     ],
47891     "MIT-0": [
47892         "MIT No Attribution",
47893         true,
47894         false
47895     ],
47896     "MIT-advertising": [
47897         "Enlightenment License (e16)",
47898         false,
47899         false
47900     ],
47901     "MIT-CMU": [
47902         "CMU License",
47903         false,
47904         false
47905     ],
47906     "MIT-enna": [
47907         "enna License",
47908         false,
47909         false
47910     ],
47911     "MIT-feh": [
47912         "feh License",
47913         false,
47914         false
47915     ],
47916     "MITNFA": [
47917         "MIT +no-false-attribs license",
47918         false,
47919         false
47920     ],
47921     "Motosoto": [
47922         "Motosoto License",
47923         true,
47924         false
47925     ],
47926     "mpich2": [
47927         "mpich2 License",
47928         false,
47929         false
47930     ],
47931     "MPL-1.0": [
47932         "Mozilla Public License 1.0",
47933         true,
47934         false
47935     ],
47936     "MPL-1.1": [
47937         "Mozilla Public License 1.1",
47938         true,
47939         false
47940     ],
47941     "MPL-2.0": [
47942         "Mozilla Public License 2.0",
47943         true,
47944         false
47945     ],
47946     "MPL-2.0-no-copyleft-exception": [
47947         "Mozilla Public License 2.0 (no copyleft exception)",
47948         true,
47949         false
47950     ],
47951     "MS-PL": [
47952         "Microsoft Public License",
47953         true,
47954         false
47955     ],
47956     "MS-RL": [
47957         "Microsoft Reciprocal License",
47958         true,
47959         false
47960     ],
47961     "MTLL": [
47962         "Matrix Template Library License",
47963         false,
47964         false
47965     ],
47966     "Multics": [
47967         "Multics License",
47968         true,
47969         false
47970     ],
47971     "Mup": [
47972         "Mup License",
47973         false,
47974         false
47975     ],
47976     "NASA-1.3": [
47977         "NASA Open Source Agreement 1.3",
47978         true,
47979         false
47980     ],
47981     "Naumen": [
47982         "Naumen Public License",
47983         true,
47984         false
47985     ],
47986     "NBPL-1.0": [
47987         "Net Boolean Public License v1",
47988         false,
47989         false
47990     ],
47991     "NCSA": [
47992         "University of Illinois/NCSA Open Source License",
47993         true,
47994         false
47995     ],
47996     "Net-SNMP": [
47997         "Net-SNMP License",
47998         false,
47999         false
48000     ],
48001     "NetCDF": [
48002         "NetCDF license",
48003         false,
48004         false
48005     ],
48006     "Newsletr": [
48007         "Newsletr License",
48008         false,
48009         false
48010     ],
48011     "NGPL": [
48012         "Nethack General Public License",
48013         true,
48014         false
48015     ],
48016     "NLOD-1.0": [
48017         "Norwegian Licence for Open Government Data",
48018         false,
48019         false
48020     ],
48021     "NLPL": [
48022         "No Limit Public License",
48023         false,
48024         false
48025     ],
48026     "Nokia": [
48027         "Nokia Open Source License",
48028         true,
48029         false
48030     ],
48031     "NOSL": [
48032         "Netizen Open Source License",
48033         false,
48034         false
48035     ],
48036     "Noweb": [
48037         "Noweb License",
48038         false,
48039         false
48040     ],
48041     "NPL-1.0": [
48042         "Netscape Public License v1.0",
48043         false,
48044         false
48045     ],
48046     "NPL-1.1": [
48047         "Netscape Public License v1.1",
48048         false,
48049         false
48050     ],
48051     "NPOSL-3.0": [
48052         "Non-Profit Open Software License 3.0",
48053         true,
48054         false
48055     ],
48056     "NRL": [
48057         "NRL License",
48058         false,
48059         false
48060     ],
48061     "NTP": [
48062         "NTP License",
48063         true,
48064         false
48065     ],
48066     "Nunit": [
48067         "Nunit License",
48068         false,
48069         true
48070     ],
48071     "OCCT-PL": [
48072         "Open CASCADE Technology Public License",
48073         false,
48074         false
48075     ],
48076     "OCLC-2.0": [
48077         "OCLC Research Public License 2.0",
48078         true,
48079         false
48080     ],
48081     "ODbL-1.0": [
48082         "ODC Open Database License v1.0",
48083         false,
48084         false
48085     ],
48086     "OFL-1.0": [
48087         "SIL Open Font License 1.0",
48088         false,
48089         false
48090     ],
48091     "OFL-1.1": [
48092         "SIL Open Font License 1.1",
48093         true,
48094         false
48095     ],
48096     "OGTSL": [
48097         "Open Group Test Suite License",
48098         true,
48099         false
48100     ],
48101     "OLDAP-1.1": [
48102         "Open LDAP Public License v1.1",
48103         false,
48104         false
48105     ],
48106     "OLDAP-1.2": [
48107         "Open LDAP Public License v1.2",
48108         false,
48109         false
48110     ],
48111     "OLDAP-1.3": [
48112         "Open LDAP Public License v1.3",
48113         false,
48114         false
48115     ],
48116     "OLDAP-1.4": [
48117         "Open LDAP Public License v1.4",
48118         false,
48119         false
48120     ],
48121     "OLDAP-2.0": [
48122         "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
48123         false,
48124         false
48125     ],
48126     "OLDAP-2.0.1": [
48127         "Open LDAP Public License v2.0.1",
48128         false,
48129         false
48130     ],
48131     "OLDAP-2.1": [
48132         "Open LDAP Public License v2.1",
48133         false,
48134         false
48135     ],
48136     "OLDAP-2.2": [
48137         "Open LDAP Public License v2.2",
48138         false,
48139         false
48140     ],
48141     "OLDAP-2.2.1": [
48142         "Open LDAP Public License v2.2.1",
48143         false,
48144         false
48145     ],
48146     "OLDAP-2.2.2": [
48147         "Open LDAP Public License 2.2.2",
48148         false,
48149         false
48150     ],
48151     "OLDAP-2.3": [
48152         "Open LDAP Public License v2.3",
48153         false,
48154         false
48155     ],
48156     "OLDAP-2.4": [
48157         "Open LDAP Public License v2.4",
48158         false,
48159         false
48160     ],
48161     "OLDAP-2.5": [
48162         "Open LDAP Public License v2.5",
48163         false,
48164         false
48165     ],
48166     "OLDAP-2.6": [
48167         "Open LDAP Public License v2.6",
48168         false,
48169         false
48170     ],
48171     "OLDAP-2.7": [
48172         "Open LDAP Public License v2.7",
48173         false,
48174         false
48175     ],
48176     "OLDAP-2.8": [
48177         "Open LDAP Public License v2.8",
48178         false,
48179         false
48180     ],
48181     "OML": [
48182         "Open Market License",
48183         false,
48184         false
48185     ],
48186     "OpenSSL": [
48187         "OpenSSL License",
48188         false,
48189         false
48190     ],
48191     "OPL-1.0": [
48192         "Open Public License v1.0",
48193         false,
48194         false
48195     ],
48196     "OSET-PL-2.1": [
48197         "OSET Public License version 2.1",
48198         true,
48199         false
48200     ],
48201     "OSL-1.0": [
48202         "Open Software License 1.0",
48203         true,
48204         false
48205     ],
48206     "OSL-1.1": [
48207         "Open Software License 1.1",
48208         false,
48209         false
48210     ],
48211     "OSL-2.0": [
48212         "Open Software License 2.0",
48213         true,
48214         false
48215     ],
48216     "OSL-2.1": [
48217         "Open Software License 2.1",
48218         true,
48219         false
48220     ],
48221     "OSL-3.0": [
48222         "Open Software License 3.0",
48223         true,
48224         false
48225     ],
48226     "PDDL-1.0": [
48227         "ODC Public Domain Dedication & License 1.0",
48228         false,
48229         false
48230     ],
48231     "PHP-3.0": [
48232         "PHP License v3.0",
48233         true,
48234         false
48235     ],
48236     "PHP-3.01": [
48237         "PHP License v3.01",
48238         false,
48239         false
48240     ],
48241     "Plexus": [
48242         "Plexus Classworlds License",
48243         false,
48244         false
48245     ],
48246     "PostgreSQL": [
48247         "PostgreSQL License",
48248         true,
48249         false
48250     ],
48251     "psfrag": [
48252         "psfrag License",
48253         false,
48254         false
48255     ],
48256     "psutils": [
48257         "psutils License",
48258         false,
48259         false
48260     ],
48261     "Python-2.0": [
48262         "Python License 2.0",
48263         true,
48264         false
48265     ],
48266     "Qhull": [
48267         "Qhull License",
48268         false,
48269         false
48270     ],
48271     "QPL-1.0": [
48272         "Q Public License 1.0",
48273         true,
48274         false
48275     ],
48276     "Rdisc": [
48277         "Rdisc License",
48278         false,
48279         false
48280     ],
48281     "RHeCos-1.1": [
48282         "Red Hat eCos Public License v1.1",
48283         false,
48284         false
48285     ],
48286     "RPL-1.1": [
48287         "Reciprocal Public License 1.1",
48288         true,
48289         false
48290     ],
48291     "RPL-1.5": [
48292         "Reciprocal Public License 1.5",
48293         true,
48294         false
48295     ],
48296     "RPSL-1.0": [
48297         "RealNetworks Public Source License v1.0",
48298         true,
48299         false
48300     ],
48301     "RSA-MD": [
48302         "RSA Message-Digest License",
48303         false,
48304         false
48305     ],
48306     "RSCPL": [
48307         "Ricoh Source Code Public License",
48308         true,
48309         false
48310     ],
48311     "Ruby": [
48312         "Ruby License",
48313         false,
48314         false
48315     ],
48316     "SAX-PD": [
48317         "Sax Public Domain Notice",
48318         false,
48319         false
48320     ],
48321     "Saxpath": [
48322         "Saxpath License",
48323         false,
48324         false
48325     ],
48326     "SCEA": [
48327         "SCEA Shared Source License",
48328         false,
48329         false
48330     ],
48331     "Sendmail": [
48332         "Sendmail License",
48333         false,
48334         false
48335     ],
48336     "SGI-B-1.0": [
48337         "SGI Free Software License B v1.0",
48338         false,
48339         false
48340     ],
48341     "SGI-B-1.1": [
48342         "SGI Free Software License B v1.1",
48343         false,
48344         false
48345     ],
48346     "SGI-B-2.0": [
48347         "SGI Free Software License B v2.0",
48348         false,
48349         false
48350     ],
48351     "SimPL-2.0": [
48352         "Simple Public License 2.0",
48353         true,
48354         false
48355     ],
48356     "SISSL": [
48357         "Sun Industry Standards Source License v1.1",
48358         true,
48359         false
48360     ],
48361     "SISSL-1.2": [
48362         "Sun Industry Standards Source License v1.2",
48363         false,
48364         false
48365     ],
48366     "Sleepycat": [
48367         "Sleepycat License",
48368         true,
48369         false
48370     ],
48371     "SMLNJ": [
48372         "Standard ML of New Jersey License",
48373         false,
48374         false
48375     ],
48376     "SMPPL": [
48377         "Secure Messaging Protocol Public License",
48378         false,
48379         false
48380     ],
48381     "SNIA": [
48382         "SNIA Public License 1.1",
48383         false,
48384         false
48385     ],
48386     "Spencer-86": [
48387         "Spencer License 86",
48388         false,
48389         false
48390     ],
48391     "Spencer-94": [
48392         "Spencer License 94",
48393         false,
48394         false
48395     ],
48396     "Spencer-99": [
48397         "Spencer License 99",
48398         false,
48399         false
48400     ],
48401     "SPL-1.0": [
48402         "Sun Public License v1.0",
48403         true,
48404         false
48405     ],
48406     "StandardML-NJ": [
48407         "Standard ML of New Jersey License",
48408         false,
48409         true
48410     ],
48411     "SugarCRM-1.1.3": [
48412         "SugarCRM Public License v1.1.3",
48413         false,
48414         false
48415     ],
48416     "SWL": [
48417         "Scheme Widget Library (SWL) Software License Agreement",
48418         false,
48419         false
48420     ],
48421     "TCL": [
48422         "TCL/TK License",
48423         false,
48424         false
48425     ],
48426     "TCP-wrappers": [
48427         "TCP Wrappers License",
48428         false,
48429         false
48430     ],
48431     "TMate": [
48432         "TMate Open Source License",
48433         false,
48434         false
48435     ],
48436     "TORQUE-1.1": [
48437         "TORQUE v2.5+ Software License v1.1",
48438         false,
48439         false
48440     ],
48441     "TOSL": [
48442         "Trusster Open Source License",
48443         false,
48444         false
48445     ],
48446     "Unicode-DFS-2015": [
48447         "Unicode License Agreement - Data Files and Software (2015)",
48448         false,
48449         false
48450     ],
48451     "Unicode-DFS-2016": [
48452         "Unicode License Agreement - Data Files and Software (2016)",
48453         false,
48454         false
48455     ],
48456     "Unicode-TOU": [
48457         "Unicode Terms of Use",
48458         false,
48459         false
48460     ],
48461     "Unlicense": [
48462         "The Unlicense",
48463         false,
48464         false
48465     ],
48466     "UPL-1.0": [
48467         "Universal Permissive License v1.0",
48468         true,
48469         false
48470     ],
48471     "Vim": [
48472         "Vim License",
48473         false,
48474         false
48475     ],
48476     "VOSTROM": [
48477         "VOSTROM Public License for Open Source",
48478         false,
48479         false
48480     ],
48481     "VSL-1.0": [
48482         "Vovida Software License v1.0",
48483         true,
48484         false
48485     ],
48486     "W3C": [
48487         "W3C Software Notice and License (2002-12-31)",
48488         true,
48489         false
48490     ],
48491     "W3C-19980720": [
48492         "W3C Software Notice and License (1998-07-20)",
48493         false,
48494         false
48495     ],
48496     "W3C-20150513": [
48497         "W3C Software Notice and Document License (2015-05-13)",
48498         false,
48499         false
48500     ],
48501     "Watcom-1.0": [
48502         "Sybase Open Watcom Public License 1.0",
48503         true,
48504         false
48505     ],
48506     "Wsuipa": [
48507         "Wsuipa License",
48508         false,
48509         false
48510     ],
48511     "WTFPL": [
48512         "Do What The F*ck You Want To Public License",
48513         false,
48514         false
48515     ],
48516     "wxWindows": [
48517         "wxWindows Library License",
48518         false,
48519         true
48520     ],
48521     "X11": [
48522         "X11 License",
48523         false,
48524         false
48525     ],
48526     "Xerox": [
48527         "Xerox License",
48528         false,
48529         false
48530     ],
48531     "XFree86-1.1": [
48532         "XFree86 License 1.1",
48533         false,
48534         false
48535     ],
48536     "xinetd": [
48537         "xinetd License",
48538         false,
48539         false
48540     ],
48541     "Xnet": [
48542         "X.Net License",
48543         true,
48544         false
48545     ],
48546     "xpp": [
48547         "XPP License",
48548         false,
48549         false
48550     ],
48551     "XSkat": [
48552         "XSkat License",
48553         false,
48554         false
48555     ],
48556     "YPL-1.0": [
48557         "Yahoo! Public License v1.0",
48558         false,
48559         false
48560     ],
48561     "YPL-1.1": [
48562         "Yahoo! Public License v1.1",
48563         false,
48564         false
48565     ],
48566     "Zed": [
48567         "Zed License",
48568         false,
48569         false
48570     ],
48571     "Zend-2.0": [
48572         "Zend License v2.0",
48573         false,
48574         false
48575     ],
48576     "Zimbra-1.3": [
48577         "Zimbra Public License v1.3",
48578         false,
48579         false
48580     ],
48581     "Zimbra-1.4": [
48582         "Zimbra Public License v1.4",
48583         false,
48584         false
48585     ],
48586     "Zlib": [
48587         "zlib License",
48588         true,
48589         false
48590     ],
48591     "zlib-acknowledgement": [
48592         "zlib/libpng License with Acknowledgement",
48593         false,
48594         false
48595     ],
48596     "ZPL-1.1": [
48597         "Zope Public License 1.1",
48598         false,
48599         false
48600     ],
48601     "ZPL-2.0": [
48602         "Zope Public License 2.0",
48603         true,
48604         false
48605     ],
48606     "ZPL-2.1": [
48607         "Zope Public License 2.1",
48608         false,
48609         false
48610     ]
48611 }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
48612 $\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
48613 \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
48614 \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
48615 \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
48616 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
48617 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
48618 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
48619   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">\r
48620     <security>\r
48621       <requestedPrivileges>\r
48622         <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>\r
48623       </requestedPrivileges>\r
48624     </security>\r
48625   </trustInfo>\r
48626   <dependency>\r
48627     <dependentAssembly>\r
48628       <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>\r
48629     </dependentAssembly>\r
48630   </dependency>\r
48631 </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
48632
48633
48634
48635
48636
48637
48638
48639
48640
48641
48642 namespace Symfony\Component\Console;
48643
48644 use Symfony\Component\Console\Descriptor\TextDescriptor;
48645 use Symfony\Component\Console\Descriptor\XmlDescriptor;
48646 use Symfony\Component\Console\Exception\ExceptionInterface;
48647 use Symfony\Component\Console\Formatter\OutputFormatter;
48648 use Symfony\Component\Console\Helper\DebugFormatterHelper;
48649 use Symfony\Component\Console\Helper\Helper;
48650 use Symfony\Component\Console\Helper\ProcessHelper;
48651 use Symfony\Component\Console\Helper\QuestionHelper;
48652 use Symfony\Component\Console\Input\InputInterface;
48653 use Symfony\Component\Console\Input\ArgvInput;
48654 use Symfony\Component\Console\Input\ArrayInput;
48655 use Symfony\Component\Console\Input\InputDefinition;
48656 use Symfony\Component\Console\Input\InputOption;
48657 use Symfony\Component\Console\Input\InputArgument;
48658 use Symfony\Component\Console\Input\InputAwareInterface;
48659 use Symfony\Component\Console\Output\BufferedOutput;
48660 use Symfony\Component\Console\Output\OutputInterface;
48661 use Symfony\Component\Console\Output\ConsoleOutput;
48662 use Symfony\Component\Console\Output\ConsoleOutputInterface;
48663 use Symfony\Component\Console\Command\Command;
48664 use Symfony\Component\Console\Command\HelpCommand;
48665 use Symfony\Component\Console\Command\ListCommand;
48666 use Symfony\Component\Console\Helper\HelperSet;
48667 use Symfony\Component\Console\Helper\FormatterHelper;
48668 use Symfony\Component\Console\Helper\DialogHelper;
48669 use Symfony\Component\Console\Helper\ProgressHelper;
48670 use Symfony\Component\Console\Helper\TableHelper;
48671 use Symfony\Component\Console\Event\ConsoleCommandEvent;
48672 use Symfony\Component\Console\Event\ConsoleExceptionEvent;
48673 use Symfony\Component\Console\Event\ConsoleTerminateEvent;
48674 use Symfony\Component\Console\Exception\CommandNotFoundException;
48675 use Symfony\Component\Console\Exception\LogicException;
48676 use Symfony\Component\Debug\Exception\FatalThrowableError;
48677 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
48678
48679
48680
48681
48682
48683
48684
48685
48686
48687
48688
48689
48690
48691
48692
48693
48694 class Application
48695 {
48696 private $commands = array();
48697 private $wantHelps = false;
48698 private $runningCommand;
48699 private $name;
48700 private $version;
48701 private $catchExceptions = true;
48702 private $autoExit = true;
48703 private $definition;
48704 private $helperSet;
48705 private $dispatcher;
48706 private $terminalDimensions;
48707 private $defaultCommand;
48708 private $initialized;
48709
48710
48711
48712
48713
48714 public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
48715 {
48716 $this->name = $name;
48717 $this->version = $version;
48718 $this->defaultCommand = 'list';
48719 }
48720
48721 public function setDispatcher(EventDispatcherInterface $dispatcher)
48722 {
48723 $this->dispatcher = $dispatcher;
48724 }
48725
48726
48727
48728
48729
48730
48731
48732
48733 public function run(InputInterface $input = null, OutputInterface $output = null)
48734 {
48735 if (null === $input) {
48736 $input = new ArgvInput();
48737 }
48738
48739 if (null === $output) {
48740 $output = new ConsoleOutput();
48741 }
48742
48743 $this->configureIO($input, $output);
48744
48745 try {
48746 $e = null;
48747 $exitCode = $this->doRun($input, $output);
48748 } catch (\Exception $e) {
48749 }
48750
48751 if (null !== $e) {
48752 if (!$this->catchExceptions) {
48753 throw $e;
48754 }
48755
48756 if ($output instanceof ConsoleOutputInterface) {
48757 $this->renderException($e, $output->getErrorOutput());
48758 } else {
48759 $this->renderException($e, $output);
48760 }
48761
48762 $exitCode = $e->getCode();
48763 if (is_numeric($exitCode)) {
48764 $exitCode = (int) $exitCode;
48765 if (0 === $exitCode) {
48766 $exitCode = 1;
48767 }
48768 } else {
48769 $exitCode = 1;
48770 }
48771 }
48772
48773 if ($this->autoExit) {
48774 if ($exitCode > 255) {
48775 $exitCode = 255;
48776 }
48777
48778 exit($exitCode);
48779 }
48780
48781 return $exitCode;
48782 }
48783
48784
48785
48786
48787
48788
48789 public function doRun(InputInterface $input, OutputInterface $output)
48790 {
48791 if (true === $input->hasParameterOption(array('--version', '-V'))) {
48792 $output->writeln($this->getLongVersion());
48793
48794 return 0;
48795 }
48796
48797 $name = $this->getCommandName($input);
48798 if (true === $input->hasParameterOption(array('--help', '-h'))) {
48799 if (!$name) {
48800 $name = 'help';
48801 $input = new ArrayInput(array('command' => 'help'));
48802 } else {
48803 $this->wantHelps = true;
48804 }
48805 }
48806
48807 if (!$name) {
48808 $name = $this->defaultCommand;
48809 $definition = $this->getDefinition();
48810 $definition->setArguments(array_merge(
48811 $definition->getArguments(),
48812 array(
48813 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
48814 )
48815 ));
48816 }
48817
48818 $this->runningCommand = null;
48819
48820  $command = $this->find($name);
48821
48822 $this->runningCommand = $command;
48823 $exitCode = $this->doRunCommand($command, $input, $output);
48824 $this->runningCommand = null;
48825
48826 return $exitCode;
48827 }
48828
48829 public function setHelperSet(HelperSet $helperSet)
48830 {
48831 $this->helperSet = $helperSet;
48832 }
48833
48834
48835
48836
48837
48838
48839 public function getHelperSet()
48840 {
48841 if (!$this->helperSet) {
48842 $this->helperSet = $this->getDefaultHelperSet();
48843 }
48844
48845 return $this->helperSet;
48846 }
48847
48848 public function setDefinition(InputDefinition $definition)
48849 {
48850 $this->definition = $definition;
48851 }
48852
48853
48854
48855
48856
48857
48858 public function getDefinition()
48859 {
48860 if (!$this->definition) {
48861 $this->definition = $this->getDefaultInputDefinition();
48862 }
48863
48864 return $this->definition;
48865 }
48866
48867
48868
48869
48870
48871
48872 public function getHelp()
48873 {
48874 return $this->getLongVersion();
48875 }
48876
48877
48878
48879
48880
48881
48882 public function setCatchExceptions($boolean)
48883 {
48884 $this->catchExceptions = (bool) $boolean;
48885 }
48886
48887
48888
48889
48890
48891
48892 public function setAutoExit($boolean)
48893 {
48894 $this->autoExit = (bool) $boolean;
48895 }
48896
48897
48898
48899
48900
48901
48902 public function getName()
48903 {
48904 return $this->name;
48905 }
48906
48907
48908
48909
48910
48911
48912 public function setName($name)
48913 {
48914 $this->name = $name;
48915 }
48916
48917
48918
48919
48920
48921
48922 public function getVersion()
48923 {
48924 return $this->version;
48925 }
48926
48927
48928
48929
48930
48931
48932 public function setVersion($version)
48933 {
48934 $this->version = $version;
48935 }
48936
48937
48938
48939
48940
48941
48942 public function getLongVersion()
48943 {
48944 if ('UNKNOWN' !== $this->getName()) {
48945 if ('UNKNOWN' !== $this->getVersion()) {
48946 return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
48947 }
48948
48949 return sprintf('<info>%s</info>', $this->getName());
48950 }
48951
48952 return '<info>Console Tool</info>';
48953 }
48954
48955
48956
48957
48958
48959
48960
48961
48962 public function register($name)
48963 {
48964 return $this->add(new Command($name));
48965 }
48966
48967
48968
48969
48970
48971
48972
48973
48974 public function addCommands(array $commands)
48975 {
48976 foreach ($commands as $command) {
48977 $this->add($command);
48978 }
48979 }
48980
48981
48982
48983
48984
48985
48986
48987
48988
48989 public function add(Command $command)
48990 {
48991 $this->init();
48992
48993 $command->setApplication($this);
48994
48995 if (!$command->isEnabled()) {
48996 $command->setApplication(null);
48997
48998 return;
48999 }
49000
49001 if (null === $command->getDefinition()) {
49002 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
49003 }
49004
49005 $this->commands[$command->getName()] = $command;
49006
49007 foreach ($command->getAliases() as $alias) {
49008 $this->commands[$alias] = $command;
49009 }
49010
49011 return $command;
49012 }
49013
49014
49015
49016
49017
49018
49019
49020
49021
49022
49023 public function get($name)
49024 {
49025 $this->init();
49026
49027 if (!isset($this->commands[$name])) {
49028 throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
49029 }
49030
49031 $command = $this->commands[$name];
49032
49033 if ($this->wantHelps) {
49034 $this->wantHelps = false;
49035
49036 $helpCommand = $this->get('help');
49037 $helpCommand->setCommand($command);
49038
49039 return $helpCommand;
49040 }
49041
49042 return $command;
49043 }
49044
49045
49046
49047
49048
49049
49050
49051
49052 public function has($name)
49053 {
49054 $this->init();
49055
49056 return isset($this->commands[$name]);
49057 }
49058
49059
49060
49061
49062
49063
49064
49065
49066 public function getNamespaces()
49067 {
49068 $namespaces = array();
49069 foreach ($this->all() as $command) {
49070 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
49071
49072 foreach ($command->getAliases() as $alias) {
49073 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
49074 }
49075 }
49076
49077 return array_values(array_unique(array_filter($namespaces)));
49078 }
49079
49080
49081
49082
49083
49084
49085
49086
49087
49088
49089 public function findNamespace($namespace)
49090 {
49091 $allNamespaces = $this->getNamespaces();
49092 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
49093 $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
49094
49095 if (empty($namespaces)) {
49096 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
49097
49098 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
49099 if (1 == count($alternatives)) {
49100 $message .= "\n\nDid you mean this?\n    ";
49101 } else {
49102 $message .= "\n\nDid you mean one of these?\n    ";
49103 }
49104
49105 $message .= implode("\n    ", $alternatives);
49106 }
49107
49108 throw new CommandNotFoundException($message, $alternatives);
49109 }
49110
49111 $exact = in_array($namespace, $namespaces, true);
49112 if (count($namespaces) > 1 && !$exact) {
49113 throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
49114 }
49115
49116 return $exact ? $namespace : reset($namespaces);
49117 }
49118
49119
49120
49121
49122
49123
49124
49125
49126
49127
49128
49129
49130
49131 public function find($name)
49132 {
49133 $this->init();
49134 $aliases = array();
49135 $allCommands = array_keys($this->commands);
49136 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
49137 $commands = preg_grep('{^'.$expr.'}', $allCommands);
49138
49139 if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
49140 if (false !== $pos = strrpos($name, ':')) {
49141
49142  $this->findNamespace(substr($name, 0, $pos));
49143 }
49144
49145 $message = sprintf('Command "%s" is not defined.', $name);
49146
49147 if ($alternatives = $this->findAlternatives($name, $allCommands)) {
49148 if (1 == count($alternatives)) {
49149 $message .= "\n\nDid you mean this?\n    ";
49150 } else {
49151 $message .= "\n\nDid you mean one of these?\n    ";
49152 }
49153 $message .= implode("\n    ", $alternatives);
49154 }
49155
49156 throw new CommandNotFoundException($message, $alternatives);
49157 }
49158
49159
49160  if (count($commands) > 1) {
49161 $commandList = $this->commands;
49162 $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) {
49163 $commandName = $commandList[$nameOrAlias]->getName();
49164 $aliases[$nameOrAlias] = $commandName;
49165
49166 return $commandName === $nameOrAlias || !in_array($commandName, $commands);
49167 });
49168 }
49169
49170 $exact = in_array($name, $commands, true) || isset($aliases[$name]);
49171 if (!$exact && count($commands) > 1) {
49172 $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
49173
49174 throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
49175 }
49176
49177 return $this->get($exact ? $name : reset($commands));
49178 }
49179
49180
49181
49182
49183
49184
49185
49186
49187
49188
49189 public function all($namespace = null)
49190 {
49191 $this->init();
49192
49193 if (null === $namespace) {
49194 return $this->commands;
49195 }
49196
49197 $commands = array();
49198 foreach ($this->commands as $name => $command) {
49199 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
49200 $commands[$name] = $command;
49201 }
49202 }
49203
49204 return $commands;
49205 }
49206
49207
49208
49209
49210
49211
49212
49213
49214 public static function getAbbreviations($names)
49215 {
49216 $abbrevs = array();
49217 foreach ($names as $name) {
49218 for ($len = strlen($name); $len > 0; --$len) {
49219 $abbrev = substr($name, 0, $len);
49220 $abbrevs[$abbrev][] = $name;
49221 }
49222 }
49223
49224 return $abbrevs;
49225 }
49226
49227
49228
49229
49230
49231
49232
49233
49234
49235
49236
49237 public function asText($namespace = null, $raw = false)
49238 {
49239 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
49240
49241 $descriptor = new TextDescriptor();
49242 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
49243 $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
49244
49245 return $output->fetch();
49246 }
49247
49248
49249
49250
49251
49252
49253
49254
49255
49256
49257
49258 public function asXml($namespace = null, $asDom = false)
49259 {
49260 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
49261
49262 $descriptor = new XmlDescriptor();
49263
49264 if ($asDom) {
49265 return $descriptor->getApplicationDocument($this, $namespace);
49266 }
49267
49268 $output = new BufferedOutput();
49269 $descriptor->describe($output, $this, array('namespace' => $namespace));
49270
49271 return $output->fetch();
49272 }
49273
49274
49275
49276
49277 public function renderException($e, $output)
49278 {
49279 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
49280
49281 do {
49282 $title = sprintf('  [%s]  ', get_class($e));
49283
49284 $len = Helper::strlen($title);
49285
49286 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
49287
49288  if (defined('HHVM_VERSION') && $width > 1 << 31) {
49289 $width = 1 << 31;
49290 }
49291 $lines = array();
49292 foreach (preg_split('/\r?\n/', trim($e->getMessage())) as $line) {
49293 foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
49294
49295  $lineLength = Helper::strlen($line) + 4;
49296 $lines[] = array($line, $lineLength);
49297
49298 $len = max($lineLength, $len);
49299 }
49300 }
49301
49302 $messages = array();
49303 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
49304 $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
49305 foreach ($lines as $line) {
49306 $messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
49307 }
49308 $messages[] = $emptyLine;
49309 $messages[] = '';
49310
49311 $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
49312
49313 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
49314 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
49315
49316
49317  $trace = $e->getTrace();
49318 array_unshift($trace, array(
49319 'function' => '',
49320 'file' => null !== $e->getFile() ? $e->getFile() : 'n/a',
49321 'line' => null !== $e->getLine() ? $e->getLine() : 'n/a',
49322 'args' => array(),
49323 ));
49324
49325 for ($i = 0, $count = count($trace); $i < $count; ++$i) {
49326 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
49327 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
49328 $function = $trace[$i]['function'];
49329 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
49330 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
49331
49332 $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
49333 }
49334
49335 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
49336 }
49337 } while ($e = $e->getPrevious());
49338
49339 if (null !== $this->runningCommand) {
49340 $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
49341 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
49342 }
49343 }
49344
49345
49346
49347
49348
49349
49350 protected function getTerminalWidth()
49351 {
49352 $dimensions = $this->getTerminalDimensions();
49353
49354 return $dimensions[0];
49355 }
49356
49357
49358
49359
49360
49361
49362 protected function getTerminalHeight()
49363 {
49364 $dimensions = $this->getTerminalDimensions();
49365
49366 return $dimensions[1];
49367 }
49368
49369
49370
49371
49372
49373
49374 public function getTerminalDimensions()
49375 {
49376 if ($this->terminalDimensions) {
49377 return $this->terminalDimensions;
49378 }
49379
49380 if ('\\' === DIRECTORY_SEPARATOR) {
49381
49382  if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
49383 return array((int) $matches[1], (int) $matches[2]);
49384 }
49385
49386  if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
49387 return array((int) $matches[1], (int) $matches[2]);
49388 }
49389 }
49390
49391 if ($sttyString = $this->getSttyColumns()) {
49392
49393  if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
49394 return array((int) $matches[2], (int) $matches[1]);
49395 }
49396
49397  if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
49398 return array((int) $matches[2], (int) $matches[1]);
49399 }
49400 }
49401
49402 return array(null, null);
49403 }
49404
49405
49406
49407
49408
49409
49410
49411
49412
49413
49414
49415 public function setTerminalDimensions($width, $height)
49416 {
49417 $this->terminalDimensions = array($width, $height);
49418
49419 return $this;
49420 }
49421
49422
49423
49424
49425 protected function configureIO(InputInterface $input, OutputInterface $output)
49426 {
49427 if (true === $input->hasParameterOption(array('--ansi'))) {
49428 $output->setDecorated(true);
49429 } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
49430 $output->setDecorated(false);
49431 }
49432
49433 if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
49434 $input->setInteractive(false);
49435 } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
49436 $inputStream = $this->getHelperSet()->get('question')->getInputStream();
49437 if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
49438 $input->setInteractive(false);
49439 }
49440 }
49441
49442 if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
49443 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
49444 $input->setInteractive(false);
49445 } else {
49446 if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || 3 === $input->getParameterOption('--verbose')) {
49447 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
49448 } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || 2 === $input->getParameterOption('--verbose')) {
49449 $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
49450 } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
49451 $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
49452 }
49453 }
49454 }
49455
49456
49457
49458
49459
49460
49461
49462
49463
49464 protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
49465 {
49466 foreach ($command->getHelperSet() as $helper) {
49467 if ($helper instanceof InputAwareInterface) {
49468 $helper->setInput($input);
49469 }
49470 }
49471
49472 if (null === $this->dispatcher) {
49473 return $command->run($input, $output);
49474 }
49475
49476
49477  try {
49478 $command->mergeApplicationDefinition();
49479 $input->bind($command->getDefinition());
49480 } catch (ExceptionInterface $e) {
49481
49482  }
49483
49484 $event = new ConsoleCommandEvent($command, $input, $output);
49485 $e = null;
49486
49487 try {
49488 $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
49489
49490 if ($event->commandShouldRun()) {
49491 $exitCode = $command->run($input, $output);
49492 } else {
49493 $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
49494 }
49495 } catch (\Exception $e) {
49496 } catch (\Throwable $e) {
49497 }
49498 if (null !== $e) {
49499 $x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
49500 $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
49501 $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
49502
49503 if ($x !== $event->getException()) {
49504 $e = $event->getException();
49505 }
49506 $exitCode = $e->getCode();
49507 }
49508
49509 $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
49510 $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
49511
49512 if (null !== $e) {
49513 throw $e;
49514 }
49515
49516 return $event->getExitCode();
49517 }
49518
49519
49520
49521
49522
49523
49524 protected function getCommandName(InputInterface $input)
49525 {
49526 return $input->getFirstArgument();
49527 }
49528
49529
49530
49531
49532
49533
49534 protected function getDefaultInputDefinition()
49535 {
49536 return new InputDefinition(array(
49537 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
49538
49539 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
49540 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
49541 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'),
49542 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
49543 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
49544 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
49545 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
49546 ));
49547 }
49548
49549
49550
49551
49552
49553
49554 protected function getDefaultCommands()
49555 {
49556 return array(new HelpCommand(), new ListCommand());
49557 }
49558
49559
49560
49561
49562
49563
49564 protected function getDefaultHelperSet()
49565 {
49566 return new HelperSet(array(
49567 new FormatterHelper(),
49568 new DialogHelper(false),
49569 new ProgressHelper(false),
49570 new TableHelper(false),
49571 new DebugFormatterHelper(),
49572 new ProcessHelper(),
49573 new QuestionHelper(),
49574 ));
49575 }
49576
49577
49578
49579
49580
49581
49582 private function getSttyColumns()
49583 {
49584 if (!function_exists('proc_open')) {
49585 return;
49586 }
49587
49588 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
49589 $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
49590 if (is_resource($process)) {
49591 $info = stream_get_contents($pipes[1]);
49592 fclose($pipes[1]);
49593 fclose($pipes[2]);
49594 proc_close($process);
49595
49596 return $info;
49597 }
49598 }
49599
49600
49601
49602
49603
49604
49605 private function getConsoleMode()
49606 {
49607 if (!function_exists('proc_open')) {
49608 return;
49609 }
49610
49611 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
49612 $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
49613 if (is_resource($process)) {
49614 $info = stream_get_contents($pipes[1]);
49615 fclose($pipes[1]);
49616 fclose($pipes[2]);
49617 proc_close($process);
49618
49619 if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
49620 return $matches[2].'x'.$matches[1];
49621 }
49622 }
49623 }
49624
49625
49626
49627
49628
49629
49630
49631
49632 private function getAbbreviationSuggestions($abbrevs)
49633 {
49634 return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
49635 }
49636
49637
49638
49639
49640
49641
49642
49643
49644
49645
49646
49647 public function extractNamespace($name, $limit = null)
49648 {
49649 $parts = explode(':', $name);
49650 array_pop($parts);
49651
49652 return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
49653 }
49654
49655
49656
49657
49658
49659
49660
49661
49662
49663
49664 private function findAlternatives($name, $collection)
49665 {
49666 $threshold = 1e3;
49667 $alternatives = array();
49668
49669 $collectionParts = array();
49670 foreach ($collection as $item) {
49671 $collectionParts[$item] = explode(':', $item);
49672 }
49673
49674 foreach (explode(':', $name) as $i => $subname) {
49675 foreach ($collectionParts as $collectionName => $parts) {
49676 $exists = isset($alternatives[$collectionName]);
49677 if (!isset($parts[$i]) && $exists) {
49678 $alternatives[$collectionName] += $threshold;
49679 continue;
49680 } elseif (!isset($parts[$i])) {
49681 continue;
49682 }
49683
49684 $lev = levenshtein($subname, $parts[$i]);
49685 if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
49686 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
49687 } elseif ($exists) {
49688 $alternatives[$collectionName] += $threshold;
49689 }
49690 }
49691 }
49692
49693 foreach ($collection as $item) {
49694 $lev = levenshtein($name, $item);
49695 if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
49696 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
49697 }
49698 }
49699
49700 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
49701 asort($alternatives);
49702
49703 return array_keys($alternatives);
49704 }
49705
49706
49707
49708
49709
49710
49711 public function setDefaultCommand($commandName)
49712 {
49713 $this->defaultCommand = $commandName;
49714 }
49715
49716 private function splitStringByWidth($string, $width)
49717 {
49718
49719  
49720  
49721  if (false === $encoding = mb_detect_encoding($string, null, true)) {
49722 return str_split($string, $width);
49723 }
49724
49725 $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
49726 $lines = array();
49727 $line = '';
49728 foreach (preg_split('//u', $utf8String) as $char) {
49729
49730  if (mb_strwidth($line.$char, 'utf8') <= $width) {
49731 $line .= $char;
49732 continue;
49733 }
49734
49735  $lines[] = str_pad($line, $width);
49736 $line = $char;
49737 }
49738
49739 $lines[] = count($lines) ? str_pad($line, $width) : $line;
49740
49741 mb_convert_variables($encoding, 'utf8', $lines);
49742
49743 return $lines;
49744 }
49745
49746
49747
49748
49749
49750
49751
49752
49753 private function extractAllNamespaces($name)
49754 {
49755
49756  $parts = explode(':', $name, -1);
49757 $namespaces = array();
49758
49759 foreach ($parts as $part) {
49760 if (count($namespaces)) {
49761 $namespaces[] = end($namespaces).':'.$part;
49762 } else {
49763 $namespaces[] = $part;
49764 }
49765 }
49766
49767 return $namespaces;
49768 }
49769
49770 private function init()
49771 {
49772 if ($this->initialized) {
49773 return;
49774 }
49775 $this->initialized = true;
49776
49777 foreach ($this->getDefaultCommands() as $command) {
49778 $this->add($command);
49779 }
49780 }
49781 }
49782 <?php
49783
49784
49785
49786
49787
49788
49789
49790
49791
49792
49793 namespace Symfony\Component\Console\Command;
49794
49795 use Symfony\Component\Console\Descriptor\TextDescriptor;
49796 use Symfony\Component\Console\Descriptor\XmlDescriptor;
49797 use Symfony\Component\Console\Exception\ExceptionInterface;
49798 use Symfony\Component\Console\Input\InputDefinition;
49799 use Symfony\Component\Console\Input\InputOption;
49800 use Symfony\Component\Console\Input\InputArgument;
49801 use Symfony\Component\Console\Input\InputInterface;
49802 use Symfony\Component\Console\Output\BufferedOutput;
49803 use Symfony\Component\Console\Output\OutputInterface;
49804 use Symfony\Component\Console\Application;
49805 use Symfony\Component\Console\Helper\HelperSet;
49806 use Symfony\Component\Console\Exception\InvalidArgumentException;
49807 use Symfony\Component\Console\Exception\LogicException;
49808
49809
49810
49811
49812
49813
49814 class Command
49815 {
49816 private $application;
49817 private $name;
49818 private $processTitle;
49819 private $aliases = array();
49820 private $definition;
49821 private $help;
49822 private $description;
49823 private $ignoreValidationErrors = false;
49824 private $applicationDefinitionMerged = false;
49825 private $applicationDefinitionMergedWithArgs = false;
49826 private $code;
49827 private $synopsis = array();
49828 private $usages = array();
49829 private $helperSet;
49830
49831
49832
49833
49834
49835
49836 public function __construct($name = null)
49837 {
49838 $this->definition = new InputDefinition();
49839
49840 if (null !== $name) {
49841 $this->setName($name);
49842 }
49843
49844 $this->configure();
49845
49846 if (!$this->name) {
49847 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
49848 }
49849 }
49850
49851
49852
49853
49854
49855
49856 public function ignoreValidationErrors()
49857 {
49858 $this->ignoreValidationErrors = true;
49859 }
49860
49861 public function setApplication(Application $application = null)
49862 {
49863 $this->application = $application;
49864 if ($application) {
49865 $this->setHelperSet($application->getHelperSet());
49866 } else {
49867 $this->helperSet = null;
49868 }
49869 }
49870
49871 public function setHelperSet(HelperSet $helperSet)
49872 {
49873 $this->helperSet = $helperSet;
49874 }
49875
49876
49877
49878
49879
49880
49881 public function getHelperSet()
49882 {
49883 return $this->helperSet;
49884 }
49885
49886
49887
49888
49889
49890
49891 public function getApplication()
49892 {
49893 return $this->application;
49894 }
49895
49896
49897
49898
49899
49900
49901
49902
49903
49904 public function isEnabled()
49905 {
49906 return true;
49907 }
49908
49909
49910
49911
49912 protected function configure()
49913 {
49914 }
49915
49916
49917
49918
49919
49920
49921
49922
49923
49924
49925
49926
49927
49928
49929
49930 protected function execute(InputInterface $input, OutputInterface $output)
49931 {
49932 throw new LogicException('You must override the execute() method in the concrete command class.');
49933 }
49934
49935
49936
49937
49938
49939
49940
49941
49942 protected function interact(InputInterface $input, OutputInterface $output)
49943 {
49944 }
49945
49946
49947
49948
49949
49950
49951
49952 protected function initialize(InputInterface $input, OutputInterface $output)
49953 {
49954 }
49955
49956
49957
49958
49959
49960
49961
49962
49963
49964
49965
49966
49967
49968
49969
49970 public function run(InputInterface $input, OutputInterface $output)
49971 {
49972
49973  $this->getSynopsis(true);
49974 $this->getSynopsis(false);
49975
49976
49977  $this->mergeApplicationDefinition();
49978
49979
49980  try {
49981 $input->bind($this->definition);
49982 } catch (ExceptionInterface $e) {
49983 if (!$this->ignoreValidationErrors) {
49984 throw $e;
49985 }
49986 }
49987
49988 $this->initialize($input, $output);
49989
49990 if (null !== $this->processTitle) {
49991 if (function_exists('cli_set_process_title')) {
49992 if (!@cli_set_process_title($this->processTitle)) {
49993 if ('Darwin' === PHP_OS) {
49994 $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
49995 } else {
49996 cli_set_process_title($this->processTitle);
49997 }
49998 }
49999 } elseif (function_exists('setproctitle')) {
50000 setproctitle($this->processTitle);
50001 } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
50002 $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
50003 }
50004 }
50005
50006 if ($input->isInteractive()) {
50007 $this->interact($input, $output);
50008 }
50009
50010
50011  
50012  
50013  if ($input->hasArgument('command') && null === $input->getArgument('command')) {
50014 $input->setArgument('command', $this->getName());
50015 }
50016
50017 $input->validate();
50018
50019 if ($this->code) {
50020 $statusCode = call_user_func($this->code, $input, $output);
50021 } else {
50022 $statusCode = $this->execute($input, $output);
50023 }
50024
50025 return is_numeric($statusCode) ? (int) $statusCode : 0;
50026 }
50027
50028
50029
50030
50031
50032
50033
50034
50035
50036
50037
50038
50039
50040
50041
50042 public function setCode($code)
50043 {
50044 if (!is_callable($code)) {
50045 throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
50046 }
50047
50048 if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
50049 $r = new \ReflectionFunction($code);
50050 if (null === $r->getClosureThis()) {
50051 if (PHP_VERSION_ID < 70000) {
50052
50053  
50054  
50055  
50056  $code = @\Closure::bind($code, $this);
50057 } else {
50058 $code = \Closure::bind($code, $this);
50059 }
50060 }
50061 }
50062
50063 $this->code = $code;
50064
50065 return $this;
50066 }
50067
50068
50069
50070
50071
50072
50073
50074
50075 public function mergeApplicationDefinition($mergeArgs = true)
50076 {
50077 if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
50078 return;
50079 }
50080
50081 $this->definition->addOptions($this->application->getDefinition()->getOptions());
50082
50083 if ($mergeArgs) {
50084 $currentArguments = $this->definition->getArguments();
50085 $this->definition->setArguments($this->application->getDefinition()->getArguments());
50086 $this->definition->addArguments($currentArguments);
50087 }
50088
50089 $this->applicationDefinitionMerged = true;
50090 if ($mergeArgs) {
50091 $this->applicationDefinitionMergedWithArgs = true;
50092 }
50093 }
50094
50095
50096
50097
50098
50099
50100
50101
50102 public function setDefinition($definition)
50103 {
50104 if ($definition instanceof InputDefinition) {
50105 $this->definition = $definition;
50106 } else {
50107 $this->definition->setDefinition($definition);
50108 }
50109
50110 $this->applicationDefinitionMerged = false;
50111
50112 return $this;
50113 }
50114
50115
50116
50117
50118
50119
50120 public function getDefinition()
50121 {
50122 return $this->definition;
50123 }
50124
50125
50126
50127
50128
50129
50130
50131
50132
50133
50134
50135 public function getNativeDefinition()
50136 {
50137 return $this->getDefinition();
50138 }
50139
50140
50141
50142
50143
50144
50145
50146
50147
50148
50149
50150 public function addArgument($name, $mode = null, $description = '', $default = null)
50151 {
50152 $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
50153
50154 return $this;
50155 }
50156
50157
50158
50159
50160
50161
50162
50163
50164
50165
50166
50167
50168 public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
50169 {
50170 $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
50171
50172 return $this;
50173 }
50174
50175
50176
50177
50178
50179
50180
50181
50182
50183
50184
50185
50186
50187
50188
50189 public function setName($name)
50190 {
50191 $this->validateName($name);
50192
50193 $this->name = $name;
50194
50195 return $this;
50196 }
50197
50198
50199
50200
50201
50202
50203
50204
50205
50206
50207
50208
50209
50210 public function setProcessTitle($title)
50211 {
50212 $this->processTitle = $title;
50213
50214 return $this;
50215 }
50216
50217
50218
50219
50220
50221
50222 public function getName()
50223 {
50224 return $this->name;
50225 }
50226
50227
50228
50229
50230
50231
50232
50233
50234 public function setDescription($description)
50235 {
50236 $this->description = $description;
50237
50238 return $this;
50239 }
50240
50241
50242
50243
50244
50245
50246 public function getDescription()
50247 {
50248 return $this->description;
50249 }
50250
50251
50252
50253
50254
50255
50256
50257
50258 public function setHelp($help)
50259 {
50260 $this->help = $help;
50261
50262 return $this;
50263 }
50264
50265
50266
50267
50268
50269
50270 public function getHelp()
50271 {
50272 return $this->help;
50273 }
50274
50275
50276
50277
50278
50279
50280
50281 public function getProcessedHelp()
50282 {
50283 $name = $this->name;
50284
50285 $placeholders = array(
50286 '%command.name%',
50287 '%command.full_name%',
50288 );
50289 $replacements = array(
50290 $name,
50291 $_SERVER['PHP_SELF'].' '.$name,
50292 );
50293
50294 return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
50295 }
50296
50297
50298
50299
50300
50301
50302
50303
50304
50305
50306 public function setAliases($aliases)
50307 {
50308 if (!is_array($aliases) && !$aliases instanceof \Traversable) {
50309 throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
50310 }
50311
50312 foreach ($aliases as $alias) {
50313 $this->validateName($alias);
50314 }
50315
50316 $this->aliases = $aliases;
50317
50318 return $this;
50319 }
50320
50321
50322
50323
50324
50325
50326 public function getAliases()
50327 {
50328 return $this->aliases;
50329 }
50330
50331
50332
50333
50334
50335
50336
50337
50338 public function getSynopsis($short = false)
50339 {
50340 $key = $short ? 'short' : 'long';
50341
50342 if (!isset($this->synopsis[$key])) {
50343 $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
50344 }
50345
50346 return $this->synopsis[$key];
50347 }
50348
50349
50350
50351
50352
50353
50354
50355
50356 public function addUsage($usage)
50357 {
50358 if (0 !== strpos($usage, $this->name)) {
50359 $usage = sprintf('%s %s', $this->name, $usage);
50360 }
50361
50362 $this->usages[] = $usage;
50363
50364 return $this;
50365 }
50366
50367
50368
50369
50370
50371
50372 public function getUsages()
50373 {
50374 return $this->usages;
50375 }
50376
50377
50378
50379
50380
50381
50382
50383
50384
50385
50386
50387 public function getHelper($name)
50388 {
50389 if (null === $this->helperSet) {
50390 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));
50391 }
50392
50393 return $this->helperSet->get($name);
50394 }
50395
50396
50397
50398
50399
50400
50401
50402
50403 public function asText()
50404 {
50405 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
50406
50407 $descriptor = new TextDescriptor();
50408 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
50409 $descriptor->describe($output, $this, array('raw_output' => true));
50410
50411 return $output->fetch();
50412 }
50413
50414
50415
50416
50417
50418
50419
50420
50421
50422
50423 public function asXml($asDom = false)
50424 {
50425 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
50426
50427 $descriptor = new XmlDescriptor();
50428
50429 if ($asDom) {
50430 return $descriptor->getCommandDocument($this);
50431 }
50432
50433 $output = new BufferedOutput();
50434 $descriptor->describe($output, $this);
50435
50436 return $output->fetch();
50437 }
50438
50439
50440
50441
50442
50443
50444
50445
50446
50447
50448 private function validateName($name)
50449 {
50450 if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
50451 throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
50452 }
50453 }
50454 }
50455 <?php
50456
50457
50458
50459
50460
50461
50462
50463
50464
50465
50466 namespace Symfony\Component\Console\Command;
50467
50468 use Symfony\Component\Console\Helper\DescriptorHelper;
50469 use Symfony\Component\Console\Input\InputArgument;
50470 use Symfony\Component\Console\Input\InputOption;
50471 use Symfony\Component\Console\Input\InputInterface;
50472 use Symfony\Component\Console\Output\OutputInterface;
50473
50474
50475
50476
50477
50478
50479 class HelpCommand extends Command
50480 {
50481 private $command;
50482
50483
50484
50485
50486 protected function configure()
50487 {
50488 $this->ignoreValidationErrors();
50489
50490 $this
50491 ->setName('help')
50492 ->setDefinition(array(
50493 new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
50494 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
50495 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
50496 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
50497 ))
50498 ->setDescription('Displays help for a command')
50499 ->setHelp(<<<'EOF'
50500 The <info>%command.name%</info> command displays help for a given command:
50501
50502   <info>php %command.full_name% list</info>
50503
50504 You can also output the help in other formats by using the <comment>--format</comment> option:
50505
50506   <info>php %command.full_name% --format=xml list</info>
50507
50508 To display the list of available commands, please use the <info>list</info> command.
50509 EOF
50510 )
50511 ;
50512 }
50513
50514 public function setCommand(Command $command)
50515 {
50516 $this->command = $command;
50517 }
50518
50519
50520
50521
50522 protected function execute(InputInterface $input, OutputInterface $output)
50523 {
50524 if (null === $this->command) {
50525 $this->command = $this->getApplication()->find($input->getArgument('command_name'));
50526 }
50527
50528 if ($input->getOption('xml')) {
50529 @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);
50530
50531 $input->setOption('format', 'xml');
50532 }
50533
50534 $helper = new DescriptorHelper();
50535 $helper->describe($output, $this->command, array(
50536 'format' => $input->getOption('format'),
50537 'raw_text' => $input->getOption('raw'),
50538 ));
50539
50540 $this->command = null;
50541 }
50542 }
50543 <?php
50544
50545
50546
50547
50548
50549
50550
50551
50552
50553
50554 namespace Symfony\Component\Console\Command;
50555
50556 use Symfony\Component\Console\Helper\DescriptorHelper;
50557 use Symfony\Component\Console\Input\InputArgument;
50558 use Symfony\Component\Console\Input\InputOption;
50559 use Symfony\Component\Console\Input\InputInterface;
50560 use Symfony\Component\Console\Output\OutputInterface;
50561 use Symfony\Component\Console\Input\InputDefinition;
50562
50563
50564
50565
50566
50567
50568 class ListCommand extends Command
50569 {
50570
50571
50572
50573 protected function configure()
50574 {
50575 $this
50576 ->setName('list')
50577 ->setDefinition($this->createDefinition())
50578 ->setDescription('Lists commands')
50579 ->setHelp(<<<'EOF'
50580 The <info>%command.name%</info> command lists all commands:
50581
50582   <info>php %command.full_name%</info>
50583
50584 You can also display the commands for a specific namespace:
50585
50586   <info>php %command.full_name% test</info>
50587
50588 You can also output the information in other formats by using the <comment>--format</comment> option:
50589
50590   <info>php %command.full_name% --format=xml</info>
50591
50592 It's also possible to get raw list of commands (useful for embedding command runner):
50593
50594   <info>php %command.full_name% --raw</info>
50595 EOF
50596 )
50597 ;
50598 }
50599
50600
50601
50602
50603 public function getNativeDefinition()
50604 {
50605 return $this->createDefinition();
50606 }
50607
50608
50609
50610
50611 protected function execute(InputInterface $input, OutputInterface $output)
50612 {
50613 if ($input->getOption('xml')) {
50614 @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);
50615
50616 $input->setOption('format', 'xml');
50617 }
50618
50619 $helper = new DescriptorHelper();
50620 $helper->describe($output, $this->getApplication(), array(
50621 'format' => $input->getOption('format'),
50622 'raw_text' => $input->getOption('raw'),
50623 'namespace' => $input->getArgument('namespace'),
50624 ));
50625 }
50626
50627
50628
50629
50630 private function createDefinition()
50631 {
50632 return new InputDefinition(array(
50633 new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
50634 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
50635 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
50636 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
50637 ));
50638 }
50639 }
50640 <?php
50641
50642
50643
50644
50645
50646
50647
50648
50649
50650
50651 namespace Symfony\Component\Console;
50652
50653
50654
50655
50656
50657
50658 final class ConsoleEvents
50659 {
50660
50661
50662
50663
50664
50665
50666
50667
50668
50669
50670 const COMMAND = 'console.command';
50671
50672
50673
50674
50675
50676
50677
50678
50679
50680
50681 const TERMINATE = 'console.terminate';
50682
50683
50684
50685
50686
50687
50688
50689
50690
50691
50692
50693 const EXCEPTION = 'console.exception';
50694 }
50695 <?php
50696
50697
50698
50699
50700
50701
50702
50703
50704
50705
50706 namespace Symfony\Component\Console\Descriptor;
50707
50708 use Symfony\Component\Console\Application;
50709 use Symfony\Component\Console\Command\Command;
50710 use Symfony\Component\Console\Exception\CommandNotFoundException;
50711
50712
50713
50714
50715
50716
50717 class ApplicationDescription
50718 {
50719 const GLOBAL_NAMESPACE = '_global';
50720
50721 private $application;
50722 private $namespace;
50723
50724
50725
50726
50727 private $namespaces;
50728
50729
50730
50731
50732 private $commands;
50733
50734
50735
50736
50737 private $aliases;
50738
50739 public function __construct(Application $application, $namespace = null)
50740 {
50741 $this->application = $application;
50742 $this->namespace = $namespace;
50743 }
50744
50745
50746
50747
50748 public function getNamespaces()
50749 {
50750 if (null === $this->namespaces) {
50751 $this->inspectApplication();
50752 }
50753
50754 return $this->namespaces;
50755 }
50756
50757
50758
50759
50760 public function getCommands()
50761 {
50762 if (null === $this->commands) {
50763 $this->inspectApplication();
50764 }
50765
50766 return $this->commands;
50767 }
50768
50769
50770
50771
50772
50773
50774
50775
50776 public function getCommand($name)
50777 {
50778 if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
50779 throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
50780 }
50781
50782 return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
50783 }
50784
50785 private function inspectApplication()
50786 {
50787 $this->commands = array();
50788 $this->namespaces = array();
50789
50790 $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
50791 foreach ($this->sortCommands($all) as $namespace => $commands) {
50792 $names = array();
50793
50794
50795 foreach ($commands as $name => $command) {
50796 if (!$command->getName()) {
50797 continue;
50798 }
50799
50800 if ($command->getName() === $name) {
50801 $this->commands[$name] = $command;
50802 } else {
50803 $this->aliases[$name] = $command;
50804 }
50805
50806 $names[] = $name;
50807 }
50808
50809 $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
50810 }
50811 }
50812
50813
50814
50815
50816 private function sortCommands(array $commands)
50817 {
50818 $namespacedCommands = array();
50819 $globalCommands = array();
50820 foreach ($commands as $name => $command) {
50821 $key = $this->application->extractNamespace($name, 1);
50822 if (!$key) {
50823 $globalCommands['_global'][$name] = $command;
50824 } else {
50825 $namespacedCommands[$key][$name] = $command;
50826 }
50827 }
50828 ksort($namespacedCommands);
50829 $namespacedCommands = array_merge($globalCommands, $namespacedCommands);
50830
50831 foreach ($namespacedCommands as &$commandsSet) {
50832 ksort($commandsSet);
50833 }
50834
50835  unset($commandsSet);
50836
50837 return $namespacedCommands;
50838 }
50839 }
50840 <?php
50841
50842
50843
50844
50845
50846
50847
50848
50849
50850
50851 namespace Symfony\Component\Console\Descriptor;
50852
50853 use Symfony\Component\Console\Application;
50854 use Symfony\Component\Console\Command\Command;
50855 use Symfony\Component\Console\Input\InputArgument;
50856 use Symfony\Component\Console\Input\InputDefinition;
50857 use Symfony\Component\Console\Input\InputOption;
50858 use Symfony\Component\Console\Output\OutputInterface;
50859 use Symfony\Component\Console\Exception\InvalidArgumentException;
50860
50861
50862
50863
50864
50865
50866 abstract class Descriptor implements DescriptorInterface
50867 {
50868
50869
50870
50871 private $output;
50872
50873
50874
50875
50876 public function describe(OutputInterface $output, $object, array $options = array())
50877 {
50878 $this->output = $output;
50879
50880 switch (true) {
50881 case $object instanceof InputArgument:
50882 $this->describeInputArgument($object, $options);
50883 break;
50884 case $object instanceof InputOption:
50885 $this->describeInputOption($object, $options);
50886 break;
50887 case $object instanceof InputDefinition:
50888 $this->describeInputDefinition($object, $options);
50889 break;
50890 case $object instanceof Command:
50891 $this->describeCommand($object, $options);
50892 break;
50893 case $object instanceof Application:
50894 $this->describeApplication($object, $options);
50895 break;
50896 default:
50897 throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
50898 }
50899 }
50900
50901
50902
50903
50904
50905
50906
50907 protected function write($content, $decorated = false)
50908 {
50909 $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
50910 }
50911
50912
50913
50914
50915
50916
50917 abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
50918
50919
50920
50921
50922
50923
50924 abstract protected function describeInputOption(InputOption $option, array $options = array());
50925
50926
50927
50928
50929
50930
50931 abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
50932
50933
50934
50935
50936
50937
50938 abstract protected function describeCommand(Command $command, array $options = array());
50939
50940
50941
50942
50943
50944
50945 abstract protected function describeApplication(Application $application, array $options = array());
50946 }
50947 <?php
50948
50949
50950
50951
50952
50953
50954
50955
50956
50957
50958 namespace Symfony\Component\Console\Descriptor;
50959
50960 use Symfony\Component\Console\Output\OutputInterface;
50961
50962
50963
50964
50965
50966
50967 interface DescriptorInterface
50968 {
50969
50970
50971
50972
50973
50974
50975
50976 public function describe(OutputInterface $output, $object, array $options = array());
50977 }
50978 <?php
50979
50980
50981
50982
50983
50984
50985
50986
50987
50988
50989 namespace Symfony\Component\Console\Descriptor;
50990
50991 use Symfony\Component\Console\Application;
50992 use Symfony\Component\Console\Command\Command;
50993 use Symfony\Component\Console\Input\InputArgument;
50994 use Symfony\Component\Console\Input\InputDefinition;
50995 use Symfony\Component\Console\Input\InputOption;
50996
50997
50998
50999
51000
51001
51002
51003
51004 class JsonDescriptor extends Descriptor
51005 {
51006
51007
51008
51009 protected function describeInputArgument(InputArgument $argument, array $options = array())
51010 {
51011 $this->writeData($this->getInputArgumentData($argument), $options);
51012 }
51013
51014
51015
51016
51017 protected function describeInputOption(InputOption $option, array $options = array())
51018 {
51019 $this->writeData($this->getInputOptionData($option), $options);
51020 }
51021
51022
51023
51024
51025 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
51026 {
51027 $this->writeData($this->getInputDefinitionData($definition), $options);
51028 }
51029
51030
51031
51032
51033 protected function describeCommand(Command $command, array $options = array())
51034 {
51035 $this->writeData($this->getCommandData($command), $options);
51036 }
51037
51038
51039
51040
51041 protected function describeApplication(Application $application, array $options = array())
51042 {
51043 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
51044 $description = new ApplicationDescription($application, $describedNamespace);
51045 $commands = array();
51046
51047 foreach ($description->getCommands() as $command) {
51048 $commands[] = $this->getCommandData($command);
51049 }
51050
51051 $data = $describedNamespace
51052 ? array('commands' => $commands, 'namespace' => $describedNamespace)
51053 : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
51054
51055 $this->writeData($data, $options);
51056 }
51057
51058
51059
51060
51061
51062
51063 private function writeData(array $data, array $options)
51064 {
51065 $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
51066 }
51067
51068
51069
51070
51071 private function getInputArgumentData(InputArgument $argument)
51072 {
51073 return array(
51074 'name' => $argument->getName(),
51075 'is_required' => $argument->isRequired(),
51076 'is_array' => $argument->isArray(),
51077 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
51078 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
51079 );
51080 }
51081
51082
51083
51084
51085 private function getInputOptionData(InputOption $option)
51086 {
51087 return array(
51088 'name' => '--'.$option->getName(),
51089 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '',
51090 'accept_value' => $option->acceptValue(),
51091 'is_value_required' => $option->isValueRequired(),
51092 'is_multiple' => $option->isArray(),
51093 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
51094 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
51095 );
51096 }
51097
51098
51099
51100
51101 private function getInputDefinitionData(InputDefinition $definition)
51102 {
51103 $inputArguments = array();
51104 foreach ($definition->getArguments() as $name => $argument) {
51105 $inputArguments[$name] = $this->getInputArgumentData($argument);
51106 }
51107
51108 $inputOptions = array();
51109 foreach ($definition->getOptions() as $name => $option) {
51110 $inputOptions[$name] = $this->getInputOptionData($option);
51111 }
51112
51113 return array('arguments' => $inputArguments, 'options' => $inputOptions);
51114 }
51115
51116
51117
51118
51119 private function getCommandData(Command $command)
51120 {
51121 $command->getSynopsis();
51122 $command->mergeApplicationDefinition(false);
51123
51124 return array(
51125 'name' => $command->getName(),
51126 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
51127 'description' => $command->getDescription(),
51128 'help' => $command->getProcessedHelp(),
51129 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
51130 );
51131 }
51132 }
51133 <?php
51134
51135
51136
51137
51138
51139
51140
51141
51142
51143
51144 namespace Symfony\Component\Console\Descriptor;
51145
51146 use Symfony\Component\Console\Application;
51147 use Symfony\Component\Console\Command\Command;
51148 use Symfony\Component\Console\Helper\Helper;
51149 use Symfony\Component\Console\Input\InputArgument;
51150 use Symfony\Component\Console\Input\InputDefinition;
51151 use Symfony\Component\Console\Input\InputOption;
51152
51153
51154
51155
51156
51157
51158
51159
51160 class MarkdownDescriptor extends Descriptor
51161 {
51162
51163
51164
51165 protected function describeInputArgument(InputArgument $argument, array $options = array())
51166 {
51167 $this->write(
51168 '**'.$argument->getName().':**'."\n\n"
51169 .'* Name: '.($argument->getName() ?: '<none>')."\n"
51170 .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
51171 .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
51172 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $argument->getDescription() ?: '<none>')."\n"
51173 .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
51174 );
51175 }
51176
51177
51178
51179
51180 protected function describeInputOption(InputOption $option, array $options = array())
51181 {
51182 $this->write(
51183 '**'.$option->getName().':**'."\n\n"
51184 .'* Name: `--'.$option->getName().'`'."\n"
51185 .'* Shortcut: '.($option->getShortcut() ? '`-'.str_replace('|', '|-', $option->getShortcut()).'`' : '<none>')."\n"
51186 .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
51187 .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
51188 .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
51189 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $option->getDescription() ?: '<none>')."\n"
51190 .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
51191 );
51192 }
51193
51194
51195
51196
51197 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
51198 {
51199 if ($showArguments = count($definition->getArguments()) > 0) {
51200 $this->write('### Arguments:');
51201 foreach ($definition->getArguments() as $argument) {
51202 $this->write("\n\n");
51203 $this->write($this->describeInputArgument($argument));
51204 }
51205 }
51206
51207 if (count($definition->getOptions()) > 0) {
51208 if ($showArguments) {
51209 $this->write("\n\n");
51210 }
51211
51212 $this->write('### Options:');
51213 foreach ($definition->getOptions() as $option) {
51214 $this->write("\n\n");
51215 $this->write($this->describeInputOption($option));
51216 }
51217 }
51218 }
51219
51220
51221
51222
51223 protected function describeCommand(Command $command, array $options = array())
51224 {
51225 $command->getSynopsis();
51226 $command->mergeApplicationDefinition(false);
51227
51228 $this->write(
51229 $command->getName()."\n"
51230 .str_repeat('-', Helper::strlen($command->getName()))."\n\n"
51231 .'* Description: '.($command->getDescription() ?: '<none>')."\n"
51232 .'* Usage:'."\n\n"
51233 .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
51234 return $carry.'  * `'.$usage.'`'."\n";
51235 })
51236 );
51237
51238 if ($help = $command->getProcessedHelp()) {
51239 $this->write("\n");
51240 $this->write($help);
51241 }
51242
51243 if ($command->getNativeDefinition()) {
51244 $this->write("\n\n");
51245 $this->describeInputDefinition($command->getNativeDefinition());
51246 }
51247 }
51248
51249
51250
51251
51252 protected function describeApplication(Application $application, array $options = array())
51253 {
51254 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
51255 $description = new ApplicationDescription($application, $describedNamespace);
51256
51257 $this->write($application->getName()."\n".str_repeat('=', Helper::strlen($application->getName())));
51258
51259 foreach ($description->getNamespaces() as $namespace) {
51260 if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
51261 $this->write("\n\n");
51262 $this->write('**'.$namespace['id'].':**');
51263 }
51264
51265 $this->write("\n\n");
51266 $this->write(implode("\n", array_map(function ($commandName) {
51267 return '* '.$commandName;
51268 }, $namespace['commands'])));
51269 }
51270
51271 foreach ($description->getCommands() as $command) {
51272 $this->write("\n\n");
51273 $this->write($this->describeCommand($command));
51274 }
51275 }
51276 }
51277 <?php
51278
51279
51280
51281
51282
51283
51284
51285
51286
51287
51288 namespace Symfony\Component\Console\Descriptor;
51289
51290 use Symfony\Component\Console\Application;
51291 use Symfony\Component\Console\Command\Command;
51292 use Symfony\Component\Console\Formatter\OutputFormatter;
51293 use Symfony\Component\Console\Helper\Helper;
51294 use Symfony\Component\Console\Input\InputArgument;
51295 use Symfony\Component\Console\Input\InputDefinition;
51296 use Symfony\Component\Console\Input\InputOption;
51297
51298
51299
51300
51301
51302
51303
51304
51305 class TextDescriptor extends Descriptor
51306 {
51307
51308
51309
51310 protected function describeInputArgument(InputArgument $argument, array $options = array())
51311 {
51312 if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
51313 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
51314 } else {
51315 $default = '';
51316 }
51317
51318 $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
51319 $spacingWidth = $totalWidth - strlen($argument->getName());
51320
51321 $this->writeText(sprintf('  <info>%s</info>  %s%s%s',
51322 $argument->getName(),
51323 str_repeat(' ', $spacingWidth),
51324
51325  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
51326 $default
51327 ), $options);
51328 }
51329
51330
51331
51332
51333 protected function describeInputOption(InputOption $option, array $options = array())
51334 {
51335 if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
51336 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
51337 } else {
51338 $default = '';
51339 }
51340
51341 $value = '';
51342 if ($option->acceptValue()) {
51343 $value = '='.strtoupper($option->getName());
51344
51345 if ($option->isValueOptional()) {
51346 $value = '['.$value.']';
51347 }
51348 }
51349
51350 $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
51351 $synopsis = sprintf('%s%s',
51352 $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
51353 sprintf('--%s%s', $option->getName(), $value)
51354 );
51355
51356 $spacingWidth = $totalWidth - Helper::strlen($synopsis);
51357
51358 $this->writeText(sprintf('  <info>%s</info>  %s%s%s%s',
51359 $synopsis,
51360 str_repeat(' ', $spacingWidth),
51361
51362  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
51363 $default,
51364 $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
51365 ), $options);
51366 }
51367
51368
51369
51370
51371 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
51372 {
51373 $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
51374 foreach ($definition->getArguments() as $argument) {
51375 $totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
51376 }
51377
51378 if ($definition->getArguments()) {
51379 $this->writeText('<comment>Arguments:</comment>', $options);
51380 $this->writeText("\n");
51381 foreach ($definition->getArguments() as $argument) {
51382 $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
51383 $this->writeText("\n");
51384 }
51385 }
51386
51387 if ($definition->getArguments() && $definition->getOptions()) {
51388 $this->writeText("\n");
51389 }
51390
51391 if ($definition->getOptions()) {
51392 $laterOptions = array();
51393
51394 $this->writeText('<comment>Options:</comment>', $options);
51395 foreach ($definition->getOptions() as $option) {
51396 if (strlen($option->getShortcut()) > 1) {
51397 $laterOptions[] = $option;
51398 continue;
51399 }
51400 $this->writeText("\n");
51401 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
51402 }
51403 foreach ($laterOptions as $option) {
51404 $this->writeText("\n");
51405 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
51406 }
51407 }
51408 }
51409
51410
51411
51412
51413 protected function describeCommand(Command $command, array $options = array())
51414 {
51415 $command->getSynopsis(true);
51416 $command->getSynopsis(false);
51417 $command->mergeApplicationDefinition(false);
51418
51419 $this->writeText('<comment>Usage:</comment>', $options);
51420 foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
51421 $this->writeText("\n");
51422 $this->writeText('  '.OutputFormatter::escape($usage), $options);
51423 }
51424 $this->writeText("\n");
51425
51426 $definition = $command->getNativeDefinition();
51427 if ($definition->getOptions() || $definition->getArguments()) {
51428 $this->writeText("\n");
51429 $this->describeInputDefinition($definition, $options);
51430 $this->writeText("\n");
51431 }
51432
51433 if ($help = $command->getProcessedHelp()) {
51434 $this->writeText("\n");
51435 $this->writeText('<comment>Help:</comment>', $options);
51436 $this->writeText("\n");
51437 $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
51438 $this->writeText("\n");
51439 }
51440 }
51441
51442
51443
51444
51445 protected function describeApplication(Application $application, array $options = array())
51446 {
51447 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
51448 $description = new ApplicationDescription($application, $describedNamespace);
51449
51450 if (isset($options['raw_text']) && $options['raw_text']) {
51451 $width = $this->getColumnWidth($description->getCommands());
51452
51453 foreach ($description->getCommands() as $command) {
51454 $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
51455 $this->writeText("\n");
51456 }
51457 } else {
51458 if ('' != $help = $application->getHelp()) {
51459 $this->writeText("$help\n\n", $options);
51460 }
51461
51462 $this->writeText("<comment>Usage:</comment>\n", $options);
51463 $this->writeText("  command [options] [arguments]\n\n", $options);
51464
51465 $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
51466
51467 $this->writeText("\n");
51468 $this->writeText("\n");
51469
51470 $width = $this->getColumnWidth($description->getCommands());
51471
51472 if ($describedNamespace) {
51473 $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
51474 } else {
51475 $this->writeText('<comment>Available commands:</comment>', $options);
51476 }
51477
51478
51479  foreach ($description->getNamespaces() as $namespace) {
51480 if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
51481 $this->writeText("\n");
51482 $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
51483 }
51484
51485 foreach ($namespace['commands'] as $name) {
51486 $this->writeText("\n");
51487 $spacingWidth = $width - Helper::strlen($name);
51488 $this->writeText(sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
51489 }
51490 }
51491
51492 $this->writeText("\n");
51493 }
51494 }
51495
51496
51497
51498
51499 private function writeText($content, array $options = array())
51500 {
51501 $this->write(
51502 isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
51503 isset($options['raw_output']) ? !$options['raw_output'] : true
51504 );
51505 }
51506
51507
51508
51509
51510
51511
51512
51513
51514 private function formatDefaultValue($default)
51515 {
51516 if (INF === $default) {
51517 return 'INF';
51518 }
51519
51520 if (is_string($default)) {
51521 $default = OutputFormatter::escape($default);
51522 } elseif (is_array($default)) {
51523 foreach ($default as $key => $value) {
51524 if (is_string($value)) {
51525 $default[$key] = OutputFormatter::escape($value);
51526 }
51527 }
51528 }
51529
51530 if (\PHP_VERSION_ID < 50400) {
51531 return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
51532 }
51533
51534 return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
51535 }
51536
51537
51538
51539
51540
51541
51542 private function getColumnWidth(array $commands)
51543 {
51544 $widths = array();
51545
51546 foreach ($commands as $command) {
51547 $widths[] = Helper::strlen($command->getName());
51548 foreach ($command->getAliases() as $alias) {
51549 $widths[] = Helper::strlen($alias);
51550 }
51551 }
51552
51553 return max($widths) + 2;
51554 }
51555
51556
51557
51558
51559
51560
51561 private function calculateTotalWidthForOptions(array $options)
51562 {
51563 $totalWidth = 0;
51564 foreach ($options as $option) {
51565
51566  $nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
51567
51568 if ($option->acceptValue()) {
51569 $valueLength = 1 + Helper::strlen($option->getName()); 
51570  $valueLength += $option->isValueOptional() ? 2 : 0; 
51571
51572 $nameLength += $valueLength;
51573 }
51574 $totalWidth = max($totalWidth, $nameLength);
51575 }
51576
51577 return $totalWidth;
51578 }
51579 }
51580 <?php
51581
51582
51583
51584
51585
51586
51587
51588
51589
51590
51591 namespace Symfony\Component\Console\Descriptor;
51592
51593 use Symfony\Component\Console\Application;
51594 use Symfony\Component\Console\Command\Command;
51595 use Symfony\Component\Console\Input\InputArgument;
51596 use Symfony\Component\Console\Input\InputDefinition;
51597 use Symfony\Component\Console\Input\InputOption;
51598
51599
51600
51601
51602
51603
51604
51605
51606 class XmlDescriptor extends Descriptor
51607 {
51608
51609
51610
51611 public function getInputDefinitionDocument(InputDefinition $definition)
51612 {
51613 $dom = new \DOMDocument('1.0', 'UTF-8');
51614 $dom->appendChild($definitionXML = $dom->createElement('definition'));
51615
51616 $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
51617 foreach ($definition->getArguments() as $argument) {
51618 $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
51619 }
51620
51621 $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
51622 foreach ($definition->getOptions() as $option) {
51623 $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
51624 }
51625
51626 return $dom;
51627 }
51628
51629
51630
51631
51632 public function getCommandDocument(Command $command)
51633 {
51634 $dom = new \DOMDocument('1.0', 'UTF-8');
51635 $dom->appendChild($commandXML = $dom->createElement('command'));
51636
51637 $command->getSynopsis();
51638 $command->mergeApplicationDefinition(false);
51639
51640 $commandXML->setAttribute('id', $command->getName());
51641 $commandXML->setAttribute('name', $command->getName());
51642
51643 $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
51644
51645 foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
51646 $usagesXML->appendChild($dom->createElement('usage', $usage));
51647 }
51648
51649 $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
51650 $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
51651
51652 $commandXML->appendChild($helpXML = $dom->createElement('help'));
51653 $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
51654
51655 $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
51656 $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
51657
51658 return $dom;
51659 }
51660
51661
51662
51663
51664
51665
51666
51667 public function getApplicationDocument(Application $application, $namespace = null)
51668 {
51669 $dom = new \DOMDocument('1.0', 'UTF-8');
51670 $dom->appendChild($rootXml = $dom->createElement('symfony'));
51671
51672 if ('UNKNOWN' !== $application->getName()) {
51673 $rootXml->setAttribute('name', $application->getName());
51674 if ('UNKNOWN' !== $application->getVersion()) {
51675 $rootXml->setAttribute('version', $application->getVersion());
51676 }
51677 }
51678
51679 $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
51680
51681 $description = new ApplicationDescription($application, $namespace);
51682
51683 if ($namespace) {
51684 $commandsXML->setAttribute('namespace', $namespace);
51685 }
51686
51687 foreach ($description->getCommands() as $command) {
51688 $this->appendDocument($commandsXML, $this->getCommandDocument($command));
51689 }
51690
51691 if (!$namespace) {
51692 $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
51693
51694 foreach ($description->getNamespaces() as $namespaceDescription) {
51695 $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
51696 $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
51697
51698 foreach ($namespaceDescription['commands'] as $name) {
51699 $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
51700 $commandXML->appendChild($dom->createTextNode($name));
51701 }
51702 }
51703 }
51704
51705 return $dom;
51706 }
51707
51708
51709
51710
51711 protected function describeInputArgument(InputArgument $argument, array $options = array())
51712 {
51713 $this->writeDocument($this->getInputArgumentDocument($argument));
51714 }
51715
51716
51717
51718
51719 protected function describeInputOption(InputOption $option, array $options = array())
51720 {
51721 $this->writeDocument($this->getInputOptionDocument($option));
51722 }
51723
51724
51725
51726
51727 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
51728 {
51729 $this->writeDocument($this->getInputDefinitionDocument($definition));
51730 }
51731
51732
51733
51734
51735 protected function describeCommand(Command $command, array $options = array())
51736 {
51737 $this->writeDocument($this->getCommandDocument($command));
51738 }
51739
51740
51741
51742
51743 protected function describeApplication(Application $application, array $options = array())
51744 {
51745 $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
51746 }
51747
51748
51749
51750
51751 private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
51752 {
51753 foreach ($importedParent->childNodes as $childNode) {
51754 $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
51755 }
51756 }
51757
51758
51759
51760
51761
51762
51763 private function writeDocument(\DOMDocument $dom)
51764 {
51765 $dom->formatOutput = true;
51766 $this->write($dom->saveXML());
51767 }
51768
51769
51770
51771
51772 private function getInputArgumentDocument(InputArgument $argument)
51773 {
51774 $dom = new \DOMDocument('1.0', 'UTF-8');
51775
51776 $dom->appendChild($objectXML = $dom->createElement('argument'));
51777 $objectXML->setAttribute('name', $argument->getName());
51778 $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
51779 $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
51780 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
51781 $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
51782
51783 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
51784 $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
51785 foreach ($defaults as $default) {
51786 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
51787 $defaultXML->appendChild($dom->createTextNode($default));
51788 }
51789
51790 return $dom;
51791 }
51792
51793
51794
51795
51796 private function getInputOptionDocument(InputOption $option)
51797 {
51798 $dom = new \DOMDocument('1.0', 'UTF-8');
51799
51800 $dom->appendChild($objectXML = $dom->createElement('option'));
51801 $objectXML->setAttribute('name', '--'.$option->getName());
51802 $pos = strpos($option->getShortcut(), '|');
51803 if (false !== $pos) {
51804 $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
51805 $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut()));
51806 } else {
51807 $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
51808 }
51809 $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
51810 $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
51811 $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
51812 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
51813 $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
51814
51815 if ($option->acceptValue()) {
51816 $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
51817 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
51818
51819 if (!empty($defaults)) {
51820 foreach ($defaults as $default) {
51821 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
51822 $defaultXML->appendChild($dom->createTextNode($default));
51823 }
51824 }
51825 }
51826
51827 return $dom;
51828 }
51829 }
51830 <?php
51831
51832
51833
51834
51835
51836
51837
51838
51839
51840
51841 namespace Symfony\Component\Console\Event;
51842
51843
51844
51845
51846
51847
51848 class ConsoleCommandEvent extends ConsoleEvent
51849 {
51850
51851
51852
51853 const RETURN_CODE_DISABLED = 113;
51854
51855
51856
51857
51858 private $commandShouldRun = true;
51859
51860
51861
51862
51863
51864
51865 public function disableCommand()
51866 {
51867 return $this->commandShouldRun = false;
51868 }
51869
51870
51871
51872
51873
51874
51875 public function enableCommand()
51876 {
51877 return $this->commandShouldRun = true;
51878 }
51879
51880
51881
51882
51883
51884
51885 public function commandShouldRun()
51886 {
51887 return $this->commandShouldRun;
51888 }
51889 }
51890 <?php
51891
51892
51893
51894
51895
51896
51897
51898
51899
51900
51901 namespace Symfony\Component\Console\Event;
51902
51903 use Symfony\Component\Console\Command\Command;
51904 use Symfony\Component\Console\Input\InputInterface;
51905 use Symfony\Component\Console\Output\OutputInterface;
51906 use Symfony\Component\EventDispatcher\Event;
51907
51908
51909
51910
51911
51912
51913 class ConsoleEvent extends Event
51914 {
51915 protected $command;
51916
51917 private $input;
51918 private $output;
51919
51920 public function __construct(Command $command, InputInterface $input, OutputInterface $output)
51921 {
51922 $this->command = $command;
51923 $this->input = $input;
51924 $this->output = $output;
51925 }
51926
51927
51928
51929
51930
51931
51932 public function getCommand()
51933 {
51934 return $this->command;
51935 }
51936
51937
51938
51939
51940
51941
51942 public function getInput()
51943 {
51944 return $this->input;
51945 }
51946
51947
51948
51949
51950
51951
51952 public function getOutput()
51953 {
51954 return $this->output;
51955 }
51956 }
51957 <?php
51958
51959
51960
51961
51962
51963
51964
51965
51966
51967
51968 namespace Symfony\Component\Console\Event;
51969
51970 use Symfony\Component\Console\Command\Command;
51971 use Symfony\Component\Console\Input\InputInterface;
51972 use Symfony\Component\Console\Output\OutputInterface;
51973
51974
51975
51976
51977
51978
51979 class ConsoleExceptionEvent extends ConsoleEvent
51980 {
51981 private $exception;
51982 private $exitCode;
51983
51984 public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
51985 {
51986 parent::__construct($command, $input, $output);
51987
51988 $this->setException($exception);
51989 $this->exitCode = (int) $exitCode;
51990 }
51991
51992
51993
51994
51995
51996
51997 public function getException()
51998 {
51999 return $this->exception;
52000 }
52001
52002
52003
52004
52005
52006
52007
52008
52009 public function setException(\Exception $exception)
52010 {
52011 $this->exception = $exception;
52012 }
52013
52014
52015
52016
52017
52018
52019 public function getExitCode()
52020 {
52021 return $this->exitCode;
52022 }
52023 }
52024 <?php
52025
52026
52027
52028
52029
52030
52031
52032
52033
52034
52035 namespace Symfony\Component\Console\Event;
52036
52037 use Symfony\Component\Console\Command\Command;
52038 use Symfony\Component\Console\Input\InputInterface;
52039 use Symfony\Component\Console\Output\OutputInterface;
52040
52041
52042
52043
52044
52045
52046 class ConsoleTerminateEvent extends ConsoleEvent
52047 {
52048
52049
52050
52051
52052
52053 private $exitCode;
52054
52055 public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
52056 {
52057 parent::__construct($command, $input, $output);
52058
52059 $this->setExitCode($exitCode);
52060 }
52061
52062
52063
52064
52065
52066
52067 public function setExitCode($exitCode)
52068 {
52069 $this->exitCode = (int) $exitCode;
52070 }
52071
52072
52073
52074
52075
52076
52077 public function getExitCode()
52078 {
52079 return $this->exitCode;
52080 }
52081 }
52082 <?php
52083
52084
52085
52086
52087
52088
52089
52090
52091
52092
52093 namespace Symfony\Component\Console\Exception;
52094
52095
52096
52097
52098
52099
52100 class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
52101 {
52102 private $alternatives;
52103
52104
52105
52106
52107
52108
52109
52110 public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
52111 {
52112 parent::__construct($message, $code, $previous);
52113
52114 $this->alternatives = $alternatives;
52115 }
52116
52117
52118
52119
52120 public function getAlternatives()
52121 {
52122 return $this->alternatives;
52123 }
52124 }
52125 <?php
52126
52127
52128
52129
52130
52131
52132
52133
52134
52135
52136 namespace Symfony\Component\Console\Exception;
52137
52138
52139
52140
52141
52142
52143 interface ExceptionInterface
52144 {
52145 }
52146 <?php
52147
52148
52149
52150
52151
52152
52153
52154
52155
52156
52157 namespace Symfony\Component\Console\Exception;
52158
52159
52160
52161
52162 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
52163 {
52164 }
52165 <?php
52166
52167
52168
52169
52170
52171
52172
52173
52174
52175
52176 namespace Symfony\Component\Console\Exception;
52177
52178
52179
52180
52181
52182
52183 class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
52184 {
52185 }
52186 <?php
52187
52188
52189
52190
52191
52192
52193
52194
52195
52196
52197 namespace Symfony\Component\Console\Exception;
52198
52199
52200
52201
52202 class LogicException extends \LogicException implements ExceptionInterface
52203 {
52204 }
52205 <?php
52206
52207
52208
52209
52210
52211
52212
52213
52214
52215
52216 namespace Symfony\Component\Console\Exception;
52217
52218
52219
52220
52221 class RuntimeException extends \RuntimeException implements ExceptionInterface
52222 {
52223 }
52224 <?php
52225
52226
52227
52228
52229
52230
52231
52232
52233
52234
52235 namespace Symfony\Component\Console\Formatter;
52236
52237 use Symfony\Component\Console\Exception\InvalidArgumentException;
52238
52239
52240
52241
52242
52243
52244 class OutputFormatter implements OutputFormatterInterface
52245 {
52246 private $decorated;
52247 private $styles = array();
52248 private $styleStack;
52249
52250
52251
52252
52253
52254
52255
52256
52257 public static function escape($text)
52258 {
52259 $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
52260
52261 return self::escapeTrailingBackslash($text);
52262 }
52263
52264
52265
52266
52267
52268
52269
52270
52271
52272
52273 public static function escapeTrailingBackslash($text)
52274 {
52275 if ('\\' === substr($text, -1)) {
52276 $len = strlen($text);
52277 $text = rtrim($text, '\\');
52278 $text = str_replace("\0", '', $text);
52279 $text .= str_repeat("\0", $len - strlen($text));
52280 }
52281
52282 return $text;
52283 }
52284
52285
52286
52287
52288
52289
52290
52291 public function __construct($decorated = false, array $styles = array())
52292 {
52293 $this->decorated = (bool) $decorated;
52294
52295 $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
52296 $this->setStyle('info', new OutputFormatterStyle('green'));
52297 $this->setStyle('comment', new OutputFormatterStyle('yellow'));
52298 $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
52299
52300 foreach ($styles as $name => $style) {
52301 $this->setStyle($name, $style);
52302 }
52303
52304 $this->styleStack = new OutputFormatterStyleStack();
52305 }
52306
52307
52308
52309
52310 public function setDecorated($decorated)
52311 {
52312 $this->decorated = (bool) $decorated;
52313 }
52314
52315
52316
52317
52318 public function isDecorated()
52319 {
52320 return $this->decorated;
52321 }
52322
52323
52324
52325
52326 public function setStyle($name, OutputFormatterStyleInterface $style)
52327 {
52328 $this->styles[strtolower($name)] = $style;
52329 }
52330
52331
52332
52333
52334 public function hasStyle($name)
52335 {
52336 return isset($this->styles[strtolower($name)]);
52337 }
52338
52339
52340
52341
52342 public function getStyle($name)
52343 {
52344 if (!$this->hasStyle($name)) {
52345 throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
52346 }
52347
52348 return $this->styles[strtolower($name)];
52349 }
52350
52351
52352
52353
52354 public function format($message)
52355 {
52356 $message = (string) $message;
52357 $offset = 0;
52358 $output = '';
52359 $tagRegex = '[a-z][a-z0-9_=;-]*+';
52360 preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
52361 foreach ($matches[0] as $i => $match) {
52362 $pos = $match[1];
52363 $text = $match[0];
52364
52365 if (0 != $pos && '\\' == $message[$pos - 1]) {
52366 continue;
52367 }
52368
52369
52370  $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
52371 $offset = $pos + strlen($text);
52372
52373
52374  if ($open = '/' != $text[1]) {
52375 $tag = $matches[1][$i][0];
52376 } else {
52377 $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
52378 }
52379
52380 if (!$open && !$tag) {
52381
52382  $this->styleStack->pop();
52383 } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
52384 $output .= $this->applyCurrentStyle($text);
52385 } elseif ($open) {
52386 $this->styleStack->push($style);
52387 } else {
52388 $this->styleStack->pop($style);
52389 }
52390 }
52391
52392 $output .= $this->applyCurrentStyle(substr($message, $offset));
52393
52394 if (false !== strpos($output, "\0")) {
52395 return strtr($output, array("\0" => '\\', '\\<' => '<'));
52396 }
52397
52398 return str_replace('\\<', '<', $output);
52399 }
52400
52401
52402
52403
52404 public function getStyleStack()
52405 {
52406 return $this->styleStack;
52407 }
52408
52409
52410
52411
52412
52413
52414
52415
52416 private function createStyleFromString($string)
52417 {
52418 if (isset($this->styles[$string])) {
52419 return $this->styles[$string];
52420 }
52421
52422 if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
52423 return false;
52424 }
52425
52426 $style = new OutputFormatterStyle();
52427 foreach ($matches as $match) {
52428 array_shift($match);
52429
52430 if ('fg' == $match[0]) {
52431 $style->setForeground($match[1]);
52432 } elseif ('bg' == $match[0]) {
52433 $style->setBackground($match[1]);
52434 } else {
52435 try {
52436 $style->setOption($match[1]);
52437 } catch (\InvalidArgumentException $e) {
52438 return false;
52439 }
52440 }
52441 }
52442
52443 return $style;
52444 }
52445
52446
52447
52448
52449
52450
52451
52452
52453 private function applyCurrentStyle($text)
52454 {
52455 return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
52456 }
52457 }
52458 <?php
52459
52460
52461
52462
52463
52464
52465
52466
52467
52468
52469 namespace Symfony\Component\Console\Formatter;
52470
52471
52472
52473
52474
52475
52476 interface OutputFormatterInterface
52477 {
52478
52479
52480
52481
52482
52483 public function setDecorated($decorated);
52484
52485
52486
52487
52488
52489
52490 public function isDecorated();
52491
52492
52493
52494
52495
52496
52497
52498 public function setStyle($name, OutputFormatterStyleInterface $style);
52499
52500
52501
52502
52503
52504
52505
52506
52507 public function hasStyle($name);
52508
52509
52510
52511
52512
52513
52514
52515
52516
52517
52518 public function getStyle($name);
52519
52520
52521
52522
52523
52524
52525
52526
52527 public function format($message);
52528 }
52529 <?php
52530
52531
52532
52533
52534
52535
52536
52537
52538
52539
52540 namespace Symfony\Component\Console\Formatter;
52541
52542 use Symfony\Component\Console\Exception\InvalidArgumentException;
52543
52544
52545
52546
52547
52548
52549 class OutputFormatterStyle implements OutputFormatterStyleInterface
52550 {
52551 private static $availableForegroundColors = array(
52552 'black' => array('set' => 30, 'unset' => 39),
52553 'red' => array('set' => 31, 'unset' => 39),
52554 'green' => array('set' => 32, 'unset' => 39),
52555 'yellow' => array('set' => 33, 'unset' => 39),
52556 'blue' => array('set' => 34, 'unset' => 39),
52557 'magenta' => array('set' => 35, 'unset' => 39),
52558 'cyan' => array('set' => 36, 'unset' => 39),
52559 'white' => array('set' => 37, 'unset' => 39),
52560 'default' => array('set' => 39, 'unset' => 39),
52561 );
52562 private static $availableBackgroundColors = array(
52563 'black' => array('set' => 40, 'unset' => 49),
52564 'red' => array('set' => 41, 'unset' => 49),
52565 'green' => array('set' => 42, 'unset' => 49),
52566 'yellow' => array('set' => 43, 'unset' => 49),
52567 'blue' => array('set' => 44, 'unset' => 49),
52568 'magenta' => array('set' => 45, 'unset' => 49),
52569 'cyan' => array('set' => 46, 'unset' => 49),
52570 'white' => array('set' => 47, 'unset' => 49),
52571 'default' => array('set' => 49, 'unset' => 49),
52572 );
52573 private static $availableOptions = array(
52574 'bold' => array('set' => 1, 'unset' => 22),
52575 'underscore' => array('set' => 4, 'unset' => 24),
52576 'blink' => array('set' => 5, 'unset' => 25),
52577 'reverse' => array('set' => 7, 'unset' => 27),
52578 'conceal' => array('set' => 8, 'unset' => 28),
52579 );
52580
52581 private $foreground;
52582 private $background;
52583 private $options = array();
52584
52585
52586
52587
52588
52589
52590
52591
52592 public function __construct($foreground = null, $background = null, array $options = array())
52593 {
52594 if (null !== $foreground) {
52595 $this->setForeground($foreground);
52596 }
52597 if (null !== $background) {
52598 $this->setBackground($background);
52599 }
52600 if (count($options)) {
52601 $this->setOptions($options);
52602 }
52603 }
52604
52605
52606
52607
52608
52609
52610
52611
52612 public function setForeground($color = null)
52613 {
52614 if (null === $color) {
52615 $this->foreground = null;
52616
52617 return;
52618 }
52619
52620 if (!isset(static::$availableForegroundColors[$color])) {
52621 throw new InvalidArgumentException(sprintf(
52622 'Invalid foreground color specified: "%s". Expected one of (%s)',
52623 $color,
52624 implode(', ', array_keys(static::$availableForegroundColors))
52625 ));
52626 }
52627
52628 $this->foreground = static::$availableForegroundColors[$color];
52629 }
52630
52631
52632
52633
52634
52635
52636
52637
52638 public function setBackground($color = null)
52639 {
52640 if (null === $color) {
52641 $this->background = null;
52642
52643 return;
52644 }
52645
52646 if (!isset(static::$availableBackgroundColors[$color])) {
52647 throw new InvalidArgumentException(sprintf(
52648 'Invalid background color specified: "%s". Expected one of (%s)',
52649 $color,
52650 implode(', ', array_keys(static::$availableBackgroundColors))
52651 ));
52652 }
52653
52654 $this->background = static::$availableBackgroundColors[$color];
52655 }
52656
52657
52658
52659
52660
52661
52662
52663
52664 public function setOption($option)
52665 {
52666 if (!isset(static::$availableOptions[$option])) {
52667 throw new InvalidArgumentException(sprintf(
52668 'Invalid option specified: "%s". Expected one of (%s)',
52669 $option,
52670 implode(', ', array_keys(static::$availableOptions))
52671 ));
52672 }
52673
52674 if (!in_array(static::$availableOptions[$option], $this->options)) {
52675 $this->options[] = static::$availableOptions[$option];
52676 }
52677 }
52678
52679
52680
52681
52682
52683
52684
52685
52686 public function unsetOption($option)
52687 {
52688 if (!isset(static::$availableOptions[$option])) {
52689 throw new InvalidArgumentException(sprintf(
52690 'Invalid option specified: "%s". Expected one of (%s)',
52691 $option,
52692 implode(', ', array_keys(static::$availableOptions))
52693 ));
52694 }
52695
52696 $pos = array_search(static::$availableOptions[$option], $this->options);
52697 if (false !== $pos) {
52698 unset($this->options[$pos]);
52699 }
52700 }
52701
52702
52703
52704
52705 public function setOptions(array $options)
52706 {
52707 $this->options = array();
52708
52709 foreach ($options as $option) {
52710 $this->setOption($option);
52711 }
52712 }
52713
52714
52715
52716
52717
52718
52719
52720
52721 public function apply($text)
52722 {
52723 $setCodes = array();
52724 $unsetCodes = array();
52725
52726 if (null !== $this->foreground) {
52727 $setCodes[] = $this->foreground['set'];
52728 $unsetCodes[] = $this->foreground['unset'];
52729 }
52730 if (null !== $this->background) {
52731 $setCodes[] = $this->background['set'];
52732 $unsetCodes[] = $this->background['unset'];
52733 }
52734 if (count($this->options)) {
52735 foreach ($this->options as $option) {
52736 $setCodes[] = $option['set'];
52737 $unsetCodes[] = $option['unset'];
52738 }
52739 }
52740
52741 if (0 === count($setCodes)) {
52742 return $text;
52743 }
52744
52745 return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
52746 }
52747 }
52748 <?php
52749
52750
52751
52752
52753
52754
52755
52756
52757
52758
52759 namespace Symfony\Component\Console\Formatter;
52760
52761
52762
52763
52764
52765
52766 interface OutputFormatterStyleInterface
52767 {
52768
52769
52770
52771
52772
52773 public function setForeground($color = null);
52774
52775
52776
52777
52778
52779
52780 public function setBackground($color = null);
52781
52782
52783
52784
52785
52786
52787 public function setOption($option);
52788
52789
52790
52791
52792
52793
52794 public function unsetOption($option);
52795
52796
52797
52798
52799 public function setOptions(array $options);
52800
52801
52802
52803
52804
52805
52806
52807
52808 public function apply($text);
52809 }
52810 <?php
52811
52812
52813
52814
52815
52816
52817
52818
52819
52820
52821 namespace Symfony\Component\Console\Formatter;
52822
52823 use Symfony\Component\Console\Exception\InvalidArgumentException;
52824
52825
52826
52827
52828 class OutputFormatterStyleStack
52829 {
52830
52831
52832
52833 private $styles;
52834
52835 private $emptyStyle;
52836
52837 public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
52838 {
52839 $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
52840 $this->reset();
52841 }
52842
52843
52844
52845
52846 public function reset()
52847 {
52848 $this->styles = array();
52849 }
52850
52851
52852
52853
52854 public function push(OutputFormatterStyleInterface $style)
52855 {
52856 $this->styles[] = $style;
52857 }
52858
52859
52860
52861
52862
52863
52864
52865
52866 public function pop(OutputFormatterStyleInterface $style = null)
52867 {
52868 if (empty($this->styles)) {
52869 return $this->emptyStyle;
52870 }
52871
52872 if (null === $style) {
52873 return array_pop($this->styles);
52874 }
52875
52876 foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
52877 if ($style->apply('') === $stackedStyle->apply('')) {
52878 $this->styles = array_slice($this->styles, 0, $index);
52879
52880 return $stackedStyle;
52881 }
52882 }
52883
52884 throw new InvalidArgumentException('Incorrectly nested style tag found.');
52885 }
52886
52887
52888
52889
52890
52891
52892 public function getCurrent()
52893 {
52894 if (empty($this->styles)) {
52895 return $this->emptyStyle;
52896 }
52897
52898 return $this->styles[count($this->styles) - 1];
52899 }
52900
52901
52902
52903
52904 public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
52905 {
52906 $this->emptyStyle = $emptyStyle;
52907
52908 return $this;
52909 }
52910
52911
52912
52913
52914 public function getEmptyStyle()
52915 {
52916 return $this->emptyStyle;
52917 }
52918 }
52919 <?php
52920
52921
52922
52923
52924
52925
52926
52927
52928
52929
52930 namespace Symfony\Component\Console\Helper;
52931
52932
52933
52934
52935
52936
52937
52938
52939 class DebugFormatterHelper extends Helper
52940 {
52941 private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
52942 private $started = array();
52943 private $count = -1;
52944
52945
52946
52947
52948
52949
52950
52951
52952
52953
52954 public function start($id, $message, $prefix = 'RUN')
52955 {
52956 $this->started[$id] = array('border' => ++$this->count % count($this->colors));
52957
52958 return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
52959 }
52960
52961
52962
52963
52964
52965
52966
52967
52968
52969
52970
52971
52972 public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
52973 {
52974 $message = '';
52975
52976 if ($error) {
52977 if (isset($this->started[$id]['out'])) {
52978 $message .= "\n";
52979 unset($this->started[$id]['out']);
52980 }
52981 if (!isset($this->started[$id]['err'])) {
52982 $message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
52983 $this->started[$id]['err'] = true;
52984 }
52985
52986 $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
52987 } else {
52988 if (isset($this->started[$id]['err'])) {
52989 $message .= "\n";
52990 unset($this->started[$id]['err']);
52991 }
52992 if (!isset($this->started[$id]['out'])) {
52993 $message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
52994 $this->started[$id]['out'] = true;
52995 }
52996
52997 $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
52998 }
52999
53000 return $message;
53001 }
53002
53003
53004
53005
53006
53007
53008
53009
53010
53011
53012
53013 public function stop($id, $message, $successful, $prefix = 'RES')
53014 {
53015 $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
53016
53017 if ($successful) {
53018 return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
53019 }
53020
53021 $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
53022
53023 unset($this->started[$id]['out'], $this->started[$id]['err']);
53024
53025 return $message;
53026 }
53027
53028
53029
53030
53031
53032
53033 private function getBorder($id)
53034 {
53035 return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
53036 }
53037
53038
53039
53040
53041 public function getName()
53042 {
53043 return 'debug_formatter';
53044 }
53045 }
53046 <?php
53047
53048
53049
53050
53051
53052
53053
53054
53055
53056
53057 namespace Symfony\Component\Console\Helper;
53058
53059 use Symfony\Component\Console\Descriptor\DescriptorInterface;
53060 use Symfony\Component\Console\Descriptor\JsonDescriptor;
53061 use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
53062 use Symfony\Component\Console\Descriptor\TextDescriptor;
53063 use Symfony\Component\Console\Descriptor\XmlDescriptor;
53064 use Symfony\Component\Console\Output\OutputInterface;
53065 use Symfony\Component\Console\Exception\InvalidArgumentException;
53066
53067
53068
53069
53070
53071
53072 class DescriptorHelper extends Helper
53073 {
53074
53075
53076
53077 private $descriptors = array();
53078
53079 public function __construct()
53080 {
53081 $this
53082 ->register('txt', new TextDescriptor())
53083 ->register('xml', new XmlDescriptor())
53084 ->register('json', new JsonDescriptor())
53085 ->register('md', new MarkdownDescriptor())
53086 ;
53087 }
53088
53089
53090
53091
53092
53093
53094
53095
53096
53097
53098
53099
53100
53101
53102 public function describe(OutputInterface $output, $object, array $options = array())
53103 {
53104 $options = array_merge(array(
53105 'raw_text' => false,
53106 'format' => 'txt',
53107 ), $options);
53108
53109 if (!isset($this->descriptors[$options['format']])) {
53110 throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
53111 }
53112
53113 $descriptor = $this->descriptors[$options['format']];
53114 $descriptor->describe($output, $object, $options);
53115 }
53116
53117
53118
53119
53120
53121
53122
53123
53124
53125 public function register($format, DescriptorInterface $descriptor)
53126 {
53127 $this->descriptors[$format] = $descriptor;
53128
53129 return $this;
53130 }
53131
53132
53133
53134
53135 public function getName()
53136 {
53137 return 'descriptor';
53138 }
53139 }
53140 <?php
53141
53142
53143
53144
53145
53146
53147
53148
53149
53150
53151 namespace Symfony\Component\Console\Helper;
53152
53153 use Symfony\Component\Console\Exception\InvalidArgumentException;
53154 use Symfony\Component\Console\Exception\RuntimeException;
53155 use Symfony\Component\Console\Output\ConsoleOutputInterface;
53156 use Symfony\Component\Console\Output\OutputInterface;
53157 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
53158
53159
53160
53161
53162
53163
53164
53165
53166
53167 class DialogHelper extends InputAwareHelper
53168 {
53169 private $inputStream;
53170 private static $shell;
53171 private static $stty;
53172
53173 public function __construct($triggerDeprecationError = true)
53174 {
53175 if ($triggerDeprecationError) {
53176 @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);
53177 }
53178 }
53179
53180
53181
53182
53183
53184
53185
53186
53187
53188
53189
53190
53191
53192
53193
53194
53195 public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
53196 {
53197 if ($output instanceof ConsoleOutputInterface) {
53198 $output = $output->getErrorOutput();
53199 }
53200
53201 $width = max(array_map('strlen', array_keys($choices)));
53202
53203 $messages = (array) $question;
53204 foreach ($choices as $key => $value) {
53205 $messages[] = sprintf("  [<info>%-{$width}s</info>] %s", $key, $value);
53206 }
53207
53208 $output->writeln($messages);
53209
53210 $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
53211
53212  $selectedChoices = str_replace(' ', '', $picked);
53213
53214 if ($multiselect) {
53215
53216  if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
53217 throw new InvalidArgumentException(sprintf($errorMessage, $picked));
53218 }
53219 $selectedChoices = explode(',', $selectedChoices);
53220 } else {
53221 $selectedChoices = array($picked);
53222 }
53223
53224 $multiselectChoices = array();
53225
53226 foreach ($selectedChoices as $value) {
53227 if (empty($choices[$value])) {
53228 throw new InvalidArgumentException(sprintf($errorMessage, $value));
53229 }
53230 $multiselectChoices[] = $value;
53231 }
53232
53233 if ($multiselect) {
53234 return $multiselectChoices;
53235 }
53236
53237 return $picked;
53238 }, $attempts, $default);
53239
53240 return $result;
53241 }
53242
53243
53244
53245
53246
53247
53248
53249
53250
53251
53252
53253
53254
53255 public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
53256 {
53257 if ($this->input && !$this->input->isInteractive()) {
53258 return $default;
53259 }
53260
53261 if ($output instanceof ConsoleOutputInterface) {
53262 $output = $output->getErrorOutput();
53263 }
53264
53265 $output->write($question);
53266
53267 $inputStream = $this->inputStream ?: STDIN;
53268
53269 if (null === $autocomplete || !$this->hasSttyAvailable()) {
53270 $ret = fgets($inputStream, 4096);
53271 if (false === $ret) {
53272 throw new RuntimeException('Aborted');
53273 }
53274 $ret = trim($ret);
53275 } else {
53276 $ret = '';
53277
53278 $i = 0;
53279 $ofs = -1;
53280 $matches = $autocomplete;
53281 $numMatches = count($matches);
53282
53283 $sttyMode = shell_exec('stty -g');
53284
53285
53286  shell_exec('stty -icanon -echo');
53287
53288
53289  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
53290
53291
53292  while (!feof($inputStream)) {
53293 $c = fread($inputStream, 1);
53294
53295
53296  if ("\177" === $c) {
53297 if (0 === $numMatches && 0 !== $i) {
53298 --$i;
53299
53300  $output->write("\033[1D");
53301 }
53302
53303 if (0 === $i) {
53304 $ofs = -1;
53305 $matches = $autocomplete;
53306 $numMatches = count($matches);
53307 } else {
53308 $numMatches = 0;
53309 }
53310
53311
53312  $ret = substr($ret, 0, $i);
53313 } elseif ("\033" === $c) {
53314
53315  $c .= fread($inputStream, 2);
53316
53317
53318  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
53319 if ('A' === $c[2] && -1 === $ofs) {
53320 $ofs = 0;
53321 }
53322
53323 if (0 === $numMatches) {
53324 continue;
53325 }
53326
53327 $ofs += ('A' === $c[2]) ? -1 : 1;
53328 $ofs = ($numMatches + $ofs) % $numMatches;
53329 }
53330 } elseif (ord($c) < 32) {
53331 if ("\t" === $c || "\n" === $c) {
53332 if ($numMatches > 0 && -1 !== $ofs) {
53333 $ret = $matches[$ofs];
53334
53335  $output->write(substr($ret, $i));
53336 $i = strlen($ret);
53337 }
53338
53339 if ("\n" === $c) {
53340 $output->write($c);
53341 break;
53342 }
53343
53344 $numMatches = 0;
53345 }
53346
53347 continue;
53348 } else {
53349 $output->write($c);
53350 $ret .= $c;
53351 ++$i;
53352
53353 $numMatches = 0;
53354 $ofs = 0;
53355
53356 foreach ($autocomplete as $value) {
53357
53358  if (0 === strpos($value, $ret) && $i !== strlen($value)) {
53359 $matches[$numMatches++] = $value;
53360 }
53361 }
53362 }
53363
53364
53365  $output->write("\033[K");
53366
53367 if ($numMatches > 0 && -1 !== $ofs) {
53368
53369  $output->write("\0337");
53370
53371  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
53372
53373  $output->write("\0338");
53374 }
53375 }
53376
53377
53378  shell_exec(sprintf('stty %s', $sttyMode));
53379 }
53380
53381 return strlen($ret) > 0 ? $ret : $default;
53382 }
53383
53384
53385
53386
53387
53388
53389
53390
53391
53392
53393
53394
53395 public function askConfirmation(OutputInterface $output, $question, $default = true)
53396 {
53397 $answer = 'z';
53398 while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
53399 $answer = $this->ask($output, $question);
53400 }
53401
53402 if (false === $default) {
53403 return $answer && 'y' == strtolower($answer[0]);
53404 }
53405
53406 return !$answer || 'y' == strtolower($answer[0]);
53407 }
53408
53409
53410
53411
53412
53413
53414
53415
53416
53417
53418
53419
53420 public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
53421 {
53422 if ($output instanceof ConsoleOutputInterface) {
53423 $output = $output->getErrorOutput();
53424 }
53425
53426 if ('\\' === DIRECTORY_SEPARATOR) {
53427 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
53428
53429
53430  if ('phar:' === substr(__FILE__, 0, 5)) {
53431 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
53432 copy($exe, $tmpExe);
53433 $exe = $tmpExe;
53434 }
53435
53436 $output->write($question);
53437 $value = rtrim(shell_exec($exe));
53438 $output->writeln('');
53439
53440 if (isset($tmpExe)) {
53441 unlink($tmpExe);
53442 }
53443
53444 return $value;
53445 }
53446
53447 if ($this->hasSttyAvailable()) {
53448 $output->write($question);
53449
53450 $sttyMode = shell_exec('stty -g');
53451
53452 shell_exec('stty -echo');
53453 $value = fgets($this->inputStream ?: STDIN, 4096);
53454 shell_exec(sprintf('stty %s', $sttyMode));
53455
53456 if (false === $value) {
53457 throw new RuntimeException('Aborted');
53458 }
53459
53460 $value = trim($value);
53461 $output->writeln('');
53462
53463 return $value;
53464 }
53465
53466 if (false !== $shell = $this->getShell()) {
53467 $output->write($question);
53468 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
53469 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
53470 $value = rtrim(shell_exec($command));
53471 $output->writeln('');
53472
53473 return $value;
53474 }
53475
53476 if ($fallback) {
53477 return $this->ask($output, $question);
53478 }
53479
53480 throw new RuntimeException('Unable to hide the response');
53481 }
53482
53483
53484
53485
53486
53487
53488
53489
53490
53491
53492
53493
53494
53495
53496
53497
53498
53499
53500
53501 public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
53502 {
53503 $that = $this;
53504
53505 $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
53506 return $that->ask($output, $question, $default, $autocomplete);
53507 };
53508
53509 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
53510 }
53511
53512
53513
53514
53515
53516
53517
53518
53519
53520
53521
53522
53523
53524
53525
53526
53527
53528
53529
53530 public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
53531 {
53532 $that = $this;
53533
53534 $interviewer = function () use ($output, $question, $fallback, $that) {
53535 return $that->askHiddenResponse($output, $question, $fallback);
53536 };
53537
53538 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
53539 }
53540
53541
53542
53543
53544
53545
53546
53547
53548 public function setInputStream($stream)
53549 {
53550 $this->inputStream = $stream;
53551 }
53552
53553
53554
53555
53556
53557
53558 public function getInputStream()
53559 {
53560 return $this->inputStream;
53561 }
53562
53563
53564
53565
53566 public function getName()
53567 {
53568 return 'dialog';
53569 }
53570
53571
53572
53573
53574
53575
53576 private function getShell()
53577 {
53578 if (null !== self::$shell) {
53579 return self::$shell;
53580 }
53581
53582 self::$shell = false;
53583
53584 if (file_exists('/usr/bin/env')) {
53585
53586  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
53587 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
53588 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
53589 self::$shell = $sh;
53590 break;
53591 }
53592 }
53593 }
53594
53595 return self::$shell;
53596 }
53597
53598 private function hasSttyAvailable()
53599 {
53600 if (null !== self::$stty) {
53601 return self::$stty;
53602 }
53603
53604 exec('stty 2>&1', $output, $exitcode);
53605
53606 return self::$stty = 0 === $exitcode;
53607 }
53608
53609
53610
53611
53612
53613
53614
53615
53616
53617
53618
53619
53620
53621 private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
53622 {
53623 if ($output instanceof ConsoleOutputInterface) {
53624 $output = $output->getErrorOutput();
53625 }
53626
53627 $e = null;
53628 while (false === $attempts || $attempts--) {
53629 if (null !== $e) {
53630 $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
53631 }
53632
53633 try {
53634 return call_user_func($validator, $interviewer());
53635 } catch (\Exception $e) {
53636 }
53637 }
53638
53639 throw $e;
53640 }
53641 }
53642 <?php
53643
53644
53645
53646
53647
53648
53649
53650
53651
53652
53653 namespace Symfony\Component\Console\Helper;
53654
53655 use Symfony\Component\Console\Formatter\OutputFormatter;
53656
53657
53658
53659
53660
53661
53662 class FormatterHelper extends Helper
53663 {
53664
53665
53666
53667
53668
53669
53670
53671
53672
53673 public function formatSection($section, $message, $style = 'info')
53674 {
53675 return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
53676 }
53677
53678
53679
53680
53681
53682
53683
53684
53685
53686
53687 public function formatBlock($messages, $style, $large = false)
53688 {
53689 if (!is_array($messages)) {
53690 $messages = array($messages);
53691 }
53692
53693 $len = 0;
53694 $lines = array();
53695 foreach ($messages as $message) {
53696 $message = OutputFormatter::escape($message);
53697 $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
53698 $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
53699 }
53700
53701 $messages = $large ? array(str_repeat(' ', $len)) : array();
53702 for ($i = 0; isset($lines[$i]); ++$i) {
53703 $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
53704 }
53705 if ($large) {
53706 $messages[] = str_repeat(' ', $len);
53707 }
53708
53709 for ($i = 0; isset($messages[$i]); ++$i) {
53710 $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
53711 }
53712
53713 return implode("\n", $messages);
53714 }
53715
53716
53717
53718
53719 public function getName()
53720 {
53721 return 'formatter';
53722 }
53723 }
53724 <?php
53725
53726
53727
53728
53729
53730
53731
53732
53733
53734
53735 namespace Symfony\Component\Console\Helper;
53736
53737 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
53738
53739
53740
53741
53742
53743
53744 abstract class Helper implements HelperInterface
53745 {
53746 protected $helperSet = null;
53747
53748
53749
53750
53751 public function setHelperSet(HelperSet $helperSet = null)
53752 {
53753 $this->helperSet = $helperSet;
53754 }
53755
53756
53757
53758
53759 public function getHelperSet()
53760 {
53761 return $this->helperSet;
53762 }
53763
53764
53765
53766
53767
53768
53769
53770
53771 public static function strlen($string)
53772 {
53773 if (false === $encoding = mb_detect_encoding($string, null, true)) {
53774 return strlen($string);
53775 }
53776
53777 return mb_strwidth($string, $encoding);
53778 }
53779
53780 public static function formatTime($secs)
53781 {
53782 static $timeFormats = array(
53783 array(0, '< 1 sec'),
53784 array(1, '1 sec'),
53785 array(2, 'secs', 1),
53786 array(60, '1 min'),
53787 array(120, 'mins', 60),
53788 array(3600, '1 hr'),
53789 array(7200, 'hrs', 3600),
53790 array(86400, '1 day'),
53791 array(172800, 'days', 86400),
53792 );
53793
53794 foreach ($timeFormats as $index => $format) {
53795 if ($secs >= $format[0]) {
53796 if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
53797 || $index == count($timeFormats) - 1
53798 ) {
53799 if (2 == count($format)) {
53800 return $format[1];
53801 }
53802
53803 return floor($secs / $format[2]).' '.$format[1];
53804 }
53805 }
53806 }
53807 }
53808
53809 public static function formatMemory($memory)
53810 {
53811 if ($memory >= 1024 * 1024 * 1024) {
53812 return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
53813 }
53814
53815 if ($memory >= 1024 * 1024) {
53816 return sprintf('%.1f MiB', $memory / 1024 / 1024);
53817 }
53818
53819 if ($memory >= 1024) {
53820 return sprintf('%d KiB', $memory / 1024);
53821 }
53822
53823 return sprintf('%d B', $memory);
53824 }
53825
53826 public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
53827 {
53828 return self::strlen(self::removeDecoration($formatter, $string));
53829 }
53830
53831 public static function removeDecoration(OutputFormatterInterface $formatter, $string)
53832 {
53833 $isDecorated = $formatter->isDecorated();
53834 $formatter->setDecorated(false);
53835
53836  $string = $formatter->format($string);
53837
53838  $string = preg_replace("/\033\[[^m]*m/", '', $string);
53839 $formatter->setDecorated($isDecorated);
53840
53841 return $string;
53842 }
53843 }
53844 <?php
53845
53846
53847
53848
53849
53850
53851
53852
53853
53854
53855 namespace Symfony\Component\Console\Helper;
53856
53857
53858
53859
53860
53861
53862 interface HelperInterface
53863 {
53864
53865
53866
53867 public function setHelperSet(HelperSet $helperSet = null);
53868
53869
53870
53871
53872
53873
53874 public function getHelperSet();
53875
53876
53877
53878
53879
53880
53881 public function getName();
53882 }
53883 <?php
53884
53885
53886
53887
53888
53889
53890
53891
53892
53893
53894 namespace Symfony\Component\Console\Helper;
53895
53896 use Symfony\Component\Console\Command\Command;
53897 use Symfony\Component\Console\Exception\InvalidArgumentException;
53898
53899
53900
53901
53902
53903
53904 class HelperSet implements \IteratorAggregate
53905 {
53906
53907
53908
53909 private $helpers = array();
53910 private $command;
53911
53912
53913
53914
53915 public function __construct(array $helpers = array())
53916 {
53917 foreach ($helpers as $alias => $helper) {
53918 $this->set($helper, is_int($alias) ? null : $alias);
53919 }
53920 }
53921
53922
53923
53924
53925
53926
53927
53928 public function set(HelperInterface $helper, $alias = null)
53929 {
53930 $this->helpers[$helper->getName()] = $helper;
53931 if (null !== $alias) {
53932 $this->helpers[$alias] = $helper;
53933 }
53934
53935 $helper->setHelperSet($this);
53936 }
53937
53938
53939
53940
53941
53942
53943
53944
53945 public function has($name)
53946 {
53947 return isset($this->helpers[$name]);
53948 }
53949
53950
53951
53952
53953
53954
53955
53956
53957
53958
53959 public function get($name)
53960 {
53961 if (!$this->has($name)) {
53962 throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
53963 }
53964
53965 if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) {
53966 @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);
53967 } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) {
53968 @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);
53969 } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) {
53970 @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);
53971 }
53972
53973 return $this->helpers[$name];
53974 }
53975
53976 public function setCommand(Command $command = null)
53977 {
53978 $this->command = $command;
53979 }
53980
53981
53982
53983
53984
53985
53986 public function getCommand()
53987 {
53988 return $this->command;
53989 }
53990
53991
53992
53993
53994 public function getIterator()
53995 {
53996 return new \ArrayIterator($this->helpers);
53997 }
53998 }
53999 <?php
54000
54001
54002
54003
54004
54005
54006
54007
54008
54009
54010 namespace Symfony\Component\Console\Helper;
54011
54012 use Symfony\Component\Console\Input\InputInterface;
54013 use Symfony\Component\Console\Input\InputAwareInterface;
54014
54015
54016
54017
54018
54019
54020 abstract class InputAwareHelper extends Helper implements InputAwareInterface
54021 {
54022 protected $input;
54023
54024
54025
54026
54027 public function setInput(InputInterface $input)
54028 {
54029 $this->input = $input;
54030 }
54031 }
54032 <?php
54033
54034
54035
54036
54037
54038
54039
54040
54041
54042
54043 namespace Symfony\Component\Console\Helper;
54044
54045 use Symfony\Component\Console\Output\ConsoleOutputInterface;
54046 use Symfony\Component\Console\Output\OutputInterface;
54047 use Symfony\Component\Process\Exception\ProcessFailedException;
54048 use Symfony\Component\Process\Process;
54049 use Symfony\Component\Process\ProcessBuilder;
54050
54051
54052
54053
54054
54055
54056 class ProcessHelper extends Helper
54057 {
54058
54059
54060
54061
54062
54063
54064
54065
54066
54067
54068
54069
54070 public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
54071 {
54072 if ($output instanceof ConsoleOutputInterface) {
54073 $output = $output->getErrorOutput();
54074 }
54075
54076 $formatter = $this->getHelperSet()->get('debug_formatter');
54077
54078 if (is_array($cmd)) {
54079 $process = ProcessBuilder::create($cmd)->getProcess();
54080 } elseif ($cmd instanceof Process) {
54081 $process = $cmd;
54082 } else {
54083 $process = new Process($cmd);
54084 }
54085
54086 if ($verbosity <= $output->getVerbosity()) {
54087 $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
54088 }
54089
54090 if ($output->isDebug()) {
54091 $callback = $this->wrapCallback($output, $process, $callback);
54092 }
54093
54094 $process->run($callback);
54095
54096 if ($verbosity <= $output->getVerbosity()) {
54097 $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
54098 $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
54099 }
54100
54101 if (!$process->isSuccessful() && null !== $error) {
54102 $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
54103 }
54104
54105 return $process;
54106 }
54107
54108
54109
54110
54111
54112
54113
54114
54115
54116
54117
54118
54119
54120
54121
54122
54123
54124
54125
54126 public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
54127 {
54128 $process = $this->run($output, $cmd, $error, $callback);
54129
54130 if (!$process->isSuccessful()) {
54131 throw new ProcessFailedException($process);
54132 }
54133
54134 return $process;
54135 }
54136
54137
54138
54139
54140
54141
54142
54143
54144
54145
54146 public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
54147 {
54148 if ($output instanceof ConsoleOutputInterface) {
54149 $output = $output->getErrorOutput();
54150 }
54151
54152 $formatter = $this->getHelperSet()->get('debug_formatter');
54153
54154 $that = $this;
54155
54156 return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
54157 $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
54158
54159 if (null !== $callback) {
54160 call_user_func($callback, $type, $buffer);
54161 }
54162 };
54163 }
54164
54165
54166
54167
54168
54169
54170 public function escapeString($str)
54171 {
54172 return str_replace('<', '\\<', $str);
54173 }
54174
54175
54176
54177
54178 public function getName()
54179 {
54180 return 'process';
54181 }
54182 }
54183 <?php
54184
54185
54186
54187
54188
54189
54190
54191
54192
54193
54194 namespace Symfony\Component\Console\Helper;
54195
54196 use Symfony\Component\Console\Output\ConsoleOutputInterface;
54197 use Symfony\Component\Console\Output\OutputInterface;
54198 use Symfony\Component\Console\Exception\LogicException;
54199
54200
54201
54202
54203
54204
54205
54206 class ProgressBar
54207 {
54208 private $barWidth = 28;
54209 private $barChar;
54210 private $emptyBarChar = '-';
54211 private $progressChar = '>';
54212 private $format;
54213 private $internalFormat;
54214 private $redrawFreq = 1;
54215 private $output;
54216 private $step = 0;
54217 private $max;
54218 private $startTime;
54219 private $stepWidth;
54220 private $percent = 0.0;
54221 private $formatLineCount;
54222 private $messages = array();
54223 private $overwrite = true;
54224 private $firstRun = true;
54225
54226 private static $formatters;
54227 private static $formats;
54228
54229
54230
54231
54232
54233 public function __construct(OutputInterface $output, $max = 0)
54234 {
54235 if ($output instanceof ConsoleOutputInterface) {
54236 $output = $output->getErrorOutput();
54237 }
54238
54239 $this->output = $output;
54240 $this->setMaxSteps($max);
54241
54242 if (!$this->output->isDecorated()) {
54243
54244  $this->overwrite = false;
54245
54246
54247  $this->setRedrawFrequency($max / 10);
54248 }
54249
54250 $this->startTime = time();
54251 }
54252
54253
54254
54255
54256
54257
54258
54259
54260
54261 public static function setPlaceholderFormatterDefinition($name, $callable)
54262 {
54263 if (!self::$formatters) {
54264 self::$formatters = self::initPlaceholderFormatters();
54265 }
54266
54267 self::$formatters[$name] = $callable;
54268 }
54269
54270
54271
54272
54273
54274
54275
54276
54277 public static function getPlaceholderFormatterDefinition($name)
54278 {
54279 if (!self::$formatters) {
54280 self::$formatters = self::initPlaceholderFormatters();
54281 }
54282
54283 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
54284 }
54285
54286
54287
54288
54289
54290
54291
54292
54293
54294 public static function setFormatDefinition($name, $format)
54295 {
54296 if (!self::$formats) {
54297 self::$formats = self::initFormats();
54298 }
54299
54300 self::$formats[$name] = $format;
54301 }
54302
54303
54304
54305
54306
54307
54308
54309
54310 public static function getFormatDefinition($name)
54311 {
54312 if (!self::$formats) {
54313 self::$formats = self::initFormats();
54314 }
54315
54316 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
54317 }
54318
54319
54320
54321
54322
54323
54324
54325
54326
54327
54328
54329 public function setMessage($message, $name = 'message')
54330 {
54331 $this->messages[$name] = $message;
54332 }
54333
54334 public function getMessage($name = 'message')
54335 {
54336 return $this->messages[$name];
54337 }
54338
54339
54340
54341
54342
54343
54344 public function getStartTime()
54345 {
54346 return $this->startTime;
54347 }
54348
54349
54350
54351
54352
54353
54354 public function getMaxSteps()
54355 {
54356 return $this->max;
54357 }
54358
54359
54360
54361
54362
54363
54364
54365
54366 public function getStep()
54367 {
54368 @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);
54369
54370 return $this->getProgress();
54371 }
54372
54373
54374
54375
54376
54377
54378 public function getProgress()
54379 {
54380 return $this->step;
54381 }
54382
54383
54384
54385
54386
54387
54388
54389
54390 public function getStepWidth()
54391 {
54392 return $this->stepWidth;
54393 }
54394
54395
54396
54397
54398
54399
54400 public function getProgressPercent()
54401 {
54402 return $this->percent;
54403 }
54404
54405
54406
54407
54408
54409
54410 public function setBarWidth($size)
54411 {
54412 $this->barWidth = (int) $size;
54413 }
54414
54415
54416
54417
54418
54419
54420 public function getBarWidth()
54421 {
54422 return $this->barWidth;
54423 }
54424
54425
54426
54427
54428
54429
54430 public function setBarCharacter($char)
54431 {
54432 $this->barChar = $char;
54433 }
54434
54435
54436
54437
54438
54439
54440 public function getBarCharacter()
54441 {
54442 if (null === $this->barChar) {
54443 return $this->max ? '=' : $this->emptyBarChar;
54444 }
54445
54446 return $this->barChar;
54447 }
54448
54449
54450
54451
54452
54453
54454 public function setEmptyBarCharacter($char)
54455 {
54456 $this->emptyBarChar = $char;
54457 }
54458
54459
54460
54461
54462
54463
54464 public function getEmptyBarCharacter()
54465 {
54466 return $this->emptyBarChar;
54467 }
54468
54469
54470
54471
54472
54473
54474 public function setProgressCharacter($char)
54475 {
54476 $this->progressChar = $char;
54477 }
54478
54479
54480
54481
54482
54483
54484 public function getProgressCharacter()
54485 {
54486 return $this->progressChar;
54487 }
54488
54489
54490
54491
54492
54493
54494 public function setFormat($format)
54495 {
54496 $this->format = null;
54497 $this->internalFormat = $format;
54498 }
54499
54500
54501
54502
54503
54504
54505 public function setRedrawFrequency($freq)
54506 {
54507 $this->redrawFreq = max((int) $freq, 1);
54508 }
54509
54510
54511
54512
54513
54514
54515 public function start($max = null)
54516 {
54517 $this->startTime = time();
54518 $this->step = 0;
54519 $this->percent = 0.0;
54520
54521 if (null !== $max) {
54522 $this->setMaxSteps($max);
54523 }
54524
54525 $this->display();
54526 }
54527
54528
54529
54530
54531
54532
54533
54534
54535 public function advance($step = 1)
54536 {
54537 $this->setProgress($this->step + $step);
54538 }
54539
54540
54541
54542
54543
54544
54545
54546
54547
54548
54549 public function setCurrent($step)
54550 {
54551 @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);
54552
54553 $this->setProgress($step);
54554 }
54555
54556
54557
54558
54559
54560
54561 public function setOverwrite($overwrite)
54562 {
54563 $this->overwrite = (bool) $overwrite;
54564 }
54565
54566
54567
54568
54569
54570
54571
54572
54573 public function setProgress($step)
54574 {
54575 $step = (int) $step;
54576 if ($step < $this->step) {
54577 throw new LogicException('You can\'t regress the progress bar.');
54578 }
54579
54580 if ($this->max && $step > $this->max) {
54581 $this->max = $step;
54582 }
54583
54584 $prevPeriod = (int) ($this->step / $this->redrawFreq);
54585 $currPeriod = (int) ($step / $this->redrawFreq);
54586 $this->step = $step;
54587 $this->percent = $this->max ? (float) $this->step / $this->max : 0;
54588 if ($prevPeriod !== $currPeriod || $this->max === $step) {
54589 $this->display();
54590 }
54591 }
54592
54593
54594
54595
54596 public function finish()
54597 {
54598 if (!$this->max) {
54599 $this->max = $this->step;
54600 }
54601
54602 if ($this->step === $this->max && !$this->overwrite) {
54603
54604  return;
54605 }
54606
54607 $this->setProgress($this->max);
54608 }
54609
54610
54611
54612
54613 public function display()
54614 {
54615 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
54616 return;
54617 }
54618
54619 if (null === $this->format) {
54620 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
54621 }
54622
54623
54624  $self = $this;
54625 $output = $this->output;
54626 $messages = $this->messages;
54627 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
54628 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
54629 $text = call_user_func($formatter, $self, $output);
54630 } elseif (isset($messages[$matches[1]])) {
54631 $text = $messages[$matches[1]];
54632 } else {
54633 return $matches[0];
54634 }
54635
54636 if (isset($matches[2])) {
54637 $text = sprintf('%'.$matches[2], $text);
54638 }
54639
54640 return $text;
54641 }, $this->format));
54642 }
54643
54644
54645
54646
54647
54648
54649
54650
54651 public function clear()
54652 {
54653 if (!$this->overwrite) {
54654 return;
54655 }
54656
54657 if (null === $this->format) {
54658 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
54659 }
54660
54661 $this->overwrite('');
54662 }
54663
54664
54665
54666
54667
54668
54669 private function setRealFormat($format)
54670 {
54671
54672  if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
54673 $this->format = self::getFormatDefinition($format.'_nomax');
54674 } elseif (null !== self::getFormatDefinition($format)) {
54675 $this->format = self::getFormatDefinition($format);
54676 } else {
54677 $this->format = $format;
54678 }
54679
54680 $this->formatLineCount = substr_count($this->format, "\n");
54681 }
54682
54683
54684
54685
54686
54687
54688 private function setMaxSteps($max)
54689 {
54690 $this->max = max(0, (int) $max);
54691 $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
54692 }
54693
54694
54695
54696
54697
54698
54699 private function overwrite($message)
54700 {
54701 if ($this->overwrite) {
54702 if (!$this->firstRun) {
54703
54704  $this->output->write("\x0D");
54705
54706
54707  $this->output->write("\x1B[2K");
54708
54709
54710  if ($this->formatLineCount > 0) {
54711 $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
54712 }
54713 }
54714 } elseif ($this->step > 0) {
54715 $this->output->writeln('');
54716 }
54717
54718 $this->firstRun = false;
54719
54720 $this->output->write($message);
54721 }
54722
54723 private function determineBestFormat()
54724 {
54725 switch ($this->output->getVerbosity()) {
54726
54727  case OutputInterface::VERBOSITY_VERBOSE:
54728 return $this->max ? 'verbose' : 'verbose_nomax';
54729 case OutputInterface::VERBOSITY_VERY_VERBOSE:
54730 return $this->max ? 'very_verbose' : 'very_verbose_nomax';
54731 case OutputInterface::VERBOSITY_DEBUG:
54732 return $this->max ? 'debug' : 'debug_nomax';
54733 default:
54734 return $this->max ? 'normal' : 'normal_nomax';
54735 }
54736 }
54737
54738 private static function initPlaceholderFormatters()
54739 {
54740 return array(
54741 'bar' => function (ProgressBar $bar, OutputInterface $output) {
54742 $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
54743 $display = str_repeat($bar->getBarCharacter(), $completeBars);
54744 if ($completeBars < $bar->getBarWidth()) {
54745 $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
54746 $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
54747 }
54748
54749 return $display;
54750 },
54751 'elapsed' => function (ProgressBar $bar) {
54752 return Helper::formatTime(time() - $bar->getStartTime());
54753 },
54754 'remaining' => function (ProgressBar $bar) {
54755 if (!$bar->getMaxSteps()) {
54756 throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
54757 }
54758
54759 if (!$bar->getProgress()) {
54760 $remaining = 0;
54761 } else {
54762 $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
54763 }
54764
54765 return Helper::formatTime($remaining);
54766 },
54767 'estimated' => function (ProgressBar $bar) {
54768 if (!$bar->getMaxSteps()) {
54769 throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
54770 }
54771
54772 if (!$bar->getProgress()) {
54773 $estimated = 0;
54774 } else {
54775 $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
54776 }
54777
54778 return Helper::formatTime($estimated);
54779 },
54780 'memory' => function (ProgressBar $bar) {
54781 return Helper::formatMemory(memory_get_usage(true));
54782 },
54783 'current' => function (ProgressBar $bar) {
54784 return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
54785 },
54786 'max' => function (ProgressBar $bar) {
54787 return $bar->getMaxSteps();
54788 },
54789 'percent' => function (ProgressBar $bar) {
54790 return floor($bar->getProgressPercent() * 100);
54791 },
54792 );
54793 }
54794
54795 private static function initFormats()
54796 {
54797 return array(
54798 'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
54799 'normal_nomax' => ' %current% [%bar%]',
54800
54801 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
54802 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
54803
54804 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
54805 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
54806
54807 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
54808 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
54809 );
54810 }
54811 }
54812 <?php
54813
54814
54815
54816
54817
54818
54819
54820
54821
54822
54823 namespace Symfony\Component\Console\Helper;
54824
54825 use Symfony\Component\Console\Output\NullOutput;
54826 use Symfony\Component\Console\Output\ConsoleOutputInterface;
54827 use Symfony\Component\Console\Output\OutputInterface;
54828 use Symfony\Component\Console\Exception\LogicException;
54829
54830
54831
54832
54833
54834
54835
54836
54837
54838
54839 class ProgressHelper extends Helper
54840 {
54841 const FORMAT_QUIET = ' %percent%%';
54842 const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
54843 const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
54844 const FORMAT_QUIET_NOMAX = ' %current%';
54845 const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
54846 const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
54847
54848
54849  private $barWidth = 28;
54850 private $barChar = '=';
54851 private $emptyBarChar = '-';
54852 private $progressChar = '>';
54853 private $format = null;
54854 private $redrawFreq = 1;
54855
54856 private $lastMessagesLength;
54857 private $barCharOriginal;
54858
54859
54860
54861
54862 private $output;
54863
54864
54865
54866
54867
54868
54869 private $current;
54870
54871
54872
54873
54874
54875
54876 private $max;
54877
54878
54879
54880
54881
54882
54883 private $startTime;
54884
54885
54886
54887
54888
54889
54890 private $defaultFormatVars = array(
54891 'current',
54892 'max',
54893 'bar',
54894 'percent',
54895 'elapsed',
54896 );
54897
54898
54899
54900
54901
54902
54903 private $formatVars;
54904
54905
54906
54907
54908
54909
54910 private $widths = array(
54911 'current' => 4,
54912 'max' => 4,
54913 'percent' => 3,
54914 'elapsed' => 6,
54915 );
54916
54917
54918
54919
54920
54921
54922 private $timeFormats = array(
54923 array(0, '???'),
54924 array(2, '1 sec'),
54925 array(59, 'secs', 1),
54926 array(60, '1 min'),
54927 array(3600, 'mins', 60),
54928 array(5400, '1 hr'),
54929 array(86400, 'hrs', 3600),
54930 array(129600, '1 day'),
54931 array(604800, 'days', 86400),
54932 );
54933
54934 public function __construct($triggerDeprecationError = true)
54935 {
54936 if ($triggerDeprecationError) {
54937 @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);
54938 }
54939 }
54940
54941
54942
54943
54944
54945
54946 public function setBarWidth($size)
54947 {
54948 $this->barWidth = (int) $size;
54949 }
54950
54951
54952
54953
54954
54955
54956 public function setBarCharacter($char)
54957 {
54958 $this->barChar = $char;
54959 }
54960
54961
54962
54963
54964
54965
54966 public function setEmptyBarCharacter($char)
54967 {
54968 $this->emptyBarChar = $char;
54969 }
54970
54971
54972
54973
54974
54975
54976 public function setProgressCharacter($char)
54977 {
54978 $this->progressChar = $char;
54979 }
54980
54981
54982
54983
54984
54985
54986 public function setFormat($format)
54987 {
54988 $this->format = $format;
54989 }
54990
54991
54992
54993
54994
54995
54996 public function setRedrawFrequency($freq)
54997 {
54998 $this->redrawFreq = (int) $freq;
54999 }
55000
55001
55002
55003
55004
55005
55006
55007 public function start(OutputInterface $output, $max = null)
55008 {
55009 if ($output instanceof ConsoleOutputInterface) {
55010 $output = $output->getErrorOutput();
55011 }
55012
55013 $this->startTime = time();
55014 $this->current = 0;
55015 $this->max = (int) $max;
55016
55017
55018  $this->output = $output->isDecorated() ? $output : new NullOutput();
55019 $this->lastMessagesLength = 0;
55020 $this->barCharOriginal = '';
55021
55022 if (null === $this->format) {
55023 switch ($output->getVerbosity()) {
55024 case OutputInterface::VERBOSITY_QUIET:
55025 $this->format = self::FORMAT_QUIET_NOMAX;
55026 if ($this->max > 0) {
55027 $this->format = self::FORMAT_QUIET;
55028 }
55029 break;
55030 case OutputInterface::VERBOSITY_VERBOSE:
55031 case OutputInterface::VERBOSITY_VERY_VERBOSE:
55032 case OutputInterface::VERBOSITY_DEBUG:
55033 $this->format = self::FORMAT_VERBOSE_NOMAX;
55034 if ($this->max > 0) {
55035 $this->format = self::FORMAT_VERBOSE;
55036 }
55037 break;
55038 default:
55039 $this->format = self::FORMAT_NORMAL_NOMAX;
55040 if ($this->max > 0) {
55041 $this->format = self::FORMAT_NORMAL;
55042 }
55043 break;
55044 }
55045 }
55046
55047 $this->initialize();
55048 }
55049
55050
55051
55052
55053
55054
55055
55056
55057
55058 public function advance($step = 1, $redraw = false)
55059 {
55060 $this->setCurrent($this->current + $step, $redraw);
55061 }
55062
55063
55064
55065
55066
55067
55068
55069
55070
55071 public function setCurrent($current, $redraw = false)
55072 {
55073 if (null === $this->startTime) {
55074 throw new LogicException('You must start the progress bar before calling setCurrent().');
55075 }
55076
55077 $current = (int) $current;
55078
55079 if ($current < $this->current) {
55080 throw new LogicException('You can\'t regress the progress bar');
55081 }
55082
55083 if (0 === $this->current) {
55084 $redraw = true;
55085 }
55086
55087 $prevPeriod = (int) ($this->current / $this->redrawFreq);
55088
55089 $this->current = $current;
55090
55091 $currPeriod = (int) ($this->current / $this->redrawFreq);
55092 if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
55093 $this->display();
55094 }
55095 }
55096
55097
55098
55099
55100
55101
55102
55103
55104 public function display($finish = false)
55105 {
55106 if (null === $this->startTime) {
55107 throw new LogicException('You must start the progress bar before calling display().');
55108 }
55109
55110 $message = $this->format;
55111 foreach ($this->generate($finish) as $name => $value) {
55112 $message = str_replace("%{$name}%", $value, $message);
55113 }
55114 $this->overwrite($this->output, $message);
55115 }
55116
55117
55118
55119
55120
55121
55122
55123
55124 public function clear()
55125 {
55126 $this->overwrite($this->output, '');
55127 }
55128
55129
55130
55131
55132 public function finish()
55133 {
55134 if (null === $this->startTime) {
55135 throw new LogicException('You must start the progress bar before calling finish().');
55136 }
55137
55138 if (null !== $this->startTime) {
55139 if (!$this->max) {
55140 $this->barChar = $this->barCharOriginal;
55141 $this->display(true);
55142 }
55143 $this->startTime = null;
55144 $this->output->writeln('');
55145 $this->output = null;
55146 }
55147 }
55148
55149
55150
55151
55152 private function initialize()
55153 {
55154 $this->formatVars = array();
55155 foreach ($this->defaultFormatVars as $var) {
55156 if (false !== strpos($this->format, "%{$var}%")) {
55157 $this->formatVars[$var] = true;
55158 }
55159 }
55160
55161 if ($this->max > 0) {
55162 $this->widths['max'] = $this->strlen($this->max);
55163 $this->widths['current'] = $this->widths['max'];
55164 } else {
55165 $this->barCharOriginal = $this->barChar;
55166 $this->barChar = $this->emptyBarChar;
55167 }
55168 }
55169
55170
55171
55172
55173
55174
55175
55176
55177 private function generate($finish = false)
55178 {
55179 $vars = array();
55180 $percent = 0;
55181 if ($this->max > 0) {
55182 $percent = (float) $this->current / $this->max;
55183 }
55184
55185 if (isset($this->formatVars['bar'])) {
55186 if ($this->max > 0) {
55187 $completeBars = floor($percent * $this->barWidth);
55188 } else {
55189 if (!$finish) {
55190 $completeBars = floor($this->current % $this->barWidth);
55191 } else {
55192 $completeBars = $this->barWidth;
55193 }
55194 }
55195
55196 $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
55197 $bar = str_repeat($this->barChar, $completeBars);
55198 if ($completeBars < $this->barWidth) {
55199 $bar .= $this->progressChar;
55200 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
55201 }
55202
55203 $vars['bar'] = $bar;
55204 }
55205
55206 if (isset($this->formatVars['elapsed'])) {
55207 $elapsed = time() - $this->startTime;
55208 $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
55209 }
55210
55211 if (isset($this->formatVars['current'])) {
55212 $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
55213 }
55214
55215 if (isset($this->formatVars['max'])) {
55216 $vars['max'] = $this->max;
55217 }
55218
55219 if (isset($this->formatVars['percent'])) {
55220 $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
55221 }
55222
55223 return $vars;
55224 }
55225
55226
55227
55228
55229
55230
55231
55232
55233 private function humaneTime($secs)
55234 {
55235 $text = '';
55236 foreach ($this->timeFormats as $format) {
55237 if ($secs < $format[0]) {
55238 if (2 == count($format)) {
55239 $text = $format[1];
55240 break;
55241 } else {
55242 $text = ceil($secs / $format[2]).' '.$format[1];
55243 break;
55244 }
55245 }
55246 }
55247
55248 return $text;
55249 }
55250
55251
55252
55253
55254
55255
55256
55257 private function overwrite(OutputInterface $output, $message)
55258 {
55259 $length = $this->strlen($message);
55260
55261
55262  if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
55263 $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
55264 }
55265
55266
55267  $output->write("\x0D");
55268 $output->write($message);
55269
55270 $this->lastMessagesLength = $this->strlen($message);
55271 }
55272
55273
55274
55275
55276 public function getName()
55277 {
55278 return 'progress';
55279 }
55280 }
55281 <?php
55282
55283
55284
55285
55286
55287
55288
55289
55290
55291
55292 namespace Symfony\Component\Console\Helper;
55293
55294 use Symfony\Component\Console\Exception\InvalidArgumentException;
55295 use Symfony\Component\Console\Exception\LogicException;
55296 use Symfony\Component\Console\Output\OutputInterface;
55297
55298
55299
55300
55301 class ProgressIndicator
55302 {
55303 private $output;
55304 private $startTime;
55305 private $format;
55306 private $message;
55307 private $indicatorValues;
55308 private $indicatorCurrent;
55309 private $indicatorChangeInterval;
55310 private $indicatorUpdateTime;
55311 private $started = false;
55312
55313 private static $formatters;
55314 private static $formats;
55315
55316
55317
55318
55319
55320
55321
55322 public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
55323 {
55324 $this->output = $output;
55325
55326 if (null === $format) {
55327 $format = $this->determineBestFormat();
55328 }
55329
55330 if (null === $indicatorValues) {
55331 $indicatorValues = array('-', '\\', '|', '/');
55332 }
55333
55334 $indicatorValues = array_values($indicatorValues);
55335
55336 if (2 > count($indicatorValues)) {
55337 throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
55338 }
55339
55340 $this->format = self::getFormatDefinition($format);
55341 $this->indicatorChangeInterval = $indicatorChangeInterval;
55342 $this->indicatorValues = $indicatorValues;
55343 $this->startTime = time();
55344 }
55345
55346
55347
55348
55349
55350
55351 public function setMessage($message)
55352 {
55353 $this->message = $message;
55354
55355 $this->display();
55356 }
55357
55358
55359
55360
55361
55362
55363
55364
55365 public function getMessage()
55366 {
55367 return $this->message;
55368 }
55369
55370
55371
55372
55373
55374
55375
55376
55377 public function getStartTime()
55378 {
55379 return $this->startTime;
55380 }
55381
55382
55383
55384
55385
55386
55387
55388
55389 public function getCurrentValue()
55390 {
55391 return $this->indicatorValues[$this->indicatorCurrent % count($this->indicatorValues)];
55392 }
55393
55394
55395
55396
55397
55398
55399 public function start($message)
55400 {
55401 if ($this->started) {
55402 throw new LogicException('Progress indicator already started.');
55403 }
55404
55405 $this->message = $message;
55406 $this->started = true;
55407 $this->startTime = time();
55408 $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
55409 $this->indicatorCurrent = 0;
55410
55411 $this->display();
55412 }
55413
55414
55415
55416
55417 public function advance()
55418 {
55419 if (!$this->started) {
55420 throw new LogicException('Progress indicator has not yet been started.');
55421 }
55422
55423 if (!$this->output->isDecorated()) {
55424 return;
55425 }
55426
55427 $currentTime = $this->getCurrentTimeInMilliseconds();
55428
55429 if ($currentTime < $this->indicatorUpdateTime) {
55430 return;
55431 }
55432
55433 $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
55434 ++$this->indicatorCurrent;
55435
55436 $this->display();
55437 }
55438
55439
55440
55441
55442
55443
55444 public function finish($message)
55445 {
55446 if (!$this->started) {
55447 throw new LogicException('Progress indicator has not yet been started.');
55448 }
55449
55450 $this->message = $message;
55451 $this->display();
55452 $this->output->writeln('');
55453 $this->started = false;
55454 }
55455
55456
55457
55458
55459
55460
55461
55462
55463 public static function getFormatDefinition($name)
55464 {
55465 if (!self::$formats) {
55466 self::$formats = self::initFormats();
55467 }
55468
55469 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
55470 }
55471
55472
55473
55474
55475
55476
55477
55478
55479
55480 public static function setPlaceholderFormatterDefinition($name, $callable)
55481 {
55482 if (!self::$formatters) {
55483 self::$formatters = self::initPlaceholderFormatters();
55484 }
55485
55486 self::$formatters[$name] = $callable;
55487 }
55488
55489
55490
55491
55492
55493
55494
55495
55496 public static function getPlaceholderFormatterDefinition($name)
55497 {
55498 if (!self::$formatters) {
55499 self::$formatters = self::initPlaceholderFormatters();
55500 }
55501
55502 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
55503 }
55504
55505 private function display()
55506 {
55507 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
55508 return;
55509 }
55510
55511 $self = $this;
55512
55513 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
55514 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
55515 return call_user_func($formatter, $self);
55516 }
55517
55518 return $matches[0];
55519 }, $this->format));
55520 }
55521
55522 private function determineBestFormat()
55523 {
55524 switch ($this->output->getVerbosity()) {
55525
55526  case OutputInterface::VERBOSITY_VERBOSE:
55527 return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
55528 case OutputInterface::VERBOSITY_VERY_VERBOSE:
55529 case OutputInterface::VERBOSITY_DEBUG:
55530 return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
55531 default:
55532 return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
55533 }
55534 }
55535
55536
55537
55538
55539
55540
55541 private function overwrite($message)
55542 {
55543 if ($this->output->isDecorated()) {
55544 $this->output->write("\x0D\x1B[2K");
55545 $this->output->write($message);
55546 } else {
55547 $this->output->writeln($message);
55548 }
55549 }
55550
55551 private function getCurrentTimeInMilliseconds()
55552 {
55553 return round(microtime(true) * 1000);
55554 }
55555
55556 private static function initPlaceholderFormatters()
55557 {
55558 return array(
55559 'indicator' => function (ProgressIndicator $indicator) {
55560 return $indicator->getCurrentValue();
55561 },
55562 'message' => function (ProgressIndicator $indicator) {
55563 return $indicator->getMessage();
55564 },
55565 'elapsed' => function (ProgressIndicator $indicator) {
55566 return Helper::formatTime(time() - $indicator->getStartTime());
55567 },
55568 'memory' => function () {
55569 return Helper::formatMemory(memory_get_usage(true));
55570 },
55571 );
55572 }
55573
55574 private static function initFormats()
55575 {
55576 return array(
55577 'normal' => ' %indicator% %message%',
55578 'normal_no_ansi' => ' %message%',
55579
55580 'verbose' => ' %indicator% %message% (%elapsed:6s%)',
55581 'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
55582
55583 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
55584 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
55585 );
55586 }
55587 }
55588 <?php
55589
55590
55591
55592
55593
55594
55595
55596
55597
55598
55599 namespace Symfony\Component\Console\Helper;
55600
55601 use Symfony\Component\Console\Exception\InvalidArgumentException;
55602 use Symfony\Component\Console\Exception\RuntimeException;
55603 use Symfony\Component\Console\Formatter\OutputFormatter;
55604 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
55605 use Symfony\Component\Console\Input\InputInterface;
55606 use Symfony\Component\Console\Output\ConsoleOutputInterface;
55607 use Symfony\Component\Console\Output\OutputInterface;
55608 use Symfony\Component\Console\Question\Question;
55609 use Symfony\Component\Console\Question\ChoiceQuestion;
55610
55611
55612
55613
55614
55615
55616 class QuestionHelper extends Helper
55617 {
55618 private $inputStream;
55619 private static $shell;
55620 private static $stty;
55621
55622
55623
55624
55625
55626
55627
55628
55629 public function ask(InputInterface $input, OutputInterface $output, Question $question)
55630 {
55631 if ($output instanceof ConsoleOutputInterface) {
55632 $output = $output->getErrorOutput();
55633 }
55634
55635 if (!$input->isInteractive()) {
55636 if ($question instanceof ChoiceQuestion) {
55637 $choices = $question->getChoices();
55638
55639 return $choices[$question->getDefault()];
55640 }
55641
55642 return $question->getDefault();
55643 }
55644
55645 if (!$question->getValidator()) {
55646 return $this->doAsk($output, $question);
55647 }
55648
55649 $that = $this;
55650
55651 $interviewer = function () use ($output, $question, $that) {
55652 return $that->doAsk($output, $question);
55653 };
55654
55655 return $this->validateAttempts($interviewer, $output, $question);
55656 }
55657
55658
55659
55660
55661
55662
55663
55664
55665
55666
55667 public function setInputStream($stream)
55668 {
55669 if (!is_resource($stream)) {
55670 throw new InvalidArgumentException('Input stream must be a valid resource.');
55671 }
55672
55673 $this->inputStream = $stream;
55674 }
55675
55676
55677
55678
55679
55680
55681 public function getInputStream()
55682 {
55683 return $this->inputStream;
55684 }
55685
55686
55687
55688
55689 public function getName()
55690 {
55691 return 'question';
55692 }
55693
55694
55695
55696
55697
55698
55699
55700
55701
55702
55703 public function doAsk(OutputInterface $output, Question $question)
55704 {
55705 $this->writePrompt($output, $question);
55706
55707 $inputStream = $this->inputStream ?: STDIN;
55708 $autocomplete = $question->getAutocompleterValues();
55709
55710 if (null === $autocomplete || !$this->hasSttyAvailable()) {
55711 $ret = false;
55712 if ($question->isHidden()) {
55713 try {
55714 $ret = trim($this->getHiddenResponse($output, $inputStream));
55715 } catch (RuntimeException $e) {
55716 if (!$question->isHiddenFallback()) {
55717 throw $e;
55718 }
55719 }
55720 }
55721
55722 if (false === $ret) {
55723 $ret = fgets($inputStream, 4096);
55724 if (false === $ret) {
55725 throw new RuntimeException('Aborted');
55726 }
55727 $ret = trim($ret);
55728 }
55729 } else {
55730 $ret = trim($this->autocomplete($output, $question, $inputStream, is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
55731 }
55732
55733 $ret = strlen($ret) > 0 ? $ret : $question->getDefault();
55734
55735 if ($normalizer = $question->getNormalizer()) {
55736 return $normalizer($ret);
55737 }
55738
55739 return $ret;
55740 }
55741
55742
55743
55744
55745 protected function writePrompt(OutputInterface $output, Question $question)
55746 {
55747 $message = $question->getQuestion();
55748
55749 if ($question instanceof ChoiceQuestion) {
55750 $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
55751
55752 $messages = (array) $question->getQuestion();
55753 foreach ($question->getChoices() as $key => $value) {
55754 $width = $maxWidth - $this->strlen($key);
55755 $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
55756 }
55757
55758 $output->writeln($messages);
55759
55760 $message = $question->getPrompt();
55761 }
55762
55763 $output->write($message);
55764 }
55765
55766
55767
55768
55769 protected function writeError(OutputInterface $output, \Exception $error)
55770 {
55771 if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
55772 $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
55773 } else {
55774 $message = '<error>'.$error->getMessage().'</error>';
55775 }
55776
55777 $output->writeln($message);
55778 }
55779
55780
55781
55782
55783
55784
55785
55786
55787
55788
55789
55790 private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete)
55791 {
55792 $ret = '';
55793
55794 $i = 0;
55795 $ofs = -1;
55796 $matches = $autocomplete;
55797 $numMatches = count($matches);
55798
55799 $sttyMode = shell_exec('stty -g');
55800
55801
55802  shell_exec('stty -icanon -echo');
55803
55804
55805  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
55806
55807
55808  while (!feof($inputStream)) {
55809 $c = fread($inputStream, 1);
55810
55811
55812  if ("\177" === $c) {
55813 if (0 === $numMatches && 0 !== $i) {
55814 --$i;
55815
55816  $output->write("\033[1D");
55817 }
55818
55819 if (0 === $i) {
55820 $ofs = -1;
55821 $matches = $autocomplete;
55822 $numMatches = count($matches);
55823 } else {
55824 $numMatches = 0;
55825 }
55826
55827
55828  $ret = substr($ret, 0, $i);
55829 } elseif ("\033" === $c) {
55830
55831  $c .= fread($inputStream, 2);
55832
55833
55834  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
55835 if ('A' === $c[2] && -1 === $ofs) {
55836 $ofs = 0;
55837 }
55838
55839 if (0 === $numMatches) {
55840 continue;
55841 }
55842
55843 $ofs += ('A' === $c[2]) ? -1 : 1;
55844 $ofs = ($numMatches + $ofs) % $numMatches;
55845 }
55846 } elseif (ord($c) < 32) {
55847 if ("\t" === $c || "\n" === $c) {
55848 if ($numMatches > 0 && -1 !== $ofs) {
55849 $ret = $matches[$ofs];
55850
55851  $output->write(substr($ret, $i));
55852 $i = strlen($ret);
55853 }
55854
55855 if ("\n" === $c) {
55856 $output->write($c);
55857 break;
55858 }
55859
55860 $numMatches = 0;
55861 }
55862
55863 continue;
55864 } else {
55865 $output->write($c);
55866 $ret .= $c;
55867 ++$i;
55868
55869 $numMatches = 0;
55870 $ofs = 0;
55871
55872 foreach ($autocomplete as $value) {
55873
55874  if (0 === strpos($value, $ret)) {
55875 $matches[$numMatches++] = $value;
55876 }
55877 }
55878 }
55879
55880
55881  $output->write("\033[K");
55882
55883 if ($numMatches > 0 && -1 !== $ofs) {
55884
55885  $output->write("\0337");
55886
55887  $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>');
55888
55889  $output->write("\0338");
55890 }
55891 }
55892
55893
55894  shell_exec(sprintf('stty %s', $sttyMode));
55895
55896 return $ret;
55897 }
55898
55899
55900
55901
55902
55903
55904
55905
55906
55907
55908
55909 private function getHiddenResponse(OutputInterface $output, $inputStream)
55910 {
55911 if ('\\' === DIRECTORY_SEPARATOR) {
55912 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
55913
55914
55915  if ('phar:' === substr(__FILE__, 0, 5)) {
55916 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
55917 copy($exe, $tmpExe);
55918 $exe = $tmpExe;
55919 }
55920
55921 $value = rtrim(shell_exec($exe));
55922 $output->writeln('');
55923
55924 if (isset($tmpExe)) {
55925 unlink($tmpExe);
55926 }
55927
55928 return $value;
55929 }
55930
55931 if ($this->hasSttyAvailable()) {
55932 $sttyMode = shell_exec('stty -g');
55933
55934 shell_exec('stty -echo');
55935 $value = fgets($inputStream, 4096);
55936 shell_exec(sprintf('stty %s', $sttyMode));
55937
55938 if (false === $value) {
55939 throw new RuntimeException('Aborted');
55940 }
55941
55942 $value = trim($value);
55943 $output->writeln('');
55944
55945 return $value;
55946 }
55947
55948 if (false !== $shell = $this->getShell()) {
55949 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
55950 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
55951 $value = rtrim(shell_exec($command));
55952 $output->writeln('');
55953
55954 return $value;
55955 }
55956
55957 throw new RuntimeException('Unable to hide the response.');
55958 }
55959
55960
55961
55962
55963
55964
55965
55966
55967
55968
55969
55970
55971 private function validateAttempts($interviewer, OutputInterface $output, Question $question)
55972 {
55973 $error = null;
55974 $attempts = $question->getMaxAttempts();
55975 while (null === $attempts || $attempts--) {
55976 if (null !== $error) {
55977 $this->writeError($output, $error);
55978 }
55979
55980 try {
55981 return call_user_func($question->getValidator(), $interviewer());
55982 } catch (RuntimeException $e) {
55983 throw $e;
55984 } catch (\Exception $error) {
55985 }
55986 }
55987
55988 throw $error;
55989 }
55990
55991
55992
55993
55994
55995
55996 private function getShell()
55997 {
55998 if (null !== self::$shell) {
55999 return self::$shell;
56000 }
56001
56002 self::$shell = false;
56003
56004 if (file_exists('/usr/bin/env')) {
56005
56006  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
56007 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
56008 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
56009 self::$shell = $sh;
56010 break;
56011 }
56012 }
56013 }
56014
56015 return self::$shell;
56016 }
56017
56018
56019
56020
56021
56022
56023 private function hasSttyAvailable()
56024 {
56025 if (null !== self::$stty) {
56026 return self::$stty;
56027 }
56028
56029 exec('stty 2>&1', $output, $exitcode);
56030
56031 return self::$stty = 0 === $exitcode;
56032 }
56033 }
56034 <?php
56035
56036
56037
56038
56039
56040
56041
56042
56043
56044
56045 namespace Symfony\Component\Console\Helper;
56046
56047 use Symfony\Component\Console\Exception\LogicException;
56048 use Symfony\Component\Console\Input\InputInterface;
56049 use Symfony\Component\Console\Output\OutputInterface;
56050 use Symfony\Component\Console\Question\ChoiceQuestion;
56051 use Symfony\Component\Console\Question\ConfirmationQuestion;
56052 use Symfony\Component\Console\Question\Question;
56053 use Symfony\Component\Console\Style\SymfonyStyle;
56054 use Symfony\Component\Console\Formatter\OutputFormatter;
56055
56056
56057
56058
56059
56060
56061 class SymfonyQuestionHelper extends QuestionHelper
56062 {
56063
56064
56065
56066 public function ask(InputInterface $input, OutputInterface $output, Question $question)
56067 {
56068 $validator = $question->getValidator();
56069 $question->setValidator(function ($value) use ($validator) {
56070 if (null !== $validator) {
56071 $value = $validator($value);
56072 } else {
56073
56074  if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
56075 throw new LogicException('A value is required.');
56076 }
56077 }
56078
56079 return $value;
56080 });
56081
56082 return parent::ask($input, $output, $question);
56083 }
56084
56085
56086
56087
56088 protected function writePrompt(OutputInterface $output, Question $question)
56089 {
56090 $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
56091 $default = $question->getDefault();
56092
56093 switch (true) {
56094 case null === $default:
56095 $text = sprintf(' <info>%s</info>:', $text);
56096
56097 break;
56098
56099 case $question instanceof ConfirmationQuestion:
56100 $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
56101
56102 break;
56103
56104 case $question instanceof ChoiceQuestion && $question->isMultiselect():
56105 $choices = $question->getChoices();
56106 $default = explode(',', $default);
56107
56108 foreach ($default as $key => $value) {
56109 $default[$key] = $choices[trim($value)];
56110 }
56111
56112 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
56113
56114 break;
56115
56116 case $question instanceof ChoiceQuestion:
56117 $choices = $question->getChoices();
56118 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default]));
56119
56120 break;
56121
56122 default:
56123 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
56124 }
56125
56126 $output->writeln($text);
56127
56128 if ($question instanceof ChoiceQuestion) {
56129 $width = max(array_map('strlen', array_keys($question->getChoices())));
56130
56131 foreach ($question->getChoices() as $key => $value) {
56132 $output->writeln(sprintf("  [<comment>%-${width}s</comment>] %s", $key, $value));
56133 }
56134 }
56135
56136 $output->write(' > ');
56137 }
56138
56139
56140
56141
56142 protected function writeError(OutputInterface $output, \Exception $error)
56143 {
56144 if ($output instanceof SymfonyStyle) {
56145 $output->newLine();
56146 $output->error($error->getMessage());
56147
56148 return;
56149 }
56150
56151 parent::writeError($output, $error);
56152 }
56153 }
56154 <?php
56155
56156
56157
56158
56159
56160
56161
56162
56163
56164
56165 namespace Symfony\Component\Console\Helper;
56166
56167 use Symfony\Component\Console\Output\OutputInterface;
56168 use Symfony\Component\Console\Exception\InvalidArgumentException;
56169
56170
56171
56172
56173
56174
56175
56176
56177
56178 class Table
56179 {
56180
56181
56182
56183 private $headers = array();
56184
56185
56186
56187
56188 private $rows = array();
56189
56190
56191
56192
56193 private $columnWidths = array();
56194
56195
56196
56197
56198
56199
56200 private $numberOfColumns;
56201
56202
56203
56204
56205 private $output;
56206
56207
56208
56209
56210 private $style;
56211
56212
56213
56214
56215 private $columnStyles = array();
56216
56217 private static $styles;
56218
56219 public function __construct(OutputInterface $output)
56220 {
56221 $this->output = $output;
56222
56223 if (!self::$styles) {
56224 self::$styles = self::initStyles();
56225 }
56226
56227 $this->setStyle('default');
56228 }
56229
56230
56231
56232
56233
56234
56235
56236 public static function setStyleDefinition($name, TableStyle $style)
56237 {
56238 if (!self::$styles) {
56239 self::$styles = self::initStyles();
56240 }
56241
56242 self::$styles[$name] = $style;
56243 }
56244
56245
56246
56247
56248
56249
56250
56251
56252 public static function getStyleDefinition($name)
56253 {
56254 if (!self::$styles) {
56255 self::$styles = self::initStyles();
56256 }
56257
56258 if (isset(self::$styles[$name])) {
56259 return self::$styles[$name];
56260 }
56261
56262 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
56263 }
56264
56265
56266
56267
56268
56269
56270
56271
56272 public function setStyle($name)
56273 {
56274 $this->style = $this->resolveStyle($name);
56275
56276 return $this;
56277 }
56278
56279
56280
56281
56282
56283
56284 public function getStyle()
56285 {
56286 return $this->style;
56287 }
56288
56289
56290
56291
56292
56293
56294
56295
56296
56297 public function setColumnStyle($columnIndex, $name)
56298 {
56299 $columnIndex = (int) $columnIndex;
56300
56301 $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
56302
56303 return $this;
56304 }
56305
56306
56307
56308
56309
56310
56311
56312
56313
56314
56315 public function getColumnStyle($columnIndex)
56316 {
56317 if (isset($this->columnStyles[$columnIndex])) {
56318 return $this->columnStyles[$columnIndex];
56319 }
56320
56321 return $this->getStyle();
56322 }
56323
56324 public function setHeaders(array $headers)
56325 {
56326 $headers = array_values($headers);
56327 if (!empty($headers) && !is_array($headers[0])) {
56328 $headers = array($headers);
56329 }
56330
56331 $this->headers = $headers;
56332
56333 return $this;
56334 }
56335
56336 public function setRows(array $rows)
56337 {
56338 $this->rows = array();
56339
56340 return $this->addRows($rows);
56341 }
56342
56343 public function addRows(array $rows)
56344 {
56345 foreach ($rows as $row) {
56346 $this->addRow($row);
56347 }
56348
56349 return $this;
56350 }
56351
56352 public function addRow($row)
56353 {
56354 if ($row instanceof TableSeparator) {
56355 $this->rows[] = $row;
56356
56357 return $this;
56358 }
56359
56360 if (!is_array($row)) {
56361 throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
56362 }
56363
56364 $this->rows[] = array_values($row);
56365
56366 return $this;
56367 }
56368
56369 public function setRow($column, array $row)
56370 {
56371 $this->rows[$column] = $row;
56372
56373 return $this;
56374 }
56375
56376
56377
56378
56379
56380
56381
56382
56383
56384
56385
56386
56387
56388
56389
56390 public function render()
56391 {
56392 $this->calculateNumberOfColumns();
56393 $rows = $this->buildTableRows($this->rows);
56394 $headers = $this->buildTableRows($this->headers);
56395
56396 $this->calculateColumnsWidth(array_merge($headers, $rows));
56397
56398 $this->renderRowSeparator();
56399 if (!empty($headers)) {
56400 foreach ($headers as $header) {
56401 $this->renderRow($header, $this->style->getCellHeaderFormat());
56402 $this->renderRowSeparator();
56403 }
56404 }
56405 foreach ($rows as $row) {
56406 if ($row instanceof TableSeparator) {
56407 $this->renderRowSeparator();
56408 } else {
56409 $this->renderRow($row, $this->style->getCellRowFormat());
56410 }
56411 }
56412 if (!empty($rows)) {
56413 $this->renderRowSeparator();
56414 }
56415
56416 $this->cleanup();
56417 }
56418
56419
56420
56421
56422
56423
56424 private function renderRowSeparator()
56425 {
56426 if (0 === $count = $this->numberOfColumns) {
56427 return;
56428 }
56429
56430 if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
56431 return;
56432 }
56433
56434 $markup = $this->style->getCrossingChar();
56435 for ($column = 0; $column < $count; ++$column) {
56436 $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
56437 }
56438
56439 $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
56440 }
56441
56442
56443
56444
56445 private function renderColumnSeparator()
56446 {
56447 return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
56448 }
56449
56450
56451
56452
56453
56454
56455
56456
56457
56458 private function renderRow(array $row, $cellFormat)
56459 {
56460 if (empty($row)) {
56461 return;
56462 }
56463
56464 $rowContent = $this->renderColumnSeparator();
56465 foreach ($this->getRowColumns($row) as $column) {
56466 $rowContent .= $this->renderCell($row, $column, $cellFormat);
56467 $rowContent .= $this->renderColumnSeparator();
56468 }
56469 $this->output->writeln($rowContent);
56470 }
56471
56472
56473
56474
56475
56476
56477
56478
56479 private function renderCell(array $row, $column, $cellFormat)
56480 {
56481 $cell = isset($row[$column]) ? $row[$column] : '';
56482 $width = $this->columnWidths[$column];
56483 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
56484
56485  foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
56486 $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
56487 }
56488 }
56489
56490
56491  if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
56492 $width += strlen($cell) - mb_strwidth($cell, $encoding);
56493 }
56494
56495 $style = $this->getColumnStyle($column);
56496
56497 if ($cell instanceof TableSeparator) {
56498 return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
56499 }
56500
56501 $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
56502 $content = sprintf($style->getCellRowContentFormat(), $cell);
56503
56504 return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
56505 }
56506
56507
56508
56509
56510 private function calculateNumberOfColumns()
56511 {
56512 if (null !== $this->numberOfColumns) {
56513 return;
56514 }
56515
56516 $columns = array(0);
56517 foreach (array_merge($this->headers, $this->rows) as $row) {
56518 if ($row instanceof TableSeparator) {
56519 continue;
56520 }
56521
56522 $columns[] = $this->getNumberOfColumns($row);
56523 }
56524
56525 $this->numberOfColumns = max($columns);
56526 }
56527
56528 private function buildTableRows($rows)
56529 {
56530 $unmergedRows = array();
56531 for ($rowKey = 0; $rowKey < count($rows); ++$rowKey) {
56532 $rows = $this->fillNextRows($rows, $rowKey);
56533
56534
56535  foreach ($rows[$rowKey] as $column => $cell) {
56536 if (!strstr($cell, "\n")) {
56537 continue;
56538 }
56539 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
56540 foreach ($lines as $lineKey => $line) {
56541 if ($cell instanceof TableCell) {
56542 $line = new TableCell($line, array('colspan' => $cell->getColspan()));
56543 }
56544 if (0 === $lineKey) {
56545 $rows[$rowKey][$column] = $line;
56546 } else {
56547 $unmergedRows[$rowKey][$lineKey][$column] = $line;
56548 }
56549 }
56550 }
56551 }
56552
56553 $tableRows = array();
56554 foreach ($rows as $rowKey => $row) {
56555 $tableRows[] = $this->fillCells($row);
56556 if (isset($unmergedRows[$rowKey])) {
56557 $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
56558 }
56559 }
56560
56561 return $tableRows;
56562 }
56563
56564
56565
56566
56567
56568
56569
56570
56571
56572 private function fillNextRows(array $rows, $line)
56573 {
56574 $unmergedRows = array();
56575 foreach ($rows[$line] as $column => $cell) {
56576 if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
56577 $nbLines = $cell->getRowspan() - 1;
56578 $lines = array($cell);
56579 if (strstr($cell, "\n")) {
56580 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
56581 $nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
56582
56583 $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
56584 unset($lines[0]);
56585 }
56586
56587
56588  $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
56589 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
56590 $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
56591 $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
56592 if ($nbLines === $unmergedRowKey - $line) {
56593 break;
56594 }
56595 }
56596 }
56597 }
56598
56599 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
56600
56601  if (isset($rows[$unmergedRowKey]) && is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
56602 foreach ($unmergedRow as $cellKey => $cell) {
56603
56604  array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
56605 }
56606 } else {
56607 $row = $this->copyRow($rows, $unmergedRowKey - 1);
56608 foreach ($unmergedRow as $column => $cell) {
56609 if (!empty($cell)) {
56610 $row[$column] = $unmergedRow[$column];
56611 }
56612 }
56613 array_splice($rows, $unmergedRowKey, 0, array($row));
56614 }
56615 }
56616
56617 return $rows;
56618 }
56619
56620
56621
56622
56623
56624
56625 private function fillCells($row)
56626 {
56627 $newRow = array();
56628 foreach ($row as $column => $cell) {
56629 $newRow[] = $cell;
56630 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
56631 foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
56632
56633  $newRow[] = '';
56634 }
56635 }
56636 }
56637
56638 return $newRow ?: $row;
56639 }
56640
56641
56642
56643
56644
56645
56646
56647 private function copyRow(array $rows, $line)
56648 {
56649 $row = $rows[$line];
56650 foreach ($row as $cellKey => $cellValue) {
56651 $row[$cellKey] = '';
56652 if ($cellValue instanceof TableCell) {
56653 $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
56654 }
56655 }
56656
56657 return $row;
56658 }
56659
56660
56661
56662
56663
56664
56665 private function getNumberOfColumns(array $row)
56666 {
56667 $columns = count($row);
56668 foreach ($row as $column) {
56669 $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
56670 }
56671
56672 return $columns;
56673 }
56674
56675
56676
56677
56678
56679
56680 private function getRowColumns(array $row)
56681 {
56682 $columns = range(0, $this->numberOfColumns - 1);
56683 foreach ($row as $cellKey => $cell) {
56684 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
56685
56686  $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
56687 }
56688 }
56689
56690 return $columns;
56691 }
56692
56693
56694
56695
56696
56697
56698 private function calculateColumnsWidth($rows)
56699 {
56700 for ($column = 0; $column < $this->numberOfColumns; ++$column) {
56701 $lengths = array();
56702 foreach ($rows as $row) {
56703 if ($row instanceof TableSeparator) {
56704 continue;
56705 }
56706
56707 foreach ($row as $i => $cell) {
56708 if ($cell instanceof TableCell) {
56709 $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
56710 $textLength = Helper::strlen($textContent);
56711 if ($textLength > 0) {
56712 $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
56713 foreach ($contentColumns as $position => $content) {
56714 $row[$i + $position] = $content;
56715 }
56716 }
56717 }
56718 }
56719
56720 $lengths[] = $this->getCellWidth($row, $column);
56721 }
56722
56723 $this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
56724 }
56725 }
56726
56727
56728
56729
56730
56731
56732 private function getColumnSeparatorWidth()
56733 {
56734 return strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
56735 }
56736
56737
56738
56739
56740
56741
56742
56743
56744
56745 private function getCellWidth(array $row, $column)
56746 {
56747 if (isset($row[$column])) {
56748 $cell = $row[$column];
56749 $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
56750
56751 return $cellWidth;
56752 }
56753
56754 return 0;
56755 }
56756
56757
56758
56759
56760 private function cleanup()
56761 {
56762 $this->columnWidths = array();
56763 $this->numberOfColumns = null;
56764 }
56765
56766 private static function initStyles()
56767 {
56768 $borderless = new TableStyle();
56769 $borderless
56770 ->setHorizontalBorderChar('=')
56771 ->setVerticalBorderChar(' ')
56772 ->setCrossingChar(' ')
56773 ;
56774
56775 $compact = new TableStyle();
56776 $compact
56777 ->setHorizontalBorderChar('')
56778 ->setVerticalBorderChar(' ')
56779 ->setCrossingChar('')
56780 ->setCellRowContentFormat('%s')
56781 ;
56782
56783 $styleGuide = new TableStyle();
56784 $styleGuide
56785 ->setHorizontalBorderChar('-')
56786 ->setVerticalBorderChar(' ')
56787 ->setCrossingChar(' ')
56788 ->setCellHeaderFormat('%s')
56789 ;
56790
56791 return array(
56792 'default' => new TableStyle(),
56793 'borderless' => $borderless,
56794 'compact' => $compact,
56795 'symfony-style-guide' => $styleGuide,
56796 );
56797 }
56798
56799 private function resolveStyle($name)
56800 {
56801 if ($name instanceof TableStyle) {
56802 return $name;
56803 }
56804
56805 if (isset(self::$styles[$name])) {
56806 return self::$styles[$name];
56807 }
56808
56809 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
56810 }
56811 }
56812 <?php
56813
56814
56815
56816
56817
56818
56819
56820
56821
56822
56823 namespace Symfony\Component\Console\Helper;
56824
56825 use Symfony\Component\Console\Exception\InvalidArgumentException;
56826
56827
56828
56829
56830 class TableCell
56831 {
56832 private $value;
56833 private $options = array(
56834 'rowspan' => 1,
56835 'colspan' => 1,
56836 );
56837
56838
56839
56840
56841
56842 public function __construct($value = '', array $options = array())
56843 {
56844 if (is_numeric($value) && !is_string($value)) {
56845 $value = (string) $value;
56846 }
56847
56848 $this->value = $value;
56849
56850
56851  if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
56852 throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
56853 }
56854
56855 $this->options = array_merge($this->options, $options);
56856 }
56857
56858
56859
56860
56861
56862
56863 public function __toString()
56864 {
56865 return $this->value;
56866 }
56867
56868
56869
56870
56871
56872
56873 public function getColspan()
56874 {
56875 return (int) $this->options['colspan'];
56876 }
56877
56878
56879
56880
56881
56882
56883 public function getRowspan()
56884 {
56885 return (int) $this->options['rowspan'];
56886 }
56887 }
56888 <?php
56889
56890
56891
56892
56893
56894
56895
56896
56897
56898
56899 namespace Symfony\Component\Console\Helper;
56900
56901 use Symfony\Component\Console\Output\OutputInterface;
56902 use Symfony\Component\Console\Output\NullOutput;
56903 use Symfony\Component\Console\Exception\InvalidArgumentException;
56904
56905
56906
56907
56908
56909
56910
56911
56912
56913
56914 class TableHelper extends Helper
56915 {
56916 const LAYOUT_DEFAULT = 0;
56917 const LAYOUT_BORDERLESS = 1;
56918 const LAYOUT_COMPACT = 2;
56919
56920 private $table;
56921
56922 public function __construct($triggerDeprecationError = true)
56923 {
56924 if ($triggerDeprecationError) {
56925 @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);
56926 }
56927
56928 $this->table = new Table(new NullOutput());
56929 }
56930
56931
56932
56933
56934
56935
56936
56937
56938
56939
56940 public function setLayout($layout)
56941 {
56942 switch ($layout) {
56943 case self::LAYOUT_BORDERLESS:
56944 $this->table->setStyle('borderless');
56945 break;
56946
56947 case self::LAYOUT_COMPACT:
56948 $this->table->setStyle('compact');
56949 break;
56950
56951 case self::LAYOUT_DEFAULT:
56952 $this->table->setStyle('default');
56953 break;
56954
56955 default:
56956 throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
56957 }
56958
56959 return $this;
56960 }
56961
56962 public function setHeaders(array $headers)
56963 {
56964 $this->table->setHeaders($headers);
56965
56966 return $this;
56967 }
56968
56969 public function setRows(array $rows)
56970 {
56971 $this->table->setRows($rows);
56972
56973 return $this;
56974 }
56975
56976 public function addRows(array $rows)
56977 {
56978 $this->table->addRows($rows);
56979
56980 return $this;
56981 }
56982
56983 public function addRow(array $row)
56984 {
56985 $this->table->addRow($row);
56986
56987 return $this;
56988 }
56989
56990 public function setRow($column, array $row)
56991 {
56992 $this->table->setRow($column, $row);
56993
56994 return $this;
56995 }
56996
56997
56998
56999
57000
57001
57002
57003
57004 public function setPaddingChar($paddingChar)
57005 {
57006 $this->table->getStyle()->setPaddingChar($paddingChar);
57007
57008 return $this;
57009 }
57010
57011
57012
57013
57014
57015
57016
57017
57018 public function setHorizontalBorderChar($horizontalBorderChar)
57019 {
57020 $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
57021
57022 return $this;
57023 }
57024
57025
57026
57027
57028
57029
57030
57031
57032 public function setVerticalBorderChar($verticalBorderChar)
57033 {
57034 $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
57035
57036 return $this;
57037 }
57038
57039
57040
57041
57042
57043
57044
57045
57046 public function setCrossingChar($crossingChar)
57047 {
57048 $this->table->getStyle()->setCrossingChar($crossingChar);
57049
57050 return $this;
57051 }
57052
57053
57054
57055
57056
57057
57058
57059
57060 public function setCellHeaderFormat($cellHeaderFormat)
57061 {
57062 $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
57063
57064 return $this;
57065 }
57066
57067
57068
57069
57070
57071
57072
57073
57074 public function setCellRowFormat($cellRowFormat)
57075 {
57076 $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
57077
57078 return $this;
57079 }
57080
57081
57082
57083
57084
57085
57086
57087
57088 public function setCellRowContentFormat($cellRowContentFormat)
57089 {
57090 $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
57091
57092 return $this;
57093 }
57094
57095
57096
57097
57098
57099
57100
57101
57102 public function setBorderFormat($borderFormat)
57103 {
57104 $this->table->getStyle()->setBorderFormat($borderFormat);
57105
57106 return $this;
57107 }
57108
57109
57110
57111
57112
57113
57114
57115
57116 public function setPadType($padType)
57117 {
57118 $this->table->getStyle()->setPadType($padType);
57119
57120 return $this;
57121 }
57122
57123
57124
57125
57126
57127
57128
57129
57130
57131
57132
57133
57134
57135 public function render(OutputInterface $output)
57136 {
57137 $p = new \ReflectionProperty($this->table, 'output');
57138 $p->setAccessible(true);
57139 $p->setValue($this->table, $output);
57140
57141 $this->table->render();
57142 }
57143
57144
57145
57146
57147 public function getName()
57148 {
57149 return 'table';
57150 }
57151 }
57152 <?php
57153
57154
57155
57156
57157
57158
57159
57160
57161
57162
57163 namespace Symfony\Component\Console\Helper;
57164
57165
57166
57167
57168
57169
57170 class TableSeparator extends TableCell
57171 {
57172 public function __construct(array $options = array())
57173 {
57174 parent::__construct('', $options);
57175 }
57176 }
57177 <?php
57178
57179
57180
57181
57182
57183
57184
57185
57186
57187
57188 namespace Symfony\Component\Console\Helper;
57189
57190 use Symfony\Component\Console\Exception\InvalidArgumentException;
57191 use Symfony\Component\Console\Exception\LogicException;
57192
57193
57194
57195
57196
57197
57198
57199 class TableStyle
57200 {
57201 private $paddingChar = ' ';
57202 private $horizontalBorderChar = '-';
57203 private $verticalBorderChar = '|';
57204 private $crossingChar = '+';
57205 private $cellHeaderFormat = '<info>%s</info>';
57206 private $cellRowFormat = '%s';
57207 private $cellRowContentFormat = ' %s ';
57208 private $borderFormat = '%s';
57209 private $padType = STR_PAD_RIGHT;
57210
57211
57212
57213
57214
57215
57216
57217
57218 public function setPaddingChar($paddingChar)
57219 {
57220 if (!$paddingChar) {
57221 throw new LogicException('The padding char must not be empty');
57222 }
57223
57224 $this->paddingChar = $paddingChar;
57225
57226 return $this;
57227 }
57228
57229
57230
57231
57232
57233
57234 public function getPaddingChar()
57235 {
57236 return $this->paddingChar;
57237 }
57238
57239
57240
57241
57242
57243
57244
57245
57246 public function setHorizontalBorderChar($horizontalBorderChar)
57247 {
57248 $this->horizontalBorderChar = $horizontalBorderChar;
57249
57250 return $this;
57251 }
57252
57253
57254
57255
57256
57257
57258 public function getHorizontalBorderChar()
57259 {
57260 return $this->horizontalBorderChar;
57261 }
57262
57263
57264
57265
57266
57267
57268
57269
57270 public function setVerticalBorderChar($verticalBorderChar)
57271 {
57272 $this->verticalBorderChar = $verticalBorderChar;
57273
57274 return $this;
57275 }
57276
57277
57278
57279
57280
57281
57282 public function getVerticalBorderChar()
57283 {
57284 return $this->verticalBorderChar;
57285 }
57286
57287
57288
57289
57290
57291
57292
57293
57294 public function setCrossingChar($crossingChar)
57295 {
57296 $this->crossingChar = $crossingChar;
57297
57298 return $this;
57299 }
57300
57301
57302
57303
57304
57305
57306 public function getCrossingChar()
57307 {
57308 return $this->crossingChar;
57309 }
57310
57311
57312
57313
57314
57315
57316
57317
57318 public function setCellHeaderFormat($cellHeaderFormat)
57319 {
57320 $this->cellHeaderFormat = $cellHeaderFormat;
57321
57322 return $this;
57323 }
57324
57325
57326
57327
57328
57329
57330 public function getCellHeaderFormat()
57331 {
57332 return $this->cellHeaderFormat;
57333 }
57334
57335
57336
57337
57338
57339
57340
57341
57342 public function setCellRowFormat($cellRowFormat)
57343 {
57344 $this->cellRowFormat = $cellRowFormat;
57345
57346 return $this;
57347 }
57348
57349
57350
57351
57352
57353
57354 public function getCellRowFormat()
57355 {
57356 return $this->cellRowFormat;
57357 }
57358
57359
57360
57361
57362
57363
57364
57365
57366 public function setCellRowContentFormat($cellRowContentFormat)
57367 {
57368 $this->cellRowContentFormat = $cellRowContentFormat;
57369
57370 return $this;
57371 }
57372
57373
57374
57375
57376
57377
57378 public function getCellRowContentFormat()
57379 {
57380 return $this->cellRowContentFormat;
57381 }
57382
57383
57384
57385
57386
57387
57388
57389
57390 public function setBorderFormat($borderFormat)
57391 {
57392 $this->borderFormat = $borderFormat;
57393
57394 return $this;
57395 }
57396
57397
57398
57399
57400
57401
57402 public function getBorderFormat()
57403 {
57404 return $this->borderFormat;
57405 }
57406
57407
57408
57409
57410
57411
57412
57413
57414 public function setPadType($padType)
57415 {
57416 if (!in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
57417 throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
57418 }
57419
57420 $this->padType = $padType;
57421
57422 return $this;
57423 }
57424
57425
57426
57427
57428
57429
57430 public function getPadType()
57431 {
57432 return $this->padType;
57433 }
57434 }
57435 <?php
57436
57437
57438
57439
57440
57441
57442
57443
57444
57445
57446 namespace Symfony\Component\Console\Input;
57447
57448 use Symfony\Component\Console\Exception\RuntimeException;
57449
57450
57451
57452
57453
57454
57455
57456
57457
57458
57459
57460
57461
57462
57463
57464
57465
57466
57467
57468
57469
57470
57471
57472
57473
57474
57475 class ArgvInput extends Input
57476 {
57477 private $tokens;
57478 private $parsed;
57479
57480
57481
57482
57483
57484 public function __construct(array $argv = null, InputDefinition $definition = null)
57485 {
57486 if (null === $argv) {
57487 $argv = $_SERVER['argv'];
57488 }
57489
57490
57491  array_shift($argv);
57492
57493 $this->tokens = $argv;
57494
57495 parent::__construct($definition);
57496 }
57497
57498 protected function setTokens(array $tokens)
57499 {
57500 $this->tokens = $tokens;
57501 }
57502
57503
57504
57505
57506 protected function parse()
57507 {
57508 $parseOptions = true;
57509 $this->parsed = $this->tokens;
57510 while (null !== $token = array_shift($this->parsed)) {
57511 if ($parseOptions && '' == $token) {
57512 $this->parseArgument($token);
57513 } elseif ($parseOptions && '--' == $token) {
57514 $parseOptions = false;
57515 } elseif ($parseOptions && 0 === strpos($token, '--')) {
57516 $this->parseLongOption($token);
57517 } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
57518 $this->parseShortOption($token);
57519 } else {
57520 $this->parseArgument($token);
57521 }
57522 }
57523 }
57524
57525
57526
57527
57528
57529
57530 private function parseShortOption($token)
57531 {
57532 $name = substr($token, 1);
57533
57534 if (strlen($name) > 1) {
57535 if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
57536
57537  $this->addShortOption($name[0], substr($name, 1));
57538 } else {
57539 $this->parseShortOptionSet($name);
57540 }
57541 } else {
57542 $this->addShortOption($name, null);
57543 }
57544 }
57545
57546
57547
57548
57549
57550
57551
57552
57553 private function parseShortOptionSet($name)
57554 {
57555 $len = strlen($name);
57556 for ($i = 0; $i < $len; ++$i) {
57557 if (!$this->definition->hasShortcut($name[$i])) {
57558 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
57559 }
57560
57561 $option = $this->definition->getOptionForShortcut($name[$i]);
57562 if ($option->acceptValue()) {
57563 $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
57564
57565 break;
57566 } else {
57567 $this->addLongOption($option->getName(), null);
57568 }
57569 }
57570 }
57571
57572
57573
57574
57575
57576
57577 private function parseLongOption($token)
57578 {
57579 $name = substr($token, 2);
57580
57581 if (false !== $pos = strpos($name, '=')) {
57582 if (0 === strlen($value = substr($name, $pos + 1))) {
57583 array_unshift($this->parsed, null);
57584 }
57585 $this->addLongOption(substr($name, 0, $pos), $value);
57586 } else {
57587 $this->addLongOption($name, null);
57588 }
57589 }
57590
57591
57592
57593
57594
57595
57596
57597
57598 private function parseArgument($token)
57599 {
57600 $c = count($this->arguments);
57601
57602
57603  if ($this->definition->hasArgument($c)) {
57604 $arg = $this->definition->getArgument($c);
57605 $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
57606
57607
57608  } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
57609 $arg = $this->definition->getArgument($c - 1);
57610 $this->arguments[$arg->getName()][] = $token;
57611
57612
57613  } else {
57614 $all = $this->definition->getArguments();
57615 if (count($all)) {
57616 throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
57617 }
57618
57619 throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
57620 }
57621 }
57622
57623
57624
57625
57626
57627
57628
57629
57630
57631 private function addShortOption($shortcut, $value)
57632 {
57633 if (!$this->definition->hasShortcut($shortcut)) {
57634 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
57635 }
57636
57637 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
57638 }
57639
57640
57641
57642
57643
57644
57645
57646
57647
57648 private function addLongOption($name, $value)
57649 {
57650 if (!$this->definition->hasOption($name)) {
57651 throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
57652 }
57653
57654 $option = $this->definition->getOption($name);
57655
57656
57657  if (!isset($value[0])) {
57658 $value = null;
57659 }
57660
57661 if (null !== $value && !$option->acceptValue()) {
57662 throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
57663 }
57664
57665 if (null === $value && $option->acceptValue() && count($this->parsed)) {
57666
57667  
57668  $next = array_shift($this->parsed);
57669 if (isset($next[0]) && '-' !== $next[0]) {
57670 $value = $next;
57671 } elseif (empty($next)) {
57672 $value = null;
57673 } else {
57674 array_unshift($this->parsed, $next);
57675 }
57676 }
57677
57678 if (null === $value) {
57679 if ($option->isValueRequired()) {
57680 throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
57681 }
57682
57683 if (!$option->isArray()) {
57684 $value = $option->isValueOptional() ? $option->getDefault() : true;
57685 }
57686 }
57687
57688 if ($option->isArray()) {
57689 $this->options[$name][] = $value;
57690 } else {
57691 $this->options[$name] = $value;
57692 }
57693 }
57694
57695
57696
57697
57698 public function getFirstArgument()
57699 {
57700 foreach ($this->tokens as $token) {
57701 if ($token && '-' === $token[0]) {
57702 continue;
57703 }
57704
57705 return $token;
57706 }
57707 }
57708
57709
57710
57711
57712 public function hasParameterOption($values)
57713 {
57714 $values = (array) $values;
57715
57716 foreach ($this->tokens as $token) {
57717 foreach ($values as $value) {
57718
57719  
57720  
57721  $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
57722 if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) {
57723 return true;
57724 }
57725 }
57726 }
57727
57728 return false;
57729 }
57730
57731
57732
57733
57734 public function getParameterOption($values, $default = false)
57735 {
57736 $values = (array) $values;
57737 $tokens = $this->tokens;
57738
57739 while (0 < count($tokens)) {
57740 $token = array_shift($tokens);
57741
57742 foreach ($values as $value) {
57743 if ($token === $value) {
57744 return array_shift($tokens);
57745 }
57746
57747  
57748  
57749  $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
57750 if ('' !== $leading && 0 === strpos($token, $leading)) {
57751 return substr($token, strlen($leading));
57752 }
57753 }
57754 }
57755
57756 return $default;
57757 }
57758
57759
57760
57761
57762
57763
57764 public function __toString()
57765 {
57766 $self = $this;
57767 $tokens = array_map(function ($token) use ($self) {
57768 if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
57769 return $match[1].$self->escapeToken($match[2]);
57770 }
57771
57772 if ($token && '-' !== $token[0]) {
57773 return $self->escapeToken($token);
57774 }
57775
57776 return $token;
57777 }, $this->tokens);
57778
57779 return implode(' ', $tokens);
57780 }
57781 }
57782 <?php
57783
57784
57785
57786
57787
57788
57789
57790
57791
57792
57793 namespace Symfony\Component\Console\Input;
57794
57795 use Symfony\Component\Console\Exception\InvalidArgumentException;
57796 use Symfony\Component\Console\Exception\InvalidOptionException;
57797
57798
57799
57800
57801
57802
57803
57804
57805
57806
57807 class ArrayInput extends Input
57808 {
57809 private $parameters;
57810
57811 public function __construct(array $parameters, InputDefinition $definition = null)
57812 {
57813 $this->parameters = $parameters;
57814
57815 parent::__construct($definition);
57816 }
57817
57818
57819
57820
57821 public function getFirstArgument()
57822 {
57823 foreach ($this->parameters as $key => $value) {
57824 if ($key && '-' === $key[0]) {
57825 continue;
57826 }
57827
57828 return $value;
57829 }
57830 }
57831
57832
57833
57834
57835 public function hasParameterOption($values)
57836 {
57837 $values = (array) $values;
57838
57839 foreach ($this->parameters as $k => $v) {
57840 if (!is_int($k)) {
57841 $v = $k;
57842 }
57843
57844 if (in_array($v, $values)) {
57845 return true;
57846 }
57847 }
57848
57849 return false;
57850 }
57851
57852
57853
57854
57855 public function getParameterOption($values, $default = false)
57856 {
57857 $values = (array) $values;
57858
57859 foreach ($this->parameters as $k => $v) {
57860 if (is_int($k)) {
57861 if (in_array($v, $values)) {
57862 return true;
57863 }
57864 } elseif (in_array($k, $values)) {
57865 return $v;
57866 }
57867 }
57868
57869 return $default;
57870 }
57871
57872
57873
57874
57875
57876
57877 public function __toString()
57878 {
57879 $params = array();
57880 foreach ($this->parameters as $param => $val) {
57881 if ($param && '-' === $param[0]) {
57882 if (is_array($val)) {
57883 foreach ($val as $v) {
57884 $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : '');
57885 }
57886 } else {
57887 $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
57888 }
57889 } else {
57890 $params[] = is_array($val) ? implode(' ', array_map(array($this, 'escapeToken'), $val)) : $this->escapeToken($val);
57891 }
57892 }
57893
57894 return implode(' ', $params);
57895 }
57896
57897
57898
57899
57900 protected function parse()
57901 {
57902 foreach ($this->parameters as $key => $value) {
57903 if (0 === strpos($key, '--')) {
57904 $this->addLongOption(substr($key, 2), $value);
57905 } elseif ('-' === $key[0]) {
57906 $this->addShortOption(substr($key, 1), $value);
57907 } else {
57908 $this->addArgument($key, $value);
57909 }
57910 }
57911 }
57912
57913
57914
57915
57916
57917
57918
57919
57920
57921 private function addShortOption($shortcut, $value)
57922 {
57923 if (!$this->definition->hasShortcut($shortcut)) {
57924 throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
57925 }
57926
57927 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
57928 }
57929
57930
57931
57932
57933
57934
57935
57936
57937
57938
57939 private function addLongOption($name, $value)
57940 {
57941 if (!$this->definition->hasOption($name)) {
57942 throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
57943 }
57944
57945 $option = $this->definition->getOption($name);
57946
57947 if (null === $value) {
57948 if ($option->isValueRequired()) {
57949 throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
57950 }
57951
57952 $value = $option->isValueOptional() ? $option->getDefault() : true;
57953 }
57954
57955 $this->options[$name] = $value;
57956 }
57957
57958
57959
57960
57961
57962
57963
57964
57965
57966 private function addArgument($name, $value)
57967 {
57968 if (!$this->definition->hasArgument($name)) {
57969 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
57970 }
57971
57972 $this->arguments[$name] = $value;
57973 }
57974 }
57975 <?php
57976
57977
57978
57979
57980
57981
57982
57983
57984
57985
57986 namespace Symfony\Component\Console\Input;
57987
57988 use Symfony\Component\Console\Exception\InvalidArgumentException;
57989 use Symfony\Component\Console\Exception\RuntimeException;
57990
57991
57992
57993
57994
57995
57996
57997
57998
57999
58000
58001
58002 abstract class Input implements InputInterface
58003 {
58004 protected $definition;
58005 protected $options = array();
58006 protected $arguments = array();
58007 protected $interactive = true;
58008
58009 public function __construct(InputDefinition $definition = null)
58010 {
58011 if (null === $definition) {
58012 $this->definition = new InputDefinition();
58013 } else {
58014 $this->bind($definition);
58015 $this->validate();
58016 }
58017 }
58018
58019
58020
58021
58022 public function bind(InputDefinition $definition)
58023 {
58024 $this->arguments = array();
58025 $this->options = array();
58026 $this->definition = $definition;
58027
58028 $this->parse();
58029 }
58030
58031
58032
58033
58034 abstract protected function parse();
58035
58036
58037
58038
58039 public function validate()
58040 {
58041 $definition = $this->definition;
58042 $givenArguments = $this->arguments;
58043
58044 $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
58045 return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
58046 });
58047
58048 if (count($missingArguments) > 0) {
58049 throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
58050 }
58051 }
58052
58053
58054
58055
58056 public function isInteractive()
58057 {
58058 return $this->interactive;
58059 }
58060
58061
58062
58063
58064 public function setInteractive($interactive)
58065 {
58066 $this->interactive = (bool) $interactive;
58067 }
58068
58069
58070
58071
58072 public function getArguments()
58073 {
58074 return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
58075 }
58076
58077
58078
58079
58080 public function getArgument($name)
58081 {
58082 if (!$this->definition->hasArgument($name)) {
58083 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
58084 }
58085
58086 return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
58087 }
58088
58089
58090
58091
58092 public function setArgument($name, $value)
58093 {
58094 if (!$this->definition->hasArgument($name)) {
58095 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
58096 }
58097
58098 $this->arguments[$name] = $value;
58099 }
58100
58101
58102
58103
58104 public function hasArgument($name)
58105 {
58106 return $this->definition->hasArgument($name);
58107 }
58108
58109
58110
58111
58112 public function getOptions()
58113 {
58114 return array_merge($this->definition->getOptionDefaults(), $this->options);
58115 }
58116
58117
58118
58119
58120 public function getOption($name)
58121 {
58122 if (!$this->definition->hasOption($name)) {
58123 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
58124 }
58125
58126 return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
58127 }
58128
58129
58130
58131
58132 public function setOption($name, $value)
58133 {
58134 if (!$this->definition->hasOption($name)) {
58135 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
58136 }
58137
58138 $this->options[$name] = $value;
58139 }
58140
58141
58142
58143
58144 public function hasOption($name)
58145 {
58146 return $this->definition->hasOption($name);
58147 }
58148
58149
58150
58151
58152
58153
58154
58155
58156 public function escapeToken($token)
58157 {
58158 return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
58159 }
58160 }
58161 <?php
58162
58163
58164
58165
58166
58167
58168
58169
58170
58171
58172 namespace Symfony\Component\Console\Input;
58173
58174 use Symfony\Component\Console\Exception\InvalidArgumentException;
58175 use Symfony\Component\Console\Exception\LogicException;
58176
58177
58178
58179
58180
58181
58182 class InputArgument
58183 {
58184 const REQUIRED = 1;
58185 const OPTIONAL = 2;
58186 const IS_ARRAY = 4;
58187
58188 private $name;
58189 private $mode;
58190 private $default;
58191 private $description;
58192
58193
58194
58195
58196
58197
58198
58199
58200
58201 public function __construct($name, $mode = null, $description = '', $default = null)
58202 {
58203 if (null === $mode) {
58204 $mode = self::OPTIONAL;
58205 } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
58206 throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
58207 }
58208
58209 $this->name = $name;
58210 $this->mode = $mode;
58211 $this->description = $description;
58212
58213 $this->setDefault($default);
58214 }
58215
58216
58217
58218
58219
58220
58221 public function getName()
58222 {
58223 return $this->name;
58224 }
58225
58226
58227
58228
58229
58230
58231 public function isRequired()
58232 {
58233 return self::REQUIRED === (self::REQUIRED & $this->mode);
58234 }
58235
58236
58237
58238
58239
58240
58241 public function isArray()
58242 {
58243 return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
58244 }
58245
58246
58247
58248
58249
58250
58251
58252
58253 public function setDefault($default = null)
58254 {
58255 if (self::REQUIRED === $this->mode && null !== $default) {
58256 throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
58257 }
58258
58259 if ($this->isArray()) {
58260 if (null === $default) {
58261 $default = array();
58262 } elseif (!is_array($default)) {
58263 throw new LogicException('A default value for an array argument must be an array.');
58264 }
58265 }
58266
58267 $this->default = $default;
58268 }
58269
58270
58271
58272
58273
58274
58275 public function getDefault()
58276 {
58277 return $this->default;
58278 }
58279
58280
58281
58282
58283
58284
58285 public function getDescription()
58286 {
58287 return $this->description;
58288 }
58289 }
58290 <?php
58291
58292
58293
58294
58295
58296
58297
58298
58299
58300
58301 namespace Symfony\Component\Console\Input;
58302
58303
58304
58305
58306
58307
58308
58309 interface InputAwareInterface
58310 {
58311
58312
58313
58314
58315
58316 public function setInput(InputInterface $input);
58317 }
58318 <?php
58319
58320
58321
58322
58323
58324
58325
58326
58327
58328
58329 namespace Symfony\Component\Console\Input;
58330
58331 use Symfony\Component\Console\Descriptor\TextDescriptor;
58332 use Symfony\Component\Console\Descriptor\XmlDescriptor;
58333 use Symfony\Component\Console\Output\BufferedOutput;
58334 use Symfony\Component\Console\Exception\InvalidArgumentException;
58335 use Symfony\Component\Console\Exception\LogicException;
58336
58337
58338
58339
58340
58341
58342
58343
58344
58345
58346
58347
58348
58349 class InputDefinition
58350 {
58351 private $arguments;
58352 private $requiredCount;
58353 private $hasAnArrayArgument = false;
58354 private $hasOptional;
58355 private $options;
58356 private $shortcuts;
58357
58358
58359
58360
58361 public function __construct(array $definition = array())
58362 {
58363 $this->setDefinition($definition);
58364 }
58365
58366
58367
58368
58369 public function setDefinition(array $definition)
58370 {
58371 $arguments = array();
58372 $options = array();
58373 foreach ($definition as $item) {
58374 if ($item instanceof InputOption) {
58375 $options[] = $item;
58376 } else {
58377 $arguments[] = $item;
58378 }
58379 }
58380
58381 $this->setArguments($arguments);
58382 $this->setOptions($options);
58383 }
58384
58385
58386
58387
58388
58389
58390 public function setArguments($arguments = array())
58391 {
58392 $this->arguments = array();
58393 $this->requiredCount = 0;
58394 $this->hasOptional = false;
58395 $this->hasAnArrayArgument = false;
58396 $this->addArguments($arguments);
58397 }
58398
58399
58400
58401
58402
58403
58404 public function addArguments($arguments = array())
58405 {
58406 if (null !== $arguments) {
58407 foreach ($arguments as $argument) {
58408 $this->addArgument($argument);
58409 }
58410 }
58411 }
58412
58413
58414
58415
58416 public function addArgument(InputArgument $argument)
58417 {
58418 if (isset($this->arguments[$argument->getName()])) {
58419 throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
58420 }
58421
58422 if ($this->hasAnArrayArgument) {
58423 throw new LogicException('Cannot add an argument after an array argument.');
58424 }
58425
58426 if ($argument->isRequired() && $this->hasOptional) {
58427 throw new LogicException('Cannot add a required argument after an optional one.');
58428 }
58429
58430 if ($argument->isArray()) {
58431 $this->hasAnArrayArgument = true;
58432 }
58433
58434 if ($argument->isRequired()) {
58435 ++$this->requiredCount;
58436 } else {
58437 $this->hasOptional = true;
58438 }
58439
58440 $this->arguments[$argument->getName()] = $argument;
58441 }
58442
58443
58444
58445
58446
58447
58448
58449
58450
58451
58452 public function getArgument($name)
58453 {
58454 if (!$this->hasArgument($name)) {
58455 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
58456 }
58457
58458 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
58459
58460 return $arguments[$name];
58461 }
58462
58463
58464
58465
58466
58467
58468
58469
58470 public function hasArgument($name)
58471 {
58472 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
58473
58474 return isset($arguments[$name]);
58475 }
58476
58477
58478
58479
58480
58481
58482 public function getArguments()
58483 {
58484 return $this->arguments;
58485 }
58486
58487
58488
58489
58490
58491
58492 public function getArgumentCount()
58493 {
58494 return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
58495 }
58496
58497
58498
58499
58500
58501
58502 public function getArgumentRequiredCount()
58503 {
58504 return $this->requiredCount;
58505 }
58506
58507
58508
58509
58510
58511
58512 public function getArgumentDefaults()
58513 {
58514 $values = array();
58515 foreach ($this->arguments as $argument) {
58516 $values[$argument->getName()] = $argument->getDefault();
58517 }
58518
58519 return $values;
58520 }
58521
58522
58523
58524
58525
58526
58527 public function setOptions($options = array())
58528 {
58529 $this->options = array();
58530 $this->shortcuts = array();
58531 $this->addOptions($options);
58532 }
58533
58534
58535
58536
58537
58538
58539 public function addOptions($options = array())
58540 {
58541 foreach ($options as $option) {
58542 $this->addOption($option);
58543 }
58544 }
58545
58546
58547
58548
58549 public function addOption(InputOption $option)
58550 {
58551 if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
58552 throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
58553 }
58554
58555 if ($option->getShortcut()) {
58556 foreach (explode('|', $option->getShortcut()) as $shortcut) {
58557 if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
58558 throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
58559 }
58560 }
58561 }
58562
58563 $this->options[$option->getName()] = $option;
58564 if ($option->getShortcut()) {
58565 foreach (explode('|', $option->getShortcut()) as $shortcut) {
58566 $this->shortcuts[$shortcut] = $option->getName();
58567 }
58568 }
58569 }
58570
58571
58572
58573
58574
58575
58576
58577
58578
58579
58580 public function getOption($name)
58581 {
58582 if (!$this->hasOption($name)) {
58583 throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
58584 }
58585
58586 return $this->options[$name];
58587 }
58588
58589
58590
58591
58592
58593
58594
58595
58596
58597
58598
58599 public function hasOption($name)
58600 {
58601 return isset($this->options[$name]);
58602 }
58603
58604
58605
58606
58607
58608
58609 public function getOptions()
58610 {
58611 return $this->options;
58612 }
58613
58614
58615
58616
58617
58618
58619
58620
58621 public function hasShortcut($name)
58622 {
58623 return isset($this->shortcuts[$name]);
58624 }
58625
58626
58627
58628
58629
58630
58631
58632
58633 public function getOptionForShortcut($shortcut)
58634 {
58635 return $this->getOption($this->shortcutToName($shortcut));
58636 }
58637
58638
58639
58640
58641
58642
58643 public function getOptionDefaults()
58644 {
58645 $values = array();
58646 foreach ($this->options as $option) {
58647 $values[$option->getName()] = $option->getDefault();
58648 }
58649
58650 return $values;
58651 }
58652
58653
58654
58655
58656
58657
58658
58659
58660
58661
58662 private function shortcutToName($shortcut)
58663 {
58664 if (!isset($this->shortcuts[$shortcut])) {
58665 throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
58666 }
58667
58668 return $this->shortcuts[$shortcut];
58669 }
58670
58671
58672
58673
58674
58675
58676
58677
58678 public function getSynopsis($short = false)
58679 {
58680 $elements = array();
58681
58682 if ($short && $this->getOptions()) {
58683 $elements[] = '[options]';
58684 } elseif (!$short) {
58685 foreach ($this->getOptions() as $option) {
58686 $value = '';
58687 if ($option->acceptValue()) {
58688 $value = sprintf(
58689 ' %s%s%s',
58690 $option->isValueOptional() ? '[' : '',
58691 strtoupper($option->getName()),
58692 $option->isValueOptional() ? ']' : ''
58693 );
58694 }
58695
58696 $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
58697 $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
58698 }
58699 }
58700
58701 if (count($elements) && $this->getArguments()) {
58702 $elements[] = '[--]';
58703 }
58704
58705 foreach ($this->getArguments() as $argument) {
58706 $element = '<'.$argument->getName().'>';
58707 if (!$argument->isRequired()) {
58708 $element = '['.$element.']';
58709 } elseif ($argument->isArray()) {
58710 $element = $element.' ('.$element.')';
58711 }
58712
58713 if ($argument->isArray()) {
58714 $element .= '...';
58715 }
58716
58717 $elements[] = $element;
58718 }
58719
58720 return implode(' ', $elements);
58721 }
58722
58723
58724
58725
58726
58727
58728
58729
58730 public function asText()
58731 {
58732 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
58733
58734 $descriptor = new TextDescriptor();
58735 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
58736 $descriptor->describe($output, $this, array('raw_output' => true));
58737
58738 return $output->fetch();
58739 }
58740
58741
58742
58743
58744
58745
58746
58747
58748
58749
58750 public function asXml($asDom = false)
58751 {
58752 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
58753
58754 $descriptor = new XmlDescriptor();
58755
58756 if ($asDom) {
58757 return $descriptor->getInputDefinitionDocument($this);
58758 }
58759
58760 $output = new BufferedOutput();
58761 $descriptor->describe($output, $this);
58762
58763 return $output->fetch();
58764 }
58765 }
58766 <?php
58767
58768
58769
58770
58771
58772
58773
58774
58775
58776
58777 namespace Symfony\Component\Console\Input;
58778
58779 use Symfony\Component\Console\Exception\InvalidArgumentException;
58780 use Symfony\Component\Console\Exception\RuntimeException;
58781
58782
58783
58784
58785
58786
58787 interface InputInterface
58788 {
58789
58790
58791
58792
58793
58794 public function getFirstArgument();
58795
58796
58797
58798
58799
58800
58801
58802
58803
58804
58805
58806
58807
58808 public function hasParameterOption($values);
58809
58810
58811
58812
58813
58814
58815
58816
58817
58818
58819
58820
58821
58822
58823 public function getParameterOption($values, $default = false);
58824
58825
58826
58827
58828 public function bind(InputDefinition $definition);
58829
58830
58831
58832
58833
58834
58835 public function validate();
58836
58837
58838
58839
58840
58841
58842 public function getArguments();
58843
58844
58845
58846
58847
58848
58849
58850
58851
58852
58853 public function getArgument($name);
58854
58855
58856
58857
58858
58859
58860
58861
58862
58863 public function setArgument($name, $value);
58864
58865
58866
58867
58868
58869
58870
58871
58872 public function hasArgument($name);
58873
58874
58875
58876
58877
58878
58879 public function getOptions();
58880
58881
58882
58883
58884
58885
58886
58887
58888
58889
58890 public function getOption($name);
58891
58892
58893
58894
58895
58896
58897
58898
58899
58900 public function setOption($name, $value);
58901
58902
58903
58904
58905
58906
58907
58908
58909 public function hasOption($name);
58910
58911
58912
58913
58914
58915
58916 public function isInteractive();
58917
58918
58919
58920
58921
58922
58923 public function setInteractive($interactive);
58924 }
58925 <?php
58926
58927
58928
58929
58930
58931
58932
58933
58934
58935
58936 namespace Symfony\Component\Console\Input;
58937
58938 use Symfony\Component\Console\Exception\InvalidArgumentException;
58939 use Symfony\Component\Console\Exception\LogicException;
58940
58941
58942
58943
58944
58945
58946 class InputOption
58947 {
58948 const VALUE_NONE = 1;
58949 const VALUE_REQUIRED = 2;
58950 const VALUE_OPTIONAL = 4;
58951 const VALUE_IS_ARRAY = 8;
58952
58953 private $name;
58954 private $shortcut;
58955 private $mode;
58956 private $default;
58957 private $description;
58958
58959
58960
58961
58962
58963
58964
58965
58966
58967
58968 public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
58969 {
58970 if (0 === strpos($name, '--')) {
58971 $name = substr($name, 2);
58972 }
58973
58974 if (empty($name)) {
58975 throw new InvalidArgumentException('An option name cannot be empty.');
58976 }
58977
58978 if (empty($shortcut)) {
58979 $shortcut = null;
58980 }
58981
58982 if (null !== $shortcut) {
58983 if (is_array($shortcut)) {
58984 $shortcut = implode('|', $shortcut);
58985 }
58986 $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
58987 $shortcuts = array_filter($shortcuts);
58988 $shortcut = implode('|', $shortcuts);
58989
58990 if (empty($shortcut)) {
58991 throw new InvalidArgumentException('An option shortcut cannot be empty.');
58992 }
58993 }
58994
58995 if (null === $mode) {
58996 $mode = self::VALUE_NONE;
58997 } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
58998 throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
58999 }
59000
59001 $this->name = $name;
59002 $this->shortcut = $shortcut;
59003 $this->mode = $mode;
59004 $this->description = $description;
59005
59006 if ($this->isArray() && !$this->acceptValue()) {
59007 throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
59008 }
59009
59010 $this->setDefault($default);
59011 }
59012
59013
59014
59015
59016
59017
59018 public function getShortcut()
59019 {
59020 return $this->shortcut;
59021 }
59022
59023
59024
59025
59026
59027
59028 public function getName()
59029 {
59030 return $this->name;
59031 }
59032
59033
59034
59035
59036
59037
59038 public function acceptValue()
59039 {
59040 return $this->isValueRequired() || $this->isValueOptional();
59041 }
59042
59043
59044
59045
59046
59047
59048 public function isValueRequired()
59049 {
59050 return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
59051 }
59052
59053
59054
59055
59056
59057
59058 public function isValueOptional()
59059 {
59060 return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
59061 }
59062
59063
59064
59065
59066
59067
59068 public function isArray()
59069 {
59070 return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
59071 }
59072
59073
59074
59075
59076
59077
59078
59079
59080 public function setDefault($default = null)
59081 {
59082 if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
59083 throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
59084 }
59085
59086 if ($this->isArray()) {
59087 if (null === $default) {
59088 $default = array();
59089 } elseif (!is_array($default)) {
59090 throw new LogicException('A default value for an array option must be an array.');
59091 }
59092 }
59093
59094 $this->default = $this->acceptValue() ? $default : false;
59095 }
59096
59097
59098
59099
59100
59101
59102 public function getDefault()
59103 {
59104 return $this->default;
59105 }
59106
59107
59108
59109
59110
59111
59112 public function getDescription()
59113 {
59114 return $this->description;
59115 }
59116
59117
59118
59119
59120
59121
59122 public function equals(self $option)
59123 {
59124 return $option->getName() === $this->getName()
59125 && $option->getShortcut() === $this->getShortcut()
59126 && $option->getDefault() === $this->getDefault()
59127 && $option->isArray() === $this->isArray()
59128 && $option->isValueRequired() === $this->isValueRequired()
59129 && $option->isValueOptional() === $this->isValueOptional()
59130 ;
59131 }
59132 }
59133 <?php
59134
59135
59136
59137
59138
59139
59140
59141
59142
59143
59144 namespace Symfony\Component\Console\Input;
59145
59146 use Symfony\Component\Console\Exception\InvalidArgumentException;
59147
59148
59149
59150
59151
59152
59153
59154
59155
59156
59157 class StringInput extends ArgvInput
59158 {
59159 const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
59160 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
59161
59162
59163
59164
59165
59166
59167
59168 public function __construct($input, InputDefinition $definition = null)
59169 {
59170 if ($definition) {
59171 @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);
59172 }
59173
59174 parent::__construct(array(), null);
59175
59176 $this->setTokens($this->tokenize($input));
59177
59178 if (null !== $definition) {
59179 $this->bind($definition);
59180 }
59181 }
59182
59183
59184
59185
59186
59187
59188
59189
59190
59191
59192 private function tokenize($input)
59193 {
59194 $tokens = array();
59195 $length = strlen($input);
59196 $cursor = 0;
59197 while ($cursor < $length) {
59198 if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
59199 } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
59200 $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
59201 } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
59202 $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
59203 } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
59204 $tokens[] = stripcslashes($match[1]);
59205 } else {
59206
59207  throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
59208 }
59209
59210 $cursor += strlen($match[0]);
59211 }
59212
59213 return $tokens;
59214 }
59215 }
59216 Copyright (c) 2004-2018 Fabien Potencier
59217
59218 Permission is hereby granted, free of charge, to any person obtaining a copy
59219 of this software and associated documentation files (the "Software"), to deal
59220 in the Software without restriction, including without limitation the rights
59221 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
59222 copies of the Software, and to permit persons to whom the Software is furnished
59223 to do so, subject to the following conditions:
59224
59225 The above copyright notice and this permission notice shall be included in all
59226 copies or substantial portions of the Software.
59227
59228 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59229 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
59230 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
59231 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59232 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
59233 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
59234 THE SOFTWARE.
59235 <?php
59236
59237
59238
59239
59240
59241
59242
59243
59244
59245
59246 namespace Symfony\Component\Console\Logger;
59247
59248 use Psr\Log\AbstractLogger;
59249 use Psr\Log\InvalidArgumentException;
59250 use Psr\Log\LogLevel;
59251 use Symfony\Component\Console\Output\OutputInterface;
59252 use Symfony\Component\Console\Output\ConsoleOutputInterface;
59253
59254
59255
59256
59257
59258
59259
59260
59261 class ConsoleLogger extends AbstractLogger
59262 {
59263 const INFO = 'info';
59264 const ERROR = 'error';
59265
59266 private $output;
59267 private $verbosityLevelMap = array(
59268 LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
59269 LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
59270 LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
59271 LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
59272 LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
59273 LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
59274 LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
59275 LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
59276 );
59277 private $formatLevelMap = array(
59278 LogLevel::EMERGENCY => self::ERROR,
59279 LogLevel::ALERT => self::ERROR,
59280 LogLevel::CRITICAL => self::ERROR,
59281 LogLevel::ERROR => self::ERROR,
59282 LogLevel::WARNING => self::INFO,
59283 LogLevel::NOTICE => self::INFO,
59284 LogLevel::INFO => self::INFO,
59285 LogLevel::DEBUG => self::INFO,
59286 );
59287
59288 public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
59289 {
59290 $this->output = $output;
59291 $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
59292 $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
59293 }
59294
59295
59296
59297
59298 public function log($level, $message, array $context = array())
59299 {
59300 if (!isset($this->verbosityLevelMap[$level])) {
59301 throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
59302 }
59303
59304
59305  if (self::ERROR === $this->formatLevelMap[$level] && $this->output instanceof ConsoleOutputInterface) {
59306 $output = $this->output->getErrorOutput();
59307 } else {
59308 $output = $this->output;
59309 }
59310
59311 if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
59312 $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
59313 }
59314 }
59315
59316
59317
59318
59319
59320
59321
59322
59323
59324
59325
59326 private function interpolate($message, array $context)
59327 {
59328
59329  $replace = array();
59330 foreach ($context as $key => $val) {
59331 if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
59332 $replace[sprintf('{%s}', $key)] = $val;
59333 }
59334 }
59335
59336
59337  return strtr($message, $replace);
59338 }
59339 }
59340 <?php
59341
59342
59343
59344
59345
59346
59347
59348
59349
59350
59351 namespace Symfony\Component\Console\Output;
59352
59353
59354
59355
59356 class BufferedOutput extends Output
59357 {
59358 private $buffer = '';
59359
59360
59361
59362
59363
59364
59365 public function fetch()
59366 {
59367 $content = $this->buffer;
59368 $this->buffer = '';
59369
59370 return $content;
59371 }
59372
59373
59374
59375
59376 protected function doWrite($message, $newline)
59377 {
59378 $this->buffer .= $message;
59379
59380 if ($newline) {
59381 $this->buffer .= PHP_EOL;
59382 }
59383 }
59384 }
59385 <?php
59386
59387
59388
59389
59390
59391
59392
59393
59394
59395
59396 namespace Symfony\Component\Console\Output;
59397
59398 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59399
59400
59401
59402
59403
59404
59405
59406
59407
59408
59409
59410
59411
59412
59413 class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
59414 {
59415 private $stderr;
59416
59417
59418
59419
59420
59421
59422 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
59423 {
59424 parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
59425
59426 $actualDecorated = $this->isDecorated();
59427 $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
59428
59429 if (null === $decorated) {
59430 $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
59431 }
59432 }
59433
59434
59435
59436
59437 public function setDecorated($decorated)
59438 {
59439 parent::setDecorated($decorated);
59440 $this->stderr->setDecorated($decorated);
59441 }
59442
59443
59444
59445
59446 public function setFormatter(OutputFormatterInterface $formatter)
59447 {
59448 parent::setFormatter($formatter);
59449 $this->stderr->setFormatter($formatter);
59450 }
59451
59452
59453
59454
59455 public function setVerbosity($level)
59456 {
59457 parent::setVerbosity($level);
59458 $this->stderr->setVerbosity($level);
59459 }
59460
59461
59462
59463
59464 public function getErrorOutput()
59465 {
59466 return $this->stderr;
59467 }
59468
59469
59470
59471
59472 public function setErrorOutput(OutputInterface $error)
59473 {
59474 $this->stderr = $error;
59475 }
59476
59477
59478
59479
59480
59481
59482
59483 protected function hasStdoutSupport()
59484 {
59485 return false === $this->isRunningOS400();
59486 }
59487
59488
59489
59490
59491
59492
59493
59494 protected function hasStderrSupport()
59495 {
59496 return false === $this->isRunningOS400();
59497 }
59498
59499
59500
59501
59502
59503
59504
59505 private function isRunningOS400()
59506 {
59507 $checks = array(
59508 function_exists('php_uname') ? php_uname('s') : '',
59509 getenv('OSTYPE'),
59510 PHP_OS,
59511 );
59512
59513 return false !== stripos(implode(';', $checks), 'OS400');
59514 }
59515
59516
59517
59518
59519 private function openOutputStream()
59520 {
59521 $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output';
59522
59523 return @fopen($outputStream, 'w') ?: fopen('php://output', 'w');
59524 }
59525
59526
59527
59528
59529 private function openErrorStream()
59530 {
59531 $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output';
59532
59533 return fopen($errorStream, 'w');
59534 }
59535 }
59536 <?php
59537
59538
59539
59540
59541
59542
59543
59544
59545
59546
59547 namespace Symfony\Component\Console\Output;
59548
59549
59550
59551
59552
59553
59554
59555 interface ConsoleOutputInterface extends OutputInterface
59556 {
59557
59558
59559
59560
59561
59562 public function getErrorOutput();
59563
59564 public function setErrorOutput(OutputInterface $error);
59565 }
59566 <?php
59567
59568
59569
59570
59571
59572
59573
59574
59575
59576
59577 namespace Symfony\Component\Console\Output;
59578
59579 use Symfony\Component\Console\Formatter\OutputFormatter;
59580 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59581
59582
59583
59584
59585
59586
59587
59588
59589
59590 class NullOutput implements OutputInterface
59591 {
59592
59593
59594
59595 public function setFormatter(OutputFormatterInterface $formatter)
59596 {
59597
59598  }
59599
59600
59601
59602
59603 public function getFormatter()
59604 {
59605
59606  return new OutputFormatter();
59607 }
59608
59609
59610
59611
59612 public function setDecorated($decorated)
59613 {
59614
59615  }
59616
59617
59618
59619
59620 public function isDecorated()
59621 {
59622 return false;
59623 }
59624
59625
59626
59627
59628 public function setVerbosity($level)
59629 {
59630
59631  }
59632
59633
59634
59635
59636 public function getVerbosity()
59637 {
59638 return self::VERBOSITY_QUIET;
59639 }
59640
59641
59642
59643
59644 public function isQuiet()
59645 {
59646 return true;
59647 }
59648
59649
59650
59651
59652 public function isVerbose()
59653 {
59654 return false;
59655 }
59656
59657
59658
59659
59660 public function isVeryVerbose()
59661 {
59662 return false;
59663 }
59664
59665
59666
59667
59668 public function isDebug()
59669 {
59670 return false;
59671 }
59672
59673
59674
59675
59676 public function writeln($messages, $options = self::OUTPUT_NORMAL)
59677 {
59678
59679  }
59680
59681
59682
59683
59684 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
59685 {
59686
59687  }
59688 }
59689 <?php
59690
59691
59692
59693
59694
59695
59696
59697
59698
59699
59700 namespace Symfony\Component\Console\Output;
59701
59702 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59703 use Symfony\Component\Console\Formatter\OutputFormatter;
59704
59705
59706
59707
59708
59709
59710
59711
59712
59713
59714
59715
59716
59717
59718 abstract class Output implements OutputInterface
59719 {
59720 private $verbosity;
59721 private $formatter;
59722
59723
59724
59725
59726
59727
59728 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
59729 {
59730 $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
59731 $this->formatter = $formatter ?: new OutputFormatter();
59732 $this->formatter->setDecorated($decorated);
59733 }
59734
59735
59736
59737
59738 public function setFormatter(OutputFormatterInterface $formatter)
59739 {
59740 $this->formatter = $formatter;
59741 }
59742
59743
59744
59745
59746 public function getFormatter()
59747 {
59748 return $this->formatter;
59749 }
59750
59751
59752
59753
59754 public function setDecorated($decorated)
59755 {
59756 $this->formatter->setDecorated($decorated);
59757 }
59758
59759
59760
59761
59762 public function isDecorated()
59763 {
59764 return $this->formatter->isDecorated();
59765 }
59766
59767
59768
59769
59770 public function setVerbosity($level)
59771 {
59772 $this->verbosity = (int) $level;
59773 }
59774
59775
59776
59777
59778 public function getVerbosity()
59779 {
59780 return $this->verbosity;
59781 }
59782
59783
59784
59785
59786 public function isQuiet()
59787 {
59788 return self::VERBOSITY_QUIET === $this->verbosity;
59789 }
59790
59791
59792
59793
59794 public function isVerbose()
59795 {
59796 return self::VERBOSITY_VERBOSE <= $this->verbosity;
59797 }
59798
59799
59800
59801
59802 public function isVeryVerbose()
59803 {
59804 return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
59805 }
59806
59807
59808
59809
59810 public function isDebug()
59811 {
59812 return self::VERBOSITY_DEBUG <= $this->verbosity;
59813 }
59814
59815
59816
59817
59818 public function writeln($messages, $options = self::OUTPUT_NORMAL)
59819 {
59820 $this->write($messages, true, $options);
59821 }
59822
59823
59824
59825
59826 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
59827 {
59828 $messages = (array) $messages;
59829
59830 $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
59831 $type = $types & $options ?: self::OUTPUT_NORMAL;
59832
59833 $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
59834 $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
59835
59836 if ($verbosity > $this->getVerbosity()) {
59837 return;
59838 }
59839
59840 foreach ($messages as $message) {
59841 switch ($type) {
59842 case OutputInterface::OUTPUT_NORMAL:
59843 $message = $this->formatter->format($message);
59844 break;
59845 case OutputInterface::OUTPUT_RAW:
59846 break;
59847 case OutputInterface::OUTPUT_PLAIN:
59848 $message = strip_tags($this->formatter->format($message));
59849 break;
59850 }
59851
59852 $this->doWrite($message, $newline);
59853 }
59854 }
59855
59856
59857
59858
59859
59860
59861
59862 abstract protected function doWrite($message, $newline);
59863 }
59864 <?php
59865
59866
59867
59868
59869
59870
59871
59872
59873
59874
59875 namespace Symfony\Component\Console\Output;
59876
59877 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59878
59879
59880
59881
59882
59883
59884 interface OutputInterface
59885 {
59886 const VERBOSITY_QUIET = 16;
59887 const VERBOSITY_NORMAL = 32;
59888 const VERBOSITY_VERBOSE = 64;
59889 const VERBOSITY_VERY_VERBOSE = 128;
59890 const VERBOSITY_DEBUG = 256;
59891
59892 const OUTPUT_NORMAL = 1;
59893 const OUTPUT_RAW = 2;
59894 const OUTPUT_PLAIN = 4;
59895
59896
59897
59898
59899
59900
59901
59902
59903 public function write($messages, $newline = false, $options = 0);
59904
59905
59906
59907
59908
59909
59910
59911 public function writeln($messages, $options = 0);
59912
59913
59914
59915
59916
59917
59918 public function setVerbosity($level);
59919
59920
59921
59922
59923
59924
59925 public function getVerbosity();
59926
59927
59928
59929
59930
59931
59932 public function setDecorated($decorated);
59933
59934
59935
59936
59937
59938
59939 public function isDecorated();
59940
59941 public function setFormatter(OutputFormatterInterface $formatter);
59942
59943
59944
59945
59946
59947
59948 public function getFormatter();
59949 }
59950 <?php
59951
59952
59953
59954
59955
59956
59957
59958
59959
59960
59961 namespace Symfony\Component\Console\Output;
59962
59963 use Symfony\Component\Console\Exception\InvalidArgumentException;
59964 use Symfony\Component\Console\Exception\RuntimeException;
59965 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59966
59967
59968
59969
59970
59971
59972
59973
59974
59975
59976
59977
59978
59979
59980 class StreamOutput extends Output
59981 {
59982 private $stream;
59983
59984
59985
59986
59987
59988
59989
59990
59991
59992 public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
59993 {
59994 if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
59995 throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
59996 }
59997
59998 $this->stream = $stream;
59999
60000 if (null === $decorated) {
60001 $decorated = $this->hasColorSupport();
60002 }
60003
60004 parent::__construct($verbosity, $decorated, $formatter);
60005 }
60006
60007
60008
60009
60010
60011
60012 public function getStream()
60013 {
60014 return $this->stream;
60015 }
60016
60017
60018
60019
60020 protected function doWrite($message, $newline)
60021 {
60022 if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
60023
60024  throw new RuntimeException('Unable to write output.');
60025 }
60026
60027 fflush($this->stream);
60028 }
60029
60030
60031
60032
60033
60034
60035
60036
60037
60038
60039
60040
60041
60042
60043 protected function hasColorSupport()
60044 {
60045 if ('Hyper' === getenv('TERM_PROGRAM')) {
60046 return true;
60047 }
60048
60049 if (DIRECTORY_SEPARATOR === '\\') {
60050 return (function_exists('sapi_windows_vt100_support')
60051 && @sapi_windows_vt100_support($this->stream))
60052 || false !== getenv('ANSICON')
60053 || 'ON' === getenv('ConEmuANSI')
60054 || 'xterm' === getenv('TERM');
60055 }
60056
60057 if (function_exists('stream_isatty')) {
60058 return @stream_isatty($this->stream);
60059 }
60060
60061 if (function_exists('posix_isatty')) {
60062 return @posix_isatty($this->stream);
60063 }
60064
60065 $stat = @fstat($this->stream);
60066
60067  return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
60068 }
60069 }
60070 <?php
60071
60072
60073
60074
60075
60076
60077
60078
60079
60080
60081 namespace Symfony\Component\Console\Question;
60082
60083 use Symfony\Component\Console\Exception\InvalidArgumentException;
60084
60085
60086
60087
60088
60089
60090 class ChoiceQuestion extends Question
60091 {
60092 private $choices;
60093 private $multiselect = false;
60094 private $prompt = ' > ';
60095 private $errorMessage = 'Value "%s" is invalid';
60096
60097
60098
60099
60100
60101
60102 public function __construct($question, array $choices, $default = null)
60103 {
60104 if (!$choices) {
60105 throw new \LogicException('Choice question must have at least 1 choice available.');
60106 }
60107
60108 parent::__construct($question, $default);
60109
60110 $this->choices = $choices;
60111 $this->setValidator($this->getDefaultValidator());
60112 $this->setAutocompleterValues($choices);
60113 }
60114
60115
60116
60117
60118
60119
60120 public function getChoices()
60121 {
60122 return $this->choices;
60123 }
60124
60125
60126
60127
60128
60129
60130
60131
60132
60133
60134 public function setMultiselect($multiselect)
60135 {
60136 $this->multiselect = $multiselect;
60137 $this->setValidator($this->getDefaultValidator());
60138
60139 return $this;
60140 }
60141
60142
60143
60144
60145
60146
60147 public function isMultiselect()
60148 {
60149 return $this->multiselect;
60150 }
60151
60152
60153
60154
60155
60156
60157 public function getPrompt()
60158 {
60159 return $this->prompt;
60160 }
60161
60162
60163
60164
60165
60166
60167
60168
60169 public function setPrompt($prompt)
60170 {
60171 $this->prompt = $prompt;
60172
60173 return $this;
60174 }
60175
60176
60177
60178
60179
60180
60181
60182
60183
60184
60185 public function setErrorMessage($errorMessage)
60186 {
60187 $this->errorMessage = $errorMessage;
60188 $this->setValidator($this->getDefaultValidator());
60189
60190 return $this;
60191 }
60192
60193
60194
60195
60196
60197
60198 private function getDefaultValidator()
60199 {
60200 $choices = $this->choices;
60201 $errorMessage = $this->errorMessage;
60202 $multiselect = $this->multiselect;
60203 $isAssoc = $this->isAssoc($choices);
60204
60205 return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
60206
60207  $selectedChoices = str_replace(' ', '', $selected);
60208
60209 if ($multiselect) {
60210
60211  if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
60212 throw new InvalidArgumentException(sprintf($errorMessage, $selected));
60213 }
60214 $selectedChoices = explode(',', $selectedChoices);
60215 } else {
60216 $selectedChoices = array($selected);
60217 }
60218
60219 $multiselectChoices = array();
60220 foreach ($selectedChoices as $value) {
60221 $results = array();
60222 foreach ($choices as $key => $choice) {
60223 if ($choice === $value) {
60224 $results[] = $key;
60225 }
60226 }
60227
60228 if (count($results) > 1) {
60229 throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
60230 }
60231
60232 $result = array_search($value, $choices);
60233
60234 if (!$isAssoc) {
60235 if (false !== $result) {
60236 $result = $choices[$result];
60237 } elseif (isset($choices[$value])) {
60238 $result = $choices[$value];
60239 }
60240 } elseif (false === $result && isset($choices[$value])) {
60241 $result = $value;
60242 }
60243
60244 if (false === $result) {
60245 throw new InvalidArgumentException(sprintf($errorMessage, $value));
60246 }
60247
60248 $multiselectChoices[] = (string) $result;
60249 }
60250
60251 if ($multiselect) {
60252 return $multiselectChoices;
60253 }
60254
60255 return current($multiselectChoices);
60256 };
60257 }
60258 }
60259 <?php
60260
60261
60262
60263
60264
60265
60266
60267
60268
60269
60270 namespace Symfony\Component\Console\Question;
60271
60272
60273
60274
60275
60276
60277 class ConfirmationQuestion extends Question
60278 {
60279 private $trueAnswerRegex;
60280
60281
60282
60283
60284
60285
60286 public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
60287 {
60288 parent::__construct($question, (bool) $default);
60289
60290 $this->trueAnswerRegex = $trueAnswerRegex;
60291 $this->setNormalizer($this->getDefaultNormalizer());
60292 }
60293
60294
60295
60296
60297
60298
60299 private function getDefaultNormalizer()
60300 {
60301 $default = $this->getDefault();
60302 $regex = $this->trueAnswerRegex;
60303
60304 return function ($answer) use ($default, $regex) {
60305 if (is_bool($answer)) {
60306 return $answer;
60307 }
60308
60309 $answerIsTrue = (bool) preg_match($regex, $answer);
60310 if (false === $default) {
60311 return $answer && $answerIsTrue;
60312 }
60313
60314 return !$answer || $answerIsTrue;
60315 };
60316 }
60317 }
60318 <?php
60319
60320
60321
60322
60323
60324
60325
60326
60327
60328
60329 namespace Symfony\Component\Console\Question;
60330
60331 use Symfony\Component\Console\Exception\InvalidArgumentException;
60332 use Symfony\Component\Console\Exception\LogicException;
60333
60334
60335
60336
60337
60338
60339 class Question
60340 {
60341 private $question;
60342 private $attempts;
60343 private $hidden = false;
60344 private $hiddenFallback = true;
60345 private $autocompleterValues;
60346 private $validator;
60347 private $default;
60348 private $normalizer;
60349
60350
60351
60352
60353
60354 public function __construct($question, $default = null)
60355 {
60356 $this->question = $question;
60357 $this->default = $default;
60358 }
60359
60360
60361
60362
60363
60364
60365 public function getQuestion()
60366 {
60367 return $this->question;
60368 }
60369
60370
60371
60372
60373
60374
60375 public function getDefault()
60376 {
60377 return $this->default;
60378 }
60379
60380
60381
60382
60383
60384
60385 public function isHidden()
60386 {
60387 return $this->hidden;
60388 }
60389
60390
60391
60392
60393
60394
60395
60396
60397
60398
60399 public function setHidden($hidden)
60400 {
60401 if ($this->autocompleterValues) {
60402 throw new LogicException('A hidden question cannot use the autocompleter.');
60403 }
60404
60405 $this->hidden = (bool) $hidden;
60406
60407 return $this;
60408 }
60409
60410
60411
60412
60413
60414
60415 public function isHiddenFallback()
60416 {
60417 return $this->hiddenFallback;
60418 }
60419
60420
60421
60422
60423
60424
60425
60426
60427 public function setHiddenFallback($fallback)
60428 {
60429 $this->hiddenFallback = (bool) $fallback;
60430
60431 return $this;
60432 }
60433
60434
60435
60436
60437
60438
60439 public function getAutocompleterValues()
60440 {
60441 return $this->autocompleterValues;
60442 }
60443
60444
60445
60446
60447
60448
60449
60450
60451
60452
60453
60454 public function setAutocompleterValues($values)
60455 {
60456 if (is_array($values)) {
60457 $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
60458 }
60459
60460 if (null !== $values && !is_array($values) && !$values instanceof \Traversable) {
60461 throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.');
60462 }
60463
60464 if ($this->hidden) {
60465 throw new LogicException('A hidden question cannot use the autocompleter.');
60466 }
60467
60468 $this->autocompleterValues = $values;
60469
60470 return $this;
60471 }
60472
60473
60474
60475
60476
60477
60478
60479
60480 public function setValidator($validator)
60481 {
60482 $this->validator = $validator;
60483
60484 return $this;
60485 }
60486
60487
60488
60489
60490
60491
60492 public function getValidator()
60493 {
60494 return $this->validator;
60495 }
60496
60497
60498
60499
60500
60501
60502
60503
60504
60505
60506
60507
60508 public function setMaxAttempts($attempts)
60509 {
60510 if (null !== $attempts && $attempts < 1) {
60511 throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
60512 }
60513
60514 $this->attempts = $attempts;
60515
60516 return $this;
60517 }
60518
60519
60520
60521
60522
60523
60524
60525
60526 public function getMaxAttempts()
60527 {
60528 return $this->attempts;
60529 }
60530
60531
60532
60533
60534
60535
60536
60537
60538
60539
60540 public function setNormalizer($normalizer)
60541 {
60542 $this->normalizer = $normalizer;
60543
60544 return $this;
60545 }
60546
60547
60548
60549
60550
60551
60552
60553
60554 public function getNormalizer()
60555 {
60556 return $this->normalizer;
60557 }
60558
60559 protected function isAssoc($array)
60560 {
60561 return (bool) count(array_filter(array_keys($array), 'is_string'));
60562 }
60563 }
60564 <?php
60565
60566
60567
60568
60569
60570
60571
60572
60573
60574
60575 namespace Symfony\Component\Console;
60576
60577 use Symfony\Component\Console\Exception\RuntimeException;
60578 use Symfony\Component\Console\Input\StringInput;
60579 use Symfony\Component\Console\Output\ConsoleOutput;
60580 use Symfony\Component\Process\ProcessBuilder;
60581 use Symfony\Component\Process\PhpExecutableFinder;
60582
60583
60584
60585
60586
60587
60588
60589
60590
60591
60592
60593
60594 class Shell
60595 {
60596 private $application;
60597 private $history;
60598 private $output;
60599 private $hasReadline;
60600 private $processIsolation = false;
60601
60602
60603
60604
60605
60606 public function __construct(Application $application)
60607 {
60608 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
60609
60610 $this->hasReadline = function_exists('readline');
60611 $this->application = $application;
60612 $this->history = getenv('HOME').'/.history_'.$application->getName();
60613 $this->output = new ConsoleOutput();
60614 }
60615
60616
60617
60618
60619 public function run()
60620 {
60621 $this->application->setAutoExit(false);
60622 $this->application->setCatchExceptions(true);
60623
60624 if ($this->hasReadline) {
60625 readline_read_history($this->history);
60626 readline_completion_function(array($this, 'autocompleter'));
60627 }
60628
60629 $this->output->writeln($this->getHeader());
60630 $php = null;
60631 if ($this->processIsolation) {
60632 $finder = new PhpExecutableFinder();
60633 $php = $finder->find();
60634 $this->output->writeln(<<<'EOF'
60635 <info>Running with process isolation, you should consider this:</info>
60636   * each command is executed as separate process,
60637   * commands don't support interactivity, all params must be passed explicitly,
60638   * commands output is not colorized.
60639
60640 EOF
60641 );
60642 }
60643
60644 while (true) {
60645 $command = $this->readline();
60646
60647 if (false === $command) {
60648 $this->output->writeln("\n");
60649
60650 break;
60651 }
60652
60653 if ($this->hasReadline) {
60654 readline_add_history($command);
60655 readline_write_history($this->history);
60656 }
60657
60658 if ($this->processIsolation) {
60659 $pb = new ProcessBuilder();
60660
60661 $process = $pb
60662 ->add($php)
60663 ->add($_SERVER['argv'][0])
60664 ->add($command)
60665 ->inheritEnvironmentVariables(true)
60666 ->getProcess()
60667 ;
60668
60669 $output = $this->output;
60670 $process->run(function ($type, $data) use ($output) {
60671 $output->writeln($data);
60672 });
60673
60674 $ret = $process->getExitCode();
60675 } else {
60676 $ret = $this->application->run(new StringInput($command), $this->output);
60677 }
60678
60679 if (0 !== $ret) {
60680 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
60681 }
60682 }
60683 }
60684
60685
60686
60687
60688
60689
60690 protected function getHeader()
60691 {
60692 return <<<EOF
60693
60694 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
60695
60696 At the prompt, type <comment>help</comment> for some help,
60697 or <comment>list</comment> to get a list of available commands.
60698
60699 To exit the shell, type <comment>^D</comment>.
60700
60701 EOF;
60702 }
60703
60704
60705
60706
60707
60708
60709 protected function getPrompt()
60710 {
60711
60712  return $this->output->getFormatter()->format($this->application->getName().' > ');
60713 }
60714
60715 protected function getOutput()
60716 {
60717 return $this->output;
60718 }
60719
60720 protected function getApplication()
60721 {
60722 return $this->application;
60723 }
60724
60725
60726
60727
60728
60729
60730
60731
60732 private function autocompleter($text)
60733 {
60734 $info = readline_info();
60735 $text = substr($info['line_buffer'], 0, $info['end']);
60736
60737 if ($info['point'] !== $info['end']) {
60738 return true;
60739 }
60740
60741
60742  if (false === strpos($text, ' ') || !$text) {
60743 return array_keys($this->application->all());
60744 }
60745
60746
60747  try {
60748 $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
60749 } catch (\Exception $e) {
60750 return true;
60751 }
60752
60753 $list = array('--help');
60754 foreach ($command->getDefinition()->getOptions() as $option) {
60755 $list[] = '--'.$option->getName();
60756 }
60757
60758 return $list;
60759 }
60760
60761
60762
60763
60764
60765
60766 private function readline()
60767 {
60768 if ($this->hasReadline) {
60769 $line = readline($this->getPrompt());
60770 } else {
60771 $this->output->write($this->getPrompt());
60772 $line = fgets(STDIN, 1024);
60773 $line = (false === $line || '' === $line) ? false : rtrim($line);
60774 }
60775
60776 return $line;
60777 }
60778
60779 public function getProcessIsolation()
60780 {
60781 return $this->processIsolation;
60782 }
60783
60784 public function setProcessIsolation($processIsolation)
60785 {
60786 $this->processIsolation = (bool) $processIsolation;
60787
60788 if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
60789 throw new RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
60790 }
60791 }
60792 }
60793 <?php
60794
60795
60796
60797
60798
60799
60800
60801
60802
60803
60804 namespace Symfony\Component\Console\Style;
60805
60806 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
60807 use Symfony\Component\Console\Helper\ProgressBar;
60808 use Symfony\Component\Console\Output\OutputInterface;
60809
60810
60811
60812
60813
60814
60815 abstract class OutputStyle implements OutputInterface, StyleInterface
60816 {
60817 private $output;
60818
60819 public function __construct(OutputInterface $output)
60820 {
60821 $this->output = $output;
60822 }
60823
60824
60825
60826
60827 public function newLine($count = 1)
60828 {
60829 $this->output->write(str_repeat(PHP_EOL, $count));
60830 }
60831
60832
60833
60834
60835
60836
60837 public function createProgressBar($max = 0)
60838 {
60839 return new ProgressBar($this->output, $max);
60840 }
60841
60842
60843
60844
60845 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
60846 {
60847 $this->output->write($messages, $newline, $type);
60848 }
60849
60850
60851
60852
60853 public function writeln($messages, $type = self::OUTPUT_NORMAL)
60854 {
60855 $this->output->writeln($messages, $type);
60856 }
60857
60858
60859
60860
60861 public function setVerbosity($level)
60862 {
60863 $this->output->setVerbosity($level);
60864 }
60865
60866
60867
60868
60869 public function getVerbosity()
60870 {
60871 return $this->output->getVerbosity();
60872 }
60873
60874
60875
60876
60877 public function setDecorated($decorated)
60878 {
60879 $this->output->setDecorated($decorated);
60880 }
60881
60882
60883
60884
60885 public function isDecorated()
60886 {
60887 return $this->output->isDecorated();
60888 }
60889
60890
60891
60892
60893 public function setFormatter(OutputFormatterInterface $formatter)
60894 {
60895 $this->output->setFormatter($formatter);
60896 }
60897
60898
60899
60900
60901 public function getFormatter()
60902 {
60903 return $this->output->getFormatter();
60904 }
60905 }
60906 <?php
60907
60908
60909
60910
60911
60912
60913
60914
60915
60916
60917 namespace Symfony\Component\Console\Style;
60918
60919
60920
60921
60922
60923
60924 interface StyleInterface
60925 {
60926
60927
60928
60929
60930
60931 public function title($message);
60932
60933
60934
60935
60936
60937
60938 public function section($message);
60939
60940
60941
60942
60943 public function listing(array $elements);
60944
60945
60946
60947
60948
60949
60950 public function text($message);
60951
60952
60953
60954
60955
60956
60957 public function success($message);
60958
60959
60960
60961
60962
60963
60964 public function error($message);
60965
60966
60967
60968
60969
60970
60971 public function warning($message);
60972
60973
60974
60975
60976
60977
60978 public function note($message);
60979
60980
60981
60982
60983
60984
60985 public function caution($message);
60986
60987
60988
60989
60990 public function table(array $headers, array $rows);
60991
60992
60993
60994
60995
60996
60997
60998
60999
61000
61001 public function ask($question, $default = null, $validator = null);
61002
61003
61004
61005
61006
61007
61008
61009
61010
61011 public function askHidden($question, $validator = null);
61012
61013
61014
61015
61016
61017
61018
61019
61020
61021 public function confirm($question, $default = true);
61022
61023
61024
61025
61026
61027
61028
61029
61030
61031
61032 public function choice($question, array $choices, $default = null);
61033
61034
61035
61036
61037
61038
61039 public function newLine($count = 1);
61040
61041
61042
61043
61044
61045
61046 public function progressStart($max = 0);
61047
61048
61049
61050
61051
61052
61053 public function progressAdvance($step = 1);
61054
61055
61056
61057
61058 public function progressFinish();
61059 }
61060 <?php
61061
61062
61063
61064
61065
61066
61067
61068
61069
61070
61071 namespace Symfony\Component\Console\Style;
61072
61073 use Symfony\Component\Console\Application;
61074 use Symfony\Component\Console\Exception\RuntimeException;
61075 use Symfony\Component\Console\Formatter\OutputFormatter;
61076 use Symfony\Component\Console\Helper\Helper;
61077 use Symfony\Component\Console\Helper\ProgressBar;
61078 use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
61079 use Symfony\Component\Console\Helper\Table;
61080 use Symfony\Component\Console\Input\InputInterface;
61081 use Symfony\Component\Console\Output\BufferedOutput;
61082 use Symfony\Component\Console\Output\OutputInterface;
61083 use Symfony\Component\Console\Question\ChoiceQuestion;
61084 use Symfony\Component\Console\Question\ConfirmationQuestion;
61085 use Symfony\Component\Console\Question\Question;
61086
61087
61088
61089
61090
61091
61092 class SymfonyStyle extends OutputStyle
61093 {
61094 const MAX_LINE_LENGTH = 120;
61095
61096 private $input;
61097 private $questionHelper;
61098 private $progressBar;
61099 private $lineLength;
61100 private $bufferedOutput;
61101
61102 public function __construct(InputInterface $input, OutputInterface $output)
61103 {
61104 $this->input = $input;
61105 $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
61106
61107  $this->lineLength = min($this->getTerminalWidth() - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
61108
61109 parent::__construct($output);
61110 }
61111
61112
61113
61114
61115
61116
61117
61118
61119
61120
61121 public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
61122 {
61123 $messages = is_array($messages) ? array_values($messages) : array($messages);
61124
61125 $this->autoPrependBlock();
61126 $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, true));
61127 $this->newLine();
61128 }
61129
61130
61131
61132
61133 public function title($message)
61134 {
61135 $this->autoPrependBlock();
61136 $this->writeln(array(
61137 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
61138 sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
61139 ));
61140 $this->newLine();
61141 }
61142
61143
61144
61145
61146 public function section($message)
61147 {
61148 $this->autoPrependBlock();
61149 $this->writeln(array(
61150 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
61151 sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
61152 ));
61153 $this->newLine();
61154 }
61155
61156
61157
61158
61159 public function listing(array $elements)
61160 {
61161 $this->autoPrependText();
61162 $elements = array_map(function ($element) {
61163 return sprintf(' * %s', $element);
61164 }, $elements);
61165
61166 $this->writeln($elements);
61167 $this->newLine();
61168 }
61169
61170
61171
61172
61173 public function text($message)
61174 {
61175 $this->autoPrependText();
61176
61177 $messages = is_array($message) ? array_values($message) : array($message);
61178 foreach ($messages as $message) {
61179 $this->writeln(sprintf(' %s', $message));
61180 }
61181 }
61182
61183
61184
61185
61186
61187
61188 public function comment($message)
61189 {
61190 $messages = is_array($message) ? array_values($message) : array($message);
61191
61192 $this->autoPrependBlock();
61193 $this->writeln($this->createBlock($messages, null, null, '<fg=default;bg=default> // </>'));
61194 $this->newLine();
61195 }
61196
61197
61198
61199
61200 public function success($message)
61201 {
61202 $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
61203 }
61204
61205
61206
61207
61208 public function error($message)
61209 {
61210 $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
61211 }
61212
61213
61214
61215
61216 public function warning($message)
61217 {
61218 $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
61219 }
61220
61221
61222
61223
61224 public function note($message)
61225 {
61226 $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
61227 }
61228
61229
61230
61231
61232 public function caution($message)
61233 {
61234 $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
61235 }
61236
61237
61238
61239
61240 public function table(array $headers, array $rows)
61241 {
61242 $style = clone Table::getStyleDefinition('symfony-style-guide');
61243 $style->setCellHeaderFormat('<info>%s</info>');
61244
61245 $table = new Table($this);
61246 $table->setHeaders($headers);
61247 $table->setRows($rows);
61248 $table->setStyle($style);
61249
61250 $table->render();
61251 $this->newLine();
61252 }
61253
61254
61255
61256
61257 public function ask($question, $default = null, $validator = null)
61258 {
61259 $question = new Question($question, $default);
61260 $question->setValidator($validator);
61261
61262 return $this->askQuestion($question);
61263 }
61264
61265
61266
61267
61268 public function askHidden($question, $validator = null)
61269 {
61270 $question = new Question($question);
61271
61272 $question->setHidden(true);
61273 $question->setValidator($validator);
61274
61275 return $this->askQuestion($question);
61276 }
61277
61278
61279
61280
61281 public function confirm($question, $default = true)
61282 {
61283 return $this->askQuestion(new ConfirmationQuestion($question, $default));
61284 }
61285
61286
61287
61288
61289 public function choice($question, array $choices, $default = null)
61290 {
61291 if (null !== $default) {
61292 $values = array_flip($choices);
61293 $default = $values[$default];
61294 }
61295
61296 return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
61297 }
61298
61299
61300
61301
61302 public function progressStart($max = 0)
61303 {
61304 $this->progressBar = $this->createProgressBar($max);
61305 $this->progressBar->start();
61306 }
61307
61308
61309
61310
61311 public function progressAdvance($step = 1)
61312 {
61313 $this->getProgressBar()->advance($step);
61314 }
61315
61316
61317
61318
61319 public function progressFinish()
61320 {
61321 $this->getProgressBar()->finish();
61322 $this->newLine(2);
61323 $this->progressBar = null;
61324 }
61325
61326
61327
61328
61329 public function createProgressBar($max = 0)
61330 {
61331 $progressBar = parent::createProgressBar($max);
61332
61333 if ('\\' !== DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) {
61334 $progressBar->setEmptyBarCharacter('░'); 
61335  $progressBar->setProgressCharacter('');
61336 $progressBar->setBarCharacter('▓'); 
61337  }
61338
61339 return $progressBar;
61340 }
61341
61342
61343
61344
61345 public function askQuestion(Question $question)
61346 {
61347 if ($this->input->isInteractive()) {
61348 $this->autoPrependBlock();
61349 }
61350
61351 if (!$this->questionHelper) {
61352 $this->questionHelper = new SymfonyQuestionHelper();
61353 }
61354
61355 $answer = $this->questionHelper->ask($this->input, $this, $question);
61356
61357 if ($this->input->isInteractive()) {
61358 $this->newLine();
61359 $this->bufferedOutput->write("\n");
61360 }
61361
61362 return $answer;
61363 }
61364
61365
61366
61367
61368 public function writeln($messages, $type = self::OUTPUT_NORMAL)
61369 {
61370 parent::writeln($messages, $type);
61371 $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
61372 }
61373
61374
61375
61376
61377 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
61378 {
61379 parent::write($messages, $newline, $type);
61380 $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
61381 }
61382
61383
61384
61385
61386 public function newLine($count = 1)
61387 {
61388 parent::newLine($count);
61389 $this->bufferedOutput->write(str_repeat("\n", $count));
61390 }
61391
61392
61393
61394
61395 private function getProgressBar()
61396 {
61397 if (!$this->progressBar) {
61398 throw new RuntimeException('The ProgressBar is not started.');
61399 }
61400
61401 return $this->progressBar;
61402 }
61403
61404 private function getTerminalWidth()
61405 {
61406 $application = new Application();
61407 $dimensions = $application->getTerminalDimensions();
61408
61409 return $dimensions[0] ?: self::MAX_LINE_LENGTH;
61410 }
61411
61412 private function autoPrependBlock()
61413 {
61414 $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
61415
61416 if (!isset($chars[0])) {
61417 return $this->newLine(); 
61418  }
61419
61420  $this->newLine(2 - substr_count($chars, "\n"));
61421 }
61422
61423 private function autoPrependText()
61424 {
61425 $fetched = $this->bufferedOutput->fetch();
61426
61427  if ("\n" !== substr($fetched, -1)) {
61428 $this->newLine();
61429 }
61430 }
61431
61432 private function reduceBuffer($messages)
61433 {
61434
61435  
61436  return array_map(function ($value) {
61437 return substr($value, -4);
61438 }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
61439 }
61440
61441 private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
61442 {
61443 $indentLength = 0;
61444 $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
61445 $lines = array();
61446
61447 if (null !== $type) {
61448 $type = sprintf('[%s] ', $type);
61449 $indentLength = strlen($type);
61450 $lineIndentation = str_repeat(' ', $indentLength);
61451 }
61452
61453
61454  foreach ($messages as $key => $message) {
61455 if ($escape) {
61456 $message = OutputFormatter::escape($message);
61457 }
61458
61459 $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
61460
61461 if (count($messages) > 1 && $key < count($messages) - 1) {
61462 $lines[] = '';
61463 }
61464 }
61465
61466 $firstLineIndex = 0;
61467 if ($padding && $this->isDecorated()) {
61468 $firstLineIndex = 1;
61469 array_unshift($lines, '');
61470 $lines[] = '';
61471 }
61472
61473 foreach ($lines as $i => &$line) {
61474 if (null !== $type) {
61475 $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
61476 }
61477
61478 $line = $prefix.$line;
61479 $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
61480
61481 if ($style) {
61482 $line = sprintf('<%s>%s</>', $style, $line);
61483 }
61484 }
61485
61486 return $lines;
61487 }
61488 }
61489 <?php
61490
61491
61492
61493
61494
61495
61496
61497
61498
61499
61500 namespace Symfony\Component\Console\Tester;
61501
61502 use Symfony\Component\Console\Application;
61503 use Symfony\Component\Console\Input\ArrayInput;
61504 use Symfony\Component\Console\Input\InputInterface;
61505 use Symfony\Component\Console\Output\OutputInterface;
61506 use Symfony\Component\Console\Output\StreamOutput;
61507
61508
61509
61510
61511
61512
61513
61514
61515
61516
61517
61518 class ApplicationTester
61519 {
61520 private $application;
61521 private $input;
61522 private $output;
61523 private $statusCode;
61524
61525 public function __construct(Application $application)
61526 {
61527 $this->application = $application;
61528 }
61529
61530
61531
61532
61533
61534
61535
61536
61537
61538
61539
61540
61541
61542
61543
61544 public function run(array $input, $options = array())
61545 {
61546 $this->input = new ArrayInput($input);
61547 if (isset($options['interactive'])) {
61548 $this->input->setInteractive($options['interactive']);
61549 }
61550
61551 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
61552 if (isset($options['decorated'])) {
61553 $this->output->setDecorated($options['decorated']);
61554 }
61555 if (isset($options['verbosity'])) {
61556 $this->output->setVerbosity($options['verbosity']);
61557 }
61558
61559 return $this->statusCode = $this->application->run($this->input, $this->output);
61560 }
61561
61562
61563
61564
61565
61566
61567
61568
61569 public function getDisplay($normalize = false)
61570 {
61571 rewind($this->output->getStream());
61572
61573 $display = stream_get_contents($this->output->getStream());
61574
61575 if ($normalize) {
61576 $display = str_replace(PHP_EOL, "\n", $display);
61577 }
61578
61579 return $display;
61580 }
61581
61582
61583
61584
61585
61586
61587 public function getInput()
61588 {
61589 return $this->input;
61590 }
61591
61592
61593
61594
61595
61596
61597 public function getOutput()
61598 {
61599 return $this->output;
61600 }
61601
61602
61603
61604
61605
61606
61607 public function getStatusCode()
61608 {
61609 return $this->statusCode;
61610 }
61611 }
61612 <?php
61613
61614
61615
61616
61617
61618
61619
61620
61621
61622
61623 namespace Symfony\Component\Console\Tester;
61624
61625 use Symfony\Component\Console\Command\Command;
61626 use Symfony\Component\Console\Input\ArrayInput;
61627 use Symfony\Component\Console\Output\StreamOutput;
61628 use Symfony\Component\Console\Input\InputInterface;
61629 use Symfony\Component\Console\Output\OutputInterface;
61630
61631
61632
61633
61634
61635
61636 class CommandTester
61637 {
61638 private $command;
61639 private $input;
61640 private $output;
61641 private $statusCode;
61642
61643 public function __construct(Command $command)
61644 {
61645 $this->command = $command;
61646 }
61647
61648
61649
61650
61651
61652
61653
61654
61655
61656
61657
61658
61659
61660
61661
61662 public function execute(array $input, array $options = array())
61663 {
61664
61665  
61666  if (!isset($input['command'])
61667 && (null !== $application = $this->command->getApplication())
61668 && $application->getDefinition()->hasArgument('command')
61669 ) {
61670 $input = array_merge(array('command' => $this->command->getName()), $input);
61671 }
61672
61673 $this->input = new ArrayInput($input);
61674 if (isset($options['interactive'])) {
61675 $this->input->setInteractive($options['interactive']);
61676 }
61677
61678 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
61679 $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
61680 if (isset($options['verbosity'])) {
61681 $this->output->setVerbosity($options['verbosity']);
61682 }
61683
61684 return $this->statusCode = $this->command->run($this->input, $this->output);
61685 }
61686
61687
61688
61689
61690
61691
61692
61693
61694 public function getDisplay($normalize = false)
61695 {
61696 rewind($this->output->getStream());
61697
61698 $display = stream_get_contents($this->output->getStream());
61699
61700 if ($normalize) {
61701 $display = str_replace(PHP_EOL, "\n", $display);
61702 }
61703
61704 return $display;
61705 }
61706
61707
61708
61709
61710
61711
61712 public function getInput()
61713 {
61714 return $this->input;
61715 }
61716
61717
61718
61719
61720
61721
61722 public function getOutput()
61723 {
61724 return $this->output;
61725 }
61726
61727
61728
61729
61730
61731
61732 public function getStatusCode()
61733 {
61734 return $this->statusCode;
61735 }
61736 }
61737 <?php
61738
61739
61740
61741
61742
61743
61744
61745
61746
61747
61748 namespace Symfony\Component\Debug;
61749
61750 use Psr\Log\AbstractLogger;
61751
61752
61753
61754
61755
61756
61757 class BufferingLogger extends AbstractLogger
61758 {
61759 private $logs = array();
61760
61761 public function log($level, $message, array $context = array())
61762 {
61763 $this->logs[] = array($level, $message, $context);
61764 }
61765
61766 public function cleanLogs()
61767 {
61768 $logs = $this->logs;
61769 $this->logs = array();
61770
61771 return $logs;
61772 }
61773 }
61774 <?php
61775
61776
61777
61778
61779
61780
61781
61782
61783
61784
61785 namespace Symfony\Component\Debug;
61786
61787
61788
61789
61790
61791
61792 class Debug
61793 {
61794 private static $enabled = false;
61795
61796
61797
61798
61799
61800
61801
61802
61803
61804 public static function enable($errorReportingLevel = null, $displayErrors = true)
61805 {
61806 if (static::$enabled) {
61807 return;
61808 }
61809
61810 static::$enabled = true;
61811
61812 if (null !== $errorReportingLevel) {
61813 error_reporting($errorReportingLevel);
61814 } else {
61815 error_reporting(-1);
61816 }
61817
61818 if (!\in_array(PHP_SAPI, array('cli', 'phpdbg'), true)) {
61819 ini_set('display_errors', 0);
61820 ExceptionHandler::register();
61821 } elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
61822
61823  ini_set('display_errors', 1);
61824 }
61825 if ($displayErrors) {
61826 ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
61827 } else {
61828 ErrorHandler::register()->throwAt(0, true);
61829 }
61830
61831 DebugClassLoader::enable();
61832 }
61833 }
61834 <?php
61835
61836
61837
61838
61839
61840
61841
61842
61843
61844
61845 namespace Symfony\Component\Debug;
61846
61847
61848
61849
61850
61851
61852
61853
61854
61855
61856
61857
61858 class DebugClassLoader
61859 {
61860 private $classLoader;
61861 private $isFinder;
61862 private $loaded = array();
61863 private $wasFinder;
61864 private static $caseCheck;
61865 private static $deprecated = array();
61866 private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
61867 private static $darwinCache = array('/' => array('/', array()));
61868
61869
61870
61871
61872 public function __construct($classLoader)
61873 {
61874 $this->wasFinder = is_object($classLoader) && method_exists($classLoader, 'findFile');
61875
61876 if ($this->wasFinder) {
61877 @trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
61878 $this->classLoader = array($classLoader, 'loadClass');
61879 $this->isFinder = true;
61880 } else {
61881 $this->classLoader = $classLoader;
61882 $this->isFinder = is_array($classLoader) && method_exists($classLoader[0], 'findFile');
61883 }
61884
61885 if (!isset(self::$caseCheck)) {
61886 $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR);
61887 $i = strrpos($file, DIRECTORY_SEPARATOR);
61888 $dir = substr($file, 0, 1 + $i);
61889 $file = substr($file, 1 + $i);
61890 $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
61891 $test = realpath($dir.$test);
61892
61893 if (false === $test || false === $i) {
61894
61895  self::$caseCheck = 0;
61896 } elseif (substr($test, -strlen($file)) === $file) {
61897
61898  self::$caseCheck = 1;
61899 } elseif (false !== stripos(PHP_OS, 'darwin')) {
61900
61901  self::$caseCheck = 2;
61902 } else {
61903
61904  self::$caseCheck = 0;
61905 }
61906 }
61907 }
61908
61909
61910
61911
61912
61913
61914 public function getClassLoader()
61915 {
61916 return $this->wasFinder ? $this->classLoader[0] : $this->classLoader;
61917 }
61918
61919
61920
61921
61922 public static function enable()
61923 {
61924
61925  class_exists('Symfony\Component\Debug\ErrorHandler');
61926 class_exists('Psr\Log\LogLevel');
61927
61928 if (!is_array($functions = spl_autoload_functions())) {
61929 return;
61930 }
61931
61932 foreach ($functions as $function) {
61933 spl_autoload_unregister($function);
61934 }
61935
61936 foreach ($functions as $function) {
61937 if (!is_array($function) || !$function[0] instanceof self) {
61938 $function = array(new static($function), 'loadClass');
61939 }
61940
61941 spl_autoload_register($function);
61942 }
61943 }
61944
61945
61946
61947
61948 public static function disable()
61949 {
61950 if (!is_array($functions = spl_autoload_functions())) {
61951 return;
61952 }
61953
61954 foreach ($functions as $function) {
61955 spl_autoload_unregister($function);
61956 }
61957
61958 foreach ($functions as $function) {
61959 if (is_array($function) && $function[0] instanceof self) {
61960 $function = $function[0]->getClassLoader();
61961 }
61962
61963 spl_autoload_register($function);
61964 }
61965 }
61966
61967
61968
61969
61970
61971
61972
61973
61974
61975
61976 public function findFile($class)
61977 {
61978 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
61979
61980 if ($this->wasFinder) {
61981 return $this->classLoader[0]->findFile($class);
61982 }
61983 }
61984
61985
61986
61987
61988
61989
61990
61991
61992
61993
61994 public function loadClass($class)
61995 {
61996 ErrorHandler::stackErrors();
61997
61998 try {
61999 if ($this->isFinder && !isset($this->loaded[$class])) {
62000 $this->loaded[$class] = true;
62001 if ($file = $this->classLoader[0]->findFile($class)) {
62002 require $file;
62003 }
62004 } else {
62005 call_user_func($this->classLoader, $class);
62006 $file = false;
62007 }
62008 } catch (\Exception $e) {
62009 ErrorHandler::unstackErrors();
62010
62011 throw $e;
62012 } catch (\Throwable $e) {
62013 ErrorHandler::unstackErrors();
62014
62015 throw $e;
62016 }
62017
62018 ErrorHandler::unstackErrors();
62019
62020 $exists = class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
62021
62022 if ($class && '\\' === $class[0]) {
62023 $class = substr($class, 1);
62024 }
62025
62026 if ($exists) {
62027 $refl = new \ReflectionClass($class);
62028 $name = $refl->getName();
62029
62030 if ($name !== $class && 0 === strcasecmp($name, $class)) {
62031 throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name));
62032 }
62033
62034 if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
62035 @trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
62036 } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
62037 self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
62038 } else {
62039 if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
62040 $len = 0;
62041 $ns = '';
62042 } else {
62043 $ns = substr($name, 0, $len);
62044 }
62045 $parent = get_parent_class($class);
62046
62047 if (!$parent || strncmp($ns, $parent, $len)) {
62048 if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
62049 @trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
62050 }
62051
62052 $parentInterfaces = array();
62053 $deprecatedInterfaces = array();
62054 if ($parent) {
62055 foreach (class_implements($parent) as $interface) {
62056 $parentInterfaces[$interface] = 1;
62057 }
62058 }
62059
62060 foreach ($refl->getInterfaceNames() as $interface) {
62061 if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
62062 $deprecatedInterfaces[] = $interface;
62063 }
62064 foreach (class_implements($interface) as $interface) {
62065 $parentInterfaces[$interface] = 1;
62066 }
62067 }
62068
62069 foreach ($deprecatedInterfaces as $interface) {
62070 if (!isset($parentInterfaces[$interface])) {
62071 @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);
62072 }
62073 }
62074 }
62075 }
62076 }
62077
62078 if ($file) {
62079 if (!$exists) {
62080 if (false !== strpos($class, '/')) {
62081 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));
62082 }
62083
62084 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));
62085 }
62086 if (self::$caseCheck) {
62087 $real = explode('\\', $class.strrchr($file, '.'));
62088 $tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file));
62089
62090 $i = count($tail) - 1;
62091 $j = count($real) - 1;
62092
62093 while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
62094 --$i;
62095 --$j;
62096 }
62097
62098 array_splice($tail, 0, $i + 1);
62099 }
62100 if (self::$caseCheck && $tail) {
62101 $tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail);
62102 $tailLen = strlen($tail);
62103 $real = $refl->getFileName();
62104
62105 if (2 === self::$caseCheck) {
62106
62107
62108 $i = 1 + strrpos($real, '/');
62109 $file = substr($real, $i);
62110 $real = substr($real, 0, $i);
62111
62112 if (isset(self::$darwinCache[$real])) {
62113 $kDir = $real;
62114 } else {
62115 $kDir = strtolower($real);
62116
62117 if (isset(self::$darwinCache[$kDir])) {
62118 $real = self::$darwinCache[$kDir][0];
62119 } else {
62120 $dir = getcwd();
62121 chdir($real);
62122 $real = getcwd().'/';
62123 chdir($dir);
62124
62125 $dir = $real;
62126 $k = $kDir;
62127 $i = strlen($dir) - 1;
62128 while (!isset(self::$darwinCache[$k])) {
62129 self::$darwinCache[$k] = array($dir, array());
62130 self::$darwinCache[$dir] = &self::$darwinCache[$k];
62131
62132 while ('/' !== $dir[--$i]) {
62133 }
62134 $k = substr($k, 0, ++$i);
62135 $dir = substr($dir, 0, $i--);
62136 }
62137 }
62138 }
62139
62140 $dirFiles = self::$darwinCache[$kDir][1];
62141
62142 if (isset($dirFiles[$file])) {
62143 $kFile = $file;
62144 } else {
62145 $kFile = strtolower($file);
62146
62147 if (!isset($dirFiles[$kFile])) {
62148 foreach (scandir($real, 2) as $f) {
62149 if ('.' !== $f[0]) {
62150 $dirFiles[$f] = $f;
62151 if ($f === $file) {
62152 $kFile = $k = $file;
62153 } elseif ($f !== $k = strtolower($f)) {
62154 $dirFiles[$k] = $f;
62155 }
62156 }
62157 }
62158 self::$darwinCache[$kDir][1] = $dirFiles;
62159 }
62160 }
62161
62162 $real .= $dirFiles[$kFile];
62163 }
62164
62165 if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
62166 && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
62167 ) {
62168 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)));
62169 }
62170 }
62171
62172 return true;
62173 }
62174 }
62175 }
62176 <?php
62177
62178
62179
62180
62181
62182
62183
62184
62185
62186
62187 namespace Symfony\Component\Debug;
62188
62189 use Psr\Log\LogLevel;
62190 use Psr\Log\LoggerInterface;
62191 use Symfony\Component\Debug\Exception\ContextErrorException;
62192 use Symfony\Component\Debug\Exception\FatalErrorException;
62193 use Symfony\Component\Debug\Exception\FatalThrowableError;
62194 use Symfony\Component\Debug\Exception\OutOfMemoryException;
62195 use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
62196 use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
62197 use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
62198 use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
62199
62200
62201
62202
62203
62204
62205
62206
62207
62208
62209
62210
62211
62212
62213
62214
62215
62216
62217
62218
62219
62220
62221
62222 class ErrorHandler
62223 {
62224
62225
62226
62227 const TYPE_DEPRECATION = -100;
62228
62229 private $levels = array(
62230 E_DEPRECATED => 'Deprecated',
62231 E_USER_DEPRECATED => 'User Deprecated',
62232 E_NOTICE => 'Notice',
62233 E_USER_NOTICE => 'User Notice',
62234 E_STRICT => 'Runtime Notice',
62235 E_WARNING => 'Warning',
62236 E_USER_WARNING => 'User Warning',
62237 E_COMPILE_WARNING => 'Compile Warning',
62238 E_CORE_WARNING => 'Core Warning',
62239 E_USER_ERROR => 'User Error',
62240 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
62241 E_COMPILE_ERROR => 'Compile Error',
62242 E_PARSE => 'Parse Error',
62243 E_ERROR => 'Error',
62244 E_CORE_ERROR => 'Core Error',
62245 );
62246
62247 private $loggers = array(
62248 E_DEPRECATED => array(null, LogLevel::INFO),
62249 E_USER_DEPRECATED => array(null, LogLevel::INFO),
62250 E_NOTICE => array(null, LogLevel::WARNING),
62251 E_USER_NOTICE => array(null, LogLevel::WARNING),
62252 E_STRICT => array(null, LogLevel::WARNING),
62253 E_WARNING => array(null, LogLevel::WARNING),
62254 E_USER_WARNING => array(null, LogLevel::WARNING),
62255 E_COMPILE_WARNING => array(null, LogLevel::WARNING),
62256 E_CORE_WARNING => array(null, LogLevel::WARNING),
62257 E_USER_ERROR => array(null, LogLevel::CRITICAL),
62258 E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
62259 E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
62260 E_PARSE => array(null, LogLevel::CRITICAL),
62261 E_ERROR => array(null, LogLevel::CRITICAL),
62262 E_CORE_ERROR => array(null, LogLevel::CRITICAL),
62263 );
62264
62265 private $thrownErrors = 0x1FFF; 
62266  private $scopedErrors = 0x1FFF; 
62267  private $tracedErrors = 0x77FB; 
62268  private $screamedErrors = 0x55; 
62269  private $loggedErrors = 0;
62270
62271 private $loggedTraces = array();
62272 private $isRecursive = 0;
62273 private $isRoot = false;
62274 private $exceptionHandler;
62275 private $bootstrappingLogger;
62276
62277 private static $reservedMemory;
62278 private static $stackedErrors = array();
62279 private static $stackedErrorLevels = array();
62280 private static $toStringException = null;
62281 private static $exitCode = 0;
62282
62283
62284
62285
62286
62287
62288 private $displayErrors = 0x1FFF;
62289
62290
62291
62292
62293
62294
62295
62296
62297
62298 public static function register($handler = null, $replace = true)
62299 {
62300 if (null === self::$reservedMemory) {
62301 self::$reservedMemory = str_repeat('x', 10240);
62302 register_shutdown_function(__CLASS__.'::handleFatalError');
62303 }
62304
62305 $levels = -1;
62306
62307 if ($handlerIsNew = !$handler instanceof self) {
62308
62309  if (null !== $handler) {
62310 $levels = $replace ? $handler : 0;
62311 $replace = true;
62312 }
62313 $handler = new static();
62314 }
62315
62316 if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
62317 restore_error_handler();
62318
62319  set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
62320 $handler->isRoot = true;
62321 }
62322
62323 if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) {
62324 $handler = $prev[0];
62325 $replace = false;
62326 }
62327 if (!$replace && $prev) {
62328 restore_error_handler();
62329 $handlerIsRegistered = is_array($prev) && $handler === $prev[0];
62330 } else {
62331 $handlerIsRegistered = true;
62332 }
62333 if (is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] instanceof self) {
62334 restore_exception_handler();
62335 if (!$handlerIsRegistered) {
62336 $handler = $prev[0];
62337 } elseif ($handler !== $prev[0] && $replace) {
62338 set_exception_handler(array($handler, 'handleException'));
62339 $p = $prev[0]->setExceptionHandler(null);
62340 $handler->setExceptionHandler($p);
62341 $prev[0]->setExceptionHandler($p);
62342 }
62343 } else {
62344 $handler->setExceptionHandler($prev);
62345 }
62346
62347 $handler->throwAt($levels & $handler->thrownErrors, true);
62348
62349 return $handler;
62350 }
62351
62352 public function __construct(BufferingLogger $bootstrappingLogger = null)
62353 {
62354 if ($bootstrappingLogger) {
62355 $this->bootstrappingLogger = $bootstrappingLogger;
62356 $this->setDefaultLogger($bootstrappingLogger);
62357 }
62358 }
62359
62360
62361
62362
62363
62364
62365
62366
62367 public function setDefaultLogger(LoggerInterface $logger, $levels = null, $replace = false)
62368 {
62369 $loggers = array();
62370
62371 if (is_array($levels)) {
62372 foreach ($levels as $type => $logLevel) {
62373 if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
62374 $loggers[$type] = array($logger, $logLevel);
62375 }
62376 }
62377 } else {
62378 if (null === $levels) {
62379 $levels = E_ALL | E_STRICT;
62380 }
62381 foreach ($this->loggers as $type => $log) {
62382 if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
62383 $log[0] = $logger;
62384 $loggers[$type] = $log;
62385 }
62386 }
62387 }
62388
62389 $this->setLoggers($loggers);
62390 }
62391
62392
62393
62394
62395
62396
62397
62398
62399
62400
62401 public function setLoggers(array $loggers)
62402 {
62403 $prevLogged = $this->loggedErrors;
62404 $prev = $this->loggers;
62405 $flush = array();
62406
62407 foreach ($loggers as $type => $log) {
62408 if (!isset($prev[$type])) {
62409 throw new \InvalidArgumentException('Unknown error type: '.$type);
62410 }
62411 if (!is_array($log)) {
62412 $log = array($log);
62413 } elseif (!array_key_exists(0, $log)) {
62414 throw new \InvalidArgumentException('No logger provided');
62415 }
62416 if (null === $log[0]) {
62417 $this->loggedErrors &= ~$type;
62418 } elseif ($log[0] instanceof LoggerInterface) {
62419 $this->loggedErrors |= $type;
62420 } else {
62421 throw new \InvalidArgumentException('Invalid logger provided');
62422 }
62423 $this->loggers[$type] = $log + $prev[$type];
62424
62425 if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
62426 $flush[$type] = $type;
62427 }
62428 }
62429 $this->reRegister($prevLogged | $this->thrownErrors);
62430
62431 if ($flush) {
62432 foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
62433 $type = $log[2]['type'];
62434 if (!isset($flush[$type])) {
62435 $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
62436 } elseif ($this->loggers[$type][0]) {
62437 $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
62438 }
62439 }
62440 }
62441
62442 return $prev;
62443 }
62444
62445
62446
62447
62448
62449
62450
62451
62452
62453
62454 public function setExceptionHandler($handler)
62455 {
62456 if (null !== $handler && !is_callable($handler)) {
62457 throw new \LogicException('The exception handler must be a valid PHP callable.');
62458 }
62459 $prev = $this->exceptionHandler;
62460 $this->exceptionHandler = $handler;
62461
62462 return $prev;
62463 }
62464
62465
62466
62467
62468
62469
62470
62471
62472
62473 public function throwAt($levels, $replace = false)
62474 {
62475 $prev = $this->thrownErrors;
62476 $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
62477 if (!$replace) {
62478 $this->thrownErrors |= $prev;
62479 }
62480 $this->reRegister($prev | $this->loggedErrors);
62481
62482
62483  $this->displayErrors = $this->thrownErrors;
62484
62485 return $prev;
62486 }
62487
62488
62489
62490
62491
62492
62493
62494
62495
62496 public function scopeAt($levels, $replace = false)
62497 {
62498 $prev = $this->scopedErrors;
62499 $this->scopedErrors = (int) $levels;
62500 if (!$replace) {
62501 $this->scopedErrors |= $prev;
62502 }
62503
62504 return $prev;
62505 }
62506
62507
62508
62509
62510
62511
62512
62513
62514
62515 public function traceAt($levels, $replace = false)
62516 {
62517 $prev = $this->tracedErrors;
62518 $this->tracedErrors = (int) $levels;
62519 if (!$replace) {
62520 $this->tracedErrors |= $prev;
62521 }
62522
62523 return $prev;
62524 }
62525
62526
62527
62528
62529
62530
62531
62532
62533
62534 public function screamAt($levels, $replace = false)
62535 {
62536 $prev = $this->screamedErrors;
62537 $this->screamedErrors = (int) $levels;
62538 if (!$replace) {
62539 $this->screamedErrors |= $prev;
62540 }
62541
62542 return $prev;
62543 }
62544
62545
62546
62547
62548 private function reRegister($prev)
62549 {
62550 if ($prev !== $this->thrownErrors | $this->loggedErrors) {
62551 $handler = set_error_handler('var_dump');
62552 $handler = is_array($handler) ? $handler[0] : null;
62553 restore_error_handler();
62554 if ($handler === $this) {
62555 restore_error_handler();
62556 if ($this->isRoot) {
62557 set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
62558 } else {
62559 set_error_handler(array($this, 'handleError'));
62560 }
62561 }
62562 }
62563 }
62564
62565
62566
62567
62568
62569
62570
62571
62572
62573
62574
62575
62576
62577
62578
62579 public function handleError($type, $message, $file, $line)
62580 {
62581 $level = error_reporting();
62582 $silenced = 0 === ($level & $type);
62583 $level |= E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
62584 $log = $this->loggedErrors & $type;
62585 $throw = $this->thrownErrors & $type & $level;
62586 $type &= $level | $this->screamedErrors;
62587
62588 if (!$type || (!$log && !$throw)) {
62589 return !$silenced && $type && $log;
62590 }
62591 $scope = $this->scopedErrors & $type;
62592
62593 if (4 < $numArgs = func_num_args()) {
62594 $context = $scope ? (func_get_arg(4) ?: array()) : array();
62595 $backtrace = 5 < $numArgs ? func_get_arg(5) : null; 
62596  } else {
62597 $context = array();
62598 $backtrace = null;
62599 }
62600
62601 if (isset($context['GLOBALS']) && $scope) {
62602 $e = $context; 
62603  unset($e['GLOBALS'], $context); 
62604  $context = $e;
62605 }
62606
62607 if (null !== $backtrace && $type & E_ERROR) {
62608
62609  
62610  
62611  $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
62612
62613 return true;
62614 }
62615
62616 if ($throw) {
62617 if (null !== self::$toStringException) {
62618 $throw = self::$toStringException;
62619 self::$toStringException = null;
62620 } elseif ($scope && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
62621
62622  $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
62623 } else {
62624 $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
62625 }
62626
62627 if (\PHP_VERSION_ID <= 50407 && (\PHP_VERSION_ID >= 50400 || \PHP_VERSION_ID <= 50317)) {
62628
62629  
62630  
62631
62632 $throw->errorHandlerCanary = new ErrorHandlerCanary();
62633 }
62634
62635 if (E_USER_ERROR & $type) {
62636 $backtrace = $backtrace ?: $throw->getTrace();
62637
62638 for ($i = 1; isset($backtrace[$i]); ++$i) {
62639 if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
62640 && '__toString' === $backtrace[$i]['function']
62641 && '->' === $backtrace[$i]['type']
62642 && !isset($backtrace[$i - 1]['class'])
62643 && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
62644 ) {
62645
62646  
62647  
62648  
62649  
62650  
62651
62652 foreach ($context as $e) {
62653 if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
62654 if (1 === $i) {
62655
62656  $throw = $e;
62657 break;
62658 }
62659 self::$toStringException = $e;
62660
62661 return true;
62662 }
62663 }
62664
62665 if (1 < $i) {
62666
62667  $this->handleException($throw);
62668
62669
62670  return false;
62671 }
62672 }
62673 }
62674 }
62675
62676 throw $throw;
62677 }
62678
62679
62680  $e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
62681 $trace = true;
62682
62683 if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
62684 $trace = false;
62685 } else {
62686 $this->loggedTraces[$e] = 1;
62687 }
62688
62689 $e = compact('type', 'file', 'line', 'level');
62690
62691 if ($type & $level) {
62692 if ($scope) {
62693 $e['scope_vars'] = $context;
62694 if ($trace) {
62695 $e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
62696 }
62697 } elseif ($trace) {
62698 if (null === $backtrace) {
62699 $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
62700 } else {
62701 foreach ($backtrace as &$frame) {
62702 unset($frame['args'], $frame);
62703 }
62704 $e['stack'] = $backtrace;
62705 }
62706 }
62707 }
62708
62709 if ($this->isRecursive) {
62710 $log = 0;
62711 } elseif (self::$stackedErrorLevels) {
62712 self::$stackedErrors[] = array($this->loggers[$type][0], ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
62713 } else {
62714 try {
62715 $this->isRecursive = true;
62716 $this->loggers[$type][0]->log(($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
62717 $this->isRecursive = false;
62718 } catch (\Exception $e) {
62719 $this->isRecursive = false;
62720
62721 throw $e;
62722 } catch (\Throwable $e) {
62723 $this->isRecursive = false;
62724
62725 throw $e;
62726 }
62727 }
62728
62729 return !$silenced && $type && $log;
62730 }
62731
62732
62733
62734
62735
62736
62737
62738
62739
62740 public function handleException($exception, array $error = null)
62741 {
62742 if (null === $error) {
62743 self::$exitCode = 255;
62744 }
62745 if (!$exception instanceof \Exception) {
62746 $exception = new FatalThrowableError($exception);
62747 }
62748 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
62749 $handlerException = null;
62750
62751 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
62752 $e = array(
62753 'type' => $type,
62754 'file' => $exception->getFile(),
62755 'line' => $exception->getLine(),
62756 'level' => error_reporting(),
62757 'stack' => $exception->getTrace(),
62758 );
62759 if ($exception instanceof FatalErrorException) {
62760 if ($exception instanceof FatalThrowableError) {
62761 $error = array(
62762 'type' => $type,
62763 'message' => $message = $exception->getMessage(),
62764 'file' => $e['file'],
62765 'line' => $e['line'],
62766 );
62767 } else {
62768 $message = 'Fatal '.$exception->getMessage();
62769 }
62770 } elseif ($exception instanceof \ErrorException) {
62771 $message = 'Uncaught '.$exception->getMessage();
62772 if ($exception instanceof ContextErrorException) {
62773 $e['context'] = $exception->getContext();
62774 }
62775 } else {
62776 $message = 'Uncaught Exception: '.$exception->getMessage();
62777 }
62778 }
62779 if ($this->loggedErrors & $type) {
62780 try {
62781 $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
62782 } catch (\Exception $handlerException) {
62783 } catch (\Throwable $handlerException) {
62784 }
62785 }
62786 if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
62787 foreach ($this->getFatalErrorHandlers() as $handler) {
62788 if ($e = $handler->handleError($error, $exception)) {
62789 $exception = $e;
62790 break;
62791 }
62792 }
62793 }
62794 $exceptionHandler = $this->exceptionHandler;
62795 $this->exceptionHandler = null;
62796 try {
62797 if (null !== $exceptionHandler) {
62798 return \call_user_func($exceptionHandler, $exception);
62799 }
62800 $handlerException = $handlerException ?: $exception;
62801 } catch (\Exception $handlerException) {
62802 } catch (\Throwable $handlerException) {
62803 }
62804 if ($exception === $handlerException) {
62805 self::$reservedMemory = null; 
62806  throw $exception; 
62807  }
62808 $this->handleException($handlerException);
62809 }
62810
62811
62812
62813
62814
62815
62816
62817
62818 public static function handleFatalError(array $error = null)
62819 {
62820 if (null === self::$reservedMemory) {
62821 return;
62822 }
62823
62824 $handler = self::$reservedMemory = null;
62825 $handlers = array();
62826 $previousHandler = null;
62827 $sameHandlerLimit = 10;
62828
62829 while (!is_array($handler) || !$handler[0] instanceof self) {
62830 $handler = set_exception_handler('var_dump');
62831 restore_exception_handler();
62832
62833 if (!$handler) {
62834 break;
62835 }
62836 restore_exception_handler();
62837
62838 if ($handler !== $previousHandler) {
62839 array_unshift($handlers, $handler);
62840 $previousHandler = $handler;
62841 } elseif (0 === --$sameHandlerLimit) {
62842 $handler = null;
62843 break;
62844 }
62845 }
62846 foreach ($handlers as $h) {
62847 set_exception_handler($h);
62848 }
62849 if (!$handler) {
62850 return;
62851 }
62852 if ($handler !== $h) {
62853 $handler[0]->setExceptionHandler($h);
62854 }
62855 $handler = $handler[0];
62856 $handlers = array();
62857
62858 if ($exit = null === $error) {
62859 $error = error_get_last();
62860 }
62861
62862 try {
62863 while (self::$stackedErrorLevels) {
62864 static::unstackErrors();
62865 }
62866 } catch (\Exception $exception) {
62867
62868  } catch (\Throwable $exception) {
62869
62870  }
62871
62872 if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
62873
62874  $handler->throwAt(0, true);
62875 $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
62876
62877 if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
62878 $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
62879 } else {
62880 $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
62881 }
62882 }
62883
62884 try {
62885 if (isset($exception)) {
62886 self::$exitCode = 255;
62887 $handler->handleException($exception, $error);
62888 }
62889 } catch (FatalErrorException $e) {
62890
62891  }
62892
62893 if ($exit && self::$exitCode) {
62894 $exitCode = self::$exitCode;
62895 register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); });
62896 }
62897 }
62898
62899
62900
62901
62902
62903
62904
62905
62906
62907
62908
62909
62910 public static function stackErrors()
62911 {
62912 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
62913 }
62914
62915
62916
62917
62918 public static function unstackErrors()
62919 {
62920 $level = array_pop(self::$stackedErrorLevels);
62921
62922 if (null !== $level) {
62923 $e = error_reporting($level);
62924 if ($e !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
62925
62926  error_reporting($e);
62927 }
62928 }
62929
62930 if (empty(self::$stackedErrorLevels)) {
62931 $errors = self::$stackedErrors;
62932 self::$stackedErrors = array();
62933
62934 foreach ($errors as $e) {
62935 $e[0]->log($e[1], $e[2], $e[3]);
62936 }
62937 }
62938 }
62939
62940
62941
62942
62943
62944
62945
62946
62947 protected function getFatalErrorHandlers()
62948 {
62949 return array(
62950 new UndefinedFunctionFatalErrorHandler(),
62951 new UndefinedMethodFatalErrorHandler(),
62952 new ClassNotFoundFatalErrorHandler(),
62953 );
62954 }
62955
62956
62957
62958
62959
62960
62961
62962
62963 public function setLevel($level)
62964 {
62965 @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);
62966
62967 $level = null === $level ? error_reporting() : $level;
62968 $this->throwAt($level, true);
62969 }
62970
62971
62972
62973
62974
62975
62976
62977
62978 public function setDisplayErrors($displayErrors)
62979 {
62980 @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);
62981
62982 if ($displayErrors) {
62983 $this->throwAt($this->displayErrors, true);
62984 } else {
62985 $displayErrors = $this->displayErrors;
62986 $this->throwAt(0, true);
62987 $this->displayErrors = $displayErrors;
62988 }
62989 }
62990
62991
62992
62993
62994
62995
62996
62997
62998
62999 public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
63000 {
63001 @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);
63002
63003 $handler = set_error_handler('var_dump');
63004 $handler = is_array($handler) ? $handler[0] : null;
63005 restore_error_handler();
63006 if (!$handler instanceof self) {
63007 return;
63008 }
63009 if ('deprecation' === $channel) {
63010 $handler->setDefaultLogger($logger, E_DEPRECATED | E_USER_DEPRECATED, true);
63011 $handler->screamAt(E_DEPRECATED | E_USER_DEPRECATED);
63012 } elseif ('scream' === $channel) {
63013 $handler->setDefaultLogger($logger, E_ALL | E_STRICT, false);
63014 $handler->screamAt(E_ALL | E_STRICT);
63015 } elseif ('emergency' === $channel) {
63016 $handler->setDefaultLogger($logger, E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR, true);
63017 $handler->screamAt(E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
63018 }
63019 }
63020
63021
63022
63023
63024 public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
63025 {
63026 $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());
63027
63028 return $this->handleError($level, $message, $file, $line, (array) $context);
63029 }
63030
63031
63032
63033
63034
63035
63036 public function handleFatal()
63037 {
63038 @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);
63039
63040 static::handleFatalError();
63041 }
63042 }
63043
63044
63045
63046
63047
63048
63049
63050
63051 class ErrorHandlerCanary
63052 {
63053 private static $displayErrors = null;
63054
63055 public function __construct()
63056 {
63057 if (null === self::$displayErrors) {
63058 self::$displayErrors = ini_set('display_errors', 1);
63059 }
63060 }
63061
63062 public function __destruct()
63063 {
63064 if (null !== self::$displayErrors) {
63065 ini_set('display_errors', self::$displayErrors);
63066 self::$displayErrors = null;
63067 }
63068 }
63069 }
63070 <?php
63071
63072
63073
63074
63075
63076
63077
63078
63079
63080
63081 namespace Symfony\Component\Debug\Exception;
63082
63083
63084
63085
63086
63087
63088 class ClassNotFoundException extends FatalErrorException
63089 {
63090 public function __construct($message, \ErrorException $previous)
63091 {
63092 parent::__construct(
63093 $message,
63094 $previous->getCode(),
63095 $previous->getSeverity(),
63096 $previous->getFile(),
63097 $previous->getLine(),
63098 null,
63099 true,
63100 null,
63101 $previous->getPrevious()
63102 );
63103 $this->setTrace($previous->getTrace());
63104 }
63105 }
63106 <?php
63107
63108
63109
63110
63111
63112
63113
63114
63115
63116
63117 namespace Symfony\Component\Debug\Exception;
63118
63119
63120
63121
63122
63123
63124 class ContextErrorException extends \ErrorException
63125 {
63126 private $context = array();
63127
63128 public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
63129 {
63130 parent::__construct($message, $code, $severity, $filename, $lineno);
63131 $this->context = $context;
63132 }
63133
63134
63135
63136
63137 public function getContext()
63138 {
63139 return $this->context;
63140 }
63141 }
63142 <?php
63143
63144
63145
63146
63147
63148
63149
63150
63151
63152
63153 namespace Symfony\Component\Debug\Exception;
63154
63155 @trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
63156
63157
63158
63159
63160
63161
63162 class DummyException extends \ErrorException
63163 {
63164 }
63165 <?php
63166
63167
63168
63169
63170
63171
63172
63173
63174
63175
63176 namespace Symfony\Component\HttpKernel\Exception;
63177
63178
63179
63180
63181
63182
63183
63184
63185
63186
63187 class FatalErrorException extends \ErrorException
63188 {
63189 }
63190
63191 namespace Symfony\Component\Debug\Exception;
63192
63193 use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
63194
63195
63196
63197
63198
63199
63200 class FatalErrorException extends LegacyFatalErrorException
63201 {
63202 public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null, $previous = null)
63203 {
63204 parent::__construct($message, $code, $severity, $filename, $lineno, $previous);
63205
63206 if (null !== $trace) {
63207 if (!$traceArgs) {
63208 foreach ($trace as &$frame) {
63209 unset($frame['args'], $frame['this'], $frame);
63210 }
63211 }
63212
63213 $this->setTrace($trace);
63214 } elseif (null !== $traceOffset) {
63215 if (function_exists('xdebug_get_function_stack')) {
63216 $trace = xdebug_get_function_stack();
63217 if (0 < $traceOffset) {
63218 array_splice($trace, -$traceOffset);
63219 }
63220
63221 foreach ($trace as &$frame) {
63222 if (!isset($frame['type'])) {
63223
63224  if (isset($frame['class'])) {
63225 $frame['type'] = '::';
63226 }
63227 } elseif ('dynamic' === $frame['type']) {
63228 $frame['type'] = '->';
63229 } elseif ('static' === $frame['type']) {
63230 $frame['type'] = '::';
63231 }
63232
63233
63234  if (!$traceArgs) {
63235 unset($frame['params'], $frame['args']);
63236 } elseif (isset($frame['params']) && !isset($frame['args'])) {
63237 $frame['args'] = $frame['params'];
63238 unset($frame['params']);
63239 }
63240 }
63241
63242 unset($frame);
63243 $trace = array_reverse($trace);
63244 } elseif (function_exists('symfony_debug_backtrace')) {
63245 $trace = symfony_debug_backtrace();
63246 if (0 < $traceOffset) {
63247 array_splice($trace, 0, $traceOffset);
63248 }
63249 } else {
63250 $trace = array();
63251 }
63252
63253 $this->setTrace($trace);
63254 }
63255 }
63256
63257 protected function setTrace($trace)
63258 {
63259 $traceReflector = new \ReflectionProperty('Exception', 'trace');
63260 $traceReflector->setAccessible(true);
63261 $traceReflector->setValue($this, $trace);
63262 }
63263 }
63264 <?php
63265
63266
63267
63268
63269
63270
63271
63272
63273
63274
63275 namespace Symfony\Component\Debug\Exception;
63276
63277
63278
63279
63280
63281
63282 class FatalThrowableError extends FatalErrorException
63283 {
63284 public function __construct(\Throwable $e)
63285 {
63286 if ($e instanceof \ParseError) {
63287 $message = 'Parse error: '.$e->getMessage();
63288 $severity = E_PARSE;
63289 } elseif ($e instanceof \TypeError) {
63290 $message = 'Type error: '.$e->getMessage();
63291 $severity = E_RECOVERABLE_ERROR;
63292 } else {
63293 $message = $e->getMessage();
63294 $severity = E_ERROR;
63295 }
63296
63297 \ErrorException::__construct(
63298 $message,
63299 $e->getCode(),
63300 $severity,
63301 $e->getFile(),
63302 $e->getLine(),
63303 $e->getPrevious()
63304 );
63305
63306 $this->setTrace($e->getTrace());
63307 }
63308 }
63309 <?php
63310
63311
63312
63313
63314
63315
63316
63317
63318
63319
63320 namespace Symfony\Component\HttpKernel\Exception;
63321
63322 use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;
63323
63324
63325
63326
63327
63328
63329
63330
63331
63332
63333 class FlattenException
63334 {
63335 private $handler;
63336
63337 public static function __callStatic($method, $args)
63338 {
63339 if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) {
63340 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_called_class(), $method));
63341 }
63342
63343 return call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
63344 }
63345
63346 public function __call($method, $args)
63347 {
63348 if (!isset($this->handler)) {
63349 $this->handler = new DebugFlattenException();
63350 }
63351
63352 if (!method_exists($this->handler, $method)) {
63353 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
63354 }
63355
63356 return call_user_func_array(array($this->handler, $method), $args);
63357 }
63358 }
63359
63360 namespace Symfony\Component\Debug\Exception;
63361
63362 use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
63363 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
63364
63365
63366
63367
63368
63369
63370
63371
63372 class FlattenException extends LegacyFlattenException
63373 {
63374 private $message;
63375 private $code;
63376 private $previous;
63377 private $trace;
63378 private $class;
63379 private $statusCode;
63380 private $headers;
63381 private $file;
63382 private $line;
63383
63384 public static function create(\Exception $exception, $statusCode = null, array $headers = array())
63385 {
63386 $e = new static();
63387 $e->setMessage($exception->getMessage());
63388 $e->setCode($exception->getCode());
63389
63390 if ($exception instanceof HttpExceptionInterface) {
63391 $statusCode = $exception->getStatusCode();
63392 $headers = array_merge($headers, $exception->getHeaders());
63393 }
63394
63395 if (null === $statusCode) {
63396 $statusCode = 500;
63397 }
63398
63399 $e->setStatusCode($statusCode);
63400 $e->setHeaders($headers);
63401 $e->setTraceFromException($exception);
63402 $e->setClass(get_class($exception));
63403 $e->setFile($exception->getFile());
63404 $e->setLine($exception->getLine());
63405
63406 $previous = $exception->getPrevious();
63407
63408 if ($previous instanceof \Exception) {
63409 $e->setPrevious(static::create($previous));
63410 } elseif ($previous instanceof \Throwable) {
63411 $e->setPrevious(static::create(new FatalThrowableError($previous)));
63412 }
63413
63414 return $e;
63415 }
63416
63417 public function toArray()
63418 {
63419 $exceptions = array();
63420 foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
63421 $exceptions[] = array(
63422 'message' => $exception->getMessage(),
63423 'class' => $exception->getClass(),
63424 'trace' => $exception->getTrace(),
63425 );
63426 }
63427
63428 return $exceptions;
63429 }
63430
63431 public function getStatusCode()
63432 {
63433 return $this->statusCode;
63434 }
63435
63436 public function setStatusCode($code)
63437 {
63438 $this->statusCode = $code;
63439 }
63440
63441 public function getHeaders()
63442 {
63443 return $this->headers;
63444 }
63445
63446 public function setHeaders(array $headers)
63447 {
63448 $this->headers = $headers;
63449 }
63450
63451 public function getClass()
63452 {
63453 return $this->class;
63454 }
63455
63456 public function setClass($class)
63457 {
63458 $this->class = $class;
63459 }
63460
63461 public function getFile()
63462 {
63463 return $this->file;
63464 }
63465
63466 public function setFile($file)
63467 {
63468 $this->file = $file;
63469 }
63470
63471 public function getLine()
63472 {
63473 return $this->line;
63474 }
63475
63476 public function setLine($line)
63477 {
63478 $this->line = $line;
63479 }
63480
63481 public function getMessage()
63482 {
63483 return $this->message;
63484 }
63485
63486 public function setMessage($message)
63487 {
63488 $this->message = $message;
63489 }
63490
63491 public function getCode()
63492 {
63493 return $this->code;
63494 }
63495
63496 public function setCode($code)
63497 {
63498 $this->code = $code;
63499 }
63500
63501 public function getPrevious()
63502 {
63503 return $this->previous;
63504 }
63505
63506 public function setPrevious(FlattenException $previous)
63507 {
63508 $this->previous = $previous;
63509 }
63510
63511 public function getAllPrevious()
63512 {
63513 $exceptions = array();
63514 $e = $this;
63515 while ($e = $e->getPrevious()) {
63516 $exceptions[] = $e;
63517 }
63518
63519 return $exceptions;
63520 }
63521
63522 public function getTrace()
63523 {
63524 return $this->trace;
63525 }
63526
63527 public function setTraceFromException(\Exception $exception)
63528 {
63529 $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
63530 }
63531
63532 public function setTrace($trace, $file, $line)
63533 {
63534 $this->trace = array();
63535 $this->trace[] = array(
63536 'namespace' => '',
63537 'short_class' => '',
63538 'class' => '',
63539 'type' => '',
63540 'function' => '',
63541 'file' => $file,
63542 'line' => $line,
63543 'args' => array(),
63544 );
63545 foreach ($trace as $entry) {
63546 $class = '';
63547 $namespace = '';
63548 if (isset($entry['class'])) {
63549 $parts = explode('\\', $entry['class']);
63550 $class = array_pop($parts);
63551 $namespace = implode('\\', $parts);
63552 }
63553
63554 $this->trace[] = array(
63555 'namespace' => $namespace,
63556 'short_class' => $class,
63557 'class' => isset($entry['class']) ? $entry['class'] : '',
63558 'type' => isset($entry['type']) ? $entry['type'] : '',
63559 'function' => isset($entry['function']) ? $entry['function'] : null,
63560 'file' => isset($entry['file']) ? $entry['file'] : null,
63561 'line' => isset($entry['line']) ? $entry['line'] : null,
63562 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
63563 );
63564 }
63565 }
63566
63567 private function flattenArgs($args, $level = 0, &$count = 0)
63568 {
63569 $result = array();
63570 foreach ($args as $key => $value) {
63571 if (++$count > 1e4) {
63572 return array('array', '*SKIPPED over 10000 entries*');
63573 }
63574 if ($value instanceof \__PHP_Incomplete_Class) {
63575
63576  $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
63577 } elseif (is_object($value)) {
63578 $result[$key] = array('object', get_class($value));
63579 } elseif (is_array($value)) {
63580 if ($level > 10) {
63581 $result[$key] = array('array', '*DEEP NESTED ARRAY*');
63582 } else {
63583 $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
63584 }
63585 } elseif (null === $value) {
63586 $result[$key] = array('null', null);
63587 } elseif (is_bool($value)) {
63588 $result[$key] = array('boolean', $value);
63589 } elseif (is_resource($value)) {
63590 $result[$key] = array('resource', get_resource_type($value));
63591 } else {
63592 $result[$key] = array('string', (string) $value);
63593 }
63594 }
63595
63596 return $result;
63597 }
63598
63599 private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
63600 {
63601 $array = new \ArrayObject($value);
63602
63603 return $array['__PHP_Incomplete_Class_Name'];
63604 }
63605 }
63606 <?php
63607
63608
63609
63610
63611
63612
63613
63614
63615
63616
63617 namespace Symfony\Component\Debug\Exception;
63618
63619
63620
63621
63622
63623
63624 class OutOfMemoryException extends FatalErrorException
63625 {
63626 }
63627 <?php
63628
63629
63630
63631
63632
63633
63634
63635
63636
63637
63638 namespace Symfony\Component\Debug\Exception;
63639
63640
63641
63642
63643
63644
63645 class UndefinedFunctionException extends FatalErrorException
63646 {
63647 public function __construct($message, \ErrorException $previous)
63648 {
63649 parent::__construct(
63650 $message,
63651 $previous->getCode(),
63652 $previous->getSeverity(),
63653 $previous->getFile(),
63654 $previous->getLine(),
63655 null,
63656 true,
63657 null,
63658 $previous->getPrevious()
63659 );
63660 $this->setTrace($previous->getTrace());
63661 }
63662 }
63663 <?php
63664
63665
63666
63667
63668
63669
63670
63671
63672
63673
63674 namespace Symfony\Component\Debug\Exception;
63675
63676
63677
63678
63679
63680
63681 class UndefinedMethodException extends FatalErrorException
63682 {
63683 public function __construct($message, \ErrorException $previous)
63684 {
63685 parent::__construct(
63686 $message,
63687 $previous->getCode(),
63688 $previous->getSeverity(),
63689 $previous->getFile(),
63690 $previous->getLine(),
63691 null,
63692 true,
63693 null,
63694 $previous->getPrevious()
63695 );
63696 $this->setTrace($previous->getTrace());
63697 }
63698 }
63699 <?php
63700
63701
63702
63703
63704
63705
63706
63707
63708
63709
63710 namespace Symfony\Component\Debug;
63711
63712 use Symfony\Component\HttpFoundation\Response;
63713 use Symfony\Component\Debug\Exception\FlattenException;
63714 use Symfony\Component\Debug\Exception\OutOfMemoryException;
63715
63716
63717
63718
63719
63720
63721
63722
63723
63724
63725
63726
63727
63728 class ExceptionHandler
63729 {
63730 private $debug;
63731 private $charset;
63732 private $handler;
63733 private $caughtBuffer;
63734 private $caughtLength;
63735 private $fileLinkFormat;
63736
63737 public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
63738 {
63739 if (false !== strpos($charset, '%')) {
63740 @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);
63741
63742
63743  $pivot = $fileLinkFormat;
63744 $fileLinkFormat = $charset;
63745 $charset = $pivot;
63746 }
63747 $this->debug = $debug;
63748 $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
63749 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
63750 }
63751
63752
63753
63754
63755
63756
63757
63758
63759
63760
63761 public static function register($debug = true, $charset = null, $fileLinkFormat = null)
63762 {
63763 $handler = new static($debug, $charset, $fileLinkFormat);
63764
63765 $prev = set_exception_handler(array($handler, 'handle'));
63766 if (is_array($prev) && $prev[0] instanceof ErrorHandler) {
63767 restore_exception_handler();
63768 $prev[0]->setExceptionHandler(array($handler, 'handle'));
63769 }
63770
63771 return $handler;
63772 }
63773
63774
63775
63776
63777
63778
63779
63780
63781 public function setHandler($handler)
63782 {
63783 if (null !== $handler && !is_callable($handler)) {
63784 throw new \LogicException('The exception handler must be a valid PHP callable.');
63785 }
63786 $old = $this->handler;
63787 $this->handler = $handler;
63788
63789 return $old;
63790 }
63791
63792
63793
63794
63795
63796
63797
63798
63799 public function setFileLinkFormat($format)
63800 {
63801 $old = $this->fileLinkFormat;
63802 $this->fileLinkFormat = $format;
63803
63804 return $old;
63805 }
63806
63807
63808
63809
63810
63811
63812
63813
63814
63815 public function handle(\Exception $exception)
63816 {
63817 if (null === $this->handler || $exception instanceof OutOfMemoryException) {
63818 $this->failSafeHandle($exception);
63819
63820 return;
63821 }
63822
63823 $caughtLength = $this->caughtLength = 0;
63824
63825 ob_start(array($this, 'catchOutput'));
63826 $this->failSafeHandle($exception);
63827 while (null === $this->caughtBuffer && ob_end_flush()) {
63828
63829  }
63830 if (isset($this->caughtBuffer[0])) {
63831 ob_start(array($this, 'cleanOutput'));
63832 echo $this->caughtBuffer;
63833 $caughtLength = ob_get_length();
63834 }
63835 $this->caughtBuffer = null;
63836
63837 try {
63838 call_user_func($this->handler, $exception);
63839 $this->caughtLength = $caughtLength;
63840 } catch (\Exception $e) {
63841 if (!$caughtLength) {
63842
63843  throw $exception;
63844 }
63845 }
63846 }
63847
63848
63849
63850
63851
63852
63853
63854
63855 private function failSafeHandle(\Exception $exception)
63856 {
63857 if (class_exists('Symfony\Component\HttpFoundation\Response', false)
63858 && __CLASS__ !== get_class($this)
63859 && ($reflector = new \ReflectionMethod($this, 'createResponse'))
63860 && __CLASS__ !== $reflector->class
63861 ) {
63862 $response = $this->createResponse($exception);
63863 $response->sendHeaders();
63864 $response->sendContent();
63865 @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);
63866
63867 return;
63868 }
63869
63870 $this->sendPhpResponse($exception);
63871 }
63872
63873
63874
63875
63876
63877
63878
63879
63880
63881 public function sendPhpResponse($exception)
63882 {
63883 if (!$exception instanceof FlattenException) {
63884 $exception = FlattenException::create($exception);
63885 }
63886
63887 if (!headers_sent()) {
63888 header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
63889 foreach ($exception->getHeaders() as $name => $value) {
63890 header($name.': '.$value, false);
63891 }
63892 header('Content-Type: text/html; charset='.$this->charset);
63893 }
63894
63895 echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
63896 }
63897
63898
63899
63900
63901
63902
63903
63904
63905
63906
63907 public function createResponse($exception)
63908 {
63909 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
63910
63911 if (!$exception instanceof FlattenException) {
63912 $exception = FlattenException::create($exception);
63913 }
63914
63915 return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
63916 }
63917
63918
63919
63920
63921
63922
63923
63924
63925 public function getHtml($exception)
63926 {
63927 if (!$exception instanceof FlattenException) {
63928 $exception = FlattenException::create($exception);
63929 }
63930
63931 return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
63932 }
63933
63934
63935
63936
63937
63938
63939 public function getContent(FlattenException $exception)
63940 {
63941 switch ($exception->getStatusCode()) {
63942 case 404:
63943 $title = 'Sorry, the page you are looking for could not be found.';
63944 break;
63945 default:
63946 $title = 'Whoops, looks like something went wrong.';
63947 }
63948
63949 $content = '';
63950 if ($this->debug) {
63951 try {
63952 $count = count($exception->getAllPrevious());
63953 $total = $count + 1;
63954 foreach ($exception->toArray() as $position => $e) {
63955 $ind = $count - $position + 1;
63956 $class = $this->formatClass($e['class']);
63957 $message = nl2br($this->escapeHtml($e['message']));
63958 $content .= sprintf(<<<'EOF'
63959                         <h2 class="block_exception clear_fix">
63960                             <span class="exception_counter">%d/%d</span>
63961                             <span class="exception_title">%s%s:</span>
63962                             <span class="exception_message">%s</span>
63963                         </h2>
63964                         <div class="block">
63965                             <ol class="traces list_exception">
63966
63967 EOF
63968 , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
63969 foreach ($e['trace'] as $trace) {
63970 $content .= '       <li>';
63971 if ($trace['function']) {
63972 $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
63973 }
63974 if (isset($trace['file']) && isset($trace['line'])) {
63975 $content .= $this->formatPath($trace['file'], $trace['line']);
63976 }
63977 $content .= "</li>\n";
63978 }
63979
63980 $content .= "    </ol>\n</div>\n";
63981 }
63982 } catch (\Exception $e) {
63983
63984  if ($this->debug) {
63985 $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $this->escapeHtml($e->getMessage()));
63986 } else {
63987 $title = 'Whoops, looks like something went wrong.';
63988 }
63989 }
63990 }
63991
63992 return <<<EOF
63993             <div id="sf-resetcontent" class="sf-reset">
63994                 <h1>$title</h1>
63995                 $content
63996             </div>
63997 EOF;
63998 }
63999
64000
64001
64002
64003
64004
64005 public function getStylesheet(FlattenException $exception)
64006 {
64007 return <<<'EOF'
64008             .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
64009             .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
64010             .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
64011             .sf-reset .clear_fix { display:inline-block; }
64012             .sf-reset * html .clear_fix { height:1%; }
64013             .sf-reset .clear_fix { display:block; }
64014             .sf-reset, .sf-reset .block { margin: auto }
64015             .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
64016             .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
64017             .sf-reset strong { font-weight:bold; }
64018             .sf-reset a { color:#6c6159; cursor: default; }
64019             .sf-reset a img { border:none; }
64020             .sf-reset a:hover { text-decoration:underline; }
64021             .sf-reset em { font-style:italic; }
64022             .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
64023             .sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
64024             .sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
64025             .sf-reset .exception_message { margin-left: 3em; display: block; }
64026             .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
64027             .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
64028                 -webkit-border-bottom-right-radius: 16px;
64029                 -webkit-border-bottom-left-radius: 16px;
64030                 -moz-border-radius-bottomright: 16px;
64031                 -moz-border-radius-bottomleft: 16px;
64032                 border-bottom-right-radius: 16px;
64033                 border-bottom-left-radius: 16px;
64034                 border-bottom:1px solid #ccc;
64035                 border-right:1px solid #ccc;
64036                 border-left:1px solid #ccc;
64037                 word-wrap: break-word;
64038             }
64039             .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
64040                 -webkit-border-top-left-radius: 16px;
64041                 -webkit-border-top-right-radius: 16px;
64042                 -moz-border-radius-topleft: 16px;
64043                 -moz-border-radius-topright: 16px;
64044                 border-top-left-radius: 16px;
64045                 border-top-right-radius: 16px;
64046                 border-top:1px solid #ccc;
64047                 border-right:1px solid #ccc;
64048                 border-left:1px solid #ccc;
64049                 overflow: hidden;
64050                 word-wrap: break-word;
64051             }
64052             .sf-reset a { background:none; color:#868686; text-decoration:none; }
64053             .sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
64054             .sf-reset ol { padding: 10px 0; }
64055             .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
64056                 -webkit-border-radius: 10px;
64057                 -moz-border-radius: 10px;
64058                 border-radius: 10px;
64059                 border: 1px solid #ccc;
64060             }
64061 EOF;
64062 }
64063
64064 private function decorate($content, $css)
64065 {
64066 return <<<EOF
64067 <!DOCTYPE html>
64068 <html>
64069     <head>
64070         <meta charset="{$this->charset}" />
64071         <meta name="robots" content="noindex,nofollow" />
64072         <style>
64073             /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
64074             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;}
64075
64076             html { background: #eee; padding: 10px }
64077             img { border: 0; }
64078             #sf-resetcontent { width:970px; margin:0 auto; }
64079             $css
64080         </style>
64081     </head>
64082     <body>
64083         $content
64084     </body>
64085 </html>
64086 EOF;
64087 }
64088
64089 private function formatClass($class)
64090 {
64091 $parts = explode('\\', $class);
64092
64093 return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
64094 }
64095
64096 private function formatPath($path, $line)
64097 {
64098 $path = $this->escapeHtml($path);
64099 $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
64100
64101 if ($linkFormat = $this->fileLinkFormat) {
64102 $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
64103
64104 return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
64105 }
64106
64107 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);
64108 }
64109
64110
64111
64112
64113
64114
64115
64116
64117 private function formatArgs(array $args)
64118 {
64119 $result = array();
64120 foreach ($args as $key => $item) {
64121 if ('object' === $item[0]) {
64122 $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
64123 } elseif ('array' === $item[0]) {
64124 $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
64125 } elseif ('string' === $item[0]) {
64126 $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1]));
64127 } elseif ('null' === $item[0]) {
64128 $formattedValue = '<em>null</em>';
64129 } elseif ('boolean' === $item[0]) {
64130 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
64131 } elseif ('resource' === $item[0]) {
64132 $formattedValue = '<em>resource</em>';
64133 } else {
64134 $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true));
64135 }
64136
64137 $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
64138 }
64139
64140 return implode(', ', $result);
64141 }
64142
64143
64144
64145
64146
64147
64148 protected static function utf8Htmlize($str)
64149 {
64150 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
64151
64152 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
64153 }
64154
64155
64156
64157
64158 private function escapeHtml($str)
64159 {
64160 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset);
64161 }
64162
64163
64164
64165
64166 public function catchOutput($buffer)
64167 {
64168 $this->caughtBuffer = $buffer;
64169
64170 return '';
64171 }
64172
64173
64174
64175
64176 public function cleanOutput($buffer)
64177 {
64178 if ($this->caughtLength) {
64179
64180  $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
64181 if (isset($cleanBuffer[0])) {
64182 $buffer = $cleanBuffer;
64183 }
64184 }
64185
64186 return $buffer;
64187 }
64188 }
64189 <?php
64190
64191
64192
64193
64194
64195
64196
64197
64198
64199
64200 namespace Symfony\Component\Debug\FatalErrorHandler;
64201
64202 use Symfony\Component\Debug\Exception\ClassNotFoundException;
64203 use Symfony\Component\Debug\Exception\FatalErrorException;
64204 use Symfony\Component\Debug\DebugClassLoader;
64205 use Composer\Autoload\ClassLoader as ComposerClassLoader;
64206 use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
64207 use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
64208
64209
64210
64211
64212
64213
64214 class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
64215 {
64216
64217
64218
64219 public function handleError(array $error, FatalErrorException $exception)
64220 {
64221 $messageLen = strlen($error['message']);
64222 $notFoundSuffix = '\' not found';
64223 $notFoundSuffixLen = strlen($notFoundSuffix);
64224 if ($notFoundSuffixLen > $messageLen) {
64225 return;
64226 }
64227
64228 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
64229 return;
64230 }
64231
64232 foreach (array('class', 'interface', 'trait') as $typeName) {
64233 $prefix = ucfirst($typeName).' \'';
64234 $prefixLen = strlen($prefix);
64235 if (0 !== strpos($error['message'], $prefix)) {
64236 continue;
64237 }
64238
64239 $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
64240 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
64241 $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
64242 $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
64243 $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
64244 $tail = ' for another namespace?';
64245 } else {
64246 $className = $fullyQualifiedClassName;
64247 $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
64248 $tail = '?';
64249 }
64250
64251 if ($candidates = $this->getClassCandidates($className)) {
64252 $tail = array_pop($candidates).'"?';
64253 if ($candidates) {
64254 $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
64255 } else {
64256 $tail = ' for "'.$tail;
64257 }
64258 }
64259 $message .= "\nDid you forget a \"use\" statement".$tail;
64260
64261 return new ClassNotFoundException($message, $exception);
64262 }
64263 }
64264
64265
64266
64267
64268
64269
64270
64271
64272
64273
64274
64275 private function getClassCandidates($class)
64276 {
64277 if (!is_array($functions = spl_autoload_functions())) {
64278 return array();
64279 }
64280
64281
64282  $classes = array();
64283
64284 foreach ($functions as $function) {
64285 if (!is_array($function)) {
64286 continue;
64287 }
64288
64289  if ($function[0] instanceof DebugClassLoader) {
64290 $function = $function[0]->getClassLoader();
64291
64292
64293  if (is_object($function)) {
64294 $function = array($function);
64295 }
64296
64297 if (!is_array($function)) {
64298 continue;
64299 }
64300 }
64301
64302 if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader || $function[0] instanceof SymfonyUniversalClassLoader) {
64303 foreach ($function[0]->getPrefixes() as $prefix => $paths) {
64304 foreach ($paths as $path) {
64305 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
64306 }
64307 }
64308 }
64309 if ($function[0] instanceof ComposerClassLoader) {
64310 foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
64311 foreach ($paths as $path) {
64312 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
64313 }
64314 }
64315 }
64316 }
64317
64318 return array_unique($classes);
64319 }
64320
64321
64322
64323
64324
64325
64326
64327
64328 private function findClassInPath($path, $class, $prefix)
64329 {
64330 if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
64331 return array();
64332 }
64333
64334 $classes = array();
64335 $filename = $class.'.php';
64336 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
64337 if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
64338 $classes[] = $class;
64339 }
64340 }
64341
64342 return $classes;
64343 }
64344
64345
64346
64347
64348
64349
64350
64351
64352 private function convertFileToClass($path, $file, $prefix)
64353 {
64354 $candidates = array(
64355
64356  $namespacedClass = str_replace(array($path.DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
64357
64358  $prefix.$namespacedClass,
64359
64360  $prefix.'\\'.$namespacedClass,
64361
64362  str_replace('\\', '_', $namespacedClass),
64363
64364  str_replace('\\', '_', $prefix.$namespacedClass),
64365
64366  str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
64367 );
64368
64369 if ($prefix) {
64370 $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
64371 }
64372
64373
64374  
64375  
64376  foreach ($candidates as $candidate) {
64377 if ($this->classExists($candidate)) {
64378 return $candidate;
64379 }
64380 }
64381
64382 require_once $file;
64383
64384 foreach ($candidates as $candidate) {
64385 if ($this->classExists($candidate)) {
64386 return $candidate;
64387 }
64388 }
64389 }
64390
64391
64392
64393
64394
64395
64396 private function classExists($class)
64397 {
64398 return class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
64399 }
64400 }
64401 <?php
64402
64403
64404
64405
64406
64407
64408
64409
64410
64411
64412 namespace Symfony\Component\Debug\FatalErrorHandler;
64413
64414 use Symfony\Component\Debug\Exception\FatalErrorException;
64415
64416
64417
64418
64419
64420
64421 interface FatalErrorHandlerInterface
64422 {
64423
64424
64425
64426
64427
64428
64429
64430
64431 public function handleError(array $error, FatalErrorException $exception);
64432 }
64433 <?php
64434
64435
64436
64437
64438
64439
64440
64441
64442
64443
64444 namespace Symfony\Component\Debug\FatalErrorHandler;
64445
64446 use Symfony\Component\Debug\Exception\UndefinedFunctionException;
64447 use Symfony\Component\Debug\Exception\FatalErrorException;
64448
64449
64450
64451
64452
64453
64454 class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
64455 {
64456
64457
64458
64459 public function handleError(array $error, FatalErrorException $exception)
64460 {
64461 $messageLen = strlen($error['message']);
64462 $notFoundSuffix = '()';
64463 $notFoundSuffixLen = strlen($notFoundSuffix);
64464 if ($notFoundSuffixLen > $messageLen) {
64465 return;
64466 }
64467
64468 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
64469 return;
64470 }
64471
64472 $prefix = 'Call to undefined function ';
64473 $prefixLen = strlen($prefix);
64474 if (0 !== strpos($error['message'], $prefix)) {
64475 return;
64476 }
64477
64478 $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
64479 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
64480 $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
64481 $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
64482 $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
64483 } else {
64484 $functionName = $fullyQualifiedFunctionName;
64485 $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
64486 }
64487
64488 $candidates = array();
64489 foreach (get_defined_functions() as $type => $definedFunctionNames) {
64490 foreach ($definedFunctionNames as $definedFunctionName) {
64491 if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
64492 $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
64493 } else {
64494 $definedFunctionNameBasename = $definedFunctionName;
64495 }
64496
64497 if ($definedFunctionNameBasename === $functionName) {
64498 $candidates[] = '\\'.$definedFunctionName;
64499 }
64500 }
64501 }
64502
64503 if ($candidates) {
64504 sort($candidates);
64505 $last = array_pop($candidates).'"?';
64506 if ($candidates) {
64507 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
64508 } else {
64509 $candidates = '"'.$last;
64510 }
64511 $message .= "\nDid you mean to call ".$candidates;
64512 }
64513
64514 return new UndefinedFunctionException($message, $exception);
64515 }
64516 }
64517 <?php
64518
64519
64520
64521
64522
64523
64524
64525
64526
64527
64528 namespace Symfony\Component\Debug\FatalErrorHandler;
64529
64530 use Symfony\Component\Debug\Exception\FatalErrorException;
64531 use Symfony\Component\Debug\Exception\UndefinedMethodException;
64532
64533
64534
64535
64536
64537
64538 class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
64539 {
64540
64541
64542
64543 public function handleError(array $error, FatalErrorException $exception)
64544 {
64545 preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
64546 if (!$matches) {
64547 return;
64548 }
64549
64550 $className = $matches[1];
64551 $methodName = $matches[2];
64552
64553 $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
64554
64555 if (!class_exists($className) || null === $methods = get_class_methods($className)) {
64556
64557  return new UndefinedMethodException($message, $exception);
64558 }
64559
64560 $candidates = array();
64561 foreach ($methods as $definedMethodName) {
64562 $lev = levenshtein($methodName, $definedMethodName);
64563 if ($lev <= strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
64564 $candidates[] = $definedMethodName;
64565 }
64566 }
64567
64568 if ($candidates) {
64569 sort($candidates);
64570 $last = array_pop($candidates).'"?';
64571 if ($candidates) {
64572 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
64573 } else {
64574 $candidates = '"'.$last;
64575 }
64576
64577 $message .= "\nDid you mean to call ".$candidates;
64578 }
64579
64580 return new UndefinedMethodException($message, $exception);
64581 }
64582 }
64583 Copyright (c) 2004-2018 Fabien Potencier
64584
64585 Permission is hereby granted, free of charge, to any person obtaining a copy
64586 of this software and associated documentation files (the "Software"), to deal
64587 in the Software without restriction, including without limitation the rights
64588 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
64589 copies of the Software, and to permit persons to whom the Software is furnished
64590 to do so, subject to the following conditions:
64591
64592 The above copyright notice and this permission notice shall be included in all
64593 copies or substantial portions of the Software.
64594
64595 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
64596 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64597 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
64598 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
64599 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
64600 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64601 THE SOFTWARE.
64602 <?php
64603
64604
64605
64606
64607
64608
64609
64610
64611
64612
64613 namespace Symfony\Component\Filesystem\Exception;
64614
64615
64616
64617
64618
64619
64620 interface ExceptionInterface
64621 {
64622 }
64623 <?php
64624
64625
64626
64627
64628
64629
64630
64631
64632
64633
64634 namespace Symfony\Component\Filesystem\Exception;
64635
64636
64637
64638
64639
64640
64641
64642 class FileNotFoundException extends IOException
64643 {
64644 public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
64645 {
64646 if (null === $message) {
64647 if (null === $path) {
64648 $message = 'File could not be found.';
64649 } else {
64650 $message = sprintf('File "%s" could not be found.', $path);
64651 }
64652 }
64653
64654 parent::__construct($message, $code, $previous, $path);
64655 }
64656 }
64657 <?php
64658
64659
64660
64661
64662
64663
64664
64665
64666
64667
64668 namespace Symfony\Component\Filesystem\Exception;
64669
64670
64671
64672
64673
64674
64675
64676
64677 class IOException extends \RuntimeException implements IOExceptionInterface
64678 {
64679 private $path;
64680
64681 public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
64682 {
64683 $this->path = $path;
64684
64685 parent::__construct($message, $code, $previous);
64686 }
64687
64688
64689
64690
64691 public function getPath()
64692 {
64693 return $this->path;
64694 }
64695 }
64696 <?php
64697
64698
64699
64700
64701
64702
64703
64704
64705
64706
64707 namespace Symfony\Component\Filesystem\Exception;
64708
64709
64710
64711
64712
64713
64714 interface IOExceptionInterface extends ExceptionInterface
64715 {
64716
64717
64718
64719
64720
64721 public function getPath();
64722 }
64723 <?php
64724
64725
64726
64727
64728
64729
64730
64731
64732
64733
64734 namespace Symfony\Component\Filesystem;
64735
64736 use Symfony\Component\Filesystem\Exception\IOException;
64737 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
64738
64739
64740
64741
64742
64743
64744 class Filesystem
64745 {
64746 private static $lastError;
64747
64748
64749
64750
64751
64752
64753
64754
64755
64756
64757
64758
64759
64760
64761
64762 public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
64763 {
64764 $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
64765 if ($originIsLocal && !is_file($originFile)) {
64766 throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
64767 }
64768
64769 $this->mkdir(dirname($targetFile));
64770
64771 $doCopy = true;
64772 if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
64773 $doCopy = filemtime($originFile) > filemtime($targetFile);
64774 }
64775
64776 if ($doCopy) {
64777
64778  if (false === $source = @fopen($originFile, 'r')) {
64779 throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
64780 }
64781
64782
64783  if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
64784 throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
64785 }
64786
64787 $bytesCopied = stream_copy_to_stream($source, $target);
64788 fclose($source);
64789 fclose($target);
64790 unset($source, $target);
64791
64792 if (!is_file($targetFile)) {
64793 throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
64794 }
64795
64796 if ($originIsLocal) {
64797
64798  @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
64799
64800 if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
64801 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);
64802 }
64803 }
64804 }
64805 }
64806
64807
64808
64809
64810
64811
64812
64813
64814
64815 public function mkdir($dirs, $mode = 0777)
64816 {
64817 foreach ($this->toIterator($dirs) as $dir) {
64818 if (is_dir($dir)) {
64819 continue;
64820 }
64821
64822 if (!self::box('mkdir', $dir, $mode, true)) {
64823 if (!is_dir($dir)) {
64824
64825  if (self::$lastError) {
64826 throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir);
64827 }
64828 throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
64829 }
64830 }
64831 }
64832 }
64833
64834
64835
64836
64837
64838
64839
64840
64841 public function exists($files)
64842 {
64843 $maxPathLength = PHP_MAXPATHLEN - 2;
64844
64845 foreach ($this->toIterator($files) as $file) {
64846 if (strlen($file) > $maxPathLength) {
64847 throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
64848 }
64849
64850 if (!file_exists($file)) {
64851 return false;
64852 }
64853 }
64854
64855 return true;
64856 }
64857
64858
64859
64860
64861
64862
64863
64864
64865
64866
64867 public function touch($files, $time = null, $atime = null)
64868 {
64869 foreach ($this->toIterator($files) as $file) {
64870 $touch = $time ? @touch($file, $time, $atime) : @touch($file);
64871 if (true !== $touch) {
64872 throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
64873 }
64874 }
64875 }
64876
64877
64878
64879
64880
64881
64882
64883
64884 public function remove($files)
64885 {
64886 if ($files instanceof \Traversable) {
64887 $files = iterator_to_array($files, false);
64888 } elseif (!is_array($files)) {
64889 $files = array($files);
64890 }
64891 $files = array_reverse($files);
64892 foreach ($files as $file) {
64893 if (is_link($file)) {
64894
64895  if (!(self::box('unlink', $file) || '\\' !== DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
64896 throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError));
64897 }
64898 } elseif (is_dir($file)) {
64899 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
64900
64901 if (!self::box('rmdir', $file) && file_exists($file)) {
64902 throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError));
64903 }
64904 } elseif (!self::box('unlink', $file) && file_exists($file)) {
64905 throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError));
64906 }
64907 }
64908 }
64909
64910
64911
64912
64913
64914
64915
64916
64917
64918
64919
64920 public function chmod($files, $mode, $umask = 0000, $recursive = false)
64921 {
64922 foreach ($this->toIterator($files) as $file) {
64923 if (true !== @chmod($file, $mode & ~$umask)) {
64924 throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
64925 }
64926 if ($recursive && is_dir($file) && !is_link($file)) {
64927 $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
64928 }
64929 }
64930 }
64931
64932
64933
64934
64935
64936
64937
64938
64939
64940
64941 public function chown($files, $user, $recursive = false)
64942 {
64943 foreach ($this->toIterator($files) as $file) {
64944 if ($recursive && is_dir($file) && !is_link($file)) {
64945 $this->chown(new \FilesystemIterator($file), $user, true);
64946 }
64947 if (is_link($file) && function_exists('lchown')) {
64948 if (true !== @lchown($file, $user)) {
64949 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
64950 }
64951 } else {
64952 if (true !== @chown($file, $user)) {
64953 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
64954 }
64955 }
64956 }
64957 }
64958
64959
64960
64961
64962
64963
64964
64965
64966
64967
64968 public function chgrp($files, $group, $recursive = false)
64969 {
64970 foreach ($this->toIterator($files) as $file) {
64971 if ($recursive && is_dir($file) && !is_link($file)) {
64972 $this->chgrp(new \FilesystemIterator($file), $group, true);
64973 }
64974 if (is_link($file) && function_exists('lchgrp')) {
64975 if (true !== @lchgrp($file, $group) || (defined('HHVM_VERSION') && !posix_getgrnam($group))) {
64976 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
64977 }
64978 } else {
64979 if (true !== @chgrp($file, $group)) {
64980 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
64981 }
64982 }
64983 }
64984 }
64985
64986
64987
64988
64989
64990
64991
64992
64993
64994
64995
64996 public function rename($origin, $target, $overwrite = false)
64997 {
64998
64999  if (!$overwrite && $this->isReadable($target)) {
65000 throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
65001 }
65002
65003 if (true !== @rename($origin, $target)) {
65004 if (is_dir($origin)) {
65005
65006  $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
65007 $this->remove($origin);
65008
65009 return;
65010 }
65011 throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
65012 }
65013 }
65014
65015
65016
65017
65018
65019
65020
65021
65022
65023
65024 private function isReadable($filename)
65025 {
65026 $maxPathLength = PHP_MAXPATHLEN - 2;
65027
65028 if (strlen($filename) > $maxPathLength) {
65029 throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename);
65030 }
65031
65032 return is_readable($filename);
65033 }
65034
65035
65036
65037
65038
65039
65040
65041
65042
65043
65044 public function symlink($originDir, $targetDir, $copyOnWindows = false)
65045 {
65046 if ('\\' === DIRECTORY_SEPARATOR) {
65047 $originDir = strtr($originDir, '/', '\\');
65048 $targetDir = strtr($targetDir, '/', '\\');
65049
65050 if ($copyOnWindows) {
65051 $this->mirror($originDir, $targetDir);
65052
65053 return;
65054 }
65055 }
65056
65057 $this->mkdir(dirname($targetDir));
65058
65059 if (is_link($targetDir)) {
65060 if (readlink($targetDir) === $originDir) {
65061 return;
65062 }
65063 $this->remove($targetDir);
65064 }
65065
65066 if (!self::box('symlink', $originDir, $targetDir)) {
65067 if (null !== self::$lastError) {
65068 if ('\\' === DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
65069 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);
65070 }
65071 }
65072 throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
65073 }
65074 }
65075
65076
65077
65078
65079
65080
65081
65082
65083
65084 public function makePathRelative($endPath, $startPath)
65085 {
65086
65087  if ('\\' === DIRECTORY_SEPARATOR) {
65088 $endPath = str_replace('\\', '/', $endPath);
65089 $startPath = str_replace('\\', '/', $startPath);
65090 }
65091
65092 $stripDriveLetter = function ($path) {
65093 if (strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) {
65094 return substr($path, 2);
65095 }
65096
65097 return $path;
65098 };
65099
65100 $endPath = $stripDriveLetter($endPath);
65101 $startPath = $stripDriveLetter($startPath);
65102
65103
65104  $startPathArr = explode('/', trim($startPath, '/'));
65105 $endPathArr = explode('/', trim($endPath, '/'));
65106
65107 $normalizePathArray = function ($pathSegments, $absolute) {
65108 $result = array();
65109
65110 foreach ($pathSegments as $segment) {
65111 if ('..' === $segment && ($absolute || count($result))) {
65112 array_pop($result);
65113 } elseif ('.' !== $segment) {
65114 $result[] = $segment;
65115 }
65116 }
65117
65118 return $result;
65119 };
65120
65121 $startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath));
65122 $endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath));
65123
65124
65125  $index = 0;
65126 while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
65127 ++$index;
65128 }
65129
65130
65131  if (1 === count($startPathArr) && '' === $startPathArr[0]) {
65132 $depth = 0;
65133 } else {
65134 $depth = count($startPathArr) - $index;
65135 }
65136
65137
65138  $traverser = str_repeat('../', $depth);
65139
65140 $endPathRemainder = implode('/', array_slice($endPathArr, $index));
65141
65142
65143  $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
65144
65145 return '' === $relativePath ? './' : $relativePath;
65146 }
65147
65148
65149
65150
65151
65152
65153
65154
65155
65156
65157
65158
65159
65160
65161
65162
65163
65164
65165
65166
65167 public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
65168 {
65169 $targetDir = rtrim($targetDir, '/\\');
65170 $originDir = rtrim($originDir, '/\\');
65171 $originDirLen = strlen($originDir);
65172
65173
65174  if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
65175 $deleteIterator = $iterator;
65176 if (null === $deleteIterator) {
65177 $flags = \FilesystemIterator::SKIP_DOTS;
65178 $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
65179 }
65180 $targetDirLen = strlen($targetDir);
65181 foreach ($deleteIterator as $file) {
65182 $origin = $originDir.substr($file->getPathname(), $targetDirLen);
65183 if (!$this->exists($origin)) {
65184 $this->remove($file);
65185 }
65186 }
65187 }
65188
65189 $copyOnWindows = false;
65190 if (isset($options['copy_on_windows'])) {
65191 $copyOnWindows = $options['copy_on_windows'];
65192 }
65193
65194 if (null === $iterator) {
65195 $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
65196 $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
65197 }
65198
65199 if ($this->exists($originDir)) {
65200 $this->mkdir($targetDir);
65201 }
65202
65203 foreach ($iterator as $file) {
65204 $target = $targetDir.substr($file->getPathname(), $originDirLen);
65205
65206 if ($copyOnWindows) {
65207 if (is_file($file)) {
65208 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
65209 } elseif (is_dir($file)) {
65210 $this->mkdir($target);
65211 } else {
65212 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
65213 }
65214 } else {
65215 if (is_link($file)) {
65216 $this->symlink($file->getLinkTarget(), $target);
65217 } elseif (is_dir($file)) {
65218 $this->mkdir($target);
65219 } elseif (is_file($file)) {
65220 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
65221 } else {
65222 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
65223 }
65224 }
65225 }
65226 }
65227
65228
65229
65230
65231
65232
65233
65234
65235 public function isAbsolutePath($file)
65236 {
65237 return strspn($file, '/\\', 0, 1)
65238 || (strlen($file) > 3 && ctype_alpha($file[0])
65239 && ':' === substr($file, 1, 1)
65240 && strspn($file, '/\\', 2, 1)
65241 )
65242 || null !== parse_url($file, PHP_URL_SCHEME)
65243 ;
65244 }
65245
65246
65247
65248
65249
65250
65251
65252
65253
65254
65255 public function tempnam($dir, $prefix)
65256 {
65257 list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
65258
65259
65260  if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) {
65261 $tmpFile = @tempnam($hierarchy, $prefix);
65262
65263
65264  if (false !== $tmpFile) {
65265 if (null !== $scheme && 'gs' !== $scheme) {
65266 return $scheme.'://'.$tmpFile;
65267 }
65268
65269 return $tmpFile;
65270 }
65271
65272 throw new IOException('A temporary file could not be created.');
65273 }
65274
65275
65276  for ($i = 0; $i < 10; ++$i) {
65277
65278  $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true);
65279
65280
65281  
65282  $handle = @fopen($tmpFile, 'x+');
65283
65284
65285  if (false === $handle) {
65286 continue;
65287 }
65288
65289
65290  @fclose($handle);
65291
65292 return $tmpFile;
65293 }
65294
65295 throw new IOException('A temporary file could not be created.');
65296 }
65297
65298
65299
65300
65301
65302
65303
65304
65305
65306
65307
65308 public function dumpFile($filename, $content, $mode = 0666)
65309 {
65310 $dir = dirname($filename);
65311
65312 if (!is_dir($dir)) {
65313 $this->mkdir($dir);
65314 }
65315
65316 if (!is_writable($dir)) {
65317 throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
65318 }
65319
65320 $tmpFile = $this->tempnam($dir, basename($filename));
65321
65322 if (false === @file_put_contents($tmpFile, $content)) {
65323 throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
65324 }
65325
65326 if (null !== $mode) {
65327 if (func_num_args() > 2) {
65328 @trigger_error('Support for modifying file permissions is deprecated since Symfony 2.3.12 and will be removed in 3.0.', E_USER_DEPRECATED);
65329 }
65330
65331 $this->chmod($tmpFile, $mode);
65332 } elseif (file_exists($filename)) {
65333 @chmod($tmpFile, fileperms($filename));
65334 }
65335
65336 $this->rename($tmpFile, $filename, true);
65337 }
65338
65339
65340
65341
65342
65343
65344 private function toIterator($files)
65345 {
65346 if (!$files instanceof \Traversable) {
65347 $files = new \ArrayObject(is_array($files) ? $files : array($files));
65348 }
65349
65350 return $files;
65351 }
65352
65353
65354
65355
65356
65357
65358
65359
65360 private function getSchemeAndHierarchy($filename)
65361 {
65362 $components = explode('://', $filename, 2);
65363
65364 return 2 === count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
65365 }
65366
65367 private static function box($func)
65368 {
65369 self::$lastError = null;
65370 \set_error_handler(__CLASS__.'::handleError');
65371 try {
65372 $result = \call_user_func_array($func, \array_slice(\func_get_args(), 1));
65373 \restore_error_handler();
65374
65375 return $result;
65376 } catch (\Throwable $e) {
65377 } catch (\Exception $e) {
65378 }
65379 \restore_error_handler();
65380
65381 throw $e;
65382 }
65383
65384
65385
65386
65387 public static function handleError($type, $msg)
65388 {
65389 self::$lastError = $msg;
65390 }
65391 }
65392 Copyright (c) 2004-2018 Fabien Potencier
65393
65394 Permission is hereby granted, free of charge, to any person obtaining a copy
65395 of this software and associated documentation files (the "Software"), to deal
65396 in the Software without restriction, including without limitation the rights
65397 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
65398 copies of the Software, and to permit persons to whom the Software is furnished
65399 to do so, subject to the following conditions:
65400
65401 The above copyright notice and this permission notice shall be included in all
65402 copies or substantial portions of the Software.
65403
65404 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
65405 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
65406 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
65407 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
65408 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
65409 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
65410 THE SOFTWARE.
65411 <?php
65412
65413
65414
65415
65416
65417
65418
65419
65420
65421
65422 namespace Symfony\Component\Filesystem;
65423
65424 use Symfony\Component\Filesystem\Exception\IOException;
65425
65426
65427
65428
65429
65430
65431
65432
65433
65434
65435
65436
65437
65438
65439 class LockHandler
65440 {
65441 private $file;
65442 private $handle;
65443
65444
65445
65446
65447
65448
65449
65450 public function __construct($name, $lockPath = null)
65451 {
65452 $lockPath = $lockPath ?: sys_get_temp_dir();
65453
65454 if (!is_dir($lockPath)) {
65455 $fs = new Filesystem();
65456 $fs->mkdir($lockPath);
65457 }
65458
65459 if (!is_writable($lockPath)) {
65460 throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
65461 }
65462
65463 $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
65464 }
65465
65466
65467
65468
65469
65470
65471
65472
65473
65474
65475 public function lock($blocking = false)
65476 {
65477 if ($this->handle) {
65478 return true;
65479 }
65480
65481 $error = null;
65482
65483
65484  set_error_handler(function ($errno, $msg) use (&$error) {
65485 $error = $msg;
65486 });
65487
65488 if (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) {
65489 if ($this->handle = fopen($this->file, 'x')) {
65490 chmod($this->file, 0666);
65491 } elseif (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) {
65492 usleep(100); 
65493  $this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r');
65494 }
65495 }
65496 restore_error_handler();
65497
65498 if (!$this->handle) {
65499 throw new IOException($error, 0, null, $this->file);
65500 }
65501
65502
65503  
65504  if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
65505 fclose($this->handle);
65506 $this->handle = null;
65507
65508 return false;
65509 }
65510
65511 return true;
65512 }
65513
65514
65515
65516
65517 public function release()
65518 {
65519 if ($this->handle) {
65520 flock($this->handle, LOCK_UN | LOCK_NB);
65521 fclose($this->handle);
65522 $this->handle = null;
65523 }
65524 }
65525 }
65526 <?php
65527
65528
65529
65530
65531
65532
65533
65534
65535
65536
65537 namespace Symfony\Component\Finder\Adapter;
65538
65539 @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);
65540
65541
65542
65543
65544
65545
65546
65547
65548 abstract class AbstractAdapter implements AdapterInterface
65549 {
65550 protected $followLinks = false;
65551 protected $mode = 0;
65552 protected $minDepth = 0;
65553 protected $maxDepth = PHP_INT_MAX;
65554 protected $exclude = array();
65555 protected $names = array();
65556 protected $notNames = array();
65557 protected $contains = array();
65558 protected $notContains = array();
65559 protected $sizes = array();
65560 protected $dates = array();
65561 protected $filters = array();
65562 protected $sort = false;
65563 protected $paths = array();
65564 protected $notPaths = array();
65565 protected $ignoreUnreadableDirs = false;
65566
65567 private static $areSupported = array();
65568
65569
65570
65571
65572 public function isSupported()
65573 {
65574 $name = $this->getName();
65575
65576 if (!array_key_exists($name, self::$areSupported)) {
65577 self::$areSupported[$name] = $this->canBeUsed();
65578 }
65579
65580 return self::$areSupported[$name];
65581 }
65582
65583
65584
65585
65586 public function setFollowLinks($followLinks)
65587 {
65588 $this->followLinks = $followLinks;
65589
65590 return $this;
65591 }
65592
65593
65594
65595
65596 public function setMode($mode)
65597 {
65598 $this->mode = $mode;
65599
65600 return $this;
65601 }
65602
65603
65604
65605
65606 public function setDepths(array $depths)
65607 {
65608 $this->minDepth = 0;
65609 $this->maxDepth = PHP_INT_MAX;
65610
65611 foreach ($depths as $comparator) {
65612 switch ($comparator->getOperator()) {
65613 case '>':
65614 $this->minDepth = $comparator->getTarget() + 1;
65615 break;
65616 case '>=':
65617 $this->minDepth = $comparator->getTarget();
65618 break;
65619 case '<':
65620 $this->maxDepth = $comparator->getTarget() - 1;
65621 break;
65622 case '<=':
65623 $this->maxDepth = $comparator->getTarget();
65624 break;
65625 default:
65626 $this->minDepth = $this->maxDepth = $comparator->getTarget();
65627 }
65628 }
65629
65630 return $this;
65631 }
65632
65633
65634
65635
65636 public function setExclude(array $exclude)
65637 {
65638 $this->exclude = $exclude;
65639
65640 return $this;
65641 }
65642
65643
65644
65645
65646 public function setNames(array $names)
65647 {
65648 $this->names = $names;
65649
65650 return $this;
65651 }
65652
65653
65654
65655
65656 public function setNotNames(array $notNames)
65657 {
65658 $this->notNames = $notNames;
65659
65660 return $this;
65661 }
65662
65663
65664
65665
65666 public function setContains(array $contains)
65667 {
65668 $this->contains = $contains;
65669
65670 return $this;
65671 }
65672
65673
65674
65675
65676 public function setNotContains(array $notContains)
65677 {
65678 $this->notContains = $notContains;
65679
65680 return $this;
65681 }
65682
65683
65684
65685
65686 public function setSizes(array $sizes)
65687 {
65688 $this->sizes = $sizes;
65689
65690 return $this;
65691 }
65692
65693
65694
65695
65696 public function setDates(array $dates)
65697 {
65698 $this->dates = $dates;
65699
65700 return $this;
65701 }
65702
65703
65704
65705
65706 public function setFilters(array $filters)
65707 {
65708 $this->filters = $filters;
65709
65710 return $this;
65711 }
65712
65713
65714
65715
65716 public function setSort($sort)
65717 {
65718 $this->sort = $sort;
65719
65720 return $this;
65721 }
65722
65723
65724
65725
65726 public function setPath(array $paths)
65727 {
65728 $this->paths = $paths;
65729
65730 return $this;
65731 }
65732
65733
65734
65735
65736 public function setNotPath(array $notPaths)
65737 {
65738 $this->notPaths = $notPaths;
65739
65740 return $this;
65741 }
65742
65743
65744
65745
65746 public function ignoreUnreadableDirs($ignore = true)
65747 {
65748 $this->ignoreUnreadableDirs = (bool) $ignore;
65749
65750 return $this;
65751 }
65752
65753
65754
65755
65756
65757
65758
65759
65760
65761
65762
65763
65764 abstract protected function canBeUsed();
65765 }
65766 <?php
65767
65768
65769
65770
65771
65772
65773
65774
65775
65776
65777 namespace Symfony\Component\Finder\Adapter;
65778
65779 @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);
65780
65781 use Symfony\Component\Finder\Exception\AccessDeniedException;
65782 use Symfony\Component\Finder\Iterator;
65783 use Symfony\Component\Finder\Shell\Shell;
65784 use Symfony\Component\Finder\Expression\Expression;
65785 use Symfony\Component\Finder\Shell\Command;
65786 use Symfony\Component\Finder\Comparator\NumberComparator;
65787 use Symfony\Component\Finder\Comparator\DateComparator;
65788
65789
65790
65791
65792
65793
65794
65795
65796 abstract class AbstractFindAdapter extends AbstractAdapter
65797 {
65798 protected $shell;
65799
65800 public function __construct()
65801 {
65802 $this->shell = new Shell();
65803 }
65804
65805
65806
65807
65808 public function searchInDirectory($dir)
65809 {
65810
65811  $dir = realpath($dir);
65812
65813
65814  if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
65815 return new Iterator\FilePathsIterator(array(), $dir);
65816 }
65817
65818 $command = Command::create();
65819 $find = $this->buildFindCommand($command, $dir);
65820
65821 if ($this->followLinks) {
65822 $find->add('-follow');
65823 }
65824
65825 $find->add('-mindepth')->add($this->minDepth + 1);
65826
65827 if (PHP_INT_MAX !== $this->maxDepth) {
65828 $find->add('-maxdepth')->add($this->maxDepth + 1);
65829 }
65830
65831 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
65832 $find->add('-type d');
65833 } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
65834 $find->add('-type f');
65835 }
65836
65837 $this->buildNamesFiltering($find, $this->names);
65838 $this->buildNamesFiltering($find, $this->notNames, true);
65839 $this->buildPathsFiltering($find, $dir, $this->paths);
65840 $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
65841 $this->buildSizesFiltering($find, $this->sizes);
65842 $this->buildDatesFiltering($find, $this->dates);
65843
65844 $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
65845 $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
65846
65847 if ($useGrep && ($this->contains || $this->notContains)) {
65848 $grep = $command->ins('grep');
65849 $this->buildContentFiltering($grep, $this->contains);
65850 $this->buildContentFiltering($grep, $this->notContains, true);
65851 }
65852
65853 if ($useSort) {
65854 $this->buildSorting($command, $this->sort);
65855 }
65856
65857 $command->setErrorHandler(
65858 $this->ignoreUnreadableDirs
65859
65860  ? function ($stderr) { }
65861 : function ($stderr) { throw new AccessDeniedException($stderr); }
65862 );
65863
65864 $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
65865 $iterator = new Iterator\FilePathsIterator($paths, $dir);
65866
65867 if ($this->exclude) {
65868 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
65869 }
65870
65871 if (!$useGrep && ($this->contains || $this->notContains)) {
65872 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
65873 }
65874
65875 if ($this->filters) {
65876 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
65877 }
65878
65879 if (!$useSort && $this->sort) {
65880 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
65881 $iterator = $iteratorAggregate->getIterator();
65882 }
65883
65884 return $iterator;
65885 }
65886
65887
65888
65889
65890 protected function canBeUsed()
65891 {
65892 return $this->shell->testCommand('find');
65893 }
65894
65895
65896
65897
65898
65899
65900
65901 protected function buildFindCommand(Command $command, $dir)
65902 {
65903 return $command
65904 ->ins('find')
65905 ->add('find ')
65906 ->arg($dir)
65907 ->add('-noleaf'); 
65908  }
65909
65910
65911
65912
65913
65914
65915 private function buildNamesFiltering(Command $command, array $names, $not = false)
65916 {
65917 if (0 === count($names)) {
65918 return;
65919 }
65920
65921 $command->add($not ? '-not' : null)->cmd('(');
65922
65923 foreach ($names as $i => $name) {
65924 $expr = Expression::create($name);
65925
65926
65927  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
65928 $expr = Expression::create($expr->getGlob()->toRegex(false));
65929 }
65930
65931
65932  
65933  
65934  if ($expr->isRegex()) {
65935 $regex = $expr->getRegex();
65936 $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
65937 ->setStartFlag(false)
65938 ->setStartJoker(true)
65939 ->replaceJokers('[^/]');
65940 if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
65941 $regex->setEndJoker(false)->append('[^/]*');
65942 }
65943 }
65944
65945 $command
65946 ->add($i > 0 ? '-or' : null)
65947 ->add($expr->isRegex()
65948 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
65949 : ($expr->isCaseSensitive() ? '-name' : '-iname')
65950 )
65951 ->arg($expr->renderPattern());
65952 }
65953
65954 $command->cmd(')');
65955 }
65956
65957
65958
65959
65960
65961
65962
65963 private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
65964 {
65965 if (0 === count($paths)) {
65966 return;
65967 }
65968
65969 $command->add($not ? '-not' : null)->cmd('(');
65970
65971 foreach ($paths as $i => $path) {
65972 $expr = Expression::create($path);
65973
65974
65975  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
65976 $expr = Expression::create($expr->getGlob()->toRegex(false));
65977 }
65978
65979
65980  if ($expr->isRegex()) {
65981 $regex = $expr->getRegex();
65982 $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
65983 } else {
65984 $expr->prepend('*')->append('*');
65985 }
65986
65987 $command
65988 ->add($i > 0 ? '-or' : null)
65989 ->add($expr->isRegex()
65990 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
65991 : ($expr->isCaseSensitive() ? '-path' : '-ipath')
65992 )
65993 ->arg($expr->renderPattern());
65994 }
65995
65996 $command->cmd(')');
65997 }
65998
65999
66000
66001
66002
66003 private function buildSizesFiltering(Command $command, array $sizes)
66004 {
66005 foreach ($sizes as $i => $size) {
66006 $command->add($i > 0 ? '-and' : null);
66007
66008 switch ($size->getOperator()) {
66009 case '<=':
66010 $command->add('-size -'.($size->getTarget() + 1).'c');
66011 break;
66012 case '>=':
66013 $command->add('-size +'.($size->getTarget() - 1).'c');
66014 break;
66015 case '>':
66016 $command->add('-size +'.$size->getTarget().'c');
66017 break;
66018 case '!=':
66019 $command->add('-size -'.$size->getTarget().'c');
66020 $command->add('-size +'.$size->getTarget().'c');
66021 break;
66022 case '<':
66023 default:
66024 $command->add('-size -'.$size->getTarget().'c');
66025 }
66026 }
66027 }
66028
66029
66030
66031
66032
66033 private function buildDatesFiltering(Command $command, array $dates)
66034 {
66035 foreach ($dates as $i => $date) {
66036 $command->add($i > 0 ? '-and' : null);
66037
66038 $mins = (int) round((time() - $date->getTarget()) / 60);
66039
66040 if (0 > $mins) {
66041
66042  $command->add(' -mmin -0');
66043
66044  return;
66045 }
66046
66047 switch ($date->getOperator()) {
66048 case '<=':
66049 $command->add('-mmin +'.($mins - 1));
66050 break;
66051 case '>=':
66052 $command->add('-mmin -'.($mins + 1));
66053 break;
66054 case '>':
66055 $command->add('-mmin -'.$mins);
66056 break;
66057 case '!=':
66058 $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
66059 break;
66060 case '<':
66061 default:
66062 $command->add('-mmin +'.$mins);
66063 }
66064 }
66065 }
66066
66067
66068
66069
66070
66071
66072
66073 private function buildSorting(Command $command, $sort)
66074 {
66075 $this->buildFormatSorting($command, $sort);
66076 }
66077
66078
66079
66080
66081
66082 abstract protected function buildFormatSorting(Command $command, $sort);
66083
66084
66085
66086
66087
66088
66089 abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
66090 }
66091 <?php
66092
66093
66094
66095
66096
66097
66098
66099
66100
66101
66102 namespace Symfony\Component\Finder\Adapter;
66103
66104
66105
66106
66107
66108
66109 interface AdapterInterface
66110 {
66111
66112
66113
66114
66115
66116 public function setFollowLinks($followLinks);
66117
66118
66119
66120
66121
66122
66123 public function setMode($mode);
66124
66125
66126
66127
66128 public function setExclude(array $exclude);
66129
66130
66131
66132
66133 public function setDepths(array $depths);
66134
66135
66136
66137
66138 public function setNames(array $names);
66139
66140
66141
66142
66143 public function setNotNames(array $notNames);
66144
66145
66146
66147
66148 public function setContains(array $contains);
66149
66150
66151
66152
66153 public function setNotContains(array $notContains);
66154
66155
66156
66157
66158 public function setSizes(array $sizes);
66159
66160
66161
66162
66163 public function setDates(array $dates);
66164
66165
66166
66167
66168 public function setFilters(array $filters);
66169
66170
66171
66172
66173
66174
66175 public function setSort($sort);
66176
66177
66178
66179
66180 public function setPath(array $paths);
66181
66182
66183
66184
66185 public function setNotPath(array $notPaths);
66186
66187
66188
66189
66190
66191
66192 public function ignoreUnreadableDirs($ignore = true);
66193
66194
66195
66196
66197
66198
66199 public function searchInDirectory($dir);
66200
66201
66202
66203
66204
66205
66206 public function isSupported();
66207
66208
66209
66210
66211
66212
66213 public function getName();
66214 }
66215 <?php
66216
66217
66218
66219
66220
66221
66222
66223
66224
66225
66226 namespace Symfony\Component\Finder\Adapter;
66227
66228 @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);
66229
66230 use Symfony\Component\Finder\Shell\Shell;
66231 use Symfony\Component\Finder\Shell\Command;
66232 use Symfony\Component\Finder\Iterator\SortableIterator;
66233 use Symfony\Component\Finder\Expression\Expression;
66234
66235
66236
66237
66238
66239
66240
66241
66242 class BsdFindAdapter extends AbstractFindAdapter
66243 {
66244
66245
66246
66247 public function getName()
66248 {
66249 return 'bsd_find';
66250 }
66251
66252
66253
66254
66255 protected function canBeUsed()
66256 {
66257 return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
66258 }
66259
66260
66261
66262
66263 protected function buildFormatSorting(Command $command, $sort)
66264 {
66265 switch ($sort) {
66266 case SortableIterator::SORT_BY_NAME:
66267 $command->ins('sort')->add('| sort');
66268
66269 return;
66270 case SortableIterator::SORT_BY_TYPE:
66271 $format = '%HT';
66272 break;
66273 case SortableIterator::SORT_BY_ACCESSED_TIME:
66274 $format = '%a';
66275 break;
66276 case SortableIterator::SORT_BY_CHANGED_TIME:
66277 $format = '%c';
66278 break;
66279 case SortableIterator::SORT_BY_MODIFIED_TIME:
66280 $format = '%m';
66281 break;
66282 default:
66283 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
66284 }
66285
66286 $command
66287 ->add('-print0 | xargs -0 stat -f')
66288 ->arg($format.'%t%N')
66289 ->add('| sort | cut -f 2');
66290 }
66291
66292
66293
66294
66295 protected function buildFindCommand(Command $command, $dir)
66296 {
66297 parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
66298
66299 return $command;
66300 }
66301
66302
66303
66304
66305 protected function buildContentFiltering(Command $command, array $contains, $not = false)
66306 {
66307 foreach ($contains as $contain) {
66308 $expr = Expression::create($contain);
66309
66310
66311  $command
66312 ->add('| grep -v \'^$\'')
66313 ->add('| xargs -I{} grep -I')
66314 ->add($expr->isCaseSensitive() ? null : '-i')
66315 ->add($not ? '-L' : '-l')
66316 ->add('-Ee')->arg($expr->renderPattern())
66317 ->add('{}')
66318 ;
66319 }
66320 }
66321 }
66322 <?php
66323
66324
66325
66326
66327
66328
66329
66330
66331
66332
66333 namespace Symfony\Component\Finder\Adapter;
66334
66335 @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);
66336
66337 use Symfony\Component\Finder\Shell\Shell;
66338 use Symfony\Component\Finder\Shell\Command;
66339 use Symfony\Component\Finder\Iterator\SortableIterator;
66340 use Symfony\Component\Finder\Expression\Expression;
66341
66342
66343
66344
66345
66346
66347
66348
66349 class GnuFindAdapter extends AbstractFindAdapter
66350 {
66351
66352
66353
66354 public function getName()
66355 {
66356 return 'gnu_find';
66357 }
66358
66359
66360
66361
66362 protected function buildFormatSorting(Command $command, $sort)
66363 {
66364 switch ($sort) {
66365 case SortableIterator::SORT_BY_NAME:
66366 $command->ins('sort')->add('| sort');
66367
66368 return;
66369 case SortableIterator::SORT_BY_TYPE:
66370 $format = '%y';
66371 break;
66372 case SortableIterator::SORT_BY_ACCESSED_TIME:
66373 $format = '%A@';
66374 break;
66375 case SortableIterator::SORT_BY_CHANGED_TIME:
66376 $format = '%C@';
66377 break;
66378 case SortableIterator::SORT_BY_MODIFIED_TIME:
66379 $format = '%T@';
66380 break;
66381 default:
66382 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
66383 }
66384
66385 $command
66386 ->get('find')
66387 ->add('-printf')
66388 ->arg($format.' %h/%f\\n')
66389 ->add('| sort | cut')
66390 ->arg('-d ')
66391 ->arg('-f2-')
66392 ;
66393 }
66394
66395
66396
66397
66398 protected function canBeUsed()
66399 {
66400 return Shell::TYPE_UNIX === $this->shell->getType() && parent::canBeUsed();
66401 }
66402
66403
66404
66405
66406 protected function buildFindCommand(Command $command, $dir)
66407 {
66408 return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
66409 }
66410
66411
66412
66413
66414 protected function buildContentFiltering(Command $command, array $contains, $not = false)
66415 {
66416 foreach ($contains as $contain) {
66417 $expr = Expression::create($contain);
66418
66419
66420  $command
66421 ->add('| xargs -I{} -r grep -I')
66422 ->add($expr->isCaseSensitive() ? null : '-i')
66423 ->add($not ? '-L' : '-l')
66424 ->add('-Ee')->arg($expr->renderPattern())
66425 ->add('{}')
66426 ;
66427 }
66428 }
66429 }
66430 <?php
66431
66432
66433
66434
66435
66436
66437
66438
66439
66440
66441 namespace Symfony\Component\Finder\Adapter;
66442
66443 @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);
66444
66445 use Symfony\Component\Finder\Iterator;
66446
66447
66448
66449
66450
66451
66452
66453
66454 class PhpAdapter extends AbstractAdapter
66455 {
66456
66457
66458
66459 public function searchInDirectory($dir)
66460 {
66461 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
66462
66463 if ($this->followLinks) {
66464 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
66465 }
66466
66467 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
66468
66469 if ($this->exclude) {
66470 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
66471 }
66472
66473 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
66474
66475 if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
66476 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
66477 }
66478
66479 if ($this->mode) {
66480 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
66481 }
66482
66483 if ($this->names || $this->notNames) {
66484 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
66485 }
66486
66487 if ($this->contains || $this->notContains) {
66488 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
66489 }
66490
66491 if ($this->sizes) {
66492 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
66493 }
66494
66495 if ($this->dates) {
66496 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
66497 }
66498
66499 if ($this->filters) {
66500 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
66501 }
66502
66503 if ($this->paths || $this->notPaths) {
66504 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
66505 }
66506
66507 if ($this->sort) {
66508 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
66509 $iterator = $iteratorAggregate->getIterator();
66510 }
66511
66512 return $iterator;
66513 }
66514
66515
66516
66517
66518 public function getName()
66519 {
66520 return 'php';
66521 }
66522
66523
66524
66525
66526 protected function canBeUsed()
66527 {
66528 return true;
66529 }
66530 }
66531 <?php
66532
66533
66534
66535
66536
66537
66538
66539
66540
66541
66542 namespace Symfony\Component\Finder\Comparator;
66543
66544
66545
66546
66547
66548
66549 class Comparator
66550 {
66551 private $target;
66552 private $operator = '==';
66553
66554
66555
66556
66557
66558
66559 public function getTarget()
66560 {
66561 return $this->target;
66562 }
66563
66564
66565
66566
66567
66568
66569 public function setTarget($target)
66570 {
66571 $this->target = $target;
66572 }
66573
66574
66575
66576
66577
66578
66579 public function getOperator()
66580 {
66581 return $this->operator;
66582 }
66583
66584
66585
66586
66587
66588
66589
66590
66591 public function setOperator($operator)
66592 {
66593 if (!$operator) {
66594 $operator = '==';
66595 }
66596
66597 if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
66598 throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
66599 }
66600
66601 $this->operator = $operator;
66602 }
66603
66604
66605
66606
66607
66608
66609
66610
66611 public function test($test)
66612 {
66613 switch ($this->operator) {
66614 case '>':
66615 return $test > $this->target;
66616 case '>=':
66617 return $test >= $this->target;
66618 case '<':
66619 return $test < $this->target;
66620 case '<=':
66621 return $test <= $this->target;
66622 case '!=':
66623 return $test != $this->target;
66624 }
66625
66626 return $test == $this->target;
66627 }
66628 }
66629 <?php
66630
66631
66632
66633
66634
66635
66636
66637
66638
66639
66640 namespace Symfony\Component\Finder\Comparator;
66641
66642
66643
66644
66645
66646
66647 class DateComparator extends Comparator
66648 {
66649
66650
66651
66652
66653
66654 public function __construct($test)
66655 {
66656 if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
66657 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
66658 }
66659
66660 try {
66661 $date = new \DateTime($matches[2]);
66662 $target = $date->format('U');
66663 } catch (\Exception $e) {
66664 throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
66665 }
66666
66667 $operator = isset($matches[1]) ? $matches[1] : '==';
66668 if ('since' === $operator || 'after' === $operator) {
66669 $operator = '>';
66670 }
66671
66672 if ('until' === $operator || 'before' === $operator) {
66673 $operator = '<';
66674 }
66675
66676 $this->setOperator($operator);
66677 $this->setTarget($target);
66678 }
66679 }
66680 <?php
66681
66682
66683
66684
66685
66686
66687
66688
66689
66690
66691 namespace Symfony\Component\Finder\Comparator;
66692
66693
66694
66695
66696
66697
66698
66699
66700
66701
66702
66703
66704
66705
66706
66707
66708
66709
66710
66711
66712
66713
66714 class NumberComparator extends Comparator
66715 {
66716
66717
66718
66719
66720
66721 public function __construct($test)
66722 {
66723 if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
66724 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
66725 }
66726
66727 $target = $matches[2];
66728 if (!is_numeric($target)) {
66729 throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
66730 }
66731 if (isset($matches[3])) {
66732
66733  switch (strtolower($matches[3])) {
66734 case 'k':
66735 $target *= 1000;
66736 break;
66737 case 'ki':
66738 $target *= 1024;
66739 break;
66740 case 'm':
66741 $target *= 1000000;
66742 break;
66743 case 'mi':
66744 $target *= 1024 * 1024;
66745 break;
66746 case 'g':
66747 $target *= 1000000000;
66748 break;
66749 case 'gi':
66750 $target *= 1024 * 1024 * 1024;
66751 break;
66752 }
66753 }
66754
66755 $this->setTarget($target);
66756 $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
66757 }
66758 }
66759 <?php
66760
66761
66762
66763
66764
66765
66766
66767
66768
66769
66770 namespace Symfony\Component\Finder\Exception;
66771
66772
66773
66774
66775 class AccessDeniedException extends \UnexpectedValueException
66776 {
66777 }
66778 <?php
66779
66780
66781
66782
66783
66784
66785
66786
66787
66788
66789 namespace Symfony\Component\Finder\Exception;
66790
66791 @trigger_error('The '.__NAMESPACE__.'\AdapterFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66792
66793 use Symfony\Component\Finder\Adapter\AdapterInterface;
66794
66795
66796
66797
66798
66799
66800
66801
66802 class AdapterFailureException extends \RuntimeException implements ExceptionInterface
66803 {
66804 private $adapter;
66805
66806
66807
66808
66809
66810
66811 public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
66812 {
66813 $this->adapter = $adapter;
66814 parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
66815 }
66816
66817
66818
66819
66820 public function getAdapter()
66821 {
66822 return $this->adapter;
66823 }
66824 }
66825 <?php
66826
66827
66828
66829
66830
66831
66832
66833
66834
66835
66836 namespace Symfony\Component\Finder\Exception;
66837
66838
66839
66840
66841 interface ExceptionInterface
66842 {
66843
66844
66845
66846 public function getAdapter();
66847 }
66848 <?php
66849
66850
66851
66852
66853
66854
66855
66856
66857
66858
66859 namespace Symfony\Component\Finder\Exception;
66860
66861 @trigger_error('The '.__NAMESPACE__.'\OperationNotPermitedException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66862
66863
66864
66865
66866
66867
66868 class OperationNotPermitedException extends AdapterFailureException
66869 {
66870 }
66871 <?php
66872
66873
66874
66875
66876
66877
66878
66879
66880
66881
66882 namespace Symfony\Component\Finder\Exception;
66883
66884 @trigger_error('The '.__NAMESPACE__.'\ShellCommandFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66885
66886 use Symfony\Component\Finder\Adapter\AdapterInterface;
66887 use Symfony\Component\Finder\Shell\Command;
66888
66889
66890
66891
66892
66893
66894 class ShellCommandFailureException extends AdapterFailureException
66895 {
66896 private $command;
66897
66898 public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
66899 {
66900 $this->command = $command;
66901 parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
66902 }
66903
66904
66905
66906
66907 public function getCommand()
66908 {
66909 return $this->command;
66910 }
66911 }
66912 <?php
66913
66914
66915
66916
66917
66918
66919
66920
66921
66922
66923 namespace Symfony\Component\Finder\Expression;
66924
66925 @trigger_error('The '.__NAMESPACE__.'\Expression class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66926
66927
66928
66929
66930 class Expression implements ValueInterface
66931 {
66932 const TYPE_REGEX = 1;
66933 const TYPE_GLOB = 2;
66934
66935
66936
66937
66938 private $value;
66939
66940
66941
66942
66943
66944
66945 public static function create($expr)
66946 {
66947 return new self($expr);
66948 }
66949
66950
66951
66952
66953 public function __construct($expr)
66954 {
66955 try {
66956 $this->value = Regex::create($expr);
66957 } catch (\InvalidArgumentException $e) {
66958 $this->value = new Glob($expr);
66959 }
66960 }
66961
66962
66963
66964
66965 public function __toString()
66966 {
66967 return $this->render();
66968 }
66969
66970
66971
66972
66973 public function render()
66974 {
66975 return $this->value->render();
66976 }
66977
66978
66979
66980
66981 public function renderPattern()
66982 {
66983 return $this->value->renderPattern();
66984 }
66985
66986
66987
66988
66989 public function isCaseSensitive()
66990 {
66991 return $this->value->isCaseSensitive();
66992 }
66993
66994
66995
66996
66997 public function getType()
66998 {
66999 return $this->value->getType();
67000 }
67001
67002
67003
67004
67005 public function prepend($expr)
67006 {
67007 $this->value->prepend($expr);
67008
67009 return $this;
67010 }
67011
67012
67013
67014
67015 public function append($expr)
67016 {
67017 $this->value->append($expr);
67018
67019 return $this;
67020 }
67021
67022
67023
67024
67025 public function isRegex()
67026 {
67027 return self::TYPE_REGEX === $this->value->getType();
67028 }
67029
67030
67031
67032
67033 public function isGlob()
67034 {
67035 return self::TYPE_GLOB === $this->value->getType();
67036 }
67037
67038
67039
67040
67041
67042
67043 public function getGlob()
67044 {
67045 if (self::TYPE_GLOB !== $this->value->getType()) {
67046 throw new \LogicException('Regex can\'t be transformed to glob.');
67047 }
67048
67049 return $this->value;
67050 }
67051
67052
67053
67054
67055 public function getRegex()
67056 {
67057 return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
67058 }
67059 }
67060 <?php
67061
67062
67063
67064
67065
67066
67067
67068
67069
67070
67071 namespace Symfony\Component\Finder\Expression;
67072
67073 @trigger_error('The '.__NAMESPACE__.'\Glob class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67074
67075 use Symfony\Component\Finder\Glob as FinderGlob;
67076
67077
67078
67079
67080 class Glob implements ValueInterface
67081 {
67082 private $pattern;
67083
67084
67085
67086
67087 public function __construct($pattern)
67088 {
67089 $this->pattern = $pattern;
67090 }
67091
67092
67093
67094
67095 public function render()
67096 {
67097 return $this->pattern;
67098 }
67099
67100
67101
67102
67103 public function renderPattern()
67104 {
67105 return $this->pattern;
67106 }
67107
67108
67109
67110
67111 public function getType()
67112 {
67113 return Expression::TYPE_GLOB;
67114 }
67115
67116
67117
67118
67119 public function isCaseSensitive()
67120 {
67121 return true;
67122 }
67123
67124
67125
67126
67127 public function prepend($expr)
67128 {
67129 $this->pattern = $expr.$this->pattern;
67130
67131 return $this;
67132 }
67133
67134
67135
67136
67137 public function append($expr)
67138 {
67139 $this->pattern .= $expr;
67140
67141 return $this;
67142 }
67143
67144
67145
67146
67147
67148
67149 public function isExpandable()
67150 {
67151 return false !== strpos($this->pattern, '{')
67152 && false !== strpos($this->pattern, '}');
67153 }
67154
67155
67156
67157
67158
67159
67160
67161 public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
67162 {
67163 $regex = FinderGlob::toRegex($this->pattern, $strictLeadingDot, $strictWildcardSlash, '');
67164
67165 return new Regex($regex);
67166 }
67167 }
67168 <?php
67169
67170
67171
67172
67173
67174
67175
67176
67177
67178
67179 namespace Symfony\Component\Finder\Expression;
67180
67181 @trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67182
67183
67184
67185
67186 class Regex implements ValueInterface
67187 {
67188 const START_FLAG = '^';
67189 const END_FLAG = '$';
67190 const BOUNDARY = '~';
67191 const JOKER = '.*';
67192 const ESCAPING = '\\';
67193
67194
67195
67196
67197 private $pattern;
67198
67199
67200
67201
67202 private $options;
67203
67204
67205
67206
67207 private $startFlag;
67208
67209
67210
67211
67212 private $endFlag;
67213
67214
67215
67216
67217 private $startJoker;
67218
67219
67220
67221
67222 private $endJoker;
67223
67224
67225
67226
67227
67228
67229
67230
67231 public static function create($expr)
67232 {
67233 if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
67234 $start = substr($m[1], 0, 1);
67235 $end = substr($m[1], -1);
67236
67237 if (
67238 ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
67239 || ('{' === $start && '}' === $end)
67240 || ('(' === $start && ')' === $end)
67241 ) {
67242 return new self(substr($m[1], 1, -1), $m[2], $end);
67243 }
67244 }
67245
67246 throw new \InvalidArgumentException('Given expression is not a regex.');
67247 }
67248
67249
67250
67251
67252
67253
67254 public function __construct($pattern, $options = '', $delimiter = null)
67255 {
67256 if (null !== $delimiter) {
67257
67258  $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
67259 }
67260
67261 $this->parsePattern($pattern);
67262 $this->options = $options;
67263 }
67264
67265
67266
67267
67268 public function __toString()
67269 {
67270 return $this->render();
67271 }
67272
67273
67274
67275
67276 public function render()
67277 {
67278 return self::BOUNDARY
67279 .$this->renderPattern()
67280 .self::BOUNDARY
67281 .$this->options;
67282 }
67283
67284
67285
67286
67287 public function renderPattern()
67288 {
67289 return ($this->startFlag ? self::START_FLAG : '')
67290 .($this->startJoker ? self::JOKER : '')
67291 .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
67292 .($this->endJoker ? self::JOKER : '')
67293 .($this->endFlag ? self::END_FLAG : '');
67294 }
67295
67296
67297
67298
67299 public function isCaseSensitive()
67300 {
67301 return !$this->hasOption('i');
67302 }
67303
67304
67305
67306
67307 public function getType()
67308 {
67309 return Expression::TYPE_REGEX;
67310 }
67311
67312
67313
67314
67315 public function prepend($expr)
67316 {
67317 $this->pattern = $expr.$this->pattern;
67318
67319 return $this;
67320 }
67321
67322
67323
67324
67325 public function append($expr)
67326 {
67327 $this->pattern .= $expr;
67328
67329 return $this;
67330 }
67331
67332
67333
67334
67335
67336
67337 public function hasOption($option)
67338 {
67339 return false !== strpos($this->options, $option);
67340 }
67341
67342
67343
67344
67345
67346
67347 public function addOption($option)
67348 {
67349 if (!$this->hasOption($option)) {
67350 $this->options .= $option;
67351 }
67352
67353 return $this;
67354 }
67355
67356
67357
67358
67359
67360
67361 public function removeOption($option)
67362 {
67363 $this->options = str_replace($option, '', $this->options);
67364
67365 return $this;
67366 }
67367
67368
67369
67370
67371
67372
67373 public function setStartFlag($startFlag)
67374 {
67375 $this->startFlag = $startFlag;
67376
67377 return $this;
67378 }
67379
67380
67381
67382
67383 public function hasStartFlag()
67384 {
67385 return $this->startFlag;
67386 }
67387
67388
67389
67390
67391
67392
67393 public function setEndFlag($endFlag)
67394 {
67395 $this->endFlag = (bool) $endFlag;
67396
67397 return $this;
67398 }
67399
67400
67401
67402
67403 public function hasEndFlag()
67404 {
67405 return $this->endFlag;
67406 }
67407
67408
67409
67410
67411
67412
67413 public function setStartJoker($startJoker)
67414 {
67415 $this->startJoker = $startJoker;
67416
67417 return $this;
67418 }
67419
67420
67421
67422
67423 public function hasStartJoker()
67424 {
67425 return $this->startJoker;
67426 }
67427
67428
67429
67430
67431
67432
67433 public function setEndJoker($endJoker)
67434 {
67435 $this->endJoker = (bool) $endJoker;
67436
67437 return $this;
67438 }
67439
67440
67441
67442
67443 public function hasEndJoker()
67444 {
67445 return $this->endJoker;
67446 }
67447
67448
67449
67450
67451 public function replaceJokers($replacement)
67452 {
67453 $replace = function ($subject) use ($replacement) {
67454 $subject = $subject[0];
67455 $replace = 0 === substr_count($subject, '\\') % 2;
67456
67457 return $replace ? str_replace('.', $replacement, $subject) : $subject;
67458 };
67459
67460 $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
67461
67462 return $this;
67463 }
67464
67465
67466
67467
67468 private function parsePattern($pattern)
67469 {
67470 if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
67471 $pattern = substr($pattern, 1);
67472 }
67473
67474 if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
67475 $pattern = substr($pattern, 2);
67476 }
67477
67478 if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
67479 $pattern = substr($pattern, 0, -1);
67480 }
67481
67482 if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
67483 $pattern = substr($pattern, 0, -2);
67484 }
67485
67486 $this->pattern = $pattern;
67487 }
67488 }
67489 <?php
67490
67491
67492
67493
67494
67495
67496
67497
67498
67499
67500 namespace Symfony\Component\Finder\Expression;
67501
67502 @trigger_error('The '.__NAMESPACE__.'\ValueInterface interface is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67503
67504
67505
67506
67507 interface ValueInterface
67508 {
67509
67510
67511
67512
67513
67514 public function render();
67515
67516
67517
67518
67519
67520
67521 public function renderPattern();
67522
67523
67524
67525
67526
67527
67528 public function isCaseSensitive();
67529
67530
67531
67532
67533
67534
67535 public function getType();
67536
67537
67538
67539
67540
67541
67542 public function prepend($expr);
67543
67544
67545
67546
67547
67548
67549 public function append($expr);
67550 }
67551 <?php
67552
67553
67554
67555
67556
67557
67558
67559
67560
67561
67562 namespace Symfony\Component\Finder;
67563
67564 use Symfony\Component\Finder\Adapter\AdapterInterface;
67565 use Symfony\Component\Finder\Adapter\GnuFindAdapter;
67566 use Symfony\Component\Finder\Adapter\BsdFindAdapter;
67567 use Symfony\Component\Finder\Adapter\PhpAdapter;
67568 use Symfony\Component\Finder\Comparator\DateComparator;
67569 use Symfony\Component\Finder\Comparator\NumberComparator;
67570 use Symfony\Component\Finder\Exception\ExceptionInterface;
67571 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
67572 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
67573 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
67574 use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
67575 use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
67576 use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
67577 use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
67578 use Symfony\Component\Finder\Iterator\SortableIterator;
67579
67580
67581
67582
67583
67584
67585
67586
67587
67588
67589
67590
67591
67592
67593 class Finder implements \IteratorAggregate, \Countable
67594 {
67595 const IGNORE_VCS_FILES = 1;
67596 const IGNORE_DOT_FILES = 2;
67597
67598 private $mode = 0;
67599 private $names = array();
67600 private $notNames = array();
67601 private $exclude = array();
67602 private $filters = array();
67603 private $depths = array();
67604 private $sizes = array();
67605 private $followLinks = false;
67606 private $sort = false;
67607 private $ignore = 0;
67608 private $dirs = array();
67609 private $dates = array();
67610 private $iterators = array();
67611 private $contains = array();
67612 private $notContains = array();
67613 private $adapters = null;
67614 private $paths = array();
67615 private $notPaths = array();
67616 private $ignoreUnreadableDirs = false;
67617
67618 private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
67619
67620 public function __construct()
67621 {
67622 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
67623 }
67624
67625
67626
67627
67628
67629
67630 public static function create()
67631 {
67632 return new static();
67633 }
67634
67635
67636
67637
67638
67639
67640
67641
67642
67643
67644
67645 public function addAdapter(AdapterInterface $adapter, $priority = 0)
67646 {
67647 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67648
67649 $this->initDefaultAdapters();
67650
67651 $this->adapters[$adapter->getName()] = array(
67652 'adapter' => $adapter,
67653 'priority' => $priority,
67654 'selected' => false,
67655 );
67656
67657 return $this->sortAdapters();
67658 }
67659
67660
67661
67662
67663
67664
67665
67666
67667 public function useBestAdapter()
67668 {
67669 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67670
67671 $this->initDefaultAdapters();
67672
67673 $this->resetAdapterSelection();
67674
67675 return $this->sortAdapters();
67676 }
67677
67678
67679
67680
67681
67682
67683
67684
67685
67686
67687
67688
67689 public function setAdapter($name)
67690 {
67691 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67692
67693 $this->initDefaultAdapters();
67694
67695 if (!isset($this->adapters[$name])) {
67696 throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
67697 }
67698
67699 $this->resetAdapterSelection();
67700 $this->adapters[$name]['selected'] = true;
67701
67702 return $this->sortAdapters();
67703 }
67704
67705
67706
67707
67708
67709
67710
67711
67712 public function removeAdapters()
67713 {
67714 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67715
67716 $this->adapters = array();
67717
67718 return $this;
67719 }
67720
67721
67722
67723
67724
67725
67726
67727
67728 public function getAdapters()
67729 {
67730 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67731
67732 $this->initDefaultAdapters();
67733
67734 return array_values(array_map(function (array $adapter) {
67735 return $adapter['adapter'];
67736 }, $this->adapters));
67737 }
67738
67739
67740
67741
67742
67743
67744 public function directories()
67745 {
67746 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
67747
67748 return $this;
67749 }
67750
67751
67752
67753
67754
67755
67756 public function files()
67757 {
67758 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
67759
67760 return $this;
67761 }
67762
67763
67764
67765
67766
67767
67768
67769
67770
67771
67772
67773
67774
67775
67776
67777
67778 public function depth($level)
67779 {
67780 $this->depths[] = new Comparator\NumberComparator($level);
67781
67782 return $this;
67783 }
67784
67785
67786
67787
67788
67789
67790
67791
67792
67793
67794
67795
67796
67797
67798
67799
67800
67801
67802
67803 public function date($date)
67804 {
67805 $this->dates[] = new Comparator\DateComparator($date);
67806
67807 return $this;
67808 }
67809
67810
67811
67812
67813
67814
67815
67816
67817
67818
67819
67820
67821
67822
67823
67824
67825 public function name($pattern)
67826 {
67827 $this->names[] = $pattern;
67828
67829 return $this;
67830 }
67831
67832
67833
67834
67835
67836
67837
67838
67839
67840
67841 public function notName($pattern)
67842 {
67843 $this->notNames[] = $pattern;
67844
67845 return $this;
67846 }
67847
67848
67849
67850
67851
67852
67853
67854
67855
67856
67857
67858
67859
67860
67861
67862 public function contains($pattern)
67863 {
67864 $this->contains[] = $pattern;
67865
67866 return $this;
67867 }
67868
67869
67870
67871
67872
67873
67874
67875
67876
67877
67878
67879
67880
67881
67882
67883 public function notContains($pattern)
67884 {
67885 $this->notContains[] = $pattern;
67886
67887 return $this;
67888 }
67889
67890
67891
67892
67893
67894
67895
67896
67897
67898
67899
67900
67901
67902
67903
67904
67905
67906 public function path($pattern)
67907 {
67908 $this->paths[] = $pattern;
67909
67910 return $this;
67911 }
67912
67913
67914
67915
67916
67917
67918
67919
67920
67921
67922
67923
67924
67925
67926
67927
67928
67929 public function notPath($pattern)
67930 {
67931 $this->notPaths[] = $pattern;
67932
67933 return $this;
67934 }
67935
67936
67937
67938
67939
67940
67941
67942
67943
67944
67945
67946
67947
67948
67949
67950 public function size($size)
67951 {
67952 $this->sizes[] = new Comparator\NumberComparator($size);
67953
67954 return $this;
67955 }
67956
67957
67958
67959
67960
67961
67962
67963
67964
67965
67966
67967
67968
67969
67970 public function exclude($dirs)
67971 {
67972 $this->exclude = array_merge($this->exclude, (array) $dirs);
67973
67974 return $this;
67975 }
67976
67977
67978
67979
67980
67981
67982
67983
67984
67985
67986
67987
67988 public function ignoreDotFiles($ignoreDotFiles)
67989 {
67990 if ($ignoreDotFiles) {
67991 $this->ignore |= static::IGNORE_DOT_FILES;
67992 } else {
67993 $this->ignore &= ~static::IGNORE_DOT_FILES;
67994 }
67995
67996 return $this;
67997 }
67998
67999
68000
68001
68002
68003
68004
68005
68006
68007
68008
68009
68010 public function ignoreVCS($ignoreVCS)
68011 {
68012 if ($ignoreVCS) {
68013 $this->ignore |= static::IGNORE_VCS_FILES;
68014 } else {
68015 $this->ignore &= ~static::IGNORE_VCS_FILES;
68016 }
68017
68018 return $this;
68019 }
68020
68021
68022
68023
68024
68025
68026
68027
68028 public static function addVCSPattern($pattern)
68029 {
68030 foreach ((array) $pattern as $p) {
68031 self::$vcsPatterns[] = $p;
68032 }
68033
68034 self::$vcsPatterns = array_unique(self::$vcsPatterns);
68035 }
68036
68037
68038
68039
68040
68041
68042
68043
68044
68045
68046
68047
68048 public function sort(\Closure $closure)
68049 {
68050 $this->sort = $closure;
68051
68052 return $this;
68053 }
68054
68055
68056
68057
68058
68059
68060
68061
68062
68063
68064 public function sortByName()
68065 {
68066 $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
68067
68068 return $this;
68069 }
68070
68071
68072
68073
68074
68075
68076
68077
68078
68079
68080 public function sortByType()
68081 {
68082 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
68083
68084 return $this;
68085 }
68086
68087
68088
68089
68090
68091
68092
68093
68094
68095
68096
68097
68098 public function sortByAccessedTime()
68099 {
68100 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
68101
68102 return $this;
68103 }
68104
68105
68106
68107
68108
68109
68110
68111
68112
68113
68114
68115
68116
68117
68118 public function sortByChangedTime()
68119 {
68120 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
68121
68122 return $this;
68123 }
68124
68125
68126
68127
68128
68129
68130
68131
68132
68133
68134
68135
68136 public function sortByModifiedTime()
68137 {
68138 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
68139
68140 return $this;
68141 }
68142
68143
68144
68145
68146
68147
68148
68149
68150
68151
68152
68153 public function filter(\Closure $closure)
68154 {
68155 $this->filters[] = $closure;
68156
68157 return $this;
68158 }
68159
68160
68161
68162
68163
68164
68165 public function followLinks()
68166 {
68167 $this->followLinks = true;
68168
68169 return $this;
68170 }
68171
68172
68173
68174
68175
68176
68177
68178
68179
68180
68181 public function ignoreUnreadableDirs($ignore = true)
68182 {
68183 $this->ignoreUnreadableDirs = (bool) $ignore;
68184
68185 return $this;
68186 }
68187
68188
68189
68190
68191
68192
68193
68194
68195
68196
68197 public function in($dirs)
68198 {
68199 $resolvedDirs = array();
68200
68201 foreach ((array) $dirs as $dir) {
68202 if (is_dir($dir)) {
68203 $resolvedDirs[] = $this->normalizeDir($dir);
68204 } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
68205 $resolvedDirs = array_merge($resolvedDirs, array_map(array($this, 'normalizeDir'), $glob));
68206 } else {
68207 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
68208 }
68209 }
68210
68211 $this->dirs = array_merge($this->dirs, $resolvedDirs);
68212
68213 return $this;
68214 }
68215
68216
68217
68218
68219
68220
68221
68222
68223
68224
68225 public function getIterator()
68226 {
68227 if (0 === count($this->dirs) && 0 === count($this->iterators)) {
68228 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
68229 }
68230
68231 if (1 === count($this->dirs) && 0 === count($this->iterators)) {
68232 return $this->searchInDirectory($this->dirs[0]);
68233 }
68234
68235 $iterator = new \AppendIterator();
68236 foreach ($this->dirs as $dir) {
68237 $iterator->append($this->searchInDirectory($dir));
68238 }
68239
68240 foreach ($this->iterators as $it) {
68241 $iterator->append($it);
68242 }
68243
68244 return $iterator;
68245 }
68246
68247
68248
68249
68250
68251
68252
68253
68254
68255
68256
68257
68258 public function append($iterator)
68259 {
68260 if ($iterator instanceof \IteratorAggregate) {
68261 $this->iterators[] = $iterator->getIterator();
68262 } elseif ($iterator instanceof \Iterator) {
68263 $this->iterators[] = $iterator;
68264 } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
68265 $it = new \ArrayIterator();
68266 foreach ($iterator as $file) {
68267 $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
68268 }
68269 $this->iterators[] = $it;
68270 } else {
68271 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
68272 }
68273
68274 return $this;
68275 }
68276
68277
68278
68279
68280
68281
68282 public function count()
68283 {
68284 return iterator_count($this->getIterator());
68285 }
68286
68287
68288
68289
68290 private function sortAdapters()
68291 {
68292 uasort($this->adapters, function (array $a, array $b) {
68293 if ($a['selected'] || $b['selected']) {
68294 return $a['selected'] ? -1 : 1;
68295 }
68296
68297 return $a['priority'] > $b['priority'] ? -1 : 1;
68298 });
68299
68300 return $this;
68301 }
68302
68303
68304
68305
68306
68307
68308 private function searchInDirectory($dir)
68309 {
68310 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
68311 $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
68312 }
68313
68314 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
68315 $this->notPaths[] = '#(^|/)\..+(/|$)#';
68316 }
68317
68318 if ($this->adapters) {
68319 foreach ($this->adapters as $adapter) {
68320 if ($adapter['adapter']->isSupported()) {
68321 try {
68322 return $this
68323 ->buildAdapter($adapter['adapter'])
68324 ->searchInDirectory($dir);
68325 } catch (ExceptionInterface $e) {
68326 }
68327 }
68328 }
68329 }
68330
68331 $minDepth = 0;
68332 $maxDepth = PHP_INT_MAX;
68333
68334 foreach ($this->depths as $comparator) {
68335 switch ($comparator->getOperator()) {
68336 case '>':
68337 $minDepth = $comparator->getTarget() + 1;
68338 break;
68339 case '>=':
68340 $minDepth = $comparator->getTarget();
68341 break;
68342 case '<':
68343 $maxDepth = $comparator->getTarget() - 1;
68344 break;
68345 case '<=':
68346 $maxDepth = $comparator->getTarget();
68347 break;
68348 default:
68349 $minDepth = $maxDepth = $comparator->getTarget();
68350 }
68351 }
68352
68353 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
68354
68355 if ($this->followLinks) {
68356 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
68357 }
68358
68359 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
68360
68361 if ($this->exclude) {
68362 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
68363 }
68364
68365 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
68366
68367 if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
68368 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
68369 }
68370
68371 if ($this->mode) {
68372 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
68373 }
68374
68375 if ($this->names || $this->notNames) {
68376 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
68377 }
68378
68379 if ($this->contains || $this->notContains) {
68380 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
68381 }
68382
68383 if ($this->sizes) {
68384 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
68385 }
68386
68387 if ($this->dates) {
68388 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
68389 }
68390
68391 if ($this->filters) {
68392 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
68393 }
68394
68395 if ($this->paths || $this->notPaths) {
68396 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
68397 }
68398
68399 if ($this->sort) {
68400 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
68401 $iterator = $iteratorAggregate->getIterator();
68402 }
68403
68404 return $iterator;
68405 }
68406
68407
68408
68409
68410 private function buildAdapter(AdapterInterface $adapter)
68411 {
68412 return $adapter
68413 ->setFollowLinks($this->followLinks)
68414 ->setDepths($this->depths)
68415 ->setMode($this->mode)
68416 ->setExclude($this->exclude)
68417 ->setNames($this->names)
68418 ->setNotNames($this->notNames)
68419 ->setContains($this->contains)
68420 ->setNotContains($this->notContains)
68421 ->setSizes($this->sizes)
68422 ->setDates($this->dates)
68423 ->setFilters($this->filters)
68424 ->setSort($this->sort)
68425 ->setPath($this->paths)
68426 ->setNotPath($this->notPaths)
68427 ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
68428 }
68429
68430
68431
68432
68433 private function resetAdapterSelection()
68434 {
68435 $this->adapters = array_map(function (array $properties) {
68436 $properties['selected'] = false;
68437
68438 return $properties;
68439 }, $this->adapters);
68440 }
68441
68442 private function initDefaultAdapters()
68443 {
68444 if (null === $this->adapters) {
68445 $this->adapters = array();
68446 $this
68447 ->addAdapter(new GnuFindAdapter())
68448 ->addAdapter(new BsdFindAdapter())
68449 ->addAdapter(new PhpAdapter(), -50)
68450 ->setAdapter('php')
68451 ;
68452 }
68453 }
68454
68455
68456
68457
68458
68459
68460
68461
68462 private function normalizeDir($dir)
68463 {
68464 return rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
68465 }
68466 }
68467 <?php
68468
68469
68470
68471
68472
68473
68474
68475
68476
68477
68478 namespace Symfony\Component\Finder;
68479
68480
68481
68482
68483
68484
68485
68486
68487
68488
68489
68490
68491
68492
68493
68494
68495
68496
68497
68498
68499
68500
68501
68502 class Glob
68503 {
68504
68505
68506
68507
68508
68509
68510
68511
68512
68513
68514 public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
68515 {
68516 $firstByte = true;
68517 $escaping = false;
68518 $inCurlies = 0;
68519 $regex = '';
68520 $sizeGlob = strlen($glob);
68521 for ($i = 0; $i < $sizeGlob; ++$i) {
68522 $car = $glob[$i];
68523 if ($firstByte) {
68524 if ($strictLeadingDot && '.' !== $car) {
68525 $regex .= '(?=[^\.])';
68526 }
68527
68528 $firstByte = false;
68529 }
68530
68531 if ('/' === $car) {
68532 $firstByte = true;
68533 }
68534
68535 if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
68536 $regex .= "\\$car";
68537 } elseif ('*' === $car) {
68538 $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
68539 } elseif ('?' === $car) {
68540 $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
68541 } elseif ('{' === $car) {
68542 $regex .= $escaping ? '\\{' : '(';
68543 if (!$escaping) {
68544 ++$inCurlies;
68545 }
68546 } elseif ('}' === $car && $inCurlies) {
68547 $regex .= $escaping ? '}' : ')';
68548 if (!$escaping) {
68549 --$inCurlies;
68550 }
68551 } elseif (',' === $car && $inCurlies) {
68552 $regex .= $escaping ? ',' : '|';
68553 } elseif ('\\' === $car) {
68554 if ($escaping) {
68555 $regex .= '\\\\';
68556 $escaping = false;
68557 } else {
68558 $escaping = true;
68559 }
68560
68561 continue;
68562 } else {
68563 $regex .= $car;
68564 }
68565 $escaping = false;
68566 }
68567
68568 return $delimiter.'^'.$regex.'$'.$delimiter;
68569 }
68570 }
68571 <?php
68572
68573
68574
68575
68576
68577
68578
68579
68580
68581
68582 namespace Symfony\Component\Finder\Iterator;
68583
68584
68585
68586
68587
68588
68589
68590
68591
68592 class CustomFilterIterator extends FilterIterator
68593 {
68594 private $filters = array();
68595
68596
68597
68598
68599
68600
68601
68602 public function __construct(\Iterator $iterator, array $filters)
68603 {
68604 foreach ($filters as $filter) {
68605 if (!is_callable($filter)) {
68606 throw new \InvalidArgumentException('Invalid PHP callback.');
68607 }
68608 }
68609 $this->filters = $filters;
68610
68611 parent::__construct($iterator);
68612 }
68613
68614
68615
68616
68617
68618
68619 public function accept()
68620 {
68621 $fileinfo = $this->current();
68622
68623 foreach ($this->filters as $filter) {
68624 if (false === call_user_func($filter, $fileinfo)) {
68625 return false;
68626 }
68627 }
68628
68629 return true;
68630 }
68631 }
68632 <?php
68633
68634
68635
68636
68637
68638
68639
68640
68641
68642
68643 namespace Symfony\Component\Finder\Iterator;
68644
68645 use Symfony\Component\Finder\Comparator\DateComparator;
68646
68647
68648
68649
68650
68651
68652 class DateRangeFilterIterator extends FilterIterator
68653 {
68654 private $comparators = array();
68655
68656
68657
68658
68659
68660 public function __construct(\Iterator $iterator, array $comparators)
68661 {
68662 $this->comparators = $comparators;
68663
68664 parent::__construct($iterator);
68665 }
68666
68667
68668
68669
68670
68671
68672 public function accept()
68673 {
68674 $fileinfo = $this->current();
68675
68676 if (!file_exists($fileinfo->getPathname())) {
68677 return false;
68678 }
68679
68680 $filedate = $fileinfo->getMTime();
68681 foreach ($this->comparators as $compare) {
68682 if (!$compare->test($filedate)) {
68683 return false;
68684 }
68685 }
68686
68687 return true;
68688 }
68689 }
68690 <?php
68691
68692
68693
68694
68695
68696
68697
68698
68699
68700
68701 namespace Symfony\Component\Finder\Iterator;
68702
68703
68704
68705
68706
68707
68708 class DepthRangeFilterIterator extends FilterIterator
68709 {
68710 private $minDepth = 0;
68711
68712
68713
68714
68715
68716
68717 public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
68718 {
68719 $this->minDepth = $minDepth;
68720 $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
68721
68722 parent::__construct($iterator);
68723 }
68724
68725
68726
68727
68728
68729
68730 public function accept()
68731 {
68732 return $this->getInnerIterator()->getDepth() >= $this->minDepth;
68733 }
68734 }
68735 <?php
68736
68737
68738
68739
68740
68741
68742
68743
68744
68745
68746 namespace Symfony\Component\Finder\Iterator;
68747
68748
68749
68750
68751
68752
68753 class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
68754 {
68755 private $iterator;
68756 private $isRecursive;
68757 private $excludedDirs = array();
68758 private $excludedPattern;
68759
68760
68761
68762
68763
68764 public function __construct(\Iterator $iterator, array $directories)
68765 {
68766 $this->iterator = $iterator;
68767 $this->isRecursive = $iterator instanceof \RecursiveIterator;
68768 $patterns = array();
68769 foreach ($directories as $directory) {
68770 $directory = rtrim($directory, '/');
68771 if (!$this->isRecursive || false !== strpos($directory, '/')) {
68772 $patterns[] = preg_quote($directory, '#');
68773 } else {
68774 $this->excludedDirs[$directory] = true;
68775 }
68776 }
68777 if ($patterns) {
68778 $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
68779 }
68780
68781 parent::__construct($iterator);
68782 }
68783
68784
68785
68786
68787
68788
68789 public function accept()
68790 {
68791 if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
68792 return false;
68793 }
68794
68795 if ($this->excludedPattern) {
68796 $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
68797 $path = str_replace('\\', '/', $path);
68798
68799 return !preg_match($this->excludedPattern, $path);
68800 }
68801
68802 return true;
68803 }
68804
68805 public function hasChildren()
68806 {
68807 return $this->isRecursive && $this->iterator->hasChildren();
68808 }
68809
68810 public function getChildren()
68811 {
68812 $children = new self($this->iterator->getChildren(), array());
68813 $children->excludedDirs = $this->excludedDirs;
68814 $children->excludedPattern = $this->excludedPattern;
68815
68816 return $children;
68817 }
68818 }
68819 <?php
68820
68821
68822
68823
68824
68825
68826
68827
68828
68829
68830 namespace Symfony\Component\Finder\Iterator;
68831
68832 @trigger_error('The '.__NAMESPACE__.'\FilePathsIterator class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68833
68834 use Symfony\Component\Finder\SplFileInfo;
68835
68836
68837
68838
68839
68840
68841
68842
68843 class FilePathsIterator extends \ArrayIterator
68844 {
68845
68846
68847
68848 private $baseDir;
68849
68850
68851
68852
68853 private $baseDirLength;
68854
68855
68856
68857
68858 private $subPath;
68859
68860
68861
68862
68863 private $subPathname;
68864
68865
68866
68867
68868 private $current;
68869
68870
68871
68872
68873
68874 public function __construct(array $paths, $baseDir)
68875 {
68876 $this->baseDir = $baseDir;
68877 $this->baseDirLength = strlen($baseDir);
68878
68879 parent::__construct($paths);
68880 }
68881
68882
68883
68884
68885
68886
68887
68888 public function __call($name, array $arguments)
68889 {
68890 return call_user_func_array(array($this->current(), $name), $arguments);
68891 }
68892
68893
68894
68895
68896
68897
68898 public function current()
68899 {
68900 return $this->current;
68901 }
68902
68903
68904
68905
68906 public function key()
68907 {
68908 return $this->current->getPathname();
68909 }
68910
68911 public function next()
68912 {
68913 parent::next();
68914 $this->buildProperties();
68915 }
68916
68917 public function rewind()
68918 {
68919 parent::rewind();
68920 $this->buildProperties();
68921 }
68922
68923
68924
68925
68926 public function getSubPath()
68927 {
68928 return $this->subPath;
68929 }
68930
68931
68932
68933
68934 public function getSubPathname()
68935 {
68936 return $this->subPathname;
68937 }
68938
68939 private function buildProperties()
68940 {
68941 $absolutePath = parent::current();
68942
68943 if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
68944 $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
68945 $dir = dirname($this->subPathname);
68946 $this->subPath = '.' === $dir ? '' : $dir;
68947 } else {
68948 $this->subPath = $this->subPathname = '';
68949 }
68950
68951 $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
68952 }
68953 }
68954 <?php
68955
68956
68957
68958
68959
68960
68961
68962
68963
68964
68965 namespace Symfony\Component\Finder\Iterator;
68966
68967
68968
68969
68970
68971
68972 class FileTypeFilterIterator extends FilterIterator
68973 {
68974 const ONLY_FILES = 1;
68975 const ONLY_DIRECTORIES = 2;
68976
68977 private $mode;
68978
68979
68980
68981
68982
68983 public function __construct(\Iterator $iterator, $mode)
68984 {
68985 $this->mode = $mode;
68986
68987 parent::__construct($iterator);
68988 }
68989
68990
68991
68992
68993
68994
68995 public function accept()
68996 {
68997 $fileinfo = $this->current();
68998 if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
68999 return false;
69000 } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
69001 return false;
69002 }
69003
69004 return true;
69005 }
69006 }
69007 <?php
69008
69009
69010
69011
69012
69013
69014
69015
69016
69017
69018 namespace Symfony\Component\Finder\Iterator;
69019
69020
69021
69022
69023
69024
69025
69026 class FilecontentFilterIterator extends MultiplePcreFilterIterator
69027 {
69028
69029
69030
69031
69032
69033 public function accept()
69034 {
69035 if (!$this->matchRegexps && !$this->noMatchRegexps) {
69036 return true;
69037 }
69038
69039 $fileinfo = $this->current();
69040
69041 if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
69042 return false;
69043 }
69044
69045 $content = $fileinfo->getContents();
69046 if (!$content) {
69047 return false;
69048 }
69049
69050 return $this->isAccepted($content);
69051 }
69052
69053
69054
69055
69056
69057
69058
69059
69060 protected function toRegex($str)
69061 {
69062 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
69063 }
69064 }
69065 <?php
69066
69067
69068
69069
69070
69071
69072
69073
69074
69075
69076 namespace Symfony\Component\Finder\Iterator;
69077
69078 use Symfony\Component\Finder\Glob;
69079
69080
69081
69082
69083
69084
69085 class FilenameFilterIterator extends MultiplePcreFilterIterator
69086 {
69087
69088
69089
69090
69091
69092 public function accept()
69093 {
69094 return $this->isAccepted($this->current()->getFilename());
69095 }
69096
69097
69098
69099
69100
69101
69102
69103
69104
69105
69106
69107 protected function toRegex($str)
69108 {
69109 return $this->isRegex($str) ? $str : Glob::toRegex($str);
69110 }
69111 }
69112 <?php
69113
69114
69115
69116
69117
69118
69119
69120
69121
69122
69123 namespace Symfony\Component\Finder\Iterator;
69124
69125
69126
69127
69128
69129
69130
69131
69132
69133 abstract class FilterIterator extends \FilterIterator
69134 {
69135
69136
69137
69138
69139
69140
69141 public function rewind()
69142 {
69143 if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
69144 parent::rewind();
69145
69146 return;
69147 }
69148
69149 $iterator = $this;
69150 while ($iterator instanceof \OuterIterator) {
69151 $innerIterator = $iterator->getInnerIterator();
69152
69153 if ($innerIterator instanceof RecursiveDirectoryIterator) {
69154
69155  if ($innerIterator->isRewindable()) {
69156 $innerIterator->next();
69157 $innerIterator->rewind();
69158 }
69159 } elseif ($innerIterator instanceof \FilesystemIterator) {
69160 $innerIterator->next();
69161 $innerIterator->rewind();
69162 }
69163
69164 $iterator = $innerIterator;
69165 }
69166
69167 parent::rewind();
69168 }
69169 }
69170 <?php
69171
69172
69173
69174
69175
69176
69177
69178
69179
69180
69181 namespace Symfony\Component\Finder\Iterator;
69182
69183
69184
69185
69186
69187
69188 abstract class MultiplePcreFilterIterator extends FilterIterator
69189 {
69190 protected $matchRegexps = array();
69191 protected $noMatchRegexps = array();
69192
69193
69194
69195
69196
69197
69198 public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
69199 {
69200 foreach ($matchPatterns as $pattern) {
69201 $this->matchRegexps[] = $this->toRegex($pattern);
69202 }
69203
69204 foreach ($noMatchPatterns as $pattern) {
69205 $this->noMatchRegexps[] = $this->toRegex($pattern);
69206 }
69207
69208 parent::__construct($iterator);
69209 }
69210
69211
69212
69213
69214
69215
69216
69217
69218
69219
69220
69221
69222 protected function isAccepted($string)
69223 {
69224
69225  foreach ($this->noMatchRegexps as $regex) {
69226 if (preg_match($regex, $string)) {
69227 return false;
69228 }
69229 }
69230
69231
69232  if ($this->matchRegexps) {
69233 foreach ($this->matchRegexps as $regex) {
69234 if (preg_match($regex, $string)) {
69235 return true;
69236 }
69237 }
69238
69239 return false;
69240 }
69241
69242
69243  return true;
69244 }
69245
69246
69247
69248
69249
69250
69251
69252
69253 protected function isRegex($str)
69254 {
69255 if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
69256 $start = substr($m[1], 0, 1);
69257 $end = substr($m[1], -1);
69258
69259 if ($start === $end) {
69260 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
69261 }
69262
69263 foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
69264 if ($start === $delimiters[0] && $end === $delimiters[1]) {
69265 return true;
69266 }
69267 }
69268 }
69269
69270 return false;
69271 }
69272
69273
69274
69275
69276
69277
69278
69279
69280 abstract protected function toRegex($str);
69281 }
69282 <?php
69283
69284
69285
69286
69287
69288
69289
69290
69291
69292
69293 namespace Symfony\Component\Finder\Iterator;
69294
69295
69296
69297
69298
69299
69300
69301 class PathFilterIterator extends MultiplePcreFilterIterator
69302 {
69303
69304
69305
69306
69307
69308 public function accept()
69309 {
69310 $filename = $this->current()->getRelativePathname();
69311
69312 if ('\\' === DIRECTORY_SEPARATOR) {
69313 $filename = str_replace('\\', '/', $filename);
69314 }
69315
69316 return $this->isAccepted($filename);
69317 }
69318
69319
69320
69321
69322
69323
69324
69325
69326
69327
69328
69329
69330
69331
69332
69333 protected function toRegex($str)
69334 {
69335 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
69336 }
69337 }
69338 <?php
69339
69340
69341
69342
69343
69344
69345
69346
69347
69348
69349 namespace Symfony\Component\Finder\Iterator;
69350
69351 use Symfony\Component\Finder\Exception\AccessDeniedException;
69352 use Symfony\Component\Finder\SplFileInfo;
69353
69354
69355
69356
69357
69358
69359 class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
69360 {
69361
69362
69363
69364 private $ignoreUnreadableDirs;
69365
69366
69367
69368
69369 private $rewindable;
69370
69371
69372  private $rootPath;
69373 private $subPath;
69374 private $directorySeparator = '/';
69375
69376
69377
69378
69379
69380
69381
69382
69383 public function __construct($path, $flags, $ignoreUnreadableDirs = false)
69384 {
69385 if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
69386 throw new \RuntimeException('This iterator only support returning current as fileinfo.');
69387 }
69388
69389 parent::__construct($path, $flags);
69390 $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
69391 $this->rootPath = (string) $path;
69392 if ('/' !== DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
69393 $this->directorySeparator = DIRECTORY_SEPARATOR;
69394 }
69395 }
69396
69397
69398
69399
69400
69401
69402 public function current()
69403 {
69404
69405
69406 if (null === $subPathname = $this->subPath) {
69407 $subPathname = $this->subPath = (string) $this->getSubPath();
69408 }
69409 if ('' !== $subPathname) {
69410 $subPathname .= $this->directorySeparator;
69411 }
69412 $subPathname .= $this->getFilename();
69413
69414 return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
69415 }
69416
69417
69418
69419
69420
69421
69422 public function getChildren()
69423 {
69424 try {
69425 $children = parent::getChildren();
69426
69427 if ($children instanceof self) {
69428
69429  $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
69430
69431
69432  $children->rewindable = &$this->rewindable;
69433 $children->rootPath = $this->rootPath;
69434 }
69435
69436 return $children;
69437 } catch (\UnexpectedValueException $e) {
69438 if ($this->ignoreUnreadableDirs) {
69439
69440  return new \RecursiveArrayIterator(array());
69441 } else {
69442 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
69443 }
69444 }
69445 }
69446
69447
69448
69449
69450 public function rewind()
69451 {
69452 if (false === $this->isRewindable()) {
69453 return;
69454 }
69455
69456
69457  if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
69458 parent::next();
69459 }
69460
69461 parent::rewind();
69462 }
69463
69464
69465
69466
69467
69468
69469 public function isRewindable()
69470 {
69471 if (null !== $this->rewindable) {
69472 return $this->rewindable;
69473 }
69474
69475
69476  if ('' === $this->getPath()) {
69477 return $this->rewindable = false;
69478 }
69479
69480 if (false !== $stream = @opendir($this->getPath())) {
69481 $infos = stream_get_meta_data($stream);
69482 closedir($stream);
69483
69484 if ($infos['seekable']) {
69485 return $this->rewindable = true;
69486 }
69487 }
69488
69489 return $this->rewindable = false;
69490 }
69491 }
69492 <?php
69493
69494
69495
69496
69497
69498
69499
69500
69501
69502
69503 namespace Symfony\Component\Finder\Iterator;
69504
69505 use Symfony\Component\Finder\Comparator\NumberComparator;
69506
69507
69508
69509
69510
69511
69512 class SizeRangeFilterIterator extends FilterIterator
69513 {
69514 private $comparators = array();
69515
69516
69517
69518
69519
69520 public function __construct(\Iterator $iterator, array $comparators)
69521 {
69522 $this->comparators = $comparators;
69523
69524 parent::__construct($iterator);
69525 }
69526
69527
69528
69529
69530
69531
69532 public function accept()
69533 {
69534 $fileinfo = $this->current();
69535 if (!$fileinfo->isFile()) {
69536 return true;
69537 }
69538
69539 $filesize = $fileinfo->getSize();
69540 foreach ($this->comparators as $compare) {
69541 if (!$compare->test($filesize)) {
69542 return false;
69543 }
69544 }
69545
69546 return true;
69547 }
69548 }
69549 <?php
69550
69551
69552
69553
69554
69555
69556
69557
69558
69559
69560 namespace Symfony\Component\Finder\Iterator;
69561
69562
69563
69564
69565
69566
69567 class SortableIterator implements \IteratorAggregate
69568 {
69569 const SORT_BY_NAME = 1;
69570 const SORT_BY_TYPE = 2;
69571 const SORT_BY_ACCESSED_TIME = 3;
69572 const SORT_BY_CHANGED_TIME = 4;
69573 const SORT_BY_MODIFIED_TIME = 5;
69574
69575 private $iterator;
69576 private $sort;
69577
69578
69579
69580
69581
69582
69583
69584 public function __construct(\Traversable $iterator, $sort)
69585 {
69586 $this->iterator = $iterator;
69587
69588 if (self::SORT_BY_NAME === $sort) {
69589 $this->sort = function ($a, $b) {
69590 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
69591 };
69592 } elseif (self::SORT_BY_TYPE === $sort) {
69593 $this->sort = function ($a, $b) {
69594 if ($a->isDir() && $b->isFile()) {
69595 return -1;
69596 } elseif ($a->isFile() && $b->isDir()) {
69597 return 1;
69598 }
69599
69600 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
69601 };
69602 } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
69603 $this->sort = function ($a, $b) {
69604 return $a->getATime() - $b->getATime();
69605 };
69606 } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
69607 $this->sort = function ($a, $b) {
69608 return $a->getCTime() - $b->getCTime();
69609 };
69610 } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
69611 $this->sort = function ($a, $b) {
69612 return $a->getMTime() - $b->getMTime();
69613 };
69614 } elseif (is_callable($sort)) {
69615 $this->sort = $sort;
69616 } else {
69617 throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
69618 }
69619 }
69620
69621 public function getIterator()
69622 {
69623 $array = iterator_to_array($this->iterator, true);
69624 uasort($array, $this->sort);
69625
69626 return new \ArrayIterator($array);
69627 }
69628 }
69629 Copyright (c) 2004-2018 Fabien Potencier
69630
69631 Permission is hereby granted, free of charge, to any person obtaining a copy
69632 of this software and associated documentation files (the "Software"), to deal
69633 in the Software without restriction, including without limitation the rights
69634 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
69635 copies of the Software, and to permit persons to whom the Software is furnished
69636 to do so, subject to the following conditions:
69637
69638 The above copyright notice and this permission notice shall be included in all
69639 copies or substantial portions of the Software.
69640
69641 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
69642 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69643 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
69644 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
69645 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
69646 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
69647 THE SOFTWARE.
69648 <?php
69649
69650
69651
69652
69653
69654
69655
69656
69657
69658
69659 namespace Symfony\Component\Finder\Shell;
69660
69661 @trigger_error('The '.__NAMESPACE__.'\Command class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69662
69663
69664
69665
69666
69667
69668 class Command
69669 {
69670 private $parent;
69671 private $bits = array();
69672 private $labels = array();
69673
69674
69675
69676
69677 private $errorHandler;
69678
69679 public function __construct(Command $parent = null)
69680 {
69681 $this->parent = $parent;
69682 }
69683
69684
69685
69686
69687
69688
69689 public function __toString()
69690 {
69691 return $this->join();
69692 }
69693
69694
69695
69696
69697
69698
69699 public static function create(Command $parent = null)
69700 {
69701 return new self($parent);
69702 }
69703
69704
69705
69706
69707
69708
69709
69710
69711 public static function escape($input)
69712 {
69713 return escapeshellcmd($input);
69714 }
69715
69716
69717
69718
69719
69720
69721
69722
69723 public static function quote($input)
69724 {
69725 return escapeshellarg($input);
69726 }
69727
69728
69729
69730
69731
69732
69733
69734
69735 public function add($bit)
69736 {
69737 $this->bits[] = $bit;
69738
69739 return $this;
69740 }
69741
69742
69743
69744
69745
69746
69747
69748
69749 public function top($bit)
69750 {
69751 array_unshift($this->bits, $bit);
69752
69753 foreach ($this->labels as $label => $index) {
69754 ++$this->labels[$label];
69755 }
69756
69757 return $this;
69758 }
69759
69760
69761
69762
69763
69764
69765
69766
69767 public function arg($arg)
69768 {
69769 $this->bits[] = self::quote($arg);
69770
69771 return $this;
69772 }
69773
69774
69775
69776
69777
69778
69779
69780
69781 public function cmd($esc)
69782 {
69783 $this->bits[] = self::escape($esc);
69784
69785 return $this;
69786 }
69787
69788
69789
69790
69791
69792
69793
69794
69795
69796
69797 public function ins($label)
69798 {
69799 if (isset($this->labels[$label])) {
69800 throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
69801 }
69802
69803 $this->bits[] = self::create($this);
69804 $this->labels[$label] = count($this->bits) - 1;
69805
69806 return $this->bits[$this->labels[$label]];
69807 }
69808
69809
69810
69811
69812
69813
69814
69815
69816
69817
69818 public function get($label)
69819 {
69820 if (!isset($this->labels[$label])) {
69821 throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
69822 }
69823
69824 return $this->bits[$this->labels[$label]];
69825 }
69826
69827
69828
69829
69830
69831
69832
69833
69834 public function end()
69835 {
69836 if (null === $this->parent) {
69837 throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
69838 }
69839
69840 return $this->parent;
69841 }
69842
69843
69844
69845
69846
69847
69848 public function length()
69849 {
69850 return count($this->bits);
69851 }
69852
69853
69854
69855
69856 public function setErrorHandler(\Closure $errorHandler)
69857 {
69858 $this->errorHandler = $errorHandler;
69859
69860 return $this;
69861 }
69862
69863
69864
69865
69866 public function getErrorHandler()
69867 {
69868 return $this->errorHandler;
69869 }
69870
69871
69872
69873
69874
69875
69876
69877
69878 public function execute()
69879 {
69880 if (null === $errorHandler = $this->errorHandler) {
69881 exec($this->join(), $output);
69882 } else {
69883 $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
69884 $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
69885
69886 if ($error = stream_get_contents($pipes[2])) {
69887 $errorHandler($error);
69888 }
69889
69890 proc_close($process);
69891 }
69892
69893 return $output ?: array();
69894 }
69895
69896
69897
69898
69899
69900
69901 public function join()
69902 {
69903 return implode(' ', array_filter(
69904 array_map(function ($bit) {
69905 return $bit instanceof Command ? $bit->join() : ($bit ?: null);
69906 }, $this->bits),
69907 function ($bit) { return null !== $bit; }
69908 ));
69909 }
69910
69911
69912
69913
69914
69915
69916
69917
69918
69919 public function addAtIndex($bit, $index)
69920 {
69921 array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit);
69922
69923 return $this;
69924 }
69925 }
69926 <?php
69927
69928
69929
69930
69931
69932
69933
69934
69935
69936
69937 namespace Symfony\Component\Finder\Shell;
69938
69939 @trigger_error('The '.__NAMESPACE__.'\Shell class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69940
69941
69942
69943
69944
69945
69946 class Shell
69947 {
69948 const TYPE_UNIX = 1;
69949 const TYPE_DARWIN = 2;
69950 const TYPE_CYGWIN = 3;
69951 const TYPE_WINDOWS = 4;
69952 const TYPE_BSD = 5;
69953
69954
69955
69956
69957 private $type;
69958
69959
69960
69961
69962
69963
69964 public function getType()
69965 {
69966 if (null === $this->type) {
69967 $this->type = $this->guessType();
69968 }
69969
69970 return $this->type;
69971 }
69972
69973
69974
69975
69976
69977
69978
69979
69980 public function testCommand($command)
69981 {
69982 if (!function_exists('exec')) {
69983 return false;
69984 }
69985
69986
69987  $testCommand = 'which ';
69988 if (self::TYPE_WINDOWS === $this->type) {
69989 $testCommand = 'where ';
69990 }
69991
69992 $command = escapeshellcmd($command);
69993
69994 exec($testCommand.$command, $output, $code);
69995
69996 return 0 === $code && count($output) > 0;
69997 }
69998
69999
70000
70001
70002
70003
70004 private function guessType()
70005 {
70006 $os = strtolower(PHP_OS);
70007
70008 if (false !== strpos($os, 'cygwin')) {
70009 return self::TYPE_CYGWIN;
70010 }
70011
70012 if (false !== strpos($os, 'darwin')) {
70013 return self::TYPE_DARWIN;
70014 }
70015
70016 if (false !== strpos($os, 'bsd')) {
70017 return self::TYPE_BSD;
70018 }
70019
70020 if (0 === strpos($os, 'win')) {
70021 return self::TYPE_WINDOWS;
70022 }
70023
70024 return self::TYPE_UNIX;
70025 }
70026 }
70027 <?php
70028
70029
70030
70031
70032
70033
70034
70035
70036
70037
70038 namespace Symfony\Component\Finder;
70039
70040
70041
70042
70043
70044
70045 class SplFileInfo extends \SplFileInfo
70046 {
70047 private $relativePath;
70048 private $relativePathname;
70049
70050
70051
70052
70053
70054
70055 public function __construct($file, $relativePath, $relativePathname)
70056 {
70057 parent::__construct($file);
70058 $this->relativePath = $relativePath;
70059 $this->relativePathname = $relativePathname;
70060 }
70061
70062
70063
70064
70065
70066
70067
70068
70069 public function getRelativePath()
70070 {
70071 return $this->relativePath;
70072 }
70073
70074
70075
70076
70077
70078
70079
70080
70081 public function getRelativePathname()
70082 {
70083 return $this->relativePathname;
70084 }
70085
70086
70087
70088
70089
70090
70091
70092
70093 public function getContents()
70094 {
70095 set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
70096 $content = file_get_contents($this->getPathname());
70097 restore_error_handler();
70098 if (false === $content) {
70099 throw new \RuntimeException($error);
70100 }
70101
70102 return $content;
70103 }
70104 }
70105 <?php
70106
70107
70108
70109
70110
70111
70112
70113
70114
70115
70116 namespace Symfony\Polyfill\Ctype;
70117
70118
70119
70120
70121
70122
70123
70124
70125 final class Ctype
70126 {
70127
70128
70129
70130
70131
70132
70133
70134
70135
70136 public static function ctype_alnum($text)
70137 {
70138 $text = self::convert_int_to_char_for_ctype($text);
70139
70140 return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
70141 }
70142
70143
70144
70145
70146
70147
70148
70149
70150
70151
70152 public static function ctype_alpha($text)
70153 {
70154 $text = self::convert_int_to_char_for_ctype($text);
70155
70156 return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
70157 }
70158
70159
70160
70161
70162
70163
70164
70165
70166
70167
70168 public static function ctype_cntrl($text)
70169 {
70170 $text = self::convert_int_to_char_for_ctype($text);
70171
70172 return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
70173 }
70174
70175
70176
70177
70178
70179
70180
70181
70182
70183
70184 public static function ctype_digit($text)
70185 {
70186 $text = self::convert_int_to_char_for_ctype($text);
70187
70188 return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
70189 }
70190
70191
70192
70193
70194
70195
70196
70197
70198
70199
70200 public static function ctype_graph($text)
70201 {
70202 $text = self::convert_int_to_char_for_ctype($text);
70203
70204 return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
70205 }
70206
70207
70208
70209
70210
70211
70212
70213
70214
70215
70216 public static function ctype_lower($text)
70217 {
70218 $text = self::convert_int_to_char_for_ctype($text);
70219
70220 return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
70221 }
70222
70223
70224
70225
70226
70227
70228
70229
70230
70231
70232 public static function ctype_print($text)
70233 {
70234 $text = self::convert_int_to_char_for_ctype($text);
70235
70236 return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
70237 }
70238
70239
70240
70241
70242
70243
70244
70245
70246
70247
70248 public static function ctype_punct($text)
70249 {
70250 $text = self::convert_int_to_char_for_ctype($text);
70251
70252 return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
70253 }
70254
70255
70256
70257
70258
70259
70260
70261
70262
70263
70264 public static function ctype_space($text)
70265 {
70266 $text = self::convert_int_to_char_for_ctype($text);
70267
70268 return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
70269 }
70270
70271
70272
70273
70274
70275
70276
70277
70278
70279
70280 public static function ctype_upper($text)
70281 {
70282 $text = self::convert_int_to_char_for_ctype($text);
70283
70284 return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
70285 }
70286
70287
70288
70289
70290
70291
70292
70293
70294
70295
70296 public static function ctype_xdigit($text)
70297 {
70298 $text = self::convert_int_to_char_for_ctype($text);
70299
70300 return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
70301 }
70302
70303
70304
70305
70306
70307
70308
70309
70310
70311
70312
70313
70314
70315 private static function convert_int_to_char_for_ctype($int)
70316 {
70317 if (!\is_int($int)) {
70318 return $int;
70319 }
70320
70321 if ($int < -128 || $int > 255) {
70322 return (string) $int;
70323 }
70324
70325 if ($int < 0) {
70326 $int += 256;
70327 }
70328
70329 return \chr($int);
70330 }
70331 }
70332 Copyright (c) 2018 Fabien Potencier
70333
70334 Permission is hereby granted, free of charge, to any person obtaining a copy
70335 of this software and associated documentation files (the "Software"), to deal
70336 in the Software without restriction, including without limitation the rights
70337 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
70338 copies of the Software, and to permit persons to whom the Software is furnished
70339 to do so, subject to the following conditions:
70340
70341 The above copyright notice and this permission notice shall be included in all
70342 copies or substantial portions of the Software.
70343
70344 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70345 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
70346 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70347 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
70348 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
70349 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
70350 THE SOFTWARE.
70351 <?php
70352
70353
70354
70355
70356
70357
70358
70359
70360
70361
70362 use Symfony\Polyfill\Ctype as p;
70363
70364 if (!function_exists('ctype_alnum')) {
70365 function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
70366 function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
70367 function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
70368 function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
70369 function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
70370 function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
70371 function ctype_print($text) { return p\Ctype::ctype_print($text); }
70372 function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
70373 function ctype_space($text) { return p\Ctype::ctype_space($text); }
70374 function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
70375 function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
70376 }
70377 Copyright (c) 2015-2018 Fabien Potencier
70378
70379 Permission is hereby granted, free of charge, to any person obtaining a copy
70380 of this software and associated documentation files (the "Software"), to deal
70381 in the Software without restriction, including without limitation the rights
70382 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
70383 copies of the Software, and to permit persons to whom the Software is furnished
70384 to do so, subject to the following conditions:
70385
70386 The above copyright notice and this permission notice shall be included in all
70387 copies or substantial portions of the Software.
70388
70389 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70390 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
70391 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
70392 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
70393 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
70394 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
70395 THE SOFTWARE.
70396 <?php
70397
70398
70399
70400
70401
70402
70403
70404
70405
70406
70407 namespace Symfony\Polyfill\Mbstring;
70408
70409
70410
70411
70412
70413
70414
70415
70416
70417
70418
70419
70420
70421
70422
70423
70424
70425
70426
70427
70428
70429
70430
70431
70432
70433
70434
70435
70436
70437
70438
70439
70440
70441
70442
70443
70444
70445
70446
70447
70448
70449
70450
70451
70452
70453
70454
70455
70456
70457
70458
70459
70460
70461
70462 final class Mbstring
70463 {
70464 const MB_CASE_FOLD = PHP_INT_MAX;
70465
70466 private static $encodingList = array('ASCII', 'UTF-8');
70467 private static $language = 'neutral';
70468 private static $internalEncoding = 'UTF-8';
70469 private static $caseFold = array(
70470 array('µ','ſ',"\xCD\x85",'ς',"\xCF\x90","\xCF\x91","\xCF\x95","\xCF\x96","\xCF\xB0","\xCF\xB1","\xCF\xB5","\xE1\xBA\x9B","\xE1\xBE\xBE"),
70471 array('μ','s','ι', 'σ','β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1",'ι'),
70472 );
70473
70474 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
70475 {
70476 if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
70477 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
70478 } else {
70479 $fromEncoding = self::getEncoding($fromEncoding);
70480 }
70481
70482 $toEncoding = self::getEncoding($toEncoding);
70483
70484 if ('BASE64' === $fromEncoding) {
70485 $s = base64_decode($s);
70486 $fromEncoding = $toEncoding;
70487 }
70488
70489 if ('BASE64' === $toEncoding) {
70490 return base64_encode($s);
70491 }
70492
70493 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
70494 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
70495 $fromEncoding = 'Windows-1252';
70496 }
70497 if ('UTF-8' !== $fromEncoding) {
70498 $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
70499 }
70500
70501 return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
70502 }
70503
70504 if ('HTML-ENTITIES' === $fromEncoding) {
70505 $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
70506 $fromEncoding = 'UTF-8';
70507 }
70508
70509 return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
70510 }
70511
70512 public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
70513 {
70514 $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
70515
70516 $ok = true;
70517 array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
70518 if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
70519 $ok = false;
70520 }
70521 });
70522
70523 return $ok ? $fromEncoding : false;
70524 }
70525
70526 public static function mb_decode_mimeheader($s)
70527 {
70528 return iconv_mime_decode($s, 2, self::$internalEncoding);
70529 }
70530
70531 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
70532 {
70533 trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
70534 }
70535
70536 public static function mb_decode_numericentity($s, $convmap, $encoding = null)
70537 {
70538 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
70539 trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.gettype($s).' given', E_USER_WARNING);
70540 return null;
70541 }
70542
70543 if (!\is_array($convmap) || !$convmap) {
70544 return false;
70545 }
70546
70547 if (null !== $encoding && !\is_scalar($encoding)) {
70548 trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.gettype($s).' given', E_USER_WARNING);
70549 return ''; 
70550  }
70551
70552 $s = (string) $s;
70553 if ('' === $s) {
70554 return '';
70555 }
70556
70557 $encoding = self::getEncoding($encoding);
70558
70559 if ('UTF-8' === $encoding) {
70560 $encoding = null;
70561 if (!preg_match('//u', $s)) {
70562 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
70563 }
70564 } else {
70565 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
70566 }
70567
70568 $cnt = floor(\count($convmap) / 4) * 4;
70569
70570 for ($i = 0; $i < $cnt; $i += 4) {
70571
70572  $convmap[$i] += $convmap[$i + 2];
70573 $convmap[$i + 1] += $convmap[$i + 2];
70574 }
70575
70576 $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
70577 $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
70578 for ($i = 0; $i < $cnt; $i += 4) {
70579 if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
70580 return Mbstring::mb_chr($c - $convmap[$i + 2]);
70581 }
70582 }
70583 return $m[0];
70584 }, $s);
70585
70586 if (null === $encoding) {
70587 return $s;
70588 }
70589
70590 return iconv('UTF-8', $encoding.'//IGNORE', $s);
70591 }
70592
70593 public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
70594 {
70595 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
70596 trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.gettype($s).' given', E_USER_WARNING);
70597 return null;
70598 }
70599
70600 if (!\is_array($convmap) || !$convmap) {
70601 return false;
70602 }
70603
70604 if (null !== $encoding && !\is_scalar($encoding)) {
70605 trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.gettype($s).' given', E_USER_WARNING);
70606 return null; 
70607  }
70608
70609 if (null !== $is_hex && !\is_scalar($is_hex)) {
70610 trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.gettype($s).' given', E_USER_WARNING);
70611 return null;
70612 }
70613
70614 $s = (string) $s;
70615 if ('' === $s) {
70616 return '';
70617 }
70618
70619 $encoding = self::getEncoding($encoding);
70620
70621 if ('UTF-8' === $encoding) {
70622 $encoding = null;
70623 if (!preg_match('//u', $s)) {
70624 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
70625 }
70626 } else {
70627 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
70628 }
70629
70630 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
70631
70632 $cnt = floor(\count($convmap) / 4) * 4;
70633 $i = 0;
70634 $len = \strlen($s);
70635 $result = '';
70636
70637 while ($i < $len) {
70638 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
70639 $uchr = substr($s, $i, $ulen);
70640 $i += $ulen;
70641 $c = self::mb_ord($uchr);
70642
70643 for ($j = 0; $j < $cnt; $j += 4) {
70644 if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
70645 $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
70646 $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
70647 continue 2;
70648 }
70649 }
70650 $result .= $uchr;
70651 }
70652
70653 if (null === $encoding) {
70654 return $result;
70655 }
70656
70657 return iconv('UTF-8', $encoding.'//IGNORE', $result);
70658 }
70659
70660 public static function mb_convert_case($s, $mode, $encoding = null)
70661 {
70662 $s = (string) $s;
70663 if ('' === $s) {
70664 return '';
70665 }
70666
70667 $encoding = self::getEncoding($encoding);
70668
70669 if ('UTF-8' === $encoding) {
70670 $encoding = null;
70671 if (!preg_match('//u', $s)) {
70672 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
70673 }
70674 } else {
70675 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
70676 }
70677
70678 if (MB_CASE_TITLE == $mode) {
70679 $s = preg_replace_callback('/\b\p{Ll}/u', array(__CLASS__, 'title_case_upper'), $s);
70680 $s = preg_replace_callback('/\B[\p{Lu}\p{Lt}]+/u', array(__CLASS__, 'title_case_lower'), $s);
70681 } else {
70682 if (MB_CASE_UPPER == $mode) {
70683 static $upper = null;
70684 if (null === $upper) {
70685 $upper = self::getData('upperCase');
70686 }
70687 $map = $upper;
70688 } else {
70689 if (self::MB_CASE_FOLD === $mode) {
70690 $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
70691 }
70692
70693 static $lower = null;
70694 if (null === $lower) {
70695 $lower = self::getData('lowerCase');
70696 }
70697 $map = $lower;
70698 }
70699
70700 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
70701
70702 $i = 0;
70703 $len = \strlen($s);
70704
70705 while ($i < $len) {
70706 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
70707 $uchr = substr($s, $i, $ulen);
70708 $i += $ulen;
70709
70710 if (isset($map[$uchr])) {
70711 $uchr = $map[$uchr];
70712 $nlen = \strlen($uchr);
70713
70714 if ($nlen == $ulen) {
70715 $nlen = $i;
70716 do {
70717 $s[--$nlen] = $uchr[--$ulen];
70718 } while ($ulen);
70719 } else {
70720 $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
70721 $len += $nlen - $ulen;
70722 $i += $nlen - $ulen;
70723 }
70724 }
70725 }
70726 }
70727
70728 if (null === $encoding) {
70729 return $s;
70730 }
70731
70732 return iconv('UTF-8', $encoding.'//IGNORE', $s);
70733 }
70734
70735 public static function mb_internal_encoding($encoding = null)
70736 {
70737 if (null === $encoding) {
70738 return self::$internalEncoding;
70739 }
70740
70741 $encoding = self::getEncoding($encoding);
70742
70743 if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
70744 self::$internalEncoding = $encoding;
70745
70746 return true;
70747 }
70748
70749 return false;
70750 }
70751
70752 public static function mb_language($lang = null)
70753 {
70754 if (null === $lang) {
70755 return self::$language;
70756 }
70757
70758 switch ($lang = strtolower($lang)) {
70759 case 'uni':
70760 case 'neutral':
70761 self::$language = $lang;
70762
70763 return true;
70764 }
70765
70766 return false;
70767 }
70768
70769 public static function mb_list_encodings()
70770 {
70771 return array('UTF-8');
70772 }
70773
70774 public static function mb_encoding_aliases($encoding)
70775 {
70776 switch (strtoupper($encoding)) {
70777 case 'UTF8':
70778 case 'UTF-8':
70779 return array('utf8');
70780 }
70781
70782 return false;
70783 }
70784
70785 public static function mb_check_encoding($var = null, $encoding = null)
70786 {
70787 if (null === $encoding) {
70788 if (null === $var) {
70789 return false;
70790 }
70791 $encoding = self::$internalEncoding;
70792 }
70793
70794 return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
70795 }
70796
70797 public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
70798 {
70799 if (null === $encodingList) {
70800 $encodingList = self::$encodingList;
70801 } else {
70802 if (!\is_array($encodingList)) {
70803 $encodingList = array_map('trim', explode(',', $encodingList));
70804 }
70805 $encodingList = array_map('strtoupper', $encodingList);
70806 }
70807
70808 foreach ($encodingList as $enc) {
70809 switch ($enc) {
70810 case 'ASCII':
70811 if (!preg_match('/[\x80-\xFF]/', $str)) {
70812 return $enc;
70813 }
70814 break;
70815
70816 case 'UTF8':
70817 case 'UTF-8':
70818 if (preg_match('//u', $str)) {
70819 return 'UTF-8';
70820 }
70821 break;
70822
70823 default:
70824 if (0 === strncmp($enc, 'ISO-8859-', 9)) {
70825 return $enc;
70826 }
70827 }
70828 }
70829
70830 return false;
70831 }
70832
70833 public static function mb_detect_order($encodingList = null)
70834 {
70835 if (null === $encodingList) {
70836 return self::$encodingList;
70837 }
70838
70839 if (!\is_array($encodingList)) {
70840 $encodingList = array_map('trim', explode(',', $encodingList));
70841 }
70842 $encodingList = array_map('strtoupper', $encodingList);
70843
70844 foreach ($encodingList as $enc) {
70845 switch ($enc) {
70846 default:
70847 if (strncmp($enc, 'ISO-8859-', 9)) {
70848 return false;
70849 }
70850 case 'ASCII':
70851 case 'UTF8':
70852 case 'UTF-8':
70853 }
70854 }
70855
70856 self::$encodingList = $encodingList;
70857
70858 return true;
70859 }
70860
70861 public static function mb_strlen($s, $encoding = null)
70862 {
70863 $encoding = self::getEncoding($encoding);
70864 if ('CP850' === $encoding || 'ASCII' === $encoding) {
70865 return \strlen($s);
70866 }
70867
70868 return @iconv_strlen($s, $encoding);
70869 }
70870
70871 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
70872 {
70873 $encoding = self::getEncoding($encoding);
70874 if ('CP850' === $encoding || 'ASCII' === $encoding) {
70875 return strpos($haystack, $needle, $offset);
70876 }
70877
70878 $needle = (string) $needle;
70879 if ('' === $needle) {
70880 trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
70881
70882 return false;
70883 }
70884
70885 return iconv_strpos($haystack, $needle, $offset, $encoding);
70886 }
70887
70888 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
70889 {
70890 $encoding = self::getEncoding($encoding);
70891 if ('CP850' === $encoding || 'ASCII' === $encoding) {
70892 return strrpos($haystack, $needle, $offset);
70893 }
70894
70895 if ($offset != (int) $offset) {
70896 $offset = 0;
70897 } elseif ($offset = (int) $offset) {
70898 if ($offset < 0) {
70899 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
70900 $offset = 0;
70901 } else {
70902 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
70903 }
70904 }
70905
70906 $pos = iconv_strrpos($haystack, $needle, $encoding);
70907
70908 return false !== $pos ? $offset + $pos : false;
70909 }
70910
70911 public static function mb_strtolower($s, $encoding = null)
70912 {
70913 return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
70914 }
70915
70916 public static function mb_strtoupper($s, $encoding = null)
70917 {
70918 return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
70919 }
70920
70921 public static function mb_substitute_character($c = null)
70922 {
70923 if (0 === strcasecmp($c, 'none')) {
70924 return true;
70925 }
70926
70927 return null !== $c ? false : 'none';
70928 }
70929
70930 public static function mb_substr($s, $start, $length = null, $encoding = null)
70931 {
70932 $encoding = self::getEncoding($encoding);
70933 if ('CP850' === $encoding || 'ASCII' === $encoding) {
70934 return substr($s, $start, null === $length ? 2147483647 : $length);
70935 }
70936
70937 if ($start < 0) {
70938 $start = iconv_strlen($s, $encoding) + $start;
70939 if ($start < 0) {
70940 $start = 0;
70941 }
70942 }
70943
70944 if (null === $length) {
70945 $length = 2147483647;
70946 } elseif ($length < 0) {
70947 $length = iconv_strlen($s, $encoding) + $length - $start;
70948 if ($length < 0) {
70949 return '';
70950 }
70951 }
70952
70953 return (string) iconv_substr($s, $start, $length, $encoding);
70954 }
70955
70956 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
70957 {
70958 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
70959 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
70960
70961 return self::mb_strpos($haystack, $needle, $offset, $encoding);
70962 }
70963
70964 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
70965 {
70966 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
70967
70968 return self::getSubpart($pos, $part, $haystack, $encoding);
70969 }
70970
70971 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
70972 {
70973 $encoding = self::getEncoding($encoding);
70974 if ('CP850' === $encoding || 'ASCII' === $encoding) {
70975 return strrchr($haystack, $needle, $part);
70976 }
70977 $needle = self::mb_substr($needle, 0, 1, $encoding);
70978 $pos = iconv_strrpos($haystack, $needle, $encoding);
70979
70980 return self::getSubpart($pos, $part, $haystack, $encoding);
70981 }
70982
70983 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
70984 {
70985 $needle = self::mb_substr($needle, 0, 1, $encoding);
70986 $pos = self::mb_strripos($haystack, $needle, $encoding);
70987
70988 return self::getSubpart($pos, $part, $haystack, $encoding);
70989 }
70990
70991 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
70992 {
70993 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
70994 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
70995
70996 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
70997 }
70998
70999 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
71000 {
71001 $pos = strpos($haystack, $needle);
71002 if (false === $pos) {
71003 return false;
71004 }
71005 if ($part) {
71006 return substr($haystack, 0, $pos);
71007 }
71008
71009 return substr($haystack, $pos);
71010 }
71011
71012 public static function mb_get_info($type = 'all')
71013 {
71014 $info = array(
71015 'internal_encoding' => self::$internalEncoding,
71016 'http_output' => 'pass',
71017 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
71018 'func_overload' => 0,
71019 'func_overload_list' => 'no overload',
71020 'mail_charset' => 'UTF-8',
71021 'mail_header_encoding' => 'BASE64',
71022 'mail_body_encoding' => 'BASE64',
71023 'illegal_chars' => 0,
71024 'encoding_translation' => 'Off',
71025 'language' => self::$language,
71026 'detect_order' => self::$encodingList,
71027 'substitute_character' => 'none',
71028 'strict_detection' => 'Off',
71029 );
71030
71031 if ('all' === $type) {
71032 return $info;
71033 }
71034 if (isset($info[$type])) {
71035 return $info[$type];
71036 }
71037
71038 return false;
71039 }
71040
71041 public static function mb_http_input($type = '')
71042 {
71043 return false;
71044 }
71045
71046 public static function mb_http_output($encoding = null)
71047 {
71048 return null !== $encoding ? 'pass' === $encoding : 'pass';
71049 }
71050
71051 public static function mb_strwidth($s, $encoding = null)
71052 {
71053 $encoding = self::getEncoding($encoding);
71054
71055 if ('UTF-8' !== $encoding) {
71056 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
71057 }
71058
71059 $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);
71060
71061 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
71062 }
71063
71064 public static function mb_substr_count($haystack, $needle, $encoding = null)
71065 {
71066 return substr_count($haystack, $needle);
71067 }
71068
71069 public static function mb_output_handler($contents, $status)
71070 {
71071 return $contents;
71072 }
71073
71074 public static function mb_chr($code, $encoding = null)
71075 {
71076 if (0x80 > $code %= 0x200000) {
71077 $s = \chr($code);
71078 } elseif (0x800 > $code) {
71079 $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
71080 } elseif (0x10000 > $code) {
71081 $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
71082 } else {
71083 $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
71084 }
71085
71086 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
71087 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
71088 }
71089
71090 return $s;
71091 }
71092
71093 public static function mb_ord($s, $encoding = null)
71094 {
71095 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
71096 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
71097 }
71098
71099 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
71100 if (0xF0 <= $code) {
71101 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
71102 }
71103 if (0xE0 <= $code) {
71104 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
71105 }
71106 if (0xC0 <= $code) {
71107 return (($code - 0xC0) << 6) + $s[2] - 0x80;
71108 }
71109
71110 return $code;
71111 }
71112
71113 private static function getSubpart($pos, $part, $haystack, $encoding)
71114 {
71115 if (false === $pos) {
71116 return false;
71117 }
71118 if ($part) {
71119 return self::mb_substr($haystack, 0, $pos, $encoding);
71120 }
71121
71122 return self::mb_substr($haystack, $pos, null, $encoding);
71123 }
71124
71125 private static function html_encoding_callback(array $m)
71126 {
71127 $i = 1;
71128 $entities = '';
71129 $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
71130
71131 while (isset($m[$i])) {
71132 if (0x80 > $m[$i]) {
71133 $entities .= \chr($m[$i++]);
71134 continue;
71135 }
71136 if (0xF0 <= $m[$i]) {
71137 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
71138 } elseif (0xE0 <= $m[$i]) {
71139 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
71140 } else {
71141 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
71142 }
71143
71144 $entities .= '&#'.$c.';';
71145 }
71146
71147 return $entities;
71148 }
71149
71150 private static function title_case_lower(array $s)
71151 {
71152 return self::mb_convert_case($s[0], MB_CASE_LOWER, 'UTF-8');
71153 }
71154
71155 private static function title_case_upper(array $s)
71156 {
71157 return self::mb_convert_case($s[0], MB_CASE_UPPER, 'UTF-8');
71158 }
71159
71160 private static function getData($file)
71161 {
71162 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
71163 return require $file;
71164 }
71165
71166 return false;
71167 }
71168
71169 private static function getEncoding($encoding)
71170 {
71171 if (null === $encoding) {
71172 return self::$internalEncoding;
71173 }
71174
71175 $encoding = strtoupper($encoding);
71176
71177 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
71178 return 'CP850';
71179 }
71180 if ('UTF8' === $encoding) {
71181 return 'UTF-8';
71182 }
71183
71184 return $encoding;
71185 }
71186 }
71187 <?php
71188
71189 static $data = array (
71190 'A' => 'a',
71191 'B' => 'b',
71192 'C' => 'c',
71193 'D' => 'd',
71194 'E' => 'e',
71195 'F' => 'f',
71196 'G' => 'g',
71197 'H' => 'h',
71198 'I' => 'i',
71199 'J' => 'j',
71200 'K' => 'k',
71201 'L' => 'l',
71202 'M' => 'm',
71203 'N' => 'n',
71204 'O' => 'o',
71205 'P' => 'p',
71206 'Q' => 'q',
71207 'R' => 'r',
71208 'S' => 's',
71209 'T' => 't',
71210 'U' => 'u',
71211 'V' => 'v',
71212 'W' => 'w',
71213 'X' => 'x',
71214 'Y' => 'y',
71215 'Z' => 'z',
71216 'À' => 'à',
71217 'Á' => 'á',
71218 'Â' => 'â',
71219 'Ã' => 'ã',
71220 'Ä' => 'ä',
71221 'Å' => 'å',
71222 'Æ' => 'æ',
71223 'Ç' => 'ç',
71224 'È' => 'è',
71225 'É' => 'é',
71226 'Ê' => 'ê',
71227 'Ë' => 'ë',
71228 'Ì' => 'ì',
71229 'Í' => 'í',
71230 'Î' => 'î',
71231 'Ï' => 'ï',
71232 'Ð' => 'ð',
71233 'Ñ' => 'ñ',
71234 'Ò' => 'ò',
71235 'Ó' => 'ó',
71236 'Ô' => 'ô',
71237 'Õ' => 'õ',
71238 'Ö' => 'ö',
71239 'Ø' => 'ø',
71240 'Ù' => 'ù',
71241 'Ú' => 'ú',
71242 'Û' => 'û',
71243 'Ü' => 'ü',
71244 'Ý' => 'ý',
71245 'Þ' => 'þ',
71246 'Ā' => 'ā',
71247 'Ă' => 'ă',
71248 'Ą' => 'ą',
71249 'Ć' => 'ć',
71250 'Ĉ' => 'ĉ',
71251 'Ċ' => 'ċ',
71252 'Č' => 'č',
71253 'Ď' => 'ď',
71254 'Đ' => 'đ',
71255 'Ē' => 'ē',
71256 'Ĕ' => 'ĕ',
71257 'Ė' => 'ė',
71258 'Ę' => 'ę',
71259 'Ě' => 'ě',
71260 'Ĝ' => 'ĝ',
71261 'Ğ' => 'ğ',
71262 'Ġ' => 'ġ',
71263 'Ģ' => 'ģ',
71264 'Ĥ' => 'ĥ',
71265 'Ħ' => 'ħ',
71266 'Ĩ' => 'ĩ',
71267 'Ī' => 'ī',
71268 'Ĭ' => 'ĭ',
71269 'Į' => 'į',
71270 'İ' => 'i',
71271 'IJ' => 'ij',
71272 'Ĵ' => 'ĵ',
71273 'Ķ' => 'ķ',
71274 'Ĺ' => 'ĺ',
71275 'Ļ' => 'ļ',
71276 'Ľ' => 'ľ',
71277 'Ŀ' => 'ŀ',
71278 'Ł' => 'ł',
71279 'Ń' => 'ń',
71280 'Ņ' => 'ņ',
71281 'Ň' => 'ň',
71282 'Ŋ' => 'ŋ',
71283 'Ō' => 'ō',
71284 'Ŏ' => 'ŏ',
71285 'Ő' => 'ő',
71286 'Œ' => 'œ',
71287 'Ŕ' => 'ŕ',
71288 'Ŗ' => 'ŗ',
71289 'Ř' => 'ř',
71290 'Ś' => 'ś',
71291 'Ŝ' => 'ŝ',
71292 'Ş' => 'ş',
71293 'Š' => 'š',
71294 'Ţ' => 'ţ',
71295 'Ť' => 'ť',
71296 'Ŧ' => 'ŧ',
71297 'Ũ' => 'ũ',
71298 'Ū' => 'ū',
71299 'Ŭ' => 'ŭ',
71300 'Ů' => 'ů',
71301 'Ű' => 'ű',
71302 'Ų' => 'ų',
71303 'Ŵ' => 'ŵ',
71304 'Ŷ' => 'ŷ',
71305 'Ÿ' => 'ÿ',
71306 'Ź' => 'ź',
71307 'Ż' => 'ż',
71308 'Ž' => 'ž',
71309 'Ɓ' => 'ɓ',
71310 'Ƃ' => 'ƃ',
71311 'Ƅ' => 'ƅ',
71312 'Ɔ' => 'ɔ',
71313 'Ƈ' => 'ƈ',
71314 'Ɖ' => 'ɖ',
71315 'Ɗ' => 'ɗ',
71316 'Ƌ' => 'ƌ',
71317 'Ǝ' => 'ǝ',
71318 'Ə' => 'ə',
71319 'Ɛ' => 'ɛ',
71320 'Ƒ' => 'ƒ',
71321 'Ɠ' => 'ɠ',
71322 'Ɣ' => 'ɣ',
71323 'Ɩ' => 'ɩ',
71324 'Ɨ' => 'ɨ',
71325 'Ƙ' => 'ƙ',
71326 'Ɯ' => 'ɯ',
71327 'Ɲ' => 'ɲ',
71328 'Ɵ' => 'ɵ',
71329 'Ơ' => 'ơ',
71330 'Ƣ' => 'ƣ',
71331 'Ƥ' => 'ƥ',
71332 'Ʀ' => 'ʀ',
71333 'Ƨ' => 'ƨ',
71334 'Ʃ' => 'ʃ',
71335 'Ƭ' => 'ƭ',
71336 'Ʈ' => 'ʈ',
71337 'Ư' => 'ư',
71338 'Ʊ' => 'ʊ',
71339 'Ʋ' => 'ʋ',
71340 'Ƴ' => 'ƴ',
71341 'Ƶ' => 'ƶ',
71342 'Ʒ' => 'ʒ',
71343 'Ƹ' => 'ƹ',
71344 'Ƽ' => 'ƽ',
71345 'DŽ' => 'dž',
71346 'Dž' => 'dž',
71347 'LJ' => 'lj',
71348 'Lj' => 'lj',
71349 'NJ' => 'nj',
71350 'Nj' => 'nj',
71351 'Ǎ' => 'ǎ',
71352 'Ǐ' => 'ǐ',
71353 'Ǒ' => 'ǒ',
71354 'Ǔ' => 'ǔ',
71355 'Ǖ' => 'ǖ',
71356 'Ǘ' => 'ǘ',
71357 'Ǚ' => 'ǚ',
71358 'Ǜ' => 'ǜ',
71359 'Ǟ' => 'ǟ',
71360 'Ǡ' => 'ǡ',
71361 'Ǣ' => 'ǣ',
71362 'Ǥ' => 'ǥ',
71363 'Ǧ' => 'ǧ',
71364 'Ǩ' => 'ǩ',
71365 'Ǫ' => 'ǫ',
71366 'Ǭ' => 'ǭ',
71367 'Ǯ' => 'ǯ',
71368 'DZ' => 'dz',
71369 'Dz' => 'dz',
71370 'Ǵ' => 'ǵ',
71371 'Ƕ' => 'ƕ',
71372 'Ƿ' => 'ƿ',
71373 'Ǹ' => 'ǹ',
71374 'Ǻ' => 'ǻ',
71375 'Ǽ' => 'ǽ',
71376 'Ǿ' => 'ǿ',
71377 'Ȁ' => 'ȁ',
71378 'Ȃ' => 'ȃ',
71379 'Ȅ' => 'ȅ',
71380 'Ȇ' => 'ȇ',
71381 'Ȉ' => 'ȉ',
71382 'Ȋ' => 'ȋ',
71383 'Ȍ' => 'ȍ',
71384 'Ȏ' => 'ȏ',
71385 'Ȑ' => 'ȑ',
71386 'Ȓ' => 'ȓ',
71387 'Ȕ' => 'ȕ',
71388 'Ȗ' => 'ȗ',
71389 'Ș' => 'ș',
71390 'Ț' => 'ț',
71391 'Ȝ' => 'ȝ',
71392 'Ȟ' => 'ȟ',
71393 'Ƞ' => 'ƞ',
71394 'Ȣ' => 'ȣ',
71395 'Ȥ' => 'ȥ',
71396 'Ȧ' => 'ȧ',
71397 'Ȩ' => 'ȩ',
71398 'Ȫ' => 'ȫ',
71399 'Ȭ' => 'ȭ',
71400 'Ȯ' => 'ȯ',
71401 'Ȱ' => 'ȱ',
71402 'Ȳ' => 'ȳ',
71403 'Ⱥ' => 'ⱥ',
71404 'Ȼ' => 'ȼ',
71405 'Ƚ' => 'ƚ',
71406 'Ⱦ' => 'ⱦ',
71407 'Ɂ' => 'ɂ',
71408 'Ƀ' => 'ƀ',
71409 'Ʉ' => 'ʉ',
71410 'Ʌ' => 'ʌ',
71411 'Ɇ' => 'ɇ',
71412 'Ɉ' => 'ɉ',
71413 'Ɋ' => 'ɋ',
71414 'Ɍ' => 'ɍ',
71415 'Ɏ' => 'ɏ',
71416 'Ͱ' => 'ͱ',
71417 'Ͳ' => 'ͳ',
71418 'Ͷ' => 'ͷ',
71419 'Ϳ' => 'ϳ',
71420 'Ά' => 'ά',
71421 'Έ' => 'έ',
71422 'Ή' => 'ή',
71423 'Ί' => 'ί',
71424 'Ό' => 'ό',
71425 'Ύ' => 'ύ',
71426 'Ώ' => 'ώ',
71427 'Α' => 'α',
71428 'Β' => 'β',
71429 'Γ' => 'γ',
71430 'Δ' => 'δ',
71431 'Ε' => 'ε',
71432 'Ζ' => 'ζ',
71433 'Η' => 'η',
71434 'Θ' => 'θ',
71435 'Ι' => 'ι',
71436 'Κ' => 'κ',
71437 'Λ' => 'λ',
71438 'Μ' => 'μ',
71439 'Ν' => 'ν',
71440 'Ξ' => 'ξ',
71441 'Ο' => 'ο',
71442 'Π' => 'π',
71443 'Ρ' => 'ρ',
71444 'Σ' => 'σ',
71445 'Τ' => 'τ',
71446 'Υ' => 'υ',
71447 'Φ' => 'φ',
71448 'Χ' => 'χ',
71449 'Ψ' => 'ψ',
71450 'Ω' => 'ω',
71451 'Ϊ' => 'ϊ',
71452 'Ϋ' => 'ϋ',
71453 'Ϗ' => 'ϗ',
71454 'Ϙ' => 'ϙ',
71455 'Ϛ' => 'ϛ',
71456 'Ϝ' => 'ϝ',
71457 'Ϟ' => 'ϟ',
71458 'Ϡ' => 'ϡ',
71459 'Ϣ' => 'ϣ',
71460 'Ϥ' => 'ϥ',
71461 'Ϧ' => 'ϧ',
71462 'Ϩ' => 'ϩ',
71463 'Ϫ' => 'ϫ',
71464 'Ϭ' => 'ϭ',
71465 'Ϯ' => 'ϯ',
71466 'ϴ' => 'θ',
71467 'Ϸ' => 'ϸ',
71468 'Ϲ' => 'ϲ',
71469 'Ϻ' => 'ϻ',
71470 'Ͻ' => 'ͻ',
71471 'Ͼ' => 'ͼ',
71472 'Ͽ' => 'ͽ',
71473 'Ѐ' => 'ѐ',
71474 'Ё' => 'ё',
71475 'Ђ' => 'ђ',
71476 'Ѓ' => 'ѓ',
71477 'Є' => 'є',
71478 'Ѕ' => 'ѕ',
71479 'І' => 'і',
71480 'Ї' => 'ї',
71481 'Ј' => 'ј',
71482 'Љ' => 'љ',
71483 'Њ' => 'њ',
71484 'Ћ' => 'ћ',
71485 'Ќ' => 'ќ',
71486 'Ѝ' => 'ѝ',
71487 'Ў' => 'ў',
71488 'Џ' => 'џ',
71489 'А' => 'а',
71490 'Б' => 'б',
71491 'В' => 'в',
71492 'Г' => 'г',
71493 'Д' => 'д',
71494 'Е' => 'е',
71495 'Ж' => 'ж',
71496 'З' => 'з',
71497 'И' => 'и',
71498 'Й' => 'й',
71499 'К' => 'к',
71500 'Л' => 'л',
71501 'М' => 'м',
71502 'Н' => 'н',
71503 'О' => 'о',
71504 'П' => 'п',
71505 'Р' => 'р',
71506 'С' => 'с',
71507 'Т' => 'т',
71508 'У' => 'у',
71509 'Ф' => 'ф',
71510 'Х' => 'х',
71511 'Ц' => 'ц',
71512 'Ч' => 'ч',
71513 'Ш' => 'ш',
71514 'Щ' => 'щ',
71515 'Ъ' => 'ъ',
71516 'Ы' => 'ы',
71517 'Ь' => 'ь',
71518 'Э' => 'э',
71519 'Ю' => 'ю',
71520 'Я' => 'я',
71521 'Ѡ' => 'ѡ',
71522 'Ѣ' => 'ѣ',
71523 'Ѥ' => 'ѥ',
71524 'Ѧ' => 'ѧ',
71525 'Ѩ' => 'ѩ',
71526 'Ѫ' => 'ѫ',
71527 'Ѭ' => 'ѭ',
71528 'Ѯ' => 'ѯ',
71529 'Ѱ' => 'ѱ',
71530 'Ѳ' => 'ѳ',
71531 'Ѵ' => 'ѵ',
71532 'Ѷ' => 'ѷ',
71533 'Ѹ' => 'ѹ',
71534 'Ѻ' => 'ѻ',
71535 'Ѽ' => 'ѽ',
71536 'Ѿ' => 'ѿ',
71537 'Ҁ' => 'ҁ',
71538 'Ҋ' => 'ҋ',
71539 'Ҍ' => 'ҍ',
71540 'Ҏ' => 'ҏ',
71541 'Ґ' => 'ґ',
71542 'Ғ' => 'ғ',
71543 'Ҕ' => 'ҕ',
71544 'Җ' => 'җ',
71545 'Ҙ' => 'ҙ',
71546 'Қ' => 'қ',
71547 'Ҝ' => 'ҝ',
71548 'Ҟ' => 'ҟ',
71549 'Ҡ' => 'ҡ',
71550 'Ң' => 'ң',
71551 'Ҥ' => 'ҥ',
71552 'Ҧ' => 'ҧ',
71553 'Ҩ' => 'ҩ',
71554 'Ҫ' => 'ҫ',
71555 'Ҭ' => 'ҭ',
71556 'Ү' => 'ү',
71557 'Ұ' => 'ұ',
71558 'Ҳ' => 'ҳ',
71559 'Ҵ' => 'ҵ',
71560 'Ҷ' => 'ҷ',
71561 'Ҹ' => 'ҹ',
71562 'Һ' => 'һ',
71563 'Ҽ' => 'ҽ',
71564 'Ҿ' => 'ҿ',
71565 'Ӏ' => 'ӏ',
71566 'Ӂ' => 'ӂ',
71567 'Ӄ' => 'ӄ',
71568 'Ӆ' => 'ӆ',
71569 'Ӈ' => 'ӈ',
71570 'Ӊ' => 'ӊ',
71571 'Ӌ' => 'ӌ',
71572 'Ӎ' => 'ӎ',
71573 'Ӑ' => 'ӑ',
71574 'Ӓ' => 'ӓ',
71575 'Ӕ' => 'ӕ',
71576 'Ӗ' => 'ӗ',
71577 'Ә' => 'ә',
71578 'Ӛ' => 'ӛ',
71579 'Ӝ' => 'ӝ',
71580 'Ӟ' => 'ӟ',
71581 'Ӡ' => 'ӡ',
71582 'Ӣ' => 'ӣ',
71583 'Ӥ' => 'ӥ',
71584 'Ӧ' => 'ӧ',
71585 'Ө' => 'ө',
71586 'Ӫ' => 'ӫ',
71587 'Ӭ' => 'ӭ',
71588 'Ӯ' => 'ӯ',
71589 'Ӱ' => 'ӱ',
71590 'Ӳ' => 'ӳ',
71591 'Ӵ' => 'ӵ',
71592 'Ӷ' => 'ӷ',
71593 'Ӹ' => 'ӹ',
71594 'Ӻ' => 'ӻ',
71595 'Ӽ' => 'ӽ',
71596 'Ӿ' => 'ӿ',
71597 'Ԁ' => 'ԁ',
71598 'Ԃ' => 'ԃ',
71599 'Ԅ' => 'ԅ',
71600 'Ԇ' => 'ԇ',
71601 'Ԉ' => 'ԉ',
71602 'Ԋ' => 'ԋ',
71603 'Ԍ' => 'ԍ',
71604 'Ԏ' => 'ԏ',
71605 'Ԑ' => 'ԑ',
71606 'Ԓ' => 'ԓ',
71607 'Ԕ' => 'ԕ',
71608 'Ԗ' => 'ԗ',
71609 'Ԙ' => 'ԙ',
71610 'Ԛ' => 'ԛ',
71611 'Ԝ' => 'ԝ',
71612 'Ԟ' => 'ԟ',
71613 'Ԡ' => 'ԡ',
71614 'Ԣ' => 'ԣ',
71615 'Ԥ' => 'ԥ',
71616 'Ԧ' => 'ԧ',
71617 'Ԩ' => 'ԩ',
71618 'Ԫ' => 'ԫ',
71619 'Ԭ' => 'ԭ',
71620 'Ԯ' => 'ԯ',
71621 'Ա' => 'ա',
71622 'Բ' => 'բ',
71623 'Գ' => 'գ',
71624 'Դ' => 'դ',
71625 'Ե' => 'ե',
71626 'Զ' => 'զ',
71627 'Է' => 'է',
71628 'Ը' => 'ը',
71629 'Թ' => 'թ',
71630 'Ժ' => 'ժ',
71631 'Ի' => 'ի',
71632 'Լ' => 'լ',
71633 'Խ' => 'խ',
71634 'Ծ' => 'ծ',
71635 'Կ' => 'կ',
71636 'Հ' => 'հ',
71637 'Ձ' => 'ձ',
71638 'Ղ' => 'ղ',
71639 'Ճ' => 'ճ',
71640 'Մ' => 'մ',
71641 'Յ' => 'յ',
71642 'Ն' => 'ն',
71643 'Շ' => 'շ',
71644 'Ո' => 'ո',
71645 'Չ' => 'չ',
71646 'Պ' => 'պ',
71647 'Ջ' => 'ջ',
71648 'Ռ' => 'ռ',
71649 'Ս' => 'ս',
71650 'Վ' => 'վ',
71651 'Տ' => 'տ',
71652 'Ր' => 'ր',
71653 'Ց' => 'ց',
71654 'Ւ' => 'ւ',
71655 'Փ' => 'փ',
71656 'Ք' => 'ք',
71657 'Օ' => 'օ',
71658 'Ֆ' => 'ֆ',
71659 'Ⴀ' => 'ⴀ',
71660 'Ⴁ' => 'ⴁ',
71661 'Ⴂ' => 'ⴂ',
71662 'Ⴃ' => 'ⴃ',
71663 'Ⴄ' => 'ⴄ',
71664 'Ⴅ' => 'ⴅ',
71665 'Ⴆ' => 'ⴆ',
71666 'Ⴇ' => 'ⴇ',
71667 'Ⴈ' => 'ⴈ',
71668 'Ⴉ' => 'ⴉ',
71669 'Ⴊ' => 'ⴊ',
71670 'Ⴋ' => 'ⴋ',
71671 'Ⴌ' => 'ⴌ',
71672 'Ⴍ' => 'ⴍ',
71673 'Ⴎ' => 'ⴎ',
71674 'Ⴏ' => 'ⴏ',
71675 'Ⴐ' => 'ⴐ',
71676 'Ⴑ' => 'ⴑ',
71677 'Ⴒ' => 'ⴒ',
71678 'Ⴓ' => 'ⴓ',
71679 'Ⴔ' => 'ⴔ',
71680 'Ⴕ' => 'ⴕ',
71681 'Ⴖ' => 'ⴖ',
71682 'Ⴗ' => 'ⴗ',
71683 'Ⴘ' => 'ⴘ',
71684 'Ⴙ' => 'ⴙ',
71685 'Ⴚ' => 'ⴚ',
71686 'Ⴛ' => 'ⴛ',
71687 'Ⴜ' => 'ⴜ',
71688 'Ⴝ' => 'ⴝ',
71689 'Ⴞ' => 'ⴞ',
71690 'Ⴟ' => 'ⴟ',
71691 'Ⴠ' => 'ⴠ',
71692 'Ⴡ' => 'ⴡ',
71693 'Ⴢ' => 'ⴢ',
71694 'Ⴣ' => 'ⴣ',
71695 'Ⴤ' => 'ⴤ',
71696 'Ⴥ' => 'ⴥ',
71697 'Ⴧ' => 'ⴧ',
71698 'Ⴭ' => 'ⴭ',
71699 'Ḁ' => 'ḁ',
71700 'Ḃ' => 'ḃ',
71701 'Ḅ' => 'ḅ',
71702 'Ḇ' => 'ḇ',
71703 'Ḉ' => 'ḉ',
71704 'Ḋ' => 'ḋ',
71705 'Ḍ' => 'ḍ',
71706 'Ḏ' => 'ḏ',
71707 'Ḑ' => 'ḑ',
71708 'Ḓ' => 'ḓ',
71709 'Ḕ' => 'ḕ',
71710 'Ḗ' => 'ḗ',
71711 'Ḙ' => 'ḙ',
71712 'Ḛ' => 'ḛ',
71713 'Ḝ' => 'ḝ',
71714 'Ḟ' => 'ḟ',
71715 'Ḡ' => 'ḡ',
71716 'Ḣ' => 'ḣ',
71717 'Ḥ' => 'ḥ',
71718 'Ḧ' => 'ḧ',
71719 'Ḩ' => 'ḩ',
71720 'Ḫ' => 'ḫ',
71721 'Ḭ' => 'ḭ',
71722 'Ḯ' => 'ḯ',
71723 'Ḱ' => 'ḱ',
71724 'Ḳ' => 'ḳ',
71725 'Ḵ' => 'ḵ',
71726 'Ḷ' => 'ḷ',
71727 'Ḹ' => 'ḹ',
71728 'Ḻ' => 'ḻ',
71729 'Ḽ' => 'ḽ',
71730 'Ḿ' => 'ḿ',
71731 'Ṁ' => 'ṁ',
71732 'Ṃ' => 'ṃ',
71733 'Ṅ' => 'ṅ',
71734 'Ṇ' => 'ṇ',
71735 'Ṉ' => 'ṉ',
71736 'Ṋ' => 'ṋ',
71737 'Ṍ' => 'ṍ',
71738 'Ṏ' => 'ṏ',
71739 'Ṑ' => 'ṑ',
71740 'Ṓ' => 'ṓ',
71741 'Ṕ' => 'ṕ',
71742 'Ṗ' => 'ṗ',
71743 'Ṙ' => 'ṙ',
71744 'Ṛ' => 'ṛ',
71745 'Ṝ' => 'ṝ',
71746 'Ṟ' => 'ṟ',
71747 'Ṡ' => 'ṡ',
71748 'Ṣ' => 'ṣ',
71749 'Ṥ' => 'ṥ',
71750 'Ṧ' => 'ṧ',
71751 'Ṩ' => 'ṩ',
71752 'Ṫ' => 'ṫ',
71753 'Ṭ' => 'ṭ',
71754 'Ṯ' => 'ṯ',
71755 'Ṱ' => 'ṱ',
71756 'Ṳ' => 'ṳ',
71757 'Ṵ' => 'ṵ',
71758 'Ṷ' => 'ṷ',
71759 'Ṹ' => 'ṹ',
71760 'Ṻ' => 'ṻ',
71761 'Ṽ' => 'ṽ',
71762 'Ṿ' => 'ṿ',
71763 'Ẁ' => 'ẁ',
71764 'Ẃ' => 'ẃ',
71765 'Ẅ' => 'ẅ',
71766 'Ẇ' => 'ẇ',
71767 'Ẉ' => 'ẉ',
71768 'Ẋ' => 'ẋ',
71769 'Ẍ' => 'ẍ',
71770 'Ẏ' => 'ẏ',
71771 'Ẑ' => 'ẑ',
71772 'Ẓ' => 'ẓ',
71773 'Ẕ' => 'ẕ',
71774 'ẞ' => 'ß',
71775 'Ạ' => 'ạ',
71776 'Ả' => 'ả',
71777 'Ấ' => 'ấ',
71778 'Ầ' => 'ầ',
71779 'Ẩ' => 'ẩ',
71780 'Ẫ' => 'ẫ',
71781 'Ậ' => 'ậ',
71782 'Ắ' => 'ắ',
71783 'Ằ' => 'ằ',
71784 'Ẳ' => 'ẳ',
71785 'Ẵ' => 'ẵ',
71786 'Ặ' => 'ặ',
71787 'Ẹ' => 'ẹ',
71788 'Ẻ' => 'ẻ',
71789 'Ẽ' => 'ẽ',
71790 'Ế' => 'ế',
71791 'Ề' => 'ề',
71792 'Ể' => 'ể',
71793 'Ễ' => 'ễ',
71794 'Ệ' => 'ệ',
71795 'Ỉ' => 'ỉ',
71796 'Ị' => 'ị',
71797 'Ọ' => 'ọ',
71798 'Ỏ' => 'ỏ',
71799 'Ố' => 'ố',
71800 'Ồ' => 'ồ',
71801 'Ổ' => 'ổ',
71802 'Ỗ' => 'ỗ',
71803 'Ộ' => 'ộ',
71804 'Ớ' => 'ớ',
71805 'Ờ' => 'ờ',
71806 'Ở' => 'ở',
71807 'Ỡ' => 'ỡ',
71808 'Ợ' => 'ợ',
71809 'Ụ' => 'ụ',
71810 'Ủ' => 'ủ',
71811 'Ứ' => 'ứ',
71812 'Ừ' => 'ừ',
71813 'Ử' => 'ử',
71814 'Ữ' => 'ữ',
71815 'Ự' => 'ự',
71816 'Ỳ' => 'ỳ',
71817 'Ỵ' => 'ỵ',
71818 'Ỷ' => 'ỷ',
71819 'Ỹ' => 'ỹ',
71820 'Ỻ' => 'ỻ',
71821 'Ỽ' => 'ỽ',
71822 'Ỿ' => 'ỿ',
71823 'Ἀ' => 'ἀ',
71824 'Ἁ' => 'ἁ',
71825 'Ἂ' => 'ἂ',
71826 'Ἃ' => 'ἃ',
71827 'Ἄ' => 'ἄ',
71828 'Ἅ' => 'ἅ',
71829 'Ἆ' => 'ἆ',
71830 'Ἇ' => 'ἇ',
71831 'Ἐ' => 'ἐ',
71832 'Ἑ' => 'ἑ',
71833 'Ἒ' => 'ἒ',
71834 'Ἓ' => 'ἓ',
71835 'Ἔ' => 'ἔ',
71836 'Ἕ' => 'ἕ',
71837 'Ἠ' => 'ἠ',
71838 'Ἡ' => 'ἡ',
71839 'Ἢ' => 'ἢ',
71840 'Ἣ' => 'ἣ',
71841 'Ἤ' => 'ἤ',
71842 'Ἥ' => 'ἥ',
71843 'Ἦ' => 'ἦ',
71844 'Ἧ' => 'ἧ',
71845 'Ἰ' => 'ἰ',
71846 'Ἱ' => 'ἱ',
71847 'Ἲ' => 'ἲ',
71848 'Ἳ' => 'ἳ',
71849 'Ἴ' => 'ἴ',
71850 'Ἵ' => 'ἵ',
71851 'Ἶ' => 'ἶ',
71852 'Ἷ' => 'ἷ',
71853 'Ὀ' => 'ὀ',
71854 'Ὁ' => 'ὁ',
71855 'Ὂ' => 'ὂ',
71856 'Ὃ' => 'ὃ',
71857 'Ὄ' => 'ὄ',
71858 'Ὅ' => 'ὅ',
71859 'Ὑ' => 'ὑ',
71860 'Ὓ' => 'ὓ',
71861 'Ὕ' => 'ὕ',
71862 'Ὗ' => 'ὗ',
71863 'Ὠ' => 'ὠ',
71864 'Ὡ' => 'ὡ',
71865 'Ὢ' => 'ὢ',
71866 'Ὣ' => 'ὣ',
71867 'Ὤ' => 'ὤ',
71868 'Ὥ' => 'ὥ',
71869 'Ὦ' => 'ὦ',
71870 'Ὧ' => 'ὧ',
71871 'ᾈ' => 'ᾀ',
71872 'ᾉ' => 'ᾁ',
71873 'ᾊ' => 'ᾂ',
71874 'ᾋ' => 'ᾃ',
71875 'ᾌ' => 'ᾄ',
71876 'ᾍ' => 'ᾅ',
71877 'ᾎ' => 'ᾆ',
71878 'ᾏ' => 'ᾇ',
71879 'ᾘ' => 'ᾐ',
71880 'ᾙ' => 'ᾑ',
71881 'ᾚ' => 'ᾒ',
71882 'ᾛ' => 'ᾓ',
71883 'ᾜ' => 'ᾔ',
71884 'ᾝ' => 'ᾕ',
71885 'ᾞ' => 'ᾖ',
71886 'ᾟ' => 'ᾗ',
71887 'ᾨ' => 'ᾠ',
71888 'ᾩ' => 'ᾡ',
71889 'ᾪ' => 'ᾢ',
71890 'ᾫ' => 'ᾣ',
71891 'ᾬ' => 'ᾤ',
71892 'ᾭ' => 'ᾥ',
71893 'ᾮ' => 'ᾦ',
71894 'ᾯ' => 'ᾧ',
71895 'Ᾰ' => 'ᾰ',
71896 'Ᾱ' => 'ᾱ',
71897 'Ὰ' => 'ὰ',
71898 'Ά' => 'ά',
71899 'ᾼ' => 'ᾳ',
71900 'Ὲ' => 'ὲ',
71901 'Έ' => 'έ',
71902 'Ὴ' => 'ὴ',
71903 'Ή' => 'ή',
71904 'ῌ' => 'ῃ',
71905 'Ῐ' => 'ῐ',
71906 'Ῑ' => 'ῑ',
71907 'Ὶ' => 'ὶ',
71908 'Ί' => 'ί',
71909 'Ῠ' => 'ῠ',
71910 'Ῡ' => 'ῡ',
71911 'Ὺ' => 'ὺ',
71912 'Ύ' => 'ύ',
71913 'Ῥ' => 'ῥ',
71914 'Ὸ' => 'ὸ',
71915 'Ό' => 'ό',
71916 'Ὼ' => 'ὼ',
71917 'Ώ' => 'ώ',
71918 'ῼ' => 'ῳ',
71919 'Ω' => 'ω',
71920 'K' => 'k',
71921 'Å' => 'å',
71922 'Ⅎ' => 'ⅎ',
71923 'Ⅰ' => 'ⅰ',
71924 'Ⅱ' => 'ⅱ',
71925 'Ⅲ' => 'ⅲ',
71926 'Ⅳ' => 'ⅳ',
71927 'Ⅴ' => 'ⅴ',
71928 'Ⅵ' => 'ⅵ',
71929 'Ⅶ' => 'ⅶ',
71930 'Ⅷ' => 'ⅷ',
71931 'Ⅸ' => 'ⅸ',
71932 'Ⅹ' => 'ⅹ',
71933 'Ⅺ' => 'ⅺ',
71934 'Ⅻ' => 'ⅻ',
71935 'Ⅼ' => 'ⅼ',
71936 'Ⅽ' => 'ⅽ',
71937 'Ⅾ' => 'ⅾ',
71938 'Ⅿ' => 'ⅿ',
71939 'Ↄ' => 'ↄ',
71940 'Ⓐ' => 'ⓐ',
71941 'Ⓑ' => 'ⓑ',
71942 'Ⓒ' => 'ⓒ',
71943 'Ⓓ' => 'ⓓ',
71944 'Ⓔ' => 'ⓔ',
71945 'Ⓕ' => 'ⓕ',
71946 'Ⓖ' => 'ⓖ',
71947 'Ⓗ' => 'ⓗ',
71948 'Ⓘ' => 'ⓘ',
71949 'Ⓙ' => 'ⓙ',
71950 'Ⓚ' => 'ⓚ',
71951 'Ⓛ' => 'ⓛ',
71952 'Ⓜ' => 'ⓜ',
71953 'Ⓝ' => 'ⓝ',
71954 'Ⓞ' => 'ⓞ',
71955 'Ⓟ' => 'ⓟ',
71956 'Ⓠ' => 'ⓠ',
71957 'Ⓡ' => 'ⓡ',
71958 'Ⓢ' => 'ⓢ',
71959 'Ⓣ' => 'ⓣ',
71960 'Ⓤ' => 'ⓤ',
71961 'Ⓥ' => 'ⓥ',
71962 'Ⓦ' => 'ⓦ',
71963 'Ⓧ' => 'ⓧ',
71964 'Ⓨ' => 'ⓨ',
71965 'Ⓩ' => 'ⓩ',
71966 'Ⰰ' => 'ⰰ',
71967 'Ⰱ' => 'ⰱ',
71968 'Ⰲ' => 'ⰲ',
71969 'Ⰳ' => 'ⰳ',
71970 'Ⰴ' => 'ⰴ',
71971 'Ⰵ' => 'ⰵ',
71972 'Ⰶ' => 'ⰶ',
71973 'Ⰷ' => 'ⰷ',
71974 'Ⰸ' => 'ⰸ',
71975 'Ⰹ' => 'ⰹ',
71976 'Ⰺ' => 'ⰺ',
71977 'Ⰻ' => 'ⰻ',
71978 'Ⰼ' => 'ⰼ',
71979 'Ⰽ' => 'ⰽ',
71980 'Ⰾ' => 'ⰾ',
71981 'Ⰿ' => 'ⰿ',
71982 'Ⱀ' => 'ⱀ',
71983 'Ⱁ' => 'ⱁ',
71984 'Ⱂ' => 'ⱂ',
71985 'Ⱃ' => 'ⱃ',
71986 'Ⱄ' => 'ⱄ',
71987 'Ⱅ' => 'ⱅ',
71988 'Ⱆ' => 'ⱆ',
71989 'Ⱇ' => 'ⱇ',
71990 'Ⱈ' => 'ⱈ',
71991 'Ⱉ' => 'ⱉ',
71992 'Ⱊ' => 'ⱊ',
71993 'Ⱋ' => 'ⱋ',
71994 'Ⱌ' => 'ⱌ',
71995 'Ⱍ' => 'ⱍ',
71996 'Ⱎ' => 'ⱎ',
71997 'Ⱏ' => 'ⱏ',
71998 'Ⱐ' => 'ⱐ',
71999 'Ⱑ' => 'ⱑ',
72000 'Ⱒ' => 'ⱒ',
72001 'Ⱓ' => 'ⱓ',
72002 'Ⱔ' => 'ⱔ',
72003 'Ⱕ' => 'ⱕ',
72004 'Ⱖ' => 'ⱖ',
72005 'Ⱗ' => 'ⱗ',
72006 'Ⱘ' => 'ⱘ',
72007 'Ⱙ' => 'ⱙ',
72008 'Ⱚ' => 'ⱚ',
72009 'Ⱛ' => 'ⱛ',
72010 'Ⱜ' => 'ⱜ',
72011 'Ⱝ' => 'ⱝ',
72012 'Ⱞ' => 'ⱞ',
72013 'Ⱡ' => 'ⱡ',
72014 'Ɫ' => 'ɫ',
72015 'Ᵽ' => 'ᵽ',
72016 'Ɽ' => 'ɽ',
72017 'Ⱨ' => 'ⱨ',
72018 'Ⱪ' => 'ⱪ',
72019 'Ⱬ' => 'ⱬ',
72020 'Ɑ' => 'ɑ',
72021 'Ɱ' => 'ɱ',
72022 'Ɐ' => 'ɐ',
72023 'Ɒ' => 'ɒ',
72024 'Ⱳ' => 'ⱳ',
72025 'Ⱶ' => 'ⱶ',
72026 'Ȿ' => 'ȿ',
72027 'Ɀ' => 'ɀ',
72028 'Ⲁ' => 'ⲁ',
72029 'Ⲃ' => 'ⲃ',
72030 'Ⲅ' => 'ⲅ',
72031 'Ⲇ' => 'ⲇ',
72032 'Ⲉ' => 'ⲉ',
72033 'Ⲋ' => 'ⲋ',
72034 'Ⲍ' => 'ⲍ',
72035 'Ⲏ' => 'ⲏ',
72036 'Ⲑ' => 'ⲑ',
72037 'Ⲓ' => 'ⲓ',
72038 'Ⲕ' => 'ⲕ',
72039 'Ⲗ' => 'ⲗ',
72040 'Ⲙ' => 'ⲙ',
72041 'Ⲛ' => 'ⲛ',
72042 'Ⲝ' => 'ⲝ',
72043 'Ⲟ' => 'ⲟ',
72044 'Ⲡ' => 'ⲡ',
72045 'Ⲣ' => 'ⲣ',
72046 'Ⲥ' => 'ⲥ',
72047 'Ⲧ' => 'ⲧ',
72048 'Ⲩ' => 'ⲩ',
72049 'Ⲫ' => 'ⲫ',
72050 'Ⲭ' => 'ⲭ',
72051 'Ⲯ' => 'ⲯ',
72052 'Ⲱ' => 'ⲱ',
72053 'Ⲳ' => 'ⲳ',
72054 'Ⲵ' => 'ⲵ',
72055 'Ⲷ' => 'ⲷ',
72056 'Ⲹ' => 'ⲹ',
72057 'Ⲻ' => 'ⲻ',
72058 'Ⲽ' => 'ⲽ',
72059 'Ⲿ' => 'ⲿ',
72060 'Ⳁ' => 'ⳁ',
72061 'Ⳃ' => 'ⳃ',
72062 'Ⳅ' => 'ⳅ',
72063 'Ⳇ' => 'ⳇ',
72064 'Ⳉ' => 'ⳉ',
72065 'Ⳋ' => 'ⳋ',
72066 'Ⳍ' => 'ⳍ',
72067 'Ⳏ' => 'ⳏ',
72068 'Ⳑ' => 'ⳑ',
72069 'Ⳓ' => 'ⳓ',
72070 'Ⳕ' => 'ⳕ',
72071 'Ⳗ' => 'ⳗ',
72072 'Ⳙ' => 'ⳙ',
72073 'Ⳛ' => 'ⳛ',
72074 'Ⳝ' => 'ⳝ',
72075 'Ⳟ' => 'ⳟ',
72076 'Ⳡ' => 'ⳡ',
72077 'Ⳣ' => 'ⳣ',
72078 'Ⳬ' => 'ⳬ',
72079 'Ⳮ' => 'ⳮ',
72080 'Ⳳ' => 'ⳳ',
72081 'Ꙁ' => 'ꙁ',
72082 'Ꙃ' => 'ꙃ',
72083 'Ꙅ' => 'ꙅ',
72084 'Ꙇ' => 'ꙇ',
72085 'Ꙉ' => 'ꙉ',
72086 'Ꙋ' => 'ꙋ',
72087 'Ꙍ' => 'ꙍ',
72088 'Ꙏ' => 'ꙏ',
72089 'Ꙑ' => 'ꙑ',
72090 'Ꙓ' => 'ꙓ',
72091 'Ꙕ' => 'ꙕ',
72092 'Ꙗ' => 'ꙗ',
72093 'Ꙙ' => 'ꙙ',
72094 'Ꙛ' => 'ꙛ',
72095 'Ꙝ' => 'ꙝ',
72096 'Ꙟ' => 'ꙟ',
72097 'Ꙡ' => 'ꙡ',
72098 'Ꙣ' => 'ꙣ',
72099 'Ꙥ' => 'ꙥ',
72100 'Ꙧ' => 'ꙧ',
72101 'Ꙩ' => 'ꙩ',
72102 'Ꙫ' => 'ꙫ',
72103 'Ꙭ' => 'ꙭ',
72104 'Ꚁ' => 'ꚁ',
72105 'Ꚃ' => 'ꚃ',
72106 'Ꚅ' => 'ꚅ',
72107 'Ꚇ' => 'ꚇ',
72108 'Ꚉ' => 'ꚉ',
72109 'Ꚋ' => 'ꚋ',
72110 'Ꚍ' => 'ꚍ',
72111 'Ꚏ' => 'ꚏ',
72112 'Ꚑ' => 'ꚑ',
72113 'Ꚓ' => 'ꚓ',
72114 'Ꚕ' => 'ꚕ',
72115 'Ꚗ' => 'ꚗ',
72116 'Ꚙ' => 'ꚙ',
72117 'Ꚛ' => 'ꚛ',
72118 'Ꜣ' => 'ꜣ',
72119 'Ꜥ' => 'ꜥ',
72120 'Ꜧ' => 'ꜧ',
72121 'Ꜩ' => 'ꜩ',
72122 'Ꜫ' => 'ꜫ',
72123 'Ꜭ' => 'ꜭ',
72124 'Ꜯ' => 'ꜯ',
72125 'Ꜳ' => 'ꜳ',
72126 'Ꜵ' => 'ꜵ',
72127 'Ꜷ' => 'ꜷ',
72128 'Ꜹ' => 'ꜹ',
72129 'Ꜻ' => 'ꜻ',
72130 'Ꜽ' => 'ꜽ',
72131 'Ꜿ' => 'ꜿ',
72132 'Ꝁ' => 'ꝁ',
72133 'Ꝃ' => 'ꝃ',
72134 'Ꝅ' => 'ꝅ',
72135 'Ꝇ' => 'ꝇ',
72136 'Ꝉ' => 'ꝉ',
72137 'Ꝋ' => 'ꝋ',
72138 'Ꝍ' => 'ꝍ',
72139 'Ꝏ' => 'ꝏ',
72140 'Ꝑ' => 'ꝑ',
72141 'Ꝓ' => 'ꝓ',
72142 'Ꝕ' => 'ꝕ',
72143 'Ꝗ' => 'ꝗ',
72144 'Ꝙ' => 'ꝙ',
72145 'Ꝛ' => 'ꝛ',
72146 'Ꝝ' => 'ꝝ',
72147 'Ꝟ' => 'ꝟ',
72148 'Ꝡ' => 'ꝡ',
72149 'Ꝣ' => 'ꝣ',
72150 'Ꝥ' => 'ꝥ',
72151 'Ꝧ' => 'ꝧ',
72152 'Ꝩ' => 'ꝩ',
72153 'Ꝫ' => 'ꝫ',
72154 'Ꝭ' => 'ꝭ',
72155 'Ꝯ' => 'ꝯ',
72156 'Ꝺ' => 'ꝺ',
72157 'Ꝼ' => 'ꝼ',
72158 'Ᵹ' => 'ᵹ',
72159 'Ꝿ' => 'ꝿ',
72160 'Ꞁ' => 'ꞁ',
72161 'Ꞃ' => 'ꞃ',
72162 'Ꞅ' => 'ꞅ',
72163 'Ꞇ' => 'ꞇ',
72164 'Ꞌ' => 'ꞌ',
72165 'Ɥ' => 'ɥ',
72166 'Ꞑ' => 'ꞑ',
72167 'Ꞓ' => 'ꞓ',
72168 'Ꞗ' => 'ꞗ',
72169 'Ꞙ' => 'ꞙ',
72170 'Ꞛ' => 'ꞛ',
72171 'Ꞝ' => 'ꞝ',
72172 'Ꞟ' => 'ꞟ',
72173 'Ꞡ' => 'ꞡ',
72174 'Ꞣ' => 'ꞣ',
72175 'Ꞥ' => 'ꞥ',
72176 'Ꞧ' => 'ꞧ',
72177 'Ꞩ' => 'ꞩ',
72178 'Ɦ' => 'ɦ',
72179 'Ɜ' => 'ɜ',
72180 'Ɡ' => 'ɡ',
72181 'Ɬ' => 'ɬ',
72182 'Ʞ' => 'ʞ',
72183 'Ʇ' => 'ʇ',
72184 'A' => 'a',
72185 'B' => 'b',
72186 'C' => 'c',
72187 'D' => 'd',
72188 'E' => 'e',
72189 'F' => 'f',
72190 'G' => 'g',
72191 'H' => 'h',
72192 'I' => 'i',
72193 'J' => 'j',
72194 'K' => 'k',
72195 'L' => 'l',
72196 'M' => 'm',
72197 'N' => 'n',
72198 'O' => 'o',
72199 'P' => 'p',
72200 'Q' => 'q',
72201 'R' => 'r',
72202 'S' => 's',
72203 'T' => 't',
72204 'U' => 'u',
72205 'V' => 'v',
72206 'W' => 'w',
72207 'X' => 'x',
72208 'Y' => 'y',
72209 'Z' => 'z',
72210 '𐐀' => '𐐨',
72211 '𐐁' => '𐐩',
72212 '𐐂' => '𐐪',
72213 '𐐃' => '𐐫',
72214 '𐐄' => '𐐬',
72215 '𐐅' => '𐐭',
72216 '𐐆' => '𐐮',
72217 '𐐇' => '𐐯',
72218 '𐐈' => '𐐰',
72219 '𐐉' => '𐐱',
72220 '𐐊' => '𐐲',
72221 '𐐋' => '𐐳',
72222 '𐐌' => '𐐴',
72223 '𐐍' => '𐐵',
72224 '𐐎' => '𐐶',
72225 '𐐏' => '𐐷',
72226 '𐐐' => '𐐸',
72227 '𐐑' => '𐐹',
72228 '𐐒' => '𐐺',
72229 '𐐓' => '𐐻',
72230 '𐐔' => '𐐼',
72231 '𐐕' => '𐐽',
72232 '𐐖' => '𐐾',
72233 '𐐗' => '𐐿',
72234 '𐐘' => '𐑀',
72235 '𐐙' => '𐑁',
72236 '𐐚' => '𐑂',
72237 '𐐛' => '𐑃',
72238 '𐐜' => '𐑄',
72239 '𐐝' => '𐑅',
72240 '𐐞' => '𐑆',
72241 '𐐟' => '𐑇',
72242 '𐐠' => '𐑈',
72243 '𐐡' => '𐑉',
72244 '𐐢' => '𐑊',
72245 '𐐣' => '𐑋',
72246 '𐐤' => '𐑌',
72247 '𐐥' => '𐑍',
72248 '𐐦' => '𐑎',
72249 '𐐧' => '𐑏',
72250 '𑢠' => '𑣀',
72251 '𑢡' => '𑣁',
72252 '𑢢' => '𑣂',
72253 '𑢣' => '𑣃',
72254 '𑢤' => '𑣄',
72255 '𑢥' => '𑣅',
72256 '𑢦' => '𑣆',
72257 '𑢧' => '𑣇',
72258 '𑢨' => '𑣈',
72259 '𑢩' => '𑣉',
72260 '𑢪' => '𑣊',
72261 '𑢫' => '𑣋',
72262 '𑢬' => '𑣌',
72263 '𑢭' => '𑣍',
72264 '𑢮' => '𑣎',
72265 '𑢯' => '𑣏',
72266 '𑢰' => '𑣐',
72267 '𑢱' => '𑣑',
72268 '𑢲' => '𑣒',
72269 '𑢳' => '𑣓',
72270 '𑢴' => '𑣔',
72271 '𑢵' => '𑣕',
72272 '𑢶' => '𑣖',
72273 '𑢷' => '𑣗',
72274 '𑢸' => '𑣘',
72275 '𑢹' => '𑣙',
72276 '𑢺' => '𑣚',
72277 '𑢻' => '𑣛',
72278 '𑢼' => '𑣜',
72279 '𑢽' => '𑣝',
72280 '𑢾' => '𑣞',
72281 '𑢿' => '𑣟',
72282 );
72283
72284 $result =& $data;
72285 unset($data);
72286
72287 return $result;
72288 <?php
72289
72290 static $data = array (
72291 'a' => 'A',
72292 'b' => 'B',
72293 'c' => 'C',
72294 'd' => 'D',
72295 'e' => 'E',
72296 'f' => 'F',
72297 'g' => 'G',
72298 'h' => 'H',
72299 'i' => 'I',
72300 'j' => 'J',
72301 'k' => 'K',
72302 'l' => 'L',
72303 'm' => 'M',
72304 'n' => 'N',
72305 'o' => 'O',
72306 'p' => 'P',
72307 'q' => 'Q',
72308 'r' => 'R',
72309 's' => 'S',
72310 't' => 'T',
72311 'u' => 'U',
72312 'v' => 'V',
72313 'w' => 'W',
72314 'x' => 'X',
72315 'y' => 'Y',
72316 'z' => 'Z',
72317 'µ' => 'Μ',
72318 'à' => 'À',
72319 'á' => 'Á',
72320 'â' => 'Â',
72321 'ã' => 'Ã',
72322 'ä' => 'Ä',
72323 'å' => 'Å',
72324 'æ' => 'Æ',
72325 'ç' => 'Ç',
72326 'è' => 'È',
72327 'é' => 'É',
72328 'ê' => 'Ê',
72329 'ë' => 'Ë',
72330 'ì' => 'Ì',
72331 'í' => 'Í',
72332 'î' => 'Î',
72333 'ï' => 'Ï',
72334 'ð' => 'Ð',
72335 'ñ' => 'Ñ',
72336 'ò' => 'Ò',
72337 'ó' => 'Ó',
72338 'ô' => 'Ô',
72339 'õ' => 'Õ',
72340 'ö' => 'Ö',
72341 'ø' => 'Ø',
72342 'ù' => 'Ù',
72343 'ú' => 'Ú',
72344 'û' => 'Û',
72345 'ü' => 'Ü',
72346 'ý' => 'Ý',
72347 'þ' => 'Þ',
72348 'ÿ' => 'Ÿ',
72349 'ā' => 'Ā',
72350 'ă' => 'Ă',
72351 'ą' => 'Ą',
72352 'ć' => 'Ć',
72353 'ĉ' => 'Ĉ',
72354 'ċ' => 'Ċ',
72355 'č' => 'Č',
72356 'ď' => 'Ď',
72357 'đ' => 'Đ',
72358 'ē' => 'Ē',
72359 'ĕ' => 'Ĕ',
72360 'ė' => 'Ė',
72361 'ę' => 'Ę',
72362 'ě' => 'Ě',
72363 'ĝ' => 'Ĝ',
72364 'ğ' => 'Ğ',
72365 'ġ' => 'Ġ',
72366 'ģ' => 'Ģ',
72367 'ĥ' => 'Ĥ',
72368 'ħ' => 'Ħ',
72369 'ĩ' => 'Ĩ',
72370 'ī' => 'Ī',
72371 'ĭ' => 'Ĭ',
72372 'į' => 'Į',
72373 'ı' => 'I',
72374 'ij' => 'IJ',
72375 'ĵ' => 'Ĵ',
72376 'ķ' => 'Ķ',
72377 'ĺ' => 'Ĺ',
72378 'ļ' => 'Ļ',
72379 'ľ' => 'Ľ',
72380 'ŀ' => 'Ŀ',
72381 'ł' => 'Ł',
72382 'ń' => 'Ń',
72383 'ņ' => 'Ņ',
72384 'ň' => 'Ň',
72385 'ŋ' => 'Ŋ',
72386 'ō' => 'Ō',
72387 'ŏ' => 'Ŏ',
72388 'ő' => 'Ő',
72389 'œ' => 'Œ',
72390 'ŕ' => 'Ŕ',
72391 'ŗ' => 'Ŗ',
72392 'ř' => 'Ř',
72393 'ś' => 'Ś',
72394 'ŝ' => 'Ŝ',
72395 'ş' => 'Ş',
72396 'š' => 'Š',
72397 'ţ' => 'Ţ',
72398 'ť' => 'Ť',
72399 'ŧ' => 'Ŧ',
72400 'ũ' => 'Ũ',
72401 'ū' => 'Ū',
72402 'ŭ' => 'Ŭ',
72403 'ů' => 'Ů',
72404 'ű' => 'Ű',
72405 'ų' => 'Ų',
72406 'ŵ' => 'Ŵ',
72407 'ŷ' => 'Ŷ',
72408 'ź' => 'Ź',
72409 'ż' => 'Ż',
72410 'ž' => 'Ž',
72411 'ſ' => 'S',
72412 'ƀ' => 'Ƀ',
72413 'ƃ' => 'Ƃ',
72414 'ƅ' => 'Ƅ',
72415 'ƈ' => 'Ƈ',
72416 'ƌ' => 'Ƌ',
72417 'ƒ' => 'Ƒ',
72418 'ƕ' => 'Ƕ',
72419 'ƙ' => 'Ƙ',
72420 'ƚ' => 'Ƚ',
72421 'ƞ' => 'Ƞ',
72422 'ơ' => 'Ơ',
72423 'ƣ' => 'Ƣ',
72424 'ƥ' => 'Ƥ',
72425 'ƨ' => 'Ƨ',
72426 'ƭ' => 'Ƭ',
72427 'ư' => 'Ư',
72428 'ƴ' => 'Ƴ',
72429 'ƶ' => 'Ƶ',
72430 'ƹ' => 'Ƹ',
72431 'ƽ' => 'Ƽ',
72432 'ƿ' => 'Ƿ',
72433 'Dž' => 'DŽ',
72434 'dž' => 'DŽ',
72435 'Lj' => 'LJ',
72436 'lj' => 'LJ',
72437 'Nj' => 'NJ',
72438 'nj' => 'NJ',
72439 'ǎ' => 'Ǎ',
72440 'ǐ' => 'Ǐ',
72441 'ǒ' => 'Ǒ',
72442 'ǔ' => 'Ǔ',
72443 'ǖ' => 'Ǖ',
72444 'ǘ' => 'Ǘ',
72445 'ǚ' => 'Ǚ',
72446 'ǜ' => 'Ǜ',
72447 'ǝ' => 'Ǝ',
72448 'ǟ' => 'Ǟ',
72449 'ǡ' => 'Ǡ',
72450 'ǣ' => 'Ǣ',
72451 'ǥ' => 'Ǥ',
72452 'ǧ' => 'Ǧ',
72453 'ǩ' => 'Ǩ',
72454 'ǫ' => 'Ǫ',
72455 'ǭ' => 'Ǭ',
72456 'ǯ' => 'Ǯ',
72457 'Dz' => 'DZ',
72458 'dz' => 'DZ',
72459 'ǵ' => 'Ǵ',
72460 'ǹ' => 'Ǹ',
72461 'ǻ' => 'Ǻ',
72462 'ǽ' => 'Ǽ',
72463 'ǿ' => 'Ǿ',
72464 'ȁ' => 'Ȁ',
72465 'ȃ' => 'Ȃ',
72466 'ȅ' => 'Ȅ',
72467 'ȇ' => 'Ȇ',
72468 'ȉ' => 'Ȉ',
72469 'ȋ' => 'Ȋ',
72470 'ȍ' => 'Ȍ',
72471 'ȏ' => 'Ȏ',
72472 'ȑ' => 'Ȑ',
72473 'ȓ' => 'Ȓ',
72474 'ȕ' => 'Ȕ',
72475 'ȗ' => 'Ȗ',
72476 'ș' => 'Ș',
72477 'ț' => 'Ț',
72478 'ȝ' => 'Ȝ',
72479 'ȟ' => 'Ȟ',
72480 'ȣ' => 'Ȣ',
72481 'ȥ' => 'Ȥ',
72482 'ȧ' => 'Ȧ',
72483 'ȩ' => 'Ȩ',
72484 'ȫ' => 'Ȫ',
72485 'ȭ' => 'Ȭ',
72486 'ȯ' => 'Ȯ',
72487 'ȱ' => 'Ȱ',
72488 'ȳ' => 'Ȳ',
72489 'ȼ' => 'Ȼ',
72490 'ȿ' => 'Ȿ',
72491 'ɀ' => 'Ɀ',
72492 'ɂ' => 'Ɂ',
72493 'ɇ' => 'Ɇ',
72494 'ɉ' => 'Ɉ',
72495 'ɋ' => 'Ɋ',
72496 'ɍ' => 'Ɍ',
72497 'ɏ' => 'Ɏ',
72498 'ɐ' => 'Ɐ',
72499 'ɑ' => 'Ɑ',
72500 'ɒ' => 'Ɒ',
72501 'ɓ' => 'Ɓ',
72502 'ɔ' => 'Ɔ',
72503 'ɖ' => 'Ɖ',
72504 'ɗ' => 'Ɗ',
72505 'ə' => 'Ə',
72506 'ɛ' => 'Ɛ',
72507 'ɜ' => 'Ɜ',
72508 'ɠ' => 'Ɠ',
72509 'ɡ' => 'Ɡ',
72510 'ɣ' => 'Ɣ',
72511 'ɥ' => 'Ɥ',
72512 'ɦ' => 'Ɦ',
72513 'ɨ' => 'Ɨ',
72514 'ɩ' => 'Ɩ',
72515 'ɫ' => 'Ɫ',
72516 'ɬ' => 'Ɬ',
72517 'ɯ' => 'Ɯ',
72518 'ɱ' => 'Ɱ',
72519 'ɲ' => 'Ɲ',
72520 'ɵ' => 'Ɵ',
72521 'ɽ' => 'Ɽ',
72522 'ʀ' => 'Ʀ',
72523 'ʃ' => 'Ʃ',
72524 'ʇ' => 'Ʇ',
72525 'ʈ' => 'Ʈ',
72526 'ʉ' => 'Ʉ',
72527 'ʊ' => 'Ʊ',
72528 'ʋ' => 'Ʋ',
72529 'ʌ' => 'Ʌ',
72530 'ʒ' => 'Ʒ',
72531 'ʞ' => 'Ʞ',
72532 'ͅ' => 'Ι',
72533 'ͱ' => 'Ͱ',
72534 'ͳ' => 'Ͳ',
72535 'ͷ' => 'Ͷ',
72536 'ͻ' => 'Ͻ',
72537 'ͼ' => 'Ͼ',
72538 'ͽ' => 'Ͽ',
72539 'ά' => 'Ά',
72540 'έ' => 'Έ',
72541 'ή' => 'Ή',
72542 'ί' => 'Ί',
72543 'α' => 'Α',
72544 'β' => 'Β',
72545 'γ' => 'Γ',
72546 'δ' => 'Δ',
72547 'ε' => 'Ε',
72548 'ζ' => 'Ζ',
72549 'η' => 'Η',
72550 'θ' => 'Θ',
72551 'ι' => 'Ι',
72552 'κ' => 'Κ',
72553 'λ' => 'Λ',
72554 'μ' => 'Μ',
72555 'ν' => 'Ν',
72556 'ξ' => 'Ξ',
72557 'ο' => 'Ο',
72558 'π' => 'Π',
72559 'ρ' => 'Ρ',
72560 'ς' => 'Σ',
72561 'σ' => 'Σ',
72562 'τ' => 'Τ',
72563 'υ' => 'Υ',
72564 'φ' => 'Φ',
72565 'χ' => 'Χ',
72566 'ψ' => 'Ψ',
72567 'ω' => 'Ω',
72568 'ϊ' => 'Ϊ',
72569 'ϋ' => 'Ϋ',
72570 'ό' => 'Ό',
72571 'ύ' => 'Ύ',
72572 'ώ' => 'Ώ',
72573 'ϐ' => 'Β',
72574 'ϑ' => 'Θ',
72575 'ϕ' => 'Φ',
72576 'ϖ' => 'Π',
72577 'ϗ' => 'Ϗ',
72578 'ϙ' => 'Ϙ',
72579 'ϛ' => 'Ϛ',
72580 'ϝ' => 'Ϝ',
72581 'ϟ' => 'Ϟ',
72582 'ϡ' => 'Ϡ',
72583 'ϣ' => 'Ϣ',
72584 'ϥ' => 'Ϥ',
72585 'ϧ' => 'Ϧ',
72586 'ϩ' => 'Ϩ',
72587 'ϫ' => 'Ϫ',
72588 'ϭ' => 'Ϭ',
72589 'ϯ' => 'Ϯ',
72590 'ϰ' => 'Κ',
72591 'ϱ' => 'Ρ',
72592 'ϲ' => 'Ϲ',
72593 'ϳ' => 'Ϳ',
72594 'ϵ' => 'Ε',
72595 'ϸ' => 'Ϸ',
72596 'ϻ' => 'Ϻ',
72597 'а' => 'А',
72598 'б' => 'Б',
72599 'в' => 'В',
72600 'г' => 'Г',
72601 'д' => 'Д',
72602 'е' => 'Е',
72603 'ж' => 'Ж',
72604 'з' => 'З',
72605 'и' => 'И',
72606 'й' => 'Й',
72607 'к' => 'К',
72608 'л' => 'Л',
72609 'м' => 'М',
72610 'н' => 'Н',
72611 'о' => 'О',
72612 'п' => 'П',
72613 'р' => 'Р',
72614 'с' => 'С',
72615 'т' => 'Т',
72616 'у' => 'У',
72617 'ф' => 'Ф',
72618 'х' => 'Х',
72619 'ц' => 'Ц',
72620 'ч' => 'Ч',
72621 'ш' => 'Ш',
72622 'щ' => 'Щ',
72623 'ъ' => 'Ъ',
72624 'ы' => 'Ы',
72625 'ь' => 'Ь',
72626 'э' => 'Э',
72627 'ю' => 'Ю',
72628 'я' => 'Я',
72629 'ѐ' => 'Ѐ',
72630 'ё' => 'Ё',
72631 'ђ' => 'Ђ',
72632 'ѓ' => 'Ѓ',
72633 'є' => 'Є',
72634 'ѕ' => 'Ѕ',
72635 'і' => 'І',
72636 'ї' => 'Ї',
72637 'ј' => 'Ј',
72638 'љ' => 'Љ',
72639 'њ' => 'Њ',
72640 'ћ' => 'Ћ',
72641 'ќ' => 'Ќ',
72642 'ѝ' => 'Ѝ',
72643 'ў' => 'Ў',
72644 'џ' => 'Џ',
72645 'ѡ' => 'Ѡ',
72646 'ѣ' => 'Ѣ',
72647 'ѥ' => 'Ѥ',
72648 'ѧ' => 'Ѧ',
72649 'ѩ' => 'Ѩ',
72650 'ѫ' => 'Ѫ',
72651 'ѭ' => 'Ѭ',
72652 'ѯ' => 'Ѯ',
72653 'ѱ' => 'Ѱ',
72654 'ѳ' => 'Ѳ',
72655 'ѵ' => 'Ѵ',
72656 'ѷ' => 'Ѷ',
72657 'ѹ' => 'Ѹ',
72658 'ѻ' => 'Ѻ',
72659 'ѽ' => 'Ѽ',
72660 'ѿ' => 'Ѿ',
72661 'ҁ' => 'Ҁ',
72662 'ҋ' => 'Ҋ',
72663 'ҍ' => 'Ҍ',
72664 'ҏ' => 'Ҏ',
72665 'ґ' => 'Ґ',
72666 'ғ' => 'Ғ',
72667 'ҕ' => 'Ҕ',
72668 'җ' => 'Җ',
72669 'ҙ' => 'Ҙ',
72670 'қ' => 'Қ',
72671 'ҝ' => 'Ҝ',
72672 'ҟ' => 'Ҟ',
72673 'ҡ' => 'Ҡ',
72674 'ң' => 'Ң',
72675 'ҥ' => 'Ҥ',
72676 'ҧ' => 'Ҧ',
72677 'ҩ' => 'Ҩ',
72678 'ҫ' => 'Ҫ',
72679 'ҭ' => 'Ҭ',
72680 'ү' => 'Ү',
72681 'ұ' => 'Ұ',
72682 'ҳ' => 'Ҳ',
72683 'ҵ' => 'Ҵ',
72684 'ҷ' => 'Ҷ',
72685 'ҹ' => 'Ҹ',
72686 'һ' => 'Һ',
72687 'ҽ' => 'Ҽ',
72688 'ҿ' => 'Ҿ',
72689 'ӂ' => 'Ӂ',
72690 'ӄ' => 'Ӄ',
72691 'ӆ' => 'Ӆ',
72692 'ӈ' => 'Ӈ',
72693 'ӊ' => 'Ӊ',
72694 'ӌ' => 'Ӌ',
72695 'ӎ' => 'Ӎ',
72696 'ӏ' => 'Ӏ',
72697 'ӑ' => 'Ӑ',
72698 'ӓ' => 'Ӓ',
72699 'ӕ' => 'Ӕ',
72700 'ӗ' => 'Ӗ',
72701 'ә' => 'Ә',
72702 'ӛ' => 'Ӛ',
72703 'ӝ' => 'Ӝ',
72704 'ӟ' => 'Ӟ',
72705 'ӡ' => 'Ӡ',
72706 'ӣ' => 'Ӣ',
72707 'ӥ' => 'Ӥ',
72708 'ӧ' => 'Ӧ',
72709 'ө' => 'Ө',
72710 'ӫ' => 'Ӫ',
72711 'ӭ' => 'Ӭ',
72712 'ӯ' => 'Ӯ',
72713 'ӱ' => 'Ӱ',
72714 'ӳ' => 'Ӳ',
72715 'ӵ' => 'Ӵ',
72716 'ӷ' => 'Ӷ',
72717 'ӹ' => 'Ӹ',
72718 'ӻ' => 'Ӻ',
72719 'ӽ' => 'Ӽ',
72720 'ӿ' => 'Ӿ',
72721 'ԁ' => 'Ԁ',
72722 'ԃ' => 'Ԃ',
72723 'ԅ' => 'Ԅ',
72724 'ԇ' => 'Ԇ',
72725 'ԉ' => 'Ԉ',
72726 'ԋ' => 'Ԋ',
72727 'ԍ' => 'Ԍ',
72728 'ԏ' => 'Ԏ',
72729 'ԑ' => 'Ԑ',
72730 'ԓ' => 'Ԓ',
72731 'ԕ' => 'Ԕ',
72732 'ԗ' => 'Ԗ',
72733 'ԙ' => 'Ԙ',
72734 'ԛ' => 'Ԛ',
72735 'ԝ' => 'Ԝ',
72736 'ԟ' => 'Ԟ',
72737 'ԡ' => 'Ԡ',
72738 'ԣ' => 'Ԣ',
72739 'ԥ' => 'Ԥ',
72740 'ԧ' => 'Ԧ',
72741 'ԩ' => 'Ԩ',
72742 'ԫ' => 'Ԫ',
72743 'ԭ' => 'Ԭ',
72744 'ԯ' => 'Ԯ',
72745 'ա' => 'Ա',
72746 'բ' => 'Բ',
72747 'գ' => 'Գ',
72748 'դ' => 'Դ',
72749 'ե' => 'Ե',
72750 'զ' => 'Զ',
72751 'է' => 'Է',
72752 'ը' => 'Ը',
72753 'թ' => 'Թ',
72754 'ժ' => 'Ժ',
72755 'ի' => 'Ի',
72756 'լ' => 'Լ',
72757 'խ' => 'Խ',
72758 'ծ' => 'Ծ',
72759 'կ' => 'Կ',
72760 'հ' => 'Հ',
72761 'ձ' => 'Ձ',
72762 'ղ' => 'Ղ',
72763 'ճ' => 'Ճ',
72764 'մ' => 'Մ',
72765 'յ' => 'Յ',
72766 'ն' => 'Ն',
72767 'շ' => 'Շ',
72768 'ո' => 'Ո',
72769 'չ' => 'Չ',
72770 'պ' => 'Պ',
72771 'ջ' => 'Ջ',
72772 'ռ' => 'Ռ',
72773 'ս' => 'Ս',
72774 'վ' => 'Վ',
72775 'տ' => 'Տ',
72776 'ր' => 'Ր',
72777 'ց' => 'Ց',
72778 'ւ' => 'Ւ',
72779 'փ' => 'Փ',
72780 'ք' => 'Ք',
72781 'օ' => 'Օ',
72782 'ֆ' => 'Ֆ',
72783 'ᵹ' => 'Ᵹ',
72784 'ᵽ' => 'Ᵽ',
72785 'ḁ' => 'Ḁ',
72786 'ḃ' => 'Ḃ',
72787 'ḅ' => 'Ḅ',
72788 'ḇ' => 'Ḇ',
72789 'ḉ' => 'Ḉ',
72790 'ḋ' => 'Ḋ',
72791 'ḍ' => 'Ḍ',
72792 'ḏ' => 'Ḏ',
72793 'ḑ' => 'Ḑ',
72794 'ḓ' => 'Ḓ',
72795 'ḕ' => 'Ḕ',
72796 'ḗ' => 'Ḗ',
72797 'ḙ' => 'Ḙ',
72798 'ḛ' => 'Ḛ',
72799 'ḝ' => 'Ḝ',
72800 'ḟ' => 'Ḟ',
72801 'ḡ' => 'Ḡ',
72802 'ḣ' => 'Ḣ',
72803 'ḥ' => 'Ḥ',
72804 'ḧ' => 'Ḧ',
72805 'ḩ' => 'Ḩ',
72806 'ḫ' => 'Ḫ',
72807 'ḭ' => 'Ḭ',
72808 'ḯ' => 'Ḯ',
72809 'ḱ' => 'Ḱ',
72810 'ḳ' => 'Ḳ',
72811 'ḵ' => 'Ḵ',
72812 'ḷ' => 'Ḷ',
72813 'ḹ' => 'Ḹ',
72814 'ḻ' => 'Ḻ',
72815 'ḽ' => 'Ḽ',
72816 'ḿ' => 'Ḿ',
72817 'ṁ' => 'Ṁ',
72818 'ṃ' => 'Ṃ',
72819 'ṅ' => 'Ṅ',
72820 'ṇ' => 'Ṇ',
72821 'ṉ' => 'Ṉ',
72822 'ṋ' => 'Ṋ',
72823 'ṍ' => 'Ṍ',
72824 'ṏ' => 'Ṏ',
72825 'ṑ' => 'Ṑ',
72826 'ṓ' => 'Ṓ',
72827 'ṕ' => 'Ṕ',
72828 'ṗ' => 'Ṗ',
72829 'ṙ' => 'Ṙ',
72830 'ṛ' => 'Ṛ',
72831 'ṝ' => 'Ṝ',
72832 'ṟ' => 'Ṟ',
72833 'ṡ' => 'Ṡ',
72834 'ṣ' => 'Ṣ',
72835 'ṥ' => 'Ṥ',
72836 'ṧ' => 'Ṧ',
72837 'ṩ' => 'Ṩ',
72838 'ṫ' => 'Ṫ',
72839 'ṭ' => 'Ṭ',
72840 'ṯ' => 'Ṯ',
72841 'ṱ' => 'Ṱ',
72842 'ṳ' => 'Ṳ',
72843 'ṵ' => 'Ṵ',
72844 'ṷ' => 'Ṷ',
72845 'ṹ' => 'Ṹ',
72846 'ṻ' => 'Ṻ',
72847 'ṽ' => 'Ṽ',
72848 'ṿ' => 'Ṿ',
72849 'ẁ' => 'Ẁ',
72850 'ẃ' => 'Ẃ',
72851 'ẅ' => 'Ẅ',
72852 'ẇ' => 'Ẇ',
72853 'ẉ' => 'Ẉ',
72854 'ẋ' => 'Ẋ',
72855 'ẍ' => 'Ẍ',
72856 'ẏ' => 'Ẏ',
72857 'ẑ' => 'Ẑ',
72858 'ẓ' => 'Ẓ',
72859 'ẕ' => 'Ẕ',
72860 'ẛ' => 'Ṡ',
72861 'ạ' => 'Ạ',
72862 'ả' => 'Ả',
72863 'ấ' => 'Ấ',
72864 'ầ' => 'Ầ',
72865 'ẩ' => 'Ẩ',
72866 'ẫ' => 'Ẫ',
72867 'ậ' => 'Ậ',
72868 'ắ' => 'Ắ',
72869 'ằ' => 'Ằ',
72870 'ẳ' => 'Ẳ',
72871 'ẵ' => 'Ẵ',
72872 'ặ' => 'Ặ',
72873 'ẹ' => 'Ẹ',
72874 'ẻ' => 'Ẻ',
72875 'ẽ' => 'Ẽ',
72876 'ế' => 'Ế',
72877 'ề' => 'Ề',
72878 'ể' => 'Ể',
72879 'ễ' => 'Ễ',
72880 'ệ' => 'Ệ',
72881 'ỉ' => 'Ỉ',
72882 'ị' => 'Ị',
72883 'ọ' => 'Ọ',
72884 'ỏ' => 'Ỏ',
72885 'ố' => 'Ố',
72886 'ồ' => 'Ồ',
72887 'ổ' => 'Ổ',
72888 'ỗ' => 'Ỗ',
72889 'ộ' => 'Ộ',
72890 'ớ' => 'Ớ',
72891 'ờ' => 'Ờ',
72892 'ở' => 'Ở',
72893 'ỡ' => 'Ỡ',
72894 'ợ' => 'Ợ',
72895 'ụ' => 'Ụ',
72896 'ủ' => 'Ủ',
72897 'ứ' => 'Ứ',
72898 'ừ' => 'Ừ',
72899 'ử' => 'Ử',
72900 'ữ' => 'Ữ',
72901 'ự' => 'Ự',
72902 'ỳ' => 'Ỳ',
72903 'ỵ' => 'Ỵ',
72904 'ỷ' => 'Ỷ',
72905 'ỹ' => 'Ỹ',
72906 'ỻ' => 'Ỻ',
72907 'ỽ' => 'Ỽ',
72908 'ỿ' => 'Ỿ',
72909 'ἀ' => 'Ἀ',
72910 'ἁ' => 'Ἁ',
72911 'ἂ' => 'Ἂ',
72912 'ἃ' => 'Ἃ',
72913 'ἄ' => 'Ἄ',
72914 'ἅ' => 'Ἅ',
72915 'ἆ' => 'Ἆ',
72916 'ἇ' => 'Ἇ',
72917 'ἐ' => 'Ἐ',
72918 'ἑ' => 'Ἑ',
72919 'ἒ' => 'Ἒ',
72920 'ἓ' => 'Ἓ',
72921 'ἔ' => 'Ἔ',
72922 'ἕ' => 'Ἕ',
72923 'ἠ' => 'Ἠ',
72924 'ἡ' => 'Ἡ',
72925 'ἢ' => 'Ἢ',
72926 'ἣ' => 'Ἣ',
72927 'ἤ' => 'Ἤ',
72928 'ἥ' => 'Ἥ',
72929 'ἦ' => 'Ἦ',
72930 'ἧ' => 'Ἧ',
72931 'ἰ' => 'Ἰ',
72932 'ἱ' => 'Ἱ',
72933 'ἲ' => 'Ἲ',
72934 'ἳ' => 'Ἳ',
72935 'ἴ' => 'Ἴ',
72936 'ἵ' => 'Ἵ',
72937 'ἶ' => 'Ἶ',
72938 'ἷ' => 'Ἷ',
72939 'ὀ' => 'Ὀ',
72940 'ὁ' => 'Ὁ',
72941 'ὂ' => 'Ὂ',
72942 'ὃ' => 'Ὃ',
72943 'ὄ' => 'Ὄ',
72944 'ὅ' => 'Ὅ',
72945 'ὑ' => 'Ὑ',
72946 'ὓ' => 'Ὓ',
72947 'ὕ' => 'Ὕ',
72948 'ὗ' => 'Ὗ',
72949 'ὠ' => 'Ὠ',
72950 'ὡ' => 'Ὡ',
72951 'ὢ' => 'Ὢ',
72952 'ὣ' => 'Ὣ',
72953 'ὤ' => 'Ὤ',
72954 'ὥ' => 'Ὥ',
72955 'ὦ' => 'Ὦ',
72956 'ὧ' => 'Ὧ',
72957 'ὰ' => 'Ὰ',
72958 'ά' => 'Ά',
72959 'ὲ' => 'Ὲ',
72960 'έ' => 'Έ',
72961 'ὴ' => 'Ὴ',
72962 'ή' => 'Ή',
72963 'ὶ' => 'Ὶ',
72964 'ί' => 'Ί',
72965 'ὸ' => 'Ὸ',
72966 'ό' => 'Ό',
72967 'ὺ' => 'Ὺ',
72968 'ύ' => 'Ύ',
72969 'ὼ' => 'Ὼ',
72970 'ώ' => 'Ώ',
72971 'ᾀ' => 'ᾈ',
72972 'ᾁ' => 'ᾉ',
72973 'ᾂ' => 'ᾊ',
72974 'ᾃ' => 'ᾋ',
72975 'ᾄ' => 'ᾌ',
72976 'ᾅ' => 'ᾍ',
72977 'ᾆ' => 'ᾎ',
72978 'ᾇ' => 'ᾏ',
72979 'ᾐ' => 'ᾘ',
72980 'ᾑ' => 'ᾙ',
72981 'ᾒ' => 'ᾚ',
72982 'ᾓ' => 'ᾛ',
72983 'ᾔ' => 'ᾜ',
72984 'ᾕ' => 'ᾝ',
72985 'ᾖ' => 'ᾞ',
72986 'ᾗ' => 'ᾟ',
72987 'ᾠ' => 'ᾨ',
72988 'ᾡ' => 'ᾩ',
72989 'ᾢ' => 'ᾪ',
72990 'ᾣ' => 'ᾫ',
72991 'ᾤ' => 'ᾬ',
72992 'ᾥ' => 'ᾭ',
72993 'ᾦ' => 'ᾮ',
72994 'ᾧ' => 'ᾯ',
72995 'ᾰ' => 'Ᾰ',
72996 'ᾱ' => 'Ᾱ',
72997 'ᾳ' => 'ᾼ',
72998 'ι' => 'Ι',
72999 'ῃ' => 'ῌ',
73000 'ῐ' => 'Ῐ',
73001 'ῑ' => 'Ῑ',
73002 'ῠ' => 'Ῠ',
73003 'ῡ' => 'Ῡ',
73004 'ῥ' => 'Ῥ',
73005 'ῳ' => 'ῼ',
73006 'ⅎ' => 'Ⅎ',
73007 'ⅰ' => 'Ⅰ',
73008 'ⅱ' => 'Ⅱ',
73009 'ⅲ' => 'Ⅲ',
73010 'ⅳ' => 'Ⅳ',
73011 'ⅴ' => 'Ⅴ',
73012 'ⅵ' => 'Ⅵ',
73013 'ⅶ' => 'Ⅶ',
73014 'ⅷ' => 'Ⅷ',
73015 'ⅸ' => 'Ⅸ',
73016 'ⅹ' => 'Ⅹ',
73017 'ⅺ' => 'Ⅺ',
73018 'ⅻ' => 'Ⅻ',
73019 'ⅼ' => 'Ⅼ',
73020 'ⅽ' => 'Ⅽ',
73021 'ⅾ' => 'Ⅾ',
73022 'ⅿ' => 'Ⅿ',
73023 'ↄ' => 'Ↄ',
73024 'ⓐ' => 'Ⓐ',
73025 'ⓑ' => 'Ⓑ',
73026 'ⓒ' => 'Ⓒ',
73027 'ⓓ' => 'Ⓓ',
73028 'ⓔ' => 'Ⓔ',
73029 'ⓕ' => 'Ⓕ',
73030 'ⓖ' => 'Ⓖ',
73031 'ⓗ' => 'Ⓗ',
73032 'ⓘ' => 'Ⓘ',
73033 'ⓙ' => 'Ⓙ',
73034 'ⓚ' => 'Ⓚ',
73035 'ⓛ' => 'Ⓛ',
73036 'ⓜ' => 'Ⓜ',
73037 'ⓝ' => 'Ⓝ',
73038 'ⓞ' => 'Ⓞ',
73039 'ⓟ' => 'Ⓟ',
73040 'ⓠ' => 'Ⓠ',
73041 'ⓡ' => 'Ⓡ',
73042 'ⓢ' => 'Ⓢ',
73043 'ⓣ' => 'Ⓣ',
73044 'ⓤ' => 'Ⓤ',
73045 'ⓥ' => 'Ⓥ',
73046 'ⓦ' => 'Ⓦ',
73047 'ⓧ' => 'Ⓧ',
73048 'ⓨ' => 'Ⓨ',
73049 'ⓩ' => 'Ⓩ',
73050 'ⰰ' => 'Ⰰ',
73051 'ⰱ' => 'Ⰱ',
73052 'ⰲ' => 'Ⰲ',
73053 'ⰳ' => 'Ⰳ',
73054 'ⰴ' => 'Ⰴ',
73055 'ⰵ' => 'Ⰵ',
73056 'ⰶ' => 'Ⰶ',
73057 'ⰷ' => 'Ⰷ',
73058 'ⰸ' => 'Ⰸ',
73059 'ⰹ' => 'Ⰹ',
73060 'ⰺ' => 'Ⰺ',
73061 'ⰻ' => 'Ⰻ',
73062 'ⰼ' => 'Ⰼ',
73063 'ⰽ' => 'Ⰽ',
73064 'ⰾ' => 'Ⰾ',
73065 'ⰿ' => 'Ⰿ',
73066 'ⱀ' => 'Ⱀ',
73067 'ⱁ' => 'Ⱁ',
73068 'ⱂ' => 'Ⱂ',
73069 'ⱃ' => 'Ⱃ',
73070 'ⱄ' => 'Ⱄ',
73071 'ⱅ' => 'Ⱅ',
73072 'ⱆ' => 'Ⱆ',
73073 'ⱇ' => 'Ⱇ',
73074 'ⱈ' => 'Ⱈ',
73075 'ⱉ' => 'Ⱉ',
73076 'ⱊ' => 'Ⱊ',
73077 'ⱋ' => 'Ⱋ',
73078 'ⱌ' => 'Ⱌ',
73079 'ⱍ' => 'Ⱍ',
73080 'ⱎ' => 'Ⱎ',
73081 'ⱏ' => 'Ⱏ',
73082 'ⱐ' => 'Ⱐ',
73083 'ⱑ' => 'Ⱑ',
73084 'ⱒ' => 'Ⱒ',
73085 'ⱓ' => 'Ⱓ',
73086 'ⱔ' => 'Ⱔ',
73087 'ⱕ' => 'Ⱕ',
73088 'ⱖ' => 'Ⱖ',
73089 'ⱗ' => 'Ⱗ',
73090 'ⱘ' => 'Ⱘ',
73091 'ⱙ' => 'Ⱙ',
73092 'ⱚ' => 'Ⱚ',
73093 'ⱛ' => 'Ⱛ',
73094 'ⱜ' => 'Ⱜ',
73095 'ⱝ' => 'Ⱝ',
73096 'ⱞ' => 'Ⱞ',
73097 'ⱡ' => 'Ⱡ',
73098 'ⱥ' => 'Ⱥ',
73099 'ⱦ' => 'Ⱦ',
73100 'ⱨ' => 'Ⱨ',
73101 'ⱪ' => 'Ⱪ',
73102 'ⱬ' => 'Ⱬ',
73103 'ⱳ' => 'Ⱳ',
73104 'ⱶ' => 'Ⱶ',
73105 'ⲁ' => 'Ⲁ',
73106 'ⲃ' => 'Ⲃ',
73107 'ⲅ' => 'Ⲅ',
73108 'ⲇ' => 'Ⲇ',
73109 'ⲉ' => 'Ⲉ',
73110 'ⲋ' => 'Ⲋ',
73111 'ⲍ' => 'Ⲍ',
73112 'ⲏ' => 'Ⲏ',
73113 'ⲑ' => 'Ⲑ',
73114 'ⲓ' => 'Ⲓ',
73115 'ⲕ' => 'Ⲕ',
73116 'ⲗ' => 'Ⲗ',
73117 'ⲙ' => 'Ⲙ',
73118 'ⲛ' => 'Ⲛ',
73119 'ⲝ' => 'Ⲝ',
73120 'ⲟ' => 'Ⲟ',
73121 'ⲡ' => 'Ⲡ',
73122 'ⲣ' => 'Ⲣ',
73123 'ⲥ' => 'Ⲥ',
73124 'ⲧ' => 'Ⲧ',
73125 'ⲩ' => 'Ⲩ',
73126 'ⲫ' => 'Ⲫ',
73127 'ⲭ' => 'Ⲭ',
73128 'ⲯ' => 'Ⲯ',
73129 'ⲱ' => 'Ⲱ',
73130 'ⲳ' => 'Ⲳ',
73131 'ⲵ' => 'Ⲵ',
73132 'ⲷ' => 'Ⲷ',
73133 'ⲹ' => 'Ⲹ',
73134 'ⲻ' => 'Ⲻ',
73135 'ⲽ' => 'Ⲽ',
73136 'ⲿ' => 'Ⲿ',
73137 'ⳁ' => 'Ⳁ',
73138 'ⳃ' => 'Ⳃ',
73139 'ⳅ' => 'Ⳅ',
73140 'ⳇ' => 'Ⳇ',
73141 'ⳉ' => 'Ⳉ',
73142 'ⳋ' => 'Ⳋ',
73143 'ⳍ' => 'Ⳍ',
73144 'ⳏ' => 'Ⳏ',
73145 'ⳑ' => 'Ⳑ',
73146 'ⳓ' => 'Ⳓ',
73147 'ⳕ' => 'Ⳕ',
73148 'ⳗ' => 'Ⳗ',
73149 'ⳙ' => 'Ⳙ',
73150 'ⳛ' => 'Ⳛ',
73151 'ⳝ' => 'Ⳝ',
73152 'ⳟ' => 'Ⳟ',
73153 'ⳡ' => 'Ⳡ',
73154 'ⳣ' => 'Ⳣ',
73155 'ⳬ' => 'Ⳬ',
73156 'ⳮ' => 'Ⳮ',
73157 'ⳳ' => 'Ⳳ',
73158 'ⴀ' => 'Ⴀ',
73159 'ⴁ' => 'Ⴁ',
73160 'ⴂ' => 'Ⴂ',
73161 'ⴃ' => 'Ⴃ',
73162 'ⴄ' => 'Ⴄ',
73163 'ⴅ' => 'Ⴅ',
73164 'ⴆ' => 'Ⴆ',
73165 'ⴇ' => 'Ⴇ',
73166 'ⴈ' => 'Ⴈ',
73167 'ⴉ' => 'Ⴉ',
73168 'ⴊ' => 'Ⴊ',
73169 'ⴋ' => 'Ⴋ',
73170 'ⴌ' => 'Ⴌ',
73171 'ⴍ' => 'Ⴍ',
73172 'ⴎ' => 'Ⴎ',
73173 'ⴏ' => 'Ⴏ',
73174 'ⴐ' => 'Ⴐ',
73175 'ⴑ' => 'Ⴑ',
73176 'ⴒ' => 'Ⴒ',
73177 'ⴓ' => 'Ⴓ',
73178 'ⴔ' => 'Ⴔ',
73179 'ⴕ' => 'Ⴕ',
73180 'ⴖ' => 'Ⴖ',
73181 'ⴗ' => 'Ⴗ',
73182 'ⴘ' => 'Ⴘ',
73183 'ⴙ' => 'Ⴙ',
73184 'ⴚ' => 'Ⴚ',
73185 'ⴛ' => 'Ⴛ',
73186 'ⴜ' => 'Ⴜ',
73187 'ⴝ' => 'Ⴝ',
73188 'ⴞ' => 'Ⴞ',
73189 'ⴟ' => 'Ⴟ',
73190 'ⴠ' => 'Ⴠ',
73191 'ⴡ' => 'Ⴡ',
73192 'ⴢ' => 'Ⴢ',
73193 'ⴣ' => 'Ⴣ',
73194 'ⴤ' => 'Ⴤ',
73195 'ⴥ' => 'Ⴥ',
73196 'ⴧ' => 'Ⴧ',
73197 'ⴭ' => 'Ⴭ',
73198 'ꙁ' => 'Ꙁ',
73199 'ꙃ' => 'Ꙃ',
73200 'ꙅ' => 'Ꙅ',
73201 'ꙇ' => 'Ꙇ',
73202 'ꙉ' => 'Ꙉ',
73203 'ꙋ' => 'Ꙋ',
73204 'ꙍ' => 'Ꙍ',
73205 'ꙏ' => 'Ꙏ',
73206 'ꙑ' => 'Ꙑ',
73207 'ꙓ' => 'Ꙓ',
73208 'ꙕ' => 'Ꙕ',
73209 'ꙗ' => 'Ꙗ',
73210 'ꙙ' => 'Ꙙ',
73211 'ꙛ' => 'Ꙛ',
73212 'ꙝ' => 'Ꙝ',
73213 'ꙟ' => 'Ꙟ',
73214 'ꙡ' => 'Ꙡ',
73215 'ꙣ' => 'Ꙣ',
73216 'ꙥ' => 'Ꙥ',
73217 'ꙧ' => 'Ꙧ',
73218 'ꙩ' => 'Ꙩ',
73219 'ꙫ' => 'Ꙫ',
73220 'ꙭ' => 'Ꙭ',
73221 'ꚁ' => 'Ꚁ',
73222 'ꚃ' => 'Ꚃ',
73223 'ꚅ' => 'Ꚅ',
73224 'ꚇ' => 'Ꚇ',
73225 'ꚉ' => 'Ꚉ',
73226 'ꚋ' => 'Ꚋ',
73227 'ꚍ' => 'Ꚍ',
73228 'ꚏ' => 'Ꚏ',
73229 'ꚑ' => 'Ꚑ',
73230 'ꚓ' => 'Ꚓ',
73231 'ꚕ' => 'Ꚕ',
73232 'ꚗ' => 'Ꚗ',
73233 'ꚙ' => 'Ꚙ',
73234 'ꚛ' => 'Ꚛ',
73235 'ꜣ' => 'Ꜣ',
73236 'ꜥ' => 'Ꜥ',
73237 'ꜧ' => 'Ꜧ',
73238 'ꜩ' => 'Ꜩ',
73239 'ꜫ' => 'Ꜫ',
73240 'ꜭ' => 'Ꜭ',
73241 'ꜯ' => 'Ꜯ',
73242 'ꜳ' => 'Ꜳ',
73243 'ꜵ' => 'Ꜵ',
73244 'ꜷ' => 'Ꜷ',
73245 'ꜹ' => 'Ꜹ',
73246 'ꜻ' => 'Ꜻ',
73247 'ꜽ' => 'Ꜽ',
73248 'ꜿ' => 'Ꜿ',
73249 'ꝁ' => 'Ꝁ',
73250 'ꝃ' => 'Ꝃ',
73251 'ꝅ' => 'Ꝅ',
73252 'ꝇ' => 'Ꝇ',
73253 'ꝉ' => 'Ꝉ',
73254 'ꝋ' => 'Ꝋ',
73255 'ꝍ' => 'Ꝍ',
73256 'ꝏ' => 'Ꝏ',
73257 'ꝑ' => 'Ꝑ',
73258 'ꝓ' => 'Ꝓ',
73259 'ꝕ' => 'Ꝕ',
73260 'ꝗ' => 'Ꝗ',
73261 'ꝙ' => 'Ꝙ',
73262 'ꝛ' => 'Ꝛ',
73263 'ꝝ' => 'Ꝝ',
73264 'ꝟ' => 'Ꝟ',
73265 'ꝡ' => 'Ꝡ',
73266 'ꝣ' => 'Ꝣ',
73267 'ꝥ' => 'Ꝥ',
73268 'ꝧ' => 'Ꝧ',
73269 'ꝩ' => 'Ꝩ',
73270 'ꝫ' => 'Ꝫ',
73271 'ꝭ' => 'Ꝭ',
73272 'ꝯ' => 'Ꝯ',
73273 'ꝺ' => 'Ꝺ',
73274 'ꝼ' => 'Ꝼ',
73275 'ꝿ' => 'Ꝿ',
73276 'ꞁ' => 'Ꞁ',
73277 'ꞃ' => 'Ꞃ',
73278 'ꞅ' => 'Ꞅ',
73279 'ꞇ' => 'Ꞇ',
73280 'ꞌ' => 'Ꞌ',
73281 'ꞑ' => 'Ꞑ',
73282 'ꞓ' => 'Ꞓ',
73283 'ꞗ' => 'Ꞗ',
73284 'ꞙ' => 'Ꞙ',
73285 'ꞛ' => 'Ꞛ',
73286 'ꞝ' => 'Ꞝ',
73287 'ꞟ' => 'Ꞟ',
73288 'ꞡ' => 'Ꞡ',
73289 'ꞣ' => 'Ꞣ',
73290 'ꞥ' => 'Ꞥ',
73291 'ꞧ' => 'Ꞧ',
73292 'ꞩ' => 'Ꞩ',
73293 'a' => 'A',
73294 'b' => 'B',
73295 'c' => 'C',
73296 'd' => 'D',
73297 'e' => 'E',
73298 'f' => 'F',
73299 'g' => 'G',
73300 'h' => 'H',
73301 'i' => 'I',
73302 'j' => 'J',
73303 'k' => 'K',
73304 'l' => 'L',
73305 'm' => 'M',
73306 'n' => 'N',
73307 'o' => 'O',
73308 'p' => 'P',
73309 'q' => 'Q',
73310 'r' => 'R',
73311 's' => 'S',
73312 't' => 'T',
73313 'u' => 'U',
73314 'v' => 'V',
73315 'w' => 'W',
73316 'x' => 'X',
73317 'y' => 'Y',
73318 'z' => 'Z',
73319 '𐐨' => '𐐀',
73320 '𐐩' => '𐐁',
73321 '𐐪' => '𐐂',
73322 '𐐫' => '𐐃',
73323 '𐐬' => '𐐄',
73324 '𐐭' => '𐐅',
73325 '𐐮' => '𐐆',
73326 '𐐯' => '𐐇',
73327 '𐐰' => '𐐈',
73328 '𐐱' => '𐐉',
73329 '𐐲' => '𐐊',
73330 '𐐳' => '𐐋',
73331 '𐐴' => '𐐌',
73332 '𐐵' => '𐐍',
73333 '𐐶' => '𐐎',
73334 '𐐷' => '𐐏',
73335 '𐐸' => '𐐐',
73336 '𐐹' => '𐐑',
73337 '𐐺' => '𐐒',
73338 '𐐻' => '𐐓',
73339 '𐐼' => '𐐔',
73340 '𐐽' => '𐐕',
73341 '𐐾' => '𐐖',
73342 '𐐿' => '𐐗',
73343 '𐑀' => '𐐘',
73344 '𐑁' => '𐐙',
73345 '𐑂' => '𐐚',
73346 '𐑃' => '𐐛',
73347 '𐑄' => '𐐜',
73348 '𐑅' => '𐐝',
73349 '𐑆' => '𐐞',
73350 '𐑇' => '𐐟',
73351 '𐑈' => '𐐠',
73352 '𐑉' => '𐐡',
73353 '𐑊' => '𐐢',
73354 '𐑋' => '𐐣',
73355 '𐑌' => '𐐤',
73356 '𐑍' => '𐐥',
73357 '𐑎' => '𐐦',
73358 '𐑏' => '𐐧',
73359 '𑣀' => '𑢠',
73360 '𑣁' => '𑢡',
73361 '𑣂' => '𑢢',
73362 '𑣃' => '𑢣',
73363 '𑣄' => '𑢤',
73364 '𑣅' => '𑢥',
73365 '𑣆' => '𑢦',
73366 '𑣇' => '𑢧',
73367 '𑣈' => '𑢨',
73368 '𑣉' => '𑢩',
73369 '𑣊' => '𑢪',
73370 '𑣋' => '𑢫',
73371 '𑣌' => '𑢬',
73372 '𑣍' => '𑢭',
73373 '𑣎' => '𑢮',
73374 '𑣏' => '𑢯',
73375 '𑣐' => '𑢰',
73376 '𑣑' => '𑢱',
73377 '𑣒' => '𑢲',
73378 '𑣓' => '𑢳',
73379 '𑣔' => '𑢴',
73380 '𑣕' => '𑢵',
73381 '𑣖' => '𑢶',
73382 '𑣗' => '𑢷',
73383 '𑣘' => '𑢸',
73384 '𑣙' => '𑢹',
73385 '𑣚' => '𑢺',
73386 '𑣛' => '𑢻',
73387 '𑣜' => '𑢼',
73388 '𑣝' => '𑢽',
73389 '𑣞' => '𑢾',
73390 '𑣟' => '𑢿',
73391 );
73392
73393 $result =& $data;
73394 unset($data);
73395
73396 return $result;
73397 <?php
73398
73399
73400
73401
73402
73403
73404
73405
73406
73407
73408 use Symfony\Polyfill\Mbstring as p;
73409
73410 if (!function_exists('mb_strlen')) {
73411 define('MB_CASE_UPPER', 0);
73412 define('MB_CASE_LOWER', 1);
73413 define('MB_CASE_TITLE', 2);
73414
73415 function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
73416 function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
73417 function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
73418 function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); }
73419 function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); }
73420 function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
73421 function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
73422 function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
73423 function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
73424 function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
73425 function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
73426 function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
73427 function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
73428 function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
73429 function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
73430 function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
73431 function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
73432 function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
73433 function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
73434 function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
73435 function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
73436 function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
73437 function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
73438 function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
73439 function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
73440 function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
73441 function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
73442 function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
73443 function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
73444 function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
73445 function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
73446 function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
73447 function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
73448 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); }
73449 }
73450 if (!function_exists('mb_chr')) {
73451 function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
73452 function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
73453 function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
73454 }
73455 <?php
73456
73457
73458
73459
73460
73461
73462
73463
73464
73465
73466 namespace Symfony\Component\Process\Exception;
73467
73468
73469
73470
73471
73472
73473 interface ExceptionInterface
73474 {
73475 }
73476 <?php
73477
73478
73479
73480
73481
73482
73483
73484
73485
73486
73487 namespace Symfony\Component\Process\Exception;
73488
73489
73490
73491
73492
73493
73494 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
73495 {
73496 }
73497 <?php
73498
73499
73500
73501
73502
73503
73504
73505
73506
73507
73508 namespace Symfony\Component\Process\Exception;
73509
73510
73511
73512
73513
73514
73515 class LogicException extends \LogicException implements ExceptionInterface
73516 {
73517 }
73518 <?php
73519
73520
73521
73522
73523
73524
73525
73526
73527
73528
73529 namespace Symfony\Component\Process\Exception;
73530
73531 use Symfony\Component\Process\Process;
73532
73533
73534
73535
73536
73537
73538 class ProcessFailedException extends RuntimeException
73539 {
73540 private $process;
73541
73542 public function __construct(Process $process)
73543 {
73544 if ($process->isSuccessful()) {
73545 throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
73546 }
73547
73548 $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
73549 $process->getCommandLine(),
73550 $process->getExitCode(),
73551 $process->getExitCodeText(),
73552 $process->getWorkingDirectory()
73553 );
73554
73555 if (!$process->isOutputDisabled()) {
73556 $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
73557 $process->getOutput(),
73558 $process->getErrorOutput()
73559 );
73560 }
73561
73562 parent::__construct($error);
73563
73564 $this->process = $process;
73565 }
73566
73567 public function getProcess()
73568 {
73569 return $this->process;
73570 }
73571 }
73572 <?php
73573
73574
73575
73576
73577
73578
73579
73580
73581
73582
73583 namespace Symfony\Component\Process\Exception;
73584
73585 use Symfony\Component\Process\Process;
73586
73587
73588
73589
73590
73591
73592 class ProcessTimedOutException extends RuntimeException
73593 {
73594 const TYPE_GENERAL = 1;
73595 const TYPE_IDLE = 2;
73596
73597 private $process;
73598 private $timeoutType;
73599
73600 public function __construct(Process $process, $timeoutType)
73601 {
73602 $this->process = $process;
73603 $this->timeoutType = $timeoutType;
73604
73605 parent::__construct(sprintf(
73606 'The process "%s" exceeded the timeout of %s seconds.',
73607 $process->getCommandLine(),
73608 $this->getExceededTimeout()
73609 ));
73610 }
73611
73612 public function getProcess()
73613 {
73614 return $this->process;
73615 }
73616
73617 public function isGeneralTimeout()
73618 {
73619 return self::TYPE_GENERAL === $this->timeoutType;
73620 }
73621
73622 public function isIdleTimeout()
73623 {
73624 return self::TYPE_IDLE === $this->timeoutType;
73625 }
73626
73627 public function getExceededTimeout()
73628 {
73629 switch ($this->timeoutType) {
73630 case self::TYPE_GENERAL:
73631 return $this->process->getTimeout();
73632
73633 case self::TYPE_IDLE:
73634 return $this->process->getIdleTimeout();
73635
73636 default:
73637 throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
73638 }
73639 }
73640 }
73641 <?php
73642
73643
73644
73645
73646
73647
73648
73649
73650
73651
73652 namespace Symfony\Component\Process\Exception;
73653
73654
73655
73656
73657
73658
73659 class RuntimeException extends \RuntimeException implements ExceptionInterface
73660 {
73661 }
73662 <?php
73663
73664
73665
73666
73667
73668
73669
73670
73671
73672
73673 namespace Symfony\Component\Process;
73674
73675
73676
73677
73678
73679
73680
73681 class ExecutableFinder
73682 {
73683 private $suffixes = array('.exe', '.bat', '.cmd', '.com');
73684
73685
73686
73687
73688 public function setSuffixes(array $suffixes)
73689 {
73690 $this->suffixes = $suffixes;
73691 }
73692
73693
73694
73695
73696
73697
73698 public function addSuffix($suffix)
73699 {
73700 $this->suffixes[] = $suffix;
73701 }
73702
73703
73704
73705
73706
73707
73708
73709
73710
73711
73712 public function find($name, $default = null, array $extraDirs = array())
73713 {
73714 if (ini_get('open_basedir')) {
73715 $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
73716 $dirs = array();
73717 foreach ($searchPath as $path) {
73718
73719  if (@is_dir($path)) {
73720 $dirs[] = $path;
73721 } else {
73722 if (basename($path) == $name && @is_executable($path)) {
73723 return $path;
73724 }
73725 }
73726 }
73727 } else {
73728 $dirs = array_merge(
73729 explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
73730 $extraDirs
73731 );
73732 }
73733
73734 $suffixes = array('');
73735 if ('\\' === DIRECTORY_SEPARATOR) {
73736 $pathExt = getenv('PATHEXT');
73737 $suffixes = array_merge($pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
73738 }
73739 foreach ($suffixes as $suffix) {
73740 foreach ($dirs as $dir) {
73741 if (@is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || @is_executable($file))) {
73742 return $file;
73743 }
73744 }
73745 }
73746
73747 return $default;
73748 }
73749 }
73750 Copyright (c) 2004-2018 Fabien Potencier
73751
73752 Permission is hereby granted, free of charge, to any person obtaining a copy
73753 of this software and associated documentation files (the "Software"), to deal
73754 in the Software without restriction, including without limitation the rights
73755 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
73756 copies of the Software, and to permit persons to whom the Software is furnished
73757 to do so, subject to the following conditions:
73758
73759 The above copyright notice and this permission notice shall be included in all
73760 copies or substantial portions of the Software.
73761
73762 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73763 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
73764 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
73765 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
73766 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
73767 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
73768 THE SOFTWARE.
73769 <?php
73770
73771
73772
73773
73774
73775
73776
73777
73778
73779
73780 namespace Symfony\Component\Process;
73781
73782
73783
73784
73785
73786
73787
73788 class PhpExecutableFinder
73789 {
73790 private $executableFinder;
73791
73792 public function __construct()
73793 {
73794 $this->executableFinder = new ExecutableFinder();
73795 }
73796
73797
73798
73799
73800
73801
73802
73803
73804 public function find($includeArgs = true)
73805 {
73806 $args = $this->findArguments();
73807 $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
73808
73809
73810  if (defined('HHVM_VERSION')) {
73811 return (getenv('PHP_BINARY') ?: PHP_BINARY).$args;
73812 }
73813
73814
73815  if (defined('PHP_BINARY') && PHP_BINARY && \in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg'), true)) {
73816 return PHP_BINARY.$args;
73817 }
73818
73819 if ($php = getenv('PHP_PATH')) {
73820 if (!@is_executable($php)) {
73821 return false;
73822 }
73823
73824 return $php;
73825 }
73826
73827 if ($php = getenv('PHP_PEAR_PHP_BIN')) {
73828 if (@is_executable($php)) {
73829 return $php;
73830 }
73831 }
73832
73833 if (@is_executable($php = PHP_BINDIR.('\\' === DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
73834 return $php;
73835 }
73836
73837 $dirs = array(PHP_BINDIR);
73838 if ('\\' === DIRECTORY_SEPARATOR) {
73839 $dirs[] = 'C:\xampp\php\\';
73840 }
73841
73842 return $this->executableFinder->find('php', false, $dirs);
73843 }
73844
73845
73846
73847
73848
73849
73850 public function findArguments()
73851 {
73852 $arguments = array();
73853
73854 if (defined('HHVM_VERSION')) {
73855 $arguments[] = '--php';
73856 } elseif ('phpdbg' === PHP_SAPI) {
73857 $arguments[] = '-qrr';
73858 }
73859
73860 return $arguments;
73861 }
73862 }
73863 <?php
73864
73865
73866
73867
73868
73869
73870
73871
73872
73873
73874 namespace Symfony\Component\Process;
73875
73876 use Symfony\Component\Process\Exception\RuntimeException;
73877
73878
73879
73880
73881
73882
73883
73884
73885
73886
73887 class PhpProcess extends Process
73888 {
73889
73890
73891
73892
73893
73894
73895
73896 public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = array())
73897 {
73898 $executableFinder = new PhpExecutableFinder();
73899 if (false === $php = $executableFinder->find()) {
73900 $php = null;
73901 }
73902 if ('phpdbg' === PHP_SAPI) {
73903 $file = tempnam(sys_get_temp_dir(), 'dbg');
73904 file_put_contents($file, $script);
73905 register_shutdown_function('unlink', $file);
73906 $php .= ' '.ProcessUtils::escapeArgument($file);
73907 $script = null;
73908 }
73909 if ('\\' !== DIRECTORY_SEPARATOR && null !== $php) {
73910
73911  
73912  
73913  $php = 'exec '.$php;
73914 }
73915
73916 parent::__construct($php, $cwd, $env, $script, $timeout, $options);
73917 }
73918
73919
73920
73921
73922 public function setPhpBinary($php)
73923 {
73924 $this->setCommandLine($php);
73925 }
73926
73927
73928
73929
73930 public function start($callback = null)
73931 {
73932 if (null === $this->getCommandLine()) {
73933 throw new RuntimeException('Unable to find the PHP executable.');
73934 }
73935
73936 parent::start($callback);
73937 }
73938 }
73939 <?php
73940
73941
73942
73943
73944
73945
73946
73947
73948
73949
73950 namespace Symfony\Component\Process\Pipes;
73951
73952
73953
73954
73955
73956
73957 abstract class AbstractPipes implements PipesInterface
73958 {
73959 public $pipes = array();
73960
73961 private $inputBuffer = '';
73962 private $input;
73963 private $blocked = true;
73964 private $lastError;
73965
73966
73967
73968
73969 public function __construct($input)
73970 {
73971 if (is_resource($input)) {
73972 $this->input = $input;
73973 } elseif (is_string($input)) {
73974 $this->inputBuffer = $input;
73975 } else {
73976 $this->inputBuffer = (string) $input;
73977 }
73978 }
73979
73980
73981
73982
73983 public function close()
73984 {
73985 foreach ($this->pipes as $pipe) {
73986 fclose($pipe);
73987 }
73988 $this->pipes = array();
73989 }
73990
73991
73992
73993
73994
73995
73996 protected function hasSystemCallBeenInterrupted()
73997 {
73998 $lastError = $this->lastError;
73999 $this->lastError = null;
74000
74001
74002  return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
74003 }
74004
74005
74006
74007
74008 protected function unblock()
74009 {
74010 if (!$this->blocked) {
74011 return;
74012 }
74013
74014 foreach ($this->pipes as $pipe) {
74015 stream_set_blocking($pipe, 0);
74016 }
74017 if (null !== $this->input) {
74018 stream_set_blocking($this->input, 0);
74019 }
74020
74021 $this->blocked = false;
74022 }
74023
74024
74025
74026
74027 protected function write()
74028 {
74029 if (!isset($this->pipes[0])) {
74030 return;
74031 }
74032 $input = $this->input;
74033 $r = $e = array();
74034 $w = array($this->pipes[0]);
74035
74036
74037  if (false === @stream_select($r, $w, $e, 0, 0)) {
74038 return;
74039 }
74040
74041 foreach ($w as $stdin) {
74042 if (isset($this->inputBuffer[0])) {
74043 $written = fwrite($stdin, $this->inputBuffer);
74044 $this->inputBuffer = substr($this->inputBuffer, $written);
74045 if (isset($this->inputBuffer[0])) {
74046 return array($this->pipes[0]);
74047 }
74048 }
74049
74050 if ($input) {
74051 for (;;) {
74052 $data = fread($input, self::CHUNK_SIZE);
74053 if (!isset($data[0])) {
74054 break;
74055 }
74056 $written = fwrite($stdin, $data);
74057 $data = substr($data, $written);
74058 if (isset($data[0])) {
74059 $this->inputBuffer = $data;
74060
74061 return array($this->pipes[0]);
74062 }
74063 }
74064 if (feof($input)) {
74065
74066  
74067  $this->input = null;
74068 }
74069 }
74070 }
74071
74072
74073  if (null === $this->input && !isset($this->inputBuffer[0])) {
74074 fclose($this->pipes[0]);
74075 unset($this->pipes[0]);
74076 } elseif (!$w) {
74077 return array($this->pipes[0]);
74078 }
74079 }
74080
74081
74082
74083
74084 public function handleError($type, $msg)
74085 {
74086 $this->lastError = $msg;
74087 }
74088 }
74089 <?php
74090
74091
74092
74093
74094
74095
74096
74097
74098
74099
74100 namespace Symfony\Component\Process\Pipes;
74101
74102
74103
74104
74105
74106
74107
74108
74109 interface PipesInterface
74110 {
74111 const CHUNK_SIZE = 16384;
74112
74113
74114
74115
74116
74117
74118 public function getDescriptors();
74119
74120
74121
74122
74123
74124
74125 public function getFiles();
74126
74127
74128
74129
74130
74131
74132
74133
74134
74135 public function readAndWrite($blocking, $close = false);
74136
74137
74138
74139
74140
74141
74142 public function areOpen();
74143
74144
74145
74146
74147 public function close();
74148 }
74149 <?php
74150
74151
74152
74153
74154
74155
74156
74157
74158
74159
74160 namespace Symfony\Component\Process\Pipes;
74161
74162 use Symfony\Component\Process\Process;
74163
74164
74165
74166
74167
74168
74169
74170
74171 class UnixPipes extends AbstractPipes
74172 {
74173 private $ttyMode;
74174 private $ptyMode;
74175 private $disableOutput;
74176
74177 public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
74178 {
74179 $this->ttyMode = (bool) $ttyMode;
74180 $this->ptyMode = (bool) $ptyMode;
74181 $this->disableOutput = (bool) $disableOutput;
74182
74183 parent::__construct($input);
74184 }
74185
74186 public function __destruct()
74187 {
74188 $this->close();
74189 }
74190
74191
74192
74193
74194 public function getDescriptors()
74195 {
74196 if ($this->disableOutput) {
74197 $nullstream = fopen('/dev/null', 'c');
74198
74199 return array(
74200 array('pipe', 'r'),
74201 $nullstream,
74202 $nullstream,
74203 );
74204 }
74205
74206 if ($this->ttyMode) {
74207 return array(
74208 array('file', '/dev/tty', 'r'),
74209 array('file', '/dev/tty', 'w'),
74210 array('file', '/dev/tty', 'w'),
74211 );
74212 }
74213
74214 if ($this->ptyMode && Process::isPtySupported()) {
74215 return array(
74216 array('pty'),
74217 array('pty'),
74218 array('pty'),
74219 );
74220 }
74221
74222 return array(
74223 array('pipe', 'r'),
74224 array('pipe', 'w'), 
74225  array('pipe', 'w'), 
74226  );
74227 }
74228
74229
74230
74231
74232 public function getFiles()
74233 {
74234 return array();
74235 }
74236
74237
74238
74239
74240 public function readAndWrite($blocking, $close = false)
74241 {
74242 $this->unblock();
74243 $w = $this->write();
74244
74245 $read = $e = array();
74246 $r = $this->pipes;
74247 unset($r[0]);
74248
74249
74250  set_error_handler(array($this, 'handleError'));
74251 if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
74252 restore_error_handler();
74253
74254  
74255  if (!$this->hasSystemCallBeenInterrupted()) {
74256 $this->pipes = array();
74257 }
74258
74259 return $read;
74260 }
74261 restore_error_handler();
74262
74263 foreach ($r as $pipe) {
74264
74265  
74266  $read[$type = array_search($pipe, $this->pipes, true)] = '';
74267
74268 do {
74269 $data = fread($pipe, self::CHUNK_SIZE);
74270 $read[$type] .= $data;
74271 } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
74272
74273 if (!isset($read[$type][0])) {
74274 unset($read[$type]);
74275 }
74276
74277 if ($close && feof($pipe)) {
74278 fclose($pipe);
74279 unset($this->pipes[$type]);
74280 }
74281 }
74282
74283 return $read;
74284 }
74285
74286
74287
74288
74289 public function areOpen()
74290 {
74291 return (bool) $this->pipes;
74292 }
74293
74294
74295
74296
74297
74298
74299
74300
74301
74302 public static function create(Process $process, $input)
74303 {
74304 return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
74305 }
74306 }
74307 <?php
74308
74309
74310
74311
74312
74313
74314
74315
74316
74317
74318 namespace Symfony\Component\Process\Pipes;
74319
74320 use Symfony\Component\Process\Process;
74321 use Symfony\Component\Process\Exception\RuntimeException;
74322
74323
74324
74325
74326
74327
74328
74329
74330
74331
74332
74333 class WindowsPipes extends AbstractPipes
74334 {
74335 private $files = array();
74336 private $fileHandles = array();
74337 private $readBytes = array(
74338 Process::STDOUT => 0,
74339 Process::STDERR => 0,
74340 );
74341 private $disableOutput;
74342
74343 public function __construct($disableOutput, $input)
74344 {
74345 $this->disableOutput = (bool) $disableOutput;
74346
74347 if (!$this->disableOutput) {
74348
74349  
74350  
74351  
74352  $pipes = array(
74353 Process::STDOUT => Process::OUT,
74354 Process::STDERR => Process::ERR,
74355 );
74356 $tmpCheck = false;
74357 $tmpDir = sys_get_temp_dir();
74358 $lastError = 'unknown reason';
74359 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
74360 for ($i = 0;; ++$i) {
74361 foreach ($pipes as $pipe => $name) {
74362 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
74363 if (file_exists($file) && !unlink($file)) {
74364 continue 2;
74365 }
74366 $h = fopen($file, 'xb');
74367 if (!$h) {
74368 $error = $lastError;
74369 if ($tmpCheck || $tmpCheck = unlink(tempnam(false, 'sf_check_'))) {
74370 continue;
74371 }
74372 restore_error_handler();
74373 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error));
74374 }
74375 if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) {
74376 continue 2;
74377 }
74378 if (isset($this->files[$pipe])) {
74379 unlink($this->files[$pipe]);
74380 }
74381 $this->files[$pipe] = $file;
74382 }
74383 break;
74384 }
74385 restore_error_handler();
74386 }
74387
74388 parent::__construct($input);
74389 }
74390
74391 public function __destruct()
74392 {
74393 $this->close();
74394 $this->removeFiles();
74395 }
74396
74397
74398
74399
74400 public function getDescriptors()
74401 {
74402 if ($this->disableOutput) {
74403 $nullstream = fopen('NUL', 'c');
74404
74405 return array(
74406 array('pipe', 'r'),
74407 $nullstream,
74408 $nullstream,
74409 );
74410 }
74411
74412
74413  
74414  
74415  return array(
74416 array('pipe', 'r'),
74417 array('file', 'NUL', 'w'),
74418 array('file', 'NUL', 'w'),
74419 );
74420 }
74421
74422
74423
74424
74425 public function getFiles()
74426 {
74427 return $this->files;
74428 }
74429
74430
74431
74432
74433 public function readAndWrite($blocking, $close = false)
74434 {
74435 $this->unblock();
74436 $w = $this->write();
74437 $read = $r = $e = array();
74438
74439 if ($blocking) {
74440 if ($w) {
74441 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
74442 } elseif ($this->fileHandles) {
74443 usleep(Process::TIMEOUT_PRECISION * 1E6);
74444 }
74445 }
74446 foreach ($this->fileHandles as $type => $fileHandle) {
74447 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
74448
74449 if (isset($data[0])) {
74450 $this->readBytes[$type] += strlen($data);
74451 $read[$type] = $data;
74452 }
74453 if ($close) {
74454 fclose($fileHandle);
74455 unset($this->fileHandles[$type]);
74456 }
74457 }
74458
74459 return $read;
74460 }
74461
74462
74463
74464
74465 public function areOpen()
74466 {
74467 return $this->pipes && $this->fileHandles;
74468 }
74469
74470
74471
74472
74473 public function close()
74474 {
74475 parent::close();
74476 foreach ($this->fileHandles as $handle) {
74477 fclose($handle);
74478 }
74479 $this->fileHandles = array();
74480 }
74481
74482
74483
74484
74485
74486
74487
74488
74489
74490 public static function create(Process $process, $input)
74491 {
74492 return new static($process->isOutputDisabled(), $input);
74493 }
74494
74495
74496
74497
74498 private function removeFiles()
74499 {
74500 foreach ($this->files as $filename) {
74501 if (file_exists($filename)) {
74502 @unlink($filename);
74503 }
74504 }
74505 $this->files = array();
74506 }
74507 }
74508 <?php
74509
74510
74511
74512
74513
74514
74515
74516
74517
74518
74519 namespace Symfony\Component\Process;
74520
74521 use Symfony\Component\Process\Exception\InvalidArgumentException;
74522 use Symfony\Component\Process\Exception\LogicException;
74523 use Symfony\Component\Process\Exception\ProcessFailedException;
74524 use Symfony\Component\Process\Exception\ProcessTimedOutException;
74525 use Symfony\Component\Process\Exception\RuntimeException;
74526 use Symfony\Component\Process\Pipes\PipesInterface;
74527 use Symfony\Component\Process\Pipes\UnixPipes;
74528 use Symfony\Component\Process\Pipes\WindowsPipes;
74529
74530
74531
74532
74533
74534
74535
74536
74537 class Process
74538 {
74539 const ERR = 'err';
74540 const OUT = 'out';
74541
74542 const STATUS_READY = 'ready';
74543 const STATUS_STARTED = 'started';
74544 const STATUS_TERMINATED = 'terminated';
74545
74546 const STDIN = 0;
74547 const STDOUT = 1;
74548 const STDERR = 2;
74549
74550
74551  const TIMEOUT_PRECISION = 0.2;
74552
74553 private $callback;
74554 private $commandline;
74555 private $cwd;
74556 private $env;
74557 private $input;
74558 private $starttime;
74559 private $lastOutputTime;
74560 private $timeout;
74561 private $idleTimeout;
74562 private $options;
74563 private $exitcode;
74564 private $fallbackStatus = array();
74565 private $processInformation;
74566 private $outputDisabled = false;
74567 private $stdout;
74568 private $stderr;
74569 private $enhanceWindowsCompatibility = true;
74570 private $enhanceSigchildCompatibility;
74571 private $process;
74572 private $status = self::STATUS_READY;
74573 private $incrementalOutputOffset = 0;
74574 private $incrementalErrorOutputOffset = 0;
74575 private $tty;
74576 private $pty;
74577
74578 private $useFileHandles = false;
74579
74580 private $processPipes;
74581
74582 private $latestSignal;
74583
74584 private static $sigchild;
74585
74586
74587
74588
74589
74590
74591 public static $exitCodes = array(
74592 0 => 'OK',
74593 1 => 'General error',
74594 2 => 'Misuse of shell builtins',
74595
74596 126 => 'Invoked command cannot execute',
74597 127 => 'Command not found',
74598 128 => 'Invalid exit argument',
74599
74600
74601  129 => 'Hangup',
74602 130 => 'Interrupt',
74603 131 => 'Quit and dump core',
74604 132 => 'Illegal instruction',
74605 133 => 'Trace/breakpoint trap',
74606 134 => 'Process aborted',
74607 135 => 'Bus error: "access to undefined portion of memory object"',
74608 136 => 'Floating point exception: "erroneous arithmetic operation"',
74609 137 => 'Kill (terminate immediately)',
74610 138 => 'User-defined 1',
74611 139 => 'Segmentation violation',
74612 140 => 'User-defined 2',
74613 141 => 'Write to pipe with no one reading',
74614 142 => 'Signal raised by alarm',
74615 143 => 'Termination (request to terminate)',
74616
74617  145 => 'Child process terminated, stopped (or continued*)',
74618 146 => 'Continue if stopped',
74619 147 => 'Stop executing temporarily',
74620 148 => 'Terminal stop signal',
74621 149 => 'Background process attempting to read from tty ("in")',
74622 150 => 'Background process attempting to write to tty ("out")',
74623 151 => 'Urgent data available on socket',
74624 152 => 'CPU time limit exceeded',
74625 153 => 'File size limit exceeded',
74626 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
74627 155 => 'Profiling timer expired',
74628
74629  157 => 'Pollable event',
74630
74631  159 => 'Bad syscall',
74632 );
74633
74634
74635
74636
74637
74638
74639
74640
74641
74642
74643
74644 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
74645 {
74646 if (!function_exists('proc_open')) {
74647 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
74648 }
74649
74650 $this->commandline = $commandline;
74651 $this->cwd = $cwd;
74652
74653
74654  
74655  
74656  
74657  if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || '\\' === DIRECTORY_SEPARATOR)) {
74658 $this->cwd = getcwd();
74659 }
74660 if (null !== $env) {
74661 $this->setEnv($env);
74662 }
74663
74664 $this->setInput($input);
74665 $this->setTimeout($timeout);
74666 $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR;
74667 $this->pty = false;
74668 $this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
74669 $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
74670 }
74671
74672 public function __destruct()
74673 {
74674 $this->stop(0);
74675 }
74676
74677 public function __clone()
74678 {
74679 $this->resetProcessData();
74680 }
74681
74682
74683
74684
74685
74686
74687
74688
74689
74690
74691
74692
74693
74694
74695
74696
74697
74698
74699
74700
74701 public function run($callback = null)
74702 {
74703 $this->start($callback);
74704
74705 return $this->wait();
74706 }
74707
74708
74709
74710
74711
74712
74713
74714
74715
74716
74717
74718
74719
74720
74721 public function mustRun($callback = null)
74722 {
74723 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
74724 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
74725 }
74726
74727 if (0 !== $this->run($callback)) {
74728 throw new ProcessFailedException($this);
74729 }
74730
74731 return $this;
74732 }
74733
74734
74735
74736
74737
74738
74739
74740
74741
74742
74743
74744
74745
74746
74747
74748
74749
74750
74751
74752
74753 public function start($callback = null)
74754 {
74755 if ($this->isRunning()) {
74756 throw new RuntimeException('Process is already running');
74757 }
74758 if ($this->outputDisabled && null !== $callback) {
74759 throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
74760 }
74761
74762 $this->resetProcessData();
74763 $this->starttime = $this->lastOutputTime = microtime(true);
74764 $this->callback = $this->buildCallback($callback);
74765 $descriptors = $this->getDescriptors();
74766
74767 $commandline = $this->commandline;
74768
74769 if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
74770 $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')';
74771 foreach ($this->processPipes->getFiles() as $offset => $filename) {
74772 $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
74773 }
74774 $commandline .= '"';
74775
74776 if (!isset($this->options['bypass_shell'])) {
74777 $this->options['bypass_shell'] = true;
74778 }
74779 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
74780
74781  $descriptors[3] = array('pipe', 'w');
74782
74783
74784  $commandline = '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
74785 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
74786
74787
74788  
74789  $ptsWorkaround = fopen(__FILE__, 'r');
74790 }
74791
74792 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
74793
74794 if (!is_resource($this->process)) {
74795 throw new RuntimeException('Unable to launch a new process.');
74796 }
74797 $this->status = self::STATUS_STARTED;
74798
74799 if (isset($descriptors[3])) {
74800 $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
74801 }
74802
74803 if ($this->tty) {
74804 return;
74805 }
74806
74807 $this->updateStatus(false);
74808 $this->checkTimeout();
74809 }
74810
74811
74812
74813
74814
74815
74816
74817
74818
74819
74820
74821
74822
74823
74824
74825
74826 public function restart($callback = null)
74827 {
74828 if ($this->isRunning()) {
74829 throw new RuntimeException('Process is already running');
74830 }
74831
74832 $process = clone $this;
74833 $process->start($callback);
74834
74835 return $process;
74836 }
74837
74838
74839
74840
74841
74842
74843
74844
74845
74846
74847
74848
74849
74850
74851
74852
74853 public function wait($callback = null)
74854 {
74855 $this->requireProcessIsStarted(__FUNCTION__);
74856
74857 $this->updateStatus(false);
74858 if (null !== $callback) {
74859 $this->callback = $this->buildCallback($callback);
74860 }
74861
74862 do {
74863 $this->checkTimeout();
74864 $running = '\\' === DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
74865 $this->readPipes($running, '\\' !== DIRECTORY_SEPARATOR || !$running);
74866 } while ($running);
74867
74868 while ($this->isRunning()) {
74869 usleep(1000);
74870 }
74871
74872 if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
74873 throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
74874 }
74875
74876 return $this->exitcode;
74877 }
74878
74879
74880
74881
74882
74883
74884 public function getPid()
74885 {
74886 return $this->isRunning() ? $this->processInformation['pid'] : null;
74887 }
74888
74889
74890
74891
74892
74893
74894
74895
74896
74897
74898
74899
74900 public function signal($signal)
74901 {
74902 $this->doSignal($signal, true);
74903
74904 return $this;
74905 }
74906
74907
74908
74909
74910
74911
74912
74913
74914
74915 public function disableOutput()
74916 {
74917 if ($this->isRunning()) {
74918 throw new RuntimeException('Disabling output while the process is running is not possible.');
74919 }
74920 if (null !== $this->idleTimeout) {
74921 throw new LogicException('Output can not be disabled while an idle timeout is set.');
74922 }
74923
74924 $this->outputDisabled = true;
74925
74926 return $this;
74927 }
74928
74929
74930
74931
74932
74933
74934
74935
74936 public function enableOutput()
74937 {
74938 if ($this->isRunning()) {
74939 throw new RuntimeException('Enabling output while the process is running is not possible.');
74940 }
74941
74942 $this->outputDisabled = false;
74943
74944 return $this;
74945 }
74946
74947
74948
74949
74950
74951
74952 public function isOutputDisabled()
74953 {
74954 return $this->outputDisabled;
74955 }
74956
74957
74958
74959
74960
74961
74962
74963
74964
74965 public function getOutput()
74966 {
74967 $this->readPipesForOutput(__FUNCTION__);
74968
74969 if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
74970 return '';
74971 }
74972
74973 return $ret;
74974 }
74975
74976
74977
74978
74979
74980
74981
74982
74983
74984
74985
74986
74987 public function getIncrementalOutput()
74988 {
74989 $this->readPipesForOutput(__FUNCTION__);
74990
74991 $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
74992 $this->incrementalOutputOffset = ftell($this->stdout);
74993
74994 if (false === $latest) {
74995 return '';
74996 }
74997
74998 return $latest;
74999 }
75000
75001
75002
75003
75004
75005
75006 public function clearOutput()
75007 {
75008 ftruncate($this->stdout, 0);
75009 fseek($this->stdout, 0);
75010 $this->incrementalOutputOffset = 0;
75011
75012 return $this;
75013 }
75014
75015
75016
75017
75018
75019
75020
75021
75022
75023 public function getErrorOutput()
75024 {
75025 $this->readPipesForOutput(__FUNCTION__);
75026
75027 if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
75028 return '';
75029 }
75030
75031 return $ret;
75032 }
75033
75034
75035
75036
75037
75038
75039
75040
75041
75042
75043
75044
75045
75046 public function getIncrementalErrorOutput()
75047 {
75048 $this->readPipesForOutput(__FUNCTION__);
75049
75050 $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
75051 $this->incrementalErrorOutputOffset = ftell($this->stderr);
75052
75053 if (false === $latest) {
75054 return '';
75055 }
75056
75057 return $latest;
75058 }
75059
75060
75061
75062
75063
75064
75065 public function clearErrorOutput()
75066 {
75067 ftruncate($this->stderr, 0);
75068 fseek($this->stderr, 0);
75069 $this->incrementalErrorOutputOffset = 0;
75070
75071 return $this;
75072 }
75073
75074
75075
75076
75077
75078
75079
75080
75081 public function getExitCode()
75082 {
75083 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
75084 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
75085 }
75086
75087 $this->updateStatus(false);
75088
75089 return $this->exitcode;
75090 }
75091
75092
75093
75094
75095
75096
75097
75098
75099
75100
75101
75102
75103 public function getExitCodeText()
75104 {
75105 if (null === $exitcode = $this->getExitCode()) {
75106 return;
75107 }
75108
75109 return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
75110 }
75111
75112
75113
75114
75115
75116
75117 public function isSuccessful()
75118 {
75119 return 0 === $this->getExitCode();
75120 }
75121
75122
75123
75124
75125
75126
75127
75128
75129
75130
75131
75132 public function hasBeenSignaled()
75133 {
75134 $this->requireProcessIsTerminated(__FUNCTION__);
75135
75136 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
75137 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
75138 }
75139
75140 return $this->processInformation['signaled'];
75141 }
75142
75143
75144
75145
75146
75147
75148
75149
75150
75151
75152
75153 public function getTermSignal()
75154 {
75155 $this->requireProcessIsTerminated(__FUNCTION__);
75156
75157 if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) {
75158 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
75159 }
75160
75161 return $this->processInformation['termsig'];
75162 }
75163
75164
75165
75166
75167
75168
75169
75170
75171
75172
75173 public function hasBeenStopped()
75174 {
75175 $this->requireProcessIsTerminated(__FUNCTION__);
75176
75177 return $this->processInformation['stopped'];
75178 }
75179
75180
75181
75182
75183
75184
75185
75186
75187
75188
75189 public function getStopSignal()
75190 {
75191 $this->requireProcessIsTerminated(__FUNCTION__);
75192
75193 return $this->processInformation['stopsig'];
75194 }
75195
75196
75197
75198
75199
75200
75201 public function isRunning()
75202 {
75203 if (self::STATUS_STARTED !== $this->status) {
75204 return false;
75205 }
75206
75207 $this->updateStatus(false);
75208
75209 return $this->processInformation['running'];
75210 }
75211
75212
75213
75214
75215
75216
75217 public function isStarted()
75218 {
75219 return self::STATUS_READY != $this->status;
75220 }
75221
75222
75223
75224
75225
75226
75227 public function isTerminated()
75228 {
75229 $this->updateStatus(false);
75230
75231 return self::STATUS_TERMINATED == $this->status;
75232 }
75233
75234
75235
75236
75237
75238
75239
75240
75241 public function getStatus()
75242 {
75243 $this->updateStatus(false);
75244
75245 return $this->status;
75246 }
75247
75248
75249
75250
75251
75252
75253
75254
75255
75256 public function stop($timeout = 10, $signal = null)
75257 {
75258 $timeoutMicro = microtime(true) + $timeout;
75259 if ($this->isRunning()) {
75260
75261  $this->doSignal(15, false);
75262 do {
75263 usleep(1000);
75264 } while ($this->isRunning() && microtime(true) < $timeoutMicro);
75265
75266 if ($this->isRunning()) {
75267
75268  
75269  $this->doSignal($signal ?: 9, false);
75270 }
75271 }
75272
75273 if ($this->isRunning()) {
75274 if (isset($this->fallbackStatus['pid'])) {
75275 unset($this->fallbackStatus['pid']);
75276
75277 return $this->stop(0, $signal);
75278 }
75279 $this->close();
75280 }
75281
75282 return $this->exitcode;
75283 }
75284
75285
75286
75287
75288
75289
75290
75291
75292 public function addOutput($line)
75293 {
75294 $this->lastOutputTime = microtime(true);
75295
75296 fseek($this->stdout, 0, SEEK_END);
75297 fwrite($this->stdout, $line);
75298 fseek($this->stdout, $this->incrementalOutputOffset);
75299 }
75300
75301
75302
75303
75304
75305
75306
75307
75308 public function addErrorOutput($line)
75309 {
75310 $this->lastOutputTime = microtime(true);
75311
75312 fseek($this->stderr, 0, SEEK_END);
75313 fwrite($this->stderr, $line);
75314 fseek($this->stderr, $this->incrementalErrorOutputOffset);
75315 }
75316
75317
75318
75319
75320
75321
75322 public function getCommandLine()
75323 {
75324 return $this->commandline;
75325 }
75326
75327
75328
75329
75330
75331
75332
75333
75334 public function setCommandLine($commandline)
75335 {
75336 $this->commandline = $commandline;
75337
75338 return $this;
75339 }
75340
75341
75342
75343
75344
75345
75346 public function getTimeout()
75347 {
75348 return $this->timeout;
75349 }
75350
75351
75352
75353
75354
75355
75356 public function getIdleTimeout()
75357 {
75358 return $this->idleTimeout;
75359 }
75360
75361
75362
75363
75364
75365
75366
75367
75368
75369
75370
75371
75372 public function setTimeout($timeout)
75373 {
75374 $this->timeout = $this->validateTimeout($timeout);
75375
75376 return $this;
75377 }
75378
75379
75380
75381
75382
75383
75384
75385
75386
75387
75388
75389
75390
75391 public function setIdleTimeout($timeout)
75392 {
75393 if (null !== $timeout && $this->outputDisabled) {
75394 throw new LogicException('Idle timeout can not be set while the output is disabled.');
75395 }
75396
75397 $this->idleTimeout = $this->validateTimeout($timeout);
75398
75399 return $this;
75400 }
75401
75402
75403
75404
75405
75406
75407
75408
75409
75410
75411 public function setTty($tty)
75412 {
75413 if ('\\' === DIRECTORY_SEPARATOR && $tty) {
75414 throw new RuntimeException('TTY mode is not supported on Windows platform.');
75415 }
75416 if ($tty) {
75417 static $isTtySupported;
75418
75419 if (null === $isTtySupported) {
75420 $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);
75421 }
75422
75423 if (!$isTtySupported) {
75424 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
75425 }
75426 }
75427
75428 $this->tty = (bool) $tty;
75429
75430 return $this;
75431 }
75432
75433
75434
75435
75436
75437
75438 public function isTty()
75439 {
75440 return $this->tty;
75441 }
75442
75443
75444
75445
75446
75447
75448
75449
75450 public function setPty($bool)
75451 {
75452 $this->pty = (bool) $bool;
75453
75454 return $this;
75455 }
75456
75457
75458
75459
75460
75461
75462 public function isPty()
75463 {
75464 return $this->pty;
75465 }
75466
75467
75468
75469
75470
75471
75472 public function getWorkingDirectory()
75473 {
75474 if (null === $this->cwd) {
75475
75476  
75477  return getcwd() ?: null;
75478 }
75479
75480 return $this->cwd;
75481 }
75482
75483
75484
75485
75486
75487
75488
75489
75490 public function setWorkingDirectory($cwd)
75491 {
75492 $this->cwd = $cwd;
75493
75494 return $this;
75495 }
75496
75497
75498
75499
75500
75501
75502 public function getEnv()
75503 {
75504 return $this->env;
75505 }
75506
75507
75508
75509
75510
75511
75512
75513
75514
75515
75516
75517
75518
75519
75520 public function setEnv(array $env)
75521 {
75522
75523  $env = array_filter($env, function ($value) {
75524 return !is_array($value);
75525 });
75526
75527 $this->env = array();
75528 foreach ($env as $key => $value) {
75529 $this->env[$key] = (string) $value;
75530 }
75531
75532 return $this;
75533 }
75534
75535
75536
75537
75538
75539
75540
75541
75542
75543
75544 public function getStdin()
75545 {
75546 @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);
75547
75548 return $this->getInput();
75549 }
75550
75551
75552
75553
75554
75555
75556 public function getInput()
75557 {
75558 return $this->input;
75559 }
75560
75561
75562
75563
75564
75565
75566
75567
75568
75569
75570
75571
75572
75573
75574 public function setStdin($stdin)
75575 {
75576 @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);
75577
75578 return $this->setInput($stdin);
75579 }
75580
75581
75582
75583
75584
75585
75586
75587
75588
75589
75590
75591
75592
75593
75594 public function setInput($input)
75595 {
75596 if ($this->isRunning()) {
75597 throw new LogicException('Input can not be set while the process is running.');
75598 }
75599
75600 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
75601
75602 return $this;
75603 }
75604
75605
75606
75607
75608
75609
75610 public function getOptions()
75611 {
75612 return $this->options;
75613 }
75614
75615
75616
75617
75618
75619
75620
75621
75622 public function setOptions(array $options)
75623 {
75624 $this->options = $options;
75625
75626 return $this;
75627 }
75628
75629
75630
75631
75632
75633
75634
75635
75636 public function getEnhanceWindowsCompatibility()
75637 {
75638 return $this->enhanceWindowsCompatibility;
75639 }
75640
75641
75642
75643
75644
75645
75646
75647
75648 public function setEnhanceWindowsCompatibility($enhance)
75649 {
75650 $this->enhanceWindowsCompatibility = (bool) $enhance;
75651
75652 return $this;
75653 }
75654
75655
75656
75657
75658
75659
75660 public function getEnhanceSigchildCompatibility()
75661 {
75662 return $this->enhanceSigchildCompatibility;
75663 }
75664
75665
75666
75667
75668
75669
75670
75671
75672
75673
75674
75675
75676 public function setEnhanceSigchildCompatibility($enhance)
75677 {
75678 $this->enhanceSigchildCompatibility = (bool) $enhance;
75679
75680 return $this;
75681 }
75682
75683
75684
75685
75686
75687
75688
75689
75690
75691 public function checkTimeout()
75692 {
75693 if (self::STATUS_STARTED !== $this->status) {
75694 return;
75695 }
75696
75697 if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
75698 $this->stop(0);
75699
75700 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
75701 }
75702
75703 if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
75704 $this->stop(0);
75705
75706 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
75707 }
75708 }
75709
75710
75711
75712
75713
75714
75715 public static function isPtySupported()
75716 {
75717 static $result;
75718
75719 if (null !== $result) {
75720 return $result;
75721 }
75722
75723 if ('\\' === DIRECTORY_SEPARATOR) {
75724 return $result = false;
75725 }
75726
75727 return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes);
75728 }
75729
75730
75731
75732
75733
75734
75735 private function getDescriptors()
75736 {
75737 if ('\\' === DIRECTORY_SEPARATOR) {
75738 $this->processPipes = WindowsPipes::create($this, $this->input);
75739 } else {
75740 $this->processPipes = UnixPipes::create($this, $this->input);
75741 }
75742
75743 return $this->processPipes->getDescriptors();
75744 }
75745
75746
75747
75748
75749
75750
75751
75752
75753
75754
75755
75756 protected function buildCallback($callback)
75757 {
75758 $that = $this;
75759 $out = self::OUT;
75760 $callback = function ($type, $data) use ($that, $callback, $out) {
75761 if ($out == $type) {
75762 $that->addOutput($data);
75763 } else {
75764 $that->addErrorOutput($data);
75765 }
75766
75767 if (null !== $callback) {
75768 call_user_func($callback, $type, $data);
75769 }
75770 };
75771
75772 return $callback;
75773 }
75774
75775
75776
75777
75778
75779
75780 protected function updateStatus($blocking)
75781 {
75782 if (self::STATUS_STARTED !== $this->status) {
75783 return;
75784 }
75785
75786 $this->processInformation = proc_get_status($this->process);
75787 $running = $this->processInformation['running'];
75788
75789 $this->readPipes($running && $blocking, '\\' !== DIRECTORY_SEPARATOR || !$running);
75790
75791 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
75792 $this->processInformation = $this->fallbackStatus + $this->processInformation;
75793 }
75794
75795 if (!$running) {
75796 $this->close();
75797 }
75798 }
75799
75800
75801
75802
75803
75804
75805 protected function isSigchildEnabled()
75806 {
75807 if (null !== self::$sigchild) {
75808 return self::$sigchild;
75809 }
75810
75811 if (!function_exists('phpinfo') || defined('HHVM_VERSION')) {
75812 return self::$sigchild = false;
75813 }
75814
75815 ob_start();
75816 phpinfo(INFO_GENERAL);
75817
75818 return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
75819 }
75820
75821
75822
75823
75824
75825
75826
75827
75828 private function readPipesForOutput($caller)
75829 {
75830 if ($this->outputDisabled) {
75831 throw new LogicException('Output has been disabled.');
75832 }
75833
75834 $this->requireProcessIsStarted($caller);
75835
75836 $this->updateStatus(false);
75837 }
75838
75839
75840
75841
75842
75843
75844
75845
75846
75847
75848 private function validateTimeout($timeout)
75849 {
75850 $timeout = (float) $timeout;
75851
75852 if (0.0 === $timeout) {
75853 $timeout = null;
75854 } elseif ($timeout < 0) {
75855 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
75856 }
75857
75858 return $timeout;
75859 }
75860
75861
75862
75863
75864
75865
75866
75867 private function readPipes($blocking, $close)
75868 {
75869 $result = $this->processPipes->readAndWrite($blocking, $close);
75870
75871 $callback = $this->callback;
75872 foreach ($result as $type => $data) {
75873 if (3 !== $type) {
75874 $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);
75875 } elseif (!isset($this->fallbackStatus['signaled'])) {
75876 $this->fallbackStatus['exitcode'] = (int) $data;
75877 }
75878 }
75879 }
75880
75881
75882
75883
75884
75885
75886 private function close()
75887 {
75888 $this->processPipes->close();
75889 if (is_resource($this->process)) {
75890 proc_close($this->process);
75891 }
75892 $this->exitcode = $this->processInformation['exitcode'];
75893 $this->status = self::STATUS_TERMINATED;
75894
75895 if (-1 === $this->exitcode) {
75896 if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
75897
75898  $this->exitcode = 128 + $this->processInformation['termsig'];
75899 } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
75900 $this->processInformation['signaled'] = true;
75901 $this->processInformation['termsig'] = -1;
75902 }
75903 }
75904
75905
75906  
75907  
75908  $this->callback = null;
75909
75910 return $this->exitcode;
75911 }
75912
75913
75914
75915
75916 private function resetProcessData()
75917 {
75918 $this->starttime = null;
75919 $this->callback = null;
75920 $this->exitcode = null;
75921 $this->fallbackStatus = array();
75922 $this->processInformation = null;
75923 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
75924 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
75925 $this->process = null;
75926 $this->latestSignal = null;
75927 $this->status = self::STATUS_READY;
75928 $this->incrementalOutputOffset = 0;
75929 $this->incrementalErrorOutputOffset = 0;
75930 }
75931
75932
75933
75934
75935
75936
75937
75938
75939
75940
75941
75942
75943
75944 private function doSignal($signal, $throwException)
75945 {
75946 if (null === $pid = $this->getPid()) {
75947 if ($throwException) {
75948 throw new LogicException('Can not send signal on a non running process.');
75949 }
75950
75951 return false;
75952 }
75953
75954 if ('\\' === DIRECTORY_SEPARATOR) {
75955 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
75956 if ($exitCode && $this->isRunning()) {
75957 if ($throwException) {
75958 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
75959 }
75960
75961 return false;
75962 }
75963 } else {
75964 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
75965 $ok = @proc_terminate($this->process, $signal);
75966 } elseif (function_exists('posix_kill')) {
75967 $ok = @posix_kill($pid, $signal);
75968 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
75969 $ok = false === fgets($pipes[2]);
75970 }
75971 if (!$ok) {
75972 if ($throwException) {
75973 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
75974 }
75975
75976 return false;
75977 }
75978 }
75979
75980 $this->latestSignal = (int) $signal;
75981 $this->fallbackStatus['signaled'] = true;
75982 $this->fallbackStatus['exitcode'] = -1;
75983 $this->fallbackStatus['termsig'] = $this->latestSignal;
75984
75985 return true;
75986 }
75987
75988
75989
75990
75991
75992
75993
75994
75995 private function requireProcessIsStarted($functionName)
75996 {
75997 if (!$this->isStarted()) {
75998 throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
75999 }
76000 }
76001
76002
76003
76004
76005
76006
76007
76008
76009 private function requireProcessIsTerminated($functionName)
76010 {
76011 if (!$this->isTerminated()) {
76012 throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
76013 }
76014 }
76015 }
76016 <?php
76017
76018
76019
76020
76021
76022
76023
76024
76025
76026
76027 namespace Symfony\Component\Process;
76028
76029 use Symfony\Component\Process\Exception\InvalidArgumentException;
76030 use Symfony\Component\Process\Exception\LogicException;
76031
76032
76033
76034
76035 class ProcessBuilder
76036 {
76037 private $arguments;
76038 private $cwd;
76039 private $env = array();
76040 private $input;
76041 private $timeout = 60;
76042 private $options = array();
76043 private $inheritEnv = true;
76044 private $prefix = array();
76045 private $outputDisabled = false;
76046
76047
76048
76049
76050 public function __construct(array $arguments = array())
76051 {
76052 $this->arguments = $arguments;
76053 }
76054
76055
76056
76057
76058
76059
76060
76061
76062 public static function create(array $arguments = array())
76063 {
76064 return new static($arguments);
76065 }
76066
76067
76068
76069
76070
76071
76072
76073
76074 public function add($argument)
76075 {
76076 $this->arguments[] = $argument;
76077
76078 return $this;
76079 }
76080
76081
76082
76083
76084
76085
76086
76087
76088
76089
76090 public function setPrefix($prefix)
76091 {
76092 $this->prefix = is_array($prefix) ? $prefix : array($prefix);
76093
76094 return $this;
76095 }
76096
76097
76098
76099
76100
76101
76102
76103
76104
76105
76106
76107 public function setArguments(array $arguments)
76108 {
76109 $this->arguments = $arguments;
76110
76111 return $this;
76112 }
76113
76114
76115
76116
76117
76118
76119
76120
76121 public function setWorkingDirectory($cwd)
76122 {
76123 $this->cwd = $cwd;
76124
76125 return $this;
76126 }
76127
76128
76129
76130
76131
76132
76133
76134
76135 public function inheritEnvironmentVariables($inheritEnv = true)
76136 {
76137 $this->inheritEnv = $inheritEnv;
76138
76139 return $this;
76140 }
76141
76142
76143
76144
76145
76146
76147
76148
76149
76150
76151
76152
76153 public function setEnv($name, $value)
76154 {
76155 $this->env[$name] = $value;
76156
76157 return $this;
76158 }
76159
76160
76161
76162
76163
76164
76165
76166
76167
76168
76169
76170
76171 public function addEnvironmentVariables(array $variables)
76172 {
76173 $this->env = array_replace($this->env, $variables);
76174
76175 return $this;
76176 }
76177
76178
76179
76180
76181
76182
76183
76184
76185
76186
76187
76188
76189 public function setInput($input)
76190 {
76191 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
76192
76193 return $this;
76194 }
76195
76196
76197
76198
76199
76200
76201
76202
76203
76204
76205
76206
76207 public function setTimeout($timeout)
76208 {
76209 if (null === $timeout) {
76210 $this->timeout = null;
76211
76212 return $this;
76213 }
76214
76215 $timeout = (float) $timeout;
76216
76217 if ($timeout < 0) {
76218 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
76219 }
76220
76221 $this->timeout = $timeout;
76222
76223 return $this;
76224 }
76225
76226
76227
76228
76229
76230
76231
76232
76233
76234 public function setOption($name, $value)
76235 {
76236 $this->options[$name] = $value;
76237
76238 return $this;
76239 }
76240
76241
76242
76243
76244
76245
76246 public function disableOutput()
76247 {
76248 $this->outputDisabled = true;
76249
76250 return $this;
76251 }
76252
76253
76254
76255
76256
76257
76258 public function enableOutput()
76259 {
76260 $this->outputDisabled = false;
76261
76262 return $this;
76263 }
76264
76265
76266
76267
76268
76269
76270
76271
76272 public function getProcess()
76273 {
76274 if (0 === count($this->prefix) && 0 === count($this->arguments)) {
76275 throw new LogicException('You must add() command arguments before calling getProcess().');
76276 }
76277
76278 $options = $this->options;
76279
76280 $arguments = array_merge($this->prefix, $this->arguments);
76281 $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
76282
76283 if ($this->inheritEnv) {
76284
76285  $env = array_replace($_ENV, $_SERVER, $this->env);
76286 } else {
76287 $env = $this->env;
76288 }
76289
76290 $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
76291
76292 if ($this->outputDisabled) {
76293 $process->disableOutput();
76294 }
76295
76296 return $process;
76297 }
76298 }
76299 <?php
76300
76301
76302
76303
76304
76305
76306
76307
76308
76309
76310 namespace Symfony\Component\Process;
76311
76312 use Symfony\Component\Process\Exception\InvalidArgumentException;
76313
76314
76315
76316
76317
76318
76319
76320
76321 class ProcessUtils
76322 {
76323
76324
76325
76326 private function __construct()
76327 {
76328 }
76329
76330
76331
76332
76333
76334
76335
76336
76337 public static function escapeArgument($argument)
76338 {
76339
76340  
76341  
76342  
76343  if ('\\' === DIRECTORY_SEPARATOR) {
76344 if ('' === $argument) {
76345 return escapeshellarg($argument);
76346 }
76347
76348 $escapedArgument = '';
76349 $quote = false;
76350 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
76351 if ('"' === $part) {
76352 $escapedArgument .= '\\"';
76353 } elseif (self::isSurroundedBy($part, '%')) {
76354
76355  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
76356 } else {
76357
76358  if ('\\' === substr($part, -1)) {
76359 $part .= '\\';
76360 }
76361 $quote = true;
76362 $escapedArgument .= $part;
76363 }
76364 }
76365 if ($quote) {
76366 $escapedArgument = '"'.$escapedArgument.'"';
76367 }
76368
76369 return $escapedArgument;
76370 }
76371
76372 return "'".str_replace("'", "'\\''", $argument)."'";
76373 }
76374
76375
76376
76377
76378
76379
76380
76381
76382
76383
76384
76385
76386
76387 public static function validateInput($caller, $input)
76388 {
76389 if (null !== $input) {
76390 if (is_resource($input)) {
76391 return $input;
76392 }
76393 if (is_string($input)) {
76394 return $input;
76395 }
76396 if (is_scalar($input)) {
76397 return (string) $input;
76398 }
76399
76400  if (is_object($input) && method_exists($input, '__toString')) {
76401 @trigger_error('Passing an object as an input is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
76402
76403 return (string) $input;
76404 }
76405
76406 throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
76407 }
76408
76409 return $input;
76410 }
76411
76412 private static function isSurroundedBy($arg, $char)
76413 {
76414 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
76415 }
76416 }
76417 Copyright (c) 2011 Jordi Boggiano
76418
76419 Permission is hereby granted, free of charge, to any person obtaining a copy
76420 of this software and associated documentation files (the "Software"), to deal
76421 in the Software without restriction, including without limitation the rights
76422 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
76423 copies of the Software, and to permit persons to whom the Software is furnished
76424 to do so, subject to the following conditions:
76425
76426 The above copyright notice and this permission notice shall be included in all
76427 copies or substantial portions of the Software.
76428
76429 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
76430 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
76431 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
76432 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76433 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
76434 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
76435 THE SOFTWARE.
76436 <?php
76437
76438
76439
76440
76441
76442
76443
76444
76445
76446
76447 namespace Seld\JsonLint;
76448
76449 class DuplicateKeyException extends ParsingException
76450 {
76451 public function __construct($message, $key, array $details = array())
76452 {
76453 $details['key'] = $key;
76454 parent::__construct($message, $details);
76455 }
76456
76457 public function getKey()
76458 {
76459 return $this->details['key'];
76460 }
76461 }
76462 <?php
76463
76464
76465
76466
76467
76468
76469
76470
76471
76472
76473 namespace Seld\JsonLint;
76474 use stdClass;
76475
76476
76477
76478
76479
76480
76481
76482
76483
76484
76485
76486
76487
76488
76489 class JsonParser
76490 {
76491 const DETECT_KEY_CONFLICTS = 1;
76492 const ALLOW_DUPLICATE_KEYS = 2;
76493 const PARSE_TO_ASSOC = 4;
76494
76495 private $lexer;
76496
76497 private $flags;
76498 private $stack;
76499 private $vstack; 
76500  private $lstack; 
76501
76502 private $symbols = array(
76503 'error' => 2,
76504 'JSONString' => 3,
76505 'STRING' => 4,
76506 'JSONNumber' => 5,
76507 'NUMBER' => 6,
76508 'JSONNullLiteral' => 7,
76509 'NULL' => 8,
76510 'JSONBooleanLiteral' => 9,
76511 'TRUE' => 10,
76512 'FALSE' => 11,
76513 'JSONText' => 12,
76514 'JSONValue' => 13,
76515 'EOF' => 14,
76516 'JSONObject' => 15,
76517 'JSONArray' => 16,
76518 '{' => 17,
76519 '}' => 18,
76520 'JSONMemberList' => 19,
76521 'JSONMember' => 20,
76522 ':' => 21,
76523 ',' => 22,
76524 '[' => 23,
76525 ']' => 24,
76526 'JSONElementList' => 25,
76527 '$accept' => 0,
76528 '$end' => 1,
76529 );
76530
76531 private $terminals_ = array(
76532 2 => "error",
76533 4 => "STRING",
76534 6 => "NUMBER",
76535 8 => "NULL",
76536 10 => "TRUE",
76537 11 => "FALSE",
76538 14 => "EOF",
76539 17 => "{",
76540 18 => "}",
76541 21 => ":",
76542 22 => ",",
76543 23 => "[",
76544 24 => "]",
76545 );
76546
76547 private $productions_ = array(
76548 0,
76549 array(3, 1),
76550 array(5, 1),
76551 array(7, 1),
76552 array(9, 1),
76553 array(9, 1),
76554 array(12, 2),
76555 array(13, 1),
76556 array(13, 1),
76557 array(13, 1),
76558 array(13, 1),
76559 array(13, 1),
76560 array(13, 1),
76561 array(15, 2),
76562 array(15, 3),
76563 array(20, 3),
76564 array(19, 1),
76565 array(19, 3),
76566 array(16, 2),
76567 array(16, 3),
76568 array(25, 1),
76569 array(25, 3)
76570 );
76571
76572 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)),
76573 );
76574
76575 private $defaultActions = array(
76576 16 => array(2, 6)
76577 );
76578
76579
76580
76581
76582
76583
76584 public function lint($input, $flags = 0)
76585 {
76586 try {
76587 $this->parse($input, $flags);
76588 } catch (ParsingException $e) {
76589 return $e;
76590 }
76591 }
76592
76593
76594
76595
76596
76597
76598
76599 public function parse($input, $flags = 0)
76600 {
76601 $this->failOnBOM($input);
76602
76603 $this->flags = $flags;
76604
76605 $this->stack = array(0);
76606 $this->vstack = array(null);
76607 $this->lstack = array();
76608
76609 $yytext = '';
76610 $yylineno = 0;
76611 $yyleng = 0;
76612 $recovering = 0;
76613 $TERROR = 2;
76614 $EOF = 1;
76615
76616 $this->lexer = new Lexer();
76617 $this->lexer->setInput($input);
76618
76619 $yyloc = $this->lexer->yylloc;
76620 $this->lstack[] = $yyloc;
76621
76622 $symbol = null;
76623 $preErrorSymbol = null;
76624 $state = null;
76625 $action = null;
76626 $a = null;
76627 $r = null;
76628 $yyval = new stdClass;
76629 $p = null;
76630 $len = null;
76631 $newState = null;
76632 $expected = null;
76633 $errStr = null;
76634
76635 while (true) {
76636
76637  $state = $this->stack[count($this->stack)-1];
76638
76639
76640  if (isset($this->defaultActions[$state])) {
76641 $action = $this->defaultActions[$state];
76642 } else {
76643 if ($symbol == null) {
76644 $symbol = $this->lex();
76645 }
76646
76647  $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false;
76648 }
76649
76650
76651  if (!$action || !$action[0]) {
76652 if (!$recovering) {
76653
76654  $expected = array();
76655 foreach ($this->table[$state] as $p => $ignore) {
76656 if (isset($this->terminals_[$p]) && $p > 2) {
76657 $expected[] = "'" . $this->terminals_[$p] . "'";
76658 }
76659 }
76660
76661 $message = null;
76662 if (in_array("'STRING'", $expected) && in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
76663 $message = "Invalid string";
76664 if ("'" === substr($this->lexer->match, 0, 1)) {
76665 $message .= ", it appears you used single quotes instead of double quotes";
76666 } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u])}', $this->lexer->getUpcomingInput(), $match)) {
76667 $message .= ", it appears you have an unescaped backslash at: ".$match[1];
76668 } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getUpcomingInput())) {
76669 $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
76670 }
76671 }
76672
76673 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
76674 $errStr .= $this->lexer->showPosition() . "\n";
76675 if ($message) {
76676 $errStr .= $message;
76677 } else {
76678 $errStr .= (count($expected) > 1) ? "Expected one of: " : "Expected: ";
76679 $errStr .= implode(', ', $expected);
76680 }
76681
76682 if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
76683 $errStr .= " - It appears you have an extra trailing comma";
76684 }
76685
76686 $this->parseError($errStr, array(
76687 'text' => $this->lexer->match,
76688 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol,
76689 'line' => $this->lexer->yylineno,
76690 'loc' => $yyloc,
76691 'expected' => $expected,
76692 ));
76693 }
76694
76695
76696  if ($recovering == 3) {
76697 if ($symbol == $EOF) {
76698 throw new ParsingException($errStr ?: 'Parsing halted.');
76699 }
76700
76701
76702  $yyleng = $this->lexer->yyleng;
76703 $yytext = $this->lexer->yytext;
76704 $yylineno = $this->lexer->yylineno;
76705 $yyloc = $this->lexer->yylloc;
76706 $symbol = $this->lex();
76707 }
76708
76709
76710  while (true) {
76711
76712  if (array_key_exists($TERROR, $this->table[$state])) {
76713 break;
76714 }
76715 if ($state == 0) {
76716 throw new ParsingException($errStr ?: 'Parsing halted.');
76717 }
76718 $this->popStack(1);
76719 $state = $this->stack[count($this->stack)-1];
76720 }
76721
76722 $preErrorSymbol = $symbol; 
76723  $symbol = $TERROR; 
76724  $state = $this->stack[count($this->stack)-1];
76725 $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false;
76726 $recovering = 3; 
76727  }
76728
76729
76730  if (is_array($action[0]) && count($action) > 1) {
76731 throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
76732 }
76733
76734 switch ($action[0]) {
76735 case 1: 
76736  $this->stack[] = $symbol;
76737 $this->vstack[] = $this->lexer->yytext;
76738 $this->lstack[] = $this->lexer->yylloc;
76739 $this->stack[] = $action[1]; 
76740  $symbol = null;
76741 if (!$preErrorSymbol) { 
76742  $yyleng = $this->lexer->yyleng;
76743 $yytext = $this->lexer->yytext;
76744 $yylineno = $this->lexer->yylineno;
76745 $yyloc = $this->lexer->yylloc;
76746 if ($recovering > 0) {
76747 $recovering--;
76748 }
76749 } else { 
76750  $symbol = $preErrorSymbol;
76751 $preErrorSymbol = null;
76752 }
76753 break;
76754
76755 case 2: 
76756  $len = $this->productions_[$action[1]][1];
76757
76758
76759  $yyval->token = $this->vstack[count($this->vstack) - $len]; 
76760  
76761  $yyval->store = array( 
76762  'first_line' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_line'],
76763 'last_line' => $this->lstack[count($this->lstack) - 1]['last_line'],
76764 'first_column' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_column'],
76765 'last_column' => $this->lstack[count($this->lstack) - 1]['last_column'],
76766 );
76767 $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack, $this->lstack);
76768
76769 if (!$r instanceof Undefined) {
76770 return $r;
76771 }
76772
76773 if ($len) {
76774 $this->popStack($len);
76775 }
76776
76777 $this->stack[] = $this->productions_[$action[1]][0]; 
76778  $this->vstack[] = $yyval->token;
76779 $this->lstack[] = $yyval->store;
76780 $newState = $this->table[$this->stack[count($this->stack)-2]][$this->stack[count($this->stack)-1]];
76781 $this->stack[] = $newState;
76782 break;
76783
76784 case 3: 
76785
76786 return true;
76787 }
76788 }
76789
76790 return true;
76791 }
76792
76793 protected function parseError($str, $hash)
76794 {
76795 throw new ParsingException($str, $hash);
76796 }
76797
76798
76799  
76800  
76801  private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens)
76802 {
76803
76804  $len = count($tokens) - 1;
76805 switch ($yystate) {
76806 case 1:
76807 $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
76808 $yyval->token = $yytext;
76809 break;
76810 case 2:
76811 if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) {
76812 $yyval->token = floatval($yytext);
76813 } else {
76814 $yyval->token = strpos($yytext, '.') === false ? intval($yytext) : floatval($yytext);
76815 }
76816 break;
76817 case 3:
76818 $yyval->token = null;
76819 break;
76820 case 4:
76821 $yyval->token = true;
76822 break;
76823 case 5:
76824 $yyval->token = false;
76825 break;
76826 case 6:
76827 return $yyval->token = $tokens[$len-1];
76828 case 13:
76829 if ($this->flags & self::PARSE_TO_ASSOC) {
76830 $yyval->token = array();
76831 } else {
76832 $yyval->token = new stdClass;
76833 }
76834 break;
76835 case 14:
76836 $yyval->token = $tokens[$len-1];
76837 break;
76838 case 15:
76839 $yyval->token = array($tokens[$len-2], $tokens[$len]);
76840 break;
76841 case 16:
76842 if (PHP_VERSION_ID < 70100) {
76843 $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
76844 } else {
76845 $property = $tokens[$len][0];
76846 }
76847 if ($this->flags & self::PARSE_TO_ASSOC) {
76848 $yyval->token = array();
76849 $yyval->token[$property] = $tokens[$len][1];
76850 } else {
76851 $yyval->token = new stdClass;
76852 $yyval->token->$property = $tokens[$len][1];
76853 }
76854 break;
76855 case 17:
76856 if ($this->flags & self::PARSE_TO_ASSOC) {
76857 $yyval->token =& $tokens[$len-2];
76858 $key = $tokens[$len][0];
76859 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
76860 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
76861 $errStr .= $this->lexer->showPosition() . "\n";
76862 $errStr .= "Duplicate key: ".$tokens[$len][0];
76863 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
76864 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) {
76865 $duplicateCount = 1;
76866 do {
76867 $duplicateKey = $key . '.' . $duplicateCount++;
76868 } while (isset($tokens[$len-2][$duplicateKey]));
76869 $key = $duplicateKey;
76870 }
76871 $tokens[$len-2][$key] = $tokens[$len][1];
76872 } else {
76873 $yyval->token = $tokens[$len-2];
76874 if (PHP_VERSION_ID < 70100) {
76875 $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
76876 } else {
76877 $key = $tokens[$len][0];
76878 }
76879 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
76880 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
76881 $errStr .= $this->lexer->showPosition() . "\n";
76882 $errStr .= "Duplicate key: ".$tokens[$len][0];
76883 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
76884 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) {
76885 $duplicateCount = 1;
76886 do {
76887 $duplicateKey = $key . '.' . $duplicateCount++;
76888 } while (isset($tokens[$len-2]->$duplicateKey));
76889 $key = $duplicateKey;
76890 }
76891 $tokens[$len-2]->$key = $tokens[$len][1];
76892 }
76893 break;
76894 case 18:
76895 $yyval->token = array();
76896 break;
76897 case 19:
76898 $yyval->token = $tokens[$len-1];
76899 break;
76900 case 20:
76901 $yyval->token = array($tokens[$len]);
76902 break;
76903 case 21:
76904 $tokens[$len-2][] = $tokens[$len];
76905 $yyval->token = $tokens[$len-2];
76906 break;
76907 }
76908
76909 return new Undefined();
76910 }
76911
76912 private function stringInterpolation($match)
76913 {
76914 switch ($match[0]) {
76915 case '\\\\':
76916 return '\\';
76917 case '\"':
76918 return '"';
76919 case '\b':
76920 return chr(8);
76921 case '\f':
76922 return chr(12);
76923 case '\n':
76924 return "\n";
76925 case '\r':
76926 return "\r";
76927 case '\t':
76928 return "\t";
76929 case '\/':
76930 return "/";
76931 default:
76932 return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', 0, 'UTF-8');
76933 }
76934 }
76935
76936 private function popStack($n)
76937 {
76938 $this->stack = array_slice($this->stack, 0, - (2 * $n));
76939 $this->vstack = array_slice($this->vstack, 0, - $n);
76940 $this->lstack = array_slice($this->lstack, 0, - $n);
76941 }
76942
76943 private function lex()
76944 {
76945 $token = $this->lexer->lex() ?: 1; 
76946  
76947  if (!is_numeric($token)) {
76948 $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token;
76949 }
76950
76951 return $token;
76952 }
76953
76954 private function failOnBOM($input)
76955 {
76956
76957  $bom = "\xEF\xBB\xBF";
76958
76959 if (substr($input, 0, 3) === $bom) {
76960 $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array());
76961 }
76962 }
76963 }
76964 <?php
76965
76966
76967
76968
76969
76970
76971
76972
76973
76974
76975 namespace Seld\JsonLint;
76976
76977
76978
76979
76980
76981
76982 class Lexer
76983 {
76984 private $EOF = 1;
76985 private $rules = array(
76986 0 => '/^\s+/',
76987 1 => '/^-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/',
76988 2 => '{^"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x1f\\\\"]++)*+"}',
76989 3 => '/^\{/',
76990 4 => '/^\}/',
76991 5 => '/^\[/',
76992 6 => '/^\]/',
76993 7 => '/^,/',
76994 8 => '/^:/',
76995 9 => '/^true\b/',
76996 10 => '/^false\b/',
76997 11 => '/^null\b/',
76998 12 => '/^$/',
76999 13 => '/^./',
77000 );
77001
77002 private $conditions = array(
77003 "INITIAL" => array(
77004 "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13),
77005 "inclusive" => true,
77006 ),
77007 );
77008
77009 private $conditionStack;
77010 private $input;
77011 private $more;
77012 private $done;
77013 private $matched;
77014
77015 public $match;
77016 public $yylineno;
77017 public $yyleng;
77018 public $yytext;
77019 public $yylloc;
77020
77021 public function lex()
77022 {
77023 $r = $this->next();
77024 if (!$r instanceof Undefined) {
77025 return $r;
77026 }
77027
77028 return $this->lex();
77029 }
77030
77031 public function setInput($input)
77032 {
77033 $this->input = $input;
77034 $this->more = false;
77035 $this->done = false;
77036 $this->yylineno = $this->yyleng = 0;
77037 $this->yytext = $this->matched = $this->match = '';
77038 $this->conditionStack = array('INITIAL');
77039 $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
77040
77041 return $this;
77042 }
77043
77044 public function showPosition()
77045 {
77046 $pre = str_replace("\n", '', $this->getPastInput());
77047 $c = str_repeat('-', max(0, strlen($pre) - 1)); 
77048
77049 return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
77050 }
77051
77052 public function getPastInput()
77053 {
77054 $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match));
77055
77056 return (strlen($past) > 20 ? '...' : '') . substr($past, -20);
77057 }
77058
77059 public function getUpcomingInput()
77060 {
77061 $next = $this->match;
77062 if (strlen($next) < 20) {
77063 $next .= substr($this->input, 0, 20 - strlen($next));
77064 }
77065
77066 return substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '');
77067 }
77068
77069 protected function parseError($str, $hash)
77070 {
77071 throw new \Exception($str);
77072 }
77073
77074 private function next()
77075 {
77076 if ($this->done) {
77077 return $this->EOF;
77078 }
77079 if ($this->input === '') {
77080 $this->done = true;
77081 }
77082
77083 $token = null;
77084 $match = null;
77085 $col = null;
77086 $lines = null;
77087
77088 if (!$this->more) {
77089 $this->yytext = '';
77090 $this->match = '';
77091 }
77092
77093 $rules = $this->getCurrentRules();
77094 $rulesLen = count($rules);
77095
77096 for ($i=0; $i < $rulesLen; $i++) {
77097 if (preg_match($this->rules[$rules[$i]], $this->input, $match)) {
77098 preg_match_all('/\n.*/', $match[0], $lines);
77099 $lines = $lines[0];
77100 if ($lines) {
77101 $this->yylineno += count($lines);
77102 }
77103
77104 $this->yylloc = array(
77105 'first_line' => $this->yylloc['last_line'],
77106 'last_line' => $this->yylineno+1,
77107 'first_column' => $this->yylloc['last_column'],
77108 'last_column' => $lines ? strlen($lines[count($lines) - 1]) - 1 : $this->yylloc['last_column'] + strlen($match[0]),
77109 );
77110 $this->yytext .= $match[0];
77111 $this->match .= $match[0];
77112 $this->yyleng = strlen($this->yytext);
77113 $this->more = false;
77114 $this->input = substr($this->input, strlen($match[0]));
77115 $this->matched .= $match[0];
77116 $token = $this->performAction($rules[$i], $this->conditionStack[count($this->conditionStack)-1]);
77117 if ($token) {
77118 return $token;
77119 }
77120
77121 return new Undefined();
77122 }
77123 }
77124
77125 if ($this->input === "") {
77126 return $this->EOF;
77127 }
77128
77129 $this->parseError(
77130 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(),
77131 array(
77132 'text' => "",
77133 'token' => null,
77134 'line' => $this->yylineno,
77135 )
77136 );
77137 }
77138
77139 private function getCurrentRules()
77140 {
77141 return $this->conditions[$this->conditionStack[count($this->conditionStack)-1]]['rules'];
77142 }
77143
77144 private function performAction($avoiding_name_collisions, $YY_START)
77145 {
77146 switch ($avoiding_name_collisions) {
77147 case 0:
77148 break;
77149 case 1:
77150 return 6;
77151 break;
77152 case 2:
77153 $this->yytext = substr($this->yytext, 1, $this->yyleng-2);
77154
77155 return 4;
77156 case 3:
77157 return 17;
77158 case 4:
77159 return 18;
77160 case 5:
77161 return 23;
77162 case 6:
77163 return 24;
77164 case 7:
77165 return 22;
77166 case 8:
77167 return 21;
77168 case 9:
77169 return 10;
77170 case 10:
77171 return 11;
77172 case 11:
77173 return 8;
77174 case 12:
77175 return 14;
77176 case 13:
77177 return 'INVALID';
77178 }
77179 }
77180 }
77181 <?php
77182
77183
77184
77185
77186
77187
77188
77189
77190
77191
77192 namespace Seld\JsonLint;
77193
77194 class ParsingException extends \Exception
77195 {
77196 protected $details;
77197
77198 public function __construct($message, $details = array())
77199 {
77200 $this->details = $details;
77201 parent::__construct($message);
77202 }
77203
77204 public function getDetails()
77205 {
77206 return $this->details;
77207 }
77208 }
77209 <?php
77210
77211
77212
77213
77214
77215
77216
77217
77218
77219
77220 namespace Seld\JsonLint;
77221
77222 class Undefined
77223 {
77224 }
77225 MIT License
77226
77227 Copyright (c) 2016
77228
77229 Permission is hereby granted, free of charge, to any person obtaining a copy
77230 of this software and associated documentation files (the "Software"), to deal
77231 in the Software without restriction, including without limitation the rights
77232 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
77233 copies of the Software, and to permit persons to whom the Software is
77234 furnished to do so, subject to the following conditions:
77235
77236 The above copyright notice and this permission notice shall be included in all
77237 copies or substantial portions of the Software.
77238
77239 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
77240 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
77241 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
77242 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
77243 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
77244 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
77245 SOFTWARE.
77246 <?php
77247
77248 require __DIR__ . '/../vendor/autoload.php';
77249
77250 $data = json_decode(file_get_contents('data.json'));
77251
77252
77253 $validator = new JsonSchema\Validator();
77254 $validator->check($data, (object) array('$ref' => 'file://' . realpath('schema.json')));
77255
77256 if ($validator->isValid()) {
77257 echo "The supplied JSON validates against the schema.\n";
77258 } else {
77259 echo "JSON does not validate. Violations:\n";
77260 foreach ($validator->getErrors() as $error) {
77261 echo sprintf("[%s] %s\n", $error['property'], $error['message']);
77262 }
77263 }
77264 <?php
77265
77266
77267
77268
77269
77270
77271
77272
77273 namespace JsonSchema\Constraints;
77274
77275 use JsonSchema\Entity\JsonPointer;
77276 use JsonSchema\Exception\InvalidArgumentException;
77277 use JsonSchema\Exception\ValidationException;
77278 use JsonSchema\Validator;
77279
77280
77281
77282
77283
77284 class BaseConstraint
77285 {
77286
77287
77288
77289 protected $errors = array();
77290
77291
77292
77293
77294 protected $errorMask = Validator::ERROR_NONE;
77295
77296
77297
77298
77299 protected $factory;
77300
77301
77302
77303
77304 public function __construct(Factory $factory = null)
77305 {
77306 $this->factory = $factory ?: new Factory();
77307 }
77308
77309 public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null)
77310 {
77311 $error = array(
77312 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')),
77313 'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
77314 'message' => $message,
77315 'constraint' => $constraint,
77316 'context' => $this->factory->getErrorContext(),
77317 );
77318
77319 if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
77320 throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
77321 }
77322
77323 if (is_array($more) && count($more) > 0) {
77324 $error += $more;
77325 }
77326
77327 $this->errors[] = $error;
77328 $this->errorMask |= $error['context'];
77329 }
77330
77331 public function addErrors(array $errors)
77332 {
77333 if ($errors) {
77334 $this->errors = array_merge($this->errors, $errors);
77335 $errorMask = &$this->errorMask;
77336 array_walk($errors, function ($error) use (&$errorMask) {
77337 if (isset($error['context'])) {
77338 $errorMask |= $error['context'];
77339 }
77340 });
77341 }
77342 }
77343
77344 public function getErrors($errorContext = Validator::ERROR_ALL)
77345 {
77346 if ($errorContext === Validator::ERROR_ALL) {
77347 return $this->errors;
77348 }
77349
77350 return array_filter($this->errors, function ($error) use ($errorContext) {
77351 if ($errorContext & $error['context']) {
77352 return true;
77353 }
77354 });
77355 }
77356
77357 public function numErrors($errorContext = Validator::ERROR_ALL)
77358 {
77359 if ($errorContext === Validator::ERROR_ALL) {
77360 return count($this->errors);
77361 }
77362
77363 return count($this->getErrors($errorContext));
77364 }
77365
77366 public function isValid()
77367 {
77368 return !$this->getErrors();
77369 }
77370
77371
77372
77373
77374
77375 public function reset()
77376 {
77377 $this->errors = array();
77378 $this->errorMask = Validator::ERROR_NONE;
77379 }
77380
77381
77382
77383
77384
77385
77386 public function getErrorMask()
77387 {
77388 return $this->errorMask;
77389 }
77390
77391
77392
77393
77394
77395
77396
77397
77398 public static function arrayToObjectRecursive($array)
77399 {
77400 $json = json_encode($array);
77401 if (json_last_error() !== \JSON_ERROR_NONE) {
77402 $message = 'Unable to encode schema array as JSON';
77403 if (function_exists('json_last_error_msg')) {
77404 $message .= ': ' . json_last_error_msg();
77405 }
77406 throw new InvalidArgumentException($message);
77407 }
77408
77409 return (object) json_decode($json);
77410 }
77411 }
77412 <?php
77413
77414
77415
77416
77417
77418
77419
77420
77421 namespace JsonSchema\Constraints;
77422
77423 use JsonSchema\Entity\JsonPointer;
77424
77425
77426
77427
77428
77429
77430
77431 class CollectionConstraint extends Constraint
77432 {
77433
77434
77435
77436 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null)
77437 {
77438
77439  if (isset($schema->minItems) && count($value) < $schema->minItems) {
77440 $this->addError($path, 'There must be a minimum of ' . $schema->minItems . ' items in the array', 'minItems', array('minItems' => $schema->minItems));
77441 }
77442
77443
77444  if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
77445 $this->addError($path, 'There must be a maximum of ' . $schema->maxItems . ' items in the array', 'maxItems', array('maxItems' => $schema->maxItems));
77446 }
77447
77448
77449  if (isset($schema->uniqueItems) && $schema->uniqueItems) {
77450 $unique = $value;
77451 if (is_array($value) && count($value)) {
77452 $unique = array_map(function ($e) {
77453 return var_export($e, true);
77454 }, $value);
77455 }
77456 if (count(array_unique($unique)) != count($value)) {
77457 $this->addError($path, 'There are no duplicates allowed in the array', 'uniqueItems');
77458 }
77459 }
77460
77461
77462  if (isset($schema->items)) {
77463 $this->validateItems($value, $schema, $path, $i);
77464 }
77465 }
77466
77467
77468
77469
77470
77471
77472
77473
77474
77475 protected function validateItems(&$value, $schema = null, JsonPointer $path = null, $i = null)
77476 {
77477 if (is_object($schema->items)) {
77478
77479
77480 if (isset($schema->items->type)
77481 && (
77482 $schema->items->type == 'string'
77483 || $schema->items->type == 'number'
77484 || $schema->items->type == 'integer'
77485 )
77486 && !isset($schema->additionalItems)
77487 ) {
77488
77489  $type = $schema->items->type;
77490 $typeValidator = $this->factory->createInstanceFor('type');
77491 $validator = $this->factory->createInstanceFor($type === 'integer' ? 'number' : $type);
77492
77493 foreach ($value as $k => &$v) {
77494 $k_path = $this->incrementPath($path, $k);
77495 $typeValidator->check($v, $schema->items, $k_path, $i);
77496
77497 $validator->check($v, $schema->items, $k_path, $i);
77498 }
77499 unset($v); 
77500
77501 $this->addErrors($typeValidator->getErrors());
77502 $this->addErrors($validator->getErrors());
77503 } else {
77504 foreach ($value as $k => &$v) {
77505 $initErrors = $this->getErrors();
77506
77507
77508  $this->checkUndefined($v, $schema->items, $path, $k);
77509
77510
77511  if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
77512 $secondErrors = $this->getErrors();
77513 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
77514 }
77515
77516
77517  if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
77518 $this->errors = $secondErrors;
77519 } elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
77520 $this->errors = $initErrors;
77521 }
77522 }
77523 unset($v); 
77524
77525 }
77526 } else {
77527
77528  foreach ($value as $k => &$v) {
77529 if (array_key_exists($k, $schema->items)) {
77530 $this->checkUndefined($v, $schema->items[$k], $path, $k);
77531 } else {
77532
77533  if (property_exists($schema, 'additionalItems')) {
77534 if ($schema->additionalItems !== false) {
77535 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
77536 } else {
77537 $this->addError(
77538 $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems));
77539 }
77540 } else {
77541
77542  $this->checkUndefined($v, new \stdClass(), $path, $k);
77543 }
77544 }
77545 }
77546 unset($v); 
77547
77548
77549
77550  if (count($value) > 0) {
77551 for ($k = count($value); $k < count($schema->items); $k++) {
77552 $undefinedInstance = $this->factory->createInstanceFor('undefined');
77553 $this->checkUndefined($undefinedInstance, $schema->items[$k], $path, $k);
77554 }
77555 }
77556 }
77557 }
77558 }
77559 <?php
77560
77561
77562
77563
77564
77565
77566
77567
77568 namespace JsonSchema\Constraints;
77569
77570 use JsonSchema\Entity\JsonPointer;
77571
77572
77573
77574
77575
77576
77577
77578 abstract class Constraint extends BaseConstraint implements ConstraintInterface
77579 {
77580 protected $inlineSchemaProperty = '$schema';
77581
77582 const CHECK_MODE_NONE = 0x00000000;
77583 const CHECK_MODE_NORMAL = 0x00000001;
77584 const CHECK_MODE_TYPE_CAST = 0x00000002;
77585 const CHECK_MODE_COERCE_TYPES = 0x00000004;
77586 const CHECK_MODE_APPLY_DEFAULTS = 0x00000008;
77587 const CHECK_MODE_EXCEPTIONS = 0x00000010;
77588 const CHECK_MODE_DISABLE_FORMAT = 0x00000020;
77589 const CHECK_MODE_ONLY_REQUIRED_DEFAULTS = 0x00000080;
77590 const CHECK_MODE_VALIDATE_SCHEMA = 0x00000100;
77591
77592
77593
77594
77595
77596
77597
77598
77599
77600 protected function incrementPath(JsonPointer $path = null, $i)
77601 {
77602 $path = $path ?: new JsonPointer('');
77603 $path = $path->withPropertyPaths(
77604 array_merge(
77605 $path->getPropertyPaths(),
77606 array_filter(array($i), 'strlen')
77607 )
77608 );
77609
77610 return $path;
77611 }
77612
77613
77614
77615
77616
77617
77618
77619
77620
77621 protected function checkArray(&$value, $schema = null, JsonPointer $path = null, $i = null)
77622 {
77623 $validator = $this->factory->createInstanceFor('collection');
77624 $validator->check($value, $schema, $path, $i);
77625
77626 $this->addErrors($validator->getErrors());
77627 }
77628
77629
77630
77631
77632
77633
77634
77635
77636
77637
77638
77639 protected function checkObject(&$value, $schema = null, JsonPointer $path = null, $properties = null,
77640 $additionalProperties = null, $patternProperties = null, $appliedDefaults = array())
77641 {
77642 $validator = $this->factory->createInstanceFor('object');
77643 $validator->check($value, $schema, $path, $properties, $additionalProperties, $patternProperties, $appliedDefaults);
77644
77645 $this->addErrors($validator->getErrors());
77646 }
77647
77648
77649
77650
77651
77652
77653
77654
77655
77656 protected function checkType(&$value, $schema = null, JsonPointer $path = null, $i = null)
77657 {
77658 $validator = $this->factory->createInstanceFor('type');
77659 $validator->check($value, $schema, $path, $i);
77660
77661 $this->addErrors($validator->getErrors());
77662 }
77663
77664
77665
77666
77667
77668
77669
77670
77671
77672 protected function checkUndefined(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
77673 {
77674 $validator = $this->factory->createInstanceFor('undefined');
77675
77676 $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i, $fromDefault);
77677
77678 $this->addErrors($validator->getErrors());
77679 }
77680
77681
77682
77683
77684
77685
77686
77687
77688
77689 protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
77690 {
77691 $validator = $this->factory->createInstanceFor('string');
77692 $validator->check($value, $schema, $path, $i);
77693
77694 $this->addErrors($validator->getErrors());
77695 }
77696
77697
77698
77699
77700
77701
77702
77703
77704
77705 protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
77706 {
77707 $validator = $this->factory->createInstanceFor('number');
77708 $validator->check($value, $schema, $path, $i);
77709
77710 $this->addErrors($validator->getErrors());
77711 }
77712
77713
77714
77715
77716
77717
77718
77719
77720
77721 protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
77722 {
77723 $validator = $this->factory->createInstanceFor('enum');
77724 $validator->check($value, $schema, $path, $i);
77725
77726 $this->addErrors($validator->getErrors());
77727 }
77728
77729
77730
77731
77732
77733
77734
77735
77736
77737 protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
77738 {
77739 $validator = $this->factory->createInstanceFor('format');
77740 $validator->check($value, $schema, $path, $i);
77741
77742 $this->addErrors($validator->getErrors());
77743 }
77744
77745
77746
77747
77748
77749
77750 protected function getTypeCheck()
77751 {
77752 return $this->factory->getTypeCheck();
77753 }
77754
77755
77756
77757
77758
77759
77760 protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
77761 {
77762 $result = array_map(
77763 function ($path) {
77764 return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
77765 },
77766 $pointer->getPropertyPaths()
77767 );
77768
77769 return trim(implode('', $result), '.');
77770 }
77771 }
77772 <?php
77773
77774
77775
77776
77777
77778
77779
77780
77781 namespace JsonSchema\Constraints;
77782
77783 use JsonSchema\Entity\JsonPointer;
77784
77785
77786
77787
77788
77789
77790 interface ConstraintInterface
77791 {
77792
77793
77794
77795
77796
77797 public function getErrors();
77798
77799
77800
77801
77802
77803
77804 public function addErrors(array $errors);
77805
77806
77807
77808
77809
77810
77811
77812
77813
77814 public function addError(JsonPointer $path = null, $message, $constraint='', array $more = null);
77815
77816
77817
77818
77819
77820
77821 public function isValid();
77822
77823
77824
77825
77826
77827
77828
77829
77830
77831
77832
77833
77834
77835 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null);
77836 }
77837 <?php
77838
77839
77840
77841
77842
77843
77844
77845
77846 namespace JsonSchema\Constraints;
77847
77848 use JsonSchema\Entity\JsonPointer;
77849
77850
77851
77852
77853
77854
77855
77856 class EnumConstraint extends Constraint
77857 {
77858
77859
77860
77861 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
77862 {
77863
77864  if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
77865 return;
77866 }
77867 $type = gettype($element);
77868
77869 foreach ($schema->enum as $enum) {
77870 $enumType = gettype($enum);
77871 if ($this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && $type == 'array' && $enumType == 'object') {
77872 if ((object) $element == $enum) {
77873 return;
77874 }
77875 }
77876
77877 if ($type === gettype($enum)) {
77878 if ($type == 'object') {
77879 if ($element == $enum) {
77880 return;
77881 }
77882 } elseif ($element === $enum) {
77883 return;
77884 }
77885 }
77886 }
77887
77888 $this->addError($path, 'Does not have a value in the enumeration ' . json_encode($schema->enum), 'enum', array('enum' => $schema->enum));
77889 }
77890 }
77891 <?php
77892
77893
77894
77895
77896
77897
77898
77899
77900 namespace JsonSchema\Constraints;
77901
77902 use JsonSchema\Exception\InvalidArgumentException;
77903 use JsonSchema\SchemaStorage;
77904 use JsonSchema\SchemaStorageInterface;
77905 use JsonSchema\Uri\UriRetriever;
77906 use JsonSchema\UriRetrieverInterface;
77907 use JsonSchema\Validator;
77908
77909
77910
77911
77912 class Factory
77913 {
77914
77915
77916
77917 protected $schemaStorage;
77918
77919
77920
77921
77922 protected $uriRetriever;
77923
77924
77925
77926
77927 private $checkMode = Constraint::CHECK_MODE_NORMAL;
77928
77929
77930
77931
77932 private $typeCheck = array();
77933
77934
77935
77936
77937 protected $errorContext = Validator::ERROR_DOCUMENT_VALIDATION;
77938
77939
77940
77941
77942 protected $constraintMap = array(
77943 'array' => 'JsonSchema\Constraints\CollectionConstraint',
77944 'collection' => 'JsonSchema\Constraints\CollectionConstraint',
77945 'object' => 'JsonSchema\Constraints\ObjectConstraint',
77946 'type' => 'JsonSchema\Constraints\TypeConstraint',
77947 'undefined' => 'JsonSchema\Constraints\UndefinedConstraint',
77948 'string' => 'JsonSchema\Constraints\StringConstraint',
77949 'number' => 'JsonSchema\Constraints\NumberConstraint',
77950 'enum' => 'JsonSchema\Constraints\EnumConstraint',
77951 'format' => 'JsonSchema\Constraints\FormatConstraint',
77952 'schema' => 'JsonSchema\Constraints\SchemaConstraint',
77953 'validator' => 'JsonSchema\Validator'
77954 );
77955
77956
77957
77958
77959 private $instanceCache = array();
77960
77961
77962
77963
77964
77965
77966 public function __construct(
77967 SchemaStorageInterface $schemaStorage = null,
77968 UriRetrieverInterface $uriRetriever = null,
77969 $checkMode = Constraint::CHECK_MODE_NORMAL
77970 ) {
77971
77972  $this->setConfig($checkMode);
77973
77974 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
77975 $this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
77976 }
77977
77978
77979
77980
77981
77982
77983 public function setConfig($checkMode = Constraint::CHECK_MODE_NORMAL)
77984 {
77985 $this->checkMode = $checkMode;
77986 }
77987
77988
77989
77990
77991
77992
77993 public function addConfig($options)
77994 {
77995 $this->checkMode |= $options;
77996 }
77997
77998
77999
78000
78001
78002
78003 public function removeConfig($options)
78004 {
78005 $this->checkMode &= ~$options;
78006 }
78007
78008
78009
78010
78011
78012
78013
78014
78015 public function getConfig($options = null)
78016 {
78017 if ($options === null) {
78018 return $this->checkMode;
78019 }
78020
78021 return $this->checkMode & $options;
78022 }
78023
78024
78025
78026
78027 public function getUriRetriever()
78028 {
78029 return $this->uriRetriever;
78030 }
78031
78032 public function getSchemaStorage()
78033 {
78034 return $this->schemaStorage;
78035 }
78036
78037 public function getTypeCheck()
78038 {
78039 if (!isset($this->typeCheck[$this->checkMode])) {
78040 $this->typeCheck[$this->checkMode] = ($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST)
78041 ? new TypeCheck\LooseTypeCheck()
78042 : new TypeCheck\StrictTypeCheck();
78043 }
78044
78045 return $this->typeCheck[$this->checkMode];
78046 }
78047
78048
78049
78050
78051
78052
78053
78054 public function setConstraintClass($name, $class)
78055 {
78056
78057  if (!class_exists($class)) {
78058 throw new InvalidArgumentException('Unknown constraint ' . $name);
78059 }
78060
78061  if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
78062 throw new InvalidArgumentException('Invalid class ' . $name);
78063 }
78064 $this->constraintMap[$name] = $class;
78065
78066 return $this;
78067 }
78068
78069
78070
78071
78072
78073
78074
78075
78076
78077
78078 public function createInstanceFor($constraintName)
78079 {
78080 if (!isset($this->constraintMap[$constraintName])) {
78081 throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
78082 }
78083
78084 if (!isset($this->instanceCache[$constraintName])) {
78085 $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
78086 }
78087
78088 return clone $this->instanceCache[$constraintName];
78089 }
78090
78091
78092
78093
78094
78095
78096 public function getErrorContext()
78097 {
78098 return $this->errorContext;
78099 }
78100
78101
78102
78103
78104
78105
78106 public function setErrorContext($errorContext)
78107 {
78108 $this->errorContext = $errorContext;
78109 }
78110 }
78111 <?php
78112
78113
78114
78115
78116
78117
78118
78119
78120 namespace JsonSchema\Constraints;
78121
78122 use JsonSchema\Entity\JsonPointer;
78123 use JsonSchema\Rfc3339;
78124
78125
78126
78127
78128
78129
78130
78131
78132 class FormatConstraint extends Constraint
78133 {
78134
78135
78136
78137 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
78138 {
78139 if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
78140 return;
78141 }
78142
78143 switch ($schema->format) {
78144 case 'date':
78145 if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
78146 $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format));
78147 }
78148 break;
78149
78150 case 'time':
78151 if (!$this->validateDateTime($element, 'H:i:s')) {
78152 $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format));
78153 }
78154 break;
78155
78156 case 'date-time':
78157 if (null === Rfc3339::createFromString($element)) {
78158 $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));
78159 }
78160 break;
78161
78162 case 'utc-millisec':
78163 if (!$this->validateDateTime($element, 'U')) {
78164 $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format));
78165 }
78166 break;
78167
78168 case 'regex':
78169 if (!$this->validateRegex($element)) {
78170 $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format));
78171 }
78172 break;
78173
78174 case 'color':
78175 if (!$this->validateColor($element)) {
78176 $this->addError($path, 'Invalid color', 'format', array('format' => $schema->format));
78177 }
78178 break;
78179
78180 case 'style':
78181 if (!$this->validateStyle($element)) {
78182 $this->addError($path, 'Invalid style', 'format', array('format' => $schema->format));
78183 }
78184 break;
78185
78186 case 'phone':
78187 if (!$this->validatePhone($element)) {
78188 $this->addError($path, 'Invalid phone number', 'format', array('format' => $schema->format));
78189 }
78190 break;
78191
78192 case 'uri':
78193 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
78194 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
78195 }
78196 break;
78197
78198 case 'uriref':
78199 case 'uri-reference':
78200 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
78201
78202  
78203  
78204  if (substr($element, 0, 2) === '//') { 
78205  $validURL = filter_var('scheme:' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
78206 } elseif (substr($element, 0, 1) === '/') { 
78207  $validURL = filter_var('scheme://host' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
78208 } elseif (strlen($element)) { 
78209  $pathParts = explode('/', $element, 2);
78210 if (strpos($pathParts[0], ':') !== false) {
78211 $validURL = null;
78212 } else {
78213 $validURL = filter_var('scheme://host/' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
78214 }
78215 } else {
78216 $validURL = null;
78217 }
78218 if ($validURL === null) {
78219 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
78220 }
78221 }
78222 break;
78223
78224 case 'email':
78225 $filterFlags = FILTER_NULL_ON_FAILURE;
78226 if (defined('FILTER_FLAG_EMAIL_UNICODE')) {
78227
78228  $filterFlags |= constant('FILTER_FLAG_EMAIL_UNICODE'); 
78229  }
78230 if (null === filter_var($element, FILTER_VALIDATE_EMAIL, $filterFlags)) {
78231 $this->addError($path, 'Invalid email', 'format', array('format' => $schema->format));
78232 }
78233 break;
78234
78235 case 'ip-address':
78236 case 'ipv4':
78237 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
78238 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
78239 }
78240 break;
78241
78242 case 'ipv6':
78243 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
78244 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
78245 }
78246 break;
78247
78248 case 'host-name':
78249 case 'hostname':
78250 if (!$this->validateHostname($element)) {
78251 $this->addError($path, 'Invalid hostname', 'format', array('format' => $schema->format));
78252 }
78253 break;
78254
78255 default:
78256
78257  
78258  
78259  
78260  
78261  
78262  break;
78263 }
78264 }
78265
78266 protected function validateDateTime($datetime, $format)
78267 {
78268 $dt = \DateTime::createFromFormat($format, $datetime);
78269
78270 if (!$dt) {
78271 return false;
78272 }
78273
78274 if ($datetime === $dt->format($format)) {
78275 return true;
78276 }
78277
78278
78279  
78280  
78281  
78282  if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', $datetime))) {
78283 return true;
78284 }
78285
78286 return false;
78287 }
78288
78289 protected function validateRegex($regex)
78290 {
78291 return false !== @preg_match('/' . $regex . '/u', '');
78292 }
78293
78294 protected function validateColor($color)
78295 {
78296 if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
78297 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
78298 'red', 'silver', 'teal', 'white', 'yellow'))) {
78299 return true;
78300 }
78301
78302 return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
78303 }
78304
78305 protected function validateStyle($style)
78306 {
78307 $properties = explode(';', rtrim($style, ';'));
78308 $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
78309
78310 return empty($invalidEntries);
78311 }
78312
78313 protected function validatePhone($phone)
78314 {
78315 return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
78316 }
78317
78318 protected function validateHostname($host)
78319 {
78320 $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';
78321
78322 return preg_match($hostnameRegex, $host);
78323 }
78324 }
78325 <?php
78326
78327
78328
78329
78330
78331
78332
78333
78334 namespace JsonSchema\Constraints;
78335
78336 use JsonSchema\Entity\JsonPointer;
78337
78338
78339
78340
78341
78342
78343
78344 class NumberConstraint extends Constraint
78345 {
78346
78347
78348
78349 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
78350 {
78351
78352  if (isset($schema->exclusiveMinimum)) {
78353 if (isset($schema->minimum)) {
78354 if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
78355 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum));
78356 } elseif ($element < $schema->minimum) {
78357 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
78358 }
78359 } else {
78360 $this->addError($path, 'Use of exclusiveMinimum requires presence of minimum', 'missingMinimum');
78361 }
78362 } elseif (isset($schema->minimum) && $element < $schema->minimum) {
78363 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
78364 }
78365
78366
78367  if (isset($schema->exclusiveMaximum)) {
78368 if (isset($schema->maximum)) {
78369 if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
78370 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum));
78371 } elseif ($element > $schema->maximum) {
78372 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
78373 }
78374 } else {
78375 $this->addError($path, 'Use of exclusiveMaximum requires presence of maximum', 'missingMaximum');
78376 }
78377 } elseif (isset($schema->maximum) && $element > $schema->maximum) {
78378 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
78379 }
78380
78381
78382  if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
78383 $this->addError($path, 'Is not divisible by ' . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy));
78384 }
78385
78386
78387  if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
78388 $this->addError($path, 'Must be a multiple of ' . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf));
78389 }
78390
78391 $this->checkFormat($element, $schema, $path, $i);
78392 }
78393
78394 private function fmod($number1, $number2)
78395 {
78396 $number1 = abs($number1);
78397 $modulus = fmod($number1, $number2);
78398 $precision = abs(0.0000000001);
78399 $diff = (float) ($modulus - $number2);
78400
78401 if (-$precision < $diff && $diff < $precision) {
78402 return 0.0;
78403 }
78404
78405 $decimals1 = mb_strpos($number1, '.') ? mb_strlen($number1) - mb_strpos($number1, '.') - 1 : 0;
78406 $decimals2 = mb_strpos($number2, '.') ? mb_strlen($number2) - mb_strpos($number2, '.') - 1 : 0;
78407
78408 return (float) round($modulus, max($decimals1, $decimals2));
78409 }
78410 }
78411 <?php
78412
78413
78414
78415
78416
78417
78418
78419
78420 namespace JsonSchema\Constraints;
78421
78422 use JsonSchema\Entity\JsonPointer;
78423
78424
78425
78426
78427
78428
78429
78430 class ObjectConstraint extends Constraint
78431 {
78432
78433
78434
78435 protected $appliedDefaults = array();
78436
78437
78438
78439
78440 public function check(&$element, $schema = null, JsonPointer $path = null, $properties = null,
78441 $additionalProp = null, $patternProperties = null, $appliedDefaults = array())
78442 {
78443 if ($element instanceof UndefinedConstraint) {
78444 return;
78445 }
78446
78447 $this->appliedDefaults = $appliedDefaults;
78448
78449 $matches = array();
78450 if ($patternProperties) {
78451
78452  $matches = $this->validatePatternProperties($element, $path, $patternProperties);
78453 }
78454
78455 if ($properties) {
78456
78457  $this->validateProperties($element, $properties, $path);
78458 }
78459
78460
78461  $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp);
78462 }
78463
78464 public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties)
78465 {
78466 $try = array('/', '#', '+', '~', '%');
78467 $matches = array();
78468 foreach ($patternProperties as $pregex => $schema) {
78469 $delimiter = '/';
78470
78471  foreach ($try as $delimiter) {
78472 if (strpos($pregex, $delimiter) === false) { 
78473  break;
78474 }
78475 }
78476
78477
78478  if (@preg_match($delimiter . $pregex . $delimiter . 'u', '') === false) {
78479 $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex));
78480 continue;
78481 }
78482 foreach ($element as $i => $value) {
78483 if (preg_match($delimiter . $pregex . $delimiter . 'u', $i)) {
78484 $matches[] = $i;
78485 $this->checkUndefined($value, $schema ?: new \stdClass(), $path, $i, in_array($i, $this->appliedDefaults));
78486 }
78487 }
78488 }
78489
78490 return $matches;
78491 }
78492
78493
78494
78495
78496
78497
78498
78499
78500
78501
78502
78503 public function validateElement($element, $matches, $schema = null, JsonPointer $path = null,
78504 $properties = null, $additionalProp = null)
78505 {
78506 $this->validateMinMaxConstraint($element, $schema, $path);
78507
78508 foreach ($element as $i => $value) {
78509 $definition = $this->getProperty($properties, $i);
78510
78511
78512  if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
78513 $this->addError($path, 'The property ' . $i . ' is not defined and the definition does not allow additional properties', 'additionalProp');
78514 }
78515
78516
78517  if (!in_array($i, $matches) && $additionalProp && !$definition) {
78518 if ($additionalProp === true) {
78519 $this->checkUndefined($value, null, $path, $i, in_array($i, $this->appliedDefaults));
78520 } else {
78521 $this->checkUndefined($value, $additionalProp, $path, $i, in_array($i, $this->appliedDefaults));
78522 }
78523 }
78524
78525
78526  $require = $this->getProperty($definition, 'requires');
78527 if ($require && !$this->getProperty($element, $require)) {
78528 $this->addError($path, 'The presence of the property ' . $i . ' requires that ' . $require . ' also be present', 'requires');
78529 }
78530
78531 $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
78532 if (is_object($property)) {
78533 $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
78534 }
78535 }
78536 }
78537
78538
78539
78540
78541
78542
78543
78544
78545 public function validateProperties(&$element, $properties = null, JsonPointer $path = null)
78546 {
78547 $undefinedConstraint = $this->factory->createInstanceFor('undefined');
78548
78549 foreach ($properties as $i => $value) {
78550 $property = &$this->getProperty($element, $i, $undefinedConstraint);
78551 $definition = $this->getProperty($properties, $i);
78552
78553 if (is_object($definition)) {
78554
78555  $this->checkUndefined($property, $definition, $path, $i, in_array($i, $this->appliedDefaults));
78556 }
78557 }
78558 }
78559
78560
78561
78562
78563
78564
78565
78566
78567
78568
78569 protected function &getProperty(&$element, $property, $fallback = null)
78570 {
78571 if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) ) {
78572 return $element[$property];
78573 } elseif (is_object($element) && property_exists($element, $property)) {
78574 return $element->$property;
78575 }
78576
78577 return $fallback;
78578 }
78579
78580
78581
78582
78583
78584
78585
78586
78587 protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null)
78588 {
78589
78590  if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
78591 if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
78592 $this->addError($path, 'Must contain a minimum of ' . $objectDefinition->minProperties . ' properties', 'minProperties', array('minProperties' => $objectDefinition->minProperties));
78593 }
78594 }
78595
78596  if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
78597 if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
78598 $this->addError($path, 'Must contain no more than ' . $objectDefinition->maxProperties . ' properties', 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties));
78599 }
78600 }
78601 }
78602 }
78603 <?php
78604
78605
78606
78607
78608
78609
78610
78611
78612 namespace JsonSchema\Constraints;
78613
78614 use JsonSchema\Entity\JsonPointer;
78615 use JsonSchema\Exception\InvalidArgumentException;
78616 use JsonSchema\Exception\InvalidSchemaException;
78617 use JsonSchema\Exception\RuntimeException;
78618 use JsonSchema\Validator;
78619
78620
78621
78622
78623
78624
78625
78626 class SchemaConstraint extends Constraint
78627 {
78628 const DEFAULT_SCHEMA_SPEC = 'http://json-schema.org/draft-04/schema#';
78629
78630
78631
78632
78633 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
78634 {
78635 if ($schema !== null) {
78636
78637  $validationSchema = $schema;
78638 } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
78639
78640  $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
78641 } else {
78642 throw new InvalidArgumentException('no schema found to verify against');
78643 }
78644
78645
78646  if (is_array($validationSchema)) {
78647 $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema);
78648 }
78649
78650
78651  
78652  if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) {
78653 if (!$this->getTypeCheck()->isObject($validationSchema)) {
78654 throw new RuntimeException('Cannot validate the schema of a non-object');
78655 }
78656 if ($this->getTypeCheck()->propertyExists($validationSchema, '$schema')) {
78657 $schemaSpec = $this->getTypeCheck()->propertyGet($validationSchema, '$schema');
78658 } else {
78659 $schemaSpec = self::DEFAULT_SCHEMA_SPEC;
78660 }
78661
78662
78663  $schemaStorage = $this->factory->getSchemaStorage();
78664 if (!$this->getTypeCheck()->isObject($schemaSpec)) {
78665 $schemaSpec = $schemaStorage->getSchema($schemaSpec);
78666 }
78667
78668
78669  $initialErrorCount = $this->numErrors();
78670 $initialConfig = $this->factory->getConfig();
78671 $initialContext = $this->factory->getErrorContext();
78672 $this->factory->removeConfig(self::CHECK_MODE_VALIDATE_SCHEMA | self::CHECK_MODE_APPLY_DEFAULTS);
78673 $this->factory->addConfig(self::CHECK_MODE_TYPE_CAST);
78674 $this->factory->setErrorContext(Validator::ERROR_SCHEMA_VALIDATION);
78675
78676
78677  try {
78678 $this->check($validationSchema, $schemaSpec);
78679 } catch (\Exception $e) {
78680 if ($this->factory->getConfig(self::CHECK_MODE_EXCEPTIONS)) {
78681 throw new InvalidSchemaException('Schema did not pass validation', 0, $e);
78682 }
78683 }
78684 if ($this->numErrors() > $initialErrorCount) {
78685 $this->addError($path, 'Schema is not valid', 'schema');
78686 }
78687
78688
78689  $this->factory->setConfig($initialConfig);
78690 $this->factory->setErrorContext($initialContext);
78691 }
78692
78693
78694  $this->checkUndefined($element, $validationSchema, $path, $i);
78695 }
78696 }
78697 <?php
78698
78699
78700
78701
78702
78703
78704
78705
78706 namespace JsonSchema\Constraints;
78707
78708 use JsonSchema\Entity\JsonPointer;
78709
78710
78711
78712
78713
78714
78715
78716 class StringConstraint extends Constraint
78717 {
78718
78719
78720
78721 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
78722 {
78723
78724  if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
78725 $this->addError($path, 'Must be at most ' . $schema->maxLength . ' characters long', 'maxLength', array(
78726 'maxLength' => $schema->maxLength,
78727 ));
78728 }
78729
78730
78731  if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
78732 $this->addError($path, 'Must be at least ' . $schema->minLength . ' characters long', 'minLength', array(
78733 'minLength' => $schema->minLength,
78734 ));
78735 }
78736
78737
78738  if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#u', $element)) {
78739 $this->addError($path, 'Does not match the regex pattern ' . $schema->pattern, 'pattern', array(
78740 'pattern' => $schema->pattern,
78741 ));
78742 }
78743
78744 $this->checkFormat($element, $schema, $path, $i);
78745 }
78746
78747 private function strlen($string)
78748 {
78749 if (extension_loaded('mbstring')) {
78750 return mb_strlen($string, mb_detect_encoding($string));
78751 }
78752
78753
78754  return strlen($string); 
78755  }
78756 }
78757 <?php
78758
78759 namespace JsonSchema\Constraints\TypeCheck;
78760
78761 class LooseTypeCheck implements TypeCheckInterface
78762 {
78763 public static function isObject($value)
78764 {
78765 return
78766 is_object($value) ||
78767 (is_array($value) && (count($value) == 0 || self::isAssociativeArray($value)));
78768 }
78769
78770 public static function isArray($value)
78771 {
78772 return
78773 is_array($value) &&
78774 (count($value) == 0 || !self::isAssociativeArray($value));
78775 }
78776
78777 public static function propertyGet($value, $property)
78778 {
78779 if (is_object($value)) {
78780 return $value->{$property};
78781 }
78782
78783 return $value[$property];
78784 }
78785
78786 public static function propertySet(&$value, $property, $data)
78787 {
78788 if (is_object($value)) {
78789 $value->{$property} = $data;
78790 } else {
78791 $value[$property] = $data;
78792 }
78793 }
78794
78795 public static function propertyExists($value, $property)
78796 {
78797 if (is_object($value)) {
78798 return property_exists($value, $property);
78799 }
78800
78801 return array_key_exists($property, $value);
78802 }
78803
78804 public static function propertyCount($value)
78805 {
78806 if (is_object($value)) {
78807 return count(get_object_vars($value));
78808 }
78809
78810 return count($value);
78811 }
78812
78813
78814
78815
78816
78817
78818
78819
78820 private static function isAssociativeArray($arr)
78821 {
78822 return array_keys($arr) !== range(0, count($arr) - 1);
78823 }
78824 }
78825 <?php
78826
78827 namespace JsonSchema\Constraints\TypeCheck;
78828
78829 class StrictTypeCheck implements TypeCheckInterface
78830 {
78831 public static function isObject($value)
78832 {
78833 return is_object($value);
78834 }
78835
78836 public static function isArray($value)
78837 {
78838 return is_array($value);
78839 }
78840
78841 public static function propertyGet($value, $property)
78842 {
78843 return $value->{$property};
78844 }
78845
78846 public static function propertySet(&$value, $property, $data)
78847 {
78848 $value->{$property} = $data;
78849 }
78850
78851 public static function propertyExists($value, $property)
78852 {
78853 return property_exists($value, $property);
78854 }
78855
78856 public static function propertyCount($value)
78857 {
78858 return count(get_object_vars($value));
78859 }
78860 }
78861 <?php
78862
78863 namespace JsonSchema\Constraints\TypeCheck;
78864
78865 interface TypeCheckInterface
78866 {
78867 public static function isObject($value);
78868
78869 public static function isArray($value);
78870
78871 public static function propertyGet($value, $property);
78872
78873 public static function propertySet(&$value, $property, $data);
78874
78875 public static function propertyExists($value, $property);
78876
78877 public static function propertyCount($value);
78878 }
78879 <?php
78880
78881
78882
78883
78884
78885
78886
78887
78888 namespace JsonSchema\Constraints;
78889
78890 use JsonSchema\Entity\JsonPointer;
78891 use JsonSchema\Exception\InvalidArgumentException;
78892 use UnexpectedValueException as StandardUnexpectedValueException;
78893
78894
78895
78896
78897
78898
78899
78900 class TypeConstraint extends Constraint
78901 {
78902
78903
78904
78905 public static $wording = array(
78906 'integer' => 'an integer',
78907 'number' => 'a number',
78908 'boolean' => 'a boolean',
78909 'object' => 'an object',
78910 'array' => 'an array',
78911 'string' => 'a string',
78912 'null' => 'a null',
78913 'any' => null, 
78914  0 => null, 
78915  );
78916
78917
78918
78919
78920 public function check(&$value = null, $schema = null, JsonPointer $path = null, $i = null)
78921 {
78922 $type = isset($schema->type) ? $schema->type : null;
78923 $isValid = false;
78924 $wording = array();
78925
78926 if (is_array($type)) {
78927 $this->validateTypesArray($value, $type, $wording, $isValid, $path);
78928 } elseif (is_object($type)) {
78929 $this->checkUndefined($value, $type, $path);
78930
78931 return;
78932 } else {
78933 $isValid = $this->validateType($value, $type);
78934 }
78935
78936 if ($isValid === false) {
78937 if (!is_array($type)) {
78938 $this->validateTypeNameWording($type);
78939 $wording[] = self::$wording[$type];
78940 }
78941 $this->addError($path, ucwords(gettype($value)) . ' value found, but ' .
78942 $this->implodeWith($wording, ', ', 'or') . ' is required', 'type');
78943 }
78944 }
78945
78946
78947
78948
78949
78950
78951
78952
78953
78954
78955
78956
78957 protected function validateTypesArray(&$value, array $type, &$validTypesWording, &$isValid, $path)
78958 {
78959 foreach ($type as $tp) {
78960
78961  
78962  if (is_object($tp)) {
78963 if (!$isValid) {
78964 $validator = $this->factory->createInstanceFor('type');
78965 $subSchema = new \stdClass();
78966 $subSchema->type = $tp;
78967 $validator->check($value, $subSchema, $path, null);
78968 $error = $validator->getErrors();
78969 $isValid = !(bool) $error;
78970 $validTypesWording[] = self::$wording['object'];
78971 }
78972 } else {
78973 $this->validateTypeNameWording($tp);
78974 $validTypesWording[] = self::$wording[$tp];
78975 if (!$isValid) {
78976 $isValid = $this->validateType($value, $tp);
78977 }
78978 }
78979 }
78980 }
78981
78982
78983
78984
78985
78986
78987
78988
78989
78990
78991
78992
78993 protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = false)
78994 {
78995 if ($listEnd === false || !isset($elements[1])) {
78996 return implode($delimiter, $elements);
78997 }
78998 $lastElement = array_slice($elements, -1);
78999 $firsElements = join($delimiter, array_slice($elements, 0, -1));
79000 $implodedElements = array_merge(array($firsElements), $lastElement);
79001
79002 return join(" $listEnd ", $implodedElements);
79003 }
79004
79005
79006
79007
79008
79009
79010
79011
79012
79013 protected function validateTypeNameWording($type)
79014 {
79015 if (!isset(self::$wording[$type])) {
79016 throw new StandardUnexpectedValueException(
79017 sprintf(
79018 'No wording for %s available, expected wordings are: [%s]',
79019 var_export($type, true),
79020 implode(', ', array_filter(self::$wording)))
79021 );
79022 }
79023 }
79024
79025
79026
79027
79028
79029
79030
79031
79032
79033
79034
79035 protected function validateType(&$value, $type)
79036 {
79037
79038  if (!$type) {
79039 return true;
79040 }
79041
79042 if ('any' === $type) {
79043 return true;
79044 }
79045
79046 if ('object' === $type) {
79047 return $this->getTypeCheck()->isObject($value);
79048 }
79049
79050 if ('array' === $type) {
79051 return $this->getTypeCheck()->isArray($value);
79052 }
79053
79054 $coerce = $this->factory->getConfig(Constraint::CHECK_MODE_COERCE_TYPES);
79055
79056 if ('integer' === $type) {
79057 if ($coerce) {
79058 $value = $this->toInteger($value);
79059 }
79060
79061 return is_int($value);
79062 }
79063
79064 if ('number' === $type) {
79065 if ($coerce) {
79066 $value = $this->toNumber($value);
79067 }
79068
79069 return is_numeric($value) && !is_string($value);
79070 }
79071
79072 if ('boolean' === $type) {
79073 if ($coerce) {
79074 $value = $this->toBoolean($value);
79075 }
79076
79077 return is_bool($value);
79078 }
79079
79080 if ('string' === $type) {
79081 return is_string($value);
79082 }
79083
79084 if ('email' === $type) {
79085 return is_string($value);
79086 }
79087
79088 if ('null' === $type) {
79089 return is_null($value);
79090 }
79091
79092 throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
79093 }
79094
79095
79096
79097
79098
79099
79100
79101
79102 protected function toBoolean($value)
79103 {
79104 if ($value === 'true') {
79105 return true;
79106 }
79107
79108 if ($value === 'false') {
79109 return false;
79110 }
79111
79112 return $value;
79113 }
79114
79115
79116
79117
79118
79119
79120
79121
79122 protected function toNumber($value)
79123 {
79124 if (is_numeric($value)) {
79125 return $value + 0; 
79126  }
79127
79128 return $value;
79129 }
79130
79131 protected function toInteger($value)
79132 {
79133 if (is_numeric($value) && (int) $value == $value) {
79134 return (int) $value; 
79135  }
79136
79137 return $value;
79138 }
79139 }
79140 <?php
79141
79142
79143
79144
79145
79146
79147
79148
79149 namespace JsonSchema\Constraints;
79150
79151 use JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
79152 use JsonSchema\Entity\JsonPointer;
79153 use JsonSchema\Exception\ValidationException;
79154 use JsonSchema\Uri\UriResolver;
79155
79156
79157
79158
79159
79160
79161
79162 class UndefinedConstraint extends Constraint
79163 {
79164
79165
79166
79167 protected $appliedDefaults = array();
79168
79169
79170
79171
79172 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
79173 {
79174 if (is_null($schema) || !is_object($schema)) {
79175 return;
79176 }
79177
79178 $path = $this->incrementPath($path ?: new JsonPointer(''), $i);
79179 if ($fromDefault) {
79180 $path->setFromDefault();
79181 }
79182
79183
79184  $this->validateCommonProperties($value, $schema, $path, $i);
79185
79186
79187  $this->validateOfProperties($value, $schema, $path, '');
79188
79189
79190  $this->validateTypes($value, $schema, $path, $i);
79191 }
79192
79193
79194
79195
79196
79197
79198
79199
79200
79201 public function validateTypes(&$value, $schema = null, JsonPointer $path, $i = null)
79202 {
79203
79204  if ($this->getTypeCheck()->isArray($value)) {
79205 $this->checkArray($value, $schema, $path, $i);
79206 }
79207
79208
79209  if (LooseTypeCheck::isObject($value)) { 
79210  
79211  
79212  $this->checkObject(
79213 $value,
79214 $schema,
79215 $path,
79216 isset($schema->properties) ? $schema->properties : null,
79217 isset($schema->additionalProperties) ? $schema->additionalProperties : null,
79218 isset($schema->patternProperties) ? $schema->patternProperties : null,
79219 $this->appliedDefaults
79220 );
79221 }
79222
79223
79224  if (is_string($value)) {
79225 $this->checkString($value, $schema, $path, $i);
79226 }
79227
79228
79229  if (is_numeric($value)) {
79230 $this->checkNumber($value, $schema, $path, $i);
79231 }
79232
79233
79234  if (isset($schema->enum)) {
79235 $this->checkEnum($value, $schema, $path, $i);
79236 }
79237 }
79238
79239
79240
79241
79242
79243
79244
79245
79246
79247 protected function validateCommonProperties(&$value, $schema = null, JsonPointer $path, $i = '')
79248 {
79249
79250  if (isset($schema->extends)) {
79251 if (is_string($schema->extends)) {
79252 $schema->extends = $this->validateUri($schema, $schema->extends);
79253 }
79254 if (is_array($schema->extends)) {
79255 foreach ($schema->extends as $extends) {
79256 $this->checkUndefined($value, $extends, $path, $i);
79257 }
79258 } else {
79259 $this->checkUndefined($value, $schema->extends, $path, $i);
79260 }
79261 }
79262
79263
79264  if (!$path->fromDefault()) {
79265 $this->applyDefaultValues($value, $schema, $path);
79266 }
79267
79268
79269  if ($this->getTypeCheck()->isObject($value)) {
79270 if (!($value instanceof self) && isset($schema->required) && is_array($schema->required)) {
79271
79272  foreach ($schema->required as $required) {
79273 if (!$this->getTypeCheck()->propertyExists($value, $required)) {
79274 $this->addError(
79275 $this->incrementPath($path ?: new JsonPointer(''), $required),
79276 'The property ' . $required . ' is required',
79277 'required'
79278 );
79279 }
79280 }
79281 } elseif (isset($schema->required) && !is_array($schema->required)) {
79282
79283  if ($schema->required && $value instanceof self) {
79284 $propertyPaths = $path->getPropertyPaths();
79285 $propertyName = end($propertyPaths);
79286 $this->addError(
79287 $path,
79288 'The property ' . $propertyName . ' is required',
79289 'required'
79290 );
79291 }
79292 }
79293 }
79294
79295
79296  if (!($value instanceof self)) {
79297 $this->checkType($value, $schema, $path, $i);
79298 }
79299
79300
79301  if (isset($schema->disallow)) {
79302 $initErrors = $this->getErrors();
79303
79304 $typeSchema = new \stdClass();
79305 $typeSchema->type = $schema->disallow;
79306 $this->checkType($value, $typeSchema, $path);
79307
79308
79309  if (count($this->getErrors()) == count($initErrors)) {
79310 $this->addError($path, 'Disallowed value was matched', 'disallow');
79311 } else {
79312 $this->errors = $initErrors;
79313 }
79314 }
79315
79316 if (isset($schema->not)) {
79317 $initErrors = $this->getErrors();
79318 $this->checkUndefined($value, $schema->not, $path, $i);
79319
79320
79321  if (count($this->getErrors()) == count($initErrors)) {
79322 $this->addError($path, 'Matched a schema which it should not', 'not');
79323 } else {
79324 $this->errors = $initErrors;
79325 }
79326 }
79327
79328
79329  if (isset($schema->dependencies) && $this->getTypeCheck()->isObject($value)) {
79330 $this->validateDependencies($value, $schema->dependencies, $path);
79331 }
79332 }
79333
79334
79335
79336
79337
79338
79339
79340
79341
79342
79343 private function shouldApplyDefaultValue($requiredOnly, $schema, $name = null, $parentSchema = null)
79344 {
79345
79346  if (!$requiredOnly) {
79347 return true;
79348 }
79349
79350  if (
79351 $name !== null
79352 && isset($parentSchema->required)
79353 && is_array($parentSchema->required)
79354 && in_array($name, $parentSchema->required)
79355 ) {
79356 return true;
79357 }
79358
79359  if (isset($schema->required) && !is_array($schema->required) && $schema->required) {
79360 return true;
79361 }
79362
79363  return false;
79364 }
79365
79366
79367
79368
79369
79370
79371
79372
79373 protected function applyDefaultValues(&$value, $schema, $path)
79374 {
79375
79376  if (!$this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
79377 return;
79378 }
79379
79380
79381  $requiredOnly = $this->factory->getConfig(self::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);
79382 if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
79383
79384  foreach ($schema->properties as $currentProperty => $propertyDefinition) {
79385 $propertyDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($propertyDefinition);
79386 if (
79387 !LooseTypeCheck::propertyExists($value, $currentProperty)
79388 && property_exists($propertyDefinition, 'default')
79389 && $this->shouldApplyDefaultValue($requiredOnly, $propertyDefinition, $currentProperty, $schema)
79390 ) {
79391
79392  if (is_object($propertyDefinition->default)) {
79393 LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
79394 } else {
79395 LooseTypeCheck::propertySet($value, $currentProperty, $propertyDefinition->default);
79396 }
79397 $this->appliedDefaults[] = $currentProperty;
79398 }
79399 }
79400 } elseif (isset($schema->items) && LooseTypeCheck::isArray($value)) {
79401 $items = array();
79402 if (LooseTypeCheck::isArray($schema->items)) {
79403 $items = $schema->items;
79404 } elseif (isset($schema->minItems) && count($value) < $schema->minItems) {
79405 $items = array_fill(count($value), $schema->minItems - count($value), $schema->items);
79406 }
79407
79408  foreach ($items as $currentItem => $itemDefinition) {
79409 $itemDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($itemDefinition);
79410 if (
79411 !array_key_exists($currentItem, $value)
79412 && property_exists($itemDefinition, 'default')
79413 && $this->shouldApplyDefaultValue($requiredOnly, $itemDefinition)) {
79414 if (is_object($itemDefinition->default)) {
79415 $value[$currentItem] = clone $itemDefinition->default;
79416 } else {
79417 $value[$currentItem] = $itemDefinition->default;
79418 }
79419 }
79420 $path->setFromDefault();
79421 }
79422 } elseif (
79423 $value instanceof self
79424 && property_exists($schema, 'default')
79425 && $this->shouldApplyDefaultValue($requiredOnly, $schema)) {
79426
79427  $value = is_object($schema->default) ? clone $schema->default : $schema->default;
79428 $path->setFromDefault();
79429 }
79430 }
79431
79432
79433
79434
79435
79436
79437
79438
79439
79440 protected function validateOfProperties(&$value, $schema, JsonPointer $path, $i = '')
79441 {
79442
79443  if ($value instanceof self) {
79444 return;
79445 }
79446
79447 if (isset($schema->allOf)) {
79448 $isValid = true;
79449 foreach ($schema->allOf as $allOf) {
79450 $initErrors = $this->getErrors();
79451 $this->checkUndefined($value, $allOf, $path, $i);
79452 $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
79453 }
79454 if (!$isValid) {
79455 $this->addError($path, 'Failed to match all schemas', 'allOf');
79456 }
79457 }
79458
79459 if (isset($schema->anyOf)) {
79460 $isValid = false;
79461 $startErrors = $this->getErrors();
79462 $caughtException = null;
79463 foreach ($schema->anyOf as $anyOf) {
79464 $initErrors = $this->getErrors();
79465 try {
79466 $this->checkUndefined($value, $anyOf, $path, $i);
79467 if ($isValid = (count($this->getErrors()) == count($initErrors))) {
79468 break;
79469 }
79470 } catch (ValidationException $e) {
79471 $isValid = false;
79472 }
79473 }
79474 if (!$isValid) {
79475 $this->addError($path, 'Failed to match at least one schema', 'anyOf');
79476 } else {
79477 $this->errors = $startErrors;
79478 }
79479 }
79480
79481 if (isset($schema->oneOf)) {
79482 $allErrors = array();
79483 $matchedSchemas = 0;
79484 $startErrors = $this->getErrors();
79485 foreach ($schema->oneOf as $oneOf) {
79486 try {
79487 $this->errors = array();
79488 $this->checkUndefined($value, $oneOf, $path, $i);
79489 if (count($this->getErrors()) == 0) {
79490 $matchedSchemas++;
79491 }
79492 $allErrors = array_merge($allErrors, array_values($this->getErrors()));
79493 } catch (ValidationException $e) {
79494
79495  
79496  }
79497 }
79498 if ($matchedSchemas !== 1) {
79499 $this->addErrors(array_merge($allErrors, $startErrors));
79500 $this->addError($path, 'Failed to match exactly one schema', 'oneOf');
79501 } else {
79502 $this->errors = $startErrors;
79503 }
79504 }
79505 }
79506
79507
79508
79509
79510
79511
79512
79513
79514
79515 protected function validateDependencies($value, $dependencies, JsonPointer $path, $i = '')
79516 {
79517 foreach ($dependencies as $key => $dependency) {
79518 if ($this->getTypeCheck()->propertyExists($value, $key)) {
79519 if (is_string($dependency)) {
79520
79521  if (!$this->getTypeCheck()->propertyExists($value, $dependency)) {
79522 $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
79523 }
79524 } elseif (is_array($dependency)) {
79525
79526  foreach ($dependency as $d) {
79527 if (!$this->getTypeCheck()->propertyExists($value, $d)) {
79528 $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
79529 }
79530 }
79531 } elseif (is_object($dependency)) {
79532
79533  $this->checkUndefined($value, $dependency, $path, $i);
79534 }
79535 }
79536 }
79537 }
79538
79539 protected function validateUri($schema, $schemaUri = null)
79540 {
79541 $resolver = new UriResolver();
79542 $retriever = $this->factory->getUriRetriever();
79543
79544 $jsonSchema = null;
79545 if ($resolver->isValid($schemaUri)) {
79546 $schemaId = property_exists($schema, 'id') ? $schema->id : null;
79547 $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
79548 }
79549
79550 return $jsonSchema;
79551 }
79552 }
79553 <?php
79554
79555
79556
79557
79558
79559
79560
79561
79562 namespace JsonSchema\Entity;
79563
79564 use JsonSchema\Exception\InvalidArgumentException;
79565
79566
79567
79568
79569
79570
79571 class JsonPointer
79572 {
79573
79574 private $filename;
79575
79576
79577 private $propertyPaths = array();
79578
79579
79580
79581
79582 private $fromDefault = false;
79583
79584
79585
79586
79587
79588
79589 public function __construct($value)
79590 {
79591 if (!is_string($value)) {
79592 throw new InvalidArgumentException('Ref value must be a string');
79593 }
79594
79595 $splitRef = explode('#', $value, 2);
79596 $this->filename = $splitRef[0];
79597 if (array_key_exists(1, $splitRef)) {
79598 $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
79599 }
79600 }
79601
79602
79603
79604
79605
79606
79607 private function decodePropertyPaths($propertyPathString)
79608 {
79609 $paths = array();
79610 foreach (explode('/', trim($propertyPathString, '/')) as $path) {
79611 $path = $this->decodePath($path);
79612 if (is_string($path) && '' !== $path) {
79613 $paths[] = $path;
79614 }
79615 }
79616
79617 return $paths;
79618 }
79619
79620
79621
79622
79623 private function encodePropertyPaths()
79624 {
79625 return array_map(
79626 array($this, 'encodePath'),
79627 $this->getPropertyPaths()
79628 );
79629 }
79630
79631
79632
79633
79634
79635
79636 private function decodePath($path)
79637 {
79638 return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
79639 }
79640
79641
79642
79643
79644
79645
79646 private function encodePath($path)
79647 {
79648 return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
79649 }
79650
79651
79652
79653
79654 public function getFilename()
79655 {
79656 return $this->filename;
79657 }
79658
79659
79660
79661
79662 public function getPropertyPaths()
79663 {
79664 return $this->propertyPaths;
79665 }
79666
79667
79668
79669
79670
79671
79672 public function withPropertyPaths(array $propertyPaths)
79673 {
79674 $new = clone $this;
79675 $new->propertyPaths = $propertyPaths;
79676
79677 return $new;
79678 }
79679
79680
79681
79682
79683 public function getPropertyPathAsString()
79684 {
79685 return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
79686 }
79687
79688
79689
79690
79691 public function __toString()
79692 {
79693 return $this->getFilename() . $this->getPropertyPathAsString();
79694 }
79695
79696
79697
79698
79699 public function setFromDefault()
79700 {
79701 $this->fromDefault = true;
79702 }
79703
79704
79705
79706
79707
79708
79709 public function fromDefault()
79710 {
79711 return $this->fromDefault;
79712 }
79713 }
79714 <?php
79715
79716 namespace JsonSchema\Exception;
79717
79718 interface ExceptionInterface
79719 {
79720 }
79721 <?php
79722
79723
79724
79725
79726
79727
79728
79729
79730 namespace JsonSchema\Exception;
79731
79732
79733
79734
79735 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
79736 {
79737 }
79738 <?php
79739
79740
79741
79742
79743
79744
79745
79746
79747 namespace JsonSchema\Exception;
79748
79749
79750
79751
79752 class InvalidConfigException extends RuntimeException
79753 {
79754 }
79755 <?php
79756
79757
79758
79759
79760
79761
79762
79763
79764 namespace JsonSchema\Exception;
79765
79766
79767
79768
79769 class InvalidSchemaException extends RuntimeException
79770 {
79771 }
79772 <?php
79773
79774
79775
79776
79777
79778
79779
79780
79781 namespace JsonSchema\Exception;
79782
79783
79784
79785
79786 class InvalidSchemaMediaTypeException extends RuntimeException
79787 {
79788 }
79789 <?php
79790
79791
79792
79793
79794
79795
79796
79797
79798 namespace JsonSchema\Exception;
79799
79800
79801
79802
79803 class InvalidSourceUriException extends InvalidArgumentException
79804 {
79805 }
79806 <?php
79807
79808
79809
79810
79811
79812
79813
79814
79815 namespace JsonSchema\Exception;
79816
79817
79818
79819
79820 class JsonDecodingException extends RuntimeException
79821 {
79822 public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
79823 {
79824 switch ($code) {
79825 case JSON_ERROR_DEPTH:
79826 $message = 'The maximum stack depth has been exceeded';
79827 break;
79828 case JSON_ERROR_STATE_MISMATCH:
79829 $message = 'Invalid or malformed JSON';
79830 break;
79831 case JSON_ERROR_CTRL_CHAR:
79832 $message = 'Control character error, possibly incorrectly encoded';
79833 break;
79834 case JSON_ERROR_UTF8:
79835 $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
79836 break;
79837 case JSON_ERROR_SYNTAX:
79838 $message = 'JSON syntax is malformed';
79839 break;
79840 default:
79841 $message = 'Syntax error';
79842 }
79843 parent::__construct($message, $code, $previous);
79844 }
79845 }
79846 <?php
79847
79848
79849
79850
79851
79852
79853
79854
79855 namespace JsonSchema\Exception;
79856
79857
79858
79859
79860 class ResourceNotFoundException extends RuntimeException
79861 {
79862 }
79863 <?php
79864
79865
79866
79867
79868
79869
79870
79871
79872 namespace JsonSchema\Exception;
79873
79874
79875
79876
79877 class RuntimeException extends \RuntimeException implements ExceptionInterface
79878 {
79879 }
79880 <?php
79881
79882
79883
79884
79885
79886
79887
79888
79889 namespace JsonSchema\Exception;
79890
79891
79892
79893
79894
79895
79896 class UnresolvableJsonPointerException extends InvalidArgumentException
79897 {
79898 }
79899 <?php
79900
79901
79902
79903
79904
79905
79906
79907
79908 namespace JsonSchema\Exception;
79909
79910
79911
79912
79913 class UriResolverException extends RuntimeException
79914 {
79915 }
79916 <?php
79917
79918
79919
79920
79921
79922
79923
79924
79925 namespace JsonSchema\Exception;
79926
79927 class ValidationException extends RuntimeException
79928 {
79929 }
79930 <?php
79931
79932
79933
79934
79935
79936
79937
79938
79939 namespace JsonSchema\Iterator;
79940
79941
79942
79943
79944
79945
79946 class ObjectIterator implements \Iterator, \Countable
79947 {
79948
79949 private $object;
79950
79951
79952 private $position = 0;
79953
79954
79955 private $data = array();
79956
79957
79958 private $initialized = false;
79959
79960
79961
79962
79963 public function __construct($object)
79964 {
79965 $this->object = $object;
79966 }
79967
79968
79969
79970
79971 public function current()
79972 {
79973 $this->initialize();
79974
79975 return $this->data[$this->position];
79976 }
79977
79978
79979
79980
79981 public function next()
79982 {
79983 $this->initialize();
79984 $this->position++;
79985 }
79986
79987
79988
79989
79990 public function key()
79991 {
79992 $this->initialize();
79993
79994 return $this->position;
79995 }
79996
79997
79998
79999
80000 public function valid()
80001 {
80002 $this->initialize();
80003
80004 return isset($this->data[$this->position]);
80005 }
80006
80007
80008
80009
80010 public function rewind()
80011 {
80012 $this->initialize();
80013 $this->position = 0;
80014 }
80015
80016
80017
80018
80019 public function count()
80020 {
80021 $this->initialize();
80022
80023 return count($this->data);
80024 }
80025
80026
80027
80028
80029 private function initialize()
80030 {
80031 if (!$this->initialized) {
80032 $this->data = $this->buildDataFromObject($this->object);
80033 $this->initialized = true;
80034 }
80035 }
80036
80037
80038
80039
80040
80041
80042 private function buildDataFromObject($object)
80043 {
80044 $result = array();
80045
80046 $stack = new \SplStack();
80047 $stack->push($object);
80048
80049 while (!$stack->isEmpty()) {
80050 $current = $stack->pop();
80051 if (is_object($current)) {
80052 array_push($result, $current);
80053 }
80054
80055 foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
80056 if (is_object($propertyValue) || is_array($propertyValue)) {
80057 $stack->push($propertyValue);
80058 }
80059 }
80060 }
80061
80062 return $result;
80063 }
80064
80065
80066
80067
80068
80069
80070 private function getDataFromItem($item)
80071 {
80072 if (!is_object($item) && !is_array($item)) {
80073 return array();
80074 }
80075
80076 return is_object($item) ? get_object_vars($item) : $item;
80077 }
80078 }
80079 <?php
80080
80081 namespace JsonSchema;
80082
80083 class Rfc3339
80084 {
80085 const REGEX = '/^(\d{4}-\d{2}-\d{2}[T ]{1}\d{2}:\d{2}:\d{2})(\.\d+)?(Z|([+-]\d{2}):?(\d{2}))$/';
80086
80087
80088
80089
80090
80091
80092
80093
80094 public static function createFromString($string)
80095 {
80096 if (!preg_match(self::REGEX, strtoupper($string), $matches)) {
80097 return null;
80098 }
80099
80100 $dateAndTime = $matches[1];
80101 $microseconds = $matches[2] ?: '.000000';
80102 $timeZone = 'Z' !== $matches[3] ? $matches[4] . ':' . $matches[5] : '+00:00';
80103 $dateFormat = strpos($dateAndTime, 'T') === false ? 'Y-m-d H:i:s.uP' : 'Y-m-d\TH:i:s.uP';
80104 $dateTime = \DateTime::createFromFormat($dateFormat, $dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
80105
80106 return $dateTime ?: null;
80107 }
80108 }
80109 <?php
80110
80111 namespace JsonSchema;
80112
80113 use JsonSchema\Constraints\BaseConstraint;
80114 use JsonSchema\Entity\JsonPointer;
80115 use JsonSchema\Exception\UnresolvableJsonPointerException;
80116 use JsonSchema\Uri\UriResolver;
80117 use JsonSchema\Uri\UriRetriever;
80118
80119 class SchemaStorage implements SchemaStorageInterface
80120 {
80121 const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema/';
80122
80123 protected $uriRetriever;
80124 protected $uriResolver;
80125 protected $schemas = array();
80126
80127 public function __construct(
80128 UriRetrieverInterface $uriRetriever = null,
80129 UriResolverInterface $uriResolver = null
80130 ) {
80131 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
80132 $this->uriResolver = $uriResolver ?: new UriResolver();
80133 }
80134
80135
80136
80137
80138 public function getUriRetriever()
80139 {
80140 return $this->uriRetriever;
80141 }
80142
80143
80144
80145
80146 public function getUriResolver()
80147 {
80148 return $this->uriResolver;
80149 }
80150
80151
80152
80153
80154 public function addSchema($id, $schema = null)
80155 {
80156 if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) {
80157
80158  
80159  
80160  $schema = $this->uriRetriever->retrieve($id);
80161 }
80162
80163
80164  if (is_array($schema)) {
80165 $schema = BaseConstraint::arrayToObjectRecursive($schema);
80166 }
80167
80168
80169  
80170  if (is_object($schema) && property_exists($schema, 'id')) {
80171 if ($schema->id == 'http://json-schema.org/draft-04/schema#') {
80172 $schema->properties->id->format = 'uri-reference';
80173 } elseif ($schema->id == 'http://json-schema.org/draft-03/schema#') {
80174 $schema->properties->id->format = 'uri-reference';
80175 $schema->properties->{'$ref'}->format = 'uri-reference';
80176 }
80177 }
80178
80179
80180  $this->expandRefs($schema, $id);
80181
80182 $this->schemas[$id] = $schema;
80183 }
80184
80185
80186
80187
80188
80189
80190
80191 private function expandRefs(&$schema, $base = null)
80192 {
80193 if (!is_object($schema)) {
80194 if (is_array($schema)) {
80195 foreach ($schema as &$member) {
80196 $this->expandRefs($member, $base);
80197 }
80198 }
80199
80200 return;
80201 }
80202
80203 if (property_exists($schema, 'id') && is_string($schema->id) && $base != $schema->id) {
80204 $base = $this->uriResolver->resolve($schema->id, $base);
80205 }
80206
80207 if (property_exists($schema, '$ref') && is_string($schema->{'$ref'})) {
80208 $refPointer = new JsonPointer($this->uriResolver->resolve($schema->{'$ref'}, $base));
80209 $schema->{'$ref'} = (string) $refPointer;
80210 }
80211
80212 foreach ($schema as &$member) {
80213 $this->expandRefs($member, $base);
80214 }
80215 }
80216
80217
80218
80219
80220 public function getSchema($id)
80221 {
80222 if (!array_key_exists($id, $this->schemas)) {
80223 $this->addSchema($id);
80224 }
80225
80226 return $this->schemas[$id];
80227 }
80228
80229
80230
80231
80232 public function resolveRef($ref)
80233 {
80234 $jsonPointer = new JsonPointer($ref);
80235
80236
80237  $fileName = $jsonPointer->getFilename();
80238 if (!strlen($fileName)) {
80239 throw new UnresolvableJsonPointerException(sprintf(
80240 "Could not resolve fragment '%s': no file is defined",
80241 $jsonPointer->getPropertyPathAsString()
80242 ));
80243 }
80244
80245
80246  $refSchema = $this->getSchema($fileName);
80247 foreach ($jsonPointer->getPropertyPaths() as $path) {
80248 if (is_object($refSchema) && property_exists($refSchema, $path)) {
80249 $refSchema = $this->resolveRefSchema($refSchema->{$path});
80250 } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) {
80251 $refSchema = $this->resolveRefSchema($refSchema[$path]);
80252 } else {
80253 throw new UnresolvableJsonPointerException(sprintf(
80254 'File: %s is found, but could not resolve fragment: %s',
80255 $jsonPointer->getFilename(),
80256 $jsonPointer->getPropertyPathAsString()
80257 ));
80258 }
80259 }
80260
80261 return $refSchema;
80262 }
80263
80264
80265
80266
80267 public function resolveRefSchema($refSchema)
80268 {
80269 if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) {
80270 $newSchema = $this->resolveRef($refSchema->{'$ref'});
80271 $refSchema = (object) (get_object_vars($refSchema) + get_object_vars($newSchema));
80272 unset($refSchema->{'$ref'});
80273 }
80274
80275 return $refSchema;
80276 }
80277 }
80278 <?php
80279
80280 namespace JsonSchema;
80281
80282 interface SchemaStorageInterface
80283 {
80284
80285
80286
80287
80288
80289
80290 public function addSchema($id, $schema = null);
80291
80292
80293
80294
80295
80296
80297
80298
80299 public function getSchema($id);
80300
80301
80302
80303
80304
80305
80306
80307
80308 public function resolveRef($ref);
80309
80310
80311
80312
80313
80314
80315
80316
80317 public function resolveRefSchema($refSchema);
80318 }
80319 <?php
80320
80321
80322
80323
80324
80325
80326 namespace JsonSchema\Uri\Retrievers;
80327
80328
80329
80330
80331
80332
80333
80334 abstract class AbstractRetriever implements UriRetrieverInterface
80335 {
80336
80337
80338
80339
80340
80341 protected $contentType;
80342
80343
80344
80345
80346
80347
80348 public function getContentType()
80349 {
80350 return $this->contentType;
80351 }
80352 }
80353 <?php
80354
80355
80356
80357
80358
80359
80360
80361
80362 namespace JsonSchema\Uri\Retrievers;
80363
80364 use JsonSchema\Exception\RuntimeException;
80365 use JsonSchema\Validator;
80366
80367
80368
80369
80370
80371
80372 class Curl extends AbstractRetriever
80373 {
80374 protected $messageBody;
80375
80376 public function __construct()
80377 {
80378 if (!function_exists('curl_init')) {
80379
80380  throw new RuntimeException('cURL not installed'); 
80381  }
80382 }
80383
80384
80385
80386
80387
80388
80389 public function retrieve($uri)
80390 {
80391 $ch = curl_init();
80392
80393 curl_setopt($ch, CURLOPT_URL, $uri);
80394 curl_setopt($ch, CURLOPT_HEADER, true);
80395 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
80396 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
80397
80398 $response = curl_exec($ch);
80399 if (false === $response) {
80400 throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
80401 }
80402
80403 $this->fetchMessageBody($response);
80404 $this->fetchContentType($response);
80405
80406 curl_close($ch);
80407
80408 return $this->messageBody;
80409 }
80410
80411
80412
80413
80414 private function fetchMessageBody($response)
80415 {
80416 preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
80417 $this->messageBody = $match[1];
80418 }
80419
80420
80421
80422
80423
80424
80425 protected function fetchContentType($response)
80426 {
80427 if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
80428 $this->contentType = trim($match[1]);
80429
80430 return true;
80431 }
80432
80433 return false;
80434 }
80435 }
80436 <?php
80437
80438
80439
80440
80441
80442
80443
80444
80445 namespace JsonSchema\Uri\Retrievers;
80446
80447 use JsonSchema\Exception\ResourceNotFoundException;
80448
80449
80450
80451
80452
80453
80454 class FileGetContents extends AbstractRetriever
80455 {
80456 protected $messageBody;
80457
80458
80459
80460
80461
80462
80463 public function retrieve($uri)
80464 {
80465 $errorMessage = null;
80466 set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
80467 $errorMessage = $errstr;
80468 });
80469 $response = file_get_contents($uri);
80470 restore_error_handler();
80471
80472 if ($errorMessage) {
80473 throw new ResourceNotFoundException($errorMessage);
80474 }
80475
80476 if (false === $response) {
80477 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
80478 }
80479
80480 if ($response == ''
80481 && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
80482 ) {
80483 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
80484 }
80485
80486 $this->messageBody = $response;
80487 if (!empty($http_response_header)) {
80488
80489  
80490  $this->fetchContentType($http_response_header); 
80491  } else { 
80492  
80493  $this->contentType = null;
80494 }
80495
80496 return $this->messageBody;
80497 }
80498
80499
80500
80501
80502
80503
80504 private function fetchContentType(array $headers)
80505 {
80506 foreach ($headers as $header) {
80507 if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
80508 return true;
80509 }
80510 }
80511
80512 return false;
80513 }
80514
80515
80516
80517
80518
80519
80520 protected static function getContentTypeMatchInHeader($header)
80521 {
80522 if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
80523 return trim($match[1]);
80524 }
80525
80526 return null;
80527 }
80528 }
80529 <?php
80530
80531 namespace JsonSchema\Uri\Retrievers;
80532
80533 use JsonSchema\Validator;
80534
80535
80536
80537
80538
80539
80540
80541
80542
80543
80544
80545
80546
80547 class PredefinedArray extends AbstractRetriever
80548 {
80549
80550
80551
80552
80553
80554 private $schemas;
80555
80556
80557
80558
80559
80560
80561
80562 public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
80563 {
80564 $this->schemas = $schemas;
80565 $this->contentType = $contentType;
80566 }
80567
80568
80569
80570
80571
80572
80573 public function retrieve($uri)
80574 {
80575 if (!array_key_exists($uri, $this->schemas)) {
80576 throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
80577 'The JSON schema "%s" was not found.',
80578 $uri
80579 ));
80580 }
80581
80582 return $this->schemas[$uri];
80583 }
80584 }
80585 <?php
80586
80587
80588
80589
80590
80591
80592
80593
80594 namespace JsonSchema\Uri\Retrievers;
80595
80596
80597
80598
80599
80600
80601 interface UriRetrieverInterface
80602 {
80603
80604
80605
80606
80607
80608
80609
80610
80611
80612 public function retrieve($uri);
80613
80614
80615
80616
80617
80618
80619 public function getContentType();
80620 }
80621 <?php
80622
80623
80624
80625
80626
80627
80628
80629
80630 namespace JsonSchema\Uri;
80631
80632 use JsonSchema\Exception\UriResolverException;
80633 use JsonSchema\UriResolverInterface;
80634
80635
80636
80637
80638
80639
80640 class UriResolver implements UriResolverInterface
80641 {
80642
80643
80644
80645
80646
80647
80648
80649 public function parse($uri)
80650 {
80651 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
80652
80653 $components = array();
80654 if (5 < count($match)) {
80655 $components = array(
80656 'scheme' => $match[2],
80657 'authority' => $match[4],
80658 'path' => $match[5]
80659 );
80660 }
80661 if (7 < count($match)) {
80662 $components['query'] = $match[7];
80663 }
80664 if (9 < count($match)) {
80665 $components['fragment'] = $match[9];
80666 }
80667
80668 return $components;
80669 }
80670
80671
80672
80673
80674
80675
80676
80677
80678 public function generate(array $components)
80679 {
80680 $uri = $components['scheme'] . '://'
80681 . $components['authority']
80682 . $components['path'];
80683
80684 if (array_key_exists('query', $components) && strlen($components['query'])) {
80685 $uri .= '?' . $components['query'];
80686 }
80687 if (array_key_exists('fragment', $components)) {
80688 $uri .= '#' . $components['fragment'];
80689 }
80690
80691 return $uri;
80692 }
80693
80694
80695
80696
80697 public function resolve($uri, $baseUri = null)
80698 {
80699
80700  if (
80701 !is_null($baseUri) &&
80702 !filter_var($baseUri, \FILTER_VALIDATE_URL) &&
80703 !preg_match('|^[^/]+://|u', $baseUri)
80704 ) {
80705 if (is_file($baseUri)) {
80706 $baseUri = 'file://' . realpath($baseUri);
80707 } elseif (is_dir($baseUri)) {
80708 $baseUri = 'file://' . realpath($baseUri) . '/';
80709 } else {
80710 $baseUri = 'file://' . getcwd() . '/' . $baseUri;
80711 }
80712 }
80713
80714 if ($uri == '') {
80715 return $baseUri;
80716 }
80717
80718 $components = $this->parse($uri);
80719 $path = $components['path'];
80720
80721 if (!empty($components['scheme'])) {
80722 return $uri;
80723 }
80724 $baseComponents = $this->parse($baseUri);
80725 $basePath = $baseComponents['path'];
80726
80727 $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
80728 if (isset($components['fragment'])) {
80729 $baseComponents['fragment'] = $components['fragment'];
80730 }
80731
80732 return $this->generate($baseComponents);
80733 }
80734
80735
80736
80737
80738
80739
80740
80741
80742
80743
80744
80745 public static function combineRelativePathWithBasePath($relativePath, $basePath)
80746 {
80747 $relativePath = self::normalizePath($relativePath);
80748 if ($relativePath == '') {
80749 return $basePath;
80750 }
80751 if ($relativePath[0] == '/') {
80752 return $relativePath;
80753 }
80754
80755 $basePathSegments = explode('/', $basePath);
80756
80757 preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
80758 $numLevelUp = strlen($match[0]) /3 + 1;
80759 if ($numLevelUp >= count($basePathSegments)) {
80760 throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
80761 }
80762
80763 $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
80764 $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
80765
80766 return implode('/', $basePathSegments) . '/' . $path;
80767 }
80768
80769
80770
80771
80772
80773
80774
80775
80776 private static function normalizePath($path)
80777 {
80778 $path = preg_replace('|((?<!\.)\./)*|', '', $path);
80779 $path = preg_replace('|//|', '/', $path);
80780
80781 return $path;
80782 }
80783
80784
80785
80786
80787
80788
80789 public function isValid($uri)
80790 {
80791 $components = $this->parse($uri);
80792
80793 return !empty($components);
80794 }
80795 }
80796 <?php
80797
80798
80799
80800
80801
80802
80803
80804
80805 namespace JsonSchema\Uri;
80806
80807 use JsonSchema\Exception\InvalidSchemaMediaTypeException;
80808 use JsonSchema\Exception\JsonDecodingException;
80809 use JsonSchema\Exception\ResourceNotFoundException;
80810 use JsonSchema\Uri\Retrievers\FileGetContents;
80811 use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
80812 use JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
80813 use JsonSchema\Validator;
80814
80815
80816
80817
80818
80819
80820 class UriRetriever implements BaseUriRetrieverInterface
80821 {
80822
80823
80824
80825 protected $translationMap = array(
80826
80827  '|^https?://json-schema.org/draft-(0[34])/schema#?|' => 'package://dist/schema/json-schema-draft-$1.json'
80828 );
80829
80830
80831
80832
80833 protected $uriRetriever = null;
80834
80835
80836
80837
80838
80839
80840 private $schemaCache = array();
80841
80842
80843
80844
80845
80846
80847
80848
80849
80850 public function confirmMediaType($uriRetriever, $uri)
80851 {
80852 $contentType = $uriRetriever->getContentType();
80853
80854 if (is_null($contentType)) {
80855
80856  return;
80857 }
80858
80859 if (in_array($contentType, array(Validator::SCHEMA_MEDIA_TYPE, 'application/json'))) {
80860 return;
80861 }
80862
80863 if (substr($uri, 0, 23) == 'http://json-schema.org/') {
80864
80865  return true;
80866 }
80867
80868 throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
80869 }
80870
80871
80872
80873
80874
80875
80876
80877
80878
80879 public function getUriRetriever()
80880 {
80881 if (is_null($this->uriRetriever)) {
80882 $this->setUriRetriever(new FileGetContents());
80883 }
80884
80885 return $this->uriRetriever;
80886 }
80887
80888
80889
80890
80891
80892
80893
80894
80895
80896
80897
80898
80899
80900
80901
80902 public function resolvePointer($jsonSchema, $uri)
80903 {
80904 $resolver = new UriResolver();
80905 $parsed = $resolver->parse($uri);
80906 if (empty($parsed['fragment'])) {
80907 return $jsonSchema;
80908 }
80909
80910 $path = explode('/', $parsed['fragment']);
80911 while ($path) {
80912 $pathElement = array_shift($path);
80913 if (!empty($pathElement)) {
80914 $pathElement = str_replace('~1', '/', $pathElement);
80915 $pathElement = str_replace('~0', '~', $pathElement);
80916 if (!empty($jsonSchema->$pathElement)) {
80917 $jsonSchema = $jsonSchema->$pathElement;
80918 } else {
80919 throw new ResourceNotFoundException(
80920 'Fragment "' . $parsed['fragment'] . '" not found'
80921 . ' in ' . $uri
80922 );
80923 }
80924
80925 if (!is_object($jsonSchema)) {
80926 throw new ResourceNotFoundException(
80927 'Fragment part "' . $pathElement . '" is no object '
80928 . ' in ' . $uri
80929 );
80930 }
80931 }
80932 }
80933
80934 return $jsonSchema;
80935 }
80936
80937
80938
80939
80940 public function retrieve($uri, $baseUri = null, $translate = true)
80941 {
80942 $resolver = new UriResolver();
80943 $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
80944
80945
80946  $arParts = $resolver->parse($resolvedUri);
80947 if (isset($arParts['fragment'])) {
80948 unset($arParts['fragment']);
80949 $fetchUri = $resolver->generate($arParts);
80950 }
80951
80952
80953  if ($translate) {
80954 $fetchUri = $this->translate($fetchUri);
80955 }
80956
80957 $jsonSchema = $this->loadSchema($fetchUri);
80958
80959
80960  $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
80961
80962 if ($jsonSchema instanceof \stdClass) {
80963 $jsonSchema->id = $resolvedUri;
80964 }
80965
80966 return $jsonSchema;
80967 }
80968
80969
80970
80971
80972
80973
80974
80975
80976
80977 protected function loadSchema($fetchUri)
80978 {
80979 if (isset($this->schemaCache[$fetchUri])) {
80980 return $this->schemaCache[$fetchUri];
80981 }
80982
80983 $uriRetriever = $this->getUriRetriever();
80984 $contents = $this->uriRetriever->retrieve($fetchUri);
80985 $this->confirmMediaType($uriRetriever, $fetchUri);
80986 $jsonSchema = json_decode($contents);
80987
80988 if (JSON_ERROR_NONE < $error = json_last_error()) {
80989 throw new JsonDecodingException($error);
80990 }
80991
80992 $this->schemaCache[$fetchUri] = $jsonSchema;
80993
80994 return $jsonSchema;
80995 }
80996
80997
80998
80999
81000
81001
81002
81003
81004 public function setUriRetriever(UriRetrieverInterface $uriRetriever)
81005 {
81006 $this->uriRetriever = $uriRetriever;
81007
81008 return $this;
81009 }
81010
81011
81012
81013
81014
81015
81016
81017
81018 public function parse($uri)
81019 {
81020 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
81021
81022 $components = array();
81023 if (5 < count($match)) {
81024 $components = array(
81025 'scheme' => $match[2],
81026 'authority' => $match[4],
81027 'path' => $match[5]
81028 );
81029 }
81030
81031 if (7 < count($match)) {
81032 $components['query'] = $match[7];
81033 }
81034
81035 if (9 < count($match)) {
81036 $components['fragment'] = $match[9];
81037 }
81038
81039 return $components;
81040 }
81041
81042
81043
81044
81045
81046
81047
81048
81049 public function generate(array $components)
81050 {
81051 $uri = $components['scheme'] . '://'
81052 . $components['authority']
81053 . $components['path'];
81054
81055 if (array_key_exists('query', $components)) {
81056 $uri .= $components['query'];
81057 }
81058
81059 if (array_key_exists('fragment', $components)) {
81060 $uri .= $components['fragment'];
81061 }
81062
81063 return $uri;
81064 }
81065
81066
81067
81068
81069
81070
81071
81072
81073
81074 public function resolve($uri, $baseUri = null)
81075 {
81076 $components = $this->parse($uri);
81077 $path = $components['path'];
81078
81079 if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
81080 return $uri;
81081 }
81082
81083 $baseComponents = $this->parse($baseUri);
81084 $basePath = $baseComponents['path'];
81085
81086 $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
81087
81088 return $this->generate($baseComponents);
81089 }
81090
81091
81092
81093
81094
81095
81096 public function isValid($uri)
81097 {
81098 $components = $this->parse($uri);
81099
81100 return !empty($components);
81101 }
81102
81103
81104
81105
81106 public function setTranslation($from, $to)
81107 {
81108 $this->translationMap[$from] = $to;
81109 }
81110
81111
81112
81113
81114 public function translate($uri)
81115 {
81116 foreach ($this->translationMap as $from => $to) {
81117 $uri = preg_replace($from, $to, $uri);
81118 }
81119
81120
81121  $uri = preg_replace('|^package://|', sprintf('file://%s/', realpath(__DIR__ . '/../../..')), $uri);
81122
81123 return $uri;
81124 }
81125 }
81126 <?php
81127
81128
81129
81130
81131
81132
81133
81134
81135 namespace JsonSchema;
81136
81137
81138
81139
81140 interface UriResolverInterface
81141 {
81142
81143
81144
81145
81146
81147
81148
81149
81150 public function resolve($uri, $baseUri = null);
81151 }
81152 <?php
81153
81154
81155
81156
81157
81158
81159
81160
81161 namespace JsonSchema;
81162
81163
81164
81165
81166 interface UriRetrieverInterface
81167 {
81168
81169
81170
81171
81172
81173
81174
81175
81176 public function retrieve($uri, $baseUri = null);
81177 }
81178 <?php
81179
81180
81181
81182
81183
81184
81185
81186
81187 namespace JsonSchema;
81188
81189 use JsonSchema\Constraints\BaseConstraint;
81190 use JsonSchema\Constraints\Constraint;
81191
81192
81193
81194
81195
81196
81197
81198
81199
81200 class Validator extends BaseConstraint
81201 {
81202 const SCHEMA_MEDIA_TYPE = 'application/schema+json';
81203
81204 const ERROR_NONE = 0x00000000;
81205 const ERROR_ALL = 0xFFFFFFFF;
81206 const ERROR_DOCUMENT_VALIDATION = 0x00000001;
81207 const ERROR_SCHEMA_VALIDATION = 0x00000002;
81208
81209
81210
81211
81212
81213
81214
81215
81216
81217
81218 public function validate(&$value, $schema = null, $checkMode = null)
81219 {
81220
81221  if (is_array($schema)) {
81222 $schema = self::arrayToObjectRecursive($schema);
81223 }
81224
81225
81226  $initialCheckMode = $this->factory->getConfig();
81227 if ($checkMode !== null) {
81228 $this->factory->setConfig($checkMode);
81229 }
81230
81231
81232  if (is_object($schema) && property_exists($schema, 'id')) {
81233 $schemaURI = $schema->id;
81234 } else {
81235 $schemaURI = SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI;
81236 }
81237 $this->factory->getSchemaStorage()->addSchema($schemaURI, $schema);
81238
81239 $validator = $this->factory->createInstanceFor('schema');
81240 $validator->check(
81241 $value,
81242 $this->factory->getSchemaStorage()->getSchema($schemaURI)
81243 );
81244
81245 $this->factory->setConfig($initialCheckMode);
81246
81247 $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
81248
81249 return $validator->getErrorMask();
81250 }
81251
81252
81253
81254
81255 public function check($value, $schema)
81256 {
81257 return $this->validate($value, $schema);
81258 }
81259
81260
81261
81262
81263 public function coerce(&$value, $schema)
81264 {
81265 return $this->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
81266 }
81267 }
81268 Copyright (C) 2015 Composer
81269
81270 Permission is hereby granted, free of charge, to any person obtaining a copy of
81271 this software and associated documentation files (the "Software"), to deal in
81272 the Software without restriction, including without limitation the rights to
81273 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
81274 of the Software, and to permit persons to whom the Software is furnished to do
81275 so, subject to the following conditions:
81276
81277 The above copyright notice and this permission notice shall be included in all
81278 copies or substantial portions of the Software.
81279
81280 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81281 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81282 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
81283 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81284 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
81285 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
81286 SOFTWARE.
81287 <?php
81288
81289
81290
81291
81292
81293
81294
81295
81296
81297
81298 namespace Composer\Spdx;
81299
81300 class SpdxLicenses
81301 {
81302
81303 const LICENSES_FILE = 'spdx-licenses.json';
81304
81305
81306 const EXCEPTIONS_FILE = 'spdx-exceptions.json';
81307
81308
81309
81310
81311
81312
81313
81314
81315
81316
81317
81318
81319
81320
81321 private $licenses;
81322
81323
81324
81325
81326 private $licensesExpression;
81327
81328
81329
81330
81331
81332
81333
81334
81335
81336
81337
81338
81339
81340
81341 private $exceptions;
81342
81343
81344
81345
81346 private $exceptionsExpression;
81347
81348 public function __construct()
81349 {
81350 $this->loadLicenses();
81351 $this->loadExceptions();
81352 }
81353
81354
81355
81356
81357
81358
81359
81360
81361
81362
81363
81364
81365
81366 public function getLicenseByIdentifier($identifier)
81367 {
81368 $key = strtolower($identifier);
81369
81370 if (!isset($this->licenses[$key])) {
81371 return;
81372 }
81373
81374 list($identifier, $name, $isOsiApproved, $isDeprecatedLicenseId) = $this->licenses[$key];
81375
81376 return array(
81377 $name,
81378 $isOsiApproved,
81379 'https://spdx.org/licenses/' . $identifier . '.html#licenseText',
81380 $isDeprecatedLicenseId,
81381 );
81382 }
81383
81384
81385
81386
81387
81388
81389 public function getLicenses()
81390 {
81391 return $this->licenses;
81392 }
81393
81394
81395
81396
81397
81398
81399
81400
81401
81402
81403
81404
81405
81406 public function getExceptionByIdentifier($identifier)
81407 {
81408 $key = strtolower($identifier);
81409
81410 if (!isset($this->exceptions[$key])) {
81411 return;
81412 }
81413
81414 list($identifier, $name) = $this->exceptions[$key];
81415
81416 return array(
81417 $name,
81418 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText',
81419 );
81420 }
81421
81422
81423
81424
81425
81426
81427
81428
81429 public function getIdentifierByName($name)
81430 {
81431 foreach ($this->licenses as $licenseData) {
81432 if ($licenseData[1] === $name) {
81433 return $licenseData[0];
81434 }
81435 }
81436
81437 foreach ($this->exceptions as $licenseData) {
81438 if ($licenseData[1] === $name) {
81439 return $licenseData[0];
81440 }
81441 }
81442 }
81443
81444
81445
81446
81447
81448
81449
81450
81451 public function isOsiApprovedByIdentifier($identifier)
81452 {
81453 return $this->licenses[strtolower($identifier)][2];
81454 }
81455
81456
81457
81458
81459
81460
81461
81462
81463 public function isDeprecatedByIdentifier($identifier)
81464 {
81465 return $this->licenses[strtolower($identifier)][3];
81466 }
81467
81468
81469
81470
81471
81472
81473
81474
81475 public function validate($license)
81476 {
81477 if (is_array($license)) {
81478 $count = count($license);
81479 if ($count !== count(array_filter($license, 'is_string'))) {
81480 throw new \InvalidArgumentException('Array of strings expected.');
81481 }
81482 $license = $count > 1 ? '(' . implode(' OR ', $license) . ')' : (string) reset($license);
81483 }
81484
81485 if (!is_string($license)) {
81486 throw new \InvalidArgumentException(sprintf(
81487 'Array or String expected, %s given.',
81488 gettype($license)
81489 ));
81490 }
81491
81492 return $this->isValidLicenseString($license);
81493 }
81494
81495
81496
81497
81498 public static function getResourcesDir()
81499 {
81500 return dirname(__DIR__) . '/res';
81501 }
81502
81503 private function loadLicenses()
81504 {
81505 if (null !== $this->licenses) {
81506 return;
81507 }
81508
81509 $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
81510 $this->licenses = array();
81511
81512 foreach (json_decode($json, true) as $identifier => $license) {
81513 $this->licenses[strtolower($identifier)] = array($identifier, $license[0], $license[1], $license[2]);
81514 }
81515 }
81516
81517 private function loadExceptions()
81518 {
81519 if (null !== $this->exceptions) {
81520 return;
81521 }
81522
81523 $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
81524 $this->exceptions = array();
81525
81526 foreach (json_decode($json, true) as $identifier => $exception) {
81527 $this->exceptions[strtolower($identifier)] = array($identifier, $exception[0]);
81528 }
81529 }
81530
81531
81532
81533
81534 private function getLicensesExpression()
81535 {
81536 if (null === $this->licensesExpression) {
81537 $licenses = array_map('preg_quote', array_keys($this->licenses));
81538 rsort($licenses);
81539 $licenses = implode('|', $licenses);
81540 $this->licensesExpression = $licenses;
81541 }
81542
81543 return $this->licensesExpression;
81544 }
81545
81546
81547
81548
81549 private function getExceptionsExpression()
81550 {
81551 if (null === $this->exceptionsExpression) {
81552 $exceptions = array_map('preg_quote', array_keys($this->exceptions));
81553 rsort($exceptions);
81554 $exceptions = implode('|', $exceptions);
81555 $this->exceptionsExpression = $exceptions;
81556 }
81557
81558 return $this->exceptionsExpression;
81559 }
81560
81561
81562
81563
81564
81565
81566
81567
81568 private function isValidLicenseString($license)
81569 {
81570 if (isset($this->licenses[strtolower($license)])) {
81571 return true;
81572 }
81573
81574 $licenses = $this->getLicensesExpression();
81575 $exceptions = $this->getExceptionsExpression();
81576
81577 $regex = <<<REGEX
81578 {
81579 (?(DEFINE)
81580     # idstring: 1*( ALPHA / DIGIT / - / . )
81581     (?<idstring>[\pL\pN.-]{1,})
81582
81583     # license-id: taken from list
81584     (?<licenseid>${licenses})
81585
81586     # license-exception-id: taken from list
81587     (?<licenseexceptionid>${exceptions})
81588
81589     # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
81590     (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))
81591
81592     # simple-expresssion: license-id / license-id+ / license-ref
81593     (?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref))
81594
81595     # compound-expression: 1*(
81596     #   simple-expression /
81597     #   simple-expression WITH license-exception-id /
81598     #   compound-expression AND compound-expression /
81599     #   compound-expression OR compound-expression
81600     # ) / ( compound-expression ) )
81601     (?<compound_head>
81602         (?&simple_expression) ( \s+ WITH \s+ (?&licenseexceptionid))?
81603             | \( \s* (?&compound_expression) \s* \)
81604     )
81605     (?<compound_expression>
81606         (?&compound_head) (?: \s+ (?:AND|OR) \s+ (?&compound_expression))?
81607     )
81608
81609     # license-expression: 1*1(simple-expression / compound-expression)
81610     (?<license_expression>(?&compound_expression) | (?&simple_expression))
81611 ) # end of define
81612
81613 ^(NONE | NOASSERTION | (?&license_expression))$
81614 }xi
81615 REGEX;
81616
81617 $match = preg_match($regex, $license);
81618
81619 if (0 === $match) {
81620 return false;
81621 }
81622
81623 if (false === $match) {
81624 throw new \RuntimeException('Regex failed to compile/run.');
81625 }
81626
81627 return true;
81628 }
81629 }
81630 Copyright (C) 2015 Composer
81631
81632 Permission is hereby granted, free of charge, to any person obtaining a copy of
81633 this software and associated documentation files (the "Software"), to deal in
81634 the Software without restriction, including without limitation the rights to
81635 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
81636 of the Software, and to permit persons to whom the Software is furnished to do
81637 so, subject to the following conditions:
81638
81639 The above copyright notice and this permission notice shall be included in all
81640 copies or substantial portions of the Software.
81641
81642 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81643 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81644 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
81645 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81646 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
81647 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
81648 SOFTWARE.
81649 <?php
81650
81651
81652
81653
81654
81655
81656
81657
81658
81659
81660 namespace Composer\Semver;
81661
81662 use Composer\Semver\Constraint\Constraint;
81663
81664 class Comparator
81665 {
81666
81667
81668
81669
81670
81671
81672
81673
81674 public static function greaterThan($version1, $version2)
81675 {
81676 return self::compare($version1, '>', $version2);
81677 }
81678
81679
81680
81681
81682
81683
81684
81685
81686
81687 public static function greaterThanOrEqualTo($version1, $version2)
81688 {
81689 return self::compare($version1, '>=', $version2);
81690 }
81691
81692
81693
81694
81695
81696
81697
81698
81699
81700 public static function lessThan($version1, $version2)
81701 {
81702 return self::compare($version1, '<', $version2);
81703 }
81704
81705
81706
81707
81708
81709
81710
81711
81712
81713 public static function lessThanOrEqualTo($version1, $version2)
81714 {
81715 return self::compare($version1, '<=', $version2);
81716 }
81717
81718
81719
81720
81721
81722
81723
81724
81725
81726 public static function equalTo($version1, $version2)
81727 {
81728 return self::compare($version1, '==', $version2);
81729 }
81730
81731
81732
81733
81734
81735
81736
81737
81738
81739 public static function notEqualTo($version1, $version2)
81740 {
81741 return self::compare($version1, '!=', $version2);
81742 }
81743
81744
81745
81746
81747
81748
81749
81750
81751
81752
81753 public static function compare($version1, $operator, $version2)
81754 {
81755 $constraint = new Constraint($operator, $version2);
81756
81757 return $constraint->matches(new Constraint('==', $version1));
81758 }
81759 }
81760 <?php
81761
81762
81763
81764
81765
81766
81767
81768
81769
81770
81771 namespace Composer\Semver\Constraint;
81772
81773 trigger_error('The ' . __CLASS__ . ' abstract class is deprecated, there is no replacement for it, it will be removed in the next major version.', E_USER_DEPRECATED);
81774
81775
81776
81777
81778 abstract class AbstractConstraint implements ConstraintInterface
81779 {
81780
81781 protected $prettyString;
81782
81783
81784
81785
81786
81787
81788 public function matches(ConstraintInterface $provider)
81789 {
81790 if ($provider instanceof $this) {
81791
81792  return $this->matchSpecific($provider);
81793 }
81794
81795
81796  return $provider->matches($this);
81797 }
81798
81799
81800
81801
81802 public function setPrettyString($prettyString)
81803 {
81804 $this->prettyString = $prettyString;
81805 }
81806
81807
81808
81809
81810 public function getPrettyString()
81811 {
81812 if ($this->prettyString) {
81813 return $this->prettyString;
81814 }
81815
81816 return $this->__toString();
81817 }
81818
81819
81820  
81821  
81822 }
81823 <?php
81824
81825
81826
81827
81828
81829
81830
81831
81832
81833
81834 namespace Composer\Semver\Constraint;
81835
81836
81837
81838
81839 class Constraint implements ConstraintInterface
81840 {
81841
81842 const OP_EQ = 0;
81843 const OP_LT = 1;
81844 const OP_LE = 2;
81845 const OP_GT = 3;
81846 const OP_GE = 4;
81847 const OP_NE = 5;
81848
81849
81850
81851
81852
81853
81854 private static $transOpStr = array(
81855 '=' => self::OP_EQ,
81856 '==' => self::OP_EQ,
81857 '<' => self::OP_LT,
81858 '<=' => self::OP_LE,
81859 '>' => self::OP_GT,
81860 '>=' => self::OP_GE,
81861 '<>' => self::OP_NE,
81862 '!=' => self::OP_NE,
81863 );
81864
81865
81866
81867
81868
81869
81870 private static $transOpInt = array(
81871 self::OP_EQ => '==',
81872 self::OP_LT => '<',
81873 self::OP_LE => '<=',
81874 self::OP_GT => '>',
81875 self::OP_GE => '>=',
81876 self::OP_NE => '!=',
81877 );
81878
81879
81880 protected $operator;
81881
81882
81883 protected $version;
81884
81885
81886 protected $prettyString;
81887
81888
81889
81890
81891
81892
81893 public function matches(ConstraintInterface $provider)
81894 {
81895 if ($provider instanceof $this) {
81896 return $this->matchSpecific($provider);
81897 }
81898
81899
81900  return $provider->matches($this);
81901 }
81902
81903
81904
81905
81906 public function setPrettyString($prettyString)
81907 {
81908 $this->prettyString = $prettyString;
81909 }
81910
81911
81912
81913
81914 public function getPrettyString()
81915 {
81916 if ($this->prettyString) {
81917 return $this->prettyString;
81918 }
81919
81920 return $this->__toString();
81921 }
81922
81923
81924
81925
81926
81927
81928 public static function getSupportedOperators()
81929 {
81930 return array_keys(self::$transOpStr);
81931 }
81932
81933
81934
81935
81936
81937
81938
81939
81940
81941 public function __construct($operator, $version)
81942 {
81943 if (!isset(self::$transOpStr[$operator])) {
81944 throw new \InvalidArgumentException(sprintf(
81945 'Invalid operator "%s" given, expected one of: %s',
81946 $operator,
81947 implode(', ', self::getSupportedOperators())
81948 ));
81949 }
81950
81951 $this->operator = self::$transOpStr[$operator];
81952 $this->version = $version;
81953 }
81954
81955
81956
81957
81958
81959
81960
81961
81962
81963
81964
81965 public function versionCompare($a, $b, $operator, $compareBranches = false)
81966 {
81967 if (!isset(self::$transOpStr[$operator])) {
81968 throw new \InvalidArgumentException(sprintf(
81969 'Invalid operator "%s" given, expected one of: %s',
81970 $operator,
81971 implode(', ', self::getSupportedOperators())
81972 ));
81973 }
81974
81975 $aIsBranch = 'dev-' === substr($a, 0, 4);
81976 $bIsBranch = 'dev-' === substr($b, 0, 4);
81977
81978 if ($aIsBranch && $bIsBranch) {
81979 return $operator === '==' && $a === $b;
81980 }
81981
81982
81983  if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
81984 return false;
81985 }
81986
81987 return version_compare($a, $b, $operator);
81988 }
81989
81990
81991
81992
81993
81994
81995
81996 public function matchSpecific(Constraint $provider, $compareBranches = false)
81997 {
81998 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
81999 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
82000
82001 $isEqualOp = self::OP_EQ === $this->operator;
82002 $isNonEqualOp = self::OP_NE === $this->operator;
82003 $isProviderEqualOp = self::OP_EQ === $provider->operator;
82004 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
82005
82006
82007  
82008  if ($isNonEqualOp || $isProviderNonEqualOp) {
82009 return !$isEqualOp && !$isProviderEqualOp
82010 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
82011 }
82012
82013
82014  
82015  if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
82016 return true;
82017 }
82018
82019 if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
82020
82021  
82022  if ($provider->version === $this->version
82023 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
82024 && self::$transOpInt[$this->operator] !== $noEqualOp) {
82025 return false;
82026 }
82027
82028 return true;
82029 }
82030
82031 return false;
82032 }
82033
82034
82035
82036
82037 public function __toString()
82038 {
82039 return self::$transOpInt[$this->operator] . ' ' . $this->version;
82040 }
82041 }
82042 <?php
82043
82044
82045
82046
82047
82048
82049
82050
82051
82052
82053 namespace Composer\Semver\Constraint;
82054
82055 interface ConstraintInterface
82056 {
82057
82058
82059
82060
82061
82062 public function matches(ConstraintInterface $provider);
82063
82064
82065
82066
82067 public function getPrettyString();
82068
82069
82070
82071
82072 public function __toString();
82073 }
82074 <?php
82075
82076
82077
82078
82079
82080
82081
82082
82083
82084
82085 namespace Composer\Semver\Constraint;
82086
82087
82088
82089
82090 class EmptyConstraint implements ConstraintInterface
82091 {
82092
82093 protected $prettyString;
82094
82095
82096
82097
82098
82099
82100 public function matches(ConstraintInterface $provider)
82101 {
82102 return true;
82103 }
82104
82105
82106
82107
82108 public function setPrettyString($prettyString)
82109 {
82110 $this->prettyString = $prettyString;
82111 }
82112
82113
82114
82115
82116 public function getPrettyString()
82117 {
82118 if ($this->prettyString) {
82119 return $this->prettyString;
82120 }
82121
82122 return $this->__toString();
82123 }
82124
82125
82126
82127
82128 public function __toString()
82129 {
82130 return '[]';
82131 }
82132 }
82133 <?php
82134
82135
82136
82137
82138
82139
82140
82141
82142
82143
82144 namespace Composer\Semver\Constraint;
82145
82146
82147
82148
82149 class MultiConstraint implements ConstraintInterface
82150 {
82151
82152 protected $constraints;
82153
82154
82155 protected $prettyString;
82156
82157
82158 protected $conjunctive;
82159
82160
82161
82162
82163
82164 public function __construct(array $constraints, $conjunctive = true)
82165 {
82166 $this->constraints = $constraints;
82167 $this->conjunctive = $conjunctive;
82168 }
82169
82170
82171
82172
82173 public function getConstraints()
82174 {
82175 return $this->constraints;
82176 }
82177
82178
82179
82180
82181 public function isConjunctive()
82182 {
82183 return $this->conjunctive;
82184 }
82185
82186
82187
82188
82189 public function isDisjunctive()
82190 {
82191 return !$this->conjunctive;
82192 }
82193
82194
82195
82196
82197
82198
82199 public function matches(ConstraintInterface $provider)
82200 {
82201 if (false === $this->conjunctive) {
82202 foreach ($this->constraints as $constraint) {
82203 if ($constraint->matches($provider)) {
82204 return true;
82205 }
82206 }
82207
82208 return false;
82209 }
82210
82211 foreach ($this->constraints as $constraint) {
82212 if (!$constraint->matches($provider)) {
82213 return false;
82214 }
82215 }
82216
82217 return true;
82218 }
82219
82220
82221
82222
82223 public function setPrettyString($prettyString)
82224 {
82225 $this->prettyString = $prettyString;
82226 }
82227
82228
82229
82230
82231 public function getPrettyString()
82232 {
82233 if ($this->prettyString) {
82234 return $this->prettyString;
82235 }
82236
82237 return $this->__toString();
82238 }
82239
82240
82241
82242
82243 public function __toString()
82244 {
82245 $constraints = array();
82246 foreach ($this->constraints as $constraint) {
82247 $constraints[] = (string) $constraint;
82248 }
82249
82250 return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
82251 }
82252 }
82253 <?php
82254
82255
82256
82257
82258
82259
82260
82261
82262
82263
82264 namespace Composer\Semver;
82265
82266 use Composer\Semver\Constraint\Constraint;
82267
82268 class Semver
82269 {
82270 const SORT_ASC = 1;
82271 const SORT_DESC = -1;
82272
82273
82274 private static $versionParser;
82275
82276
82277
82278
82279
82280
82281
82282
82283
82284 public static function satisfies($version, $constraints)
82285 {
82286 if (null === self::$versionParser) {
82287 self::$versionParser = new VersionParser();
82288 }
82289
82290 $versionParser = self::$versionParser;
82291 $provider = new Constraint('==', $versionParser->normalize($version));
82292 $constraints = $versionParser->parseConstraints($constraints);
82293
82294 return $constraints->matches($provider);
82295 }
82296
82297
82298
82299
82300
82301
82302
82303
82304
82305 public static function satisfiedBy(array $versions, $constraints)
82306 {
82307 $versions = array_filter($versions, function ($version) use ($constraints) {
82308 return Semver::satisfies($version, $constraints);
82309 });
82310
82311 return array_values($versions);
82312 }
82313
82314
82315
82316
82317
82318
82319
82320
82321 public static function sort(array $versions)
82322 {
82323 return self::usort($versions, self::SORT_ASC);
82324 }
82325
82326
82327
82328
82329
82330
82331
82332
82333 public static function rsort(array $versions)
82334 {
82335 return self::usort($versions, self::SORT_DESC);
82336 }
82337
82338
82339
82340
82341
82342
82343
82344 private static function usort(array $versions, $direction)
82345 {
82346 if (null === self::$versionParser) {
82347 self::$versionParser = new VersionParser();
82348 }
82349
82350 $versionParser = self::$versionParser;
82351 $normalized = array();
82352
82353
82354  
82355  foreach ($versions as $key => $version) {
82356 $normalized[] = array($versionParser->normalize($version), $key);
82357 }
82358
82359 usort($normalized, function (array $left, array $right) use ($direction) {
82360 if ($left[0] === $right[0]) {
82361 return 0;
82362 }
82363
82364 if (Comparator::lessThan($left[0], $right[0])) {
82365 return -$direction;
82366 }
82367
82368 return $direction;
82369 });
82370
82371
82372  $sorted = array();
82373 foreach ($normalized as $item) {
82374 $sorted[] = $versions[$item[1]];
82375 }
82376
82377 return $sorted;
82378 }
82379 }
82380 <?php
82381
82382
82383
82384
82385
82386
82387
82388
82389
82390
82391 namespace Composer\Semver;
82392
82393 use Composer\Semver\Constraint\ConstraintInterface;
82394 use Composer\Semver\Constraint\EmptyConstraint;
82395 use Composer\Semver\Constraint\MultiConstraint;
82396 use Composer\Semver\Constraint\Constraint;
82397
82398
82399
82400
82401
82402
82403 class VersionParser
82404 {
82405
82406
82407
82408
82409
82410
82411
82412
82413
82414
82415
82416
82417
82418 private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
82419
82420
82421 private static $stabilities = array('stable', 'RC', 'beta', 'alpha', 'dev');
82422
82423
82424
82425
82426
82427
82428
82429
82430 public static function parseStability($version)
82431 {
82432 $version = preg_replace('{#.+$}i', '', $version);
82433
82434 if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
82435 return 'dev';
82436 }
82437
82438 preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
82439 if (!empty($match[3])) {
82440 return 'dev';
82441 }
82442
82443 if (!empty($match[1])) {
82444 if ('beta' === $match[1] || 'b' === $match[1]) {
82445 return 'beta';
82446 }
82447 if ('alpha' === $match[1] || 'a' === $match[1]) {
82448 return 'alpha';
82449 }
82450 if ('rc' === $match[1]) {
82451 return 'RC';
82452 }
82453 }
82454
82455 return 'stable';
82456 }
82457
82458
82459
82460
82461
82462
82463 public static function normalizeStability($stability)
82464 {
82465 $stability = strtolower($stability);
82466
82467 return $stability === 'rc' ? 'RC' : $stability;
82468 }
82469
82470
82471
82472
82473
82474
82475
82476
82477
82478
82479
82480 public function normalize($version, $fullVersion = null)
82481 {
82482 $version = trim($version);
82483 if (null === $fullVersion) {
82484 $fullVersion = $version;
82485 }
82486
82487
82488  if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
82489 $version = $match[1];
82490 }
82491
82492
82493  if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
82494 return '9999999-dev';
82495 }
82496
82497
82498  if ('dev-' === strtolower(substr($version, 0, 4))) {
82499 return 'dev-' . substr($version, 4);
82500 }
82501
82502
82503  if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
82504 $version = $match[1];
82505 }
82506
82507
82508  if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
82509 $version = $matches[1]
82510 . (!empty($matches[2]) ? $matches[2] : '.0')
82511 . (!empty($matches[3]) ? $matches[3] : '.0')
82512 . (!empty($matches[4]) ? $matches[4] : '.0');
82513 $index = 5;
82514
82515  } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) {
82516 $version = preg_replace('{\D}', '.', $matches[1]);
82517 $index = 2;
82518 }
82519
82520
82521  if (isset($index)) {
82522 if (!empty($matches[$index])) {
82523 if ('stable' === $matches[$index]) {
82524 return $version;
82525 }
82526 $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? ltrim($matches[$index + 1], '.-') : '');
82527 }
82528
82529 if (!empty($matches[$index + 2])) {
82530 $version .= '-dev';
82531 }
82532
82533 return $version;
82534 }
82535
82536
82537  if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
82538 try {
82539 return $this->normalizeBranch($match[1]);
82540 } catch (\Exception $e) {
82541 }
82542 }
82543
82544 $extraMessage = '';
82545 if (preg_match('{ +as +' . preg_quote($version) . '$}', $fullVersion)) {
82546 $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
82547 } elseif (preg_match('{^' . preg_quote($version) . ' +as +}', $fullVersion)) {
82548 $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
82549 }
82550
82551 throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage);
82552 }
82553
82554
82555
82556
82557
82558
82559
82560
82561 public function parseNumericAliasPrefix($branch)
82562 {
82563 if (preg_match('{^(?P<version>(\d++\\.)*\d++)(?:\.x)?-dev$}i', $branch, $matches)) {
82564 return $matches['version'] . '.';
82565 }
82566
82567 return false;
82568 }
82569
82570
82571
82572
82573
82574
82575
82576
82577 public function normalizeBranch($name)
82578 {
82579 $name = trim($name);
82580
82581 if (in_array($name, array('master', 'trunk', 'default'))) {
82582 return $this->normalize($name);
82583 }
82584
82585 if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
82586 $version = '';
82587 for ($i = 1; $i < 5; ++$i) {
82588 $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
82589 }
82590
82591 return str_replace('x', '9999999', $version) . '-dev';
82592 }
82593
82594 return 'dev-' . $name;
82595 }
82596
82597
82598
82599
82600
82601
82602
82603
82604 public function parseConstraints($constraints)
82605 {
82606 $prettyConstraint = $constraints;
82607
82608 if (preg_match('{^([^,\s]*?)@(' . implode('|', self::$stabilities) . ')$}i', $constraints, $match)) {
82609 $constraints = empty($match[1]) ? '*' : $match[1];
82610 }
82611
82612 if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) {
82613 $constraints = $match[1];
82614 }
82615
82616 $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
82617 $orGroups = array();
82618 foreach ($orConstraints as $constraints) {
82619 $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
82620 if (count($andConstraints) > 1) {
82621 $constraintObjects = array();
82622 foreach ($andConstraints as $constraint) {
82623 foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
82624 $constraintObjects[] = $parsedConstraint;
82625 }
82626 }
82627 } else {
82628 $constraintObjects = $this->parseConstraint($andConstraints[0]);
82629 }
82630
82631 if (1 === count($constraintObjects)) {
82632 $constraint = $constraintObjects[0];
82633 } else {
82634 $constraint = new MultiConstraint($constraintObjects);
82635 }
82636
82637 $orGroups[] = $constraint;
82638 }
82639
82640 if (1 === count($orGroups)) {
82641 $constraint = $orGroups[0];
82642 } elseif (2 === count($orGroups)
82643
82644  
82645  && $orGroups[0] instanceof MultiConstraint
82646 && $orGroups[1] instanceof MultiConstraint
82647 && 2 === count($orGroups[0]->getConstraints())
82648 && 2 === count($orGroups[1]->getConstraints())
82649 && ($a = (string) $orGroups[0])
82650 && substr($a, 0, 3) === '[>=' && (false !== ($posA = strpos($a, '<', 4)))
82651 && ($b = (string) $orGroups[1])
82652 && substr($b, 0, 3) === '[>=' && (false !== ($posB = strpos($b, '<', 4)))
82653 && substr($a, $posA + 2, -1) === substr($b, 4, $posB - 5)
82654 ) {
82655 $constraint = new MultiConstraint(array(
82656 new Constraint('>=', substr($a, 4, $posA - 5)),
82657 new Constraint('<', substr($b, $posB + 2, -1)),
82658 ));
82659 } else {
82660 $constraint = new MultiConstraint($orGroups, false);
82661 }
82662
82663 $constraint->setPrettyString($prettyConstraint);
82664
82665 return $constraint;
82666 }
82667
82668
82669
82670
82671
82672
82673
82674
82675 private function parseConstraint($constraint)
82676 {
82677 if (preg_match('{^([^,\s]+?)@(' . implode('|', self::$stabilities) . ')$}i', $constraint, $match)) {
82678 $constraint = $match[1];
82679 if ($match[2] !== 'stable') {
82680 $stabilityModifier = $match[2];
82681 }
82682 }
82683
82684 if (preg_match('{^v?[xX*](\.[xX*])*$}i', $constraint)) {
82685 return array(new EmptyConstraint());
82686 }
82687
82688 $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?' . self::$modifierRegex . '(?:\+[^\s]+)?';
82689
82690
82691  
82692  
82693  
82694  
82695  if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
82696 if (substr($constraint, 0, 2) === '~>') {
82697 throw new \UnexpectedValueException(
82698 'Could not parse version constraint ' . $constraint . ': ' .
82699 'Invalid operator "~>", you probably meant to use the "~" operator'
82700 );
82701 }
82702
82703
82704  if (isset($matches[4]) && '' !== $matches[4]) {
82705 $position = 4;
82706 } elseif (isset($matches[3]) && '' !== $matches[3]) {
82707 $position = 3;
82708 } elseif (isset($matches[2]) && '' !== $matches[2]) {
82709 $position = 2;
82710 } else {
82711 $position = 1;
82712 }
82713
82714
82715  $stabilitySuffix = '';
82716 if (!empty($matches[5])) {
82717 $stabilitySuffix .= '-' . $this->expandStability($matches[5]) . (!empty($matches[6]) ? $matches[6] : '');
82718 }
82719
82720 if (!empty($matches[7])) {
82721 $stabilitySuffix .= '-dev';
82722 }
82723
82724 if (!$stabilitySuffix) {
82725 $stabilitySuffix = '-dev';
82726 }
82727
82728 $lowVersion = $this->manipulateVersionString($matches, $position, 0) . $stabilitySuffix;
82729 $lowerBound = new Constraint('>=', $lowVersion);
82730
82731
82732  
82733  $highPosition = max(1, $position - 1);
82734 $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
82735 $upperBound = new Constraint('<', $highVersion);
82736
82737 return array(
82738 $lowerBound,
82739 $upperBound,
82740 );
82741 }
82742
82743
82744  
82745  
82746  
82747  
82748  if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
82749
82750  if ('0' !== $matches[1] || '' === $matches[2]) {
82751 $position = 1;
82752 } elseif ('0' !== $matches[2] || '' === $matches[3]) {
82753 $position = 2;
82754 } else {
82755 $position = 3;
82756 }
82757
82758
82759  $stabilitySuffix = '';
82760 if (empty($matches[5]) && empty($matches[7])) {
82761 $stabilitySuffix .= '-dev';
82762 }
82763
82764 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
82765 $lowerBound = new Constraint('>=', $lowVersion);
82766
82767
82768  
82769  $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
82770 $upperBound = new Constraint('<', $highVersion);
82771
82772 return array(
82773 $lowerBound,
82774 $upperBound,
82775 );
82776 }
82777
82778
82779  
82780  
82781  
82782  if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
82783 if (isset($matches[3]) && '' !== $matches[3]) {
82784 $position = 3;
82785 } elseif (isset($matches[2]) && '' !== $matches[2]) {
82786 $position = 2;
82787 } else {
82788 $position = 1;
82789 }
82790
82791 $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
82792 $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
82793
82794 if ($lowVersion === '0.0.0.0-dev') {
82795 return array(new Constraint('<', $highVersion));
82796 }
82797
82798 return array(
82799 new Constraint('>=', $lowVersion),
82800 new Constraint('<', $highVersion),
82801 );
82802 }
82803
82804
82805  
82806  
82807  
82808  
82809  
82810  if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
82811
82812  $lowStabilitySuffix = '';
82813 if (empty($matches[6]) && empty($matches[8])) {
82814 $lowStabilitySuffix = '-dev';
82815 }
82816
82817 $lowVersion = $this->normalize($matches['from']);
82818 $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
82819
82820 $empty = function ($x) {
82821 return ($x === 0 || $x === '0') ? false : empty($x);
82822 };
82823
82824 if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) {
82825 $highVersion = $this->normalize($matches['to']);
82826 $upperBound = new Constraint('<=', $highVersion);
82827 } else {
82828 $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]);
82829 $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev';
82830 $upperBound = new Constraint('<', $highVersion);
82831 }
82832
82833 return array(
82834 $lowerBound,
82835 $upperBound,
82836 );
82837 }
82838
82839
82840  if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
82841 try {
82842 $version = $this->normalize($matches[2]);
82843
82844 if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') {
82845 $version .= '-' . $stabilityModifier;
82846 } elseif ('<' === $matches[1] || '>=' === $matches[1]) {
82847 if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
82848 if (substr($matches[2], 0, 4) !== 'dev-') {
82849 $version .= '-dev';
82850 }
82851 }
82852 }
82853
82854 return array(new Constraint($matches[1] ?: '=', $version));
82855 } catch (\Exception $e) {
82856 }
82857 }
82858
82859 $message = 'Could not parse version constraint ' . $constraint;
82860 if (isset($e)) {
82861 $message .= ': ' . $e->getMessage();
82862 }
82863
82864 throw new \UnexpectedValueException($message);
82865 }
82866
82867
82868
82869
82870
82871
82872
82873
82874
82875
82876
82877
82878
82879 private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
82880 {
82881 for ($i = 4; $i > 0; --$i) {
82882 if ($i > $position) {
82883 $matches[$i] = $pad;
82884 } elseif ($i === $position && $increment) {
82885 $matches[$i] += $increment;
82886
82887  if ($matches[$i] < 0) {
82888 $matches[$i] = $pad;
82889 --$position;
82890
82891
82892  if ($i === 1) {
82893 return;
82894 }
82895 }
82896 }
82897 }
82898
82899 return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
82900 }
82901
82902
82903
82904
82905
82906
82907
82908
82909 private function expandStability($stability)
82910 {
82911 $stability = strtolower($stability);
82912
82913 switch ($stability) {
82914 case 'a':
82915 return 'alpha';
82916 case 'b':
82917 return 'beta';
82918 case 'p':
82919 case 'pl':
82920 return 'patch';
82921 case 'rc':
82922 return 'RC';
82923 default:
82924 return $stability;
82925 }
82926 }
82927 }
82928 Copyright (C) 2016 Composer
82929
82930 Permission is hereby granted, free of charge, to any person obtaining a copy of
82931 this software and associated documentation files (the "Software"), to deal in
82932 the Software without restriction, including without limitation the rights to
82933 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
82934 of the Software, and to permit persons to whom the Software is furnished to do
82935 so, subject to the following conditions:
82936
82937 The above copyright notice and this permission notice shall be included in all
82938 copies or substantial portions of the Software.
82939
82940 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
82941 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
82942 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
82943 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
82944 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
82945 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
82946 SOFTWARE.
82947 <?php
82948
82949
82950
82951
82952
82953
82954
82955
82956
82957
82958 namespace Composer\CaBundle;
82959
82960 use Psr\Log\LoggerInterface;
82961 use Symfony\Component\Process\PhpProcess;
82962
82963
82964
82965
82966
82967 class CaBundle
82968 {
82969 private static $caPath;
82970 private static $caFileValidity = array();
82971 private static $useOpensslParse;
82972
82973
82974
82975
82976
82977
82978
82979
82980
82981
82982
82983
82984
82985
82986
82987
82988
82989
82990
82991
82992
82993
82994
82995
82996
82997
82998
82999
83000
83001
83002
83003
83004
83005
83006
83007
83008
83009
83010 public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
83011 {
83012 if (self::$caPath !== null) {
83013 return self::$caPath;
83014 }
83015
83016
83017  
83018  $envCertFile = getenv('SSL_CERT_FILE');
83019 if ($envCertFile && is_readable($envCertFile) && static::validateCaFile($envCertFile, $logger)) {
83020 return self::$caPath = $envCertFile;
83021 }
83022
83023
83024  
83025  $envCertDir = getenv('SSL_CERT_DIR');
83026 if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) {
83027 return self::$caPath = $envCertDir;
83028 }
83029
83030 $configured = ini_get('openssl.cafile');
83031 if ($configured && strlen($configured) > 0 && is_readable($configured) && static::validateCaFile($configured, $logger)) {
83032 return self::$caPath = $configured;
83033 }
83034
83035 $configured = ini_get('openssl.capath');
83036 if ($configured && is_dir($configured) && is_readable($configured)) {
83037 return self::$caPath = $configured;
83038 }
83039
83040 $caBundlePaths = array(
83041 '/etc/pki/tls/certs/ca-bundle.crt', 
83042  '/etc/ssl/certs/ca-certificates.crt', 
83043  '/etc/ssl/ca-bundle.pem', 
83044  '/usr/local/share/certs/ca-root-nss.crt', 
83045  '/usr/ssl/certs/ca-bundle.crt', 
83046  '/opt/local/share/curl/curl-ca-bundle.crt', 
83047  '/usr/local/share/curl/curl-ca-bundle.crt', 
83048  '/usr/share/ssl/certs/ca-bundle.crt', 
83049  '/etc/ssl/cert.pem', 
83050  '/usr/local/etc/ssl/cert.pem', 
83051  '/usr/local/etc/openssl/cert.pem', 
83052  );
83053
83054 foreach ($caBundlePaths as $caBundle) {
83055 if (@is_readable($caBundle) && static::validateCaFile($caBundle, $logger)) {
83056 return self::$caPath = $caBundle;
83057 }
83058 }
83059
83060 foreach ($caBundlePaths as $caBundle) {
83061 $caBundle = dirname($caBundle);
83062 if (@is_dir($caBundle) && glob($caBundle.'/*')) {
83063 return self::$caPath = $caBundle;
83064 }
83065 }
83066
83067 return self::$caPath = static::getBundledCaBundlePath(); 
83068  }
83069
83070
83071
83072
83073
83074
83075
83076
83077 public static function getBundledCaBundlePath()
83078 {
83079 $caBundleFile = __DIR__.'/../res/cacert.pem';
83080
83081
83082  
83083  if (0 === strpos($caBundleFile, 'phar://')) {
83084 file_put_contents(
83085 $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
83086 file_get_contents($caBundleFile)
83087 );
83088
83089 register_shutdown_function(function() use ($tempCaBundleFile) {
83090 @unlink($tempCaBundleFile);
83091 });
83092
83093 $caBundleFile = $tempCaBundleFile;
83094 }
83095
83096 return $caBundleFile;
83097 }
83098
83099
83100
83101
83102
83103
83104
83105
83106
83107 public static function validateCaFile($filename, LoggerInterface $logger = null)
83108 {
83109 static $warned = false;
83110
83111 if (isset(self::$caFileValidity[$filename])) {
83112 return self::$caFileValidity[$filename];
83113 }
83114
83115 $contents = file_get_contents($filename);
83116
83117
83118  
83119  if (!static::isOpensslParseSafe()) {
83120 if (!$warned && $logger) {
83121 $logger->warning(sprintf(
83122 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
83123 PHP_VERSION
83124 ));
83125 $warned = true;
83126 }
83127
83128 $isValid = !empty($contents);
83129 } else {
83130 $isValid = (bool) openssl_x509_parse($contents);
83131 }
83132
83133 if ($logger) {
83134 $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
83135 }
83136
83137 return self::$caFileValidity[$filename] = $isValid;
83138 }
83139
83140
83141
83142
83143
83144
83145
83146
83147
83148 public static function isOpensslParseSafe()
83149 {
83150 if (null !== self::$useOpensslParse) {
83151 return self::$useOpensslParse;
83152 }
83153
83154 if (PHP_VERSION_ID >= 50600) {
83155 return self::$useOpensslParse = true;
83156 }
83157
83158
83159  
83160  
83161  
83162  if (
83163 (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
83164 || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
83165 || (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
83166 ) {
83167
83168  return self::$useOpensslParse = true;
83169 }
83170
83171 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
83172
83173  return self::$useOpensslParse = false;
83174 }
83175
83176 $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
83177 $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
83178
83179 if (preg_match($regex, PHP_VERSION, $m)) {
83180 return ((int) $m[1]) >= $fixedVersion;
83181 }
83182
83183 return false;
83184 };
83185
83186
83187  if (
83188 $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) 
83189  || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) 
83190  || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) 
83191  ) {
83192 return self::$useOpensslParse = true;
83193 }
83194
83195
83196  if (!class_exists('Symfony\Component\Process\PhpProcess')) {
83197 return self::$useOpensslParse = false;
83198 }
83199
83200
83201  
83202  
83203  
83204  
83205  
83206
83207
83208  
83209  $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
83210 $script = <<<'EOT'
83211
83212 error_reporting(-1);
83213 $info = openssl_x509_parse(base64_decode('%s'));
83214 var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
83215
83216 EOT;
83217 $script = '<'."?php\n".sprintf($script, $cert);
83218
83219 try {
83220 $process = new PhpProcess($script);
83221 $process->mustRun();
83222 } catch (\Exception $e) {
83223
83224  
83225  return self::$useOpensslParse = false;
83226 }
83227
83228 $output = preg_split('{\r?\n}', trim($process->getOutput()));
83229 $errorOutput = trim($process->getErrorOutput());
83230
83231 if (
83232 count($output) === 3
83233 && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
83234 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
83235 && $output[2] === 'int(-1)'
83236 && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
83237 ) {
83238
83239  return self::$useOpensslParse = true;
83240 }
83241
83242 return self::$useOpensslParse = false;
83243 }
83244
83245
83246
83247
83248 public static function reset()
83249 {
83250 self::$caFileValidity = array();
83251 self::$caPath = null;
83252 self::$useOpensslParse = null;
83253 }
83254 }
83255 MIT License
83256
83257 Copyright (c) 2017 Composer
83258
83259 Permission is hereby granted, free of charge, to any person obtaining a copy
83260 of this software and associated documentation files (the "Software"), to deal
83261 in the Software without restriction, including without limitation the rights
83262 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
83263 copies of the Software, and to permit persons to whom the Software is
83264 furnished to do so, subject to the following conditions:
83265
83266 The above copyright notice and this permission notice shall be included in all
83267 copies or substantial portions of the Software.
83268
83269 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
83270 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
83271 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
83272 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
83273 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
83274 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
83275 SOFTWARE.
83276 <?php
83277
83278
83279
83280
83281
83282
83283
83284
83285
83286
83287 namespace Composer\XdebugHandler;
83288
83289
83290
83291
83292 class PhpConfig
83293 {
83294
83295
83296
83297
83298
83299 public function useOriginal()
83300 {
83301 $this->getDataAndReset();
83302 return array();
83303 }
83304
83305
83306
83307
83308
83309
83310 public function useStandard()
83311 {
83312 if ($data = $this->getDataAndReset()) {
83313 return array('-n', '-c', $data['tmpIni']);
83314 }
83315
83316 return array();
83317 }
83318
83319
83320
83321
83322
83323
83324 public function usePersistent()
83325 {
83326 if ($data = $this->getDataAndReset()) {
83327 Process::setEnv('PHPRC', $data['tmpIni']);
83328 Process::setEnv('PHP_INI_SCAN_DIR', '');
83329 }
83330
83331 return array();
83332 }
83333
83334
83335
83336
83337
83338
83339 private function getDataAndReset()
83340 {
83341 if ($data = XdebugHandler::getRestartSettings()) {
83342 Process::setEnv('PHPRC', $data['phprc']);
83343 Process::setEnv('PHP_INI_SCAN_DIR', $data['scanDir']);
83344 }
83345
83346 return $data;
83347 }
83348 }
83349 <?php
83350
83351
83352
83353
83354
83355
83356
83357
83358
83359
83360 namespace Composer\XdebugHandler;
83361
83362
83363
83364
83365
83366
83367
83368
83369 class Process
83370 {
83371
83372
83373
83374
83375
83376
83377
83378
83379
83380
83381 public static function addColorOption(array $args, $colorOption)
83382 {
83383 if (!$colorOption
83384 || in_array($colorOption, $args)
83385 || !preg_match('/^--([a-z]+$)|(^--[a-z]+=)/', $colorOption, $matches)) {
83386 return $args;
83387 }
83388
83389 if (isset($matches[2])) {
83390
83391  if (false !== ($index = array_search($matches[2].'auto', $args))) {
83392 $args[$index] = $colorOption;
83393 return $args;
83394 } elseif (preg_grep('/^'.$matches[2].'/', $args)) {
83395 return $args;
83396 }
83397 } elseif (in_array('--no-'.$matches[1], $args)) {
83398 return $args;
83399 }
83400
83401 if (false !== ($index = array_search('--', $args))) {
83402
83403  array_splice($args, $index, 0, $colorOption);
83404 } else {
83405 $args[] = $colorOption;
83406 }
83407
83408 return $args;
83409 }
83410
83411
83412
83413
83414
83415
83416
83417
83418
83419
83420
83421
83422
83423 public static function escape($arg, $meta = true, $module = false)
83424 {
83425 if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
83426 return "'".str_replace("'", "'\\''", $arg)."'";
83427 }
83428
83429 $quote = strpbrk($arg, " \t") !== false || $arg === '';
83430
83431 $arg = preg_replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes);
83432
83433 if ($meta) {
83434 $meta = $dquotes || preg_match('/%[^%]+%/', $arg);
83435
83436 if (!$meta) {
83437 $quote = $quote || strpbrk($arg, '^&|<>()') !== false;
83438 } elseif ($module && !$dquotes && $quote) {
83439 $meta = false;
83440 }
83441 }
83442
83443 if ($quote) {
83444 $arg = '"'.preg_replace('/(\\\\*)$/', '$1$1', $arg).'"';
83445 }
83446
83447 if ($meta) {
83448 $arg = preg_replace('/(["^&|<>()%])/', '^$1', $arg);
83449 }
83450
83451 return $arg;
83452 }
83453
83454
83455
83456
83457
83458
83459
83460
83461
83462
83463
83464 public static function supportsColor($output)
83465 {
83466 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
83467 return (function_exists('sapi_windows_vt100_support')
83468 && sapi_windows_vt100_support($output))
83469 || false !== getenv('ANSICON')
83470 || 'ON' === getenv('ConEmuANSI')
83471 || 'xterm' === getenv('TERM');
83472 }
83473
83474 if (function_exists('stream_isatty')) {
83475 return stream_isatty($output);
83476 } elseif (function_exists('posix_isatty')) {
83477 return posix_isatty($output);
83478 }
83479
83480 $stat = fstat($output);
83481
83482  return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
83483 }
83484
83485
83486
83487
83488
83489
83490
83491
83492
83493 public static function setEnv($name, $value = false)
83494 {
83495 $unset = false === $value;
83496
83497 if (!putenv($unset ? $name : $name.'='.$value)) {
83498 return false;
83499 }
83500
83501 if ($unset) {
83502 unset($_SERVER[$name]);
83503 } else {
83504 $_SERVER[$name] = $value;
83505 }
83506 return true;
83507 }
83508 }
83509 <?php
83510
83511
83512
83513
83514
83515
83516
83517
83518
83519
83520 namespace Composer\XdebugHandler;
83521
83522 use Psr\Log\LoggerInterface;
83523 use Psr\Log\LogLevel;
83524
83525
83526
83527
83528
83529 class Status
83530 {
83531 const ENV_RESTART = 'XDEBUG_HANDLER_RESTART';
83532 const CHECK = 'Check';
83533 const ERROR = 'Error';
83534 const INFO = 'Info';
83535 const NORESTART = 'NoRestart';
83536 const RESTART = 'Restart';
83537 const RESTARTING = 'Restarting';
83538 const RESTARTED = 'Restarted';
83539
83540 private $debug;
83541 private $envAllowXdebug;
83542 private $loaded;
83543 private $logger;
83544 private $time;
83545
83546
83547
83548
83549
83550
83551
83552 public function __construct($envAllowXdebug, $debug)
83553 {
83554 $start = getenv(self::ENV_RESTART);
83555 Process::setEnv(self::ENV_RESTART);
83556 $this->time = $start ? round((microtime(true) - $start) * 1000) : 0;
83557
83558 $this->envAllowXdebug = $envAllowXdebug;
83559 $this->debug = $debug;
83560 }
83561
83562
83563
83564
83565 public function setLogger(LoggerInterface $logger)
83566 {
83567 $this->logger = $logger;
83568 }
83569
83570
83571
83572
83573
83574
83575
83576 public function report($op, $data)
83577 {
83578 if ($this->logger || $this->debug) {
83579 call_user_func(array($this, 'report'.$op), $data);
83580 }
83581 }
83582
83583
83584
83585
83586
83587
83588
83589 private function output($text, $level = null)
83590 {
83591 if ($this->logger) {
83592 $this->logger->log($level ?: LogLevel::DEBUG, $text);
83593 }
83594
83595 if ($this->debug) {
83596 printf('xdebug-handler[%d] %s%s', getmypid(), $text, PHP_EOL);
83597 }
83598 }
83599
83600 private function reportCheck($loaded)
83601 {
83602 $this->loaded = $loaded;
83603 $this->output('Checking '.$this->envAllowXdebug);
83604 }
83605
83606 private function reportError($error)
83607 {
83608 $this->output(sprintf('No restart (%s)', $error), LogLevel::WARNING);
83609 }
83610
83611 private function reportInfo($info)
83612 {
83613 $this->output($info);
83614 }
83615
83616 private function reportNoRestart()
83617 {
83618 $this->output($this->getLoadedMessage());
83619
83620 if ($this->loaded) {
83621 $text = sprintf('No restart (%s)', $this->getEnvAllow());
83622 if (!getenv($this->envAllowXdebug)) {
83623 $text .= ' Allowed by application';
83624 }
83625 $this->output($text);
83626 }
83627 }
83628
83629 private function reportRestart()
83630 {
83631 $this->output($this->getLoadedMessage());
83632 Process::setEnv(self::ENV_RESTART, (string) microtime(true));
83633 }
83634
83635 private function reportRestarted()
83636 {
83637 $loaded = $this->getLoadedMessage();
83638 $text = sprintf('Restarted (%d ms). %s', $this->time, $loaded);
83639 $level = $this->loaded ? LogLevel::WARNING : null;
83640 $this->output($text, $level);
83641 }
83642
83643 private function reportRestarting($command)
83644 {
83645 $text = sprintf('Process restarting (%s)', $this->getEnvAllow());
83646 $this->output($text);
83647 $text = 'Running '.$command;
83648 $this->output($text);
83649 }
83650
83651
83652
83653
83654
83655
83656 private function getEnvAllow()
83657 {
83658 return $this->envAllowXdebug.'='.getenv($this->envAllowXdebug);
83659 }
83660
83661
83662
83663
83664
83665
83666 private function getLoadedMessage()
83667 {
83668 $loaded = $this->loaded ? sprintf('loaded (%s)', $this->loaded) : 'not loaded';
83669 return 'The xdebug extension is '.$loaded;
83670 }
83671 }
83672 <?php
83673
83674
83675
83676
83677
83678
83679
83680
83681
83682
83683 namespace Composer\XdebugHandler;
83684
83685 use Psr\Log\LoggerInterface;
83686
83687
83688
83689
83690 class XdebugHandler
83691 {
83692 const SUFFIX_ALLOW = '_ALLOW_XDEBUG';
83693 const SUFFIX_INIS = '_ORIGINAL_INIS';
83694 const RESTART_ID = 'internal';
83695 const RESTART_SETTINGS = 'XDEBUG_HANDLER_SETTINGS';
83696 const DEBUG = 'XDEBUG_HANDLER_DEBUG';
83697
83698
83699 protected $tmpIni;
83700
83701 private static $inRestart;
83702 private static $name;
83703 private static $skipped;
83704
83705 private $cli;
83706 private $colorOption;
83707 private $debug;
83708 private $envAllowXdebug;
83709 private $envOriginalInis;
83710 private $loaded;
83711 private $script;
83712
83713 private $statusWriter;
83714
83715
83716
83717
83718
83719
83720
83721
83722
83723
83724
83725
83726 public function __construct($envPrefix, $colorOption = '')
83727 {
83728 if (!is_string($envPrefix) || empty($envPrefix) || !is_string($colorOption)) {
83729 throw new \RuntimeException('Invalid constructor parameter');
83730 }
83731
83732 self::$name = strtoupper($envPrefix);
83733 $this->envAllowXdebug = self::$name.self::SUFFIX_ALLOW;
83734 $this->envOriginalInis = self::$name.self::SUFFIX_INIS;
83735
83736 $this->colorOption = $colorOption;
83737
83738 if (extension_loaded('xdebug')) {
83739 $ext = new \ReflectionExtension('xdebug');
83740 $this->loaded = $ext->getVersion() ?: 'unknown';
83741 }
83742
83743 if ($this->cli = PHP_SAPI === 'cli') {
83744 $this->debug = getenv(self::DEBUG);
83745 }
83746
83747 $this->statusWriter = new Status($this->envAllowXdebug, (bool) $this->debug);
83748 }
83749
83750
83751
83752
83753
83754
83755
83756
83757 public function setLogger(LoggerInterface $logger)
83758 {
83759 $this->statusWriter->setLogger($logger);
83760 return $this;
83761 }
83762
83763
83764
83765
83766
83767
83768
83769
83770 public function setMainScript($script)
83771 {
83772 $this->script = $script;
83773 return $this;
83774 }
83775
83776
83777
83778
83779
83780
83781
83782
83783 public function check()
83784 {
83785 $this->notify(Status::CHECK, $this->loaded);
83786 $envArgs = explode('|', (string) getenv($this->envAllowXdebug));
83787
83788 if (empty($envArgs[0]) && $this->requiresRestart((bool) $this->loaded)) {
83789
83790  $this->notify(Status::RESTART);
83791
83792 if ($this->prepareRestart()) {
83793 $command = $this->getCommand();
83794 $this->notify(Status::RESTARTING, $command);
83795 $this->restart($command);
83796 }
83797 return;
83798 }
83799
83800 if (self::RESTART_ID === $envArgs[0] && count($envArgs) === 5) {
83801
83802  $this->notify(Status::RESTARTED);
83803
83804 Process::setEnv($this->envAllowXdebug);
83805 self::$inRestart = true;
83806
83807 if (!$this->loaded) {
83808
83809  self::$skipped = $envArgs[1];
83810 }
83811
83812
83813  $this->setEnvRestartSettings($envArgs);
83814 return;
83815 }
83816
83817 $this->notify(Status::NORESTART);
83818
83819 if ($settings = self::getRestartSettings()) {
83820
83821  $this->syncSettings($settings);
83822 }
83823 }
83824
83825
83826
83827
83828
83829
83830
83831
83832
83833 public static function getAllIniFiles()
83834 {
83835 if (!empty(self::$name)) {
83836 $env = getenv(self::$name.self::SUFFIX_INIS);
83837
83838 if (false !== $env) {
83839 return explode(PATH_SEPARATOR, $env);
83840 }
83841 }
83842
83843 $paths = array((string) php_ini_loaded_file());
83844
83845 if ($scanned = php_ini_scanned_files()) {
83846 $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
83847 }
83848
83849 return $paths;
83850 }
83851
83852
83853
83854
83855
83856
83857
83858
83859
83860 public static function getRestartSettings()
83861 {
83862 $envArgs = explode('|', (string) getenv(self::RESTART_SETTINGS));
83863
83864 if (count($envArgs) !== 6
83865 || (!self::$inRestart && php_ini_loaded_file() !== $envArgs[0])) {
83866 return;
83867 }
83868
83869 return array(
83870 'tmpIni' => $envArgs[0],
83871 'scannedInis' => (bool) $envArgs[1],
83872 'scanDir' => '*' === $envArgs[2] ? false : $envArgs[2],
83873 'phprc' => '*' === $envArgs[3] ? false : $envArgs[3],
83874 'inis' => explode(PATH_SEPARATOR, $envArgs[4]),
83875 'skipped' => $envArgs[5],
83876 );
83877 }
83878
83879
83880
83881
83882
83883
83884 public static function getSkippedVersion()
83885 {
83886 return (string) self::$skipped;
83887 }
83888
83889
83890
83891
83892
83893
83894
83895
83896 protected function requiresRestart($isLoaded)
83897 {
83898 return $isLoaded;
83899 }
83900
83901
83902
83903
83904
83905
83906 protected function restart($command)
83907 {
83908 $this->doRestart($command);
83909 }
83910
83911
83912
83913
83914
83915
83916 private function doRestart($command)
83917 {
83918 passthru($command, $exitCode);
83919 $this->notify(Status::INFO, 'Restarted process exited '.$exitCode);
83920
83921 if ($this->debug === '2') {
83922 $this->notify(Status::INFO, 'Temp ini saved: '.$this->tmpIni);
83923 } else {
83924 @unlink($this->tmpIni);
83925 }
83926
83927 exit($exitCode);
83928 }
83929
83930
83931
83932
83933
83934
83935
83936
83937
83938
83939
83940 private function prepareRestart()
83941 {
83942 $error = '';
83943 $iniFiles = self::getAllIniFiles();
83944 $scannedInis = count($iniFiles) > 1;
83945
83946 if (!$this->cli) {
83947 $error = 'Unsupported SAPI: '.PHP_SAPI;
83948 } elseif (!defined('PHP_BINARY')) {
83949 $error = 'PHP version is too old: '.PHP_VERSION;
83950 } elseif (!$this->checkMainScript()) {
83951 $error = 'Unable to access main script: '.$this->script;
83952 } elseif (!$this->writeTmpIni($iniFiles)) {
83953 $error = 'Unable to create temporary ini file';
83954 } elseif (!$this->setEnvironment($scannedInis, $iniFiles)) {
83955 $error = 'Unable to set environment variables';
83956 }
83957
83958 if ($error) {
83959 $this->notify(Status::ERROR, $error);
83960 }
83961
83962 return empty($error);
83963 }
83964
83965
83966
83967
83968
83969
83970
83971
83972 private function writeTmpIni(array $iniFiles)
83973 {
83974 if (!$this->tmpIni = tempnam(sys_get_temp_dir(), '')) {
83975 return false;
83976 }
83977
83978
83979  if (empty($iniFiles[0])) {
83980 array_shift($iniFiles);
83981 }
83982
83983 $content = '';
83984 $regex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
83985
83986 foreach ($iniFiles as $file) {
83987 $data = preg_replace($regex, ';$1', file_get_contents($file));
83988 $content .= $data.PHP_EOL;
83989 }
83990
83991
83992  if ($config = parse_ini_string($content)) {
83993 $loaded = ini_get_all(null, false);
83994 $content .= $this->mergeLoadedConfig($loaded, $config);
83995 }
83996
83997
83998  $content .= 'opcache.enable_cli=0'.PHP_EOL;
83999
84000 return @file_put_contents($this->tmpIni, $content);
84001 }
84002
84003
84004
84005
84006
84007
84008 private function getCommand()
84009 {
84010 $args = array_slice($_SERVER['argv'], 1);
84011
84012 if (defined('STDOUT') && Process::supportsColor(STDOUT)) {
84013 $args = Process::addColorOption($args, $this->colorOption);
84014 }
84015
84016 $executable = array(PHP_BINARY, '-n', '-c', $this->tmpIni, $this->script);
84017 $args = array_merge($executable, $args);
84018
84019 $cmd = Process::escape(array_shift($args), true, true);
84020 foreach ($args as $arg) {
84021 $cmd .= ' '.Process::escape($arg);
84022 }
84023
84024 return $cmd;
84025 }
84026
84027
84028
84029
84030
84031
84032
84033
84034
84035
84036
84037 private function setEnvironment($scannedInis, array $iniFiles)
84038 {
84039 $scanDir = getenv('PHP_INI_SCAN_DIR');
84040 $phprc = getenv('PHPRC');
84041
84042
84043  if (!putenv($this->envOriginalInis.'='.implode(PATH_SEPARATOR, $iniFiles))) {
84044 return false;
84045 }
84046
84047
84048  $envArgs = array(
84049 self::RESTART_ID,
84050 $this->loaded,
84051 (int) $scannedInis,
84052 false === $scanDir ? '*' : $scanDir,
84053 false === $phprc ? '*' : $phprc,
84054 );
84055
84056 return putenv($this->envAllowXdebug.'='.implode('|', $envArgs));
84057 }
84058
84059
84060
84061
84062
84063
84064
84065 private function notify($op, $data = null)
84066 {
84067 $this->statusWriter->report($op, $data);
84068 }
84069
84070
84071
84072
84073
84074
84075
84076
84077
84078 private function mergeLoadedConfig(array $loadedConfig, array $iniConfig)
84079 {
84080 $content = '';
84081
84082 foreach ($loadedConfig as $name => $value) {
84083
84084  if (!is_string($value) || strpos($name, 'xdebug') === 0) {
84085 continue;
84086 }
84087
84088 if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) {
84089
84090  $content .= $name.'="'.addcslashes($value, '\\"').'"'.PHP_EOL;
84091 }
84092 }
84093
84094 return $content;
84095 }
84096
84097
84098
84099
84100
84101
84102 private function checkMainScript()
84103 {
84104 if (null !== $this->script) {
84105
84106  return file_exists($this->script) || '--' === $this->script;
84107 }
84108
84109 if (file_exists($this->script = $_SERVER['argv'][0])) {
84110 return true;
84111 }
84112
84113
84114  $options = PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false;
84115 $trace = debug_backtrace($options);
84116
84117 if (($main = end($trace)) && isset($main['file'])) {
84118 return file_exists($this->script = $main['file']);
84119 }
84120
84121 return false;
84122 }
84123
84124
84125
84126
84127
84128
84129 private function setEnvRestartSettings($envArgs)
84130 {
84131 $settings = array(
84132 php_ini_loaded_file(),
84133 $envArgs[2],
84134 $envArgs[3],
84135 $envArgs[4],
84136 getenv($this->envOriginalInis),
84137 self::$skipped,
84138 );
84139
84140 Process::setEnv(self::RESTART_SETTINGS, implode('|', $settings));
84141 }
84142
84143
84144
84145
84146
84147
84148 private function syncSettings(array $settings)
84149 {
84150 if (false === getenv($this->envOriginalInis)) {
84151
84152  Process::setEnv($this->envOriginalInis, implode(PATH_SEPARATOR, $settings['inis']));
84153 }
84154
84155 self::$skipped = $settings['skipped'];
84156 $this->notify(Status::INFO, 'Process called with existing restart settings');
84157 }
84158 }
84159 Copyright (c) 2012 PHP Framework Interoperability Group
84160
84161 Permission is hereby granted, free of charge, to any person obtaining a copy 
84162 of this software and associated documentation files (the "Software"), to deal
84163 in the Software without restriction, including without limitation the rights 
84164 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
84165 copies of the Software, and to permit persons to whom the Software is 
84166 furnished to do so, subject to the following conditions:
84167
84168 The above copyright notice and this permission notice shall be included in 
84169 all copies or substantial portions of the Software.
84170
84171 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84172 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
84173 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
84174 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
84175 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
84176 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
84177 THE SOFTWARE.
84178 <?php
84179
84180 namespace Psr\Log;
84181
84182
84183
84184
84185
84186
84187
84188
84189 abstract class AbstractLogger implements LoggerInterface
84190 {
84191
84192
84193
84194
84195
84196
84197
84198
84199 public function emergency($message, array $context = array())
84200 {
84201 $this->log(LogLevel::EMERGENCY, $message, $context);
84202 }
84203
84204
84205
84206
84207
84208
84209
84210
84211
84212
84213
84214
84215 public function alert($message, array $context = array())
84216 {
84217 $this->log(LogLevel::ALERT, $message, $context);
84218 }
84219
84220
84221
84222
84223
84224
84225
84226
84227
84228
84229
84230 public function critical($message, array $context = array())
84231 {
84232 $this->log(LogLevel::CRITICAL, $message, $context);
84233 }
84234
84235
84236
84237
84238
84239
84240
84241
84242
84243
84244 public function error($message, array $context = array())
84245 {
84246 $this->log(LogLevel::ERROR, $message, $context);
84247 }
84248
84249
84250
84251
84252
84253
84254
84255
84256
84257
84258
84259
84260 public function warning($message, array $context = array())
84261 {
84262 $this->log(LogLevel::WARNING, $message, $context);
84263 }
84264
84265
84266
84267
84268
84269
84270
84271
84272
84273 public function notice($message, array $context = array())
84274 {
84275 $this->log(LogLevel::NOTICE, $message, $context);
84276 }
84277
84278
84279
84280
84281
84282
84283
84284
84285
84286
84287
84288 public function info($message, array $context = array())
84289 {
84290 $this->log(LogLevel::INFO, $message, $context);
84291 }
84292
84293
84294
84295
84296
84297
84298
84299
84300
84301 public function debug($message, array $context = array())
84302 {
84303 $this->log(LogLevel::DEBUG, $message, $context);
84304 }
84305 }
84306 <?php
84307
84308 namespace Psr\Log;
84309
84310 class InvalidArgumentException extends \InvalidArgumentException
84311 {
84312 }
84313 <?php
84314
84315 namespace Psr\Log;
84316
84317
84318
84319
84320 class LogLevel
84321 {
84322 const EMERGENCY = 'emergency';
84323 const ALERT = 'alert';
84324 const CRITICAL = 'critical';
84325 const ERROR = 'error';
84326 const WARNING = 'warning';
84327 const NOTICE = 'notice';
84328 const INFO = 'info';
84329 const DEBUG = 'debug';
84330 }
84331 <?php
84332
84333 namespace Psr\Log;
84334
84335
84336
84337
84338 interface LoggerAwareInterface
84339 {
84340
84341
84342
84343
84344
84345
84346
84347 public function setLogger(LoggerInterface $logger);
84348 }
84349 <?php
84350
84351 namespace Psr\Log;
84352
84353
84354
84355
84356 trait LoggerAwareTrait
84357 {
84358
84359
84360
84361
84362
84363 protected $logger;
84364
84365
84366
84367
84368
84369
84370 public function setLogger(LoggerInterface $logger)
84371 {
84372 $this->logger = $logger;
84373 }
84374 }
84375 <?php
84376
84377 namespace Psr\Log;
84378
84379
84380
84381
84382
84383
84384
84385
84386
84387
84388
84389
84390
84391
84392
84393
84394 interface LoggerInterface
84395 {
84396
84397
84398
84399
84400
84401
84402
84403
84404 public function emergency($message, array $context = array());
84405
84406
84407
84408
84409
84410
84411
84412
84413
84414
84415
84416
84417 public function alert($message, array $context = array());
84418
84419
84420
84421
84422
84423
84424
84425
84426
84427
84428
84429 public function critical($message, array $context = array());
84430
84431
84432
84433
84434
84435
84436
84437
84438
84439
84440 public function error($message, array $context = array());
84441
84442
84443
84444
84445
84446
84447
84448
84449
84450
84451
84452
84453 public function warning($message, array $context = array());
84454
84455
84456
84457
84458
84459
84460
84461
84462
84463 public function notice($message, array $context = array());
84464
84465
84466
84467
84468
84469
84470
84471
84472
84473
84474
84475 public function info($message, array $context = array());
84476
84477
84478
84479
84480
84481
84482
84483
84484
84485 public function debug($message, array $context = array());
84486
84487
84488
84489
84490
84491
84492
84493
84494
84495
84496 public function log($level, $message, array $context = array());
84497 }
84498 <?php
84499
84500 namespace Psr\Log;
84501
84502
84503
84504
84505
84506
84507
84508
84509
84510 trait LoggerTrait
84511 {
84512
84513
84514
84515
84516
84517
84518
84519
84520 public function emergency($message, array $context = array())
84521 {
84522 $this->log(LogLevel::EMERGENCY, $message, $context);
84523 }
84524
84525
84526
84527
84528
84529
84530
84531
84532
84533
84534
84535
84536 public function alert($message, array $context = array())
84537 {
84538 $this->log(LogLevel::ALERT, $message, $context);
84539 }
84540
84541
84542
84543
84544
84545
84546
84547
84548
84549
84550
84551 public function critical($message, array $context = array())
84552 {
84553 $this->log(LogLevel::CRITICAL, $message, $context);
84554 }
84555
84556
84557
84558
84559
84560
84561
84562
84563
84564
84565 public function error($message, array $context = array())
84566 {
84567 $this->log(LogLevel::ERROR, $message, $context);
84568 }
84569
84570
84571
84572
84573
84574
84575
84576
84577
84578
84579
84580
84581 public function warning($message, array $context = array())
84582 {
84583 $this->log(LogLevel::WARNING, $message, $context);
84584 }
84585
84586
84587
84588
84589
84590
84591
84592
84593
84594 public function notice($message, array $context = array())
84595 {
84596 $this->log(LogLevel::NOTICE, $message, $context);
84597 }
84598
84599
84600
84601
84602
84603
84604
84605
84606
84607
84608
84609 public function info($message, array $context = array())
84610 {
84611 $this->log(LogLevel::INFO, $message, $context);
84612 }
84613
84614
84615
84616
84617
84618
84619
84620
84621
84622 public function debug($message, array $context = array())
84623 {
84624 $this->log(LogLevel::DEBUG, $message, $context);
84625 }
84626
84627
84628
84629
84630
84631
84632
84633
84634
84635
84636 abstract public function log($level, $message, array $context = array());
84637 }
84638 <?php
84639
84640 namespace Psr\Log;
84641
84642
84643
84644
84645
84646
84647
84648
84649
84650 class NullLogger extends AbstractLogger
84651 {
84652
84653
84654
84655
84656
84657
84658
84659
84660
84661 public function log($level, $message, array $context = array())
84662 {
84663
84664  }
84665 }
84666 <?php
84667
84668 namespace Psr\Log\Test;
84669
84670 use Psr\Log\LoggerInterface;
84671 use Psr\Log\LogLevel;
84672
84673
84674
84675
84676
84677
84678
84679 abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase
84680 {
84681
84682
84683
84684 abstract public function getLogger();
84685
84686
84687
84688
84689
84690
84691
84692
84693
84694
84695 abstract public function getLogs();
84696
84697 public function testImplements()
84698 {
84699 $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
84700 }
84701
84702
84703
84704
84705 public function testLogsAtAllLevels($level, $message)
84706 {
84707 $logger = $this->getLogger();
84708 $logger->{$level}($message, array('user' => 'Bob'));
84709 $logger->log($level, $message, array('user' => 'Bob'));
84710
84711 $expected = array(
84712 $level.' message of level '.$level.' with context: Bob',
84713 $level.' message of level '.$level.' with context: Bob',
84714 );
84715 $this->assertEquals($expected, $this->getLogs());
84716 }
84717
84718 public function provideLevelsAndMessages()
84719 {
84720 return array(
84721 LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
84722 LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
84723 LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
84724 LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
84725 LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
84726 LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
84727 LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
84728 LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
84729 );
84730 }
84731
84732
84733
84734
84735 public function testThrowsOnInvalidLevel()
84736 {
84737 $logger = $this->getLogger();
84738 $logger->log('invalid level', 'Foo');
84739 }
84740
84741 public function testContextReplacement()
84742 {
84743 $logger = $this->getLogger();
84744 $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
84745
84746 $expected = array('info {Message {nothing} Bob Bar a}');
84747 $this->assertEquals($expected, $this->getLogs());
84748 }
84749
84750 public function testObjectCastToString()
84751 {
84752 if (method_exists($this, 'createPartialMock')) {
84753 $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
84754 } else {
84755 $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
84756 }
84757 $dummy->expects($this->once())
84758 ->method('__toString')
84759 ->will($this->returnValue('DUMMY'));
84760
84761 $this->getLogger()->warning($dummy);
84762
84763 $expected = array('warning DUMMY');
84764 $this->assertEquals($expected, $this->getLogs());
84765 }
84766
84767 public function testContextCanContainAnything()
84768 {
84769 $context = array(
84770 'bool' => true,
84771 'null' => null,
84772 'string' => 'Foo',
84773 'int' => 0,
84774 'float' => 0.5,
84775 'nested' => array('with object' => new DummyTest),
84776 'object' => new \DateTime,
84777 'resource' => fopen('php://memory', 'r'),
84778 );
84779
84780 $this->getLogger()->warning('Crazy context data', $context);
84781
84782 $expected = array('warning Crazy context data');
84783 $this->assertEquals($expected, $this->getLogs());
84784 }
84785
84786 public function testContextExceptionKeyCanBeExceptionOrOtherValues()
84787 {
84788 $logger = $this->getLogger();
84789 $logger->warning('Random message', array('exception' => 'oops'));
84790 $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
84791
84792 $expected = array(
84793 'warning Random message',
84794 'critical Uncaught Exception!'
84795 );
84796 $this->assertEquals($expected, $this->getLogs());
84797 }
84798 }
84799
84800 class DummyTest
84801 {
84802 public function __toString()
84803 {
84804 }
84805 }
84806 <?php
84807
84808
84809
84810 require_once __DIR__ . '/composer/autoload_real.php';
84811
84812 return ComposerAutoloaderInitComposerPhar1534431432::getLoader();
84813 <?php
84814
84815
84816
84817 $vendorDir = dirname(dirname(__FILE__));
84818 $baseDir = dirname($vendorDir);
84819
84820 return array(
84821 );
84822 <?php
84823
84824
84825
84826 $vendorDir = dirname(dirname(__FILE__));
84827 $baseDir = dirname($vendorDir);
84828
84829 return array(
84830 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
84831 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
84832 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
84833 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
84834 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
84835 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
84836 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
84837 'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
84838 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
84839 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
84840 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
84841 'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'),
84842 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
84843 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
84844 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
84845 'Composer\\' => array($baseDir . '/src/Composer'),
84846 );
84847 <?php
84848
84849
84850
84851 $vendorDir = dirname(dirname(__FILE__));
84852 $baseDir = dirname($vendorDir);
84853
84854 return array(
84855 );
84856 <?php
84857
84858
84859
84860 $vendorDir = dirname(dirname(__FILE__));
84861 $baseDir = dirname($vendorDir);
84862
84863 return array(
84864 '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
84865 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
84866 );
84867 <?php
84868
84869
84870
84871 class ComposerAutoloaderInitComposerPhar1534431432
84872 {
84873 private static $loader;
84874
84875 public static function loadClassLoader($class)
84876 {
84877 if ('Composer\Autoload\ClassLoader' === $class) {
84878 require __DIR__ . '/ClassLoader.php';
84879 }
84880 }
84881
84882 public static function getLoader()
84883 {
84884 if (null !== self::$loader) {
84885 return self::$loader;
84886 }
84887
84888 spl_autoload_register(array('ComposerAutoloaderInitComposerPhar1534431432', 'loadClassLoader'), true, true);
84889 self::$loader = $loader = new \Composer\Autoload\ClassLoader();
84890 spl_autoload_unregister(array('ComposerAutoloaderInitComposerPhar1534431432', 'loadClassLoader'));
84891
84892 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
84893 if ($useStaticLoader) {
84894 require_once __DIR__ . '/autoload_static.php';
84895
84896 call_user_func(\Composer\Autoload\ComposerStaticInitComposerPhar1534431432::getInitializer($loader));
84897 } else {
84898 $map = require __DIR__ . '/autoload_namespaces.php';
84899 foreach ($map as $namespace => $path) {
84900 $loader->set($namespace, $path);
84901 }
84902
84903 $map = require __DIR__ . '/autoload_psr4.php';
84904 foreach ($map as $namespace => $path) {
84905 $loader->setPsr4($namespace, $path);
84906 }
84907
84908 $classMap = require __DIR__ . '/autoload_classmap.php';
84909 if ($classMap) {
84910 $loader->addClassMap($classMap);
84911 }
84912 }
84913
84914 $loader->register(true);
84915
84916 if ($useStaticLoader) {
84917 $includeFiles = Composer\Autoload\ComposerStaticInitComposerPhar1534431432::$files;
84918 } else {
84919 $includeFiles = require __DIR__ . '/autoload_files.php';
84920 }
84921 foreach ($includeFiles as $fileIdentifier => $file) {
84922 composerRequireComposerPhar1534431432($fileIdentifier, $file);
84923 }
84924
84925 return $loader;
84926 }
84927 }
84928
84929 function composerRequireComposerPhar1534431432($fileIdentifier, $file)
84930 {
84931 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
84932 require $file;
84933
84934 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
84935 }
84936 }
84937 <?php
84938
84939
84940
84941 namespace Composer\Autoload;
84942
84943 class ComposerStaticInitComposerPhar1534431432
84944 {
84945 public static $files = array (
84946 '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
84947 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
84948 );
84949
84950 public static $prefixLengthsPsr4 = array (
84951 'S' => 
84952 array (
84953 'Symfony\\Polyfill\\Mbstring\\' => 26,
84954 'Symfony\\Polyfill\\Ctype\\' => 23,
84955 'Symfony\\Component\\Process\\' => 26,
84956 'Symfony\\Component\\Finder\\' => 25,
84957 'Symfony\\Component\\Filesystem\\' => 29,
84958 'Symfony\\Component\\Debug\\' => 24,
84959 'Symfony\\Component\\Console\\' => 26,
84960 'Seld\\PharUtils\\' => 15,
84961 'Seld\\JsonLint\\' => 14,
84962 ),
84963 'P' => 
84964 array (
84965 'Psr\\Log\\' => 8,
84966 ),
84967 'J' => 
84968 array (
84969 'JsonSchema\\' => 11,
84970 ),
84971 'C' => 
84972 array (
84973 'Composer\\XdebugHandler\\' => 23,
84974 'Composer\\Spdx\\' => 14,
84975 'Composer\\Semver\\' => 16,
84976 'Composer\\CaBundle\\' => 18,
84977 'Composer\\' => 9,
84978 ),
84979 );
84980
84981 public static $prefixDirsPsr4 = array (
84982 'Symfony\\Polyfill\\Mbstring\\' => 
84983 array (
84984 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
84985 ),
84986 'Symfony\\Polyfill\\Ctype\\' => 
84987 array (
84988 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
84989 ),
84990 'Symfony\\Component\\Process\\' => 
84991 array (
84992 0 => __DIR__ . '/..' . '/symfony/process',
84993 ),
84994 'Symfony\\Component\\Finder\\' => 
84995 array (
84996 0 => __DIR__ . '/..' . '/symfony/finder',
84997 ),
84998 'Symfony\\Component\\Filesystem\\' => 
84999 array (
85000 0 => __DIR__ . '/..' . '/symfony/filesystem',
85001 ),
85002 'Symfony\\Component\\Debug\\' => 
85003 array (
85004 0 => __DIR__ . '/..' . '/symfony/debug',
85005 ),
85006 'Symfony\\Component\\Console\\' => 
85007 array (
85008 0 => __DIR__ . '/..' . '/symfony/console',
85009 ),
85010 'Seld\\PharUtils\\' => 
85011 array (
85012 0 => __DIR__ . '/..' . '/seld/phar-utils/src',
85013 ),
85014 'Seld\\JsonLint\\' => 
85015 array (
85016 0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
85017 ),
85018 'Psr\\Log\\' => 
85019 array (
85020 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
85021 ),
85022 'JsonSchema\\' => 
85023 array (
85024 0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema',
85025 ),
85026 'Composer\\XdebugHandler\\' => 
85027 array (
85028 0 => __DIR__ . '/..' . '/composer/xdebug-handler/src',
85029 ),
85030 'Composer\\Spdx\\' => 
85031 array (
85032 0 => __DIR__ . '/..' . '/composer/spdx-licenses/src',
85033 ),
85034 'Composer\\Semver\\' => 
85035 array (
85036 0 => __DIR__ . '/..' . '/composer/semver/src',
85037 ),
85038 'Composer\\CaBundle\\' => 
85039 array (
85040 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
85041 ),
85042 'Composer\\' => 
85043 array (
85044 0 => __DIR__ . '/../..' . '/src/Composer',
85045 ),
85046 );
85047
85048 public static function getInitializer(ClassLoader $loader)
85049 {
85050 return \Closure::bind(function () use ($loader) {
85051 $loader->prefixLengthsPsr4 = ComposerStaticInitComposerPhar1534431432::$prefixLengthsPsr4;
85052 $loader->prefixDirsPsr4 = ComposerStaticInitComposerPhar1534431432::$prefixDirsPsr4;
85053
85054 }, null, ClassLoader::class);
85055 }
85056 }
85057 <?php
85058
85059
85060
85061
85062
85063
85064
85065
85066
85067
85068
85069 namespace Composer\Autoload;
85070
85071
85072
85073
85074
85075
85076
85077
85078
85079
85080
85081
85082
85083
85084
85085
85086
85087
85088
85089
85090
85091
85092
85093
85094
85095
85096
85097
85098
85099 class ClassLoader
85100 {
85101
85102  private $prefixLengthsPsr4 = array();
85103 private $prefixDirsPsr4 = array();
85104 private $fallbackDirsPsr4 = array();
85105
85106
85107  private $prefixesPsr0 = array();
85108 private $fallbackDirsPsr0 = array();
85109
85110 private $useIncludePath = false;
85111 private $classMap = array();
85112 private $classMapAuthoritative = false;
85113 private $missingClasses = array();
85114 private $apcuPrefix;
85115
85116 public function getPrefixes()
85117 {
85118 if (!empty($this->prefixesPsr0)) {
85119 return call_user_func_array('array_merge', $this->prefixesPsr0);
85120 }
85121
85122 return array();
85123 }
85124
85125 public function getPrefixesPsr4()
85126 {
85127 return $this->prefixDirsPsr4;
85128 }
85129
85130 public function getFallbackDirs()
85131 {
85132 return $this->fallbackDirsPsr0;
85133 }
85134
85135 public function getFallbackDirsPsr4()
85136 {
85137 return $this->fallbackDirsPsr4;
85138 }
85139
85140 public function getClassMap()
85141 {
85142 return $this->classMap;
85143 }
85144
85145
85146
85147
85148 public function addClassMap(array $classMap)
85149 {
85150 if ($this->classMap) {
85151 $this->classMap = array_merge($this->classMap, $classMap);
85152 } else {
85153 $this->classMap = $classMap;
85154 }
85155 }
85156
85157
85158
85159
85160
85161
85162
85163
85164
85165 public function add($prefix, $paths, $prepend = false)
85166 {
85167 if (!$prefix) {
85168 if ($prepend) {
85169 $this->fallbackDirsPsr0 = array_merge(
85170 (array) $paths,
85171 $this->fallbackDirsPsr0
85172 );
85173 } else {
85174 $this->fallbackDirsPsr0 = array_merge(
85175 $this->fallbackDirsPsr0,
85176 (array) $paths
85177 );
85178 }
85179
85180 return;
85181 }
85182
85183 $first = $prefix[0];
85184 if (!isset($this->prefixesPsr0[$first][$prefix])) {
85185 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
85186
85187 return;
85188 }
85189 if ($prepend) {
85190 $this->prefixesPsr0[$first][$prefix] = array_merge(
85191 (array) $paths,
85192 $this->prefixesPsr0[$first][$prefix]
85193 );
85194 } else {
85195 $this->prefixesPsr0[$first][$prefix] = array_merge(
85196 $this->prefixesPsr0[$first][$prefix],
85197 (array) $paths
85198 );
85199 }
85200 }
85201
85202
85203
85204
85205
85206
85207
85208
85209
85210
85211
85212 public function addPsr4($prefix, $paths, $prepend = false)
85213 {
85214 if (!$prefix) {
85215
85216  if ($prepend) {
85217 $this->fallbackDirsPsr4 = array_merge(
85218 (array) $paths,
85219 $this->fallbackDirsPsr4
85220 );
85221 } else {
85222 $this->fallbackDirsPsr4 = array_merge(
85223 $this->fallbackDirsPsr4,
85224 (array) $paths
85225 );
85226 }
85227 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
85228
85229  $length = strlen($prefix);
85230 if ('\\' !== $prefix[$length - 1]) {
85231 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
85232 }
85233 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
85234 $this->prefixDirsPsr4[$prefix] = (array) $paths;
85235 } elseif ($prepend) {
85236
85237  $this->prefixDirsPsr4[$prefix] = array_merge(
85238 (array) $paths,
85239 $this->prefixDirsPsr4[$prefix]
85240 );
85241 } else {
85242
85243  $this->prefixDirsPsr4[$prefix] = array_merge(
85244 $this->prefixDirsPsr4[$prefix],
85245 (array) $paths
85246 );
85247 }
85248 }
85249
85250
85251
85252
85253
85254
85255
85256
85257 public function set($prefix, $paths)
85258 {
85259 if (!$prefix) {
85260 $this->fallbackDirsPsr0 = (array) $paths;
85261 } else {
85262 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
85263 }
85264 }
85265
85266
85267
85268
85269
85270
85271
85272
85273
85274
85275 public function setPsr4($prefix, $paths)
85276 {
85277 if (!$prefix) {
85278 $this->fallbackDirsPsr4 = (array) $paths;
85279 } else {
85280 $length = strlen($prefix);
85281 if ('\\' !== $prefix[$length - 1]) {
85282 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
85283 }
85284 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
85285 $this->prefixDirsPsr4[$prefix] = (array) $paths;
85286 }
85287 }
85288
85289
85290
85291
85292
85293
85294 public function setUseIncludePath($useIncludePath)
85295 {
85296 $this->useIncludePath = $useIncludePath;
85297 }
85298
85299
85300
85301
85302
85303
85304
85305 public function getUseIncludePath()
85306 {
85307 return $this->useIncludePath;
85308 }
85309
85310
85311
85312
85313
85314
85315
85316 public function setClassMapAuthoritative($classMapAuthoritative)
85317 {
85318 $this->classMapAuthoritative = $classMapAuthoritative;
85319 }
85320
85321
85322
85323
85324
85325
85326 public function isClassMapAuthoritative()
85327 {
85328 return $this->classMapAuthoritative;
85329 }
85330
85331
85332
85333
85334
85335
85336 public function setApcuPrefix($apcuPrefix)
85337 {
85338 $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
85339 }
85340
85341
85342
85343
85344
85345
85346 public function getApcuPrefix()
85347 {
85348 return $this->apcuPrefix;
85349 }
85350
85351
85352
85353
85354
85355
85356 public function register($prepend = false)
85357 {
85358 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
85359 }
85360
85361
85362
85363
85364 public function unregister()
85365 {
85366 spl_autoload_unregister(array($this, 'loadClass'));
85367 }
85368
85369
85370
85371
85372
85373
85374
85375 public function loadClass($class)
85376 {
85377 if ($file = $this->findFile($class)) {
85378 includeFile($file);
85379
85380 return true;
85381 }
85382 }
85383
85384
85385
85386
85387
85388
85389
85390
85391 public function findFile($class)
85392 {
85393
85394  if (isset($this->classMap[$class])) {
85395 return $this->classMap[$class];
85396 }
85397 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
85398 return false;
85399 }
85400 if (null !== $this->apcuPrefix) {
85401 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
85402 if ($hit) {
85403 return $file;
85404 }
85405 }
85406
85407 $file = $this->findFileWithExtension($class, '.php');
85408
85409
85410  if (false === $file && defined('HHVM_VERSION')) {
85411 $file = $this->findFileWithExtension($class, '.hh');
85412 }
85413
85414 if (null !== $this->apcuPrefix) {
85415 apcu_add($this->apcuPrefix.$class, $file);
85416 }
85417
85418 if (false === $file) {
85419
85420  $this->missingClasses[$class] = true;
85421 }
85422
85423 return $file;
85424 }
85425
85426 private function findFileWithExtension($class, $ext)
85427 {
85428
85429  $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
85430
85431 $first = $class[0];
85432 if (isset($this->prefixLengthsPsr4[$first])) {
85433 $subPath = $class;
85434 while (false !== $lastPos = strrpos($subPath, '\\')) {
85435 $subPath = substr($subPath, 0, $lastPos);
85436 $search = $subPath . '\\';
85437 if (isset($this->prefixDirsPsr4[$search])) {
85438 $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
85439 foreach ($this->prefixDirsPsr4[$search] as $dir) {
85440 if (file_exists($file = $dir . $pathEnd)) {
85441 return $file;
85442 }
85443 }
85444 }
85445 }
85446 }
85447
85448
85449  foreach ($this->fallbackDirsPsr4 as $dir) {
85450 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
85451 return $file;
85452 }
85453 }
85454
85455
85456  if (false !== $pos = strrpos($class, '\\')) {
85457
85458  $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
85459 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
85460 } else {
85461
85462  $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
85463 }
85464
85465 if (isset($this->prefixesPsr0[$first])) {
85466 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
85467 if (0 === strpos($class, $prefix)) {
85468 foreach ($dirs as $dir) {
85469 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
85470 return $file;
85471 }
85472 }
85473 }
85474 }
85475 }
85476
85477
85478  foreach ($this->fallbackDirsPsr0 as $dir) {
85479 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
85480 return $file;
85481 }
85482 }
85483
85484
85485  if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
85486 return $file;
85487 }
85488
85489 return false;
85490 }
85491 }
85492
85493
85494
85495
85496
85497
85498 function includeFile($file)
85499 {
85500 include $file;
85501 }
85502 ##
85503 ## Bundle of CA Root Certificates
85504 ##
85505 ## Certificate data from Mozilla as of: Wed Jun 20 03:12:06 2018 GMT
85506 ##
85507 ## This is a bundle of X.509 certificates of public Certificate Authorities
85508 ## (CA). These were automatically extracted from Mozilla's root certificates
85509 ## file (certdata.txt).  This file can be found in the mozilla source tree:
85510 ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
85511 ##
85512 ## It contains the certificates in PEM format and therefore
85513 ## can be directly used with curl / libcurl / php_curl, or with
85514 ## an Apache+mod_ssl webserver for SSL client authentication.
85515 ## Just configure this file as the SSLCACertificateFile.
85516 ##
85517 ## Conversion done with mk-ca-bundle.pl version 1.27.
85518 ## SHA256: c80f571d9f4ebca4a91e0ad3a546f263153d71afffc845c6f8f52ce9d1a2e8ec
85519 ##
85520
85521
85522 GlobalSign Root CA
85523 ==================
85524 -----BEGIN CERTIFICATE-----
85525 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
85526 GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
85527 b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
85528 BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
85529 VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
85530 DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
85531 THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
85532 Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
85533 c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
85534 gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
85535 HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
85536 AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
85537 Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
85538 j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
85539 hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
85540 X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
85541 -----END CERTIFICATE-----
85542
85543 GlobalSign Root CA - R2
85544 =======================
85545 -----BEGIN CERTIFICATE-----
85546 MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
85547 YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
85548 bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
85549 aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
85550 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
85551 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
85552 s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
85553 S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
85554 TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
85555 ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
85556 FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
85557 YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
85558 BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
85559 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
85560 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
85561 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
85562 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
85563 -----END CERTIFICATE-----
85564
85565 Verisign Class 3 Public Primary Certification Authority - G3
85566 ============================================================
85567 -----BEGIN CERTIFICATE-----
85568 MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
85569 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
85570 cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
85571 IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
85572 dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
85573 CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
85574 dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
85575 cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
85576 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
85577 ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
85578 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
85579 cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
85580 EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
85581 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
85582 ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
85583 j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
85584 /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
85585 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
85586 t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
85587 -----END CERTIFICATE-----
85588
85589 Entrust.net Premium 2048 Secure Server CA
85590 =========================================
85591 -----BEGIN CERTIFICATE-----
85592 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
85593 ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
85594 bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
85595 BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
85596 NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
85597 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
85598 MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
85599 ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
85600 MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
85601 Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
85602 hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
85603 nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
85604 VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
85605 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
85606 KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
85607 T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
85608 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
85609 J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
85610 nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
85611 -----END CERTIFICATE-----
85612
85613 Baltimore CyberTrust Root
85614 =========================
85615 -----BEGIN CERTIFICATE-----
85616 MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
85617 ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
85618 ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
85619 SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
85620 dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
85621 uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
85622 UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
85623 G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
85624 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
85625 l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
85626 VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
85627 BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
85628 cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
85629 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
85630 Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
85631 RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
85632 -----END CERTIFICATE-----
85633
85634 AddTrust External Root
85635 ======================
85636 -----BEGIN CERTIFICATE-----
85637 MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
85638 QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
85639 VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
85640 NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
85641 cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
85642 Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
85643 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
85644 Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
85645 aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
85646 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
85647 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
85648 BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
85649 VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
85650 VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
85651 IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
85652 j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
85653 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
85654 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
85655 G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
85656 -----END CERTIFICATE-----
85657
85658 Entrust Root Certification Authority
85659 ====================================
85660 -----BEGIN CERTIFICATE-----
85661 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
85662 BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
85663 b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
85664 A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
85665 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
85666 MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
85667 Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
85668 dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
85669 ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
85670 A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
85671 Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
85672 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
85673 rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
85674 DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
85675 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
85676 hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
85677 A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
85678 Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
85679 v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
85680 W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
85681 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
85682 -----END CERTIFICATE-----
85683
85684 GeoTrust Global CA
85685 ==================
85686 -----BEGIN CERTIFICATE-----
85687 MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
85688 Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
85689 MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
85690 LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
85691 CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
85692 BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
85693 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
85694 T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
85695 vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
85696 AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
85697 DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
85698 zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
85699 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
85700 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
85701 XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
85702 Mw==
85703 -----END CERTIFICATE-----
85704
85705 GeoTrust Universal CA
85706 =====================
85707 -----BEGIN CERTIFICATE-----
85708 MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
85709 R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
85710 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
85711 Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
85712 ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
85713 JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
85714 RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
85715 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
85716 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
85717 qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
85718 Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
85719 Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
85720 KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
85721 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
85722 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
85723 hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
85724 aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
85725 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
85726 oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
85727 xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
85728 KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
85729 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
85730 xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
85731 p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
85732 P/rmMuGNG2+k5o7Y+SlIis5z/iw=
85733 -----END CERTIFICATE-----
85734
85735 GeoTrust Universal CA 2
85736 =======================
85737 -----BEGIN CERTIFICATE-----
85738 MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
85739 R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
85740 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
85741 SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
85742 A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
85743 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
85744 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
85745 JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
85746 QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
85747 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
85748 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
85749 ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
85750 SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
85751 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
85752 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
85753 BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
85754 dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
85755 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
85756 mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
85757 A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
85758 Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
85759 pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
85760 FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
85761 gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
85762 X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
85763 -----END CERTIFICATE-----
85764
85765 Visa eCommerce Root
85766 ===================
85767 -----BEGIN CERTIFICATE-----
85768 MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
85769 EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
85770 QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
85771 WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
85772 VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
85773 bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
85774 F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
85775 RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
85776 TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
85777 /k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
85778 GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
85779 MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
85780 CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
85781 YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
85782 zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
85783 YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
85784 398znM/jra6O1I7mT1GvFpLgXPYHDw==
85785 -----END CERTIFICATE-----
85786
85787 Comodo AAA Services root
85788 ========================
85789 -----BEGIN CERTIFICATE-----
85790 MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
85791 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
85792 TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
85793 MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
85794 c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
85795 BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
85796 ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
85797 C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
85798 i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
85799 Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
85800 Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
85801 Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
85802 BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
85803 cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
85804 LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
85805 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
85806 Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
85807 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
85808 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
85809 -----END CERTIFICATE-----
85810
85811 QuoVadis Root CA
85812 ================
85813 -----BEGIN CERTIFICATE-----
85814 MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
85815 ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
85816 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
85817 MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
85818 cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
85819 EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
85820 AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
85821 J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
85822 F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
85823 YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
85824 AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
85825 PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
85826 ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
85827 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
85828 YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
85829 ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
85830 Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
85831 Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
85832 BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
85833 FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
85834 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
85835 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
85836 fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
85837 LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
85838 gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
85839 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
85840 5nrQNiOKSnQ2+Q==
85841 -----END CERTIFICATE-----
85842
85843 QuoVadis Root CA 2
85844 ==================
85845 -----BEGIN CERTIFICATE-----
85846 MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
85847 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
85848 ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
85849 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
85850 DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
85851 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
85852 lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
85853 lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
85854 lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
85855 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
85856 wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
85857 D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
85858 BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
85859 J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
85860 DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
85861 a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
85862 ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
85863 Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
85864 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
85865 VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
85866 +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
85867 IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
85868 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
85869 f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
85870 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
85871 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
85872 -----END CERTIFICATE-----
85873
85874 QuoVadis Root CA 3
85875 ==================
85876 -----BEGIN CERTIFICATE-----
85877 MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
85878 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
85879 OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
85880 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
85881 DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
85882 DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
85883 KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
85884 DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
85885 BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
85886 p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
85887 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
85888 MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
85889 Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
85890 uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
85891 BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
85892 YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
85893 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
85894 BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
85895 VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
85896 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
85897 AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
85898 qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
85899 hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
85900 POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
85901 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
85902 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
85903 bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
85904 g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
85905 vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
85906 qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
85907 -----END CERTIFICATE-----
85908
85909 Security Communication Root CA
85910 ==============================
85911 -----BEGIN CERTIFICATE-----
85912 MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
85913 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
85914 HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
85915 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
85916 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
85917 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
85918 DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
85919 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
85920 DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
85921 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
85922 DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
85923 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
85924 mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
85925 s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
85926 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
85927 FL39vmwLAw==
85928 -----END CERTIFICATE-----
85929
85930 Sonera Class 2 Root CA
85931 ======================
85932 -----BEGIN CERTIFICATE-----
85933 MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
85934 U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
85935 NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
85936 IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
85937 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
85938 dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
85939 f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
85940 tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
85941 nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
85942 XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
85943 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
85944 cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
85945 Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
85946 EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
85947 llpwrN9M
85948 -----END CERTIFICATE-----
85949
85950 XRamp Global CA Root
85951 ====================
85952 -----BEGIN CERTIFICATE-----
85953 MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
85954 BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
85955 dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
85956 dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
85957 HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
85958 U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
85959 dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
85960 IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
85961 foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
85962 zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
85963 AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
85964 xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
85965 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
85966 oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
85967 AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
85968 /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
85969 qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
85970 nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
85971 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
85972 -----END CERTIFICATE-----
85973
85974 Go Daddy Class 2 CA
85975 ===================
85976 -----BEGIN CERTIFICATE-----
85977 MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
85978 VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
85979 ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
85980 A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
85981 RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
85982 ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
85983 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
85984 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
85985 YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
85986 vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
85987 BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
85988 atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
85989 MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
85990 A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
85991 PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
85992 I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
85993 HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
85994 Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
85995 vZ8=
85996 -----END CERTIFICATE-----
85997
85998 Starfield Class 2 CA
85999 ====================
86000 -----BEGIN CERTIFICATE-----
86001 MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
86002 U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
86003 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
86004 MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
86005 A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
86006 SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
86007 bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
86008 JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
86009 epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
86010 F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
86011 MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
86012 hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
86013 bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
86014 QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
86015 afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
86016 PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
86017 xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
86018 KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
86019 QBFGmh95DmK/D5fs4C8fF5Q=
86020 -----END CERTIFICATE-----
86021
86022 Taiwan GRCA
86023 ===========
86024 -----BEGIN CERTIFICATE-----
86025 MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
86026 EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
86027 DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
86028 dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
86029 ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
86030 w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
86031 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
86032 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
86033 htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
86034 J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
86035 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
86036 B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
86037 O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
86038 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
86039 HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
86040 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
86041 TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
86042 Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
86043 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
86044 D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
86045 DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
86046 Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
86047 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
86048 CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
86049 +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
86050 -----END CERTIFICATE-----
86051
86052 DigiCert Assured ID Root CA
86053 ===========================
86054 -----BEGIN CERTIFICATE-----
86055 MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
86056 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
86057 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
86058 MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
86059 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
86060 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
86061 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
86062 UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
86063 /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
86064 oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
86065 GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
86066 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
86067 hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
86068 EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
86069 SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
86070 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
86071 +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
86072 -----END CERTIFICATE-----
86073
86074 DigiCert Global Root CA
86075 =======================
86076 -----BEGIN CERTIFICATE-----
86077 MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
86078 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
86079 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
86080 MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
86081 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
86082 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
86083 TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
86084 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
86085 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
86086 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
86087 o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
86088 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
86089 BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
86090 EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
86091 tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
86092 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
86093 CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
86094 -----END CERTIFICATE-----
86095
86096 DigiCert High Assurance EV Root CA
86097 ==================================
86098 -----BEGIN CERTIFICATE-----
86099 MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
86100 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
86101 KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
86102 MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
86103 MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
86104 Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
86105 Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
86106 OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
86107 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
86108 NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
86109 h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
86110 Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
86111 JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
86112 V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
86113 myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
86114 mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
86115 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
86116 -----END CERTIFICATE-----
86117
86118 Certplus Class 2 Primary CA
86119 ===========================
86120 -----BEGIN CERTIFICATE-----
86121 MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
86122 BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
86123 OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
86124 dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
86125 ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
86126 5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
86127 Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
86128 YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
86129 e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
86130 CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
86131 YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
86132 L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
86133 P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
86134 TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
86135 7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
86136 //1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
86137 l7+ijrRU
86138 -----END CERTIFICATE-----
86139
86140 DST Root CA X3
86141 ==============
86142 -----BEGIN CERTIFICATE-----
86143 MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
86144 ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
86145 DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
86146 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
86147 ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
86148 rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
86149 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
86150 xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
86151 utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
86152 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
86153 MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
86154 dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
86155 GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
86156 RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
86157 fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
86158 -----END CERTIFICATE-----
86159
86160 SwissSign Gold CA - G2
86161 ======================
86162 -----BEGIN CERTIFICATE-----
86163 MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
86164 EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
86165 MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
86166 c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
86167 AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
86168 t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
86169 jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
86170 vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
86171 ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
86172 AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
86173 jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
86174 peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
86175 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
86176 GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
86177 AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
86178 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
86179 L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
86180 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
86181 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
86182 Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
86183 Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
86184 mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
86185 vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
86186 KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
86187 NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
86188 viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
86189 -----END CERTIFICATE-----
86190
86191 SwissSign Silver CA - G2
86192 ========================
86193 -----BEGIN CERTIFICATE-----
86194 MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
86195 BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
86196 DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
86197 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
86198 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
86199 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
86200 +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
86201 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
86202 MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
86203 qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
86204 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
86205 ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
86206 celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
86207 CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
86208 BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
86209 tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
86210 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
86211 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
86212 kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
86213 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
86214 /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
86215 DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
86216 e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
86217 WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
86218 DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
86219 DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
86220 -----END CERTIFICATE-----
86221
86222 GeoTrust Primary Certification Authority
86223 ========================================
86224 -----BEGIN CERTIFICATE-----
86225 MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
86226 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
86227 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
86228 CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
86229 cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
86230 CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
86231 b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
86232 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
86233 RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
86234 tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86235 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
86236 hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
86237 Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
86238 NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
86239 Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
86240 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
86241 -----END CERTIFICATE-----
86242
86243 thawte Primary Root CA
86244 ======================
86245 -----BEGIN CERTIFICATE-----
86246 MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
86247 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
86248 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
86249 cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
86250 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
86251 SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
86252 KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
86253 FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
86254 oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
86255 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
86256 q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
86257 aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
86258 afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
86259 VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
86260 AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
86261 uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
86262 xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
86263 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
86264 z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
86265 -----END CERTIFICATE-----
86266
86267 VeriSign Class 3 Public Primary Certification Authority - G5
86268 ============================================================
86269 -----BEGIN CERTIFICATE-----
86270 MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
86271 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
86272 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
86273 IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
86274 ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
86275 yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
86276 biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
86277 dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
86278 YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
86279 ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
86280 j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
86281 Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
86282 Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
86283 fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
86284 BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
86285 Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
86286 aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
86287 SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
86288 X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
86289 KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
86290 Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
86291 ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
86292 -----END CERTIFICATE-----
86293
86294 SecureTrust CA
86295 ==============
86296 -----BEGIN CERTIFICATE-----
86297 MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
86298 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
86299 dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
86300 BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
86301 ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
86302 OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
86303 DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
86304 GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
86305 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
86306 ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
86307 BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
86308 aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
86309 KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
86310 SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
86311 mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
86312 nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
86313 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
86314 -----END CERTIFICATE-----
86315
86316 Secure Global CA
86317 ================
86318 -----BEGIN CERTIFICATE-----
86319 MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
86320 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
86321 bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
86322 MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
86323 Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
86324 YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
86325 bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
86326 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
86327 HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
86328 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
86329 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
86330 oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
86331 MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
86332 OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
86333 CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
86334 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
86335 f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
86336 -----END CERTIFICATE-----
86337
86338 COMODO Certification Authority
86339 ==============================
86340 -----BEGIN CERTIFICATE-----
86341 MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
86342 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
86343 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
86344 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
86345 MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
86346 T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
86347 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
86348 +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
86349 xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
86350 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
86351 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
86352 rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
86353 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
86354 b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
86355 AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
86356 OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
86357 RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
86358 IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
86359 +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
86360 -----END CERTIFICATE-----
86361
86362 Network Solutions Certificate Authority
86363 =======================================
86364 -----BEGIN CERTIFICATE-----
86365 MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
86366 EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
86367 IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
86368 MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
86369 MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
86370 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
86371 jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
86372 aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
86373 crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
86374 /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
86375 AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
86376 BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
86377 bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
86378 A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
86379 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
86380 GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
86381 wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
86382 ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
86383 -----END CERTIFICATE-----
86384
86385 COMODO ECC Certification Authority
86386 ==================================
86387 -----BEGIN CERTIFICATE-----
86388 MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
86389 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
86390 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
86391 dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
86392 GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
86393 Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
86394 b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
86395 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
86396 wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
86397 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
86398 FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
86399 U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
86400 -----END CERTIFICATE-----
86401
86402 OISTE WISeKey Global Root GA CA
86403 ===============================
86404 -----BEGIN CERTIFICATE-----
86405 MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
86406 BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
86407 A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
86408 bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
86409 VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
86410 IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
86411 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
86412 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
86413 Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
86414 d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
86415 /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
86416 LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
86417 AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
86418 KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
86419 MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
86420 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
86421 hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
86422 okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
86423 -----END CERTIFICATE-----
86424
86425 Certigna
86426 ========
86427 -----BEGIN CERTIFICATE-----
86428 MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
86429 EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
86430 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
86431 Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
86432 XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
86433 GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
86434 ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
86435 DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
86436 Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
86437 tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
86438 BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
86439 SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
86440 hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
86441 ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
86442 PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
86443 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
86444 WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
86445 -----END CERTIFICATE-----
86446
86447 Deutsche Telekom Root CA 2
86448 ==========================
86449 -----BEGIN CERTIFICATE-----
86450 MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
86451 RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
86452 A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
86453 MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
86454 A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
86455 b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
86456 bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
86457 KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
86458 AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
86459 Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
86460 jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
86461 HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
86462 E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
86463 zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
86464 rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
86465 dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
86466 Cm26OWMohpLzGITY+9HPBVZkVw==
86467 -----END CERTIFICATE-----
86468
86469 Cybertrust Global Root
86470 ======================
86471 -----BEGIN CERTIFICATE-----
86472 MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
86473 ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
86474 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
86475 ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
86476 +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
86477 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
86478 AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
86479 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
86480 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
86481 BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
86482 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
86483 A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
86484 lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
86485 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
86486 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
86487 X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
86488 WL1WMRJOEcgh4LMRkWXbtKaIOM5V
86489 -----END CERTIFICATE-----
86490
86491 ePKI Root Certification Authority
86492 =================================
86493 -----BEGIN CERTIFICATE-----
86494 MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
86495 EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
86496 Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
86497 MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
86498 MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
86499 AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
86500 IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
86501 lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
86502 qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
86503 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
86504 WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
86505 ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
86506 lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
86507 vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
86508 Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
86509 MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
86510 ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
86511 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
86512 KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
86513 xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
86514 NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
86515 GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
86516 xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
86517 gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
86518 sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
86519 BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
86520 -----END CERTIFICATE-----
86521
86522 certSIGN ROOT CA
86523 ================
86524 -----BEGIN CERTIFICATE-----
86525 MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
86526 VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
86527 Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
86528 CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
86529 JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
86530 rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
86531 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
86532 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
86533 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
86534 Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
86535 AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
86536 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
86537 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
86538 vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
86539 TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
86540 -----END CERTIFICATE-----
86541
86542 GeoTrust Primary Certification Authority - G3
86543 =============================================
86544 -----BEGIN CERTIFICATE-----
86545 MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
86546 BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
86547 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
86548 eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
86549 NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
86550 YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
86551 LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
86552 hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
86553 K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
86554 c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
86555 IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
86556 dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
86557 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
86558 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
86559 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
86560 Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
86561 AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
86562 t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
86563 -----END CERTIFICATE-----
86564
86565 thawte Primary Root CA - G2
86566 ===========================
86567 -----BEGIN CERTIFICATE-----
86568 MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
86569 VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
86570 IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
86571 Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
86572 MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
86573 b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
86574 IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
86575 LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
86576 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
86577 mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
86578 G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
86579 rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
86580 -----END CERTIFICATE-----
86581
86582 thawte Primary Root CA - G3
86583 ===========================
86584 -----BEGIN CERTIFICATE-----
86585 MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
86586 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
86587 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
86588 cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
86589 ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
86590 d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
86591 VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
86592 A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
86593 MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
86594 P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
86595 +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
86596 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
86597 vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
86598 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
86599 KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
86600 A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
86601 t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
86602 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
86603 er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
86604 -----END CERTIFICATE-----
86605
86606 GeoTrust Primary Certification Authority - G2
86607 =============================================
86608 -----BEGIN CERTIFICATE-----
86609 MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
86610 VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
86611 Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
86612 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
86613 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
86614 MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
86615 b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
86616 BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
86617 KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
86618 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
86619 EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
86620 ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
86621 npaqBA+K
86622 -----END CERTIFICATE-----
86623
86624 VeriSign Universal Root Certification Authority
86625 ===============================================
86626 -----BEGIN CERTIFICATE-----
86627 MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
86628 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
86629 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
86630 IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
86631 IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
86632 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
86633 cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
86634 IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
86635 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
86636 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
86637 MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
86638 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
86639 AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
86640 tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
86641 CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
86642 a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
86643 DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
86644 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
86645 Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
86646 P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
86647 wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
86648 mJO37M2CYfE45k+XmCpajQ==
86649 -----END CERTIFICATE-----
86650
86651 VeriSign Class 3 Public Primary Certification Authority - G4
86652 ============================================================
86653 -----BEGIN CERTIFICATE-----
86654 MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
86655 VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
86656 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
86657 ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
86658 YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
86659 MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
86660 cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
86661 b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
86662 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
86663 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
86664 rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
86665 /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
86666 HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
86667 Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
86668 A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
86669 AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
86670 -----END CERTIFICATE-----
86671
86672 NetLock Arany (Class Gold) Főtanúsítvány
86673 ========================================
86674 -----BEGIN CERTIFICATE-----
86675 MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
86676 A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
86677 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
86678 cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
86679 MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
86680 ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
86681 biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
86682 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
86683 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
86684 /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
86685 H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
86686 fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
86687 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
86688 BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
86689 qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
86690 YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
86691 bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
86692 NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
86693 dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
86694 -----END CERTIFICATE-----
86695
86696 Staat der Nederlanden Root CA - G2
86697 ==================================
86698 -----BEGIN CERTIFICATE-----
86699 MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
86700 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
86701 Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
86702 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
86703 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
86704 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
86705 vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
86706 CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
86707 e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
86708 OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
86709 CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
86710 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
86711 trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
86712 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
86713 AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
86714 ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
86715 HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
86716 A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
86717 +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
86718 f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
86719 kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
86720 CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
86721 URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
86722 CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
86723 oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
86724 IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
86725 66+KAQ==
86726 -----END CERTIFICATE-----
86727
86728 Hongkong Post Root CA 1
86729 =======================
86730 -----BEGIN CERTIFICATE-----
86731 MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
86732 DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
86733 NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
86734 IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
86735 AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
86736 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
86737 auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
86738 qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
86739 V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
86740 HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
86741 h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
86742 l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
86743 IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
86744 T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
86745 c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
86746 -----END CERTIFICATE-----
86747
86748 SecureSign RootCA11
86749 ===================
86750 -----BEGIN CERTIFICATE-----
86751 MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
86752 SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
86753 b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
86754 KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
86755 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
86756 TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
86757 wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
86758 g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
86759 O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
86760 bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
86761 t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
86762 OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
86763 bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
86764 Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
86765 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
86766 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
86767 -----END CERTIFICATE-----
86768
86769 Microsec e-Szigno Root CA 2009
86770 ==============================
86771 -----BEGIN CERTIFICATE-----
86772 MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
86773 MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
86774 c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
86775 dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
86776 BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
86777 U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
86778 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
86779 fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
86780 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
86781 pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
86782 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
86783 AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
86784 QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
86785 FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
86786 lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
86787 I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
86788 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
86789 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
86790 LXpUq3DDfSJlgnCW
86791 -----END CERTIFICATE-----
86792
86793 GlobalSign Root CA - R3
86794 =======================
86795 -----BEGIN CERTIFICATE-----
86796 MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
86797 YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
86798 bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
86799 aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
86800 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
86801 iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
86802 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
86803 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
86804 OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
86805 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
86806 FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
86807 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
86808 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
86809 bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
86810 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
86811 kpeDMdmztcpHWD9f
86812 -----END CERTIFICATE-----
86813
86814 Autoridad de Certificacion Firmaprofesional CIF A62634068
86815 =========================================================
86816 -----BEGIN CERTIFICATE-----
86817 MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
86818 BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
86819 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
86820 QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
86821 NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
86822 Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
86823 B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
86824 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
86825 ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
86826 plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
86827 MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
86828 LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
86829 bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
86830 vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
86831 EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
86832 DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
86833 cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
86834 bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
86835 ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
86836 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
86837 R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
86838 T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
86839 Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
86840 osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
86841 crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
86842 saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
86843 KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
86844 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
86845 -----END CERTIFICATE-----
86846
86847 Izenpe.com
86848 ==========
86849 -----BEGIN CERTIFICATE-----
86850 MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
86851 EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
86852 MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
86853 QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
86854 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
86855 ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
86856 +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
86857 PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
86858 OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
86859 F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
86860 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
86861 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
86862 leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
86863 AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
86864 SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
86865 NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
86866 MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
86867 BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
86868 Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
86869 kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
86870 hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
86871 g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
86872 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
86873 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
86874 ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
86875 Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
86876 WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
86877 -----END CERTIFICATE-----
86878
86879 Chambers of Commerce Root - 2008
86880 ================================
86881 -----BEGIN CERTIFICATE-----
86882 MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
86883 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
86884 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
86885 QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
86886 Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
86887 ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
86888 EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
86889 cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
86890 AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
86891 XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
86892 h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
86893 ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
86894 NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
86895 D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
86896 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
86897 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
86898 ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
86899 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
86900 G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
86901 BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
86902 bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
86903 bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
86904 CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
86905 AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
86906 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
86907 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
86908 RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
86909 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
86910 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
86911 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
86912 zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
86913 nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
86914 OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
86915 -----END CERTIFICATE-----
86916
86917 Global Chambersign Root - 2008
86918 ==============================
86919 -----BEGIN CERTIFICATE-----
86920 MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
86921 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
86922 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
86923 QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
86924 NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
86925 Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
86926 QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
86927 aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
86928 VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
86929 XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
86930 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
86931 /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
86932 TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
86933 H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
86934 Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
86935 HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
86936 wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
86937 AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
86938 BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
86939 BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
86940 aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
86941 aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
86942 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
86943 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
86944 /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
86945 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
86946 dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
86947 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
86948 foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
86949 qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
86950 P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
86951 c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
86952 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
86953 -----END CERTIFICATE-----
86954
86955 Go Daddy Root Certificate Authority - G2
86956 ========================================
86957 -----BEGIN CERTIFICATE-----
86958 MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
86959 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
86960 MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
86961 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
86962 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
86963 A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
86964 hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
86965 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
86966 +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
86967 fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
86968 NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
86969 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
86970 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
86971 vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
86972 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
86973 N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
86974 LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
86975 -----END CERTIFICATE-----
86976
86977 Starfield Root Certificate Authority - G2
86978 =========================================
86979 -----BEGIN CERTIFICATE-----
86980 MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
86981 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
86982 b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
86983 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
86984 DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
86985 VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
86986 dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
86987 W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
86988 bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
86989 N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
86990 ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
86991 JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
86992 AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
86993 TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
86994 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
86995 F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
86996 pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
86997 c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
86998 -----END CERTIFICATE-----
86999
87000 Starfield Services Root Certificate Authority - G2
87001 ==================================================
87002 -----BEGIN CERTIFICATE-----
87003 MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
87004 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
87005 b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
87006 IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
87007 BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
87008 dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
87009 Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
87010 AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
87011 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
87012 hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
87013 LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
87014 rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
87015 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
87016 SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
87017 E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
87018 xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
87019 iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
87020 YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
87021 -----END CERTIFICATE-----
87022
87023 AffirmTrust Commercial
87024 ======================
87025 -----BEGIN CERTIFICATE-----
87026 MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
87027 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
87028 MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
87029 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
87030 AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
87031 DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
87032 C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
87033 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
87034 MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
87035 HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
87036 AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
87037 hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
87038 qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
87039 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
87040 sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
87041 -----END CERTIFICATE-----
87042
87043 AffirmTrust Networking
87044 ======================
87045 -----BEGIN CERTIFICATE-----
87046 MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
87047 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
87048 MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
87049 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
87050 AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
87051 Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
87052 dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
87053 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
87054 h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
87055 HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
87056 AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
87057 UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
87058 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
87059 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
87060 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
87061 -----END CERTIFICATE-----
87062
87063 AffirmTrust Premium
87064 ===================
87065 -----BEGIN CERTIFICATE-----
87066 MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
87067 BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
87068 OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
87069 dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
87070 MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
87071 BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
87072 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
87073 +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
87074 GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
87075 p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
87076 S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
87077 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
87078 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
87079 +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
87080 /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
87081 MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
87082 Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
87083 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
87084 L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
87085 +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
87086 BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
87087 IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
87088 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
87089 zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
87090 -----END CERTIFICATE-----
87091
87092 AffirmTrust Premium ECC
87093 =======================
87094 -----BEGIN CERTIFICATE-----
87095 MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
87096 BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
87097 MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
87098 cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
87099 IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
87100 N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
87101 BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
87102 BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
87103 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
87104 eQ==
87105 -----END CERTIFICATE-----
87106
87107 Certum Trusted Network CA
87108 =========================
87109 -----BEGIN CERTIFICATE-----
87110 MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
87111 ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
87112 biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
87113 MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
87114 ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
87115 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
87116 AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
87117 l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
87118 J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
87119 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
87120 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
87121 Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
87122 DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
87123 jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
87124 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
87125 Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
87126 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
87127 -----END CERTIFICATE-----
87128
87129 TWCA Root Certification Authority
87130 =================================
87131 -----BEGIN CERTIFICATE-----
87132 MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
87133 VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
87134 dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
87135 EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
87136 IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
87137 AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
87138 QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
87139 oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
87140 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
87141 y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
87142 BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
87143 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
87144 mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
87145 QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
87146 T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
87147 Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
87148 -----END CERTIFICATE-----
87149
87150 Security Communication RootCA2
87151 ==============================
87152 -----BEGIN CERTIFICATE-----
87153 MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
87154 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
87155 dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
87156 SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
87157 aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
87158 ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
87159 +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
87160 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
87161 spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
87162 EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
87163 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
87164 CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
87165 u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
87166 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
87167 tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
87168 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
87169 -----END CERTIFICATE-----
87170
87171 EC-ACC
87172 ======
87173 -----BEGIN CERTIFICATE-----
87174 MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
87175 BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
87176 ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
87177 VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
87178 CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
87179 BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
87180 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
87181 SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
87182 Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
87183 cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
87184 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
87185 w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
87186 ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
87187 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
87188 E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
87189 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
87190 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
87191 VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
87192 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
87193 dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
87194 lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
87195 Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
87196 l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
87197 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
87198 5EI=
87199 -----END CERTIFICATE-----
87200
87201 Hellenic Academic and Research Institutions RootCA 2011
87202 =======================================================
87203 -----BEGIN CERTIFICATE-----
87204 MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
87205 O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
87206 aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
87207 IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
87208 AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
87209 IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
87210 IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
87211 AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
87212 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
87213 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
87214 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
87215 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
87216 MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
87217 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
87218 b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
87219 XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
87220 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
87221 /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
87222 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
87223 -----END CERTIFICATE-----
87224
87225 Actalis Authentication Root CA
87226 ==============================
87227 -----BEGIN CERTIFICATE-----
87228 MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
87229 BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
87230 AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
87231 MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
87232 IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
87233 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
87234 wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
87235 by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
87236 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
87237 YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
87238 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
87239 EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
87240 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
87241 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
87242 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
87243 iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
87244 ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
87245 WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
87246 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
87247 K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
87248 Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
87249 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
87250 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
87251 lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
87252 OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
87253 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
87254 -----END CERTIFICATE-----
87255
87256 Trustis FPS Root CA
87257 ===================
87258 -----BEGIN CERTIFICATE-----
87259 MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
87260 EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
87261 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
87262 BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
87263 KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
87264 RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
87265 H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
87266 cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
87267 o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
87268 AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
87269 BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
87270 GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
87271 yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
87272 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
87273 l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
87274 iB6XzCGcKQENZetX2fNXlrtIzYE=
87275 -----END CERTIFICATE-----
87276
87277 Buypass Class 2 Root CA
87278 =======================
87279 -----BEGIN CERTIFICATE-----
87280 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
87281 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
87282 DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
87283 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
87284 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
87285 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
87286 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
87287 /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
87288 CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
87289 awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
87290 zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
87291 Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
87292 Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
87293 M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
87294 VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
87295 AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
87296 A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
87297 osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
87298 aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
87299 DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
87300 LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
87301 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
87302 wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
87303 CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
87304 rJgWVqA=
87305 -----END CERTIFICATE-----
87306
87307 Buypass Class 3 Root CA
87308 =======================
87309 -----BEGIN CERTIFICATE-----
87310 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
87311 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
87312 DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
87313 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
87314 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
87315 sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
87316 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
87317 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
87318 ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
87319 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
87320 /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
87321 RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
87322 Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
87323 j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
87324 VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
87325 AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
87326 cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
87327 uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
87328 Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
87329 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
87330 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
87331 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
87332 UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
87333 eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
87334 Cp/HuZc=
87335 -----END CERTIFICATE-----
87336
87337 T-TeleSec GlobalRoot Class 3
87338 ============================
87339 -----BEGIN CERTIFICATE-----
87340 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
87341 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
87342 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
87343 MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
87344 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
87345 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
87346 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
87347 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
87348 NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
87349 iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
87350 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
87351 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
87352 AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
87353 fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
87354 ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
87355 P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
87356 e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
87357 -----END CERTIFICATE-----
87358
87359 EE Certification Centre Root CA
87360 ===============================
87361 -----BEGIN CERTIFICATE-----
87362 MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
87363 EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
87364 dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
87365 MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
87366 UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
87367 ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
87368 DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
87369 TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
87370 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
87371 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
87372 P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
87373 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
87374 MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
87375 BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
87376 xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
87377 lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
87378 uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
87379 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
87380 dcGWxZ0=
87381 -----END CERTIFICATE-----
87382
87383 D-TRUST Root Class 3 CA 2 2009
87384 ==============================
87385 -----BEGIN CERTIFICATE-----
87386 MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
87387 DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
87388 Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
87389 LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
87390 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
87391 ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
87392 BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
87393 KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
87394 p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
87395 AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
87396 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
87397 eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
87398 MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
87399 PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
87400 OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
87401 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
87402 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
87403 dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
87404 X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
87405 -----END CERTIFICATE-----
87406
87407 D-TRUST Root Class 3 CA 2 EV 2009
87408 =================================
87409 -----BEGIN CERTIFICATE-----
87410 MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
87411 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
87412 OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
87413 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
87414 OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
87415 egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
87416 zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
87417 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
87418 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
87419 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
87420 cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
87421 ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
87422 MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
87423 b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
87424 c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
87425 PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
87426 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
87427 ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
87428 NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
87429 w9y4AyHqnxbxLFS1
87430 -----END CERTIFICATE-----
87431
87432 CA Disig Root R2
87433 ================
87434 -----BEGIN CERTIFICATE-----
87435 MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
87436 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
87437 ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
87438 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
87439 c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
87440 w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
87441 xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
87442 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
87443 GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
87444 g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
87445 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
87446 koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
87447 Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
87448 Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
87449 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
87450 Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
87451 tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
87452 sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
87453 dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
87454 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
87455 mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
87456 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
87457 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
87458 UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
87459 7+ZtsH8tZ/3zbBt1RqPlShfppNcL
87460 -----END CERTIFICATE-----
87461
87462 ACCVRAIZ1
87463 =========
87464 -----BEGIN CERTIFICATE-----
87465 MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
87466 SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
87467 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
87468 UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
87469 DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
87470 jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
87471 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
87472 aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
87473 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
87474 WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
87475 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
87476 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
87477 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
87478 Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
87479 Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
87480 Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
87481 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
87482 Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
87483 QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
87484 AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
87485 YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
87486 AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
87487 IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
87488 aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
87489 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
87490 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
87491 hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
87492 R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
87493 YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
87494 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
87495 TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
87496 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
87497 I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
87498 Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
87499 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
87500 EfbRD0tVNEYqi4Y7
87501 -----END CERTIFICATE-----
87502
87503 TWCA Global Root CA
87504 ===================
87505 -----BEGIN CERTIFICATE-----
87506 MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
87507 CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
87508 QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
87509 EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
87510 Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
87511 nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
87512 r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
87513 Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
87514 tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
87515 KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
87516 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
87517 yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
87518 kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
87519 zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
87520 AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
87521 cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
87522 LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
87523 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
87524 /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
87525 lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
87526 A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
87527 i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
87528 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
87529 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
87530 -----END CERTIFICATE-----
87531
87532 TeliaSonera Root CA v1
87533 ======================
87534 -----BEGIN CERTIFICATE-----
87535 MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
87536 CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
87537 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
87538 VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
87539 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
87540 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
87541 B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
87542 Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
87543 oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
87544 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
87545 oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
87546 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
87547 TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
87548 AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
87549 DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
87550 zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
87551 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
87552 pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
87553 G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
87554 c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
87555 JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
87556 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
87557 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
87558 WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
87559 -----END CERTIFICATE-----
87560
87561 E-Tugra Certification Authority
87562 ===============================
87563 -----BEGIN CERTIFICATE-----
87564 MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
87565 DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
87566 ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
87567 ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
87568 NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
87569 QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
87570 cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
87571 DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
87572 MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
87573 hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
87574 CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
87575 ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
87576 BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
87577 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
87578 rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
87579 jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
87580 rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
87581 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
87582 /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
87583 MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
87584 kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
87585 XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
87586 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
87587 a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
87588 dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
87589 KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
87590 Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
87591 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
87592 C7TbO6Orb1wdtn7os4I07QZcJA==
87593 -----END CERTIFICATE-----
87594
87595 T-TeleSec GlobalRoot Class 2
87596 ============================
87597 -----BEGIN CERTIFICATE-----
87598 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
87599 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
87600 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
87601 MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
87602 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
87603 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
87604 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
87605 SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
87606 vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
87607 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
87608 WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
87609 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
87610 YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
87611 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
87612 vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
87613 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
87614 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
87615 -----END CERTIFICATE-----
87616
87617 Atos TrustedRoot 2011
87618 =====================
87619 -----BEGIN CERTIFICATE-----
87620 MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
87621 cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
87622 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
87623 A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
87624 hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
87625 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
87626 DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
87627 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
87628 z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
87629 l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
87630 bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
87631 CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
87632 k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
87633 TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
87634 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
87635 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
87636 -----END CERTIFICATE-----
87637
87638 QuoVadis Root CA 1 G3
87639 =====================
87640 -----BEGIN CERTIFICATE-----
87641 MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
87642 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
87643 b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
87644 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
87645 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
87646 PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
87647 PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
87648 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
87649 ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
87650 g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
87651 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
87652 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
87653 iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
87654 t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
87655 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
87656 hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
87657 MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
87658 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
87659 Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
87660 +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
87661 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
87662 wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
87663 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
87664 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
87665 hMJKzRwuJIczYOXD
87666 -----END CERTIFICATE-----
87667
87668 QuoVadis Root CA 2 G3
87669 =====================
87670 -----BEGIN CERTIFICATE-----
87671 MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
87672 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
87673 b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
87674 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
87675 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
87676 ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
87677 NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
87678 oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
87679 MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
87680 V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
87681 L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
87682 sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
87683 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
87684 lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
87685 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
87686 hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
87687 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
87688 pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
87689 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
87690 dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
87691 U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
87692 mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
87693 zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
87694 JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
87695 O3jtZsSOeWmD3n+M
87696 -----END CERTIFICATE-----
87697
87698 QuoVadis Root CA 3 G3
87699 =====================
87700 -----BEGIN CERTIFICATE-----
87701 MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
87702 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
87703 b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
87704 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
87705 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
87706 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
87707 Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
87708 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
87709 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
87710 VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
87711 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
87712 Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
87713 dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
87714 rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
87715 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
87716 hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
87717 KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
87718 t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
87719 TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
87720 DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
87721 Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
87722 hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
87723 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
87724 dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
87725 PpxxVJkES/1Y+Zj0
87726 -----END CERTIFICATE-----
87727
87728 DigiCert Assured ID Root G2
87729 ===========================
87730 -----BEGIN CERTIFICATE-----
87731 MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
87732 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
87733 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
87734 MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
87735 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
87736 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
87737 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
87738 bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
87739 VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
87740 YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
87741 lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
87742 w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
87743 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
87744 d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
87745 hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
87746 jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
87747 IhNzbM8m9Yop5w==
87748 -----END CERTIFICATE-----
87749
87750 DigiCert Assured ID Root G3
87751 ===========================
87752 -----BEGIN CERTIFICATE-----
87753 MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
87754 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
87755 VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
87756 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
87757 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
87758 BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
87759 RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
87760 KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
87761 UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
87762 YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
87763 1vUhZscv6pZjamVFkpUBtA==
87764 -----END CERTIFICATE-----
87765
87766 DigiCert Global Root G2
87767 =======================
87768 -----BEGIN CERTIFICATE-----
87769 MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
87770 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
87771 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
87772 MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
87773 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
87774 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
87775 kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
87776 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
87777 BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
87778 UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
87779 o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
87780 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
87781 F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
87782 WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
87783 QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
87784 iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
87785 MrY=
87786 -----END CERTIFICATE-----
87787
87788 DigiCert Global Root G3
87789 =======================
87790 -----BEGIN CERTIFICATE-----
87791 MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
87792 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
87793 VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
87794 MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
87795 aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
87796 AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
87797 YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
87798 BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
87799 Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
87800 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
87801 VOKa5Vt8sycX
87802 -----END CERTIFICATE-----
87803
87804 DigiCert Trusted Root G4
87805 ========================
87806 -----BEGIN CERTIFICATE-----
87807 MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
87808 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
87809 HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
87810 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
87811 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
87812 CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
87813 pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
87814 k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
87815 vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
87816 QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
87817 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
87818 mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
87819 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
87820 dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
87821 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
87822 DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
87823 ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
87824 ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
87825 yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
87826 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
87827 ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
87828 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
87829 /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
87830 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
87831 G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
87832 82Z+
87833 -----END CERTIFICATE-----
87834
87835 COMODO RSA Certification Authority
87836 ==================================
87837 -----BEGIN CERTIFICATE-----
87838 MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
87839 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
87840 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
87841 biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
87842 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
87843 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
87844 dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
87845 dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
87846 FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
87847 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
87848 x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
87849 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
87850 OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
87851 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
87852 GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
87853 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
87854 FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
87855 DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
87856 rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
87857 nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
87858 tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
87859 sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
87860 pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
87861 zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
87862 ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
87863 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
87864 LaZRfyHBNVOFBkpdn627G190
87865 -----END CERTIFICATE-----
87866
87867 USERTrust RSA Certification Authority
87868 =====================================
87869 -----BEGIN CERTIFICATE-----
87870 MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
87871 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
87872 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
87873 dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
87874 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
87875 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
87876 dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
87877 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
87878 Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
87879 RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
87880 +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
87881 /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
87882 Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
87883 lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
87884 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
87885 eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
87886 BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
87887 MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
87888 FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
87889 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
87890 Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
87891 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
87892 FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
87893 yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
87894 J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
87895 sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
87896 Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
87897 -----END CERTIFICATE-----
87898
87899 USERTrust ECC Certification Authority
87900 =====================================
87901 -----BEGIN CERTIFICATE-----
87902 MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
87903 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
87904 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
87905 biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
87906 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
87907 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
87908 biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
87909 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
87910 nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
87911 HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
87912 HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
87913 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
87914 -----END CERTIFICATE-----
87915
87916 GlobalSign ECC Root CA - R4
87917 ===========================
87918 -----BEGIN CERTIFICATE-----
87919 MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
87920 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
87921 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
87922 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
87923 EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
87924 OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
87925 AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
87926 MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
87927 JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
87928 -----END CERTIFICATE-----
87929
87930 GlobalSign ECC Root CA - R5
87931 ===========================
87932 -----BEGIN CERTIFICATE-----
87933 MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
87934 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
87935 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
87936 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
87937 EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
87938 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
87939 h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
87940 BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
87941 uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
87942 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
87943 -----END CERTIFICATE-----
87944
87945 Staat der Nederlanden Root CA - G3
87946 ==================================
87947 -----BEGIN CERTIFICATE-----
87948 MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
87949 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
87950 Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
87951 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
87952 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
87953 olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
87954 x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
87955 EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
87956 Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
87957 mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
87958 1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
87959 07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
87960 FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
87961 41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
87962 AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
87963 yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
87964 U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
87965 KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
87966 v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
87967 8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
87968 8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
87969 mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
87970 1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
87971 JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
87972 tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
87973 -----END CERTIFICATE-----
87974
87975 Staat der Nederlanden EV Root CA
87976 ================================
87977 -----BEGIN CERTIFICATE-----
87978 MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
87979 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
87980 RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
87981 MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
87982 cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
87983 SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
87984 O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
87985 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
87986 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
87987 XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
87988 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
87989 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
87990 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
87991 fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
87992 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
87993 ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
87994 eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
87995 c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
87996 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
87997 b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
87998 f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
87999 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
88000 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
88001 DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
88002 eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
88003 -----END CERTIFICATE-----
88004
88005 IdenTrust Commercial Root CA 1
88006 ==============================
88007 -----BEGIN CERTIFICATE-----
88008 MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
88009 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
88010 b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
88011 MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
88012 IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
88013 hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
88014 mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
88015 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
88016 XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
88017 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
88018 NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
88019 WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
88020 xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
88021 uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
88022 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
88023 hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
88024 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
88025 ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
88026 ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
88027 YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
88028 feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
88029 kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
88030 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
88031 Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
88032 cGzM7vRX+Bi6hG6H
88033 -----END CERTIFICATE-----
88034
88035 IdenTrust Public Sector Root CA 1
88036 =================================
88037 -----BEGIN CERTIFICATE-----
88038 MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
88039 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
88040 ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
88041 UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
88042 b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
88043 P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
88044 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
88045 rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
88046 qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
88047 mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
88048 ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
88049 LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
88050 iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
88051 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
88052 Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
88053 DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
88054 t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
88055 mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
88056 GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
88057 m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
88058 NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
88059 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
88060 ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
88061 ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
88062 3Wl9af0AVqW3rLatt8o+Ae+c
88063 -----END CERTIFICATE-----
88064
88065 Entrust Root Certification Authority - G2
88066 =========================================
88067 -----BEGIN CERTIFICATE-----
88068 MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
88069 BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
88070 bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
88071 b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
88072 HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
88073 DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
88074 OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
88075 eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
88076 MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
88077 /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
88078 HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
88079 s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
88080 TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
88081 AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
88082 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
88083 iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
88084 Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
88085 nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
88086 vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
88087 e4pIb4tF9g==
88088 -----END CERTIFICATE-----
88089
88090 Entrust Root Certification Authority - EC1
88091 ==========================================
88092 -----BEGIN CERTIFICATE-----
88093 MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
88094 FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
88095 YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
88096 ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
88097 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
88098 FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
88099 LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
88100 dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
88101 IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
88102 AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
88103 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
88104 FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
88105 vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
88106 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
88107 -----END CERTIFICATE-----
88108
88109 CFCA EV ROOT
88110 ============
88111 -----BEGIN CERTIFICATE-----
88112 MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
88113 CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
88114 IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
88115 MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
88116 DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
88117 BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
88118 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
88119 uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
88120 ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
88121 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
88122 py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
88123 gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
88124 hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
88125 tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
88126 BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
88127 /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
88128 ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
88129 ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
88130 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
88131 E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
88132 BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
88133 aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
88134 PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
88135 kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
88136 ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
88137 -----END CERTIFICATE-----
88138
88139 Certinomis - Root CA
88140 ====================
88141 -----BEGIN CERTIFICATE-----
88142 MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
88143 Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg
88144 LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx
88145 EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD
88146 ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos
88147 P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo
88148 d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap
88149 z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00
88150 8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x
88151 RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE
88152 6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t
88153 FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV
88154 PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH
88155 i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj
88156 YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I
88157 6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF
88158 AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV
88159 WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw
88160 Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX
88161 lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ
88162 y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9
88163 Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng
88164 DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi
88165 I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM
88166 cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr
88167 hkIGuUE=
88168 -----END CERTIFICATE-----
88169
88170 OISTE WISeKey Global Root GB CA
88171 ===============================
88172 -----BEGIN CERTIFICATE-----
88173 MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
88174 EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
88175 ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
88176 MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
88177 VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
88178 b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
88179 scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
88180 rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
88181 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
88182 Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
88183 GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
88184 /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
88185 hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
88186 dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
88187 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
88188 HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
88189 Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
88190 -----END CERTIFICATE-----
88191
88192 SZAFIR ROOT CA2
88193 ===============
88194 -----BEGIN CERTIFICATE-----
88195 MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
88196 A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
88197 BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
88198 BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
88199 VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
88200 qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
88201 DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
88202 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
88203 ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
88204 ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
88205 AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
88206 AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
88207 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
88208 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
88209 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
88210 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
88211 -----END CERTIFICATE-----
88212
88213 Certum Trusted Network CA 2
88214 ===========================
88215 -----BEGIN CERTIFICATE-----
88216 MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
88217 BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
88218 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
88219 ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
88220 TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
88221 cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
88222 IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
88223 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
88224 CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
88225 Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
88226 uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
88227 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
88228 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
88229 Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
88230 hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
88231 BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
88232 AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
88233 hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
88234 Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
88235 L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
88236 clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
88237 pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
88238 w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
88239 J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
88240 ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
88241 is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
88242 zAYspsbiDrW5viSP
88243 -----END CERTIFICATE-----
88244
88245 Hellenic Academic and Research Institutions RootCA 2015
88246 =======================================================
88247 -----BEGIN CERTIFICATE-----
88248 MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
88249 BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
88250 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
88251 YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
88252 MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
88253 QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
88254 BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
88255 MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
88256 bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
88257 iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
88258 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
88259 FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
88260 i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
88261 GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
88262 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
88263 iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
88264 Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
88265 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
88266 hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
88267 D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
88268 d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
88269 d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
88270 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
88271 davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
88272 Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
88273 J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
88274 JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
88275 p/UsQu0yrbYhnr68
88276 -----END CERTIFICATE-----
88277
88278 Hellenic Academic and Research Institutions ECC RootCA 2015
88279 ===========================================================
88280 -----BEGIN CERTIFICATE-----
88281 MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
88282 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
88283 cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
88284 aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
88285 MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
88286 IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
88287 VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
88288 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
88289 dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
88290 Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
88291 BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
88292 GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
88293 dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
88294 -----END CERTIFICATE-----
88295
88296 Certplus Root CA G1
88297 ===================
88298 -----BEGIN CERTIFICATE-----
88299 MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUAMD4xCzAJBgNV
88300 BAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTAe
88301 Fw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhD
88302 ZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQAD
88303 ggIPADCCAgoCggIBANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHN
88304 r49aiZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt6kuJPKNx
88305 Qv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP0FG7Yn2ksYyy/yARujVj
88306 BYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTv
88307 LRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDEEW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2
88308 z4QTd28n6v+WZxcIbekN1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc
88309 4nBvCGrch2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCTmehd
88310 4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV4EJQeIQEQWGw9CEj
88311 jy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPOWftwenMGE9nTdDckQQoRb5fc5+R+
88312 ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G
88313 A1UdDgQWBBSowcCbkahDFXxdBie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHY
88314 lwuBsTANBgkqhkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh
88315 66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7/SMNkPX0XtPG
88316 YX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BSS7CTKtQ+FjPlnsZlFT5kOwQ/
88317 2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F
88318 6ALEUz65noe8zDUa3qHpimOHZR4RKttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilX
88319 CNQ314cnrUlZp5GrRHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWe
88320 tUNy6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEVV/xuZDDC
88321 VRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5g4VCXA9DO2pJNdWY9BW/
88322 +mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl++O/QmueD6i9a5jc2NvLi6Td11n0bt3+
88323 qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo=
88324 -----END CERTIFICATE-----
88325
88326 Certplus Root CA G2
88327 ===================
88328 -----BEGIN CERTIFICATE-----
88329 MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4xCzAJBgNVBAYT
88330 AkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjAeFw0x
88331 NDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0
88332 cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IA
88333 BM0PW1aC3/BFGtat93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uN
88334 Am8xIk0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0PAQH/BAQD
88335 AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMB8GA1Ud
88336 IwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqGSM49BAMDA2gAMGUCMHD+sAvZ94OX7PNV
88337 HdTcswYO/jOYnYs5kGuUIe22113WTNchp+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjl
88338 vPl5adytRSv3tjFzzAalU5ORGpOucGpnutee5WEaXw==
88339 -----END CERTIFICATE-----
88340
88341 OpenTrust Root CA G1
88342 ====================
88343 -----BEGIN CERTIFICATE-----
88344 MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV
88345 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx
88346 MB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
88347 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEB
88348 AQUAA4ICDwAwggIKAoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7fa
88349 Yp6bwiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX/uMftk87
88350 ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR077F9jAHiOH3BX2pfJLKO
88351 YheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGPuY4zbGneWK2gDqdkVBFpRGZPTBKnjix9
88352 xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLxp2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO
88353 9z0M+Yo0FMT7MzUj8czxKselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq
88354 3ywgsNw2TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+WG+Oi
88355 n6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPwvFEVVJSmdz7QdFG9
88356 URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYYEQRVzXR7z2FwefR7LFxckvzluFqr
88357 TJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
88358 /zAdBgNVHQ4EFgQUl0YhVyE12jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/Px
88359 N3DlCPaTKbYwDQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E
88360 PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kfgLMtMrpkZ2Cv
88361 uVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbSFXJfLkur1J1juONI5f6ELlgK
88362 n0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLh
88363 X4SPgPL0DTatdrOjteFkdjpY3H1PXlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80
88364 nR14SohWZ25g/4/Ii+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcm
88365 GS3tTAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L9109S5zvE/
88366 bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/KyPu1svf0OnWZzsD2097+o
88367 4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJAwSQiumPv+i2tCqjI40cHLI5kqiPAlxA
88368 OXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj1oxx
88369 -----END CERTIFICATE-----
88370
88371 OpenTrust Root CA G2
88372 ====================
88373 -----BEGIN CERTIFICATE-----
88374 MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUAMEAxCzAJBgNV
88375 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcy
88376 MB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
88377 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEB
88378 AQUAA4ICDwAwggIKAoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+
88379 Ntmh/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78eCbY2albz
88380 4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/61UWY0jUJ9gNDlP7ZvyCV
88381 eYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fEFY8ElggGQgT4hNYdvJGmQr5J1WqIP7wt
88382 UdGejeBSzFfdNTVY27SPJIjki9/ca1TSgSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz
88383 3GIZ38i1MH/1PCZ1Eb3XG7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj
88384 3CzMpSZyYhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaHvGOz
88385 9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4t/bQWVyJ98LVtZR0
88386 0dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/gh7PU3+06yzbXfZqfUAkBXKJOAGT
88387 y3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
88388 /zAdBgNVHQ4EFgQUajn6QiL35okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59
88389 M4PLuG53hq8wDQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz
88390 Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0nXGEL8pZ0keI
88391 mUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qTRmTFAHneIWv2V6CG1wZy7HBG
88392 S4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpTwm+bREx50B1ws9efAvSyB7DH5fitIw6mVskp
88393 EndI2S9G/Tvw/HRwkqWOOAgfZDC2t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ
88394 6e18CL13zSdkzJTaTkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97kr
88395 gCf2o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU3jg9CcCo
88396 SmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eAiN1nE28daCSLT7d0geX0
88397 YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14fWKGVyasvc0rQLW6aWQ9VGHgtPFGml4vm
88398 u7JwqkwR3v98KzfUetF3NI/n+UL3PIEMS1IK
88399 -----END CERTIFICATE-----
88400
88401 OpenTrust Root CA G3
88402 ====================
88403 -----BEGIN CERTIFICATE-----
88404 MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAxCzAJBgNVBAYT
88405 AkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEczMB4X
88406 DTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9w
88407 ZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQA
88408 IgNiAARK7liuTcpm3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5B
88409 ta1doYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4GA1UdDwEB
88410 /wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAf
88411 BgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAKBggqhkjOPQQDAwNpADBmAjEAj6jcnboM
88412 BBf6Fek9LykBl7+BFjNAk2z8+e2AcG+qj9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta
88413 3U1fJAuwACEl74+nBCZx4nxp5V2a+EEfOzmTk51V6s2N8fvB
88414 -----END CERTIFICATE-----
88415
88416 ISRG Root X1
88417 ============
88418 -----BEGIN CERTIFICATE-----
88419 MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
88420 BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
88421 EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
88422 EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
88423 DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
88424 Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
88425 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
88426 b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
88427 Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
88428 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
88429 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
88430 hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
88431 usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
88432 OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
88433 A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
88434 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
88435 ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
88436 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
88437 hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
88438 TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
88439 e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
88440 JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
88441 YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
88442 JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
88443 m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
88444 -----END CERTIFICATE-----
88445
88446 AC RAIZ FNMT-RCM
88447 ================
88448 -----BEGIN CERTIFICATE-----
88449 MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
88450 AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
88451 MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
88452 TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
88453 ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
88454 qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
88455 btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
88456 j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
88457 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
88458 WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
88459 tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
88460 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
88461 ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
88462 i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
88463 FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
88464 dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
88465 nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
88466 D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
88467 j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
88468 Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
88469 +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
88470 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
88471 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
88472 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
88473 rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
88474 -----END CERTIFICATE-----
88475
88476 Amazon Root CA 1
88477 ================
88478 -----BEGIN CERTIFICATE-----
88479 MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
88480 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
88481 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
88482 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
88483 ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
88484 FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
88485 gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
88486 dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
88487 VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
88488 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
88489 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
88490 CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
88491 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
88492 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
88493 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
88494 -----END CERTIFICATE-----
88495
88496 Amazon Root CA 2
88497 ================
88498 -----BEGIN CERTIFICATE-----
88499 MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
88500 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
88501 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
88502 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
88503 ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
88504 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
88505 N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
88506 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
88507 fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
88508 kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
88509 btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
88510 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
88511 c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
88512 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
88513 DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
88514 A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
88515 +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
88516 YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
88517 xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
88518 gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
88519 aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
88520 Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
88521 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
88522 JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
88523 -----END CERTIFICATE-----
88524
88525 Amazon Root CA 3
88526 ================
88527 -----BEGIN CERTIFICATE-----
88528 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
88529 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
88530 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
88531 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
88532 f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
88533 Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
88534 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
88535 eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
88536 -----END CERTIFICATE-----
88537
88538 Amazon Root CA 4
88539 ================
88540 -----BEGIN CERTIFICATE-----
88541 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
88542 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
88543 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
88544 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
88545 /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
88546 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
88547 HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
88548 MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
88549 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
88550 -----END CERTIFICATE-----
88551
88552 LuxTrust Global Root 2
88553 ======================
88554 -----BEGIN CERTIFICATE-----
88555 MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG
88556 A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh
88557 bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW
88558 MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC
88559 AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm
88560 Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2
88561 xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC
88562 wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm
88563 1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm
88564 FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF
88565 wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/
88566 a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U
88567 ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ
88568 MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB
88569 /zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5
88570 Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
88571 +Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ
88572 FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN
88573 H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW
88574 7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu
88575 ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA
88576 VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR
88577 TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
88578 /f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc
88579 7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
88580 iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
88581 -----END CERTIFICATE-----
88582
88583 TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
88584 =============================================
88585 -----BEGIN CERTIFICATE-----
88586 MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
88587 D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
88588 IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
88589 TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
88590 ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
88591 VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
88592 c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
88593 bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
88594 IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
88595 MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
88596 6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
88597 wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
88598 3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
88599 WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
88600 ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
88601 KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
88602 AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
88603 lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
88604 e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
88605 q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
88606 -----END CERTIFICATE-----
88607
88608 GDCA TrustAUTH R5 ROOT
88609 ======================
88610 -----BEGIN CERTIFICATE-----
88611 MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw
88612 BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD
88613 DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow
88614 YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
88615 IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B
88616 AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs
88617 AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p
88618 OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr
88619 pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ
88620 9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ
88621 xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM
88622 R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ
88623 D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4
88624 oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx
88625 9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR
88626 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
88627 p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9
88628 H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35
88629 6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd
88630 +PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ
88631 HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD
88632 F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ
88633 8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv
88634 /EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT
88635 aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
88636 -----END CERTIFICATE-----
88637
88638 TrustCor RootCert CA-1
88639 ======================
88640 -----BEGIN CERTIFICATE-----
88641 MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP
88642 MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
88643 U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
88644 dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx
88645 MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu
88646 YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe
88647 VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy
88648 dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq
88649 jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4
88650 pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0
88651 JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h
88652 gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw
88653 /Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j
88654 BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
88655 AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5
88656 mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf
88657 ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C
88658 qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P
88659 3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk=
88660 -----END CERTIFICATE-----
88661
88662 TrustCor RootCert CA-2
88663 ======================
88664 -----BEGIN CERTIFICATE-----
88665 MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNVBAYTAlBBMQ8w
88666 DQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQwIgYDVQQKDBtUcnVzdENvciBT
88667 eXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0
88668 eTEfMB0GA1UEAwwWVHJ1c3RDb3IgUm9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEy
88669 MzExNzI2MzlaMIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5h
88670 bWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
88671 cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0
88672 IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnIG7CKqJiJJWQdsg4foDSq8Gb
88673 ZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9Nk
88674 RvRUqdw6VC0xK5mC8tkq1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1
88675 oYxOdqHp2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nKDOOb
88676 XUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hapeaz6LMvYHL1cEksr1
88677 /p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF3wP+TfSvPd9cW436cOGlfifHhi5q
88678 jxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQP
88679 eSghYA2FFn3XVDjxklb9tTNMg9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+Ctg
88680 rKAmrhQhJ8Z3mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh
88681 8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAdBgNVHQ4EFgQU
88682 2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6UnrybPZx9mCAZ5YwwYrIwDwYD
88683 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/h
88684 Osh80QA9z+LqBrWyOrsGS2h60COXdKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnp
88685 kpfbsEZC89NiqpX+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv
88686 2wnL/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RXCI/hOWB3
88687 S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYaZH9bDTMJBzN7Bj8RpFxw
88688 PIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dv
88689 DDqPys/cA8GiCcjl/YBeyGBCARsaU1q7N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYU
88690 RpFHmygk71dSTlxCnKr3Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANE
88691 xdqtvArBAs8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp5KeX
88692 RKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu1uwJ
88693 -----END CERTIFICATE-----
88694
88695 TrustCor ECA-1
88696 ==============
88697 -----BEGIN CERTIFICATE-----
88698 MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP
88699 MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
88700 U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
88701 dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw
88702 N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5
88703 MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y
88704 IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG
88705 SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR
88706 MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23
88707 xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc
88708 p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+
88709 fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj
88710 YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL
88711 f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
88712 AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u
88713 /ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F
88714 hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs
88715 J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC
88716 jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g==
88717 -----END CERTIFICATE-----
88718
88719 SSL.com Root Certification Authority RSA
88720 ========================================
88721 -----BEGIN CERTIFICATE-----
88722 MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM
88723 BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x
88724 MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw
88725 MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
88726 EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM
88727 LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD
88728 ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C
88729 Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8
88730 P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge
88731 oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp
88732 k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z
88733 fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ
88734 gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2
88735 UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8
88736 1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s
88737 bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
88738 HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE
88739 AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr
88740 dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf
88741 ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl
88742 u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq
88743 erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj
88744 MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ
88745 vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI
88746 Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y
88747 wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI
88748 WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k=
88749 -----END CERTIFICATE-----
88750
88751 SSL.com Root Certification Authority ECC
88752 ========================================
88753 -----BEGIN CERTIFICATE-----
88754 MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV
88755 BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv
88756 BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy
88757 MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO
88758 BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
88759 bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
88760 BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+
88761 8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR
88762 hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT
88763 jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW
88764 e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z
88765 5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
88766 -----END CERTIFICATE-----
88767
88768 SSL.com EV Root Certification Authority RSA R2
88769 ==============================================
88770 -----BEGIN CERTIFICATE-----
88771 MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w
88772 DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u
88773 MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
88774 MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI
88775 DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD
88776 VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN
88777 BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh
88778 hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w
88779 cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO
88780 Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+
88781 B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh
88782 CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim
88783 9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto
88784 RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm
88785 JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48
88786 +qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
88787 HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp
88788 qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1
88789 ++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx
88790 Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G
88791 guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz
88792 OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7
88793 CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq
88794 lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR
88795 rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1
88796 hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX
88797 9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
88798 -----END CERTIFICATE-----
88799
88800 SSL.com EV Root Certification Authority ECC
88801 ===========================================
88802 -----BEGIN CERTIFICATE-----
88803 MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV
88804 BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy
88805 BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw
88806 MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
88807 EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM
88808 LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
88809 BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy
88810 3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O
88811 BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe
88812 5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ
88813 N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm
88814 m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
88815 -----END CERTIFICATE-----
88816 <?php
88817
88818 if (PHP_SAPI !== 'cli') {
88819     echo 'Warning: Composer should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
88820 }
88821
88822 setlocale(LC_ALL, 'C');
88823 require __DIR__.'/../src/bootstrap.php';
88824
88825 use Composer\Console\Application;
88826 use Composer\XdebugHandler\XdebugHandler;
88827
88828 error_reporting(-1);
88829
88830 // Restart without xdebug
88831 $xdebug = new XdebugHandler('Composer', '--ansi');
88832 $xdebug->check();
88833 unset($xdebug);
88834
88835 if (function_exists('ini_set')) {
88836     @ini_set('display_errors', 1);
88837
88838     $memoryInBytes = function ($value) {
88839         $unit = strtolower(substr($value, -1, 1));
88840         $value = (int) $value;
88841         switch($unit) {
88842             case 'g':
88843                 $value *= 1024;
88844                 // no break (cumulative multiplier)
88845             case 'm':
88846                 $value *= 1024;
88847                 // no break (cumulative multiplier)
88848             case 'k':
88849                 $value *= 1024;
88850         }
88851
88852         return $value;
88853     };
88854
88855     $memoryLimit = trim(ini_get('memory_limit'));
88856     // Increase memory_limit if it is lower than 1.5GB
88857     if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
88858         @ini_set('memory_limit', '1536M');
88859     }
88860     // Set user defined memory limit
88861     if ($memoryLimit = getenv('COMPOSER_MEMORY_LIMIT')) {
88862         @ini_set('memory_limit', $memoryLimit);
88863     }
88864     unset($memoryInBytes, $memoryLimit);
88865 }
88866
88867 putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
88868
88869 // run the command application
88870 $application = new Application();
88871 $application->run();
88872
88873 Copyright (c) Nils Adermann, Jordi Boggiano
88874
88875 Permission is hereby granted, free of charge, to any person obtaining a copy
88876 of this software and associated documentation files (the "Software"), to deal
88877 in the Software without restriction, including without limitation the rights
88878 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
88879 copies of the Software, and to permit persons to whom the Software is furnished
88880 to do so, subject to the following conditions:
88881
88882 The above copyright notice and this permission notice shall be included in all
88883 copies or substantial portions of the Software.
88884
88885 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
88886 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
88887 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
88888 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
88889 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
88890 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
88891 THE SOFTWARE.
88892
88893 Qm/\f\1f\93¹øen¨\89i­Ï³Ñn*l\ 2\0\0\0GBMB