Pull merge.
[yaffs-website] / 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 ù\91\0\0ë\ 1\0\0\11\0\0\0\ 1\0\r\0\0\0composer.phar\0\0\0\0+\0\0\0src/Composer/Autoload/AutoloadGenerator.phpþa\0\0\92àqZþa\0\0tG\9d\94\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Autoload/ClassMapGenerator.php«\11\0\0\92àqZ«\11\0\0\10ëÊ\9a\ 1\0\0\0\0\0\0\16\0\0\0src/Composer/Cache.phpt\13\0\0\92àqZt\13\0\0\0\11&#¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Command/AboutCommand.phpË\ 2\0\0\92àqZË\ 2\0\0º¡Ãh¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/ArchiveCommand.phpL\14\0\0\92àqZL\14\0\0\85\r;V¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/BaseCommand.phpÉ        \0\0\92àqZÉ \0\0\97P!£¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Command/BaseDependencyCommand.phpÉ\18\0\0\92àqZÉ\18\0\0D{²Ð¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Command/CheckPlatformReqsCommand.php\82\f\0\0\92àqZ\82\f\0\0\a\88D\86\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/ClearCacheCommand.php]\ 5\0\0\92àqZ]\ 5\0\0\1f\82ß´¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/ConfigCommand.php\87H\0\0\92àqZ\87H\0\0Ä×\ 5Ö¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Command/CreateProjectCommand.php;6\0\0\92àqZ;6\0\0ü\80\ 4\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/DependsCommand.php·\ 2\0\0\92àqZ·\ 2\0\0o±¹ú¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/DiagnoseCommand.phpÕG\0\0\92àqZÕG\0\0ðõü\v\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Command/DumpAutoloadCommand.php\12
28 \0\0\92àqZ\12
29 \0\0'K¬\9e\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ExecCommand.phpi\a\0\0\92àqZi\a\0\0\ 4\80\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/GlobalCommand.phpü\a\0\0\92àqZü\a\0\0ÝH\8f\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/HomeCommand.phpÃ\ e\0\0\92àqZÃ\ e\0\0¯àyB¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/InitCommand.phpºJ\0\0\92àqZºJ\0\0"T¼\96\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/InstallCommand.phpý\13\0\0\92àqZý\13\0\00ö:\89\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/LicensesCommand.php&\ e\0\0\92àqZ&\ e\0\0Óv\83\1e\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/OutdatedCommand.php°
30 \0\0\92àqZ°
31 \0\07àzk¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/ProhibitsCommand.phpË\ 2\0\0\92àqZË\ 2\0\0\1ag\8fð¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/RemoveCommand.php\9b\15\0\0\92àqZ\9b\15\0\0>Sþ\98\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/RequireCommand.phpÖ \0\0\92àqZÖ \0\0B÷õE¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/RunScriptCommand.phpq\ e\0\0\92àqZq\ e\0\0p@­\86\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Command/ScriptAliasCommand.phpo\ 5\0\0\92àqZo\ 5\0\0\r5Þl¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/SearchCommand.phpã\b\0\0\92àqZã\b\0\0ñ\v¼w¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/SelfUpdateCommand.phpÈ2\0\0\92àqZÈ2\0\0+}\94\14\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ShowCommand.phpug\0\0\92àqZug\0\0ÀÕé\13\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/StatusCommand.php/\15\0\0\92àqZ/\15\0\0ôE\12\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/SuggestsCommand.php¨\r\0\0\92àqZ¨\r\0\0¼Ñ\ 5\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/UpdateCommand.php¯#\0\0\92àqZ¯#\0\0\97ú\8d\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/ValidateCommand.php#\14\0\0\92àqZ#\14\0\0\89\0\9d\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Composer.phpù  \0\0\92àqZù \0\0\86\83R\ f\ 1\0\0\0\0\0\0\17\0\0\0src/Composer/Config.phpÅ"\0\0\92àqZÅ"\0\0\9d¡¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Config/ConfigSourceInterface.php\ e\ 2\0\0\92àqZ\ e\ 2\0\0³\f[/¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Config/JsonConfigSource.php!\13\0\0\92àqZ!\13\0\0¾S\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Console/Application.php§3\0\0\92àqZ§3\0\0\89D;q¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Console/HtmlOutputFormatter.php3\ 6\0\0\92àqZ3\ 6\0\0Ú\81Eu¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/DependencyResolver/Decisions.phpQ\ f\0\0\92àqZQ\ f\0\0?\98¬$¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/DefaultPolicy.php\ 2\17\0\0\92àqZ\ 2\17\0\0õÝv\7f\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/GenericRule.php·\ 3\0\0\92àqZ·\ 3\0\0Ì~¯³¶\ 1\0\0\0\0\0\0>\0\0\0src/Composer/DependencyResolver/Operation/InstallOperation.phpC\ 2\0\0\92àqZC\ 2\0\0´\õ*¶\ 1\0\0\0\0\0\0I\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php÷\ 2\0\0\92àqZ÷\ 2\0\0ïÎà÷¶\ 1\0\0\0\0\0\0K\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpý\ 2\0\0\92àqZý\ 2\0\0\193#\86\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ\0\0\0\92àqZÓ\0\0\0Ùâ&ä¶\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/SolverOperation.php¹\ 1\0\0\92àqZ¹\ 1\0\0&¢e
32\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/UninstallOperation.phpI\ 2\0\0\92àqZI\ 2\0\0FûÂɶ\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/UpdateOperation.phph\ 3\0\0\92àqZh\ 3\0\0öSÕ]¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/PolicyInterface.php­\ 1\0\0\92àqZ­\ 1\0\0\18\9f\8b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Pool.php°"\0\0\92àqZ°"\0\0\1d   \8e\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Problem.php¥\18\0\0\92àqZ¥\18\0\0@\88<4¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Request.php\83\ 4\0\0\92àqZ\83\ 4\0\0åVP\84\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Rule.php¶\18\0\0\92àqZ¶\18\0\0Ú{\8d\8d\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/Rule2Literals.php§\ 4\0\0\92àqZ§\ 4\0\0~Ð'ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/RuleSet.phpª
33 \0\0\92àqZª
34 \0\0\82\e\ 1\0\0\0\0\0\04\0\0\0src/Composer/DependencyResolver/RuleSetGenerator.phpL\e\0\0\92àqZL\e\0\0¡³`\ 5\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/RuleSetIterator.php\11\ 6\0\0\92àqZ\11\ 6\0\0\9bCü$¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchChain.phpi\ 1\0\0\92àqZi\ 1\0\0\9a\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchGraph.phpá\ 6\0\0\92àqZá\ 6\0\0\89rôv¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/RuleWatchNode.phpé\ 3\0\0\92àqZé\ 3\0\0hØÑ´¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/DependencyResolver/Solver.php\9f8\0\0\92àqZ\9f8\0\0\1epöb¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/DependencyResolver/SolverBugException.php\98\ 1\0\0\92àqZ\98\ 1\0\0\7f"qN¶\ 1\0\0\0\0\0\0;\0\0\0src/Composer/DependencyResolver/SolverProblemsException.phpô\a\0\0\92àqZô\a\0\0×|Ŧ¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/Transaction.phpÙ\13\0\0\92àqZÙ\13\0\05ÖHÀ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Downloader/ArchiveDownloader.php³      \0\0\92àqZ³ \0\0ÖðÞ\9f\ 1\0\0\0\0\0\01\0\0\0src/Composer/Downloader/ChangeReportInterface.phpÌ\0\0\0\92àqZÌ\0\0\0¯à¨¿¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Downloader/DownloadManager.php`\15\0\0\92àqZ`\15\0\0\86ë\9d¾¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/DownloaderInterface.phpÊ\ 1\0\0\92àqZÊ\ 1\0\0gs!l¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Downloader/DvcsDownloaderInterface.phpÑ\0\0\0\92àqZÑ\0\0\0\9c¿¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/FileDownloader.php\8d\18\0\0\92àqZ\8d\18\0\01\82ã\14\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/FilesystemException.php
35 \ 1\0\0\92àqZ
36 \ 1\0\0.-\1e\8b\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Downloader/FossilDownloader.php`\v\0\0\92àqZ`\v\0\0ÿI©u¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/GitDownloader.php?4\0\0\92àqZ?4\0\0e\8d\17\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/GzipDownloader.phpó\ 6\0\0\92àqZó\ 6\0\0}Úo¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/HgDownloader.php8 \0\0\92àqZ8 \0\0ëyàn¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PathDownloader.phpK\11\0\0\92àqZK\11\0\09\95&c¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Downloader/PearPackageExtractor.phpu\e\0\0\92àqZu\e\0\0z\84\15\87\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/PerforceDownloader.php§\a\0\0\92àqZ§\a\0\0â\83\10¨¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PharDownloader.phpå\0\0\0\92àqZå\0\0\0ÞÉ\1fç¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/RarDownloader.php\9e\a\0\0\92àqZ\9e\a\0\06      3U¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/SvnDownloader.phpH\14\0\0\92àqZH\14\0\0\ 3ùÀF¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/TarDownloader.phpã\0\0\0\92àqZã\0\0\0Í\92X?¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/TransportException.php=\ 2\0\0\92àqZ=\ 2\0\0ZÎÈÞ¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Downloader/VcsCapableDownloaderInterface.phpÔ\0\0\0\92àqZÔ\0\0\0`§ôö¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/VcsDownloader.php"\16\0\0\92àqZ"\16\0\0\9c\1a\9f\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/XzDownloader.php§\ 4\0\0\92àqZ§\ 4\0\0W$;á¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/ZipDownloader.php\98\13\0\0\92àqZ\98\13\0\0\9b@\ 2ü¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/EventDispatcher/Event.php \ 2\0\0\92àqZ \ 2\0\0±\99jï¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/EventDispatcher/EventDispatcher.phpß0\0\0\92àqZß0\0\0}f\18\a\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/EventSubscriberInterface.php©\0\0\0\92àqZ©\0\0\0\ 1\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/ScriptExecutionException.phpv\0\0\0\92àqZv\0\0\0wZ8S¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Exception/NoSslException.phpf\0\0\0\92àqZf\0\0\0ËíM\9d\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Factory.phpU=\0\0\92àqZU=\0\0%êÿí¶\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/BaseIO.php\8c\10\0\0\92àqZ\8c\10\0\0(\82l\91\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/IO/BufferIO.php*\ 4\0\0\92àqZ*\ 4\0\0¢®hT¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/IO/ConsoleIO.php\87\16\0\0\92àqZ\87\16\0\0h\97tH¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/IO/IOInterface.phpì\ 5\0\0\92àqZì\ 5\0\0\0Õ\9d\ e\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/NullIO.phpÀ\ 4\0\0\92àqZÀ\ 4\0\0F`sʶ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/Installer.phpX\9c\0\0\92àqZX\9c\0\0éå*\1c\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/BinaryInstaller.phpÛ\11\0\0\92àqZÛ\11\0\0<x> ¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Installer/BinaryPresenceInterface.phpË\0\0\0\92àqZË\0\0\0À5\9a¨¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/InstallationManager.php-\17\0\0\92àqZ-\17\0\0¾}\8c\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Installer/InstallerEvent.php\ e\ 6\0\0\92àqZ\ e\ 6\0\0lÔzi¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/InstallerEvents.phpÞ\0\0\0\92àqZÞ\0\0\0ì\9f@G¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Installer/InstallerInterface.phpã\ 2\0\0\92àqZã\ 2\0\0^\83\93ʶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/LibraryInstaller.php^\13\0\0\92àqZ^\13\0\0\10\1aÍr¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Installer/MetapackageInstaller.php\9c\ 4\0\0\92àqZ\9c\ 4\0\0Æ\12Å!¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/NoopInstaller.php+\ 5\0\0\92àqZ+\ 5\0\0À·M}¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Installer/PackageEvent.phpe\ 3\0\0\92àqZe\ 3\0\0;° \1a\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PackageEvents.php¸\ 1\0\0\92àqZ¸\ 1\0\0dbØs¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/PearBinaryInstaller.phpâ\f\0\0\92àqZâ\f\0\0;øiU¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PearInstaller.php¢\a\0\0\92àqZ¢\a\0\0È\82¶Ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/PluginInstaller.php\9f\ 6\0\0\92àqZ\9f\ 6\0\0<tú,¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/ProjectInstaller.php\1d\ 6\0\0\92àqZ\1d\ 6\0\0*0@P¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Installer/SuggestedPackagesReporter.php\10\a\0\0\92àqZ\10\a\0\0+±]Ķ\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Json/JsonFile.phpï\13\0\0\92àqZï\13\0\0_(\18\v\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Json/JsonFormatter.php\ 6\ 6\0\0\92àqZ\ 6\ 6\0\0\1eÐqu¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Json/JsonManipulator.php°2\0\0\92àqZ°2\0\0\8eè\ 4ζ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Json/JsonValidationException.php\\ 1\0\0\92àqZ\\ 1\0\0.Xóܶ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Package/AliasPackage.php\ 5\17\0\0\92àqZ\ 5\17\0\0¹\97~\9a\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFilter.php       \ 2\0\0\92àqZ \ 2\0\0yY+¦¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFinder.phpÞ\ 5\0\0\92àqZÞ\ 5\0\0\f²²¹¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Archiver/ArchiveManager.php°\f\0\0\92àqZ°\f\0\0gþÒ)¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/ArchiverInterface.php\a\ 1\0\0\92àqZ\a\ 1\0\0ñ´>\v\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/BaseExcludeFilter.php\96\ 6\0\0\92àqZ\96\ 6\0\0y¶=ƶ\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ComposerExcludeFilter.php\1f\ 1\0\0\92àqZ\1f\ 1\0\0\8bSZ0¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Package/Archiver/GitExcludeFilter.phpq\ 3\0\0\92àqZq\ 3\0\05¾i&¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Archiver/HgExcludeFilter.php\v\ 5\0\0\92àqZ\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\92àqZ>\ 6\0\0 5\89í¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/Archiver/ZipArchiver.php¼\ 4\0\0\92àqZ¼\ 4\0\0\91XÝë¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/BasePackage.php&\r\0\0\92àqZ&\r\0\0\e'\1fݶ\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Package/CompletePackage.phpü\ 6\0\0\92àqZü\ 6\0\0þM˶¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/CompletePackageInterface.phpõ\ 1\0\0\92àqZõ\ 1\0\0¦Ê\81ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Dumper/ArrayDumper.phpë\v\0\0\92àqZë\v\0\0Ó8WE¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Package/Link.php\88\ 5\0\0\92àqZ\88\ 5\0\0å¶Y«¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/EmptyConstraint.php\82\ 1\0\0\92àqZ\82\ 1\0\0\ eé~\8b\ 1\0\0\0\0\0\0?\0\0\0src/Composer/Package/LinkConstraint/LinkConstraintInterface.phpd\ 1\0\0\92àqZd\ 1\0\0¤ôLn¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/MultiConstraint.php\82\ 1\0\0\92àqZ\82\ 1\0\0ób`ý¶\ 1\0\0\0\0\0\0:\0\0\0src/Composer/Package/LinkConstraint/SpecificConstraint.phpi\ 1\0\0\92àqZi\ 1\0\0Þ\94\9a\ 1\0\0\0\0\0\09\0\0\0src/Composer/Package/LinkConstraint/VersionConstraint.phpX\ 1\0\0\92àqZX\ 1\0\0\ 2}`y¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Loader/ArrayLoader.php\1f\1e\0\0\92àqZ\1f\1e\0\0n~\9c\9b\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Loader/InvalidPackageException.phpE\ 2\0\0\92àqZE\ 2\0\0xb\13¾¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Loader/JsonLoader.phpù\ 1\0\0\92àqZù\ 1\0\0!~\88\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Loader/LoaderInterface.php²\0\0\0\92àqZ²\0\0\0¦}úζ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Loader/RootPackageLoader.php$\17\0\0\92àqZ$\17\0\0Ârü°¶\ 1\0\0\0\0\0\05\0\0\0src/Composer/Package/Loader/ValidatingArrayLoader.phpT:\0\0\92àqZT:\0\0AôX϶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Package/Locker.php©!\0\0\92àqZ©!\0\0A\8aõë¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Package/Package.phpÉ\1a\0\0\92àqZÉ\1a\0\0\8f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/PackageInterface.php \a\0\0\92àqZ \a\0\0ûÇ^ƶ\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/RootAliasPackage.php\1f   \0\0\92àqZ\1f \0\0      _\80ø¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/RootPackage.php\11\ 5\0\0\92àqZ\11\ 5\0\0\ 2\8eÎ_¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/RootPackageInterface.php¹\ 3\0\0\92àqZ¹\ 3\0\0"maV¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Version/VersionGuesser.phpO\1e\0\0\92àqZO\1e\0\0\88S\9c\11\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Version/VersionParser.phpo\ 4\0\0\92àqZo\ 4\0\0m\1e\80\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Version/VersionSelector.phpK\f\0\0\92àqZK\f\0\0²<\ fȶ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Plugin/Capability/Capability.phpW\0\0\0\92àqZW\0\0\0æ_¨1¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Plugin/Capability/CommandProvider.php\97\0\0\0\92àqZ\97\0\0\0ûOâ>¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Plugin/Capable.php\7f\0\0\0\92àqZ\7f\0\0\0Æq\15\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/CommandEvent.phpâ\ 2\0\0\92àqZâ\ 2\0\0³ÆÇW¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/PluginEvents.phpÂ\0\0\0\92àqZÂ\0\0\0^Íþ\ 6\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Plugin/PluginInterface.phpô\0\0\0\92àqZô\0\0\0)'*ض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Plugin/PluginManager.php\1f$\0\0\92àqZ\1f$\0\0ë\8e"»¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Plugin/PreFileDownloadEvent.php`\ 2\0\0\92àqZ`\ 2\0\0\09-ζ\ 1\0\0\0\0\0\04\0\0\0src/Composer/Question/StrictConfirmationQuestion.php\1e\ 5\0\0\92àqZ\1e\ 5\0\0'.³è¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Repository/ArrayRepository.php\13\ e\0\0\92àqZ\13\ e\0\0éÌt\0\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ArtifactRepository.php»\f\0\0\92àqZ»\f\0\0\88Ý÷<¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/BaseRepository.php]\r\0\0\92àqZ]\r\0\0ä&3\87\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ComposerRepository.php\87T\0\0\92àqZ\87T\0\0Ç\93×{¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/CompositeRepository.php;\b\0\0\92àqZ;\b\0\0¤¯S\1f\ 1\0\0\0\0\0\0;\0\0\0src/Composer/Repository/ConfigurableRepositoryInterface.php\85\0\0\0\92àqZ\85\0\0\0±\9f_\1c\ 1\0\0\0\0\0\00\0\0\0src/Composer/Repository/FilesystemRepository.php$\ 5\0\0\92àqZ$\ 5\0\0¾Ãá\85\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/InstalledArrayRepository.php£\0\0\0\92àqZ£\0\0\0/ö~>¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Repository/InstalledFilesystemRepository.php£\0\0\0\92àqZ£\0\0\0V
37 \95\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/InstalledRepositoryInterface.php\87\0\0\0\92àqZ\87\0\0\0\18£9p¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/Repository/InvalidRepositoryException.phpn\0\0\0\92àqZn\0\0\0à\93ë\98\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/PackageRepository.phpj\ 3\0\0\92àqZj\ 3\0\0¥ôò̶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PathRepository.phpw
38 \0\0\92àqZw
39 \0\0\0~õ³¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Pear/BaseChannelReader.phpI\ 5\0\0\92àqZI\ 5\0\0c\b6³¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ChannelInfo.phpÄ\ 1\0\0\92àqZÄ\ 1\0\0:T*ɶ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Pear/ChannelReader.phpí\ 6\0\0\92àqZí\ 6\0\0?ÈYT¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest10Reader.php® \0\0\92àqZ® \0\0\99ÖÛú¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest11Reader.php& \0\0\92àqZ& \0\0òUb\b\ 1\0\0\0\0\0\05\0\0\0src/Composer/Repository/Pear/DependencyConstraint.phpq\ 2\0\0\92àqZq\ 2\0\09\ e\17\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Pear/DependencyInfo.phpq\ 1\0\0\92àqZq\ 1\0\0fºTò¶\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/Pear/PackageDependencyParser.php\85\16\0\0\92àqZ\85\16\0\0÷$Li¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/PackageInfo.php°\ 3\0\0\92àqZ°\ 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\92àqZ\92\ 1\0\0o\93\8aö\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PearRepository.phpª\16\0\0\92àqZª\16\0\0)\9f\83\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/PlatformRepository.php\ 2\e\0\0\92àqZ\ 2\e\0\0fVÉ¢¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryFactory.php2\12\0\0\92àqZ2\12\0\0\12t\ 4\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/RepositoryInterface.phpÛ\ 1\0\0\92àqZÛ\ 1\0\0\92\11âÁ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryManager.php,
40 \0\0\92àqZ,
41 \0\0¾\85\\95\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/RepositorySecurityException.phpo\0\0\0\92àqZo\0\0\0pÕ«ª¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Vcs/BitbucketDriver.phpô\1e\0\0\92àqZô\1e\0\0\ 4x¤ü¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/FossilDriver.php\9d\12\0\0\92àqZ\9d\12\0\0\ eÀ]µ¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/GitBitbucketDriver.phpê\ 5\0\0\92àqZê\ 5\0\0Ã\8e»\14\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/GitDriver.php¼\11\0\0\92àqZ¼\11\0\0\8a©Ðê¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitHubDriver.php¡+\0\0\92àqZ¡+\0\0ýYû
42\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitLabDriver.phpÍ#\0\0\92àqZÍ#\0\0ßNìʶ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/Vcs/HgBitbucketDriver.phpä\ 5\0\0\92àqZä\ 5\0\0i\9büà¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Repository/Vcs/HgDriver.phpe\12\0\0\92àqZe\12\0\0O!O\13\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Vcs/PerforceDriver.php'    \0\0\92àqZ' \0\0ÙóH\ 5\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/SvnDriver.php\15\e\0\0\92àqZ\15\e\0\0\1dÕzï¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/VcsDriver.phpæ
43 \0\0\92àqZæ
44 \0\0eׯ-¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/VcsDriverInterface.php÷\ 2\0\0\92àqZ÷\ 2\0\0ÇX[\89\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/VcsRepository.php´\1e\0\0\92àqZ´\1e\0\0\ 1ªÖG¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Repository/WritableArrayRepository.php\ f\ 3\0\0\92àqZ\ f\ 3\0\0¾G\17\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/WritableRepositoryInterface.php\89\ 1\0\0\92àqZ\89\ 1\0\0\91/sï¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/CommandEvent.phpW\0\0\0\92àqZW\0\0\0£VZt¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Script/Event.phpµ\ 2\0\0\92àqZµ\ 2\0\0lt¦M¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/PackageEvent.php\9c\0\0\0\92àqZ\9c\0\0\0§ÿÉ\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/ScriptEvents.phpP\ 4\0\0\92àqZP\ 4\0\0\87\8f\ 4¶¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/SelfUpdate/Keys.php\9d\ 1\0\0\92àqZ\9d\ 1\0\0\vîÊN¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/SelfUpdate/Versions.phpì\ 5\0\0\92àqZì\ 5\0\0͵\91\83\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/AuthHelper.phpË\ 3\0\0\92àqZË\ 3\0\0>zx\96\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/Bitbucket.php%\15\0\0\92àqZ%\15\0\0n=gÓ¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/ComposerMirror.php±\ 4\0\0\92àqZ±\ 4\0\0­½øض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ConfigValidator.php¥\ e\0\0\92àqZ¥\ e\0\0\9eê¶\ 1\0\0\0\0\0\0"\0\0\0src/Composer/Util/ErrorHandler.php\87\ 4\0\0\92àqZ\87\ 4\0\0He\1c\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/Filesystem.php3/\0\0\92àqZ3/\0\0m44ô¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Git.php!&\0\0\92àqZ!&\0\0lsý׶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitHub.phpÏ
45 \0\0\92àqZÏ
46 \0\0ÁØ\å¶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitLab.php\99\f\0\0\92àqZ\99\f\0\0\17BLF¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/IniHelper.php]\ 3\0\0\92àqZ]\ 3\0\0®äéä¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/NoProxyPattern.php¾\ 6\0\0\92àqZ¾\ 6\0\0Z+°m¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Perforce.php\821\0\0\92àqZ\821\0\0,\9cbx¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Platform.phpü\ 4\0\0\92àqZü\ 4\0\0s­fç¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ProcessExecutor.phpÚ\v\0\0\92àqZÚ\v\0\0£ÒÙ\ 5\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Util/RemoteFilesystem.phpýb\0\0\92àqZýb\0\0Mùjж\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Silencer.phpé\ 2\0\0\92àqZé\ 2\0\0\93Vjf¶\ 1\0\0\0\0\0\0!\0\0\0src/Composer/Util/SpdxLicense.php\ 3\ 1\0\0\92àqZ\ 3\ 1\0\0¾7
47 ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Util/StreamContextFactory.php\18\10\0\0\92àqZ\18\10\0\0ËH*v¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Svn.php\82\13\0\0\92àqZ\82\13\0\0 Vr¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/TlsHelper.phpp
48 \0\0\92àqZp
49 \0\0¤eÞæ¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Url.phpÀ\a\0\0\92àqZÀ\a\0\0lqh\17\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/XdebugHandler.php\93\ f\0\0\92àqZ\93\ f\0\0ÕWÖ>¶\ 1\0\0\0\0\0\0\11\0\0\0src/bootstrap.php¹\ 1\0\0\92àqZ¹\ 1\0\0\15I}\9c\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Autoload/ClassLoader.phpl4\0\0\92àqZl4\0\0\92ø[÷¶\ 1\0\0\0\0\0\0#\0\0\0res/composer-repository-schema.jsonð\ f\0\0\92àqZð\ f\0\0\81GÐà¶\ 1\0\0\0\0\0\0\18\0\0\0res/composer-schema.jsony\95\0\0\92àqZy\95\0\0³Ì¶`¶\ 1\0\0\0\0\0\06\0\0\0vendor/composer/spdx-licenses/res/spdx-exceptions.json}\a\0\0\92àqZ}\a\0\0\ 3/Y\9e\ 1\0\0\0\0\0\04\0\0\0vendor/composer/spdx-licenses/res/spdx-licenses.jsonà\8c\0\0\92àqZà\8c\0\0£\7f\1a\ 1\0\0\0\0\0\0*\0\0\0vendor/seld/cli-prompt/res/hiddeninput.exe\0$\0\0\92àqZ\0$\0\0\95\8d¥v¶\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Application.php#W\0\0\92àqZ#W\0\0\eèðz¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Command/Command.phpò"\0\0\92àqZò"\0\0ÊRÑç¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/HelpCommand.phpØ\a\0\0\92àqZØ\a\0\0$Y\1c«¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/ListCommand.phpZ\b\0\0\92àqZZ\b\0\0É£ \16\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/ConsoleEvents.phpé\0\0\0\92àqZé\0\0\0RÛÔe¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/console/Descriptor/ApplicationDescription.phpÐ\b\0\0\92àqZÐ\b\0\0\99\8e5°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Descriptor/Descriptor.php\8e\a\0\0\92àqZ\8e\a\0\0éð8\9f\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Descriptor/DescriptorInterface.phpü\0\0\0\92àqZü\0\0\0±Q\aµ¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/JsonDescriptor.phpá\r\0\0\92àqZá\r\0\0\87    àƶ\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Descriptor/MarkdownDescriptor.php¹\ e\0\0\92àqZ¹\ e\0\0k\9f.a¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/TextDescriptor.php²\1e\0\0\92àqZ²\1e\0\0\8f­ùâ¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Descriptor/XmlDescriptor.php\ 2\1c\0\0\92àqZ\ 2\1c\0\0
50 ]\85ζ\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Event/ConsoleCommandEvent.php°\ 1\0\0\92àqZ°\ 1\0\0\a!\0ȶ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Event/ConsoleEvent.phpÅ\ 2\0\0\92àqZÅ\ 2\0\0ÒxÛ\¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleExceptionEvent.php\12\ 3\0\0\92àqZ\12\ 3\0\0á\162é¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleTerminateEvent.phpz\ 2\0\0\92àqZz\ 2\0\0³,îL¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/CommandNotFoundException.phpÔ\ 1\0\0\92àqZÔ\ 1\0\0È÷ L¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Exception/ExceptionInterface.phpf\0\0\0\92àqZf\0\0\0¡ABª¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/InvalidArgumentException.php¦\0\0\0\92àqZ¦\0\0\0Ö̽Z¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/console/Exception/InvalidOptionException.php¦\0\0\0\92àqZ¦\0\0\0\13Ë×H¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Exception/LogicException.php\92\0\0\0\92àqZ\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\92àqZ\96\0\0\0Ùí,6¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Formatter/OutputFormatter.php2\ e\0\0\92àqZ2\ e\0\0RÌYh¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Formatter/OutputFormatterInterface.php\8c\ 1\0\0\92àqZ\8c\ 1\0\0òññÀ¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyle.phpJ\10\0\0\92àqZJ\10\0\0ÏDSȶ\ 1\0\0\0\0\0\0B\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php\84\ 1\0\0\92àqZ\84\ 1\0\0÷½\10\ 1\0\0\0\0\0\0>\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleStack.php>\ 5\0\0\92àqZ>\ 5\0\0[\86¿\96\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Helper/DebugFormatterHelper.phpx\b\0\0\92àqZx\b\0\0N©Ø¼¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/DescriptorHelper.phpw\ 5\0\0\92àqZw\ 5\0\0ÅHð.¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Helper/DialogHelper.phpú\1e\0\0\92àqZú\1e\0\0¼\fO\81\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/FormatterHelper.phpc\ 4\0\0\92àqZc\ 4\0\0\93ý«N¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Helper/Helper.php¨\a\0\0\92àqZ¨\a\0\0\9coû3¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/HelperInterface.phpå\0\0\0\92àqZå\0\0\0\1f\8a \18\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/HelperSet.phpÉ\a\0\0\92àqZÉ\a\0\0\9cf\15\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/InputAwareHelper.phpc\ 1\0\0\92àqZc\ 1\0\0ñø\90\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Helper/ProcessHelper.phpÑ     \0\0\92àqZÑ \0\0@±ã\81\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/ProgressBar.phpk%\0\0\92àqZk%\0\0ì\19îa¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/ProgressHelper.php\\e\0\0\92àqZ\\e\0\0\91ÃYÓ¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Helper/ProgressIndicator.phpK\14\0\0\92àqZK\14\0\0í\1cÍ°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/QuestionHelper.php  \1c\0\0\92àqZ \1c\0\0L\17ú4¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Helper/SymfonyQuestionHelper.phpl
51 \0\0\92àqZl
52 \0\0\1e÷ÞL¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/console/Helper/Table.php¨*\0\0\92àqZ¨*\0\0e{))¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/TableCell.php\80\ 3\0\0\92àqZ\80\ 3\0\0Ìî*Û¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/TableHelper.php\ e\f\0\0\92àqZ\ e\f\0\0QRº\1e\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/TableSeparator.phpÊ\0\0\0\92àqZÊ\0\0\0az\1f\1c\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Helper/TableStyle.php\1f
53 \0\0\92àqZ\1f
54 \0\0PÞµ¦¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Input/ArgvInput.php7\16\0\0\92àqZ7\16\0\0ØQ|ʶ\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Input/ArrayInput.php\14\v\0\0\92àqZ\14\v\0\0ʹóþ¶\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Input/Input.php¢\v\0\0\92àqZ¢\v\0\0\94\87B"¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Input/InputArgument.php\10\ 6\0\0\92àqZ\10\ 6\0\0&<¦¯¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Input/InputAwareInterface.php\9a\0\0\0\92àqZ\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\92àqZ\8a\19\0\0émáP¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Input/InputInterface.php\9d\ 3\0\0\92àqZ\9d\ 3\0\0®#£\10\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/InputOption.php\18\f\0\0\92àqZ\18\f\0\0ùýN4¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/StringInput.php\96\ 6\0\0\92àqZ\96\ 6\0\0cì\(¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/console/LICENSE)\ 4\0\0\92àqZ)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Logger/ConsoleLogger.php.    \0\0\92àqZ. \0\0¤\8c\85ζ\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Output/BufferedOutput.php_\ 1\0\0\92àqZ_\ 1\0\0\8b >P¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Output/ConsoleOutput.php°\a\0\0\92àqZ°\a\0\0]k~o¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Output/ConsoleOutputInterface.phpà\0\0\0\92àqZà\0\0\0\87\86Æʶ\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Output/NullOutput.phpÏ\ 3\0\0\92àqZÏ\ 3\0\0®\98\8b\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Output/Output.php\98  \0\0\92àqZ\98 \0\0\1fpf\¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Output/OutputInterface.php\17\ 3\0\0\92àqZ\17\ 3\0\0\0ì\ 6\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Output/StreamOutput.phpÂ\ 5\0\0\92àqZÂ\ 5\0\0\ 4¥<I¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Question/ChoiceQuestion.phpw
55 \0\0\92àqZw
56 \0\02\15t\ 6\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Question/ConfirmationQuestion.phpç\ 2\0\0\92àqZç\ 2\0\0\r­òf¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Question/Question.phpË     \0\0\92àqZË \0\0ÒqµR¶\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/console/Shell.phpå\ f\0\0\92àqZå\ f\0\0\95\9axS¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Style/OutputStyle.php\\ 5\0\0\92àqZ\\ 5\0\0wפ\ 4\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Style/StyleInterface.phpÏ\ 3\0\0\92àqZÏ\ 3\0\0&nÅѶ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Style/SymfonyStyle.php¶\1f\0\0\92àqZ¶\1f\0\0ª×\10ì¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Tester/ApplicationTester.phpÏ\ 5\0\0\92àqZÏ\ 5\0\0s\9e9i¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Tester/CommandTester.phpª\ 6\0\0\92àqZª\ 6\0\0µ.âr¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/debug/BufferingLogger.phpt\ 1\0\0\92àqZt\ 1\0\0=\0hܶ\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/debug/Debug.phpé\ 2\0\0\92àqZé\ 2\0\0Àxa?¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/DebugClassLoader.php¡\1d\0\0\92àqZ¡\1d\0\0ó\80v\87\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/debug/ErrorHandler.php\80C\0\0\92àqZ\80C\0\0¥æõ¾¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/debug/Exception/ClassNotFoundException.php\84\ 1\0\0\92àqZ\84\ 1\0\0n\90¡\85\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/debug/Exception/ContextErrorException.php\98\ 1\0\0\92àqZ\98\ 1\0\0-
57 d2¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/debug/Exception/DummyException.php\ 2\ 1\0\0\92àqZ\ 2\ 1\0\0-"ûd¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalErrorException.phpï\ 6\0\0\92àqZï\ 6\0\0æ\ffz¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalThrowableError.phpD\ 2\0\0\92àqZD\ 2\0\0¡\fÂí¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/debug/Exception/FlattenException.php²\16\0\0\92àqZ²\16\0\0HòÑ\ f\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/debug/Exception/OutOfMemoryException.php~\0\0\0\92àqZ~\0\0\0ë¨oâ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/debug/Exception/UndefinedFunctionException.php\88\ 1\0\0\92àqZ\88\ 1\0\0¢G\82\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/debug/Exception/UndefinedMethodException.php\86\ 1\0\0\92àqZ\86\ 1\0\0¨LÚ:¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/ExceptionHandler.php\193\0\0\92àqZ\193\0\0\8a\ 1\0\0\0\0\0\0I\0\0\0vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php7\12\0\0\92àqZ7\12\0\0Ñj/=¶\ 1\0\0\0\0\0\0E\0\0\0vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php\ 3\ 1\0\0\92àqZ\ 3\ 1\0\0ĹBV¶\ 1\0\0\0\0\0\0M\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.phpu\b\0\0\92àqZu\b\0\0éj\ 3\19\ 1\0\0\0\0\0\0K\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.phpN\ 5\0\0\92àqZN\ 5\0\0Ço-ç¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/symfony/debug/LICENSE)\ 4\0\0\92àqZ)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/filesystem/Exception/ExceptionInterface.phpi\0\0\0\92àqZi\0\0\0$ ÿ\9b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/filesystem/Exception/FileNotFoundException.php¼\ 1\0\0\92àqZ¼\ 1\0\0pí\¶¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/filesystem/Exception/IOException.php\87\ 1\0\0\92àqZ\87\ 1\0\0\80ü#Ѷ\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/filesystem/Exception/IOExceptionInterface.php¦\0\0\0\92àqZ¦\0\0\0jÙwM¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/filesystem/Filesystem.phpö2\0\0\92àqZö2\0\0ëP\81ò¶\ 1\0\0\0\0\0\0!\0\0\0vendor/symfony/filesystem/LICENSE)\ 4\0\0\92àqZ)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/filesystem/LockHandler.php¢\ 5\0\0\92àqZ¢\ 5\0\0D\91;i¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Adapter/AbstractAdapter.php\\v\0\0\92àqZ\\v\0\0Æ\93É\80\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Adapter/AbstractFindAdapter.php\8b\19\0\0\92àqZ\8b\19\0\0]vk1¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/finder/Adapter/AdapterInterface.php\9b\ 3\0\0\92àqZ\9b\ 3\0\0M\aþ\e\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/BsdFindAdapter.php2\a\0\0\92àqZ2\a\0\0Q/ÇC¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/GnuFindAdapter.php\15\a\0\0\92àqZ\15\a\0\0(\fí?¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/finder/Adapter/PhpAdapter.phpô\a\0\0\92àqZô\a\0\0\16\1d:?¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Comparator/Comparator.php\8c\ 3\0\0\92àqZ\8c\ 3\0\0\16wþT¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Comparator/DateComparator.php#\ 3\0\0\92àqZ#\ 3\0\0\16°\1fζ\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Comparator/NumberComparator.php|\ 3\0\0\92àqZ|\ 3\0\0ITÇͶ\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Exception/AccessDeniedException.php\84\0\0\0\92àqZ\84\0\0\0½¾s\9c\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Exception/AdapterFailureException.php¬\ 2\0\0\92àqZ¬\ 2\0\0\91\9e\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/finder/Exception/ExceptionInterface.php\84\0\0\0\92àqZ\84\0\0\0\1cGz-¶\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Exception/OperationNotPermitedException.php)\ 1\0\0\92àqZ)\ 1\0\0ìcj=¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/finder/Exception/ShellCommandFailureException.phpº\ 2\0\0\92àqZº\ 2\0\0\18Êø\1c\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Expression/Expression.php\a\ 6\0\0\92àqZ\a\ 6\0\0µoÔ\ 6\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/finder/Expression/Glob.phpf\ 4\0\0\92àqZf\ 4\0\0lïÜP¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/finder/Expression/Regex.php\ 4\ f\0\0\92àqZ\ 4\ f\0\0Qr\93¡¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Expression/ValueInterface.phpÍ\ 1\0\0\92àqZÍ\ 1\0\0²~øb¶\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/finder/Finder.php¹-\0\0\92àqZ¹-\0\0Q\1aÿ2¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/finder/Glob.phpK\ 5\0\0\92àqZK\ 5\0\0já±n¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/finder/Iterator/CustomFilterIterator.php[\ 2\0\0\92àqZ[\ 2\0\0­\ 4åW¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpx\ 2\0\0\92àqZx\ 2\0\0\ fô\ 3\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpî\ 1\0\0\92àqZî\ 1\0\0üÍ\9d\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.phpí\ 5\0\0\92àqZí\ 5\0\0n\ 5õH¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/finder/Iterator/FilePathsIterator.php \ 6\0\0\92àqZ \ 6\0\0fQCe¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FileTypeFilterIterator.phpZ\ 2\0\0\92àqZZ\ 2\0\0(\1a&ø¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/finder/Iterator/FilecontentFilterIterator.php5\ 2\0\0\92àqZ5\ 2\0\0\9aí\1f\14\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FilenameFilterIterator.phpr\ 1\0\0\92àqZr\ 1\0\0t\b\1a\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Iterator/FilterIterator.phpÃ\ 2\0\0\92àqZÃ\ 2\0\0\9a+µÞ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php-\ 5\0\0\92àqZ-\ 5\0\0ºÎÒ_¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Iterator/PathFilterIterator.phpÏ\ 1\0\0\92àqZÏ\ 1\0\0º\1cªÇ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php\13   \0\0\92àqZ\13 \0\0 \12ÿ¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpe\ 2\0\0\92àqZe\ 2\0\0\9f\92áé¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Iterator/SortableIterator.php*\ 6\0\0\92àqZ*\ 6\0\0\80õ´^¶\ 1\0\0\0\0\0\0\1d\0\0\0vendor/symfony/finder/LICENSE)\ 4\0\0\92àqZ)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/finder/Shell/Command.php?\v\0\0\92àqZ?\v\0\0\9aPw\89\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/Shell/Shell.phpp\ 4\0\0\92àqZp\ 4\0\0\18Ó}g¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/SplFileInfo.phpý\ 2\0\0\92àqZý\ 2\0\0\13`ØÓ¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/polyfill-mbstring/LICENSE)\ 4\0\0\92àqZ)\ 4\0\0î*L\14\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/polyfill-mbstring/Mbstring.phpÄ6\0\0\92àqZÄ6\0\0U.\17ݶ\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php2A\0\0\92àqZ2A\0\0½\11=¨¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php¡A\0\0\92àqZ¡A\0\0\ eÚ    Í¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/polyfill-mbstring/bootstrap.php±\ f\0\0\92àqZ±\ f\0\0|\8a©Ò¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/process/Exception/ExceptionInterface.phpf\0\0\0\92àqZf\0\0\0]ö>T¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/InvalidArgumentException.php¨\0\0\0\92àqZ¨\0\0\0ÐÀ+_¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/process/Exception/LogicException.php\94\0\0\0\92àqZ\94\0\0\0 ³ãñ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/process/Exception/ProcessFailedException.phpx\ 3\0\0\92àqZx\ 3\0\0¨Ìzy¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/ProcessTimedOutException.php\1f\ 4\0\0\92àqZ\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\92àqZ\98\0\0\0¢\eØ:¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/process/ExecutableFinder.php\99\ 4\0\0\92àqZ\99\ 4\0\0|O¿é¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/process/LICENSE)\ 4\0\0\92àqZ)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/PhpExecutableFinder.phpg\ 4\0\0\92àqZg\ 4\0\0\8dçµ\ 6\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/process/PhpProcess.phpú\ 3\0\0\92àqZú\ 3\0\0¯\93Õ\81\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/Pipes/AbstractPipes.php]\a\0\0\92àqZ]\a\0\0g\18\16\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/process/Pipes/PipesInterface.phpD\ 1\0\0\92àqZD\ 1\0\0vØ\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/process/Pipes/UnixPipes.phpâ\a\0\0\92àqZâ\a\0\0\7fß\10Ŷ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/process/Pipes/WindowsPipes.php\89\v\0\0\92àqZ\89\v\0\0\bÀ"¢¶\ 1\0\0\0\0\0\0"\0\0\0vendor/symfony/process/Process.php£R\0\0\92àqZ£R\0\0\8b\84&E¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/process/ProcessBuilder.phpß
58 \0\0\92àqZß
59 \0\0^\83\17\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/process/ProcessUtils.phpK\ 6\0\0\92àqZK\ 6\0\0µ½~ò¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/seld/jsonlint/LICENSE"\ 4\0\0\92àqZ"\ 4\0\0a\83sy¶\ 1\0\0\0\0\0\0@\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php*\ 1\0\0\92àqZ*\ 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\92àqZ/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\92àqZ\ 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\92àqZ\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\92àqZ>\0\0\0ÿq\9f\9f\ 1\0\0\0\0\0\0\1e\0\0\0vendor/seld/cli-prompt/LICENSE"\ 4\0\0\92àqZ"\ 4\0\0\88ñ?e¶\ 1\0\0\0\0\0\0&\0\0\0vendor/seld/cli-prompt/res/example.php'\ 1\0\0\92àqZ'\ 1\0\0I\1c\ 5£¶\ 1\0\0\0\0\0\0(\0\0\0vendor/seld/cli-prompt/src/CliPrompt.phpC\ 6\0\0\92àqZC\ 6\0\0Ð}\8d\ 1\0\0\0\0\0\0(\0\0\0vendor/justinrainbow/json-schema/LICENSE \ 4\0\0\92àqZ \ 4\0\0ºç\ 6©¶\ 1\0\0\0\0\0\0.\0\0\0vendor/justinrainbow/json-schema/demo/demo.phpñ\ 1\0\0\92àqZñ\ 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\92àqZ¡ \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\92àqZ)\r\0\0\14\14\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php\f\ e\0\0\92àqZ\f\ e\0\0Òé`\13\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php¼\ 1\0\0\92àqZ¼\ 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\92àqZ]\ 3\0\0V\8eU<¶\ 1\0\0\0\0\0\0G\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php;\r\0\0\92àqZ;\r\0\0!/)\18\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php\85\14\0\0\92àqZ\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
60 \0\0\92àqZ\9a
61 \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\92àqZÃ\11\0\0©Å¼x¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.phpN \0\0\92àqZN \0\0QÓmV¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php\7f\ 4\0\0\92àqZ\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\92àqZa\ 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\92àqZp\ 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\92àqZ\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\92àqZ&\ f\0\04\98©T¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.phpr!\0\0\92àqZr!\0\0\89Ö\91\b\ 1\0\0\0\0\0\0F\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.phpè\ 6\0\0\92àqZè\ 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\92àqZI\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\92àqZ\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\92àqZl\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\92àqZl\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\92àqZu\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\92àqZw\0\0\0N-ò[¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ\ 2\0\0\92àqZÞ\ 2\0\0\r
62\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpo\0\0\0\92àqZo\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\92àqZ\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\92àqZ\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\92àqZj\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\92àqZf\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\92àqZþ\ 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\92àqZ \ 2\0\0f4÷³¶\ 1\0\0\0\0\0\0A\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php\9c\r\0\0\92àqZ\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\92àqZ\ 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\92àqZá\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\92àqZ¥\ 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\92àqZ%\ 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\92àqZ,\ 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\92àqZ®\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\92àqZ\ 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\92àqZ&\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\92àqZ\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\92àqZ\85\0\0\0íæ\e\ 1\0\0\0\0\0\0=\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Validator.phpÇ\ 5\0\0\92àqZÇ\ 5\0\0ù\85oÞ¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/spdx-licenses/LICENSE\1c\ 4\0\0\92àqZ\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\02\0\0\0vendor/composer/spdx-licenses/src/SpdxLicenses.phpH\14\0\0\92àqZH\14\0\0Í\89T\ 4\ 1\0\0\0\0\0\0\1e\0\0\0vendor/composer/semver/LICENSE\1c\ 4\0\0\92àqZ\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\0)\0\0\0vendor/composer/semver/src/Comparator.php\ 2\ 4\0\0\92àqZ\ 2\ 4\0\0wl\83ï¶\ 1\0\0\0\0\0\0<\0\0\0vendor/composer/semver/src/Constraint/AbstractConstraint.php×\ 2\0\0\92àqZ×\ 2\0\0õî>\8e\ 1\0\0\0\0\0\04\0\0\0vendor/composer/semver/src/Constraint/Constraint.phpª\f\0\0\92àqZª\f\0\0ÇO7²¶\ 1\0\0\0\0\0\0=\0\0\0vendor/composer/semver/src/Constraint/ConstraintInterface.phpß\0\0\0\92àqZß\0\0\00C,\87\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/EmptyConstraint.phpé\ 1\0\0\92àqZé\ 1\0\0!-Ø\99\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/MultiConstraint.php1\ 5\0\0\92àqZ1\ 5\0\0í xU¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/semver/src/Semver.phpv\ 6\0\0\92àqZv\ 6\0\0\8b×È\9b\ 1\0\0\0\0\0\0,\0\0\0vendor/composer/semver/src/VersionParser.php¿*\0\0\92àqZ¿*\0\0\13)mƶ\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/ca-bundle/LICENSE\1c\ 4\0\0\92àqZ\1c\ 4\0\0*!^`¶\ 1\0\0\0\0\0\0*\0\0\0vendor/composer/ca-bundle/src/CaBundle.php\15\1d\0\0\92àqZ\15\1d\0\0Ê\v~Ķ\ 1\0\0\0\0\0\0\16\0\0\0vendor/psr/log/LICENSE=\ 4\0\0\92àqZ=\ 4\0\0\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/AbstractLogger.php;\ 4\0\0\92àqZ;\ 4\0\0ñ>3[¶\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/InvalidArgumentException.php`\0\0\0\92àqZ`\0\0\0 \88X1¶\ 1\0\0\0\0\0\0#\0\0\0vendor/psr/log/Psr/Log/LogLevel.phpû\0\0\0\92àqZû\0\0\0jðñ8¶\ 1\0\0\0\0\0\0/\0\0\0vendor/psr/log/Psr/Log/LoggerAwareInterface.php|\0\0\0\92àqZ|\0\0\0$\13£\88\ 1\0\0\0\0\0\0+\0\0\0vendor/psr/log/Psr/Log/LoggerAwareTrait.php§\0\0\0\92àqZ§\0\0\0T½úB¶\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/LoggerInterface.phpÆ\ 2\0\0\92àqZÆ\ 2\0\0»\12sg¶\ 1\0\0\0\0\0\0&\0\0\0vendor/psr/log/Psr/Log/LoggerTrait.phpi\ 4\0\0\92àqZi\ 4\0\035§Þ¶\ 1\0\0\0\0\0\0%\0\0\0vendor/psr/log/Psr/Log/NullLogger.php\9e\0\0\0\92àqZ\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\92àqZü\f\0\0iq0ض\ 1\0\0\0\0\0\0\13\0\0\0vendor/autoload.php\82\0\0\0\92àqZ\82\0\0\0£û}ä¶\ 1\0\0\0\0\0\0'\0\0\0vendor/composer/autoload_namespaces.phpd\0\0\0\92àqZd\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_psr4.php\98\ 4\0\0\92àqZ\98\ 4\0\0\9e\1c{¢¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/autoload_classmap.phpd\0\0\0\92àqZd\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0"\0\0\0vendor/composer/autoload_files.phpÃ\0\0\0\92àqZÃ\0\0\0ÒÂür¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_real.phpI\a\0\0\92àqZI\a\0\0çÝ\18\ 1\0\0\0\0\0\0#\0\0\0vendor/composer/autoload_static.php¬  \0\0\92àqZ¬ \0\0bU\93è¶\ 1\0\0\0\0\0\0\1f\0\0\0vendor/composer/ClassLoader.php\81\18\0\0\92àqZ\81\18\0\0\82Aãd¶\ 1\0\0\0\0\0\0(\0\0\0vendor/composer/ca-bundle/res/cacert.pem\1d\9a\ 3\0\92àqZ\1d\9a\ 3\0\1aÛ¾§¶\ 1\0\0\0\0\0\0\f\0\0\0bin/composer \ 6\0\0\92àqZ \ 6\0\0Ð\7f\9e\ 1\0\0\0\0\0\0\a\0\0\0LICENSE.\ 4\0\0\92àqZ.\ 4\0\0 Õ\b\ 3\ 1\0\0\0\0\0\0<?php
63
64
65
66
67
68
69
70
71
72
73
74 namespace Composer\Autoload;
75
76 use Composer\Config;
77 use Composer\EventDispatcher\EventDispatcher;
78 use Composer\Installer\InstallationManager;
79 use Composer\IO\IOInterface;
80 use Composer\Package\AliasPackage;
81 use Composer\Package\PackageInterface;
82 use Composer\Repository\InstalledRepositoryInterface;
83 use Composer\Util\Filesystem;
84 use Composer\Script\ScriptEvents;
85
86
87
88
89
90 class AutoloadGenerator
91 {
92
93
94
95 private $eventDispatcher;
96
97
98
99
100 private $io;
101
102
103
104
105 private $devMode = false;
106
107
108
109
110 private $classMapAuthoritative = false;
111
112
113
114
115 private $apcu = false;
116
117
118
119
120 private $runScripts = false;
121
122 public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
123 {
124 $this->eventDispatcher = $eventDispatcher;
125 $this->io = $io;
126 }
127
128 public function setDevMode($devMode = true)
129 {
130 $this->devMode = (bool) $devMode;
131 }
132
133
134
135
136
137
138
139 public function setClassMapAuthoritative($classMapAuthoritative)
140 {
141 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
142 }
143
144
145
146
147
148
149 public function setApcu($apcu)
150 {
151 $this->apcu = (bool) $apcu;
152 }
153
154
155
156
157
158
159 public function setRunScripts($runScripts = true)
160 {
161 $this->runScripts = (bool) $runScripts;
162 }
163
164 public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
165 {
166 if ($this->classMapAuthoritative) {
167
168  $scanPsr0Packages = true;
169 }
170 if ($this->runScripts) {
171 $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
172 'optimize' => (bool) $scanPsr0Packages,
173 ));
174 }
175
176 $filesystem = new Filesystem();
177 $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
178
179  
180  
181  $basePath = $filesystem->normalizePath(realpath(realpath(getcwd())));
182 $vendorPath = $filesystem->normalizePath(realpath(realpath($config->get('vendor-dir'))));
183 $useGlobalIncludePath = (bool) $config->get('use-include-path');
184 $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
185 $targetDir = $vendorPath.'/'.$targetDir;
186 $filesystem->ensureDirectoryExists($targetDir);
187
188 $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
189 $vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
190 $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
191
192 $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
193 $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
194
195 $namespacesFile = <<<EOF
196 <?php
197
198 // autoload_namespaces.php @generated by Composer
199
200 \$vendorDir = $vendorPathCode52;
201 \$baseDir = $appBaseDirCode;
202
203 return array(
204
205 EOF;
206
207 $psr4File = <<<EOF
208 <?php
209
210 // autoload_psr4.php @generated by Composer
211
212 \$vendorDir = $vendorPathCode52;
213 \$baseDir = $appBaseDirCode;
214
215 return array(
216
217 EOF;
218
219
220  $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
221 $autoloads = $this->parseAutoloads($packageMap, $mainPackage);
222
223
224  foreach ($autoloads['psr-0'] as $namespace => $paths) {
225 $exportedPaths = array();
226 foreach ($paths as $path) {
227 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
228 }
229 $exportedPrefix = var_export($namespace, true);
230 $namespacesFile .= "    $exportedPrefix => ";
231 $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
232 }
233 $namespacesFile .= ");\n";
234
235
236  foreach ($autoloads['psr-4'] as $namespace => $paths) {
237 $exportedPaths = array();
238 foreach ($paths as $path) {
239 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
240 }
241 $exportedPrefix = var_export($namespace, true);
242 $psr4File .= "    $exportedPrefix => ";
243 $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
244 }
245 $psr4File .= ");\n";
246
247 $classmapFile = <<<EOF
248 <?php
249
250 // autoload_classmap.php @generated by Composer
251
252 \$vendorDir = $vendorPathCode52;
253 \$baseDir = $appBaseDirCode;
254
255 return array(
256
257 EOF;
258
259
260  $targetDirLoader = null;
261 $mainAutoload = $mainPackage->getAutoload();
262 if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
263 $levels = substr_count($filesystem->normalizePath($mainPackage->getTargetDir()), '/') + 1;
264 $prefixes = implode(', ', array_map(function ($prefix) {
265 return var_export($prefix, true);
266 }, array_keys($mainAutoload['psr-0'])));
267 $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
268
269 $targetDirLoader = <<<EOF
270
271     public static function autoload(\$class)
272     {
273         \$dir = $baseDirFromTargetDirCode . '/';
274         \$prefixes = array($prefixes);
275         foreach (\$prefixes as \$prefix) {
276             if (0 !== strpos(\$class, \$prefix)) {
277                 continue;
278             }
279             \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), $levels)).'.php';
280             if (!\$path = stream_resolve_include_path(\$path)) {
281                 return false;
282             }
283             require \$path;
284
285             return true;
286         }
287     }
288
289 EOF;
290 }
291
292 $blacklist = null;
293 if (!empty($autoloads['exclude-from-classmap'])) {
294 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
295 }
296
297
298  $classMap = array();
299 if ($scanPsr0Packages) {
300 $namespacesToScan = array();
301
302
303  foreach (array('psr-0', 'psr-4') as $psrType) {
304 foreach ($autoloads[$psrType] as $namespace => $paths) {
305 $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
306 }
307 }
308
309 krsort($namespacesToScan);
310
311 foreach ($namespacesToScan as $namespace => $groups) {
312 foreach ($groups as $group) {
313 foreach ($group['paths'] as $dir) {
314 $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
315 if (!is_dir($dir)) {
316 continue;
317 }
318
319 $namespaceFilter = $namespace === '' ? null : $namespace;
320 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespaceFilter, $classMap);
321 }
322 }
323 }
324 }
325
326 foreach ($autoloads['classmap'] as $dir) {
327 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, $classMap);
328 }
329
330 ksort($classMap);
331 foreach ($classMap as $class => $code) {
332 $classmapFile .= '    '.var_export($class, true).' => '.$code;
333 }
334 $classmapFile .= ");\n";
335
336 if (!$suffix) {
337 if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
338 $content = file_get_contents($vendorPath.'/autoload.php');
339 if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
340 $suffix = $match[1];
341 }
342 }
343
344 if (!$suffix) {
345 $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true));
346 }
347 }
348
349 file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
350 file_put_contents($targetDir.'/autoload_psr4.php', $psr4File);
351 file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);
352 $includePathFilePath = $targetDir.'/include_paths.php';
353 if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
354 file_put_contents($includePathFilePath, $includePathFileContents);
355 } elseif (file_exists($includePathFilePath)) {
356 unlink($includePathFilePath);
357 }
358 $includeFilesFilePath = $targetDir.'/autoload_files.php';
359 if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
360 file_put_contents($includeFilesFilePath, $includeFilesFileContents);
361 } elseif (file_exists($includeFilesFilePath)) {
362 unlink($includeFilesFilePath);
363 }
364 file_put_contents($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
365 file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
366 file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
367
368 $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
369 $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
370
371 if ($this->runScripts) {
372 $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
373 'optimize' => (bool) $scanPsr0Packages,
374 ));
375 }
376 }
377
378 private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist = null, $namespaceFilter = null, array $classMap = array())
379 {
380 foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter) as $class => $path) {
381 $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
382 if (!isset($classMap[$class])) {
383 $classMap[$class] = $pathCode;
384 } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
385 $this->io->writeError(
386 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
387 ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
388 );
389 }
390 }
391
392 return $classMap;
393 }
394
395 private function generateClassMap($dir, $blacklist = null, $namespaceFilter = null, $showAmbiguousWarning = true)
396 {
397 return ClassMapGenerator::createMap($dir, $blacklist, $showAmbiguousWarning ? $this->io : null, $namespaceFilter);
398 }
399
400 public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
401 {
402
403  $packageMap = array(array($mainPackage, ''));
404
405 foreach ($packages as $package) {
406 if ($package instanceof AliasPackage) {
407 continue;
408 }
409 $this->validatePackage($package);
410
411 $packageMap[] = array(
412 $package,
413 $installationManager->getInstallPath($package),
414 );
415 }
416
417 return $packageMap;
418 }
419
420
421
422
423
424
425 protected function validatePackage(PackageInterface $package)
426 {
427 $autoload = $package->getAutoload();
428 if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
429 $name = $package->getName();
430 $package->getTargetDir();
431 throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '$name'.");
432 }
433 if (!empty($autoload['psr-4'])) {
434 foreach ($autoload['psr-4'] as $namespace => $dirs) {
435 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
436 throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '$namespace' does not, use '$namespace\\'.");
437 }
438 }
439 }
440 }
441
442
443
444
445
446
447
448
449 public function parseAutoloads(array $packageMap, PackageInterface $mainPackage)
450 {
451 $mainPackageMap = array_shift($packageMap);
452 $sortedPackageMap = $this->sortPackageMap($packageMap);
453 $sortedPackageMap[] = $mainPackageMap;
454 array_unshift($packageMap, $mainPackageMap);
455
456 $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
457 $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
458 $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
459 $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
460 $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
461
462 krsort($psr0);
463 krsort($psr4);
464
465 return array(
466 'psr-0' => $psr0,
467 'psr-4' => $psr4,
468 'classmap' => $classmap,
469 'files' => $files,
470 'exclude-from-classmap' => $exclude,
471 );
472 }
473
474
475
476
477
478
479
480 public function createLoader(array $autoloads)
481 {
482 $loader = new ClassLoader();
483
484 if (isset($autoloads['psr-0'])) {
485 foreach ($autoloads['psr-0'] as $namespace => $path) {
486 $loader->add($namespace, $path);
487 }
488 }
489
490 if (isset($autoloads['psr-4'])) {
491 foreach ($autoloads['psr-4'] as $namespace => $path) {
492 $loader->addPsr4($namespace, $path);
493 }
494 }
495
496 if (isset($autoloads['classmap'])) {
497 $blacklist = null;
498 if (!empty($autoloads['exclude-from-classmap'])) {
499 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
500 }
501
502 foreach ($autoloads['classmap'] as $dir) {
503 try {
504 $loader->addClassMap($this->generateClassMap($dir, $blacklist, null, false));
505 } catch (\RuntimeException $e) {
506 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
507 }
508 }
509 }
510
511 return $loader;
512 }
513
514 protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
515 {
516 $includePaths = array();
517
518 foreach ($packageMap as $item) {
519 list($package, $installPath) = $item;
520
521 if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
522 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
523 }
524
525 foreach ($package->getIncludePaths() as $includePath) {
526 $includePath = trim($includePath, '/');
527 $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
528 }
529 }
530
531 if (!$includePaths) {
532 return;
533 }
534
535 $includePathsCode = '';
536 foreach ($includePaths as $path) {
537 $includePathsCode .= "    " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
538 }
539
540 return <<<EOF
541 <?php
542
543 // include_paths.php @generated by Composer
544
545 \$vendorDir = $vendorPathCode;
546 \$baseDir = $appBaseDirCode;
547
548 return array(
549 $includePathsCode);
550
551 EOF;
552 }
553
554 protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
555 {
556 $filesCode = '';
557 foreach ($files as $fileIdentifier => $functionFile) {
558 $filesCode .= '    ' . var_export($fileIdentifier, true) . ' => '
559 . $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile) . ",\n";
560 }
561
562 if (!$filesCode) {
563 return false;
564 }
565
566 return <<<EOF
567 <?php
568
569 // autoload_files.php @generated by Composer
570
571 \$vendorDir = $vendorPathCode;
572 \$baseDir = $appBaseDirCode;
573
574 return array(
575 $filesCode);
576
577 EOF;
578 }
579
580 protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $path)
581 {
582 if (!$filesystem->isAbsolutePath($path)) {
583 $path = $basePath . '/' . $path;
584 }
585 $path = $filesystem->normalizePath($path);
586
587 $baseDir = '';
588 if (strpos($path.'/', $vendorPath.'/') === 0) {
589 $path = substr($path, strlen($vendorPath));
590 $baseDir = '$vendorDir';
591
592 if ($path !== false) {
593 $baseDir .= " . ";
594 }
595 } else {
596 $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, true));
597 if (!$filesystem->isAbsolutePath($path)) {
598 $baseDir = '$baseDir . ';
599 $path = '/' . $path;
600 }
601 }
602
603 if (preg_match('/\.phar.+$/', $path)) {
604 $baseDir = "'phar://' . " . $baseDir;
605 }
606
607 return $baseDir . (($path !== false) ? var_export($path, true) : "");
608 }
609
610 protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix)
611 {
612 $lastChar = $vendorPathToTargetDirCode[strlen($vendorPathToTargetDirCode) - 1];
613 if ("'" === $lastChar || '"' === $lastChar) {
614 $vendorPathToTargetDirCode = substr($vendorPathToTargetDirCode, 0, -1).'/autoload_real.php'.$lastChar;
615 } else {
616 $vendorPathToTargetDirCode .= " . '/autoload_real.php'";
617 }
618
619 return <<<AUTOLOAD
620 <?php
621
622 // autoload.php @generated by Composer
623
624 require_once $vendorPathToTargetDirCode;
625
626 return ComposerAutoloaderInit$suffix::getLoader();
627
628 AUTOLOAD;
629 }
630
631 protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion = 70000)
632 {
633 $file = <<<HEADER
634 <?php
635
636 // autoload_real.php @generated by Composer
637
638 class ComposerAutoloaderInit$suffix
639 {
640     private static \$loader;
641
642     public static function loadClassLoader(\$class)
643     {
644         if ('Composer\\Autoload\\ClassLoader' === \$class) {
645             require __DIR__ . '/ClassLoader.php';
646         }
647     }
648
649     public static function getLoader()
650     {
651         if (null !== self::\$loader) {
652             return self::\$loader;
653         }
654
655         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader);
656         self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
657         spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
658
659
660 HEADER;
661
662 if ($useIncludePath) {
663 $file .= <<<'INCLUDE_PATH'
664         $includePaths = require __DIR__ . '/include_paths.php';
665         $includePaths[] = get_include_path();
666         set_include_path(implode(PATH_SEPARATOR, $includePaths));
667
668
669 INCLUDE_PATH;
670 }
671
672 $file .= <<<STATIC_INIT
673         \$useStaticLoader = PHP_VERSION_ID >= $staticPhpVersion && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
674         if (\$useStaticLoader) {
675             require_once __DIR__ . '/autoload_static.php';
676
677             call_user_func(\Composer\Autoload\ComposerStaticInit$suffix::getInitializer(\$loader));
678         } else {
679
680 STATIC_INIT;
681
682 if (!$this->classMapAuthoritative) {
683 $file .= <<<'PSR04'
684             $map = require __DIR__ . '/autoload_namespaces.php';
685             foreach ($map as $namespace => $path) {
686                 $loader->set($namespace, $path);
687             }
688
689             $map = require __DIR__ . '/autoload_psr4.php';
690             foreach ($map as $namespace => $path) {
691                 $loader->setPsr4($namespace, $path);
692             }
693
694
695 PSR04;
696 }
697
698 if ($useClassMap) {
699 $file .= <<<'CLASSMAP'
700             $classMap = require __DIR__ . '/autoload_classmap.php';
701             if ($classMap) {
702                 $loader->addClassMap($classMap);
703             }
704
705 CLASSMAP;
706 }
707
708 $file .= "        }\n\n";
709
710 if ($this->classMapAuthoritative) {
711 $file .= <<<'CLASSMAPAUTHORITATIVE'
712         $loader->setClassMapAuthoritative(true);
713
714 CLASSMAPAUTHORITATIVE;
715 }
716
717 if ($this->apcu) {
718 $apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
719 $file .= <<<APCU
720         \$loader->setApcuPrefix('$apcuPrefix');
721
722 APCU;
723 }
724
725 if ($useGlobalIncludePath) {
726 $file .= <<<'INCLUDEPATH'
727         $loader->setUseIncludePath(true);
728
729 INCLUDEPATH;
730 }
731
732 if ($targetDirLoader) {
733 $file .= <<<REGISTER_TARGET_DIR_AUTOLOAD
734         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true, true);
735
736
737 REGISTER_TARGET_DIR_AUTOLOAD;
738 }
739
740 $file .= <<<REGISTER_LOADER
741         \$loader->register($prependAutoloader);
742
743
744 REGISTER_LOADER;
745
746 if ($useIncludeFiles) {
747 $file .= <<<INCLUDE_FILES
748         if (\$useStaticLoader) {
749             \$includeFiles = Composer\Autoload\ComposerStaticInit$suffix::\$files;
750         } else {
751             \$includeFiles = require __DIR__ . '/autoload_files.php';
752         }
753         foreach (\$includeFiles as \$fileIdentifier => \$file) {
754             composerRequire$suffix(\$fileIdentifier, \$file);
755         }
756
757
758 INCLUDE_FILES;
759 }
760
761 $file .= <<<METHOD_FOOTER
762         return \$loader;
763     }
764
765 METHOD_FOOTER;
766
767 $file .= $targetDirLoader;
768
769 if ($useIncludeFiles) {
770 return $file . <<<FOOTER
771 }
772
773 function composerRequire$suffix(\$fileIdentifier, \$file)
774 {
775     if (empty(\$GLOBALS['__composer_autoload_files'][\$fileIdentifier])) {
776         require \$file;
777
778         \$GLOBALS['__composer_autoload_files'][\$fileIdentifier] = true;
779     }
780 }
781
782 FOOTER;
783 }
784
785 return $file . <<<FOOTER
786 }
787
788 FOOTER;
789 }
790
791 protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion)
792 {
793 $staticPhpVersion = 50600;
794
795 $file = <<<HEADER
796 <?php
797
798 // autoload_static.php @generated by Composer
799
800 namespace Composer\Autoload;
801
802 class ComposerStaticInit$suffix
803 {
804
805 HEADER;
806
807 $loader = new ClassLoader();
808
809 $map = require $targetDir . '/autoload_namespaces.php';
810 foreach ($map as $namespace => $path) {
811 $loader->set($namespace, $path);
812 }
813
814 $map = require $targetDir . '/autoload_psr4.php';
815 foreach ($map as $namespace => $path) {
816 $loader->setPsr4($namespace, $path);
817 }
818
819 $classMap = require $targetDir . '/autoload_classmap.php';
820 if ($classMap) {
821 $loader->addClassMap($classMap);
822 }
823
824 $filesystem = new Filesystem();
825
826 $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
827 $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
828
829 $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
830 $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
831
832 $initializer = '';
833 $prefix = "\0Composer\Autoload\ClassLoader\0";
834 $prefixLen = strlen($prefix);
835 if (file_exists($targetDir . '/autoload_files.php')) {
836 $maps = array('files' => require $targetDir . '/autoload_files.php');
837 } else {
838 $maps = array();
839 }
840
841 foreach ((array) $loader as $prop => $value) {
842 if ($value && 0 === strpos($prop, $prefix)) {
843 $maps[substr($prop, $prefixLen)] = $value;
844 }
845 }
846
847 foreach ($maps as $prop => $value) {
848 if (count($value) > 32767) {
849
850  
851  $staticPhpVersion = 70000;
852 }
853 $value = var_export($value, true);
854 $value = str_replace($absoluteVendorPathCode, $vendorPathCode, $value);
855 $value = str_replace($absoluteAppBaseDirCode, $appBaseDirCode, $value);
856 $value = ltrim(preg_replace('/^ */m', '    $0$0', $value));
857
858 $file .= sprintf("    public static $%s = %s;\n\n", $prop, $value);
859 if ('files' !== $prop) {
860 $initializer .= "            \$loader->$prop = ComposerStaticInit$suffix::\$$prop;\n";
861 }
862 }
863
864 return $file . <<<INITIALIZER
865     public static function getInitializer(ClassLoader \$loader)
866     {
867         return \Closure::bind(function () use (\$loader) {
868 $initializer
869         }, null, ClassLoader::class);
870     }
871 }
872
873 INITIALIZER;
874 }
875
876 protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
877 {
878 $autoloads = array();
879
880 foreach ($packageMap as $item) {
881 list($package, $installPath) = $item;
882
883 $autoload = $package->getAutoload();
884 if ($this->devMode && $package === $mainPackage) {
885 $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
886 }
887
888
889  if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
890 continue;
891 }
892 if (null !== $package->getTargetDir() && $package !== $mainPackage) {
893 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
894 }
895
896 foreach ($autoload[$type] as $namespace => $paths) {
897 foreach ((array) $paths as $path) {
898 if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
899
900  if ($package === $mainPackage) {
901 $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
902 $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
903 } else {
904
905  $path = $package->getTargetDir() . '/' . $path;
906 }
907 }
908
909 if ($type === 'exclude-from-classmap') {
910
911  $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
912
913
914  $path = str_replace('\\*\\*', '.+?', $path);
915 $path = str_replace('\\*', '[^/]+?', $path);
916
917
918  $updir = null;
919 $path = preg_replace_callback(
920 '{^((?:(?:\\\\\\.){1,2}+/)+)}',
921 function ($matches) use (&$updir) {
922 if (isset($matches[1])) {
923
924  $updir = str_replace('\\.', '.', $matches[1]);
925 }
926
927 return '';
928 },
929 $path
930 );
931 if (empty($installPath)) {
932 $installPath = strtr(getcwd(), '\\', '/');
933 }
934
935 $resolvedPath = realpath($installPath . '/' . $updir);
936 $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path;
937 continue;
938 }
939
940 $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
941
942 if ($type === 'files') {
943 $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
944 continue;
945 } elseif ($type === 'classmap') {
946 $autoloads[] = $relativePath;
947 continue;
948 }
949
950 $autoloads[$namespace][] = $relativePath;
951 }
952 }
953 }
954
955 return $autoloads;
956 }
957
958 protected function getFileIdentifier(PackageInterface $package, $path)
959 {
960 return md5($package->getName() . ':' . $path);
961 }
962
963
964
965
966
967
968
969
970
971 protected function sortPackageMap(array $packageMap)
972 {
973 $packages = array();
974 $paths = array();
975 $usageList = array();
976
977 foreach ($packageMap as $item) {
978 list($package, $path) = $item;
979 $name = $package->getName();
980 $packages[$name] = $package;
981 $paths[$name] = $path;
982
983 foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) {
984 $target = $link->getTarget();
985 $usageList[$target][] = $name;
986 }
987 }
988
989 $computing = array();
990 $computed = array();
991 $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
992
993  if (isset($computed[$name])) {
994 return $computed[$name];
995 }
996
997
998  if (isset($computing[$name])) {
999 return 0;
1000 }
1001
1002 $computing[$name] = true;
1003 $weight = 0;
1004
1005 if (isset($usageList[$name])) {
1006 foreach ($usageList[$name] as $user) {
1007 $weight -= 1 - $computeImportance($user);
1008 }
1009 }
1010
1011 unset($computing[$name]);
1012 $computed[$name] = $weight;
1013
1014 return $weight;
1015 };
1016
1017 $weightList = array();
1018
1019 foreach ($packages as $name => $package) {
1020 $weight = $computeImportance($name);
1021 $weightList[$name] = $weight;
1022 }
1023
1024 $stable_sort = function (&$array) {
1025 static $transform, $restore;
1026
1027 $i = 0;
1028
1029 if (!$transform) {
1030 $transform = function (&$v, $k) use (&$i) {
1031 $v = array($v, ++$i, $k, $v);
1032 };
1033
1034 $restore = function (&$v, $k) {
1035 $v = $v[3];
1036 };
1037 }
1038
1039 array_walk($array, $transform);
1040 asort($array);
1041 array_walk($array, $restore);
1042 };
1043
1044 $stable_sort($weightList);
1045
1046 $sortedPackageMap = array();
1047
1048 foreach (array_keys($weightList) as $name) {
1049 $sortedPackageMap[] = array($packages[$name], $paths[$name]);
1050 }
1051
1052 return $sortedPackageMap;
1053 }
1054
1055
1056
1057
1058
1059
1060
1061 protected function safeCopy($source, $target)
1062 {
1063 $source = fopen($source, 'r');
1064 $target = fopen($target, 'w+');
1065
1066 stream_copy_to_stream($source, $target);
1067 fclose($source);
1068 fclose($target);
1069 }
1070 }
1071 <?php
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089 namespace Composer\Autoload;
1090
1091 use Symfony\Component\Finder\Finder;
1092 use Composer\IO\IOInterface;
1093 use Composer\Util\Filesystem;
1094
1095
1096
1097
1098
1099
1100
1101 class ClassMapGenerator
1102 {
1103
1104
1105
1106
1107
1108
1109 public static function dump($dirs, $file)
1110 {
1111 $maps = array();
1112
1113 foreach ($dirs as $dir) {
1114 $maps = array_merge($maps, static::createMap($dir));
1115 }
1116
1117 file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
1118 }
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131 public static function createMap($path, $blacklist = null, IOInterface $io = null, $namespace = null)
1132 {
1133 if (is_string($path)) {
1134 if (is_file($path)) {
1135 $path = array(new \SplFileInfo($path));
1136 } elseif (is_dir($path)) {
1137 $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
1138 } else {
1139 throw new \RuntimeException(
1140 'Could not scan for classes inside "'.$path.
1141 '" which does not appear to be a file nor a folder'
1142 );
1143 }
1144 }
1145
1146 $map = array();
1147 $filesystem = new Filesystem();
1148 $cwd = realpath(getcwd());
1149
1150 foreach ($path as $file) {
1151 $filePath = $file->getPathname();
1152 if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
1153 continue;
1154 }
1155
1156 if (!$filesystem->isAbsolutePath($filePath)) {
1157 $filePath = $cwd . '/' . $filePath;
1158 $filePath = $filesystem->normalizePath($filePath);
1159 } else {
1160 $filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath);
1161 }
1162
1163
1164  if ($blacklist && preg_match($blacklist, strtr(realpath($filePath), '\\', '/'))) {
1165 continue;
1166 }
1167
1168 $classes = self::findClasses($filePath);
1169
1170 foreach ($classes as $class) {
1171
1172  if (null !== $namespace && 0 !== strpos($class, $namespace)) {
1173 continue;
1174 }
1175
1176 if (!isset($map[$class])) {
1177 $map[$class] = $filePath;
1178 } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
1179 $io->writeError(
1180 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
1181 ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
1182 );
1183 }
1184 }
1185 }
1186
1187 return $map;
1188 }
1189
1190
1191
1192
1193
1194
1195
1196
1197 private static function findClasses($path)
1198 {
1199 $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
1200 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
1201 $extraTypes .= '|enum';
1202 }
1203
1204
1205  
1206  $contents = @php_strip_whitespace($path);
1207 if (!$contents) {
1208 if (!file_exists($path)) {
1209 $message = 'File at "%s" does not exist, check your classmap definitions';
1210 } elseif (!is_readable($path)) {
1211 $message = 'File at "%s" is not readable, check its permissions';
1212 } elseif ('' === trim(file_get_contents($path))) {
1213
1214  return array();
1215 } else {
1216 $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
1217 }
1218 $error = error_get_last();
1219 if (isset($error['message'])) {
1220 $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
1221 }
1222 throw new \RuntimeException(sprintf($message, $path));
1223 }
1224
1225
1226  if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
1227 return array();
1228 }
1229
1230
1231  $contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents);
1232
1233  $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
1234
1235  if (substr($contents, 0, 2) !== '<?') {
1236 $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
1237 if ($replacements === 0) {
1238 return array();
1239 }
1240 }
1241
1242  $contents = preg_replace('{\?>.+<\?}s', '?><?', $contents);
1243
1244  $pos = strrpos($contents, '?>');
1245 if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
1246 $contents = substr($contents, 0, $pos);
1247 }
1248
1249 preg_match_all('{
1250             (?:
1251                  \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
1252                | \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*+ [\{;]
1253             )
1254         }ix', $contents, $matches);
1255
1256 $classes = array();
1257 $namespace = '';
1258
1259 for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
1260 if (!empty($matches['ns'][$i])) {
1261 $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
1262 } else {
1263 $name = $matches['name'][$i];
1264
1265  if ($name === 'extends' || $name === 'implements') {
1266 continue;
1267 }
1268 if ($name[0] === ':') {
1269
1270  $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
1271 } elseif ($matches['type'][$i] === 'enum') {
1272
1273  
1274  
1275  
1276  $name = rtrim($name, ':');
1277 }
1278 $classes[] = ltrim($namespace . $name, '\\');
1279 }
1280 }
1281
1282 return $classes;
1283 }
1284 }
1285 <?php
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297 namespace Composer;
1298
1299 use Composer\IO\IOInterface;
1300 use Composer\Util\Filesystem;
1301 use Composer\Util\Silencer;
1302 use Symfony\Component\Finder\Finder;
1303
1304
1305
1306
1307
1308
1309 class Cache
1310 {
1311 private static $cacheCollected = false;
1312 private $io;
1313 private $root;
1314 private $enabled = true;
1315 private $whitelist;
1316 private $filesystem;
1317
1318
1319
1320
1321
1322
1323
1324 public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
1325 {
1326 $this->io = $io;
1327 $this->root = rtrim($cacheDir, '/\\') . '/';
1328 $this->whitelist = $whitelist;
1329 $this->filesystem = $filesystem ?: new Filesystem();
1330
1331 if (preg_match('{(^|[\\\\/])(\$null|NUL|/dev/null)([\\\\/]|$)}', $cacheDir)) {
1332 $this->enabled = false;
1333
1334 return;
1335 }
1336
1337 if (
1338 (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, true))
1339 || !is_writable($this->root)
1340 ) {
1341 $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
1342 $this->enabled = false;
1343 }
1344 }
1345
1346 public function isEnabled()
1347 {
1348 return $this->enabled;
1349 }
1350
1351 public function getRoot()
1352 {
1353 return $this->root;
1354 }
1355
1356 public function read($file)
1357 {
1358 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1359 if ($this->enabled && file_exists($this->root . $file)) {
1360 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1361
1362 return file_get_contents($this->root . $file);
1363 }
1364
1365 return false;
1366 }
1367
1368 public function write($file, $contents)
1369 {
1370 if ($this->enabled) {
1371 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1372
1373 $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
1374
1375 try {
1376 return file_put_contents($this->root . $file, $contents);
1377 } catch (\ErrorException $e) {
1378 $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', true, IOInterface::DEBUG);
1379 if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
1380
1381  unlink($this->root . $file);
1382
1383 $message = sprintf(
1384 '<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available</warning>',
1385 $this->root . $file,
1386 $m[1],
1387 $m[2],
1388 @disk_free_space($this->root . dirname($file))
1389 );
1390
1391 $this->io->writeError($message);
1392
1393 return false;
1394 }
1395
1396 throw $e;
1397 }
1398 }
1399
1400 return false;
1401 }
1402
1403
1404
1405
1406 public function copyFrom($file, $source)
1407 {
1408 if ($this->enabled) {
1409 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1410 $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
1411
1412 if (!file_exists($source)) {
1413 $this->io->writeError('<error>'.$source.' does not exist, can not write into cache</error>');
1414 } elseif ($this->io->isDebug()) {
1415 $this->io->writeError('Writing '.$this->root . $file.' into cache from '.$source);
1416 }
1417
1418 return copy($source, $this->root . $file);
1419 }
1420
1421 return false;
1422 }
1423
1424
1425
1426
1427 public function copyTo($file, $target)
1428 {
1429 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1430 if ($this->enabled && file_exists($this->root . $file)) {
1431 try {
1432 touch($this->root . $file, filemtime($this->root . $file), time());
1433 } catch (\ErrorException $e) {
1434
1435  
1436  Silencer::call('touch', $this->root . $file);
1437 }
1438
1439 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1440
1441 return copy($this->root . $file, $target);
1442 }
1443
1444 return false;
1445 }
1446
1447 public function gcIsNecessary()
1448 {
1449 return (!self::$cacheCollected && !mt_rand(0, 50));
1450 }
1451
1452 public function remove($file)
1453 {
1454 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1455 if ($this->enabled && file_exists($this->root . $file)) {
1456 return $this->filesystem->unlink($this->root . $file);
1457 }
1458
1459 return false;
1460 }
1461
1462 public function clear()
1463 {
1464 if ($this->enabled) {
1465 return $this->filesystem->removeDirectory($this->root);
1466 }
1467
1468 return false;
1469 }
1470
1471 public function gc($ttl, $maxSize)
1472 {
1473 if ($this->enabled) {
1474 $expire = new \DateTime();
1475 $expire->modify('-'.$ttl.' seconds');
1476
1477 $finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
1478 foreach ($finder as $file) {
1479 $this->filesystem->unlink($file->getPathname());
1480 }
1481
1482 $totalSize = $this->filesystem->size($this->root);
1483 if ($totalSize > $maxSize) {
1484 $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
1485 while ($totalSize > $maxSize && $iterator->valid()) {
1486 $filepath = $iterator->current()->getPathname();
1487 $totalSize -= $this->filesystem->size($filepath);
1488 $this->filesystem->unlink($filepath);
1489 $iterator->next();
1490 }
1491 }
1492
1493 self::$cacheCollected = true;
1494
1495 return true;
1496 }
1497
1498 return false;
1499 }
1500
1501 public function sha1($file)
1502 {
1503 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1504 if ($this->enabled && file_exists($this->root . $file)) {
1505 return sha1_file($this->root . $file);
1506 }
1507
1508 return false;
1509 }
1510
1511 public function sha256($file)
1512 {
1513 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1514 if ($this->enabled && file_exists($this->root . $file)) {
1515 return hash_file('sha256', $this->root . $file);
1516 }
1517
1518 return false;
1519 }
1520
1521 protected function getFinder()
1522 {
1523 return Finder::create()->in($this->root)->files();
1524 }
1525 }
1526 <?php
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538 namespace Composer\Command;
1539
1540 use Symfony\Component\Console\Input\InputInterface;
1541 use Symfony\Component\Console\Output\OutputInterface;
1542
1543
1544
1545
1546 class AboutCommand extends BaseCommand
1547 {
1548 protected function configure()
1549 {
1550 $this
1551 ->setName('about')
1552 ->setDescription('Shows the short information about Composer.')
1553 ->setHelp(<<<EOT
1554 <info>php composer.phar about</info>
1555 EOT
1556 )
1557 ;
1558 }
1559
1560 protected function execute(InputInterface $input, OutputInterface $output)
1561 {
1562 $this->getIO()->write(<<<EOT
1563 <info>Composer - Package Management for PHP</info>
1564 <comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
1565 See https://getcomposer.org/ for more information.</comment>
1566 EOT
1567 );
1568 }
1569 }
1570 <?php
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582 namespace Composer\Command;
1583
1584 use Composer\Factory;
1585 use Composer\IO\IOInterface;
1586 use Composer\Config;
1587 use Composer\Composer;
1588 use Composer\Repository\CompositeRepository;
1589 use Composer\Repository\RepositoryFactory;
1590 use Composer\Script\ScriptEvents;
1591 use Composer\Plugin\CommandEvent;
1592 use Composer\Plugin\PluginEvents;
1593 use Composer\Util\Filesystem;
1594 use Symfony\Component\Console\Input\InputArgument;
1595 use Symfony\Component\Console\Input\InputInterface;
1596 use Symfony\Component\Console\Input\InputOption;
1597 use Symfony\Component\Console\Output\OutputInterface;
1598
1599
1600
1601
1602
1603
1604 class ArchiveCommand extends BaseCommand
1605 {
1606 protected function configure()
1607 {
1608 $this
1609 ->setName('archive')
1610 ->setDescription('Creates an archive of this composer package.')
1611 ->setDefinition(array(
1612 new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project'),
1613 new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'),
1614 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar or zip'),
1615 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
1616 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
1617 .' Note that the format will be appended.'),
1618 new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
1619 ))
1620 ->setHelp(<<<EOT
1621 The <info>archive</info> command creates an archive of the specified format
1622 containing the files and directories of the Composer project or the specified
1623 package in the specified version and writes it to the specified directory.
1624
1625 <info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
1626
1627 EOT
1628 )
1629 ;
1630 }
1631
1632 protected function execute(InputInterface $input, OutputInterface $output)
1633 {
1634 $config = Factory::createConfig();
1635 $composer = $this->getComposer(false);
1636 if ($composer) {
1637 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
1638 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
1639 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
1640 }
1641
1642 if (null === $input->getOption('format')) {
1643 $input->setOption('format', $config->get('archive-format'));
1644 }
1645 if (null === $input->getOption('dir')) {
1646 $input->setOption('dir', $config->get('archive-dir'));
1647 }
1648
1649 $returnCode = $this->archive(
1650 $this->getIO(),
1651 $config,
1652 $input->getArgument('package'),
1653 $input->getArgument('version'),
1654 $input->getOption('format'),
1655 $input->getOption('dir'),
1656 $input->getOption('file'),
1657 $input->getOption('ignore-filters'),
1658 $composer
1659 );
1660
1661 if (0 === $returnCode && $composer) {
1662 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
1663 }
1664
1665 return $returnCode;
1666 }
1667
1668 protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null, $ignoreFilters = false, Composer $composer = null)
1669 {
1670 if ($composer) {
1671 $archiveManager = $composer->getArchiveManager();
1672 } else {
1673 $factory = new Factory;
1674 $downloadManager = $factory->createDownloadManager($io, $config);
1675 $archiveManager = $factory->createArchiveManager($config, $downloadManager);
1676 }
1677
1678 if ($packageName) {
1679 $package = $this->selectPackage($io, $packageName, $version);
1680
1681 if (!$package) {
1682 return 1;
1683 }
1684 } else {
1685 $package = $this->getComposer()->getPackage();
1686 }
1687
1688 $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
1689 $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
1690 $fs = new Filesystem;
1691 $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
1692
1693 $io->writeError('Created: ', false);
1694 $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
1695
1696 return 0;
1697 }
1698
1699 protected function selectPackage(IOInterface $io, $packageName, $version = null)
1700 {
1701 $io->writeError('<info>Searching for the specified package.</info>');
1702
1703 if ($composer = $this->getComposer(false)) {
1704 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
1705 $repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
1706 } else {
1707 $defaultRepos = RepositoryFactory::defaultRepos($this->getIO());
1708 $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
1709 $repo = new CompositeRepository($defaultRepos);
1710 }
1711
1712 $packages = $repo->findPackages($packageName, $version);
1713
1714 if (count($packages) > 1) {
1715 $package = reset($packages);
1716 $io->writeError('<info>Found multiple matches, selected '.$package->getPrettyString().'.</info>');
1717 $io->writeError('Alternatives were '.implode(', ', array_map(function ($p) {
1718 return $p->getPrettyString();
1719 }, $packages)).'.');
1720 $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
1721 } elseif ($packages) {
1722 $package = reset($packages);
1723 $io->writeError('<info>Found an exact match '.$package->getPrettyString().'.</info>');
1724 } else {
1725 $io->writeError('<error>Could not find a package matching '.$packageName.'.</error>');
1726
1727 return false;
1728 }
1729
1730 return $package;
1731 }
1732 }
1733 <?php
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745 namespace Composer\Command;
1746
1747 use Composer\Composer;
1748 use Composer\Config;
1749 use Composer\Console\Application;
1750 use Composer\IO\IOInterface;
1751 use Composer\IO\NullIO;
1752 use Symfony\Component\Console\Input\InputInterface;
1753 use Symfony\Component\Console\Output\OutputInterface;
1754 use Symfony\Component\Console\Command\Command;
1755
1756
1757
1758
1759
1760
1761
1762 abstract class BaseCommand extends Command
1763 {
1764
1765
1766
1767 private $composer;
1768
1769
1770
1771
1772 private $io;
1773
1774
1775
1776
1777
1778
1779
1780 public function getComposer($required = true, $disablePlugins = null)
1781 {
1782 if (null === $this->composer) {
1783 $application = $this->getApplication();
1784 if ($application instanceof Application) {
1785
1786 $this->composer = $application->getComposer($required, $disablePlugins);
1787 } elseif ($required) {
1788 throw new \RuntimeException(
1789 'Could not create a Composer\Composer instance, you must inject '.
1790 'one if this command is not used with a Composer\Console\Application instance'
1791 );
1792 }
1793 }
1794
1795 return $this->composer;
1796 }
1797
1798
1799
1800
1801 public function setComposer(Composer $composer)
1802 {
1803 $this->composer = $composer;
1804 }
1805
1806
1807
1808
1809 public function resetComposer()
1810 {
1811 $this->composer = null;
1812 $this->getApplication()->resetComposer();
1813 }
1814
1815
1816
1817
1818
1819
1820
1821
1822 public function isProxyCommand()
1823 {
1824 return false;
1825 }
1826
1827
1828
1829
1830 public function getIO()
1831 {
1832 if (null === $this->io) {
1833 $application = $this->getApplication();
1834 if ($application instanceof Application) {
1835
1836 $this->io = $application->getIO();
1837 } else {
1838 $this->io = new NullIO();
1839 }
1840 }
1841
1842 return $this->io;
1843 }
1844
1845
1846
1847
1848 public function setIO(IOInterface $io)
1849 {
1850 $this->io = $io;
1851 }
1852
1853
1854
1855
1856 protected function initialize(InputInterface $input, OutputInterface $output)
1857 {
1858 if (true === $input->hasParameterOption(array('--no-ansi')) && $input->hasOption('no-progress')) {
1859 $input->setOption('no-progress', true);
1860 }
1861
1862 parent::initialize($input, $output);
1863 }
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874 protected function getPreferredInstallOptions(Config $config, InputInterface $input, $keepVcsRequiresPreferSource = false)
1875 {
1876 $preferSource = false;
1877 $preferDist = false;
1878
1879 switch ($config->get('preferred-install')) {
1880 case 'source':
1881 $preferSource = true;
1882 break;
1883 case 'dist':
1884 $preferDist = true;
1885 break;
1886 case 'auto':
1887 default:
1888
1889  break;
1890 }
1891
1892 if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
1893 $preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
1894 $preferDist = $input->getOption('prefer-dist');
1895 }
1896
1897 return array($preferSource, $preferDist);
1898 }
1899 }
1900 <?php
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912 namespace Composer\Command;
1913
1914 use Composer\DependencyResolver\Pool;
1915 use Composer\Package\Link;
1916 use Composer\Package\PackageInterface;
1917 use Composer\Repository\ArrayRepository;
1918 use Composer\Repository\CompositeRepository;
1919 use Composer\Repository\PlatformRepository;
1920 use Composer\Repository\RepositoryFactory;
1921 use Composer\Plugin\CommandEvent;
1922 use Composer\Plugin\PluginEvents;
1923 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
1924 use Composer\Package\Version\VersionParser;
1925 use Symfony\Component\Console\Helper\Table;
1926 use Symfony\Component\Console\Input\InputArgument;
1927 use Symfony\Component\Console\Input\InputInterface;
1928 use Symfony\Component\Console\Input\InputOption;
1929 use Symfony\Component\Console\Output\OutputInterface;
1930
1931
1932
1933
1934
1935
1936 class BaseDependencyCommand extends BaseCommand
1937 {
1938 const ARGUMENT_PACKAGE = 'package';
1939 const ARGUMENT_CONSTRAINT = 'constraint';
1940 const OPTION_RECURSIVE = 'recursive';
1941 const OPTION_TREE = 'tree';
1942
1943 protected $colors;
1944
1945
1946
1947
1948 protected function configure()
1949 {
1950 $this->setDefinition(array(
1951 new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
1952 new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
1953 new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
1954 new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
1955 ));
1956 }
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966 protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
1967 {
1968
1969  $composer = $this->getComposer();
1970 $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
1971 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
1972
1973
1974  $platformOverrides = $composer->getConfig()->get('platform') ?: array();
1975 $repository = new CompositeRepository(array(
1976 new ArrayRepository(array($composer->getPackage())),
1977 $composer->getRepositoryManager()->getLocalRepository(),
1978 new PlatformRepository(array(), $platformOverrides),
1979 ));
1980 $pool = new Pool();
1981 $pool->addRepository($repository);
1982
1983
1984  list($needle, $textConstraint) = array_pad(
1985 explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
1986 2,
1987 $input->getArgument(self::ARGUMENT_CONSTRAINT)
1988 );
1989
1990
1991  $packages = $pool->whatProvides($needle);
1992 if (empty($packages)) {
1993 throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
1994 }
1995
1996
1997  
1998  if (!$repository->findPackage($needle, $textConstraint)) {
1999 $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
2000 if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
2001 $repository->addRepository(new ArrayRepository(array(clone $match)));
2002 }
2003 }
2004
2005
2006  $needles = array($needle);
2007 if ($inverted) {
2008 foreach ($packages as $package) {
2009 $needles = array_merge($needles, array_map(function (Link $link) {
2010 return $link->getTarget();
2011 }, $package->getReplaces()));
2012 }
2013 }
2014
2015
2016  if ('*' !== $textConstraint) {
2017 $versionParser = new VersionParser();
2018 $constraint = $versionParser->parseConstraints($textConstraint);
2019 } else {
2020 $constraint = null;
2021 }
2022
2023
2024  $renderTree = $input->getOption(self::OPTION_TREE);
2025 $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
2026
2027
2028  $results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
2029 if (empty($results)) {
2030 $extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
2031 $this->getIO()->writeError(sprintf('<info>There is no installed package depending on "%s"%s</info>',
2032 $needle, $extra));
2033 } elseif ($renderTree) {
2034 $this->initStyles($output);
2035 $root = $packages[0];
2036 $this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
2037 $this->printTree($results);
2038 } else {
2039 $this->printTable($output, $results);
2040 }
2041
2042 return 0;
2043 }
2044
2045
2046
2047
2048
2049
2050
2051 protected function printTable(OutputInterface $output, $results)
2052 {
2053 $table = array();
2054 $doubles = array();
2055 do {
2056 $queue = array();
2057 $rows = array();
2058 foreach ($results as $result) {
2059
2060
2061
2062
2063 list($package, $link, $children) = $result;
2064 $unique = (string) $link;
2065 if (isset($doubles[$unique])) {
2066 continue;
2067 }
2068 $doubles[$unique] = true;
2069 $version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
2070 $rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
2071 if ($children) {
2072 $queue = array_merge($queue, $children);
2073 }
2074 }
2075 $results = $queue;
2076 $table = array_merge($rows, $table);
2077 } while (!empty($results));
2078
2079
2080  $renderer = new Table($output);
2081 $renderer->setStyle('compact');
2082 $renderer->getStyle()->setVerticalBorderChar('');
2083 $renderer->getStyle()->setCellRowContentFormat('%s  ');
2084 $renderer->setRows($table)->render();
2085 }
2086
2087
2088
2089
2090
2091
2092 protected function initStyles(OutputInterface $output)
2093 {
2094 $this->colors = array(
2095 'green',
2096 'yellow',
2097 'cyan',
2098 'magenta',
2099 'blue',
2100 );
2101
2102 foreach ($this->colors as $color) {
2103 $style = new OutputFormatterStyle($color);
2104 $output->getFormatter()->setStyle($color, $style);
2105 }
2106 }
2107
2108
2109
2110
2111
2112
2113
2114
2115 protected function printTree($results, $prefix = '', $level = 1)
2116 {
2117 $count = count($results);
2118 $idx = 0;
2119 foreach ($results as $result) {
2120
2121
2122
2123
2124
2125 list($package, $link, $children) = $result;
2126
2127 $color = $this->colors[$level % count($this->colors)];
2128 $prevColor = $this->colors[($level - 1) % count($this->colors)];
2129 $isLast = (++$idx == $count);
2130 $versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
2131 $packageText = rtrim(sprintf('<%s>%s</%1$s> %s', $color, $package->getPrettyName(), $versionText));
2132 $linkText = sprintf('%s <%s>%s</%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
2133 $circularWarn = $children === false ? '(circular dependency aborted here)' : '';
2134 $this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
2135 if ($children) {
2136 $this->printTree($children, $prefix . ($isLast ? '   ' : '│  '), $level + 1);
2137 }
2138 }
2139 }
2140
2141 private function writeTreeLine($line)
2142 {
2143 $io = $this->getIO();
2144 if (!$io->isDecorated()) {
2145 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
2146 }
2147
2148 $io->write($line);
2149 }
2150 }
2151 <?php
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163 namespace Composer\Command;
2164
2165 use Composer\Package\Link;
2166 use Composer\Package\PackageInterface;
2167 use Composer\Semver\Constraint\Constraint;
2168 use Symfony\Component\Console\Helper\Table;
2169 use Symfony\Component\Console\Input\InputInterface;
2170 use Symfony\Component\Console\Output\OutputInterface;
2171 use Composer\Repository\PlatformRepository;
2172
2173 class CheckPlatformReqsCommand extends BaseCommand
2174 {
2175 protected function configure()
2176 {
2177 $this->setName('check-platform-reqs')
2178 ->setDescription('Check that platform requirements are satisfied.')
2179 ->setHelp(<<<EOT
2180 Checks that your PHP and extensions versions match the platform requirements of the installed packages.
2181
2182 <info>php composer.phar check-platform-reqs</info>
2183
2184 EOT
2185 );
2186 }
2187
2188 protected function execute(InputInterface $input, OutputInterface $output)
2189 {
2190 $composer = $this->getComposer();
2191
2192 $repos = $composer->getRepositoryManager()->getLocalRepository();
2193
2194 $allPackages = array_merge(array($composer->getPackage()), $repos->getPackages());
2195 $requires = $composer->getPackage()->getDevRequires();
2196 foreach ($requires as $require => $link) {
2197 $requires[$require] = array($link);
2198 }
2199
2200
2201
2202
2203 foreach ($allPackages as $package) {
2204 foreach ($package->getRequires() as $require => $link) {
2205 $requires[$require][] = $link;
2206 }
2207 }
2208 ksort($requires);
2209
2210 $platformRepo = new PlatformRepository(array(), array());
2211 $currentPlatformPackages = $platformRepo->getPackages();
2212 $currentPlatformPackageMap = array();
2213
2214
2215
2216
2217 foreach ($currentPlatformPackages as $currentPlatformPackage) {
2218 $currentPlatformPackageMap[$currentPlatformPackage->getName()] = $currentPlatformPackage;
2219 }
2220
2221 $results = array();
2222
2223 $exitCode = 0;
2224
2225
2226
2227
2228 foreach ($requires as $require => $links) {
2229 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $require)) {
2230 if (isset($currentPlatformPackageMap[$require])) {
2231 $pass = true;
2232 $version = $currentPlatformPackageMap[$require]->getVersion();
2233
2234 foreach ($links as $link) {
2235 if (!$link->getConstraint()->matches(new Constraint('=', $version))) {
2236 $results[] = array(
2237 $currentPlatformPackageMap[$require]->getPrettyName(),
2238 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2239 $link,
2240 '<error>failed</error>',
2241 );
2242 $pass = false;
2243
2244 $exitCode = max($exitCode, 1);
2245 }
2246 }
2247
2248 if ($pass) {
2249 $results[] = array(
2250 $currentPlatformPackageMap[$require]->getPrettyName(),
2251 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2252 null,
2253 '<info>success</info>',
2254 );
2255 }
2256 } else {
2257 $results[] = array(
2258 $require,
2259 'n/a',
2260 $links[0],
2261 '<error>missing</error>',
2262 );
2263
2264 $exitCode = max($exitCode, 2);
2265 }
2266 }
2267 }
2268
2269 $this->printTable($output, $results);
2270
2271 return $exitCode;
2272 }
2273
2274 protected function printTable(OutputInterface $output, $results)
2275 {
2276 $table = array();
2277 $rows = array();
2278 foreach ($results as $result) {
2279
2280
2281
2282 list($platformPackage, $version, $link, $status) = $result;
2283 $rows[] = array(
2284 $platformPackage,
2285 $version,
2286 $link ? sprintf('%s %s %s (%s)', $link->getSource(), $link->getDescription(), $link->getTarget(), $link->getPrettyConstraint()) : '',
2287 $status,
2288 );
2289 }
2290 $table = array_merge($rows, $table);
2291
2292
2293  $renderer = new Table($output);
2294 $renderer->setStyle('compact');
2295 $renderer->getStyle()->setVerticalBorderChar('');
2296 $renderer->getStyle()->setCellRowContentFormat('%s  ');
2297 $renderer->setRows($table)->render();
2298 }
2299 }
2300 <?php
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312 namespace Composer\Command;
2313
2314 use Composer\Cache;
2315 use Composer\Factory;
2316 use Symfony\Component\Console\Input\InputInterface;
2317 use Symfony\Component\Console\Output\OutputInterface;
2318
2319
2320
2321
2322 class ClearCacheCommand extends BaseCommand
2323 {
2324 protected function configure()
2325 {
2326 $this
2327 ->setName('clear-cache')
2328 ->setAliases(array('clearcache'))
2329 ->setDescription('Clears composer\'s internal package cache.')
2330 ->setHelp(<<<EOT
2331 The <info>clear-cache</info> deletes all cached packages from composer's
2332 cache directory.
2333 EOT
2334 )
2335 ;
2336 }
2337
2338 protected function execute(InputInterface $input, OutputInterface $output)
2339 {
2340 $config = Factory::createConfig();
2341 $io = $this->getIO();
2342
2343 $cachePaths = array(
2344 'cache-vcs-dir' => $config->get('cache-vcs-dir'),
2345 'cache-repo-dir' => $config->get('cache-repo-dir'),
2346 'cache-files-dir' => $config->get('cache-files-dir'),
2347 'cache-dir' => $config->get('cache-dir'),
2348 );
2349
2350 foreach ($cachePaths as $key => $cachePath) {
2351 $cachePath = realpath($cachePath);
2352 if (!$cachePath) {
2353 $io->writeError("<info>Cache directory does not exist ($key): $cachePath</info>");
2354
2355 continue;
2356 }
2357 $cache = new Cache($io, $cachePath);
2358 if (!$cache->isEnabled()) {
2359 $io->writeError("<info>Cache is not enabled ($key): $cachePath</info>");
2360
2361 continue;
2362 }
2363
2364 $io->writeError("<info>Clearing cache ($key): $cachePath</info>");
2365 $cache->clear();
2366 }
2367
2368 $io->writeError('<info>All caches cleared.</info>');
2369 }
2370 }
2371 <?php
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383 namespace Composer\Command;
2384
2385 use Composer\Util\Platform;
2386 use Composer\Util\Silencer;
2387 use Symfony\Component\Console\Input\InputInterface;
2388 use Symfony\Component\Console\Input\InputArgument;
2389 use Symfony\Component\Console\Input\InputOption;
2390 use Symfony\Component\Console\Output\OutputInterface;
2391 use Composer\Config;
2392 use Composer\Config\JsonConfigSource;
2393 use Composer\Factory;
2394 use Composer\Json\JsonFile;
2395 use Composer\Semver\VersionParser;
2396 use Composer\Package\BasePackage;
2397
2398
2399
2400
2401
2402 class ConfigCommand extends BaseCommand
2403 {
2404
2405
2406
2407 protected $config;
2408
2409
2410
2411
2412 protected $configFile;
2413
2414
2415
2416
2417 protected $configSource;
2418
2419
2420
2421
2422 protected $authConfigFile;
2423
2424
2425
2426
2427 protected $authConfigSource;
2428
2429
2430
2431
2432 protected function configure()
2433 {
2434 $this
2435 ->setName('config')
2436 ->setDescription('Sets config options.')
2437 ->setDefinition(array(
2438 new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'),
2439 new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'),
2440 new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
2441 new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
2442 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
2443 new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
2444 new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
2445 new InputArgument('setting-key', null, 'Setting key'),
2446 new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
2447 ))
2448 ->setHelp(<<<EOT
2449 This command allows you to edit composer config settings and repositories
2450 in either the local composer.json file or the global config.json file.
2451
2452 Additionally it lets you edit most properties in the local composer.json.
2453
2454 To set a config setting:
2455
2456     <comment>%command.full_name% bin-dir bin/</comment>
2457
2458 To read a config setting:
2459
2460     <comment>%command.full_name% bin-dir</comment>
2461     Outputs: <info>bin</info>
2462
2463 To edit the global config.json file:
2464
2465     <comment>%command.full_name% --global</comment>
2466
2467 To add a repository:
2468
2469     <comment>%command.full_name% repositories.foo vcs https://bar.com</comment>
2470
2471 To remove a repository (repo is a short alias for repositories):
2472
2473     <comment>%command.full_name% --unset repo.foo</comment>
2474
2475 To disable packagist:
2476
2477     <comment>%command.full_name% repo.packagist false</comment>
2478
2479 You can alter repositories in the global config.json file by passing in the
2480 <info>--global</info> option.
2481
2482 To edit the file in an external editor:
2483
2484     <comment>%command.full_name% --editor</comment>
2485
2486 To choose your editor you can set the "EDITOR" env variable.
2487
2488 To get a list of configuration values in the file:
2489
2490     <comment>%command.full_name% --list</comment>
2491
2492 You can always pass more than one option. As an example, if you want to edit the
2493 global config.json file.
2494
2495     <comment>%command.full_name% --editor --global</comment>
2496 EOT
2497 )
2498 ;
2499 }
2500
2501
2502
2503
2504 protected function initialize(InputInterface $input, OutputInterface $output)
2505 {
2506 parent::initialize($input, $output);
2507
2508 if ($input->getOption('global') && null !== $input->getOption('file')) {
2509 throw new \RuntimeException('--file and --global can not be combined');
2510 }
2511
2512 $io = $this->getIO();
2513 $this->config = Factory::createConfig($io);
2514
2515
2516  
2517  $configFile = $input->getOption('global')
2518 ? ($this->config->get('home') . '/config.json')
2519 : ($input->getOption('file') ?: Factory::getComposerFile());
2520
2521
2522  if (
2523 ($configFile === 'composer.json' || $configFile === './composer.json')
2524 && !file_exists($configFile)
2525 && realpath(getcwd()) === realpath($this->config->get('home'))
2526 ) {
2527 file_put_contents($configFile, "{\n}\n");
2528 }
2529
2530 $this->configFile = new JsonFile($configFile, null, $io);
2531 $this->configSource = new JsonConfigSource($this->configFile);
2532
2533 $authConfigFile = $input->getOption('global')
2534 ? ($this->config->get('home') . '/auth.json')
2535 : dirname(realpath($configFile)) . '/auth.json';
2536
2537 $this->authConfigFile = new JsonFile($authConfigFile, null, $io);
2538 $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
2539
2540
2541  if ($input->getOption('global') && !$this->configFile->exists()) {
2542 touch($this->configFile->getPath());
2543 $this->configFile->write(array('config' => new \ArrayObject));
2544 Silencer::call('chmod', $this->configFile->getPath(), 0600);
2545 }
2546 if ($input->getOption('global') && !$this->authConfigFile->exists()) {
2547 touch($this->authConfigFile->getPath());
2548 $this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject));
2549 Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
2550 }
2551
2552 if (!$this->configFile->exists()) {
2553 throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
2554 }
2555 }
2556
2557
2558
2559
2560 protected function execute(InputInterface $input, OutputInterface $output)
2561 {
2562
2563  if ($input->getOption('editor')) {
2564 $editor = escapeshellcmd(getenv('EDITOR'));
2565 if (!$editor) {
2566 if (Platform::isWindows()) {
2567 $editor = 'notepad';
2568 } else {
2569 foreach (array('editor', 'vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
2570 if (exec('which '.$candidate)) {
2571 $editor = $candidate;
2572 break;
2573 }
2574 }
2575 }
2576 }
2577
2578 $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
2579 system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
2580
2581 return 0;
2582 }
2583
2584 if (!$input->getOption('global')) {
2585 $this->config->merge($this->configFile->read());
2586 $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
2587 }
2588
2589
2590  if ($input->getOption('list')) {
2591 $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
2592
2593 return 0;
2594 }
2595
2596 $settingKey = $input->getArgument('setting-key');
2597 if (!$settingKey) {
2598 return 0;
2599 }
2600
2601
2602  if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
2603 throw new \RuntimeException('You can not combine a setting value with --unset');
2604 }
2605
2606
2607  if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
2608 $properties = array('name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra');
2609 $rawData = $this->configFile->read();
2610 $data = $this->config->all();
2611 if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
2612 if (!isset($matches[1]) || $matches[1] === '') {
2613 $value = isset($data['repositories']) ? $data['repositories'] : array();
2614 } else {
2615 if (!isset($data['repositories'][$matches[1]])) {
2616 throw new \InvalidArgumentException('There is no '.$matches[1].' repository defined');
2617 }
2618
2619 $value = $data['repositories'][$matches[1]];
2620 }
2621 } elseif (strpos($settingKey, '.')) {
2622 $bits = explode('.', $settingKey);
2623 if ($bits[0] === 'extra') {
2624 $data = $rawData;
2625 } else {
2626 $data = $data['config'];
2627 }
2628 $match = false;
2629 foreach ($bits as $bit) {
2630 $key = isset($key) ? $key.'.'.$bit : $bit;
2631 $match = false;
2632 if (isset($data[$key])) {
2633 $match = true;
2634 $data = $data[$key];
2635 unset($key);
2636 }
2637 }
2638
2639 if (!$match) {
2640 throw new \RuntimeException($settingKey.' is not defined.');
2641 }
2642
2643 $value = $data;
2644 } elseif (isset($data['config'][$settingKey])) {
2645 $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
2646 } elseif (in_array($settingKey, $properties, true) && isset($rawData[$settingKey])) {
2647 $value = $rawData[$settingKey];
2648 } else {
2649 throw new \RuntimeException($settingKey.' is not defined');
2650 }
2651
2652 if (is_array($value)) {
2653 $value = json_encode($value);
2654 }
2655
2656 $this->getIO()->write($value);
2657
2658 return 0;
2659 }
2660
2661 $values = $input->getArgument('setting-value'); 
2662
2663 $booleanValidator = function ($val) {
2664 return in_array($val, array('true', 'false', '1', '0'), true);
2665 };
2666 $booleanNormalizer = function ($val) {
2667 return $val !== 'false' && (bool) $val;
2668 };
2669
2670
2671  $uniqueConfigValues = array(
2672 'process-timeout' => array('is_numeric', 'intval'),
2673 'use-include-path' => array($booleanValidator, $booleanNormalizer),
2674 'preferred-install' => array(
2675 function ($val) {
2676 return in_array($val, array('auto', 'source', 'dist'), true);
2677 },
2678 function ($val) {
2679 return $val;
2680 },
2681 ),
2682 'store-auths' => array(
2683 function ($val) {
2684 return in_array($val, array('true', 'false', 'prompt'), true);
2685 },
2686 function ($val) {
2687 if ('prompt' === $val) {
2688 return 'prompt';
2689 }
2690
2691 return $val !== 'false' && (bool) $val;
2692 },
2693 ),
2694 'notify-on-install' => array($booleanValidator, $booleanNormalizer),
2695 'vendor-dir' => array('is_string', function ($val) {
2696 return $val;
2697 }),
2698 'bin-dir' => array('is_string', function ($val) {
2699 return $val;
2700 }),
2701 'archive-dir' => array('is_string', function ($val) {
2702 return $val;
2703 }),
2704 'archive-format' => array('is_string', function ($val) {
2705 return $val;
2706 }),
2707 'data-dir' => array('is_string', function ($val) {
2708 return $val;
2709 }),
2710 'cache-dir' => array('is_string', function ($val) {
2711 return $val;
2712 }),
2713 'cache-files-dir' => array('is_string', function ($val) {
2714 return $val;
2715 }),
2716 'cache-repo-dir' => array('is_string', function ($val) {
2717 return $val;
2718 }),
2719 'cache-vcs-dir' => array('is_string', function ($val) {
2720 return $val;
2721 }),
2722 'cache-ttl' => array('is_numeric', 'intval'),
2723 'cache-files-ttl' => array('is_numeric', 'intval'),
2724 'cache-files-maxsize' => array(
2725 function ($val) {
2726 return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0;
2727 },
2728 function ($val) {
2729 return $val;
2730 },
2731 ),
2732 'bin-compat' => array(
2733 function ($val) {
2734 return in_array($val, array('auto', 'full'));
2735 },
2736 function ($val) {
2737 return $val;
2738 },
2739 ),
2740 'discard-changes' => array(
2741 function ($val) {
2742 return in_array($val, array('stash', 'true', 'false', '1', '0'), true);
2743 },
2744 function ($val) {
2745 if ('stash' === $val) {
2746 return 'stash';
2747 }
2748
2749 return $val !== 'false' && (bool) $val;
2750 },
2751 ),
2752 'autoloader-suffix' => array('is_string', function ($val) {
2753 return $val === 'null' ? null : $val;
2754 }),
2755 'sort-packages' => array($booleanValidator, $booleanNormalizer),
2756 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
2757 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
2758 'apcu-autoloader' => array($booleanValidator, $booleanNormalizer),
2759 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
2760 'disable-tls' => array($booleanValidator, $booleanNormalizer),
2761 'secure-http' => array($booleanValidator, $booleanNormalizer),
2762 'cafile' => array(
2763 function ($val) {
2764 return file_exists($val) && is_readable($val);
2765 },
2766 function ($val) {
2767 return $val === 'null' ? null : $val;
2768 },
2769 ),
2770 'capath' => array(
2771 function ($val) {
2772 return is_dir($val) && is_readable($val);
2773 },
2774 function ($val) {
2775 return $val === 'null' ? null : $val;
2776 },
2777 ),
2778 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
2779 'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
2780 );
2781 $multiConfigValues = array(
2782 'github-protocols' => array(
2783 function ($vals) {
2784 if (!is_array($vals)) {
2785 return 'array expected';
2786 }
2787
2788 foreach ($vals as $val) {
2789 if (!in_array($val, array('git', 'https', 'ssh'))) {
2790 return 'valid protocols include: git, https, ssh';
2791 }
2792 }
2793
2794 return true;
2795 },
2796 function ($vals) {
2797 return $vals;
2798 },
2799 ),
2800 'github-domains' => array(
2801 function ($vals) {
2802 if (!is_array($vals)) {
2803 return 'array expected';
2804 }
2805
2806 return true;
2807 },
2808 function ($vals) {
2809 return $vals;
2810 },
2811 ),
2812 'gitlab-domains' => array(
2813 function ($vals) {
2814 if (!is_array($vals)) {
2815 return 'array expected';
2816 }
2817
2818 return true;
2819 },
2820 function ($vals) {
2821 return $vals;
2822 },
2823 ),
2824 );
2825
2826 if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) {
2827 return $this->configSource->removeConfigSetting($settingKey);
2828 }
2829 if (isset($uniqueConfigValues[$settingKey])) {
2830 return $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
2831 }
2832 if (isset($multiConfigValues[$settingKey])) {
2833 return $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
2834 }
2835
2836
2837  $uniqueProps = array(
2838 'name' => array('is_string', function ($val) {
2839 return $val;
2840 }),
2841 'type' => array('is_string', function ($val) {
2842 return $val;
2843 }),
2844 'description' => array('is_string', function ($val) {
2845 return $val;
2846 }),
2847 'homepage' => array('is_string', function ($val) {
2848 return $val;
2849 }),
2850 'version' => array('is_string', function ($val) {
2851 return $val;
2852 }),
2853 'minimum-stability' => array(
2854 function ($val) {
2855 return isset(BasePackage::$stabilities[VersionParser::normalizeStability($val)]);
2856 },
2857 function ($val) {
2858 return VersionParser::normalizeStability($val);
2859 },
2860 ),
2861 'prefer-stable' => array($booleanValidator, $booleanNormalizer),
2862 );
2863 $multiProps = array(
2864 'keywords' => array(
2865 function ($vals) {
2866 if (!is_array($vals)) {
2867 return 'array expected';
2868 }
2869
2870 return true;
2871 },
2872 function ($vals) {
2873 return $vals;
2874 },
2875 ),
2876 'license' => array(
2877 function ($vals) {
2878 if (!is_array($vals)) {
2879 return 'array expected';
2880 }
2881
2882 return true;
2883 },
2884 function ($vals) {
2885 return $vals;
2886 },
2887 ),
2888 );
2889
2890 if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) {
2891 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');
2892 }
2893 if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
2894 return $this->configSource->removeProperty($settingKey);
2895 }
2896 if (isset($uniqueProps[$settingKey])) {
2897 return $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
2898 }
2899 if (isset($multiProps[$settingKey])) {
2900 return $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
2901 }
2902
2903
2904  if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
2905 if ($input->getOption('unset')) {
2906 return $this->configSource->removeRepository($matches[1]);
2907 }
2908
2909 if (2 === count($values)) {
2910 return $this->configSource->addRepository($matches[1], array(
2911 'type' => $values[0],
2912 'url' => $values[1],
2913 ));
2914 }
2915
2916 if (1 === count($values)) {
2917 $value = strtolower($values[0]);
2918 if (true === $booleanValidator($value)) {
2919 if (false === $booleanNormalizer($value)) {
2920 return $this->configSource->addRepository($matches[1], false);
2921 }
2922 } else {
2923 $value = JsonFile::parseJson($values[0]);
2924
2925 return $this->configSource->addRepository($matches[1], $value);
2926 }
2927 }
2928
2929 throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
2930 }
2931
2932
2933  if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) {
2934 if ($input->getOption('unset')) {
2935 return $this->configSource->removeProperty($settingKey);
2936 }
2937
2938 return $this->configSource->addProperty($settingKey, $values[0]);
2939 }
2940
2941
2942  if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
2943 if ($input->getOption('unset')) {
2944 return $this->configSource->removeConfigSetting($settingKey);
2945 }
2946
2947 return $this->configSource->addConfigSetting($settingKey, $values[0]);
2948 }
2949 if ($settingKey === 'platform' && $input->getOption('unset')) {
2950 return $this->configSource->removeConfigSetting($settingKey);
2951 }
2952
2953
2954  if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic)\.(.+)/', $settingKey, $matches)) {
2955 if ($input->getOption('unset')) {
2956 $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2957 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2958
2959 return;
2960 }
2961
2962 if ($matches[1] === 'bitbucket-oauth') {
2963 if (2 !== count($values)) {
2964 throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got '.count($values));
2965 }
2966 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2967 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
2968 } elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token'), true)) {
2969 if (1 !== count($values)) {
2970 throw new \RuntimeException('Too many arguments, expected only one token');
2971 }
2972 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2973 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], $values[0]);
2974 } elseif ($matches[1] === 'http-basic') {
2975 if (2 !== count($values)) {
2976 throw new \RuntimeException('Expected two arguments (username, password), got '.count($values));
2977 }
2978 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2979 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
2980 }
2981
2982 return;
2983 }
2984
2985 throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
2986 }
2987
2988 protected function handleSingleValue($key, array $callbacks, array $values, $method)
2989 {
2990 list($validator, $normalizer) = $callbacks;
2991 if (1 !== count($values)) {
2992 throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
2993 }
2994
2995 if (true !== $validation = $validator($values[0])) {
2996 throw new \RuntimeException(sprintf(
2997 '"%s" is an invalid value'.($validation ? ' ('.$validation.')' : ''),
2998 $values[0]
2999 ));
3000 }
3001
3002 return call_user_func(array($this->configSource, $method), $key, $normalizer($values[0]));
3003 }
3004
3005 protected function handleMultiValue($key, array $callbacks, array $values, $method)
3006 {
3007 list($validator, $normalizer) = $callbacks;
3008 if (true !== $validation = $validator($values)) {
3009 throw new \RuntimeException(sprintf(
3010 '%s is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3011 json_encode($values)
3012 ));
3013 }
3014
3015 return call_user_func(array($this->configSource, $method), $key, $normalizer($values));
3016 }
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026 protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
3027 {
3028 $origK = $k;
3029 $io = $this->getIO();
3030 foreach ($contents as $key => $value) {
3031 if ($k === null && !in_array($key, array('config', 'repositories'))) {
3032 continue;
3033 }
3034
3035 $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null;
3036
3037 if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
3038 $k .= preg_replace('{^config\.}', '', $key . '.');
3039 $this->listConfiguration($value, $rawVal, $output, $k);
3040 $k = $origK;
3041
3042 continue;
3043 }
3044
3045 if (is_array($value)) {
3046 $value = array_map(function ($val) {
3047 return is_array($val) ? json_encode($val) : $val;
3048 }, $value);
3049
3050 $value = '['.implode(', ', $value).']';
3051 }
3052
3053 if (is_bool($value)) {
3054 $value = var_export($value, true);
3055 }
3056
3057 if (is_string($rawVal) && $rawVal != $value) {
3058 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>');
3059 } else {
3060 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>');
3061 }
3062 }
3063 }
3064 }
3065 <?php
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077 namespace Composer\Command;
3078
3079 use Composer\Config;
3080 use Composer\Factory;
3081 use Composer\Installer;
3082 use Composer\Installer\ProjectInstaller;
3083 use Composer\Installer\InstallationManager;
3084 use Composer\Installer\SuggestedPackagesReporter;
3085 use Composer\IO\IOInterface;
3086 use Composer\Package\BasePackage;
3087 use Composer\DependencyResolver\Pool;
3088 use Composer\DependencyResolver\Operation\InstallOperation;
3089 use Composer\Package\Version\VersionSelector;
3090 use Composer\Package\AliasPackage;
3091 use Composer\Repository\RepositoryFactory;
3092 use Composer\Repository\CompositeRepository;
3093 use Composer\Repository\PlatformRepository;
3094 use Composer\Repository\InstalledFilesystemRepository;
3095 use Composer\Script\ScriptEvents;
3096 use Composer\Util\Silencer;
3097 use Symfony\Component\Console\Input\InputArgument;
3098 use Symfony\Component\Console\Input\InputInterface;
3099 use Symfony\Component\Console\Input\InputOption;
3100 use Symfony\Component\Console\Output\OutputInterface;
3101 use Symfony\Component\Finder\Finder;
3102 use Composer\Json\JsonFile;
3103 use Composer\Config\JsonConfigSource;
3104 use Composer\Util\Filesystem;
3105 use Composer\Package\Version\VersionParser;
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115 class CreateProjectCommand extends BaseCommand
3116 {
3117
3118
3119
3120 protected $suggestedPackagesReporter;
3121
3122 protected function configure()
3123 {
3124 $this
3125 ->setName('create-project')
3126 ->setDescription('Creates new project from a package into given directory.')
3127 ->setDefinition(array(
3128 new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'),
3129 new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'),
3130 new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
3131 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
3132 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
3133 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
3134 new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
3135 new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
3136 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
3137 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
3138 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
3139 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'),
3140 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
3141 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.'),
3142 new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deleting the vcs folder.'),
3143 new InputOption('remove-vcs', null, InputOption::VALUE_NONE, 'Whether to force deletion of the vcs folder without prompting.'),
3144 new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
3145 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
3146 ))
3147 ->setHelp(<<<EOT
3148 The <info>create-project</info> command creates a new project from a given
3149 package into a new directory. If executed without params and in a directory
3150 with a composer.json file it installs the packages for the current project.
3151
3152 You can use this command to bootstrap new projects or setup a clean
3153 version-controlled installation for developers of your project.
3154
3155 <info>php composer.phar create-project vendor/project target-directory [version]</info>
3156
3157 You can also specify the version with the package name using = or : as separator.
3158
3159 <info>php composer.phar create-project vendor/project:version target-directory</info>
3160
3161 To install unstable packages, either specify the version you want, or use the
3162 --stability=dev (where dev can be one of RC, beta, alpha or dev).
3163
3164 To setup a developer workable version you should create the project using the source
3165 controlled code by appending the <info>'--prefer-source'</info> flag.
3166
3167 To install a package from another repository than the default one you
3168 can pass the <info>'--repository=https://myrepository.org'</info> flag.
3169
3170 EOT
3171 )
3172 ;
3173 }
3174
3175 protected function execute(InputInterface $input, OutputInterface $output)
3176 {
3177 $config = Factory::createConfig();
3178 $io = $this->getIO();
3179
3180 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input, true);
3181
3182 if ($input->getOption('dev')) {
3183 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
3184 }
3185 if ($input->getOption('no-custom-installers')) {
3186 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
3187 $input->setOption('no-plugins', true);
3188 }
3189
3190 return $this->installProject(
3191 $io,
3192 $config,
3193 $input,
3194 $input->getArgument('package'),
3195 $input->getArgument('directory'),
3196 $input->getArgument('version'),
3197 $input->getOption('stability'),
3198 $preferSource,
3199 $preferDist,
3200 !$input->getOption('no-dev'),
3201 $input->getOption('repository') ?: $input->getOption('repository-url'),
3202 $input->getOption('no-plugins'),
3203 $input->getOption('no-scripts'),
3204 $input->getOption('keep-vcs'),
3205 $input->getOption('no-progress'),
3206 $input->getOption('no-install'),
3207 $input->getOption('ignore-platform-reqs'),
3208 !$input->getOption('no-secure-http'),
3209 $input->getOption('remove-vcs')
3210 );
3211 }
3212
3213 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, $keepVcs = false, $noProgress = false, $noInstall = false, $ignorePlatformReqs = false, $secureHttp = true, $removeVcs = false)
3214 {
3215 $oldCwd = getcwd();
3216
3217
3218  $io->loadConfiguration($config);
3219
3220 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
3221
3222 if ($packageName !== null) {
3223 $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $keepVcs, $noProgress, $ignorePlatformReqs, $secureHttp);
3224 } else {
3225 $installedFromVcs = false;
3226 }
3227
3228 $composer = Factory::create($io, null, $disablePlugins);
3229 $composer->getDownloadManager()->setOutputProgress(!$noProgress);
3230
3231 $fs = new Filesystem();
3232
3233 if ($noScripts === false) {
3234
3235  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
3236 }
3237
3238
3239  $config = $composer->getConfig();
3240 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
3241
3242
3243  if ($noInstall === false) {
3244 $installer = Installer::create($io, $composer);
3245 $installer->setPreferSource($preferSource)
3246 ->setPreferDist($preferDist)
3247 ->setDevMode($installDevPackages)
3248 ->setRunScripts(!$noScripts)
3249 ->setIgnorePlatformRequirements($ignorePlatformReqs)
3250 ->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
3251 ->setOptimizeAutoloader($config->get('optimize-autoloader'));
3252
3253 if ($disablePlugins) {
3254 $installer->disablePlugins();
3255 }
3256
3257 $status = $installer->run();
3258 if (0 !== $status) {
3259 return $status;
3260 }
3261 }
3262
3263 $hasVcs = $installedFromVcs;
3264 if (
3265 !$keepVcs
3266 && $installedFromVcs
3267 && (
3268 $removeVcs
3269 || !$io->isInteractive()
3270 || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true)
3271 )
3272 ) {
3273 $finder = new Finder();
3274 $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
3275 foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_') as $vcsName) {
3276 $finder->name($vcsName);
3277 }
3278
3279 try {
3280 $dirs = iterator_to_array($finder);
3281 unset($finder);
3282 foreach ($dirs as $dir) {
3283 if (!$fs->removeDirectory($dir)) {
3284 throw new \RuntimeException('Could not remove '.$dir);
3285 }
3286 }
3287 } catch (\Exception $e) {
3288 $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
3289 }
3290
3291 $hasVcs = false;
3292 }
3293
3294
3295  if (!$hasVcs) {
3296 $package = $composer->getPackage();
3297 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3298 foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
3299 foreach ($package->{'get'.$meta['method']}() as $link) {
3300 if ($link->getPrettyConstraint() === 'self.version') {
3301 $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
3302 }
3303 }
3304 }
3305 }
3306
3307 if ($noScripts === false) {
3308
3309  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
3310 }
3311
3312 chdir($oldCwd);
3313 $vendorComposerDir = $config->get('vendor-dir').'/composer';
3314 if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
3315 Silencer::call('rmdir', $vendorComposerDir);
3316 $vendorDir = $config->get('vendor-dir');
3317 if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
3318 Silencer::call('rmdir', $vendorDir);
3319 }
3320 }
3321
3322 return 0;
3323 }
3324
3325 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, $keepVcs = false, $noProgress = false, $ignorePlatformReqs = false, $secureHttp = true)
3326 {
3327 if (!$secureHttp) {
3328 $config->merge(array('config' => array('secure-http' => false)));
3329 }
3330
3331 if (null === $repository) {
3332 $sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config));
3333 } else {
3334 $sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true);
3335 }
3336
3337 $parser = new VersionParser();
3338 $requirements = $parser->parseNameVersionPairs(array($packageName));
3339 $name = strtolower($requirements[0]['name']);
3340 if (!$packageVersion && isset($requirements[0]['version'])) {
3341 $packageVersion = $requirements[0]['version'];
3342 }
3343
3344 if (null === $stability) {
3345 if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
3346 $stability = $match[1];
3347 } else {
3348 $stability = VersionParser::parseStability($packageVersion);
3349 }
3350 }
3351
3352 $stability = VersionParser::normalizeStability($stability);
3353
3354 if (!isset(BasePackage::$stabilities[$stability])) {
3355 throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
3356 }
3357
3358 $pool = new Pool($stability);
3359 $pool->addRepository($sourceRepo);
3360
3361 $phpVersion = null;
3362 $prettyPhpVersion = null;
3363 if (!$ignorePlatformReqs) {
3364 $platformOverrides = $config->get('platform') ?: array();
3365
3366  $platform = new PlatformRepository(array(), $platformOverrides);
3367 $phpPackage = $platform->findPackage('php', '*');
3368 $phpVersion = $phpPackage->getVersion();
3369 $prettyPhpVersion = $phpPackage->getPrettyVersion();
3370 }
3371
3372
3373  $versionSelector = new VersionSelector($pool);
3374 $package = $versionSelector->findBestCandidate($name, $packageVersion, $phpVersion, $stability);
3375
3376 if (!$package) {
3377 $errorMessage = "Could not find package $name with " . ($packageVersion ? "version $packageVersion" : "stability $stability");
3378 if ($phpVersion && $versionSelector->findBestCandidate($name, $packageVersion, null, $stability)) {
3379 throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version '.$prettyPhpVersion.'.');
3380 }
3381
3382 throw new \InvalidArgumentException($errorMessage .'.');
3383 }
3384
3385 if (null === $directory) {
3386 $parts = explode("/", $name, 2);
3387 $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
3388 }
3389
3390
3391  if (function_exists('pcntl_async_signals')) {
3392 @mkdir($directory, 0777, true);
3393 if ($realDir = realpath($directory)) {
3394 pcntl_async_signals(true);
3395 pcntl_signal(SIGINT, function () use ($realDir) {
3396 $fs = new Filesystem();
3397 $fs->removeDirectory($realDir);
3398 exit(130);
3399 });
3400 }
3401 }
3402
3403 $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')</info>');
3404
3405 if ($disablePlugins) {
3406 $io->writeError('<info>Plugins have been disabled.</info>');
3407 }
3408
3409 if ($package instanceof AliasPackage) {
3410 $package = $package->getAliasOf();
3411 }
3412
3413 if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) {
3414 $package->setSourceReference(substr($package->getPrettyVersion(), 4));
3415 }
3416
3417 $dm = $this->createDownloadManager($io, $config);
3418 $dm->setPreferSource($preferSource)
3419 ->setPreferDist($preferDist)
3420 ->setOutputProgress(!$noProgress);
3421
3422 $projectInstaller = new ProjectInstaller($directory, $dm);
3423 $im = $this->createInstallationManager();
3424 $im->addInstaller($projectInstaller);
3425 $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
3426 $im->notifyInstalls($io);
3427
3428
3429  $this->suggestedPackagesReporter->addSuggestionsFromPackage($package);
3430
3431 $installedFromVcs = 'source' === $package->getInstallationSource();
3432
3433 $io->writeError('<info>Created project in ' . $directory . '</info>');
3434 chdir($directory);
3435
3436 $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
3437 putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
3438
3439 return $installedFromVcs;
3440 }
3441
3442 protected function createDownloadManager(IOInterface $io, Config $config)
3443 {
3444 $factory = new Factory();
3445
3446 return $factory->createDownloadManager($io, $config);
3447 }
3448
3449 protected function createInstallationManager()
3450 {
3451 return new InstallationManager();
3452 }
3453 }
3454 <?php
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466 namespace Composer\Command;
3467
3468 use Symfony\Component\Console\Input\InputInterface;
3469 use Symfony\Component\Console\Output\OutputInterface;
3470
3471
3472
3473
3474 class DependsCommand extends BaseDependencyCommand
3475 {
3476
3477
3478
3479 protected function configure()
3480 {
3481 parent::configure();
3482
3483 $this
3484 ->setName('depends')
3485 ->setAliases(array('why'))
3486 ->setDescription('Shows which packages cause the given package to be installed.')
3487 ->setHelp(<<<EOT
3488 Displays detailed information about where a package is referenced.
3489
3490 <info>php composer.phar depends composer/composer</info>
3491
3492 EOT
3493 )
3494 ;
3495 }
3496
3497
3498
3499
3500
3501
3502
3503
3504 protected function execute(InputInterface $input, OutputInterface $output)
3505 {
3506 return parent::doExecute($input, $output, false);
3507 }
3508 }
3509 <?php
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521 namespace Composer\Command;
3522
3523 use Composer\Composer;
3524 use Composer\Factory;
3525 use Composer\Config;
3526 use Composer\Downloader\TransportException;
3527 use Composer\Plugin\CommandEvent;
3528 use Composer\Plugin\PluginEvents;
3529 use Composer\Util\ConfigValidator;
3530 use Composer\Util\IniHelper;
3531 use Composer\Util\ProcessExecutor;
3532 use Composer\Util\RemoteFilesystem;
3533 use Composer\Util\StreamContextFactory;
3534 use Composer\SelfUpdate\Keys;
3535 use Composer\SelfUpdate\Versions;
3536 use Composer\IO\NullIO;
3537 use Symfony\Component\Console\Input\InputInterface;
3538 use Symfony\Component\Console\Output\OutputInterface;
3539
3540
3541
3542
3543 class DiagnoseCommand extends BaseCommand
3544 {
3545
3546 protected $rfs;
3547
3548
3549 protected $process;
3550
3551
3552 protected $exitCode = 0;
3553
3554 protected function configure()
3555 {
3556 $this
3557 ->setName('diagnose')
3558 ->setDescription('Diagnoses the system to identify common errors.')
3559 ->setHelp(<<<EOT
3560 The <info>diagnose</info> command checks common errors to help debugging problems.
3561
3562 The process exit code will be 1 in case of warnings and 2 for errors.
3563
3564 EOT
3565 )
3566 ;
3567 }
3568
3569
3570
3571
3572 protected function execute(InputInterface $input, OutputInterface $output)
3573 {
3574 $composer = $this->getComposer(false);
3575 $io = $this->getIO();
3576
3577 if ($composer) {
3578 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
3579 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
3580
3581 $io->write('Checking composer.json: ', false);
3582 $this->outputResult($this->checkComposerSchema());
3583 }
3584
3585 if ($composer) {
3586 $config = $composer->getConfig();
3587 } else {
3588 $config = Factory::createConfig();
3589 }
3590
3591 $config->merge(array('config' => array('secure-http' => false)));
3592 $config->prohibitUrlByConfig('http://packagist.org', new NullIO);
3593
3594 $this->rfs = Factory::createRemoteFilesystem($io, $config);
3595 $this->process = new ProcessExecutor($io);
3596
3597 $io->write('Checking platform settings: ', false);
3598 $this->outputResult($this->checkPlatform());
3599
3600 $io->write('Checking git settings: ', false);
3601 $this->outputResult($this->checkGit());
3602
3603 $io->write('Checking http connectivity to packagist: ', false);
3604 $this->outputResult($this->checkHttp('http', $config));
3605
3606 $io->write('Checking https connectivity to packagist: ', false);
3607 $this->outputResult($this->checkHttp('https', $config));
3608
3609 $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
3610 if (!empty($opts['http']['proxy'])) {
3611 $io->write('Checking HTTP proxy: ', false);
3612 $this->outputResult($this->checkHttpProxy());
3613 $io->write('Checking HTTP proxy support for request_fulluri: ', false);
3614 $this->outputResult($this->checkHttpProxyFullUriRequestParam());
3615 $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
3616 $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
3617 }
3618
3619 if ($oauth = $config->get('github-oauth')) {
3620 foreach ($oauth as $domain => $token) {
3621 $io->write('Checking '.$domain.' oauth access: ', false);
3622 $this->outputResult($this->checkGithubOauth($domain, $token));
3623 }
3624 } else {
3625 $io->write('Checking github.com rate limit: ', false);
3626 try {
3627 $rate = $this->getGithubRateLimit('github.com');
3628 $this->outputResult(true);
3629 if (10 > $rate['remaining']) {
3630 $io->write('<warning>WARNING</warning>');
3631 $io->write(sprintf(
3632 '<comment>Github has a rate limit on their API. '
3633 . 'You currently have <options=bold>%u</options=bold> '
3634 . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
3635 . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
3636 . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>',
3637 $rate['remaining'],
3638 $rate['limit']
3639 ));
3640 }
3641 } catch (\Exception $e) {
3642 if ($e instanceof TransportException && $e->getCode() === 401) {
3643 $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
3644 } else {
3645 $this->outputResult($e);
3646 }
3647 }
3648 }
3649
3650 $io->write('Checking disk free space: ', false);
3651 $this->outputResult($this->checkDiskSpace($config));
3652
3653 if ('phar:' === substr(__FILE__, 0, 5)) {
3654 $io->write('Checking pubkeys: ', false);
3655 $this->outputResult($this->checkPubKeys($config));
3656
3657 $io->write('Checking composer version: ', false);
3658 $this->outputResult($this->checkVersion($config));
3659 }
3660
3661 $io->write(sprintf('Composer version: <comment>%s</comment>', Composer::VERSION));
3662
3663 $io->write(sprintf('PHP version: <comment>%s</comment>', PHP_VERSION));
3664
3665 if (defined('PHP_BINARY')) {
3666 $io->write(sprintf('PHP binary path: <comment>%s</comment>', PHP_BINARY));
3667 }
3668
3669 return $this->exitCode;
3670 }
3671
3672 private function checkComposerSchema()
3673 {
3674 $validator = new ConfigValidator($this->getIO());
3675 list($errors, , $warnings) = $validator->validate(Factory::getComposerFile());
3676
3677 if ($errors || $warnings) {
3678 $messages = array(
3679 'error' => $errors,
3680 'warning' => $warnings,
3681 );
3682
3683 $output = '';
3684 foreach ($messages as $style => $msgs) {
3685 foreach ($msgs as $msg) {
3686 $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . PHP_EOL;
3687 }
3688 }
3689
3690 return rtrim($output);
3691 }
3692
3693 return true;
3694 }
3695
3696 private function checkGit()
3697 {
3698 $this->process->execute('git config color.ui', $output);
3699 if (strtolower(trim($output)) === 'always') {
3700 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>';
3701 }
3702
3703 return true;
3704 }
3705
3706 private function checkHttp($proto, Config $config)
3707 {
3708 $disableTls = false;
3709 $result = array();
3710 if ($proto === 'https' && $config->get('disable-tls') === true) {
3711 $disableTls = true;
3712 $result[] = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
3713 }
3714 if ($proto === 'https' && !extension_loaded('openssl') && !$disableTls) {
3715 $result[] = '<error>Composer is configured to use SSL/TLS protection but the openssl extension is not available.</error>';
3716 }
3717
3718 try {
3719 $this->rfs->getContents('packagist.org', $proto . '://packagist.org/packages.json', false);
3720 } catch (TransportException $e) {
3721 if (false !== strpos($e->getMessage(), 'cafile')) {
3722 $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
3723 $result[] = '<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>';
3724 $result[] = '<error>You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option.</error>';
3725 } else {
3726 array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage());
3727 }
3728 }
3729
3730 if (count($result) > 0) {
3731 return $result;
3732 }
3733
3734 return true;
3735 }
3736
3737 private function checkHttpProxy()
3738 {
3739 $protocol = extension_loaded('openssl') ? 'https' : 'http';
3740 try {
3741 $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://packagist.org/packages.json', false), true);
3742 $hash = reset($json['provider-includes']);
3743 $hash = $hash['sha256'];
3744 $path = str_replace('%hash%', $hash, key($json['provider-includes']));
3745 $provider = $this->rfs->getContents('packagist.org', $protocol . '://packagist.org/'.$path, false);
3746
3747 if (hash('sha256', $provider) !== $hash) {
3748 return 'It seems that your proxy is modifying http traffic on the fly';
3749 }
3750 } catch (\Exception $e) {
3751 return $e;
3752 }
3753
3754 return true;
3755 }
3756
3757
3758
3759
3760
3761
3762
3763
3764 private function checkHttpProxyFullUriRequestParam()
3765 {
3766 $url = 'http://packagist.org/packages.json';
3767 try {
3768 $this->rfs->getContents('packagist.org', $url, false);
3769 } catch (TransportException $e) {
3770 try {
3771 $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
3772 } catch (TransportException $e) {
3773 return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
3774 }
3775
3776 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"';
3777 }
3778
3779 return true;
3780 }
3781
3782
3783
3784
3785
3786
3787
3788
3789 private function checkHttpsProxyFullUriRequestParam()
3790 {
3791 if (!extension_loaded('openssl')) {
3792 return 'You need the openssl extension installed for this check';
3793 }
3794
3795 $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
3796 try {
3797 $this->rfs->getContents('github.com', $url, false);
3798 } catch (TransportException $e) {
3799 try {
3800 $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
3801 } catch (TransportException $e) {
3802 return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
3803 }
3804
3805 return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
3806 }
3807
3808 return true;
3809 }
3810
3811 private function checkGithubOauth($domain, $token)
3812 {
3813 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3814 try {
3815 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
3816
3817 return $this->rfs->getContents($domain, $url, false, array(
3818 'retry-auth-failure' => false,
3819 )) ? true : 'Unexpected error';
3820 } catch (\Exception $e) {
3821 if ($e instanceof TransportException && $e->getCode() === 401) {
3822 return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
3823 }
3824
3825 return $e;
3826 }
3827 }
3828
3829
3830
3831
3832
3833
3834
3835 private function getGithubRateLimit($domain, $token = null)
3836 {
3837 if ($token) {
3838 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3839 }
3840
3841 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
3842 $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
3843 $data = json_decode($json, true);
3844
3845 return $data['resources']['core'];
3846 }
3847
3848 private function checkDiskSpace($config)
3849 {
3850 $minSpaceFree = 1024 * 1024;
3851 if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
3852 || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
3853 ) {
3854 return '<error>The disk hosting '.$dir.' is full</error>';
3855 }
3856
3857 return true;
3858 }
3859
3860 private function checkPubKeys($config)
3861 {
3862 $home = $config->get('home');
3863 $errors = array();
3864 $io = $this->getIO();
3865
3866 if (file_exists($home.'/keys.tags.pub') && file_exists($home.'/keys.dev.pub')) {
3867 $io->write('');
3868 }
3869
3870 if (file_exists($home.'/keys.tags.pub')) {
3871 $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.tags.pub'));
3872 } else {
3873 $errors[] = '<error>Missing pubkey for tags verification</error>';
3874 }
3875
3876 if (file_exists($home.'/keys.dev.pub')) {
3877 $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.dev.pub'));
3878 } else {
3879 $errors[] = '<error>Missing pubkey for dev verification</error>';
3880 }
3881
3882 if ($errors) {
3883 $errors[] = '<error>Run composer self-update --update-keys to set them up</error>';
3884 }
3885
3886 return $errors ?: true;
3887 }
3888
3889 private function checkVersion($config)
3890 {
3891 $versionsUtil = new Versions($config, $this->rfs);
3892 $latest = $versionsUtil->getLatest();
3893
3894 if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
3895 return '<comment>You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')</comment>';
3896 }
3897
3898 return true;
3899 }
3900
3901
3902
3903
3904 private function outputResult($result)
3905 {
3906 $io = $this->getIO();
3907 if (true === $result) {
3908 $io->write('<info>OK</info>');
3909
3910 return;
3911 }
3912
3913 $hadError = false;
3914 if ($result instanceof \Exception) {
3915 $result = '<error>['.get_class($result).'] '.$result->getMessage().'</error>';
3916 }
3917
3918 if (!$result) {
3919
3920  $hadError = true;
3921 } else {
3922 if (!is_array($result)) {
3923 $result = array($result);
3924 }
3925 foreach ($result as $message) {
3926 if (false !== strpos($message, '<error>')) {
3927 $hadError = true;
3928 }
3929 }
3930 }
3931
3932 if ($hadError) {
3933 $io->write('<error>FAIL</error>');
3934 $this->exitCode = 2;
3935 } else {
3936 $io->write('<warning>WARNING</warning>');
3937 $this->exitCode = 1;
3938 }
3939
3940 if ($result) {
3941 foreach ($result as $message) {
3942 $io->write($message);
3943 }
3944 }
3945 }
3946
3947 private function checkPlatform()
3948 {
3949 $output = '';
3950 $out = function ($msg, $style) use (&$output) {
3951 $output .= '<'.$style.'>'.$msg.'</'.$style.'>'.PHP_EOL;
3952 };
3953
3954
3955  $errors = array();
3956 $warnings = array();
3957 $displayIniMessage = false;
3958
3959 $iniMessage = PHP_EOL.PHP_EOL.IniHelper::getMessage();
3960 $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.';
3961
3962 if (!function_exists('json_decode')) {
3963 $errors['json'] = true;
3964 }
3965
3966 if (!extension_loaded('Phar')) {
3967 $errors['phar'] = true;
3968 }
3969
3970 if (!extension_loaded('filter')) {
3971 $errors['filter'] = true;
3972 }
3973
3974 if (!extension_loaded('hash')) {
3975 $errors['hash'] = true;
3976 }
3977
3978 if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
3979 $errors['iconv_mbstring'] = true;
3980 }
3981
3982 if (!ini_get('allow_url_fopen')) {
3983 $errors['allow_url_fopen'] = true;
3984 }
3985
3986 if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
3987 $errors['ioncube'] = ioncube_loader_version();
3988 }
3989
3990 if (PHP_VERSION_ID < 50302) {
3991 $errors['php'] = PHP_VERSION;
3992 }
3993
3994 if (!isset($errors['php']) && PHP_VERSION_ID < 50304) {
3995 $warnings['php'] = PHP_VERSION;
3996 }
3997
3998 if (!extension_loaded('openssl')) {
3999 $errors['openssl'] = true;
4000 }
4001
4002 if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) {
4003 $warnings['openssl_version'] = true;
4004 }
4005
4006 if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) {
4007 $warnings['apc_cli'] = true;
4008 }
4009
4010 if (!extension_loaded('zlib')) {
4011 $warnings['zlib'] = true;
4012 }
4013
4014 ob_start();
4015 phpinfo(INFO_GENERAL);
4016 $phpinfo = ob_get_clean();
4017 if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
4018 $configure = $match[1];
4019
4020 if (false !== strpos($configure, '--enable-sigchild')) {
4021 $warnings['sigchild'] = true;
4022 }
4023
4024 if (false !== strpos($configure, '--with-curlwrappers')) {
4025 $warnings['curlwrappers'] = true;
4026 }
4027 }
4028
4029 if (ini_get('xdebug.profiler_enabled')) {
4030 $warnings['xdebug_profile'] = true;
4031 } elseif (extension_loaded('xdebug')) {
4032 $warnings['xdebug_loaded'] = true;
4033 }
4034
4035 if (!empty($errors)) {
4036 foreach ($errors as $error => $current) {
4037 switch ($error) {
4038 case 'json':
4039 $text = PHP_EOL."The json extension is missing.".PHP_EOL;
4040 $text .= "Install it or recompile php without --disable-json";
4041 break;
4042
4043 case 'phar':
4044 $text = PHP_EOL."The phar extension is missing.".PHP_EOL;
4045 $text .= "Install it or recompile php without --disable-phar";
4046 break;
4047
4048 case 'filter':
4049 $text = PHP_EOL."The filter extension is missing.".PHP_EOL;
4050 $text .= "Install it or recompile php without --disable-filter";
4051 break;
4052
4053 case 'hash':
4054 $text = PHP_EOL."The hash extension is missing.".PHP_EOL;
4055 $text .= "Install it or recompile php without --disable-hash";
4056 break;
4057
4058 case 'iconv_mbstring':
4059 $text = PHP_EOL."The iconv OR mbstring extension is required and both are missing.".PHP_EOL;
4060 $text .= "Install either of them or recompile php without --disable-iconv";
4061 break;
4062
4063 case 'unicode':
4064 $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
4065 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4066 $text .= "    detect_unicode = Off";
4067 $displayIniMessage = true;
4068 break;
4069
4070 case 'suhosin':
4071 $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
4072 $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;
4073 $text .= "    suhosin.executor.include.whitelist = phar ".$current;
4074 $displayIniMessage = true;
4075 break;
4076
4077 case 'php':
4078 $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
4079 break;
4080
4081 case 'allow_url_fopen':
4082 $text = PHP_EOL."The allow_url_fopen setting is incorrect.".PHP_EOL;
4083 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4084 $text .= "    allow_url_fopen = On";
4085 $displayIniMessage = true;
4086 break;
4087
4088 case 'ioncube':
4089 $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
4090 $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;
4091 $text .= "    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
4092 $displayIniMessage = true;
4093 break;
4094
4095 case 'openssl':
4096 $text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
4097 $text .= "If possible you should enable it or recompile php with --with-openssl";
4098 break;
4099 }
4100 $out($text, 'error');
4101 }
4102
4103 $output .= PHP_EOL;
4104 }
4105
4106 if (!empty($warnings)) {
4107 foreach ($warnings as $warning => $current) {
4108 switch ($warning) {
4109 case 'apc_cli':
4110 $text = "The apc.enable_cli setting is incorrect.".PHP_EOL;
4111 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4112 $text .= "  apc.enable_cli = Off";
4113 $displayIniMessage = true;
4114 break;
4115
4116 case 'zlib':
4117 $text = 'The zlib extension is not loaded, this can slow down Composer a lot.'.PHP_EOL;
4118 $text .= 'If possible, enable it or recompile php with --with-zlib'.PHP_EOL;
4119 $displayIniMessage = true;
4120 break;
4121
4122 case 'sigchild':
4123 $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms.".PHP_EOL;
4124 $text .= "Recompile it without this flag if possible, see also:".PHP_EOL;
4125 $text .= "  https://bugs.php.net/bug.php?id=22999";
4126 break;
4127
4128 case 'curlwrappers':
4129 $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.".PHP_EOL;
4130 $text .= " Recompile it without this flag if possible";
4131 break;
4132
4133 case 'php':
4134 $text = "Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL;
4135 $text .= " Composer works with 5.3.2+ for most people, but there might be edge case issues.";
4136 break;
4137
4138 case 'openssl_version':
4139
4140  $opensslVersion = strstr(trim(strstr(OPENSSL_VERSION_TEXT, ' ')), ' ', true);
4141 $opensslVersion = $opensslVersion ?: OPENSSL_VERSION_TEXT;
4142
4143 $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1.".PHP_EOL;
4144 $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above.";
4145 break;
4146
4147 case 'xdebug_loaded':
4148 $text = "The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL;
4149 $text .= " Disabling it when using Composer is recommended.";
4150 break;
4151
4152 case 'xdebug_profile':
4153 $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL;
4154 $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL;
4155 $text .= "  xdebug.profiler_enabled = 0";
4156 $displayIniMessage = true;
4157 break;
4158 }
4159 $out($text, 'comment');
4160 }
4161 }
4162
4163 if ($displayIniMessage) {
4164 $out($iniMessage, 'comment');
4165 }
4166
4167 return !$warnings && !$errors ? true : $output;
4168 }
4169 }
4170 <?php
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182 namespace Composer\Command;
4183
4184 use Composer\Plugin\CommandEvent;
4185 use Composer\Plugin\PluginEvents;
4186 use Symfony\Component\Console\Input\InputInterface;
4187 use Symfony\Component\Console\Input\InputOption;
4188 use Symfony\Component\Console\Output\OutputInterface;
4189
4190
4191
4192
4193 class DumpAutoloadCommand extends BaseCommand
4194 {
4195 protected function configure()
4196 {
4197 $this
4198 ->setName('dump-autoload')
4199 ->setAliases(array('dumpautoload'))
4200 ->setDescription('Dumps the autoloader.')
4201 ->setDefinition(array(
4202 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
4203 new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
4204 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
4205 new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
4206 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
4207 ))
4208 ->setHelp(<<<EOT
4209 <info>php composer.phar dump-autoload</info>
4210 EOT
4211 )
4212 ;
4213 }
4214
4215 protected function execute(InputInterface $input, OutputInterface $output)
4216 {
4217 $composer = $this->getComposer();
4218
4219 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
4220 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
4221
4222 $installationManager = $composer->getInstallationManager();
4223 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
4224 $package = $composer->getPackage();
4225 $config = $composer->getConfig();
4226
4227 $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
4228 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
4229 $apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
4230
4231 if ($authoritative) {
4232 $this->getIO()->writeError('<info>Generating optimized autoload files (authoritative)</info>');
4233 } elseif ($optimize) {
4234 $this->getIO()->writeError('<info>Generating optimized autoload files</info>');
4235 } else {
4236 $this->getIO()->writeError('<info>Generating autoload files</info>');
4237 }
4238
4239 $generator = $composer->getAutoloadGenerator();
4240 $generator->setDevMode(!$input->getOption('no-dev'));
4241 $generator->setClassMapAuthoritative($authoritative);
4242 $generator->setApcu($apcu);
4243 $generator->setRunScripts(!$input->getOption('no-scripts'));
4244 $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
4245 }
4246 }
4247 <?php
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259 namespace Composer\Command;
4260
4261 use Symfony\Component\Console\Input\InputInterface;
4262 use Symfony\Component\Console\Input\InputOption;
4263 use Symfony\Component\Console\Output\OutputInterface;
4264 use Symfony\Component\Console\Input\InputArgument;
4265
4266
4267
4268
4269 class ExecCommand extends BaseCommand
4270 {
4271 protected function configure()
4272 {
4273 $this
4274 ->setName('exec')
4275 ->setDescription('Executes a vendored binary/script.')
4276 ->setDefinition(array(
4277 new InputOption('list', 'l', InputOption::VALUE_NONE),
4278 new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit'),
4279 new InputArgument(
4280 'args',
4281 InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
4282 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
4283 ),
4284 ))
4285 ;
4286 }
4287
4288 protected function execute(InputInterface $input, OutputInterface $output)
4289 {
4290 $composer = $this->getComposer();
4291 $binDir = $composer->getConfig()->get('bin-dir');
4292 if ($input->getOption('list') || !$input->getArgument('binary')) {
4293 $bins = glob($binDir . '/*');
4294 $bins = array_merge($bins, array_map(function ($e) {
4295 return "$e (local)";
4296 }, $composer->getPackage()->getBinaries()));
4297
4298 if (!$bins) {
4299 throw new \RuntimeException("No binaries found in composer.json or in bin-dir ($binDir)");
4300 }
4301
4302 $this->getIO()->write(<<<EOT
4303 <comment>Available binaries:</comment>
4304 EOT
4305 );
4306
4307 foreach ($bins as $bin) {
4308
4309  if (isset($previousBin) && $bin === $previousBin.'.bat') {
4310 continue;
4311 }
4312
4313 $previousBin = $bin;
4314 $bin = basename($bin);
4315 $this->getIO()->write(<<<EOT
4316 <info>- $bin</info>
4317 EOT
4318 );
4319 }
4320
4321 return 0;
4322 }
4323
4324 $binary = $input->getArgument('binary');
4325
4326 $dispatcher = $composer->getEventDispatcher();
4327 $dispatcher->addListener('__exec_command', $binary);
4328 if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
4329 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
4330 }
4331
4332 return $dispatcher->dispatchScript('__exec_command', true, $input->getArgument('args'));
4333 }
4334 }
4335 <?php
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347 namespace Composer\Command;
4348
4349 use Composer\Factory;
4350 use Symfony\Component\Console\Input\InputInterface;
4351 use Symfony\Component\Console\Input\InputArgument;
4352 use Symfony\Component\Console\Input\StringInput;
4353 use Symfony\Component\Console\Output\OutputInterface;
4354
4355
4356
4357
4358 class GlobalCommand extends BaseCommand
4359 {
4360 protected function configure()
4361 {
4362 $this
4363 ->setName('global')
4364 ->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME).')
4365 ->setDefinition(array(
4366 new InputArgument('command-name', InputArgument::REQUIRED, ''),
4367 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
4368 ))
4369 ->setHelp(<<<EOT
4370 Use this command as a wrapper to run other Composer commands
4371 within the global context of COMPOSER_HOME.
4372
4373 You can use this to install CLI utilities globally, all you need
4374 is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.
4375
4376 COMPOSER_HOME is c:\Users\<user>\AppData\Roaming\Composer on Windows
4377 and /home/<user>/.composer on unix systems.
4378
4379 If your system uses freedesktop.org standards, then it will first check
4380 XDG_CONFIG_HOME or default to /home/<user>/.config/composer
4381
4382 Note: This path may vary depending on customizations to bin-dir in
4383 composer.json or the environmental variable COMPOSER_BIN_DIR.
4384
4385 EOT
4386 )
4387 ;
4388 }
4389
4390 public function run(InputInterface $input, OutputInterface $output)
4391 {
4392
4393  $tokens = preg_split('{\s+}', $input->__toString());
4394 $args = array();
4395 foreach ($tokens as $token) {
4396 if ($token && $token[0] !== '-') {
4397 $args[] = $token;
4398 if (count($args) >= 2) {
4399 break;
4400 }
4401 }
4402 }
4403
4404
4405  if (count($args) < 2) {
4406 return parent::run($input, $output);
4407 }
4408
4409
4410  $config = Factory::createConfig();
4411 chdir($config->get('home'));
4412 $this->getIO()->writeError('<info>Changed current directory to '.$config->get('home').'</info>');
4413
4414
4415  $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
4416 $this->getApplication()->resetComposer();
4417
4418 return $this->getApplication()->run($input, $output);
4419 }
4420
4421
4422
4423
4424 public function isProxyCommand()
4425 {
4426 return true;
4427 }
4428 }
4429 <?php
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441 namespace Composer\Command;
4442
4443 use Composer\Package\CompletePackageInterface;
4444 use Composer\Repository\RepositoryInterface;
4445 use Composer\Repository\ArrayRepository;
4446 use Composer\Repository\RepositoryFactory;
4447 use Composer\Util\Platform;
4448 use Composer\Util\ProcessExecutor;
4449 use Symfony\Component\Console\Input\InputArgument;
4450 use Symfony\Component\Console\Input\InputOption;
4451 use Symfony\Component\Console\Input\InputInterface;
4452 use Symfony\Component\Console\Output\OutputInterface;
4453
4454
4455
4456
4457 class HomeCommand extends BaseCommand
4458 {
4459
4460
4461
4462 protected function configure()
4463 {
4464 $this
4465 ->setName('browse')
4466 ->setAliases(array('home'))
4467 ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
4468 ->setDefinition(array(
4469 new InputArgument('packages', InputArgument::IS_ARRAY, 'Package(s) to browse to.'),
4470 new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
4471 new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
4472 ))
4473 ->setHelp(<<<EOT
4474 The home command opens or shows a package's repository URL or
4475 homepage in your default browser.
4476
4477 To open the homepage by default, use -H or --homepage.
4478 To show instead of open the repository or homepage URL, use -s or --show.
4479 EOT
4480 );
4481 }
4482
4483
4484
4485
4486 protected function execute(InputInterface $input, OutputInterface $output)
4487 {
4488 $repos = $this->initializeRepos();
4489 $io = $this->getIO();
4490 $return = 0;
4491
4492 $packages = $input->getArgument('packages');
4493 if (!$packages) {
4494 $io->writeError('No package specified, opening homepage for the root package');
4495 $packages = array($this->getComposer()->getPackage()->getName());
4496 }
4497
4498 foreach ($packages as $packageName) {
4499 $handled = false;
4500 $packageExists = false;
4501 foreach ($repos as $repo) {
4502 foreach ($repo->findPackages($packageName) as $package) {
4503 $packageExists = true;
4504 if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
4505 $handled = true;
4506 break 2;
4507 }
4508 }
4509 }
4510
4511 if (!$packageExists) {
4512 $return = 1;
4513 $io->writeError('<warning>Package '.$packageName.' not found</warning>');
4514 }
4515
4516 if (!$handled) {
4517 $return = 1;
4518 $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
4519 }
4520 }
4521
4522 return $return;
4523 }
4524
4525 private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
4526 {
4527 $support = $package->getSupport();
4528 $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
4529 if (!$url || $showHomepage) {
4530 $url = $package->getHomepage();
4531 }
4532
4533 if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
4534 return false;
4535 }
4536
4537 if ($showOnly) {
4538 $this->getIO()->write(sprintf('<info>%s</info>', $url));
4539 } else {
4540 $this->openBrowser($url);
4541 }
4542
4543 return true;
4544 }
4545
4546
4547
4548
4549
4550
4551 private function openBrowser($url)
4552 {
4553 $url = ProcessExecutor::escape($url);
4554
4555 $process = new ProcessExecutor($this->getIO());
4556 if (Platform::isWindows()) {
4557 return $process->execute('start "web" explorer "' . $url . '"', $output);
4558 }
4559
4560 $linux = $process->execute('which xdg-open', $output);
4561 $osx = $process->execute('which open', $output);
4562
4563 if (0 === $linux) {
4564 $process->execute('xdg-open ' . $url, $output);
4565 } elseif (0 === $osx) {
4566 $process->execute('open ' . $url, $output);
4567 } else {
4568 $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
4569 }
4570 }
4571
4572
4573
4574
4575
4576
4577
4578
4579 private function initializeRepos()
4580 {
4581 $composer = $this->getComposer(false);
4582
4583 if ($composer) {
4584 return array_merge(
4585 array(new ArrayRepository(array($composer->getPackage()))), 
4586  array($composer->getRepositoryManager()->getLocalRepository()), 
4587  $composer->getRepositoryManager()->getRepositories() 
4588  );
4589 }
4590
4591 return RepositoryFactory::defaultRepos($this->getIO());
4592 }
4593 }
4594 <?php
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606 namespace Composer\Command;
4607
4608 use Composer\DependencyResolver\Pool;
4609 use Composer\Factory;
4610 use Composer\Json\JsonFile;
4611 use Composer\Package\BasePackage;
4612 use Composer\Package\Version\VersionParser;
4613 use Composer\Package\Version\VersionSelector;
4614 use Composer\Repository\CompositeRepository;
4615 use Composer\Repository\PlatformRepository;
4616 use Composer\Repository\RepositoryFactory;
4617 use Composer\Util\ProcessExecutor;
4618 use Symfony\Component\Console\Input\InputInterface;
4619 use Symfony\Component\Console\Input\InputOption;
4620 use Symfony\Component\Console\Output\OutputInterface;
4621 use Symfony\Component\Process\ExecutableFinder;
4622 use Symfony\Component\Process\Process;
4623
4624
4625
4626
4627
4628 class InitCommand extends BaseCommand
4629 {
4630
4631 protected $repos;
4632
4633
4634 private $gitConfig;
4635
4636
4637 private $pools;
4638
4639
4640
4641
4642 protected function configure()
4643 {
4644 $this
4645 ->setName('init')
4646 ->setDescription('Creates a basic composer.json file in current directory.')
4647 ->setDefinition(array(
4648 new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
4649 new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
4650 new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
4651
4652  new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of package (e.g. library, project, metapackage, composer-plugin)'),
4653 new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
4654 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"'),
4655 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"'),
4656 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
4657 new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
4658 new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
4659 ))
4660 ->setHelp(<<<EOT
4661 The <info>init</info> command creates a basic composer.json file
4662 in the current directory.
4663
4664 <info>php composer.phar init</info>
4665
4666 EOT
4667 )
4668 ;
4669 }
4670
4671
4672
4673
4674 protected function execute(InputInterface $input, OutputInterface $output)
4675 {
4676 $io = $this->getIO();
4677
4678 $whitelist = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license');
4679 $options = array_filter(array_intersect_key($input->getOptions(), array_flip($whitelist)));
4680
4681 if (isset($options['author'])) {
4682 $options['authors'] = $this->formatAuthors($options['author']);
4683 unset($options['author']);
4684 }
4685
4686 $repositories = $input->getOption('repository');
4687 if ($repositories) {
4688 $config = Factory::createConfig($io);
4689 foreach ($repositories as $repo) {
4690 $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
4691 }
4692 }
4693
4694 if (isset($options['stability'])) {
4695 $options['minimum-stability'] = $options['stability'];
4696 unset($options['stability']);
4697 }
4698
4699 $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass;
4700 if (array() === $options['require']) {
4701 $options['require'] = new \stdClass;
4702 }
4703
4704 if (isset($options['require-dev'])) {
4705 $options['require-dev'] = $this->formatRequirements($options['require-dev']);
4706 if (array() === $options['require-dev']) {
4707 $options['require-dev'] = new \stdClass;
4708 }
4709 }
4710
4711 $file = new JsonFile(Factory::getComposerFile());
4712 $json = $file->encode($options);
4713
4714 if ($input->isInteractive()) {
4715 $io->writeError(array('', $json, ''));
4716 if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
4717 $io->writeError('<error>Command aborted</error>');
4718
4719 return 1;
4720 }
4721 }
4722
4723 $file->write($options);
4724
4725 if ($input->isInteractive() && is_dir('.git')) {
4726 $ignoreFile = realpath('.gitignore');
4727
4728 if (false === $ignoreFile) {
4729 $ignoreFile = realpath('.') . '/.gitignore';
4730 }
4731
4732 if (!$this->hasVendorIgnore($ignoreFile)) {
4733 $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
4734
4735 if ($io->askConfirmation($question, true)) {
4736 $this->addVendorIgnore($ignoreFile);
4737 }
4738 }
4739 }
4740 }
4741
4742
4743
4744
4745 protected function interact(InputInterface $input, OutputInterface $output)
4746 {
4747 $git = $this->getGitConfig();
4748 $io = $this->getIO();
4749 $formatter = $this->getHelperSet()->get('formatter');
4750
4751
4752  $repositories = $input->getOption('repository');
4753 if ($repositories) {
4754 $config = Factory::createConfig($io);
4755 $repos = array(new PlatformRepository);
4756 foreach ($repositories as $repo) {
4757 $repos[] = RepositoryFactory::fromString($io, $config, $repo);
4758 }
4759 $repos[] = RepositoryFactory::createRepo($io, $config, array(
4760 'type' => 'composer',
4761 'url' => 'https://packagist.org',
4762 ));
4763
4764 $this->repos = new CompositeRepository($repos);
4765 unset($repos, $config, $repositories);
4766 }
4767
4768 $io->writeError(array(
4769 '',
4770 $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
4771 '',
4772 ));
4773
4774
4775  $io->writeError(array(
4776 '',
4777 'This command will guide you through creating your composer.json config.',
4778 '',
4779 ));
4780
4781 $cwd = realpath(".");
4782
4783 if (!$name = $input->getOption('name')) {
4784 $name = basename($cwd);
4785 $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
4786 $name = strtolower($name);
4787 if (!empty($_SERVER['COMPOSER_DEFAULT_VENDOR'])) {
4788 $name = $_SERVER['COMPOSER_DEFAULT_VENDOR'] . '/' . $name;
4789 } elseif (isset($git['github.user'])) {
4790 $name = $git['github.user'] . '/' . $name;
4791 } elseif (!empty($_SERVER['USERNAME'])) {
4792 $name = $_SERVER['USERNAME'] . '/' . $name;
4793 } elseif (!empty($_SERVER['USER'])) {
4794 $name = $_SERVER['USER'] . '/' . $name;
4795 } elseif (get_current_user()) {
4796 $name = get_current_user() . '/' . $name;
4797 } else {
4798
4799  $name = $name . '/' . $name;
4800 }
4801 $name = strtolower($name);
4802 } else {
4803 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $name)) {
4804 throw new \InvalidArgumentException(
4805 '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_.-]+'
4806 );
4807 }
4808 }
4809
4810 $name = $io->askAndValidate(
4811 'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
4812 function ($value) use ($name) {
4813 if (null === $value) {
4814 return $name;
4815 }
4816
4817 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $value)) {
4818 throw new \InvalidArgumentException(
4819 '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_.-]+'
4820 );
4821 }
4822
4823 return $value;
4824 },
4825 null,
4826 $name
4827 );
4828 $input->setOption('name', $name);
4829
4830 $description = $input->getOption('description') ?: false;
4831 $description = $io->ask(
4832 'Description [<comment>'.$description.'</comment>]: ',
4833 $description
4834 );
4835 $input->setOption('description', $description);
4836
4837 if (null === $author = $input->getOption('author')) {
4838 if (!empty($_SERVER['COMPOSER_DEFAULT_AUTHOR'])) {
4839 $author_name = $_SERVER['COMPOSER_DEFAULT_AUTHOR'];
4840 } elseif (isset($git['user.name'])) {
4841 $author_name = $git['user.name'];
4842 }
4843
4844 if (!empty($_SERVER['COMPOSER_DEFAULT_EMAIL'])) {
4845 $author_email = $_SERVER['COMPOSER_DEFAULT_EMAIL'];
4846 } elseif (isset($git['user.email'])) {
4847 $author_email = $git['user.email'];
4848 }
4849
4850 if (isset($author_name) && isset($author_email)) {
4851 $author = sprintf('%s <%s>', $author_name, $author_email);
4852 }
4853 }
4854
4855 $self = $this;
4856 $author = $io->askAndValidate(
4857 'Author [<comment>'.$author.'</comment>, n to skip]: ',
4858 function ($value) use ($self, $author) {
4859 if ($value === 'n' || $value === 'no') {
4860 return;
4861 }
4862 $value = $value ?: $author;
4863 $author = $self->parseAuthorString($value);
4864
4865 return sprintf('%s <%s>', $author['name'], $author['email']);
4866 },
4867 null,
4868 $author
4869 );
4870 $input->setOption('author', $author);
4871
4872 $minimumStability = $input->getOption('stability') ?: null;
4873 $minimumStability = $io->askAndValidate(
4874 'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
4875 function ($value) use ($self, $minimumStability) {
4876 if (null === $value) {
4877 return $minimumStability;
4878 }
4879
4880 if (!isset(BasePackage::$stabilities[$value])) {
4881 throw new \InvalidArgumentException(
4882 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
4883 implode(', ', array_keys(BasePackage::$stabilities))
4884 );
4885 }
4886
4887 return $value;
4888 },
4889 null,
4890 $minimumStability
4891 );
4892 $input->setOption('stability', $minimumStability);
4893
4894 $type = $input->getOption('type') ?: false;
4895 $type = $io->ask(
4896 'Package Type (e.g. library, project, metapackage, composer-plugin) [<comment>'.$type.'</comment>]: ',
4897 $type
4898 );
4899 $input->setOption('type', $type);
4900
4901 if (null === $license = $input->getOption('license')) {
4902 if (!empty($_SERVER['COMPOSER_DEFAULT_LICENSE'])) {
4903 $license = $_SERVER['COMPOSER_DEFAULT_LICENSE'];
4904 }
4905 }
4906
4907 $license = $io->ask(
4908 'License [<comment>'.$license.'</comment>]: ',
4909 $license
4910 );
4911 $input->setOption('license', $license);
4912
4913 $io->writeError(array('', 'Define your dependencies.', ''));
4914
4915 $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
4916 $require = $input->getOption('require');
4917 $requirements = array();
4918 if ($require || $io->askConfirmation($question, true)) {
4919 $requirements = $this->determineRequirements($input, $output, $require);
4920 }
4921 $input->setOption('require', $requirements);
4922
4923 $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
4924 $requireDev = $input->getOption('require-dev');
4925 $devRequirements = array();
4926 if ($requireDev || $io->askConfirmation($question, true)) {
4927 $devRequirements = $this->determineRequirements($input, $output, $requireDev);
4928 }
4929 $input->setOption('require-dev', $devRequirements);
4930 }
4931
4932
4933
4934
4935
4936
4937 public function parseAuthorString($author)
4938 {
4939 if (preg_match('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P<email>.+?)>$/u', $author, $match)) {
4940 if ($this->isValidEmail($match['email'])) {
4941 return array(
4942 'name' => trim($match['name']),
4943 'email' => $match['email'],
4944 );
4945 }
4946 }
4947
4948 throw new \InvalidArgumentException(
4949 'Invalid author string.  Must be in the format: '.
4950 'John Smith <john@example.com>'
4951 );
4952 }
4953
4954 protected function findPackages($name)
4955 {
4956 return $this->getRepos()->search($name);
4957 }
4958
4959 protected function getRepos()
4960 {
4961 if (!$this->repos) {
4962 $this->repos = new CompositeRepository(array_merge(
4963 array(new PlatformRepository),
4964 RepositoryFactory::defaultRepos($this->getIO())
4965 ));
4966 }
4967
4968 return $this->repos;
4969 }
4970
4971 protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable')
4972 {
4973 if ($requires) {
4974 $requires = $this->normalizeRequirements($requires);
4975 $result = array();
4976 $io = $this->getIO();
4977
4978 foreach ($requires as $requirement) {
4979 if (!isset($requirement['version'])) {
4980
4981  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability);
4982 $requirement['version'] = $version;
4983
4984
4985  $requirement['name'] = $name;
4986
4987 $io->writeError(sprintf(
4988 'Using version <info>%s</info> for <info>%s</info>',
4989 $requirement['version'],
4990 $requirement['name']
4991 ));
4992 } else {
4993
4994  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $requirement['version'], 'dev');
4995
4996
4997  $requirement['name'] = $name;
4998 }
4999
5000 $result[] = $requirement['name'] . ' ' . $requirement['version'];
5001 }
5002
5003 return $result;
5004 }
5005
5006 $versionParser = new VersionParser();
5007 $io = $this->getIO();
5008 while (null !== $package = $io->ask('Search for a package: ')) {
5009 $matches = $this->findPackages($package);
5010
5011 if (count($matches)) {
5012 $exactMatch = null;
5013 $choices = array();
5014 foreach ($matches as $position => $foundPackage) {
5015 $abandoned = '';
5016 if (isset($foundPackage['abandoned'])) {
5017 if (is_string($foundPackage['abandoned'])) {
5018 $replacement = sprintf('Use %s instead', $foundPackage['abandoned']);
5019 } else {
5020 $replacement = 'No replacement was suggested';
5021 }
5022 $abandoned = sprintf('<warning>Abandoned. %s.</warning>', $replacement);
5023 }
5024
5025 $choices[] = sprintf(' <info>%5s</info> %s %s', "[$position]", $foundPackage['name'], $abandoned);
5026 if ($foundPackage['name'] === $package) {
5027 $exactMatch = true;
5028 break;
5029 }
5030 }
5031
5032
5033  if (!$exactMatch) {
5034 $io->writeError(array(
5035 '',
5036 sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
5037 '',
5038 ));
5039
5040 $io->writeError($choices);
5041 $io->writeError('');
5042
5043 $validator = function ($selection) use ($matches, $versionParser) {
5044 if ('' === $selection) {
5045 return false;
5046 }
5047
5048 if (is_numeric($selection) && isset($matches[(int) $selection])) {
5049 $package = $matches[(int) $selection];
5050
5051 return $package['name'];
5052 }
5053
5054 if (preg_match('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
5055 if (isset($packageMatches['version'])) {
5056
5057
5058
5059  $versionParser->parseConstraints($packageMatches['version']);
5060
5061 return $packageMatches['name'].' '.$packageMatches['version'];
5062 }
5063
5064
5065  return $packageMatches['name'];
5066 }
5067
5068 throw new \Exception('Not a valid selection');
5069 };
5070
5071 $package = $io->askAndValidate(
5072 'Enter package # to add, or the complete package name if it is not listed: ',
5073 $validator,
5074 3,
5075 false
5076 );
5077 }
5078
5079
5080  if (false !== $package && false === strpos($package, ' ')) {
5081 $validator = function ($input) {
5082 $input = trim($input);
5083
5084 return $input ?: false;
5085 };
5086
5087 $constraint = $io->askAndValidate(
5088 'Enter the version constraint to require (or leave blank to use the latest version): ',
5089 $validator,
5090 3,
5091 false
5092 );
5093
5094 if (false === $constraint) {
5095 list($name, $constraint) = $this->findBestVersionAndNameForPackage($input, $package, $phpVersion, $preferredStability);
5096
5097 $io->writeError(sprintf(
5098 'Using version <info>%s</info> for <info>%s</info>',
5099 $constraint,
5100 $package
5101 ));
5102 }
5103
5104 $package .= ' '.$constraint;
5105 }
5106
5107 if (false !== $package) {
5108 $requires[] = $package;
5109 }
5110 }
5111 }
5112
5113 return $requires;
5114 }
5115
5116 protected function formatAuthors($author)
5117 {
5118 return array($this->parseAuthorString($author));
5119 }
5120
5121 protected function formatRequirements(array $requirements)
5122 {
5123 $requires = array();
5124 $requirements = $this->normalizeRequirements($requirements);
5125 foreach ($requirements as $requirement) {
5126 $requires[$requirement['name']] = $requirement['version'];
5127 }
5128
5129 return $requires;
5130 }
5131
5132 protected function getGitConfig()
5133 {
5134 if (null !== $this->gitConfig) {
5135 return $this->gitConfig;
5136 }
5137
5138 $finder = new ExecutableFinder();
5139 $gitBin = $finder->find('git');
5140
5141 $cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
5142 $cmd->run();
5143
5144 if ($cmd->isSuccessful()) {
5145 $this->gitConfig = array();
5146 preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER);
5147 foreach ($matches as $match) {
5148 $this->gitConfig[$match[1]] = $match[2];
5149 }
5150
5151 return $this->gitConfig;
5152 }
5153
5154 return $this->gitConfig = array();
5155 }
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173 protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
5174 {
5175 if (!file_exists($ignoreFile)) {
5176 return false;
5177 }
5178
5179 $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
5180
5181 $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES);
5182 foreach ($lines as $line) {
5183 if (preg_match($pattern, $line)) {
5184 return true;
5185 }
5186 }
5187
5188 return false;
5189 }
5190
5191 protected function normalizeRequirements(array $requirements)
5192 {
5193 $parser = new VersionParser();
5194
5195 return $parser->parseNameVersionPairs($requirements);
5196 }
5197
5198 protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
5199 {
5200 $contents = "";
5201 if (file_exists($ignoreFile)) {
5202 $contents = file_get_contents($ignoreFile);
5203
5204 if ("\n" !== substr($contents, 0, -1)) {
5205 $contents .= "\n";
5206 }
5207 }
5208
5209 file_put_contents($ignoreFile, $contents . $vendor. "\n");
5210 }
5211
5212 protected function isValidEmail($email)
5213 {
5214
5215  if (!function_exists('filter_var')) {
5216 return true;
5217 }
5218
5219
5220  if (PHP_VERSION_ID < 50303) {
5221 return true;
5222 }
5223
5224 return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
5225 }
5226
5227 private function getPool(InputInterface $input, $minimumStability = null)
5228 {
5229 $key = $minimumStability ?: 'default';
5230
5231 if (!isset($this->pools[$key])) {
5232 $this->pools[$key] = $pool = new Pool($minimumStability ?: $this->getMinimumStability($input));
5233 $pool->addRepository($this->getRepos());
5234 }
5235
5236 return $this->pools[$key];
5237 }
5238
5239 private function getMinimumStability(InputInterface $input)
5240 {
5241 if ($input->hasOption('stability')) {
5242 return $input->getOption('stability') ?: 'stable';
5243 }
5244
5245 $file = Factory::getComposerFile();
5246 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
5247 if (!empty($composer['minimum-stability'])) {
5248 return $composer['minimum-stability'];
5249 }
5250 }
5251
5252 return 'stable';
5253 }
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269 private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null)
5270 {
5271
5272  $versionSelector = new VersionSelector($this->getPool($input, $minimumStability));
5273 $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
5274
5275
5276  if ($input->hasOption('ignore-platform-reqs') && $input->getOption('ignore-platform-reqs')) {
5277 $phpVersion = null;
5278 $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
5279 }
5280
5281 if (!$package) {
5282
5283  if ($phpVersion && $versionSelector->findBestCandidate($name, $requiredVersion, null, $preferredStability)) {
5284 throw new \InvalidArgumentException(sprintf(
5285 'Package %s at version %s has a PHP requirement incompatible with your PHP version (%s)', $name, $requiredVersion, $phpVersion
5286 ));
5287 }
5288
5289  if ($requiredVersion && $versionSelector->findBestCandidate($name, null, $phpVersion, $preferredStability)) {
5290 throw new \InvalidArgumentException(sprintf(
5291 'Could not find package %s in a version matching %s', $name, $requiredVersion
5292 ));
5293 }
5294
5295  if ($phpVersion && $versionSelector->findBestCandidate($name)) {
5296 throw new \InvalidArgumentException(sprintf(
5297 'Could not find package %s in any version matching your PHP version (%s)', $name, $phpVersion
5298 ));
5299 }
5300
5301
5302  $similar = $this->findSimilar($name);
5303 if ($similar) {
5304
5305  if ($requiredVersion === null && in_array($name, $similar, true)) {
5306 throw new \InvalidArgumentException(sprintf(
5307 'Could not find a version of package %s matching your minimum-stability (%s). Require it with an explicit version constraint allowing its desired stability.',
5308 $name,
5309 $this->getMinimumStability($input)
5310 ));
5311 }
5312
5313 throw new \InvalidArgumentException(sprintf(
5314 "Could not find package %s.\n\nDid you mean " . (count($similar) > 1 ? 'one of these' : 'this') . "?\n    %s",
5315 $name,
5316 implode("\n    ", $similar)
5317 ));
5318 }
5319
5320 throw new \InvalidArgumentException(sprintf(
5321 '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).',
5322 $name,
5323 $this->getMinimumStability($input)
5324 ));
5325 }
5326
5327 return array(
5328 $package->getPrettyName(),
5329 $versionSelector->findRecommendedRequireVersion($package)
5330 );
5331 }
5332
5333 private function findSimilar($package)
5334 {
5335 try {
5336 $results = $this->repos->search($package);
5337 } catch (\Exception $e) {
5338
5339  return array();
5340 }
5341 $similarPackages = array();
5342
5343 foreach ($results as $result) {
5344 $similarPackages[$result['name']] = levenshtein($package, $result['name']);
5345 }
5346 asort($similarPackages);
5347
5348 return array_keys(array_slice($similarPackages, 0, 5));
5349 }
5350 }
5351 <?php
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363 namespace Composer\Command;
5364
5365 use Composer\Installer;
5366 use Composer\Plugin\CommandEvent;
5367 use Composer\Plugin\PluginEvents;
5368 use Symfony\Component\Console\Input\InputInterface;
5369 use Symfony\Component\Console\Input\InputOption;
5370 use Symfony\Component\Console\Input\InputArgument;
5371 use Symfony\Component\Console\Output\OutputInterface;
5372
5373
5374
5375
5376
5377
5378
5379 class InstallCommand extends BaseCommand
5380 {
5381 protected function configure()
5382 {
5383 $this
5384 ->setName('install')
5385 ->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
5386 ->setDefinition(array(
5387 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5388 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5389 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
5390 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
5391 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
5392 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
5393 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
5394 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5395 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5396 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5397 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
5398 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5399 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5400 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5401 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5402 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
5403 ))
5404 ->setHelp(<<<EOT
5405 The <info>install</info> command reads the composer.lock file from
5406 the current directory, processes it, and downloads and installs all the
5407 libraries and dependencies outlined in that file. If the file does not
5408 exist it will look for composer.json and do the same.
5409
5410 <info>php composer.phar install</info>
5411
5412 EOT
5413 )
5414 ;
5415 }
5416
5417 protected function execute(InputInterface $input, OutputInterface $output)
5418 {
5419 $io = $this->getIO();
5420 if ($args = $input->getArgument('packages')) {
5421 $io->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
5422
5423 return 1;
5424 }
5425
5426 if ($input->getOption('no-custom-installers')) {
5427 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
5428 $input->setOption('no-plugins', true);
5429 }
5430
5431 if ($input->getOption('dev')) {
5432 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
5433 }
5434
5435 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5436 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5437
5438 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
5439 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5440
5441 $install = Installer::create($io, $composer);
5442
5443 $config = $composer->getConfig();
5444 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
5445
5446 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
5447 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
5448 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
5449
5450 $install
5451 ->setDryRun($input->getOption('dry-run'))
5452 ->setVerbose($input->getOption('verbose'))
5453 ->setPreferSource($preferSource)
5454 ->setPreferDist($preferDist)
5455 ->setDevMode(!$input->getOption('no-dev'))
5456 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
5457 ->setRunScripts(!$input->getOption('no-scripts'))
5458 ->setSkipSuggest($input->getOption('no-suggest'))
5459 ->setOptimizeAutoloader($optimize)
5460 ->setClassMapAuthoritative($authoritative)
5461 ->setApcuAutoloader($apcu)
5462 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5463 ;
5464
5465 if ($input->getOption('no-plugins')) {
5466 $install->disablePlugins();
5467 }
5468
5469 return $install->run();
5470 }
5471 }
5472 <?php
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484 namespace Composer\Command;
5485
5486 use Composer\Json\JsonFile;
5487 use Composer\Plugin\CommandEvent;
5488 use Composer\Plugin\PluginEvents;
5489 use Composer\Package\PackageInterface;
5490 use Composer\Repository\RepositoryInterface;
5491 use Symfony\Component\Console\Helper\Table;
5492 use Symfony\Component\Console\Input\InputInterface;
5493 use Symfony\Component\Console\Input\InputOption;
5494 use Symfony\Component\Console\Output\OutputInterface;
5495
5496
5497
5498
5499 class LicensesCommand extends BaseCommand
5500 {
5501 protected function configure()
5502 {
5503 $this
5504 ->setName('licenses')
5505 ->setDescription('Shows information about licenses of dependencies.')
5506 ->setDefinition(array(
5507 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5508 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
5509 ))
5510 ->setHelp(<<<EOT
5511 The license command displays detailed information about the licenses of
5512 the installed dependencies.
5513
5514 EOT
5515 )
5516 ;
5517 }
5518
5519 protected function execute(InputInterface $input, OutputInterface $output)
5520 {
5521 $composer = $this->getComposer();
5522
5523 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
5524 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5525
5526 $root = $composer->getPackage();
5527 $repo = $composer->getRepositoryManager()->getLocalRepository();
5528
5529 if ($input->getOption('no-dev')) {
5530 $packages = $this->filterRequiredPackages($repo, $root);
5531 } else {
5532 $packages = $this->appendPackages($repo->getPackages(), array());
5533 }
5534
5535 ksort($packages);
5536 $io = $this->getIO();
5537
5538 switch ($format = $input->getOption('format')) {
5539 case 'text':
5540 $io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
5541 $io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
5542 $io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
5543 $io->write('Dependencies:');
5544 $io->write('');
5545
5546 $table = new Table($output);
5547 $table->setStyle('compact');
5548 $table->getStyle()->setVerticalBorderChar('');
5549 $table->getStyle()->setCellRowContentFormat('%s  ');
5550 $table->setHeaders(array('Name', 'Version', 'License'));
5551 foreach ($packages as $package) {
5552 $table->addRow(array(
5553 $package->getPrettyName(),
5554 $package->getFullPrettyVersion(),
5555 implode(', ', $package->getLicense()) ?: 'none',
5556 ));
5557 }
5558 $table->render();
5559 break;
5560
5561 case 'json':
5562 $dependencies = array();
5563 foreach ($packages as $package) {
5564 $dependencies[$package->getPrettyName()] = array(
5565 'version' => $package->getFullPrettyVersion(),
5566 'license' => $package->getLicense(),
5567 );
5568 }
5569
5570 $io->write(JsonFile::encode(array(
5571 'name' => $root->getPrettyName(),
5572 'version' => $root->getFullPrettyVersion(),
5573 'license' => $root->getLicense(),
5574 'dependencies' => $dependencies,
5575 )));
5576 break;
5577
5578 default:
5579 throw new \RuntimeException(sprintf('Unsupported format "%s".  See help for supported formats.', $format));
5580 }
5581 }
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591 private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
5592 {
5593 $requires = array_keys($package->getRequires());
5594
5595 $packageListNames = array_keys($bucket);
5596 $packages = array_filter(
5597 $repo->getPackages(),
5598 function ($package) use ($requires, $packageListNames) {
5599 return in_array($package->getName(), $requires) && !in_array($package->getName(), $packageListNames);
5600 }
5601 );
5602
5603 $bucket = $this->appendPackages($packages, $bucket);
5604
5605 foreach ($packages as $package) {
5606 $bucket = $this->filterRequiredPackages($repo, $package, $bucket);
5607 }
5608
5609 return $bucket;
5610 }
5611
5612
5613
5614
5615
5616
5617
5618
5619 public function appendPackages(array $packages, array $bucket)
5620 {
5621 foreach ($packages as $package) {
5622 $bucket[$package->getName()] = $package;
5623 }
5624
5625 return $bucket;
5626 }
5627 }
5628 <?php
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640 namespace Composer\Command;
5641
5642 use Symfony\Component\Console\Input\InputInterface;
5643 use Symfony\Component\Console\Input\InputArgument;
5644 use Symfony\Component\Console\Input\ArrayInput;
5645 use Symfony\Component\Console\Input\InputOption;
5646 use Symfony\Component\Console\Output\OutputInterface;
5647
5648
5649
5650
5651 class OutdatedCommand extends ShowCommand
5652 {
5653 protected function configure()
5654 {
5655 $this
5656 ->setName('outdated')
5657 ->setDescription('Shows a list of installed packages that have updates available, including their latest version.')
5658 ->setDefinition(array(
5659 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
5660 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'),
5661 new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'),
5662 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
5663 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
5664 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
5665 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5666 ))
5667 ->setHelp(<<<EOT
5668 The outdated command is just a proxy for `composer show -l`
5669
5670 The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:
5671
5672 - <info>green</info> (=): Dependency is in the latest version and is up to date.
5673 - <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
5674   compatibility breaks according to semver, so upgrade when you can but it
5675   may involve work.
5676 - <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
5677
5678
5679 EOT
5680 )
5681 ;
5682 }
5683
5684 protected function execute(InputInterface $input, OutputInterface $output)
5685 {
5686 $args = array(
5687 'show',
5688 '--latest' => true,
5689 );
5690 if (!$input->getOption('all')) {
5691 $args['--outdated'] = true;
5692 }
5693 if ($input->getOption('direct')) {
5694 $args['--direct'] = true;
5695 }
5696 if ($input->getArgument('package')) {
5697 $args['package'] = $input->getArgument('package');
5698 }
5699 if ($input->getOption('strict')) {
5700 $args['--strict'] = true;
5701 }
5702 if ($input->getOption('minor-only')) {
5703 $args['--minor-only'] = true;
5704 }
5705 $args['--format'] = $input->getOption('format');
5706
5707 $input = new ArrayInput($args);
5708
5709 return $this->getApplication()->run($input, $output);
5710 }
5711
5712
5713
5714
5715 public function isProxyCommand()
5716 {
5717 return true;
5718 }
5719 }
5720 <?php
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732 namespace Composer\Command;
5733
5734 use Symfony\Component\Console\Input\InputInterface;
5735 use Symfony\Component\Console\Output\OutputInterface;
5736
5737
5738
5739
5740 class ProhibitsCommand extends BaseDependencyCommand
5741 {
5742
5743
5744
5745 protected function configure()
5746 {
5747 parent::configure();
5748
5749 $this
5750 ->setName('prohibits')
5751 ->setAliases(array('why-not'))
5752 ->setDescription('Shows which packages prevent the given package from being installed.')
5753 ->setHelp(<<<EOT
5754 Displays detailed information about why a package cannot be installed.
5755
5756 <info>php composer.phar prohibits composer/composer</info>
5757
5758 EOT
5759 )
5760 ;
5761 }
5762
5763
5764
5765
5766
5767
5768
5769
5770 protected function execute(InputInterface $input, OutputInterface $output)
5771 {
5772 return parent::doExecute($input, $output, true);
5773 }
5774 }
5775 <?php
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787 namespace Composer\Command;
5788
5789 use Composer\Config\JsonConfigSource;
5790 use Composer\Installer;
5791 use Composer\Plugin\CommandEvent;
5792 use Composer\Plugin\PluginEvents;
5793 use Composer\Json\JsonFile;
5794 use Composer\Factory;
5795 use Symfony\Component\Console\Input\InputInterface;
5796 use Symfony\Component\Console\Input\InputOption;
5797 use Symfony\Component\Console\Input\InputArgument;
5798 use Symfony\Component\Console\Output\OutputInterface;
5799
5800
5801
5802
5803
5804 class RemoveCommand extends BaseCommand
5805 {
5806 protected function configure()
5807 {
5808 $this
5809 ->setName('remove')
5810 ->setDescription('Removes a package from the require or require-dev.')
5811 ->setDefinition(array(
5812 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
5813 new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
5814 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5815 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
5816 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5817 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
5818 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
5819 new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
5820 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5821 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5822 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5823 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5824 ))
5825 ->setHelp(<<<EOT
5826 The <info>remove</info> command removes a package from the current
5827 list of installed packages
5828
5829 <info>php composer.phar remove</info>
5830
5831 EOT
5832 )
5833 ;
5834 }
5835
5836 protected function execute(InputInterface $input, OutputInterface $output)
5837 {
5838 $packages = $input->getArgument('packages');
5839 $packages = array_map('strtolower', $packages);
5840
5841 $file = Factory::getComposerFile();
5842
5843 $jsonFile = new JsonFile($file);
5844 $composer = $jsonFile->read();
5845 $composerBackup = file_get_contents($jsonFile->getPath());
5846
5847 $json = new JsonConfigSource($jsonFile);
5848
5849 $type = $input->getOption('dev') ? 'require-dev' : 'require';
5850 $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
5851 $io = $this->getIO();
5852
5853 if ($input->getOption('update-with-dependencies')) {
5854 $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>');
5855 }
5856
5857
5858  foreach (array('require', 'require-dev') as $linkType) {
5859 if (isset($composer[$linkType])) {
5860 foreach ($composer[$linkType] as $name => $version) {
5861 $composer[$linkType][strtolower($name)] = $name;
5862 }
5863 }
5864 }
5865
5866 foreach ($packages as $package) {
5867 if (isset($composer[$type][$package])) {
5868 $json->removeLink($type, $composer[$type][$package]);
5869 } elseif (isset($composer[$altType][$package])) {
5870 $io->writeError('<warning>'.$composer[$altType][$package].' could not be found in '.$type.' but it is present in '.$altType.'</warning>');
5871 if ($io->isInteractive()) {
5872 if ($io->askConfirmation('Do you want to remove it from '.$altType.' [<comment>yes</comment>]? ', true)) {
5873 $json->removeLink($altType, $composer[$altType][$package]);
5874 }
5875 }
5876 } else {
5877 $io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
5878 }
5879 }
5880
5881 if ($input->getOption('no-update')) {
5882 return 0;
5883 }
5884
5885
5886  $this->resetComposer();
5887 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5888 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5889
5890 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
5891 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5892
5893 $install = Installer::create($io, $composer);
5894
5895 $updateDevMode = !$input->getOption('update-no-dev');
5896 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
5897 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
5898 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
5899
5900 $install
5901 ->setVerbose($input->getOption('verbose'))
5902 ->setDevMode($updateDevMode)
5903 ->setOptimizeAutoloader($optimize)
5904 ->setClassMapAuthoritative($authoritative)
5905 ->setApcuAutoloader($apcu)
5906 ->setUpdate(true)
5907 ->setUpdateWhitelist($packages)
5908 ->setWhitelistTransitiveDependencies(!$input->getOption('no-update-with-dependencies'))
5909 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5910 ->setRunScripts(!$input->getOption('no-scripts'))
5911 ;
5912
5913 $status = $install->run();
5914 if ($status !== 0) {
5915 $io->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
5916 file_put_contents($jsonFile->getPath(), $composerBackup);
5917 }
5918
5919 return $status;
5920 }
5921 }
5922 <?php
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934 namespace Composer\Command;
5935
5936 use Symfony\Component\Console\Input\InputInterface;
5937 use Symfony\Component\Console\Input\InputArgument;
5938 use Symfony\Component\Console\Input\InputOption;
5939 use Symfony\Component\Console\Output\OutputInterface;
5940 use Composer\Factory;
5941 use Composer\Installer;
5942 use Composer\Json\JsonFile;
5943 use Composer\Json\JsonManipulator;
5944 use Composer\Package\Version\VersionParser;
5945 use Composer\Plugin\CommandEvent;
5946 use Composer\Plugin\PluginEvents;
5947 use Composer\Repository\CompositeRepository;
5948 use Composer\Repository\PlatformRepository;
5949
5950
5951
5952
5953
5954 class RequireCommand extends InitCommand
5955 {
5956 protected function configure()
5957 {
5958 $this
5959 ->setName('require')
5960 ->setDescription('Adds required packages to your composer.json and installs them.')
5961 ->setDefinition(array(
5962 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"'),
5963 new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
5964 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5965 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5966 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5967 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5968 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
5969 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5970 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
5971 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
5972 new InputOption('update-with-all-dependencies', null, InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
5973 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5974 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
5975 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
5976 new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
5977 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5978 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5979 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5980 ))
5981 ->setHelp(<<<EOT
5982 The require command adds required packages to your composer.json and installs them.
5983
5984 If you do not specify a package, composer will prompt you to search for a package, and given results, provide a list of 
5985 matches to require.
5986
5987 If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.
5988
5989 If you do not want to install the new dependencies immediately you can call it with --no-update
5990
5991 EOT
5992 )
5993 ;
5994 }
5995
5996 protected function execute(InputInterface $input, OutputInterface $output)
5997 {
5998 $file = Factory::getComposerFile();
5999 $io = $this->getIO();
6000
6001 $newlyCreated = !file_exists($file);
6002 if ($newlyCreated && !file_put_contents($file, "{\n}\n")) {
6003 $io->writeError('<error>'.$file.' could not be created.</error>');
6004
6005 return 1;
6006 }
6007 if (!is_readable($file)) {
6008 $io->writeError('<error>'.$file.' is not readable.</error>');
6009
6010 return 1;
6011 }
6012 if (!is_writable($file)) {
6013 $io->writeError('<error>'.$file.' is not writable.</error>');
6014
6015 return 1;
6016 }
6017
6018 if (filesize($file) === 0) {
6019 file_put_contents($file, "{\n}\n");
6020 }
6021
6022 $json = new JsonFile($file);
6023 $composerBackup = file_get_contents($json->getPath());
6024
6025 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6026 $repos = $composer->getRepositoryManager()->getRepositories();
6027
6028 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6029
6030  $this->repos = new CompositeRepository(array_merge(
6031 array(new PlatformRepository(array(), $platformOverrides)),
6032 $repos
6033 ));
6034
6035 if ($composer->getPackage()->getPreferStable()) {
6036 $preferredStability = 'stable';
6037 } else {
6038 $preferredStability = $composer->getPackage()->getMinimumStability();
6039 }
6040
6041 $phpVersion = $this->repos->findPackage('php', '*')->getPrettyVersion();
6042 $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability);
6043
6044 $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
6045 $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
6046 $requirements = $this->formatRequirements($requirements);
6047
6048
6049  $versionParser = new VersionParser();
6050 foreach ($requirements as $constraint) {
6051 $versionParser->parseConstraints($constraint);
6052 }
6053
6054 $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
6055
6056 if (!$this->updateFileCleanly($json, $requirements, $requireKey, $removeKey, $sortPackages)) {
6057 $composerDefinition = $json->read();
6058 foreach ($requirements as $package => $version) {
6059 $composerDefinition[$requireKey][$package] = $version;
6060 unset($composerDefinition[$removeKey][$package]);
6061 }
6062 $json->write($composerDefinition);
6063 }
6064
6065 $io->writeError('<info>'.$file.' has been '.($newlyCreated ? 'created' : 'updated').'</info>');
6066
6067 if ($input->getOption('no-update')) {
6068 return 0;
6069 }
6070 $updateDevMode = !$input->getOption('update-no-dev');
6071 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6072 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6073 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6074
6075
6076  $this->resetComposer();
6077 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6078 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6079
6080 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
6081 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6082
6083 $install = Installer::create($io, $composer);
6084
6085 $install
6086 ->setVerbose($input->getOption('verbose'))
6087 ->setPreferSource($input->getOption('prefer-source'))
6088 ->setPreferDist($input->getOption('prefer-dist'))
6089 ->setDevMode($updateDevMode)
6090 ->setRunScripts(!$input->getOption('no-scripts'))
6091 ->setSkipSuggest($input->getOption('no-suggest'))
6092 ->setOptimizeAutoloader($optimize)
6093 ->setClassMapAuthoritative($authoritative)
6094 ->setApcuAutoloader($apcu)
6095 ->setUpdate(true)
6096 ->setUpdateWhitelist(array_keys($requirements))
6097 ->setWhitelistTransitiveDependencies($input->getOption('update-with-dependencies'))
6098 ->setWhitelistAllDependencies($input->getOption('update-with-all-dependencies'))
6099 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6100 ->setPreferStable($input->getOption('prefer-stable'))
6101 ->setPreferLowest($input->getOption('prefer-lowest'))
6102 ;
6103
6104 $status = $install->run();
6105 if ($status !== 0) {
6106 if ($newlyCreated) {
6107 $io->writeError("\n".'<error>Installation failed, deleting '.$file.'.</error>');
6108 unlink($json->getPath());
6109 } else {
6110 $io->writeError("\n".'<error>Installation failed, reverting '.$file.' to its original content.</error>');
6111 file_put_contents($json->getPath(), $composerBackup);
6112 }
6113 }
6114
6115 return $status;
6116 }
6117
6118 private function updateFileCleanly($json, array $new, $requireKey, $removeKey, $sortPackages)
6119 {
6120 $contents = file_get_contents($json->getPath());
6121
6122 $manipulator = new JsonManipulator($contents);
6123
6124 foreach ($new as $package => $constraint) {
6125 if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
6126 return false;
6127 }
6128 if (!$manipulator->removeSubNode($removeKey, $package)) {
6129 return false;
6130 }
6131 }
6132
6133 file_put_contents($json->getPath(), $manipulator->getContents());
6134
6135 return true;
6136 }
6137
6138 protected function interact(InputInterface $input, OutputInterface $output)
6139 {
6140 return;
6141 }
6142 }
6143 <?php
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155 namespace Composer\Command;
6156
6157 use Composer\Script\Event as ScriptEvent;
6158 use Composer\Script\ScriptEvents;
6159 use Composer\Util\ProcessExecutor;
6160 use Symfony\Component\Console\Input\InputInterface;
6161 use Symfony\Component\Console\Input\InputOption;
6162 use Symfony\Component\Console\Input\InputArgument;
6163 use Symfony\Component\Console\Output\OutputInterface;
6164 use Symfony\Component\Console\Helper\Table;
6165
6166
6167
6168
6169 class RunScriptCommand extends BaseCommand
6170 {
6171
6172
6173
6174 protected $scriptEvents = array(
6175 ScriptEvents::PRE_INSTALL_CMD,
6176 ScriptEvents::POST_INSTALL_CMD,
6177 ScriptEvents::PRE_UPDATE_CMD,
6178 ScriptEvents::POST_UPDATE_CMD,
6179 ScriptEvents::PRE_STATUS_CMD,
6180 ScriptEvents::POST_STATUS_CMD,
6181 ScriptEvents::POST_ROOT_PACKAGE_INSTALL,
6182 ScriptEvents::POST_CREATE_PROJECT_CMD,
6183 ScriptEvents::PRE_ARCHIVE_CMD,
6184 ScriptEvents::POST_ARCHIVE_CMD,
6185 ScriptEvents::PRE_AUTOLOAD_DUMP,
6186 ScriptEvents::POST_AUTOLOAD_DUMP,
6187 );
6188
6189 protected function configure()
6190 {
6191 $this
6192 ->setName('run-script')
6193 ->setDescription('Runs the scripts defined in composer.json.')
6194 ->setDefinition(array(
6195 new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),
6196 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6197 new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'),
6198 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6199 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6200 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.'),
6201 ))
6202 ->setHelp(<<<EOT
6203 The <info>run-script</info> command runs scripts defined in composer.json:
6204
6205 <info>php composer.phar run-script post-update-cmd</info>
6206 EOT
6207 )
6208 ;
6209 }
6210
6211 protected function execute(InputInterface $input, OutputInterface $output)
6212 {
6213 if ($input->getOption('list')) {
6214 return $this->listScripts($output);
6215 } elseif (!$input->getArgument('script')) {
6216 throw new \RuntimeException('Missing required argument "script"');
6217 }
6218
6219 $script = $input->getArgument('script');
6220 if (!in_array($script, $this->scriptEvents)) {
6221 if (defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
6222 throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
6223 }
6224 }
6225
6226 $composer = $this->getComposer();
6227 $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
6228 $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode);
6229 $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event);
6230 if (!$hasListeners) {
6231 throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
6232 }
6233
6234 $args = $input->getArgument('args');
6235
6236 if (null !== $timeout = $input->getOption('timeout')) {
6237 if (!ctype_digit($timeout)) {
6238 throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever');
6239 }
6240
6241  ProcessExecutor::setTimeout((int) $timeout);
6242 }
6243
6244 return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
6245 }
6246
6247 protected function listScripts(OutputInterface $output)
6248 {
6249 $scripts = $this->getComposer()->getPackage()->getScripts();
6250
6251 if (!count($scripts)) {
6252 return 0;
6253 }
6254
6255 $io = $this->getIO();
6256 $io->writeError('<info>scripts:</info>');
6257 $table = array();
6258 foreach ($scripts as $name => $script) {
6259 $cmd = $this->getApplication()->find($name);
6260 $description = '';
6261 if ($cmd instanceof ScriptAliasCommand) {
6262 $description = $cmd->getDescription();
6263 }
6264 $table[] = array('  '.$name, $description);
6265 }
6266
6267 $renderer = new Table($output);
6268 $renderer->setStyle('compact');
6269 $renderer->getStyle()->setVerticalBorderChar('');
6270 $renderer->getStyle()->setCellRowContentFormat('%s  ');
6271 $renderer->setRows($table)->render();
6272
6273 return 0;
6274 }
6275 }
6276 <?php
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288 namespace Composer\Command;
6289
6290 use Symfony\Component\Console\Input\InputInterface;
6291 use Symfony\Component\Console\Input\InputOption;
6292 use Symfony\Component\Console\Input\InputArgument;
6293 use Symfony\Component\Console\Output\OutputInterface;
6294
6295
6296
6297
6298 class ScriptAliasCommand extends BaseCommand
6299 {
6300 private $script;
6301 private $description;
6302
6303 public function __construct($script, $description)
6304 {
6305 $this->script = $script;
6306 $this->description = empty($description) ? 'Runs the '.$script.' script as defined in composer.json.' : $description;
6307
6308 parent::__construct();
6309 }
6310
6311 protected function configure()
6312 {
6313 $this
6314 ->setName($this->script)
6315 ->setDescription($this->description)
6316 ->setDefinition(array(
6317 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6318 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6319 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6320 ))
6321 ->setHelp(<<<EOT
6322 The <info>run-script</info> command runs scripts defined in composer.json:
6323
6324 <info>php composer.phar run-script post-update-cmd</info>
6325 EOT
6326 )
6327 ;
6328 }
6329
6330 protected function execute(InputInterface $input, OutputInterface $output)
6331 {
6332 $composer = $this->getComposer();
6333
6334 $args = $input->getArguments();
6335
6336 return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args']);
6337 }
6338 }
6339 <?php
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351 namespace Composer\Command;
6352
6353 use Composer\Factory;
6354 use Symfony\Component\Console\Input\InputInterface;
6355 use Symfony\Component\Console\Input\InputArgument;
6356 use Symfony\Component\Console\Input\InputOption;
6357 use Symfony\Component\Console\Output\OutputInterface;
6358 use Composer\Repository\CompositeRepository;
6359 use Composer\Repository\PlatformRepository;
6360 use Composer\Repository\RepositoryInterface;
6361 use Composer\Plugin\CommandEvent;
6362 use Composer\Plugin\PluginEvents;
6363
6364
6365
6366
6367 class SearchCommand extends BaseCommand
6368 {
6369 protected $matches;
6370 protected $lowMatches = array();
6371 protected $tokens;
6372 protected $output;
6373 protected $onlyName;
6374
6375 protected function configure()
6376 {
6377 $this
6378 ->setName('search')
6379 ->setDescription('Searches for packages.')
6380 ->setDefinition(array(
6381 new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
6382 new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
6383 new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
6384 ))
6385 ->setHelp(<<<EOT
6386 The search command searches for packages by its name
6387 <info>php composer.phar search symfony composer</info>
6388
6389 EOT
6390 )
6391 ;
6392 }
6393
6394 protected function execute(InputInterface $input, OutputInterface $output)
6395 {
6396
6397  $platformRepo = new PlatformRepository;
6398 $io = $this->getIO();
6399 if (!($composer = $this->getComposer(false))) {
6400 $composer = Factory::create($this->getIO(), array());
6401 }
6402 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6403 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6404 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6405
6406 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
6407 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6408
6409 $onlyName = $input->getOption('only-name');
6410 $type = $input->getOption('type') ?: null;
6411
6412 $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
6413 $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
6414
6415 foreach ($results as $result) {
6416 $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
6417 }
6418 }
6419 }
6420 <?php
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432 namespace Composer\Command;
6433
6434 use Composer\Composer;
6435 use Composer\Factory;
6436 use Composer\Config;
6437 use Composer\Util\Filesystem;
6438 use Composer\SelfUpdate\Keys;
6439 use Composer\SelfUpdate\Versions;
6440 use Composer\IO\IOInterface;
6441 use Composer\Downloader\FilesystemException;
6442 use Symfony\Component\Console\Input\InputInterface;
6443 use Symfony\Component\Console\Input\InputOption;
6444 use Symfony\Component\Console\Input\InputArgument;
6445 use Symfony\Component\Console\Output\OutputInterface;
6446 use Symfony\Component\Finder\Finder;
6447
6448
6449
6450
6451
6452
6453 class SelfUpdateCommand extends BaseCommand
6454 {
6455 const HOMEPAGE = 'getcomposer.org';
6456 const OLD_INSTALL_EXT = '-old.phar';
6457
6458 protected function configure()
6459 {
6460 $this
6461 ->setName('self-update')
6462 ->setAliases(array('selfupdate'))
6463 ->setDescription('Updates composer.phar to the latest version.')
6464 ->setDefinition(array(
6465 new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'),
6466 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'),
6467 new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'),
6468 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6469 new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'),
6470 new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'),
6471 new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'),
6472 new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'),
6473 new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit'),
6474 ))
6475 ->setHelp(<<<EOT
6476 The <info>self-update</info> command checks getcomposer.org for newer
6477 versions of composer and if found, installs the latest.
6478
6479 <info>php composer.phar self-update</info>
6480
6481 EOT
6482 )
6483 ;
6484 }
6485
6486 protected function execute(InputInterface $input, OutputInterface $output)
6487 {
6488 $config = Factory::createConfig();
6489
6490 if ($config->get('disable-tls') === true) {
6491 $baseUrl = 'http://' . self::HOMEPAGE;
6492 } else {
6493 $baseUrl = 'https://' . self::HOMEPAGE;
6494 }
6495
6496 $io = $this->getIO();
6497 $remoteFilesystem = Factory::createRemoteFilesystem($io, $config);
6498
6499 $versionsUtil = new Versions($config, $remoteFilesystem);
6500
6501
6502  foreach (array('stable', 'preview', 'snapshot') as $channel) {
6503 if ($input->getOption($channel)) {
6504 $versionsUtil->setChannel($channel);
6505 }
6506 }
6507
6508 if ($input->getOption('set-channel-only')) {
6509 return 0;
6510 }
6511
6512 $cacheDir = $config->get('cache-dir');
6513 $rollbackDir = $config->get('data-dir');
6514 $home = $config->get('home');
6515 $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
6516
6517 if ($input->getOption('update-keys')) {
6518 return $this->fetchKeys($io, $config);
6519 }
6520
6521
6522  $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
6523
6524
6525  if (!is_writable($tmpDir)) {
6526 throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written');
6527 }
6528
6529
6530  if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
6531 $composeUser = posix_getpwuid(posix_geteuid());
6532 $homeOwner = posix_getpwuid(fileowner($home));
6533 if (isset($composeUser['name']) && isset($homeOwner['name']) && $composeUser['name'] !== $homeOwner['name']) {
6534 $io->writeError('<warning>You are running composer as "'.$composeUser['name'].'", while "'.$home.'" is owned by "'.$homeOwner['name'].'"</warning>');
6535 }
6536 }
6537
6538 if ($input->getOption('rollback')) {
6539 return $this->rollback($output, $rollbackDir, $localFilename);
6540 }
6541
6542 $latest = $versionsUtil->getLatest();
6543 $latestVersion = $latest['version'];
6544 $updateVersion = $input->getArgument('version') ?: $latestVersion;
6545
6546 if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
6547 $io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
6548
6549 return 1;
6550 }
6551
6552 if (Composer::VERSION === $updateVersion) {
6553 $io->writeError(sprintf('<info>You are already using composer version %s (%s channel).</info>', $updateVersion, $versionsUtil->getChannel()));
6554
6555
6556  if ($input->getOption('clean-backups')) {
6557 $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir));
6558 }
6559
6560 return 0;
6561 }
6562
6563 $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar';
6564 $backupFile = sprintf(
6565 '%s/%s-%s%s',
6566 $rollbackDir,
6567 strtr(Composer::RELEASE_DATE, ' :', '_-'),
6568 preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION),
6569 self::OLD_INSTALL_EXT
6570 );
6571
6572 $updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion);
6573
6574 $io->write(sprintf("Updating to version <info>%s</info> (%s channel).", $updateVersion, $versionsUtil->getChannel()));
6575 $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
6576 $signature = $remoteFilesystem->getContents(self::HOMEPAGE, $remoteFilename.'.sig', false);
6577 $io->writeError('   ', false);
6578 $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
6579 $io->writeError('');
6580
6581 if (!file_exists($tempFilename) || !$signature) {
6582 $io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
6583
6584 return 1;
6585 }
6586
6587
6588  if (!extension_loaded('openssl') && $config->get('disable-tls')) {
6589 $io->writeError('<warning>Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls</warning>');
6590 } else {
6591 if (!extension_loaded('openssl')) {
6592 throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. '
6593 . '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.');
6594 }
6595
6596 $sigFile = 'file://'.$home.'/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub');
6597 if (!file_exists($sigFile)) {
6598 file_put_contents($home.'/keys.dev.pub', <<<DEVPUBKEY
6599 -----BEGIN PUBLIC KEY-----
6600 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f
6601 FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi
6602 i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A
6603 hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f
6604 o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk
6605 8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn
6606 8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf
6607 TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9
6608 pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72
6609 8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4
6610 r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE
6611 wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ==
6612 -----END PUBLIC KEY-----
6613 DEVPUBKEY
6614 );
6615 file_put_contents($home.'/keys.tags.pub', <<<TAGSPUBKEY
6616 -----BEGIN PUBLIC KEY-----
6617 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2
6618 MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh
6619 vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO
6620 bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M
6621 mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf
6622 noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM
6623 nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ
6624 rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr
6625 RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK
6626 tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e
6627 TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95
6628 RGv89BPD+2DLnJysngsvVaUCAwEAAQ==
6629 -----END PUBLIC KEY-----
6630 TAGSPUBKEY
6631 );
6632 }
6633
6634 $pubkeyid = openssl_pkey_get_public($sigFile);
6635 $algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384';
6636 if (!in_array('SHA384', openssl_get_md_methods())) {
6637 throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
6638 }
6639 $signature = json_decode($signature, true);
6640 $signature = base64_decode($signature['sha384']);
6641 $verified = 1 === openssl_verify(file_get_contents($tempFilename), $signature, $pubkeyid, $algo);
6642 openssl_free_key($pubkeyid);
6643 if (!$verified) {
6644 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');
6645 }
6646 }
6647
6648
6649  if ($input->getOption('clean-backups')) {
6650 $this->cleanBackups($rollbackDir);
6651 }
6652
6653 if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
6654 @unlink($tempFilename);
6655 $io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
6656 $io->writeError('<error>Please re-run the self-update command to try again.</error>');
6657
6658 return 1;
6659 }
6660
6661 if (file_exists($backupFile)) {
6662 $io->writeError(sprintf(
6663 'Use <info>composer self-update --rollback</info> to return to version <comment>%s</comment>',
6664 Composer::VERSION
6665 ));
6666 } else {
6667 $io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
6668 }
6669 }
6670
6671 protected function fetchKeys(IOInterface $io, Config $config)
6672 {
6673 if (!$io->isInteractive()) {
6674 throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
6675 }
6676
6677 $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
6678
6679 $validator = function ($value) {
6680 if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
6681 throw new \UnexpectedValueException('Invalid input');
6682 }
6683
6684 return trim($value)."\n";
6685 };
6686
6687 $devKey = '';
6688 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
6689 $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
6690 while ($line = $io->ask('')) {
6691 $devKey .= trim($line)."\n";
6692 if (trim($line) === '-----END PUBLIC KEY-----') {
6693 break;
6694 }
6695 }
6696 }
6697 file_put_contents($keyPath = $config->get('home').'/keys.dev.pub', $match[0]);
6698 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6699
6700 $tagsKey = '';
6701 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
6702 $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
6703 while ($line = $io->ask('')) {
6704 $tagsKey .= trim($line)."\n";
6705 if (trim($line) === '-----END PUBLIC KEY-----') {
6706 break;
6707 }
6708 }
6709 }
6710 file_put_contents($keyPath = $config->get('home').'/keys.tags.pub', $match[0]);
6711 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6712
6713 $io->write('Public keys stored in '.$config->get('home'));
6714 }
6715
6716 protected function rollback(OutputInterface $output, $rollbackDir, $localFilename)
6717 {
6718 $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
6719 if (!$rollbackVersion) {
6720 throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"');
6721 }
6722
6723 $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
6724
6725 if (!is_file($oldFile)) {
6726 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
6727 }
6728 if (!is_readable($oldFile)) {
6729 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
6730 }
6731
6732 $io = $this->getIO();
6733 $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
6734 if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
6735 $io->writeError('<error>The backup file was corrupted ('.$err->getMessage().').</error>');
6736
6737 return 1;
6738 }
6739
6740 return 0;
6741 }
6742
6743
6744
6745
6746
6747
6748
6749
6750 protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
6751 {
6752 try {
6753 @chmod($newFilename, fileperms($localFilename));
6754 if (!ini_get('phar.readonly')) {
6755
6756  $phar = new \Phar($newFilename);
6757
6758  unset($phar);
6759 }
6760
6761
6762  if ($backupTarget && file_exists($localFilename)) {
6763 @copy($localFilename, $backupTarget);
6764 }
6765
6766 rename($newFilename, $localFilename);
6767
6768 return null;
6769 } catch (\Exception $e) {
6770 if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
6771 throw $e;
6772 }
6773
6774 return $e;
6775 }
6776 }
6777
6778 protected function cleanBackups($rollbackDir, $except = null)
6779 {
6780 $finder = $this->getOldInstallationFinder($rollbackDir);
6781 $io = $this->getIO();
6782 $fs = new Filesystem;
6783
6784 foreach ($finder as $file) {
6785 if ($except && $file->getBasename(self::OLD_INSTALL_EXT) === $except) {
6786 continue;
6787 }
6788 $file = (string) $file;
6789 $io->writeError('<info>Removing: '.$file.'</info>');
6790 $fs->remove($file);
6791 }
6792 }
6793
6794 protected function getLastBackupVersion($rollbackDir)
6795 {
6796 $finder = $this->getOldInstallationFinder($rollbackDir);
6797 $finder->sortByName();
6798 $files = iterator_to_array($finder);
6799
6800 if (count($files)) {
6801 return basename(end($files), self::OLD_INSTALL_EXT);
6802 }
6803
6804 return false;
6805 }
6806
6807 protected function getOldInstallationFinder($rollbackDir)
6808 {
6809 $finder = Finder::create()
6810 ->depth(0)
6811 ->files()
6812 ->name('*' . self::OLD_INSTALL_EXT)
6813 ->in($rollbackDir);
6814
6815 return $finder;
6816 }
6817 }
6818 <?php
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830 namespace Composer\Command;
6831
6832 use Composer\Composer;
6833 use Composer\DependencyResolver\DefaultPolicy;
6834 use Composer\DependencyResolver\Pool;
6835 use Composer\Json\JsonFile;
6836 use Composer\Package\BasePackage;
6837 use Composer\Package\CompletePackageInterface;
6838 use Composer\Package\PackageInterface;
6839 use Composer\Package\Version\VersionParser;
6840 use Composer\Package\Version\VersionSelector;
6841 use Composer\Plugin\CommandEvent;
6842 use Composer\Plugin\PluginEvents;
6843 use Composer\Repository\ArrayRepository;
6844 use Composer\Repository\ComposerRepository;
6845 use Composer\Repository\CompositeRepository;
6846 use Composer\Repository\PlatformRepository;
6847 use Composer\Repository\RepositoryFactory;
6848 use Composer\Repository\RepositoryInterface;
6849 use Composer\Semver\Constraint\ConstraintInterface;
6850 use Composer\Semver\Semver;
6851 use Composer\Spdx\SpdxLicenses;
6852 use Composer\Util\Platform;
6853 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
6854 use Symfony\Component\Console\Input\InputArgument;
6855 use Symfony\Component\Console\Input\InputInterface;
6856 use Symfony\Component\Console\Input\InputOption;
6857 use Symfony\Component\Console\Output\OutputInterface;
6858 use Symfony\Component\Console\Terminal;
6859
6860
6861
6862
6863
6864
6865
6866 class ShowCommand extends BaseCommand
6867 {
6868
6869 protected $versionParser;
6870 protected $colors;
6871
6872
6873 private $pool;
6874
6875 protected function configure()
6876 {
6877 $this
6878 ->setName('show')
6879 ->setAliases(array('info'))
6880 ->setDescription('Shows information about packages.')
6881 ->setDefinition(array(
6882 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
6883 new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
6884 new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'),
6885 new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'),
6886 new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
6887 new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
6888 new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
6889 new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
6890 new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
6891 new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
6892 new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'),
6893 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'),
6894 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
6895 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
6896 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
6897 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
6898 ))
6899 ->setHelp(<<<EOT
6900 The show command displays detailed information about a package, or
6901 lists all packages available.
6902
6903 EOT
6904 )
6905 ;
6906 }
6907
6908 protected function execute(InputInterface $input, OutputInterface $output)
6909 {
6910 $this->versionParser = new VersionParser;
6911 if ($input->getOption('tree')) {
6912 $this->initStyles($output);
6913 }
6914
6915 $composer = $this->getComposer(false);
6916 $io = $this->getIO();
6917
6918 if ($input->getOption('installed')) {
6919 $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>');
6920 }
6921
6922 if ($input->getOption('outdated')) {
6923 $input->setOption('latest', true);
6924 }
6925
6926 if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) {
6927 $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)');
6928
6929 return 1;
6930 }
6931
6932 if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) {
6933 $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)');
6934
6935 return 1;
6936 }
6937
6938 $format = $input->getOption('format');
6939 if (!in_array($format, array('text', 'json'))) {
6940 $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
6941
6942 return 1;
6943 }
6944
6945
6946  $platformOverrides = array();
6947 if ($composer) {
6948 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6949 }
6950 $platformRepo = new PlatformRepository(array(), $platformOverrides);
6951 $phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
6952
6953 if ($input->getOption('self')) {
6954 $package = $this->getComposer()->getPackage();
6955 $repos = $installedRepo = new ArrayRepository(array($package));
6956 } elseif ($input->getOption('platform')) {
6957 $repos = $installedRepo = $platformRepo;
6958 } elseif ($input->getOption('available')) {
6959 $installedRepo = $platformRepo;
6960 if ($composer) {
6961 $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
6962 } else {
6963 $defaultRepos = RepositoryFactory::defaultRepos($io);
6964 $repos = new CompositeRepository($defaultRepos);
6965 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
6966 }
6967 } elseif ($input->getOption('all') && $composer) {
6968 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6969 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6970 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6971 } elseif ($input->getOption('all')) {
6972 $defaultRepos = RepositoryFactory::defaultRepos($io);
6973 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
6974 $installedRepo = $platformRepo;
6975 $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
6976 } else {
6977 $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
6978 $rootPkg = $this->getComposer()->getPackage();
6979 if (!$installedRepo->getPackages() && ($rootPkg->getRequires() || $rootPkg->getDevRequires())) {
6980 $io->writeError('<warning>No dependencies installed. Try running composer install or update.</warning>');
6981 }
6982 }
6983
6984 if ($composer) {
6985 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
6986 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6987 }
6988
6989 if ($input->getOption('latest') && null === $composer) {
6990 $io->writeError('No composer.json found in the current directory, disabling "latest" option');
6991 $input->setOption('latest', false);
6992 }
6993
6994 $packageFilter = $input->getArgument('package');
6995
6996
6997  if (($packageFilter && false === strpos($packageFilter, '*')) || !empty($package)) {
6998 if ('json' === $format) {
6999 $io->writeError('Format "json" is only supported for package listings, falling back to format "text"');
7000 }
7001 if (empty($package)) {
7002 list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version'));
7003
7004 if (empty($package)) {
7005 $options = $input->getOptions();
7006 if (!isset($options['working-dir']) || !file_exists('composer.json')) {
7007 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found');
7008 }
7009
7010 $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
7011
7012 return 1;
7013 }
7014 } else {
7015 $versions = array($package->getPrettyVersion() => $package->getVersion());
7016 }
7017
7018 $exitCode = 0;
7019 if ($input->getOption('tree')) {
7020 $this->displayPackageTree($package, $installedRepo, $repos);
7021 } else {
7022 $latestPackage = null;
7023 if ($input->getOption('latest')) {
7024 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion);
7025 }
7026 if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
7027 $exitCode = 1;
7028 }
7029 $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
7030 $this->printLinks($package, 'requires');
7031 $this->printLinks($package, 'devRequires', 'requires (dev)');
7032 if ($package->getSuggests()) {
7033 $io->write("\n<info>suggests</info>");
7034 foreach ($package->getSuggests() as $suggested => $reason) {
7035 $io->write($suggested . ' <comment>' . $reason . '</comment>');
7036 }
7037 }
7038 $this->printLinks($package, 'provides');
7039 $this->printLinks($package, 'conflicts');
7040 $this->printLinks($package, 'replaces');
7041 }
7042
7043 return $exitCode;
7044 }
7045
7046
7047  if ($input->getOption('tree')) {
7048 if ('json' === $format) {
7049 $io->writeError('Format "json" is only supported for package listings, falling back to format "text"');
7050 }
7051 $rootRequires = $this->getRootRequires();
7052 $packages = $installedRepo->getPackages();
7053 usort($packages, 'strcmp');
7054 foreach ($packages as $package) {
7055 if (in_array($package->getName(), $rootRequires, true)) {
7056 $this->displayPackageTree($package, $installedRepo, $repos);
7057 }
7058 }
7059
7060 return 0;
7061 }
7062
7063 if ($repos instanceof CompositeRepository) {
7064 $repos = $repos->getRepositories();
7065 } elseif (!is_array($repos)) {
7066 $repos = array($repos);
7067 }
7068
7069
7070  $packages = array();
7071 if (null !== $packageFilter) {
7072 $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
7073 }
7074
7075 $packageListFilter = array();
7076 if ($input->getOption('direct')) {
7077 $packageListFilter = $this->getRootRequires();
7078 }
7079
7080 if (class_exists('Symfony\Component\Console\Terminal')) {
7081 $terminal = new Terminal();
7082 $width = $terminal->getWidth();
7083 } else {
7084
7085  list($width) = $this->getApplication()->getTerminalDimensions();
7086 }
7087 if (null === $width) {
7088
7089  
7090  $width = PHP_INT_MAX;
7091 }
7092 if (Platform::isWindows()) {
7093 $width--;
7094 } else {
7095 $width = max(80, $width);
7096 }
7097
7098 if ($input->getOption('path') && null === $composer) {
7099 $io->writeError('No composer.json found in the current directory, disabling "path" option');
7100 $input->setOption('path', false);
7101 }
7102
7103 foreach ($repos as $repo) {
7104 if ($repo === $platformRepo) {
7105 $type = 'platform';
7106 } elseif (
7107 $repo === $installedRepo
7108 || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
7109 ) {
7110 $type = 'installed';
7111 } else {
7112 $type = 'available';
7113 }
7114 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
7115 foreach ($repo->getProviderNames() as $name) {
7116 if (!$packageFilter || preg_match($packageFilter, $name)) {
7117 $packages[$type][$name] = $name;
7118 }
7119 }
7120 } else {
7121 foreach ($repo->getPackages() as $package) {
7122 if (!isset($packages[$type][$package->getName()])
7123 || !is_object($packages[$type][$package->getName()])
7124 || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
7125 ) {
7126 if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
7127 if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
7128 $packages[$type][$package->getName()] = $package;
7129 }
7130 }
7131 }
7132 }
7133 }
7134 }
7135
7136 $showAllTypes = $input->getOption('all');
7137 $showLatest = $input->getOption('latest');
7138 $showMinorOnly = $input->getOption('minor-only');
7139 $indent = $showAllTypes ? '  ' : '';
7140 $latestPackages = array();
7141 $exitCode = 0;
7142 $viewData = array();
7143 $viewMetaData = array();
7144 foreach (array('platform' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
7145 if (isset($packages[$type])) {
7146 ksort($packages[$type]);
7147
7148 $nameLength = $versionLength = $latestLength = 0;
7149 foreach ($packages[$type] as $package) {
7150 if (is_object($package)) {
7151 $nameLength = max($nameLength, strlen($package->getPrettyName()));
7152 if ($showVersion) {
7153 $versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
7154 if ($showLatest) {
7155 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion, $showMinorOnly);
7156 if ($latestPackage === false) {
7157 continue;
7158 }
7159
7160 $latestPackages[$package->getPrettyName()] = $latestPackage;
7161 $latestLength = max($latestLength, strlen($latestPackage->getFullPrettyVersion()));
7162 }
7163 }
7164 } else {
7165 $nameLength = max($nameLength, strlen($package));
7166 }
7167 }
7168
7169 $writePath = !$input->getOption('name-only') && $input->getOption('path');
7170 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
7171 $writeLatest = $writeVersion && $showLatest;
7172 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
7173
7174 $hasOutdatedPackages = false;
7175
7176 $viewData[$type] = array();
7177 $viewMetaData[$type] = array(
7178 'nameLength' => $nameLength,
7179 'versionLength' => $versionLength,
7180 'latestLength' => $latestLength,
7181 );
7182 foreach ($packages[$type] as $package) {
7183 $packageViewData = array();
7184 if (is_object($package)) {
7185 $latestPackage = null;
7186 if ($showLatest && isset($latestPackages[$package->getPrettyName()])) {
7187 $latestPackage = $latestPackages[$package->getPrettyName()];
7188 }
7189 if ($input->getOption('outdated') && $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
7190 continue;
7191 } elseif ($input->getOption('outdated') || $input->getOption('strict')) {
7192 $hasOutdatedPackages = true;
7193 }
7194
7195 $packageViewData['name'] = $package->getPrettyName();
7196 if ($writeVersion) {
7197 $packageViewData['version'] = $package->getFullPrettyVersion();
7198 }
7199 if ($writeLatest && $latestPackage) {
7200 $packageViewData['latest'] = $latestPackage->getFullPrettyVersion();
7201 $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
7202 }
7203 if ($writeDescription) {
7204 $packageViewData['description'] = $package->getDescription();
7205 }
7206 if ($writePath) {
7207 $packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
7208 }
7209
7210 if ($latestPackage && $latestPackage->isAbandoned()) {
7211 $replacement = (is_string($latestPackage->getReplacementPackage()))
7212 ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead'
7213 : 'No replacement was suggested';
7214 $packageWarning = sprintf(
7215 'Package %s is abandoned, you should avoid using it. %s.',
7216 $package->getPrettyName(),
7217 $replacement
7218 );
7219 $packageViewData['warning'] = $packageWarning;
7220 }
7221 } else {
7222 $packageViewData['name'] = $package;
7223 }
7224 $viewData[$type][] = $packageViewData;
7225 }
7226 if ($input->getOption('strict') && $hasOutdatedPackages) {
7227 $exitCode = 1;
7228 break;
7229 }
7230 }
7231 }
7232
7233 if ('json' === $format) {
7234 $io->write(JsonFile::encode($viewData));
7235 } else {
7236 foreach ($viewData as $type => $packages) {
7237 $nameLength = $viewMetaData[$type]['nameLength'];
7238 $versionLength = $viewMetaData[$type]['versionLength'];
7239 $latestLength = $viewMetaData[$type]['latestLength'];
7240
7241 $writeVersion = $nameLength + $versionLength + 3 <= $width;
7242 $writeLatest = $nameLength + $versionLength + $latestLength + 3 <= $width;
7243 $writeDescription = $nameLength + $versionLength + $latestLength + 24 <= $width;
7244
7245 if ($writeLatest && !$io->isDecorated()) {
7246 $latestLength += 2;
7247 }
7248
7249 if ($showAllTypes) {
7250 if ('available' === $type) {
7251 $io->write('<comment>' . $type . '</comment>:');
7252 } else {
7253 $io->write('<info>' . $type . '</info>:');
7254 }
7255 }
7256
7257 foreach ($packages as $package) {
7258 $io->write($indent . str_pad($package['name'], $nameLength, ' '), false);
7259 if (isset($package['version']) && $writeVersion) {
7260 $io->write(' ' . str_pad($package['version'], $versionLength, ' '), false);
7261 }
7262 if (isset($package['latest']) && $writeLatest) {
7263 $latestVersion = $package['latest'];
7264 $updateStatus = $package['latest-status'];
7265 $style = $this->updateStatusToVersionStyle($updateStatus);
7266 if (!$io->isDecorated()) {
7267 $latestVersion = str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('=', '!', '~'), $updateStatus) . ' ' . $latestVersion;
7268 }
7269 $io->write(' <' . $style . '>' . str_pad($latestVersion, $latestLength, ' ') . '</' . $style . '>', false);
7270 }
7271 if (isset($package['description']) && $writeDescription) {
7272 $description = strtok($package['description'], "\r\n");
7273 $remaining = $width - $nameLength - $versionLength - 4;
7274 if ($writeLatest) {
7275 $remaining -= $latestLength;
7276 }
7277 if (strlen($description) > $remaining) {
7278 $description = substr($description, 0, $remaining - 3) . '...';
7279 }
7280 $io->write(' ' . $description, false);
7281 }
7282 if (isset($package['path'])) {
7283 $io->write(' ' . $package['path'], false);
7284 }
7285 $io->write('');
7286 if (isset($package['warning'])) {
7287 $io->write('<warning>' . $package['warning'] . '</warning>');
7288 }
7289 }
7290
7291 if ($showAllTypes) {
7292 $io->write('');
7293 }
7294 }
7295 }
7296
7297 return $exitCode;
7298 }
7299
7300 protected function getRootRequires()
7301 {
7302 $rootPackage = $this->getComposer()->getPackage();
7303
7304 return array_map(
7305 'strtolower',
7306 array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))
7307 );
7308 }
7309
7310 protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package)
7311 {
7312 return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package));
7313 }
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325 protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
7326 {
7327 $name = strtolower($name);
7328 $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
7329
7330 $policy = new DefaultPolicy();
7331 $pool = new Pool('dev');
7332 $pool->addRepository($repos);
7333
7334 $matchedPackage = null;
7335 $versions = array();
7336 $matches = $pool->whatProvides($name, $constraint);
7337 foreach ($matches as $index => $package) {
7338
7339  if ($package->getName() !== $name) {
7340 unset($matches[$index]);
7341 continue;
7342 }
7343
7344
7345  if (null === $version && $installedRepo->hasPackage($package)) {
7346 $matchedPackage = $package;
7347 }
7348
7349 $versions[$package->getPrettyVersion()] = $package->getVersion();
7350 $matches[$index] = $package->getId();
7351 }
7352
7353
7354  if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
7355 $matchedPackage = $pool->literalToPackage($preferred[0]);
7356 }
7357
7358 return array($matchedPackage, $versions);
7359 }
7360
7361
7362
7363
7364
7365
7366
7367
7368 protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
7369 {
7370 $io = $this->getIO();
7371 $io->write('<info>name</info>     : ' . $package->getPrettyName());
7372 $io->write('<info>descrip.</info> : ' . $package->getDescription());
7373 $io->write('<info>keywords</info> : ' . implode(', ', $package->getKeywords() ?: array()));
7374 $this->printVersions($package, $versions, $installedRepo);
7375 if ($latestPackage) {
7376 $style = $this->getVersionStyle($latestPackage, $package);
7377 $io->write('<info>latest</info>   : <'.$style.'>' . $latestPackage->getPrettyVersion() . '</'.$style.'>');
7378 } else {
7379 $latestPackage = $package;
7380 }
7381 $io->write('<info>type</info>     : ' . $package->getType());
7382 $this->printLicenses($package);
7383 $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
7384 $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
7385 $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
7386
7387 if ($latestPackage->isAbandoned()) {
7388 $replacement = ($latestPackage->getReplacementPackage() !== null)
7389 ? ' The author suggests using the ' . $latestPackage->getReplacementPackage(). ' package instead.'
7390 : null;
7391
7392 $io->writeError(
7393 sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
7394 );
7395 }
7396
7397 if ($package->getSupport()) {
7398 $io->write("\n<info>support</info>");
7399 foreach ($package->getSupport() as $type => $value) {
7400 $io->write('<comment>' . $type . '</comment> : '.$value);
7401 }
7402 }
7403
7404 if ($package->getAutoload()) {
7405 $io->write("\n<info>autoload</info>");
7406 foreach ($package->getAutoload() as $type => $autoloads) {
7407 $io->write('<comment>' . $type . '</comment>');
7408
7409 if ($type === 'psr-0') {
7410 foreach ($autoloads as $name => $path) {
7411 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7412 }
7413 } elseif ($type === 'psr-4') {
7414 foreach ($autoloads as $name => $path) {
7415 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7416 }
7417 } elseif ($type === 'classmap') {
7418 $io->write(implode(', ', $autoloads));
7419 }
7420 }
7421 if ($package->getIncludePaths()) {
7422 $io->write('<comment>include-path</comment>');
7423 $io->write(implode(', ', $package->getIncludePaths()));
7424 }
7425 }
7426 }
7427
7428
7429
7430
7431
7432
7433
7434
7435 protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
7436 {
7437 uasort($versions, 'version_compare');
7438 $versions = array_keys(array_reverse($versions));
7439
7440
7441  if ($installedRepo->hasPackage($package)) {
7442 $installedVersion = $package->getPrettyVersion();
7443 $key = array_search($installedVersion, $versions);
7444 if (false !== $key) {
7445 $versions[$key] = '<info>* ' . $installedVersion . '</info>';
7446 }
7447 }
7448
7449 $versions = implode(', ', $versions);
7450
7451 $this->getIO()->write('<info>versions</info> : ' . $versions);
7452 }
7453
7454
7455
7456
7457
7458
7459
7460
7461 protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
7462 {
7463 $title = $title ?: $linkType;
7464 $io = $this->getIO();
7465 if ($links = $package->{'get'.ucfirst($linkType)}()) {
7466 $io->write("\n<info>" . $title . "</info>");
7467
7468 foreach ($links as $link) {
7469 $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
7470 }
7471 }
7472 }
7473
7474
7475
7476
7477
7478
7479 protected function printLicenses(CompletePackageInterface $package)
7480 {
7481 $spdxLicenses = new SpdxLicenses();
7482
7483 $licenses = $package->getLicense();
7484 $io = $this->getIO();
7485
7486 foreach ($licenses as $licenseId) {
7487 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
7488
7489 if (!$license) {
7490 $out = $licenseId;
7491 } else {
7492
7493  if ($license[1] === true) {
7494 $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
7495 } else {
7496 $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
7497 }
7498 }
7499
7500 $io->write('<info>license</info>  : ' . $out);
7501 }
7502 }
7503
7504
7505
7506
7507
7508
7509 protected function initStyles(OutputInterface $output)
7510 {
7511 $this->colors = array(
7512 'green',
7513 'yellow',
7514 'cyan',
7515 'magenta',
7516 'blue',
7517 );
7518
7519 foreach ($this->colors as $color) {
7520 $style = new OutputFormatterStyle($color);
7521 $output->getFormatter()->setStyle($color, $style);
7522 }
7523 }
7524
7525
7526
7527
7528
7529
7530
7531
7532 protected function displayPackageTree(PackageInterface $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos)
7533 {
7534 $io = $this->getIO();
7535 $io->write(sprintf('<info>%s</info>', $package->getPrettyName()), false);
7536 $io->write(' ' . $package->getPrettyVersion(), false);
7537 $io->write(' ' . strtok($package->getDescription(), "\r\n"));
7538
7539 if (is_object($package)) {
7540 $requires = $package->getRequires();
7541 ksort($requires);
7542 $treeBar = '├';
7543 $j = 0;
7544 $total = count($requires);
7545 foreach ($requires as $requireName => $require) {
7546 $j++;
7547 if ($j == 0) {
7548 $this->writeTreeLine($treeBar);
7549 }
7550 if ($j == $total) {
7551 $treeBar = '└';
7552 }
7553 $level = 1;
7554 $color = $this->colors[$level];
7555 $info = sprintf('%s──<%s>%s</%s> %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint());
7556 $this->writeTreeLine($info);
7557
7558 $treeBar = str_replace('└', ' ', $treeBar);
7559 $packagesInTree = array($package->getName(), $requireName);
7560
7561 $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree, $treeBar, $level + 1);
7562 }
7563 }
7564 }
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577 protected function displayTree($name, $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos, array $packagesInTree, $previousTreeBar = '├', $level = 1)
7578 {
7579 $previousTreeBar = str_replace('├', '│', $previousTreeBar);
7580 list($package, $versions) = $this->getPackage($installedRepo, $distantRepos, $name, $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint());
7581 if (is_object($package)) {
7582 $requires = $package->getRequires();
7583 ksort($requires);
7584 $treeBar = $previousTreeBar . '  ├';
7585 $i = 0;
7586 $total = count($requires);
7587 foreach ($requires as $requireName => $require) {
7588 $currentTree = $packagesInTree;
7589 $i++;
7590 if ($i == $total) {
7591 $treeBar = $previousTreeBar . '  └';
7592 }
7593 $colorIdent = $level % count($this->colors);
7594 $color = $this->colors[$colorIdent];
7595
7596 $circularWarn = in_array($requireName, $currentTree) ? '(circular dependency aborted here)' : '';
7597 $info = rtrim(sprintf('%s──<%s>%s</%s> %s %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint(), $circularWarn));
7598 $this->writeTreeLine($info);
7599
7600 $treeBar = str_replace('└', ' ', $treeBar);
7601 if (!in_array($requireName, $currentTree)) {
7602 $currentTree[] = $requireName;
7603 $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $currentTree, $treeBar, $level + 1);
7604 }
7605 }
7606 }
7607 }
7608
7609 private function updateStatusToVersionStyle($updateStatus)
7610 {
7611
7612  
7613  
7614  return str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('info', 'highlight', 'comment'), $updateStatus);
7615 }
7616
7617 private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package)
7618 {
7619 if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) {
7620 return 'up-to-date';
7621 }
7622
7623 $constraint = $package->getVersion();
7624 if (0 !== strpos($constraint, 'dev-')) {
7625 $constraint = '^'.$constraint;
7626 }
7627 if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) {
7628
7629  return 'semver-safe-update';
7630 }
7631
7632
7633  return 'update-possible';
7634 }
7635
7636 private function writeTreeLine($line)
7637 {
7638 $io = $this->getIO();
7639 if (!$io->isDecorated()) {
7640 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
7641 }
7642
7643 $io->write($line);
7644 }
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656 private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
7657 {
7658
7659  $name = $package->getName();
7660 $versionSelector = new VersionSelector($this->getPool($composer));
7661 $stability = $composer->getPackage()->getMinimumStability();
7662 $flags = $composer->getPackage()->getStabilityFlags();
7663 if (isset($flags[$name])) {
7664 $stability = array_search($flags[$name], BasePackage::$stabilities, true);
7665 }
7666
7667 $bestStability = $stability;
7668 if ($composer->getPackage()->getPreferStable()) {
7669 $bestStability = $package->getStability();
7670 }
7671
7672 $targetVersion = null;
7673 if (0 === strpos($package->getVersion(), 'dev-')) {
7674 $targetVersion = $package->getVersion();
7675 }
7676
7677 if ($targetVersion === null && $minorOnly) {
7678 $targetVersion = '^' . $package->getVersion();
7679 }
7680
7681 return $versionSelector->findBestCandidate($name, $targetVersion, $phpVersion, $bestStability);
7682 }
7683
7684 private function getPool(Composer $composer)
7685 {
7686 if (!$this->pool) {
7687 $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
7688 $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
7689 }
7690
7691 return $this->pool;
7692 }
7693 }
7694 <?php
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706 namespace Composer\Command;
7707
7708 use Symfony\Component\Console\Input\InputInterface;
7709 use Symfony\Component\Console\Input\InputOption;
7710 use Symfony\Component\Console\Output\OutputInterface;
7711 use Composer\Downloader\ChangeReportInterface;
7712 use Composer\Downloader\DvcsDownloaderInterface;
7713 use Composer\Downloader\VcsCapableDownloaderInterface;
7714 use Composer\Package\Dumper\ArrayDumper;
7715 use Composer\Package\Version\VersionGuesser;
7716 use Composer\Package\Version\VersionParser;
7717 use Composer\Plugin\CommandEvent;
7718 use Composer\Plugin\PluginEvents;
7719 use Composer\Script\ScriptEvents;
7720 use Composer\Util\ProcessExecutor;
7721
7722
7723
7724
7725
7726 class StatusCommand extends BaseCommand
7727 {
7728 const EXIT_CODE_ERRORS = 1;
7729 const EXIT_CODE_UNPUSHED_CHANGES = 2;
7730 const EXIT_CODE_VERSION_CHANGES = 4;
7731
7732 protected function configure()
7733 {
7734 $this
7735 ->setName('status')
7736 ->setDescription('Shows a list of locally modified packages.')
7737 ->setDefinition(array(
7738 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
7739 ))
7740 ->setHelp(<<<EOT
7741 The status command displays a list of dependencies that have
7742 been modified locally.
7743
7744 EOT
7745 )
7746 ;
7747 }
7748
7749 protected function execute(InputInterface $input, OutputInterface $output)
7750 {
7751
7752  $composer = $this->getComposer();
7753
7754 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
7755 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7756
7757 $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
7758
7759 $dm = $composer->getDownloadManager();
7760 $im = $composer->getInstallationManager();
7761
7762
7763  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
7764
7765 $errors = array();
7766 $io = $this->getIO();
7767 $unpushedChanges = array();
7768 $vcsVersionChanges = array();
7769
7770 $parser = new VersionParser;
7771 $guesser = new VersionGuesser($composer->getConfig(), new ProcessExecutor($io), $parser);
7772 $dumper = new ArrayDumper;
7773
7774
7775  foreach ($installedRepo->getCanonicalPackages() as $package) {
7776 $downloader = $dm->getDownloaderForInstalledPackage($package);
7777 $targetDir = $im->getInstallPath($package);
7778
7779 if ($downloader instanceof ChangeReportInterface) {
7780 if (is_link($targetDir)) {
7781 $errors[$targetDir] = $targetDir . ' is a symbolic link.';
7782 }
7783
7784 if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
7785 $errors[$targetDir] = $changes;
7786 }
7787 }
7788
7789 if ($downloader instanceof VcsCapableDownloaderInterface) {
7790 if ($currentRef = $downloader->getVcsReference($package, $targetDir)) {
7791 switch ($package->getInstallationSource()) {
7792 case 'source':
7793 $previousRef = $package->getSourceReference();
7794 break;
7795 case 'dist':
7796 $previousRef = $package->getDistReference();
7797 break;
7798 default:
7799 $previousRef = null;
7800 }
7801
7802 $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir);
7803
7804 if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef) {
7805 $vcsVersionChanges[$targetDir] = array(
7806 'previous' => array(
7807 'version' => $package->getPrettyVersion(),
7808 'ref' => $previousRef,
7809 ),
7810 'current' => array(
7811 'version' => $currentVersion['pretty_version'],
7812 'ref' => $currentVersion['commit'],
7813 ),
7814 );
7815 }
7816 }
7817 }
7818
7819 if ($downloader instanceof DvcsDownloaderInterface) {
7820 if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
7821 $unpushedChanges[$targetDir] = $unpushed;
7822 }
7823 }
7824 }
7825
7826
7827  if (!$errors && !$unpushedChanges && !$vcsVersionChanges) {
7828 $io->writeError('<info>No local changes</info>');
7829
7830 return 0;
7831 }
7832
7833 if ($errors) {
7834 $io->writeError('<error>You have changes in the following dependencies:</error>');
7835
7836 foreach ($errors as $path => $changes) {
7837 if ($input->getOption('verbose')) {
7838 $indentedChanges = implode("\n", array_map(function ($line) {
7839 return '    ' . ltrim($line);
7840 }, explode("\n", $changes)));
7841 $io->write('<info>'.$path.'</info>:');
7842 $io->write($indentedChanges);
7843 } else {
7844 $io->write($path);
7845 }
7846 }
7847 }
7848
7849 if ($unpushedChanges) {
7850 $io->writeError('<warning>You have unpushed changes on the current branch in the following dependencies:</warning>');
7851
7852 foreach ($unpushedChanges as $path => $changes) {
7853 if ($input->getOption('verbose')) {
7854 $indentedChanges = implode("\n", array_map(function ($line) {
7855 return '    ' . ltrim($line);
7856 }, explode("\n", $changes)));
7857 $io->write('<info>'.$path.'</info>:');
7858 $io->write($indentedChanges);
7859 } else {
7860 $io->write($path);
7861 }
7862 }
7863 }
7864
7865 if ($vcsVersionChanges) {
7866 $io->writeError('<warning>You have version variations in the following dependencies:</warning>');
7867
7868 foreach ($vcsVersionChanges as $path => $changes) {
7869 if ($input->getOption('verbose')) {
7870
7871  $currentVersion = $changes['current']['version'] ?: $changes['current']['ref'];
7872 $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref'];
7873
7874 if ($io->isVeryVerbose()) {
7875
7876  $currentVersion .= sprintf(' (%s)', $changes['current']['ref']);
7877 $previousVersion .= sprintf(' (%s)', $changes['previous']['ref']);
7878 }
7879
7880 $io->write('<info>'.$path.'</info>:');
7881 $io->write(sprintf('    From <comment>%s</comment> to <comment>%s</comment>', $previousVersion, $currentVersion));
7882 } else {
7883 $io->write($path);
7884 }
7885 }
7886 }
7887
7888 if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) {
7889 $io->writeError('Use --verbose (-v) to see a list of files');
7890 }
7891
7892
7893  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
7894
7895 return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0);
7896 }
7897 }
7898 <?php
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910 namespace Composer\Command;
7911
7912 use Composer\Repository\PlatformRepository;
7913 use Symfony\Component\Console\Input\InputArgument;
7914 use Symfony\Component\Console\Input\InputInterface;
7915 use Symfony\Component\Console\Input\InputOption;
7916 use Symfony\Component\Console\Output\OutputInterface;
7917
7918 class SuggestsCommand extends BaseCommand
7919 {
7920 protected function configure()
7921 {
7922 $this
7923 ->setName('suggests')
7924 ->setDescription('Shows package suggestions.')
7925 ->setDefinition(array(
7926 new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package'),
7927 new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'),
7928 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
7929 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
7930 ))
7931 ->setHelp(<<<EOT
7932
7933 The <info>%command.name%</info> command shows a sorted list of suggested packages.
7934
7935 Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
7936
7937 EOT
7938 )
7939 ;
7940 }
7941
7942 protected function execute(InputInterface $input, OutputInterface $output)
7943 {
7944 $lock = $this->getComposer()->getLocker()->getLockData();
7945
7946 if (empty($lock)) {
7947 throw new \RuntimeException('Lockfile seems to be empty?');
7948 }
7949
7950 $packages = $lock['packages'];
7951
7952 if (!$input->getOption('no-dev')) {
7953 $packages += $lock['packages-dev'];
7954 }
7955
7956 $filter = $input->getArgument('packages');
7957
7958
7959  $installed = array();
7960 foreach ($packages as $package) {
7961 $installed[] = $package['name'];
7962
7963 if (!empty($package['provide'])) {
7964 $installed = array_merge($installed, array_keys($package['provide']));
7965 }
7966
7967 if (!empty($package['replace'])) {
7968 $installed = array_merge($installed, array_keys($package['replace']));
7969 }
7970 }
7971
7972
7973  $installed = array_flip($installed);
7974 ksort($installed);
7975
7976
7977  $platform = new PlatformRepository(array(), $this->getComposer()->getConfig()->get('platform') ?: array());
7978
7979
7980  $suggesters = array();
7981 $suggested = array();
7982 foreach ($packages as $package) {
7983 $packageName = $package['name'];
7984 if ((!empty($filter) && !in_array($packageName, $filter)) || empty($package['suggest'])) {
7985 continue;
7986 }
7987 foreach ($package['suggest'] as $suggestion => $reason) {
7988 if (false === strpos('/', $suggestion) && null !== $platform->findPackage($suggestion, '*')) {
7989 continue;
7990 }
7991 if (!isset($installed[$suggestion])) {
7992 $suggesters[$packageName][$suggestion] = $reason;
7993 $suggested[$suggestion][$packageName] = $reason;
7994 }
7995 }
7996 }
7997 ksort($suggesters);
7998 ksort($suggested);
7999
8000
8001  $mode = 0;
8002 $io = $this->getIO();
8003 if ($input->getOption('by-package') || $io->isVerbose()) {
8004 $mode |= 1;
8005 }
8006 if ($input->getOption('by-suggestion')) {
8007 $mode |= 2;
8008 }
8009
8010
8011  if ($mode === 0) {
8012 foreach (array_keys($suggested) as $suggestion) {
8013 $io->write(sprintf('<info>%s</info>', $suggestion));
8014 }
8015
8016 return;
8017 }
8018
8019
8020  if ($mode & 1) {
8021 foreach ($suggesters as $suggester => $suggestions) {
8022 $io->write(sprintf('<comment>%s</comment> suggests:', $suggester));
8023
8024 foreach ($suggestions as $suggestion => $reason) {
8025 $io->write(sprintf(' - <info>%s</info>: %s', $suggestion, $reason ?: '*'));
8026 }
8027 $io->write('');
8028 }
8029 }
8030
8031
8032  if ($mode & 2) {
8033
8034  if ($mode & 1) {
8035 $io->write(str_repeat('-', 78));
8036 }
8037 foreach ($suggested as $suggestion => $suggesters) {
8038 $io->write(sprintf('<comment>%s</comment> is suggested by:', $suggestion));
8039
8040 foreach ($suggesters as $suggester => $reason) {
8041 $io->write(sprintf(' - <info>%s</info>: %s', $suggester, $reason ?: '*'));
8042 }
8043 $io->write('');
8044 }
8045 }
8046 }
8047 }
8048 <?php
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060 namespace Composer\Command;
8061
8062 use Composer\Composer;
8063 use Composer\Installer;
8064 use Composer\IO\IOInterface;
8065 use Composer\Plugin\CommandEvent;
8066 use Composer\Plugin\PluginEvents;
8067 use Symfony\Component\Console\Helper\Table;
8068 use Symfony\Component\Console\Input\InputInterface;
8069 use Symfony\Component\Console\Input\InputOption;
8070 use Symfony\Component\Console\Input\InputArgument;
8071 use Symfony\Component\Console\Output\OutputInterface;
8072 use Symfony\Component\Console\Question\Question;
8073
8074
8075
8076
8077
8078 class UpdateCommand extends BaseCommand
8079 {
8080 protected function configure()
8081 {
8082 $this
8083 ->setName('update')
8084 ->setAliases(array('upgrade'))
8085 ->setDescription('Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
8086 ->setDefinition(array(
8087 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
8088 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
8089 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
8090 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
8091 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
8092 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
8093 new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
8094 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
8095 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
8096 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
8097 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
8098 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
8099 new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also dependencies of whitelisted packages to the whitelist, except those defined in root package.'),
8100 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.'),
8101 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
8102 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
8103 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
8104 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
8105 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
8106 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
8107 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
8108 new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
8109 new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
8110 ))
8111 ->setHelp(<<<EOT
8112 The <info>update</info> command reads the composer.json file from the
8113 current directory, processes it, and updates, removes or installs all the
8114 dependencies.
8115
8116 <info>php composer.phar update</info>
8117
8118 To limit the update operation to a few packages, you can list the package(s)
8119 you want to update as such:
8120
8121 <info>php composer.phar update vendor/package1 foo/mypackage [...]</info>
8122
8123 You may also use an asterisk (*) pattern to limit the update operation to package(s)
8124 from a specific vendor:
8125
8126 <info>php composer.phar update vendor/package1 foo/* [...]</info>
8127
8128 To select packages names interactively with auto-completion use <info>-i</info>.
8129
8130 EOT
8131 )
8132 ;
8133 }
8134
8135 protected function execute(InputInterface $input, OutputInterface $output)
8136 {
8137 $io = $this->getIO();
8138 if ($input->getOption('no-custom-installers')) {
8139 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
8140 $input->setOption('no-plugins', true);
8141 }
8142
8143 if ($input->getOption('dev')) {
8144 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
8145 }
8146
8147 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
8148
8149 $packages = $input->getArgument('packages');
8150
8151 if ($input->getOption('interactive')) {
8152 $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
8153 }
8154
8155 if ($input->getOption('root-reqs')) {
8156 $require = array_keys($composer->getPackage()->getRequires());
8157 if (!$input->getOption('no-dev')) {
8158 $requireDev = array_keys($composer->getPackage()->getDevRequires());
8159 $require = array_merge($require, $requireDev);
8160 }
8161
8162 if (!empty($packages)) {
8163 $packages = array_intersect($packages, $require);
8164 } else {
8165 $packages = $require;
8166 }
8167 }
8168
8169 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
8170
8171 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
8172 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8173
8174 $install = Installer::create($io, $composer);
8175
8176 $config = $composer->getConfig();
8177 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
8178
8179 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
8180 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
8181 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
8182
8183 $install
8184 ->setDryRun($input->getOption('dry-run'))
8185 ->setVerbose($input->getOption('verbose'))
8186 ->setPreferSource($preferSource)
8187 ->setPreferDist($preferDist)
8188 ->setDevMode(!$input->getOption('no-dev'))
8189 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
8190 ->setRunScripts(!$input->getOption('no-scripts'))
8191 ->setSkipSuggest($input->getOption('no-suggest'))
8192 ->setOptimizeAutoloader($optimize)
8193 ->setClassMapAuthoritative($authoritative)
8194 ->setApcuAutoloader($apcu)
8195 ->setUpdate(true)
8196 ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages)
8197 ->setWhitelistTransitiveDependencies($input->getOption('with-dependencies'))
8198 ->setWhitelistAllDependencies($input->getOption('with-all-dependencies'))
8199 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
8200 ->setPreferStable($input->getOption('prefer-stable'))
8201 ->setPreferLowest($input->getOption('prefer-lowest'))
8202 ;
8203
8204 if ($input->getOption('no-plugins')) {
8205 $install->disablePlugins();
8206 }
8207
8208 return $install->run();
8209 }
8210
8211 private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages)
8212 {
8213 if (!$input->isInteractive()) {
8214 throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
8215 }
8216
8217 $requires = array_merge(
8218 $composer->getPackage()->getRequires(),
8219 $composer->getPackage()->getDevRequires()
8220 );
8221 $autocompleterValues = array();
8222 foreach ($requires as $require) {
8223 $target = $require->getTarget();
8224 $autocompleterValues[strtolower($target)] = $target;
8225 }
8226
8227 $installedPackages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
8228 foreach ($installedPackages as $package) {
8229 $autocompleterValues[$package->getName()] = $package->getPrettyName();
8230 }
8231
8232 $helper = $this->getHelper('question');
8233 $question = new Question('<comment>Enter package name: </comment>', null);
8234
8235 $io->writeError('<info>Press enter without value to end submission</info>');
8236
8237 do {
8238 $autocompleterValues = array_diff($autocompleterValues, $packages);
8239 $question->setAutocompleterValues($autocompleterValues);
8240 $addedPackage = $helper->ask($input, $output, $question);
8241
8242 if (!is_string($addedPackage) || empty($addedPackage)) {
8243 break;
8244 }
8245
8246 $addedPackage = strtolower($addedPackage);
8247 if (!in_array($addedPackage, $packages)) {
8248 $packages[] = $addedPackage;
8249 }
8250 } while (true);
8251
8252 $packages = array_filter($packages);
8253 if (!$packages) {
8254 throw new \InvalidArgumentException('You must enter minimum one package.');
8255 }
8256
8257 $table = new Table($output);
8258 $table->setHeaders(array('Selected packages'));
8259 foreach ($packages as $package) {
8260 $table->addRow(array($package));
8261 }
8262 $table->render();
8263
8264 if ($io->askConfirmation(sprintf(
8265 'Would you like to continue and update the above package%s [<comment>yes</comment>]? ',
8266 1 === count($packages) ? '' : 's'
8267 ), true)) {
8268 return $packages;
8269 }
8270
8271 throw new \RuntimeException('Installation aborted.');
8272 }
8273 }
8274 <?php
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286 namespace Composer\Command;
8287
8288 use Composer\Factory;
8289 use Composer\Package\Loader\ValidatingArrayLoader;
8290 use Composer\Plugin\CommandEvent;
8291 use Composer\Plugin\PluginEvents;
8292 use Composer\Util\ConfigValidator;
8293 use Symfony\Component\Console\Input\InputArgument;
8294 use Symfony\Component\Console\Input\InputInterface;
8295 use Symfony\Component\Console\Input\InputOption;
8296 use Symfony\Component\Console\Output\OutputInterface;
8297
8298
8299
8300
8301
8302
8303
8304 class ValidateCommand extends BaseCommand
8305 {
8306
8307
8308
8309 protected function configure()
8310 {
8311 $this
8312 ->setName('validate')
8313 ->setDescription('Validates a composer.json and composer.lock.')
8314 ->setDefinition(array(
8315 new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'),
8316 new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
8317 new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
8318 new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
8319 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
8320 new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file'),
8321 ))
8322 ->setHelp(<<<EOT
8323 The validate command validates a given composer.json and composer.lock
8324
8325 Exit codes in case of errors are:
8326 1 validation warning(s), only when --strict is given
8327 2 validation error(s)
8328 3 file unreadable or missing
8329
8330 EOT
8331 );
8332 }
8333
8334
8335
8336
8337
8338
8339
8340 protected function execute(InputInterface $input, OutputInterface $output)
8341 {
8342 $file = $input->getArgument('file') ?: Factory::getComposerFile();
8343 $io = $this->getIO();
8344
8345 if (!file_exists($file)) {
8346 $io->writeError('<error>' . $file . ' not found.</error>');
8347
8348 return 3;
8349 }
8350 if (!is_readable($file)) {
8351 $io->writeError('<error>' . $file . ' is not readable.</error>');
8352
8353 return 3;
8354 }
8355
8356 $validator = new ConfigValidator($io);
8357 $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
8358 $checkPublish = !$input->getOption('no-check-publish');
8359 $checkLock = !$input->getOption('no-check-lock');
8360 $isStrict = $input->getOption('strict');
8361 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8362
8363 $lockErrors = array();
8364 $composer = Factory::create($io, $file);
8365 $locker = $composer->getLocker();
8366 if ($locker->isLocked() && !$locker->isFresh()) {
8367 $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update`.';
8368 }
8369
8370 $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true);
8371
8372 $exitCode = $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 2 : ($isStrict && $warnings ? 1 : 0);
8373
8374 if ($input->getOption('with-dependencies')) {
8375 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
8376 foreach ($localRepo->getPackages() as $package) {
8377 $path = $composer->getInstallationManager()->getInstallPath($package);
8378 $file = $path . '/composer.json';
8379 if (is_dir($path) && file_exists($file)) {
8380 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8381 $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
8382
8383 $depCode = $errors || ($publishErrors && $checkPublish) ? 2 : ($isStrict && $warnings ? 1 : 0);
8384 $exitCode = max($depCode, $exitCode);
8385 }
8386 }
8387 }
8388
8389 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
8390 $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8391 $exitCode = max($eventCode, $exitCode);
8392
8393 return $exitCode;
8394 }
8395
8396 private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false)
8397 {
8398 if (!$errors && !$publishErrors && !$warnings) {
8399 $io->write('<info>' . $name . ' is valid</info>');
8400 } elseif (!$errors && !$publishErrors) {
8401 $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
8402 if ($printSchemaUrl) {
8403 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8404 }
8405 } elseif (!$errors) {
8406 $io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
8407 $io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
8408 if ($printSchemaUrl) {
8409 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8410 }
8411 } else {
8412 $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
8413 }
8414
8415
8416  if ($checkPublish) {
8417 $errors = array_merge($errors, $publishErrors);
8418 } else {
8419 $warnings = array_merge($warnings, $publishErrors);
8420 }
8421
8422
8423  if ($checkLock) {
8424 $errors = array_merge($errors, $lockErrors);
8425 } else {
8426 $warnings = array_merge($warnings, $lockErrors);
8427 }
8428
8429 $messages = array(
8430 'error' => $errors,
8431 'warning' => $warnings,
8432 );
8433
8434 foreach ($messages as $style => $msgs) {
8435 foreach ($msgs as $msg) {
8436 $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
8437 }
8438 }
8439 }
8440 }
8441 <?php
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453 namespace Composer;
8454
8455 use Composer\Package\RootPackageInterface;
8456 use Composer\Package\Locker;
8457 use Composer\Repository\RepositoryManager;
8458 use Composer\Installer\InstallationManager;
8459 use Composer\Plugin\PluginManager;
8460 use Composer\Downloader\DownloadManager;
8461 use Composer\EventDispatcher\EventDispatcher;
8462 use Composer\Autoload\AutoloadGenerator;
8463 use Composer\Package\Archiver\ArchiveManager;
8464
8465
8466
8467
8468
8469
8470 class Composer
8471 {
8472 const VERSION = '1.6.3';
8473 const BRANCH_ALIAS_VERSION = '';
8474 const RELEASE_DATE = '2018-01-31 16:28:17';
8475
8476
8477
8478
8479 private $package;
8480
8481
8482
8483
8484 private $locker;
8485
8486
8487
8488
8489 private $repositoryManager;
8490
8491
8492
8493
8494 private $downloadManager;
8495
8496
8497
8498
8499 private $installationManager;
8500
8501
8502
8503
8504 private $pluginManager;
8505
8506
8507
8508
8509 private $config;
8510
8511
8512
8513
8514 private $eventDispatcher;
8515
8516
8517
8518
8519 private $autoloadGenerator;
8520
8521
8522
8523
8524 private $archiveManager;
8525
8526
8527
8528
8529
8530 public function setPackage(RootPackageInterface $package)
8531 {
8532 $this->package = $package;
8533 }
8534
8535
8536
8537
8538 public function getPackage()
8539 {
8540 return $this->package;
8541 }
8542
8543
8544
8545
8546 public function setConfig(Config $config)
8547 {
8548 $this->config = $config;
8549 }
8550
8551
8552
8553
8554 public function getConfig()
8555 {
8556 return $this->config;
8557 }
8558
8559
8560
8561
8562 public function setLocker(Locker $locker)
8563 {
8564 $this->locker = $locker;
8565 }
8566
8567
8568
8569
8570 public function getLocker()
8571 {
8572 return $this->locker;
8573 }
8574
8575
8576
8577
8578 public function setRepositoryManager(RepositoryManager $manager)
8579 {
8580 $this->repositoryManager = $manager;
8581 }
8582
8583
8584
8585
8586 public function getRepositoryManager()
8587 {
8588 return $this->repositoryManager;
8589 }
8590
8591
8592
8593
8594 public function setDownloadManager(DownloadManager $manager)
8595 {
8596 $this->downloadManager = $manager;
8597 }
8598
8599
8600
8601
8602 public function getDownloadManager()
8603 {
8604 return $this->downloadManager;
8605 }
8606
8607
8608
8609
8610 public function setArchiveManager(ArchiveManager $manager)
8611 {
8612 $this->archiveManager = $manager;
8613 }
8614
8615
8616
8617
8618 public function getArchiveManager()
8619 {
8620 return $this->archiveManager;
8621 }
8622
8623
8624
8625
8626 public function setInstallationManager(InstallationManager $manager)
8627 {
8628 $this->installationManager = $manager;
8629 }
8630
8631
8632
8633
8634 public function getInstallationManager()
8635 {
8636 return $this->installationManager;
8637 }
8638
8639
8640
8641
8642 public function setPluginManager(PluginManager $manager)
8643 {
8644 $this->pluginManager = $manager;
8645 }
8646
8647
8648
8649
8650 public function getPluginManager()
8651 {
8652 return $this->pluginManager;
8653 }
8654
8655
8656
8657
8658 public function setEventDispatcher(EventDispatcher $eventDispatcher)
8659 {
8660 $this->eventDispatcher = $eventDispatcher;
8661 }
8662
8663
8664
8665
8666 public function getEventDispatcher()
8667 {
8668 return $this->eventDispatcher;
8669 }
8670
8671
8672
8673
8674 public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
8675 {
8676 $this->autoloadGenerator = $autoloadGenerator;
8677 }
8678
8679
8680
8681
8682 public function getAutoloadGenerator()
8683 {
8684 return $this->autoloadGenerator;
8685 }
8686 }
8687 <?php
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699 namespace Composer;
8700
8701 use Composer\Config\ConfigSourceInterface;
8702 use Composer\Downloader\TransportException;
8703 use Composer\IO\IOInterface;
8704 use Composer\Util\Platform;
8705
8706
8707
8708
8709 class Config
8710 {
8711 const RELATIVE_PATHS = 1;
8712
8713 public static $defaultConfig = array(
8714 'process-timeout' => 300,
8715 'use-include-path' => false,
8716 'preferred-install' => 'auto',
8717 'notify-on-install' => true,
8718 'github-protocols' => array('https', 'ssh', 'git'),
8719 'vendor-dir' => 'vendor',
8720 'bin-dir' => '{$vendor-dir}/bin',
8721 'cache-dir' => '{$home}/cache',
8722 'data-dir' => '{$home}',
8723 'cache-files-dir' => '{$cache-dir}/files',
8724 'cache-repo-dir' => '{$cache-dir}/repo',
8725 'cache-vcs-dir' => '{$cache-dir}/vcs',
8726 'cache-ttl' => 15552000, 
8727  'cache-files-ttl' => null, 
8728  'cache-files-maxsize' => '300MiB',
8729 'bin-compat' => 'auto',
8730 'discard-changes' => false,
8731 'autoloader-suffix' => null,
8732 'sort-packages' => false,
8733 'optimize-autoloader' => false,
8734 'classmap-authoritative' => false,
8735 'apcu-autoloader' => false,
8736 'prepend-autoloader' => true,
8737 'github-domains' => array('github.com'),
8738 'bitbucket-expose-hostname' => true,
8739 'disable-tls' => false,
8740 'secure-http' => true,
8741 'cafile' => null,
8742 'capath' => null,
8743 'github-expose-hostname' => true,
8744 'gitlab-domains' => array('gitlab.com'),
8745 'store-auths' => 'prompt',
8746 'platform' => array(),
8747 'archive-format' => 'tar',
8748 'archive-dir' => '.',
8749 'htaccess-protect' => true,
8750
8751  
8752  
8753  
8754  
8755  
8756  );
8757
8758 public static $defaultRepositories = array(
8759 'packagist.org' => array(
8760 'type' => 'composer',
8761 'url' => 'https?://packagist.org',
8762 'allow_ssl_downgrade' => true,
8763 ),
8764 );
8765
8766 private $config;
8767 private $baseDir;
8768 private $repositories;
8769
8770 private $configSource;
8771
8772 private $authConfigSource;
8773 private $useEnvironment;
8774 private $warnedHosts = array();
8775
8776
8777
8778
8779
8780 public function __construct($useEnvironment = true, $baseDir = null)
8781 {
8782
8783  $this->config = static::$defaultConfig;
8784 $this->repositories = static::$defaultRepositories;
8785 $this->useEnvironment = (bool) $useEnvironment;
8786 $this->baseDir = $baseDir;
8787 }
8788
8789 public function setConfigSource(ConfigSourceInterface $source)
8790 {
8791 $this->configSource = $source;
8792 }
8793
8794 public function getConfigSource()
8795 {
8796 return $this->configSource;
8797 }
8798
8799 public function setAuthConfigSource(ConfigSourceInterface $source)
8800 {
8801 $this->authConfigSource = $source;
8802 }
8803
8804 public function getAuthConfigSource()
8805 {
8806 return $this->authConfigSource;
8807 }
8808
8809
8810
8811
8812
8813
8814 public function merge($config)
8815 {
8816
8817  if (!empty($config['config']) && is_array($config['config'])) {
8818 foreach ($config['config'] as $key => $val) {
8819 if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic')) && isset($this->config[$key])) {
8820 $this->config[$key] = array_merge($this->config[$key], $val);
8821 } elseif ('preferred-install' === $key && isset($this->config[$key])) {
8822 if (is_array($val) || is_array($this->config[$key])) {
8823 if (is_string($val)) {
8824 $val = array('*' => $val);
8825 }
8826 if (is_string($this->config[$key])) {
8827 $this->config[$key] = array('*' => $this->config[$key]);
8828 }
8829 $this->config[$key] = array_merge($this->config[$key], $val);
8830
8831  if (isset($this->config[$key]['*'])) {
8832 $wildcard = $this->config[$key]['*'];
8833 unset($this->config[$key]['*']);
8834 $this->config[$key]['*'] = $wildcard;
8835 }
8836 } else {
8837 $this->config[$key] = $val;
8838 }
8839 } else {
8840 $this->config[$key] = $val;
8841 }
8842 }
8843 }
8844
8845 if (!empty($config['repositories']) && is_array($config['repositories'])) {
8846 $this->repositories = array_reverse($this->repositories, true);
8847 $newRepos = array_reverse($config['repositories'], true);
8848 foreach ($newRepos as $name => $repository) {
8849
8850  if (false === $repository) {
8851 $this->disableRepoByName($name);
8852 continue;
8853 }
8854
8855
8856  if (is_array($repository) && 1 === count($repository) && false === current($repository)) {
8857 $this->disableRepoByName(key($repository));
8858 continue;
8859 }
8860
8861
8862  if (is_int($name)) {
8863 $this->repositories[] = $repository;
8864 } else {
8865 if ($name === 'packagist') { 
8866  $this->repositories[$name . '.org'] = $repository;
8867 } else {
8868 $this->repositories[$name] = $repository;
8869 }
8870 }
8871 }
8872 $this->repositories = array_reverse($this->repositories, true);
8873 }
8874 }
8875
8876
8877
8878
8879 public function getRepositories()
8880 {
8881 return $this->repositories;
8882 }
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892 public function get($key, $flags = 0)
8893 {
8894 switch ($key) {
8895 case 'vendor-dir':
8896 case 'bin-dir':
8897 case 'process-timeout':
8898 case 'data-dir':
8899 case 'cache-dir':
8900 case 'cache-files-dir':
8901 case 'cache-repo-dir':
8902 case 'cache-vcs-dir':
8903 case 'cafile':
8904 case 'capath':
8905 case 'htaccess-protect':
8906
8907  $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
8908
8909 $val = $this->getComposerEnv($env);
8910 $val = rtrim((string) $this->process(false !== $val ? $val : $this->config[$key], $flags), '/\\');
8911 $val = Platform::expandPath($val);
8912
8913 if (substr($key, -4) !== '-dir') {
8914 return $val;
8915 }
8916
8917 return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
8918
8919 case 'cache-ttl':
8920 return (int) $this->config[$key];
8921
8922 case 'cache-files-maxsize':
8923 if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
8924 throw new \RuntimeException(
8925 "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
8926 );
8927 }
8928 $size = $matches[1];
8929 if (isset($matches[2])) {
8930 switch (strtolower($matches[2])) {
8931 case 'g':
8932 $size *= 1024;
8933
8934  case 'm':
8935 $size *= 1024;
8936
8937  case 'k':
8938 $size *= 1024;
8939 break;
8940 }
8941 }
8942
8943 return $size;
8944
8945 case 'cache-files-ttl':
8946 if (isset($this->config[$key])) {
8947 return (int) $this->config[$key];
8948 }
8949
8950 return (int) $this->config['cache-ttl'];
8951
8952 case 'home':
8953 $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $this->config[$key]);
8954
8955 return rtrim($this->process($val, $flags), '/\\');
8956
8957 case 'bin-compat':
8958 $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
8959
8960 if (!in_array($value, array('auto', 'full'))) {
8961 throw new \RuntimeException(
8962 "Invalid value for 'bin-compat': {$value}. Expected auto, full"
8963 );
8964 }
8965
8966 return $value;
8967
8968 case 'discard-changes':
8969 if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
8970 if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
8971 throw new \RuntimeException(
8972 "Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"
8973 );
8974 }
8975 if ('stash' === $env) {
8976 return 'stash';
8977 }
8978
8979
8980  return $env !== 'false' && (bool) $env;
8981 }
8982
8983 if (!in_array($this->config[$key], array(true, false, 'stash'), true)) {
8984 throw new \RuntimeException(
8985 "Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"
8986 );
8987 }
8988
8989 return $this->config[$key];
8990
8991 case 'github-protocols':
8992 $protos = $this->config['github-protocols'];
8993 if ($this->config['secure-http'] && false !== ($index = array_search('git', $protos))) {
8994 unset($protos[$index]);
8995 }
8996 if (reset($protos) === 'http') {
8997 throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
8998 }
8999
9000 return $protos;
9001
9002 case 'disable-tls':
9003 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
9004
9005 case 'secure-http':
9006 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
9007
9008 default:
9009 if (!isset($this->config[$key])) {
9010 return null;
9011 }
9012
9013 return $this->process($this->config[$key], $flags);
9014 }
9015 }
9016
9017 public function all($flags = 0)
9018 {
9019 $all = array(
9020 'repositories' => $this->getRepositories(),
9021 );
9022 foreach (array_keys($this->config) as $key) {
9023 $all['config'][$key] = $this->get($key, $flags);
9024 }
9025
9026 return $all;
9027 }
9028
9029 public function raw()
9030 {
9031 return array(
9032 'repositories' => $this->getRepositories(),
9033 'config' => $this->config,
9034 );
9035 }
9036
9037
9038
9039
9040
9041
9042
9043 public function has($key)
9044 {
9045 return array_key_exists($key, $this->config);
9046 }
9047
9048
9049
9050
9051
9052
9053
9054
9055 private function process($value, $flags)
9056 {
9057 $config = $this;
9058
9059 if (!is_string($value)) {
9060 return $value;
9061 }
9062
9063 return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
9064 return $config->get($match[1], $flags);
9065 }, $value);
9066 }
9067
9068
9069
9070
9071
9072
9073
9074
9075
9076 private function realpath($path)
9077 {
9078 if (preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) {
9079 return $path;
9080 }
9081
9082 return $this->baseDir . '/' . $path;
9083 }
9084
9085
9086
9087
9088
9089
9090
9091
9092
9093
9094 private function getComposerEnv($var)
9095 {
9096 if ($this->useEnvironment) {
9097 return getenv($var);
9098 }
9099
9100 return false;
9101 }
9102
9103 private function disableRepoByName($name)
9104 {
9105 if (isset($this->repositories[$name])) {
9106 unset($this->repositories[$name]);
9107 } elseif ($name === 'packagist') { 
9108  unset($this->repositories['packagist.org']);
9109 }
9110 }
9111
9112
9113
9114
9115
9116
9117
9118 public function prohibitUrlByConfig($url, IOInterface $io = null)
9119 {
9120
9121  if (false === filter_var($url, FILTER_VALIDATE_URL)) {
9122 return;
9123 }
9124
9125
9126  $scheme = parse_url($url, PHP_URL_SCHEME);
9127 if (in_array($scheme, array('http', 'git', 'ftp', 'svn'))) {
9128 if ($this->get('secure-http')) {
9129 throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
9130 } elseif ($io) {
9131 $host = parse_url($url, PHP_URL_HOST);
9132 if (!isset($this->warnedHosts[$host])) {
9133 $io->writeError("<warning>Warning: Accessing $host over $scheme which is an insecure protocol.</warning>");
9134 }
9135 $this->warnedHosts[$host] = true;
9136 }
9137 }
9138 }
9139 }
9140 <?php
9141
9142
9143
9144
9145
9146
9147
9148
9149
9150
9151
9152 namespace Composer\Config;
9153
9154
9155
9156
9157
9158
9159
9160 interface ConfigSourceInterface
9161 {
9162
9163
9164
9165
9166
9167
9168 public function addRepository($name, $config);
9169
9170
9171
9172
9173
9174
9175 public function removeRepository($name);
9176
9177
9178
9179
9180
9181
9182
9183 public function addConfigSetting($name, $value);
9184
9185
9186
9187
9188
9189
9190 public function removeConfigSetting($name);
9191
9192
9193
9194
9195
9196
9197
9198 public function addProperty($name, $value);
9199
9200
9201
9202
9203
9204
9205 public function removeProperty($name);
9206
9207
9208
9209
9210
9211
9212
9213
9214 public function addLink($type, $name, $value);
9215
9216
9217
9218
9219
9220
9221
9222 public function removeLink($type, $name);
9223
9224
9225
9226
9227
9228
9229 public function getName();
9230 }
9231 <?php
9232
9233
9234
9235
9236
9237
9238
9239
9240
9241
9242
9243 namespace Composer\Config;
9244
9245 use Composer\Json\JsonFile;
9246 use Composer\Json\JsonManipulator;
9247 use Composer\Util\Silencer;
9248
9249
9250
9251
9252
9253
9254
9255 class JsonConfigSource implements ConfigSourceInterface
9256 {
9257
9258
9259
9260 private $file;
9261
9262
9263
9264
9265 private $authConfig;
9266
9267
9268
9269
9270
9271
9272
9273 public function __construct(JsonFile $file, $authConfig = false)
9274 {
9275 $this->file = $file;
9276 $this->authConfig = $authConfig;
9277 }
9278
9279
9280
9281
9282 public function getName()
9283 {
9284 return $this->file->getPath();
9285 }
9286
9287
9288
9289
9290 public function addRepository($name, $config)
9291 {
9292 $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
9293
9294  
9295  if (isset($config['repositories'])) {
9296 foreach ($config['repositories'] as $index => $val) {
9297 if ($index === $repo) {
9298 continue;
9299 }
9300 if (is_numeric($index) && ($val === array('packagist' => false) || $val === array('packagist.org' => false))) {
9301 unset($config['repositories'][$index]);
9302 $config['repositories']['packagist.org'] = false;
9303 break;
9304 }
9305 }
9306 }
9307
9308 $config['repositories'][$repo] = $repoConfig;
9309 });
9310 }
9311
9312
9313
9314
9315 public function removeRepository($name)
9316 {
9317 $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
9318 unset($config['repositories'][$repo]);
9319 });
9320 }
9321
9322
9323
9324
9325 public function addConfigSetting($name, $value)
9326 {
9327 $authConfig = $this->authConfig;
9328 $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) {
9329 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9330 list($key, $host) = explode('.', $key, 2);
9331 if ($authConfig) {
9332 $config[$key][$host] = $val;
9333 } else {
9334 $config['config'][$key][$host] = $val;
9335 }
9336 } else {
9337 $config['config'][$key] = $val;
9338 }
9339 });
9340 }
9341
9342
9343
9344
9345 public function removeConfigSetting($name)
9346 {
9347 $authConfig = $this->authConfig;
9348 $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) {
9349 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9350 list($key, $host) = explode('.', $key, 2);
9351 if ($authConfig) {
9352 unset($config[$key][$host]);
9353 } else {
9354 unset($config['config'][$key][$host]);
9355 }
9356 } else {
9357 unset($config['config'][$key]);
9358 }
9359 });
9360 }
9361
9362
9363
9364
9365 public function addProperty($name, $value)
9366 {
9367 $this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) {
9368 if (substr($key, 0, 6) === 'extra.') {
9369 $bits = explode('.', $key);
9370 $last = array_pop($bits);
9371 $arr = &$config['extra'];
9372 foreach ($bits as $bit) {
9373 if (!isset($arr[$bit])) {
9374 $arr[$bit] = array();
9375 }
9376 $arr = &$arr[$bit];
9377 }
9378 $arr[$last] = $val;
9379 } else {
9380 $config[$key] = $val;
9381 }
9382 });
9383 }
9384
9385
9386
9387
9388 public function removeProperty($name)
9389 {
9390 $authConfig = $this->authConfig;
9391 $this->manipulateJson('removeProperty', $name, function (&$config, $key) {
9392 if (substr($key, 0, 6) === 'extra.') {
9393 $bits = explode('.', $key);
9394 $last = array_pop($bits);
9395 $arr = &$config['extra'];
9396 foreach ($bits as $bit) {
9397 if (!isset($arr[$bit])) {
9398 return;
9399 }
9400 $arr = &$arr[$bit];
9401 }
9402 unset($arr[$last]);
9403 } else {
9404 unset($config[$key]);
9405 }
9406 });
9407 }
9408
9409
9410
9411
9412 public function addLink($type, $name, $value)
9413 {
9414 $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
9415 $config[$type][$name] = $value;
9416 });
9417 }
9418
9419
9420
9421
9422 public function removeLink($type, $name)
9423 {
9424 $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
9425 unset($config[$type][$name]);
9426 });
9427 }
9428
9429 protected function manipulateJson($method, $args, $fallback)
9430 {
9431 $args = func_get_args();
9432
9433  array_shift($args);
9434 $fallback = array_pop($args);
9435
9436 if ($this->file->exists()) {
9437 if (!is_writable($this->file->getPath())) {
9438 throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
9439 }
9440
9441 if (!is_readable($this->file->getPath())) {
9442 throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
9443 }
9444
9445 $contents = file_get_contents($this->file->getPath());
9446 } elseif ($this->authConfig) {
9447 $contents = "{\n}\n";
9448 } else {
9449 $contents = "{\n    \"config\": {\n    }\n}\n";
9450 }
9451
9452 $manipulator = new JsonManipulator($contents);
9453
9454 $newFile = !$this->file->exists();
9455
9456
9457  if ($this->authConfig && $method === 'addConfigSetting') {
9458 $method = 'addSubNode';
9459 list($mainNode, $name) = explode('.', $args[0], 2);
9460 $args = array($mainNode, $name, $args[1]);
9461 } elseif ($this->authConfig && $method === 'removeConfigSetting') {
9462 $method = 'removeSubNode';
9463 list($mainNode, $name) = explode('.', $args[0], 2);
9464 $args = array($mainNode, $name);
9465 }
9466
9467
9468  if (call_user_func_array(array($manipulator, $method), $args)) {
9469 file_put_contents($this->file->getPath(), $manipulator->getContents());
9470 } else {
9471
9472  $config = $this->file->read();
9473 $this->arrayUnshiftRef($args, $config);
9474 call_user_func_array($fallback, $args);
9475 $this->file->write($config);
9476 }
9477
9478 if ($newFile) {
9479 Silencer::call('chmod', $this->file->getPath(), 0600);
9480 }
9481 }
9482
9483
9484
9485
9486
9487
9488
9489
9490 private function arrayUnshiftRef(&$array, &$value)
9491 {
9492 $return = array_unshift($array, '');
9493 $array[0] = &$value;
9494
9495 return $return;
9496 }
9497 }
9498 <?php
9499
9500
9501
9502
9503
9504
9505
9506
9507
9508
9509
9510 namespace Composer\Console;
9511
9512 use Composer\Util\Platform;
9513 use Composer\Util\Silencer;
9514 use Symfony\Component\Console\Application as BaseApplication;
9515 use Symfony\Component\Console\Input\InputInterface;
9516 use Symfony\Component\Console\Input\InputOption;
9517 use Symfony\Component\Console\Output\OutputInterface;
9518 use Composer\Command;
9519 use Composer\Composer;
9520 use Composer\Factory;
9521 use Composer\IO\IOInterface;
9522 use Composer\IO\ConsoleIO;
9523 use Composer\Json\JsonValidationException;
9524 use Composer\Util\ErrorHandler;
9525 use Composer\EventDispatcher\ScriptExecutionException;
9526 use Composer\Exception\NoSslException;
9527
9528
9529
9530
9531
9532
9533
9534
9535 class Application extends BaseApplication
9536 {
9537
9538
9539
9540 protected $composer;
9541
9542
9543
9544
9545 protected $io;
9546
9547 private static $logo = '   ______
9548   / ____/___  ____ ___  ____  ____  ________  _____
9549  / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
9550 / /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
9551 \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
9552                     /_/
9553 ';
9554
9555 private $hasPluginCommands = false;
9556 private $disablePluginsByDefault = false;
9557
9558 public function __construct()
9559 {
9560 static $shutdownRegistered = false;
9561
9562 if (function_exists('ini_set') && extension_loaded('xdebug')) {
9563 ini_set('xdebug.show_exception_trace', false);
9564 ini_set('xdebug.scream', false);
9565 }
9566
9567 if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
9568 date_default_timezone_set(Silencer::call('date_default_timezone_get'));
9569 }
9570
9571 if (!$shutdownRegistered) {
9572 $shutdownRegistered = true;
9573
9574 register_shutdown_function(function () {
9575 $lastError = error_get_last();
9576
9577 if ($lastError && $lastError['message'] &&
9578 (strpos($lastError['message'], 'Allowed memory') !== false  ||
9579 strpos($lastError['message'], 'exceeded memory') !== false )) {
9580 echo "\n". 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
9581 }
9582 });
9583 }
9584
9585 parent::__construct('Composer', Composer::VERSION);
9586 }
9587
9588
9589
9590
9591 public function run(InputInterface $input = null, OutputInterface $output = null)
9592 {
9593 if (null === $output) {
9594 $output = Factory::createOutput();
9595 }
9596
9597 return parent::run($input, $output);
9598 }
9599
9600
9601
9602
9603 public function doRun(InputInterface $input, OutputInterface $output)
9604 {
9605 $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
9606
9607 $io = $this->io = new ConsoleIO($input, $output, $this->getHelperSet());
9608 ErrorHandler::register($io);
9609
9610
9611  if ($newWorkDir = $this->getNewWorkingDir($input)) {
9612 $oldWorkingDir = getcwd();
9613 chdir($newWorkDir);
9614 $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
9615 }
9616
9617
9618  $commandName = '';
9619 if ($name = $this->getCommandName($input)) {
9620 try {
9621 $commandName = $this->find($name)->getName();
9622 } catch (\InvalidArgumentException $e) {
9623 }
9624 }
9625
9626
9627  if ($io->isInteractive() && !$newWorkDir && !in_array($commandName, array('', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project'), true) && !file_exists(Factory::getComposerFile())) {
9628 $dir = dirname(getcwd());
9629 $home = realpath(getenv('HOME') ?: getenv('USERPROFILE') ?: '/');
9630
9631
9632  while (dirname($dir) !== $dir && $dir !== $home) {
9633 if (file_exists($dir.'/'.Factory::getComposerFile())) {
9634 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)) {
9635 $oldWorkingDir = getcwd();
9636 chdir($dir);
9637 }
9638 break;
9639 }
9640 $dir = dirname($dir);
9641 }
9642 }
9643
9644 if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
9645 try {
9646 foreach ($this->getPluginCommands() as $command) {
9647 if ($this->has($command->getName())) {
9648 $io->writeError('<warning>Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped</warning>');
9649 } else {
9650 $this->add($command);
9651 }
9652 }
9653 } catch (NoSslException $e) {
9654
9655  }
9656
9657 $this->hasPluginCommands = true;
9658 }
9659
9660
9661  $isProxyCommand = false;
9662 if ($name = $this->getCommandName($input)) {
9663 try {
9664 $command = $this->find($name);
9665 $commandName = $command->getName();
9666 $isProxyCommand = ($command instanceof Command\BaseCommand && $command->isProxyCommand());
9667 } catch (\InvalidArgumentException $e) {
9668 }
9669 }
9670
9671 if (!$isProxyCommand) {
9672 $io->writeError(sprintf(
9673 'Running %s (%s) with %s on %s',
9674 Composer::VERSION,
9675 Composer::RELEASE_DATE,
9676 defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
9677 function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
9678 ), true, IOInterface::DEBUG);
9679
9680 if (PHP_VERSION_ID < 50302) {
9681 $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>');
9682 }
9683
9684 if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
9685 $io->writeError('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
9686 }
9687
9688 if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
9689 $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']));
9690 }
9691
9692 if (getenv('COMPOSER_NO_INTERACTION')) {
9693 $input->setInteractive(false);
9694 }
9695
9696 if (!Platform::isWindows() && function_exists('exec') && !getenv('COMPOSER_ALLOW_SUPERUSER')) {
9697 if (function_exists('posix_getuid') && posix_getuid() === 0) {
9698 if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
9699 $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
9700 }
9701 if ($uid = (int) getenv('SUDO_UID')) {
9702
9703  
9704  Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
9705 }
9706 }
9707
9708  Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
9709 }
9710
9711
9712  Silencer::call(function () use ($io) {
9713 $tempfile = sys_get_temp_dir() . '/temp-' . md5(microtime());
9714 if (!(file_put_contents($tempfile, __FILE__) && (file_get_contents($tempfile) == __FILE__) && unlink($tempfile) && !file_exists($tempfile))) {
9715 $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()));
9716 }
9717 });
9718
9719
9720  $file = Factory::getComposerFile();
9721 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
9722 if (isset($composer['scripts']) && is_array($composer['scripts'])) {
9723 foreach ($composer['scripts'] as $script => $dummy) {
9724 if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
9725 if ($this->has($script)) {
9726 $io->writeError('<warning>A script named '.$script.' would override a Composer command and has been skipped</warning>');
9727 } else {
9728 $description = null;
9729
9730 if (isset($composer['scripts-descriptions'][$script])) {
9731 $description = $composer['scripts-descriptions'][$script];
9732 }
9733
9734 $this->add(new Command\ScriptAliasCommand($script, $description));
9735 }
9736 }
9737 }
9738 }
9739 }
9740 }
9741
9742 try {
9743 if ($input->hasParameterOption('--profile')) {
9744 $startTime = microtime(true);
9745 $this->io->enableDebugging($startTime);
9746 }
9747
9748 $result = parent::doRun($input, $output);
9749
9750 if (isset($oldWorkingDir)) {
9751 chdir($oldWorkingDir);
9752 }
9753
9754 if (isset($startTime)) {
9755 $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');
9756 }
9757
9758 restore_error_handler();
9759
9760 return $result;
9761 } catch (ScriptExecutionException $e) {
9762 return $e->getCode();
9763 } catch (\Exception $e) {
9764 $this->hintCommonErrors($e);
9765 restore_error_handler();
9766 throw $e;
9767 }
9768 }
9769
9770
9771
9772
9773
9774
9775 private function getNewWorkingDir(InputInterface $input)
9776 {
9777 $workingDir = $input->getParameterOption(array('--working-dir', '-d'));
9778 if (false !== $workingDir && !is_dir($workingDir)) {
9779 throw new \RuntimeException('Invalid working directory specified, '.$workingDir.' does not exist.');
9780 }
9781
9782 return $workingDir;
9783 }
9784
9785
9786
9787
9788 private function hintCommonErrors($exception)
9789 {
9790 $io = $this->getIO();
9791
9792 Silencer::suppress();
9793 try {
9794 $composer = $this->getComposer(false, true);
9795 if ($composer) {
9796 $config = $composer->getConfig();
9797
9798 $minSpaceFree = 1024 * 1024;
9799 if ((($df = disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
9800 || (($df = disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
9801 || (($df = disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
9802 ) {
9803 $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>', true, IOInterface::QUIET);
9804 }
9805 }
9806 } catch (\Exception $e) {
9807 }
9808 Silencer::restore();
9809
9810 if (Platform::isWindows() && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
9811 $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', true, IOInterface::QUIET);
9812 $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);
9813 }
9814
9815 if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
9816 $io->writeError('<error>The following exception is caused by a lack of memory or swap, or not having swap configured</error>', true, IOInterface::QUIET);
9817 $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
9818 }
9819 }
9820
9821
9822
9823
9824
9825
9826
9827 public function getComposer($required = true, $disablePlugins = null)
9828 {
9829 if (null === $disablePlugins) {
9830 $disablePlugins = $this->disablePluginsByDefault;
9831 }
9832
9833 if (null === $this->composer) {
9834 try {
9835 $this->composer = Factory::create($this->io, null, $disablePlugins);
9836 } catch (\InvalidArgumentException $e) {
9837 if ($required) {
9838 $this->io->writeError($e->getMessage());
9839 exit(1);
9840 }
9841 } catch (JsonValidationException $e) {
9842 $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
9843 $message = $e->getMessage() . ':' . PHP_EOL . $errors;
9844 throw new JsonValidationException($message);
9845 }
9846 }
9847
9848 return $this->composer;
9849 }
9850
9851
9852
9853
9854 public function resetComposer()
9855 {
9856 $this->composer = null;
9857 }
9858
9859
9860
9861
9862 public function getIO()
9863 {
9864 return $this->io;
9865 }
9866
9867 public function getHelp()
9868 {
9869 return self::$logo . parent::getHelp();
9870 }
9871
9872
9873
9874
9875 protected function getDefaultCommands()
9876 {
9877 $commands = array_merge(parent::getDefaultCommands(), array(
9878 new Command\AboutCommand(),
9879 new Command\ConfigCommand(),
9880 new Command\DependsCommand(),
9881 new Command\ProhibitsCommand(),
9882 new Command\InitCommand(),
9883 new Command\InstallCommand(),
9884 new Command\CreateProjectCommand(),
9885 new Command\UpdateCommand(),
9886 new Command\SearchCommand(),
9887 new Command\ValidateCommand(),
9888 new Command\ShowCommand(),
9889 new Command\SuggestsCommand(),
9890 new Command\RequireCommand(),
9891 new Command\DumpAutoloadCommand(),
9892 new Command\StatusCommand(),
9893 new Command\ArchiveCommand(),
9894 new Command\DiagnoseCommand(),
9895 new Command\RunScriptCommand(),
9896 new Command\LicensesCommand(),
9897 new Command\GlobalCommand(),
9898 new Command\ClearCacheCommand(),
9899 new Command\RemoveCommand(),
9900 new Command\HomeCommand(),
9901 new Command\ExecCommand(),
9902 new Command\OutdatedCommand(),
9903 new Command\CheckPlatformReqsCommand(),
9904 ));
9905
9906 if ('phar:' === substr(__FILE__, 0, 5)) {
9907 $commands[] = new Command\SelfUpdateCommand();
9908 }
9909
9910 return $commands;
9911 }
9912
9913
9914
9915
9916 public function getLongVersion()
9917 {
9918 if (Composer::BRANCH_ALIAS_VERSION) {
9919 return sprintf(
9920 '<info>%s</info> version <comment>%s (%s)</comment> %s',
9921 $this->getName(),
9922 Composer::BRANCH_ALIAS_VERSION,
9923 $this->getVersion(),
9924 Composer::RELEASE_DATE
9925 );
9926 }
9927
9928 return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE;
9929 }
9930
9931
9932
9933
9934 protected function getDefaultInputDefinition()
9935 {
9936 $definition = parent::getDefaultInputDefinition();
9937 $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
9938 $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'));
9939 $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
9940
9941 return $definition;
9942 }
9943
9944 private function getPluginCommands()
9945 {
9946 $commands = array();
9947
9948 $composer = $this->getComposer(false, false);
9949 if (null === $composer) {
9950 $composer = Factory::createGlobal($this->io, false);
9951 }
9952
9953 if (null !== $composer) {
9954 $pm = $composer->getPluginManager();
9955 foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $composer, 'io' => $this->io)) as $capability) {
9956 $newCommands = $capability->getCommands();
9957 if (!is_array($newCommands)) {
9958 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands');
9959 }
9960 foreach ($newCommands as $command) {
9961 if (!$command instanceof Command\BaseCommand) {
9962 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects');
9963 }
9964 }
9965 $commands = array_merge($commands, $newCommands);
9966 }
9967 }
9968
9969 return $commands;
9970 }
9971 }
9972 <?php
9973
9974
9975
9976
9977
9978
9979
9980
9981
9982
9983
9984 namespace Composer\Console;
9985
9986 use Symfony\Component\Console\Formatter\OutputFormatter;
9987
9988
9989
9990
9991 class HtmlOutputFormatter extends OutputFormatter
9992 {
9993 private static $availableForegroundColors = array(
9994 30 => 'black',
9995 31 => 'red',
9996 32 => 'green',
9997 33 => 'yellow',
9998 34 => 'blue',
9999 35 => 'magenta',
10000 36 => 'cyan',
10001 37 => 'white',
10002 );
10003 private static $availableBackgroundColors = array(
10004 40 => 'black',
10005 41 => 'red',
10006 42 => 'green',
10007 43 => 'yellow',
10008 44 => 'blue',
10009 45 => 'magenta',
10010 46 => 'cyan',
10011 47 => 'white',
10012 );
10013 private static $availableOptions = array(
10014 1 => 'bold',
10015 4 => 'underscore',
10016
10017  
10018  
10019  );
10020
10021
10022
10023
10024 public function __construct(array $styles = array())
10025 {
10026 parent::__construct(true, $styles);
10027 }
10028
10029 public function format($message)
10030 {
10031 $formatted = parent::format($message);
10032
10033 $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
10034
10035 return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted);
10036 }
10037
10038 private function formatHtml($matches)
10039 {
10040 $out = '<span style="';
10041 foreach (explode(';', $matches[1]) as $code) {
10042 if (isset(self::$availableForegroundColors[$code])) {
10043 $out .= 'color:'.self::$availableForegroundColors[$code].';';
10044 } elseif (isset(self::$availableBackgroundColors[$code])) {
10045 $out .= 'background-color:'.self::$availableBackgroundColors[$code].';';
10046 } elseif (isset(self::$availableOptions[$code])) {
10047 switch (self::$availableOptions[$code]) {
10048 case 'bold':
10049 $out .= 'font-weight:bold;';
10050 break;
10051
10052 case 'underscore':
10053 $out .= 'text-decoration:underline;';
10054 break;
10055 }
10056 }
10057 }
10058
10059 return $out.'">'.$matches[2].'</span>';
10060 }
10061 }
10062 <?php
10063
10064
10065
10066
10067
10068
10069
10070
10071
10072
10073
10074 namespace Composer\DependencyResolver;
10075
10076
10077
10078
10079
10080
10081 class Decisions implements \Iterator, \Countable
10082 {
10083 const DECISION_LITERAL = 0;
10084 const DECISION_REASON = 1;
10085
10086 protected $pool;
10087 protected $decisionMap;
10088 protected $decisionQueue = array();
10089
10090 public function __construct($pool)
10091 {
10092 $this->pool = $pool;
10093 $this->decisionMap = array();
10094 }
10095
10096 public function decide($literal, $level, $why)
10097 {
10098 $this->addDecision($literal, $level);
10099 $this->decisionQueue[] = array(
10100 self::DECISION_LITERAL => $literal,
10101 self::DECISION_REASON => $why,
10102 );
10103 }
10104
10105 public function satisfy($literal)
10106 {
10107 $packageId = abs($literal);
10108
10109 return (
10110 $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 ||
10111 $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0
10112 );
10113 }
10114
10115 public function conflict($literal)
10116 {
10117 $packageId = abs($literal);
10118
10119 return (
10120 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0) ||
10121 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0)
10122 );
10123 }
10124
10125 public function decided($literalOrPackageId)
10126 {
10127 return !empty($this->decisionMap[abs($literalOrPackageId)]);
10128 }
10129
10130 public function undecided($literalOrPackageId)
10131 {
10132 return empty($this->decisionMap[abs($literalOrPackageId)]);
10133 }
10134
10135 public function decidedInstall($literalOrPackageId)
10136 {
10137 $packageId = abs($literalOrPackageId);
10138
10139 return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
10140 }
10141
10142 public function decisionLevel($literalOrPackageId)
10143 {
10144 $packageId = abs($literalOrPackageId);
10145 if (isset($this->decisionMap[$packageId])) {
10146 return abs($this->decisionMap[$packageId]);
10147 }
10148
10149 return 0;
10150 }
10151
10152 public function decisionRule($literalOrPackageId)
10153 {
10154 $packageId = abs($literalOrPackageId);
10155
10156 foreach ($this->decisionQueue as $i => $decision) {
10157 if ($packageId === abs($decision[self::DECISION_LITERAL])) {
10158 return $decision[self::DECISION_REASON];
10159 }
10160 }
10161
10162 return null;
10163 }
10164
10165 public function atOffset($queueOffset)
10166 {
10167 return $this->decisionQueue[$queueOffset];
10168 }
10169
10170 public function validOffset($queueOffset)
10171 {
10172 return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
10173 }
10174
10175 public function lastReason()
10176 {
10177 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
10178 }
10179
10180 public function lastLiteral()
10181 {
10182 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
10183 }
10184
10185 public function reset()
10186 {
10187 while ($decision = array_pop($this->decisionQueue)) {
10188 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
10189 }
10190 }
10191
10192 public function resetToOffset($offset)
10193 {
10194 while (count($this->decisionQueue) > $offset + 1) {
10195 $decision = array_pop($this->decisionQueue);
10196 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
10197 }
10198 }
10199
10200 public function revertLast()
10201 {
10202 $this->decisionMap[abs($this->lastLiteral())] = 0;
10203 array_pop($this->decisionQueue);
10204 }
10205
10206 public function count()
10207 {
10208 return count($this->decisionQueue);
10209 }
10210
10211 public function rewind()
10212 {
10213 end($this->decisionQueue);
10214 }
10215
10216 public function current()
10217 {
10218 return current($this->decisionQueue);
10219 }
10220
10221 public function key()
10222 {
10223 return key($this->decisionQueue);
10224 }
10225
10226 public function next()
10227 {
10228 return prev($this->decisionQueue);
10229 }
10230
10231 public function valid()
10232 {
10233 return false !== current($this->decisionQueue);
10234 }
10235
10236 public function isEmpty()
10237 {
10238 return count($this->decisionQueue) === 0;
10239 }
10240
10241 protected function addDecision($literal, $level)
10242 {
10243 $packageId = abs($literal);
10244
10245 $previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
10246 if ($previousDecision != 0) {
10247 $literalString = $this->pool->literalToString($literal);
10248 $package = $this->pool->literalToPackage($literal);
10249 throw new SolverBugException(
10250 "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
10251 );
10252 }
10253
10254 if ($literal > 0) {
10255 $this->decisionMap[$packageId] = $level;
10256 } else {
10257 $this->decisionMap[$packageId] = -$level;
10258 }
10259 }
10260 }
10261 <?php
10262
10263
10264
10265
10266
10267
10268
10269
10270
10271
10272
10273 namespace Composer\DependencyResolver;
10274
10275 use Composer\Package\PackageInterface;
10276 use Composer\Package\AliasPackage;
10277 use Composer\Package\BasePackage;
10278 use Composer\Semver\Constraint\Constraint;
10279
10280
10281
10282
10283
10284 class DefaultPolicy implements PolicyInterface
10285 {
10286 private $preferStable;
10287 private $preferLowest;
10288
10289 public function __construct($preferStable = false, $preferLowest = false)
10290 {
10291 $this->preferStable = $preferStable;
10292 $this->preferLowest = $preferLowest;
10293 }
10294
10295 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
10296 {
10297 if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
10298 return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
10299 }
10300
10301 $constraint = new Constraint($operator, $b->getVersion());
10302 $version = new Constraint('==', $a->getVersion());
10303
10304 return $constraint->matchSpecific($version, true);
10305 }
10306
10307 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
10308 {
10309 $packages = array();
10310
10311 foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
10312 if ($candidate !== $package) {
10313 $packages[] = $candidate;
10314 }
10315 }
10316
10317 return $packages;
10318 }
10319
10320 public function getPriority(Pool $pool, PackageInterface $package)
10321 {
10322 return $pool->getPriority($package->getRepository());
10323 }
10324
10325 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
10326 {
10327 $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
10328
10329 foreach ($packages as &$literals) {
10330 $policy = $this;
10331 usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10332 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
10333 });
10334 }
10335
10336 foreach ($packages as &$literals) {
10337 $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
10338
10339 $literals = $this->pruneToBestVersion($pool, $literals);
10340
10341 $literals = $this->pruneRemoteAliases($pool, $literals);
10342 }
10343
10344 $selected = call_user_func_array('array_merge', $packages);
10345
10346
10347  usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10348 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
10349 });
10350
10351 return $selected;
10352 }
10353
10354 protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
10355 {
10356 $packages = array();
10357 foreach ($literals as $literal) {
10358 $packageName = $pool->literalToPackage($literal)->getName();
10359
10360 if (!isset($packages[$packageName])) {
10361 $packages[$packageName] = array();
10362 }
10363
10364 if (isset($installedMap[abs($literal)])) {
10365 array_unshift($packages[$packageName], $literal);
10366 } else {
10367 $packages[$packageName][] = $literal;
10368 }
10369 }
10370
10371 return $packages;
10372 }
10373
10374
10375
10376
10377 public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
10378 {
10379 if ($a->getRepository() === $b->getRepository()) {
10380
10381  if ($a->getName() === $b->getName()) {
10382 $aAliased = $a instanceof AliasPackage;
10383 $bAliased = $b instanceof AliasPackage;
10384 if ($aAliased && !$bAliased) {
10385 return -1; 
10386  }
10387 if (!$aAliased && $bAliased) {
10388 return 1; 
10389  }
10390 }
10391
10392 if (!$ignoreReplace) {
10393
10394  if ($this->replaces($a, $b)) {
10395 return 1; 
10396  }
10397 if ($this->replaces($b, $a)) {
10398 return -1; 
10399  }
10400
10401
10402  
10403  if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
10404 $requiredVendor = substr($requiredPackage, 0, $pos);
10405
10406 $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
10407 $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
10408
10409 if ($bIsSameVendor !== $aIsSameVendor) {
10410 return $aIsSameVendor ? -1 : 1;
10411 }
10412 }
10413 }
10414
10415
10416  if ($a->id === $b->id) {
10417 return 0;
10418 }
10419
10420 return ($a->id < $b->id) ? -1 : 1;
10421 }
10422
10423 if (isset($installedMap[$a->id])) {
10424 return -1;
10425 }
10426
10427 if (isset($installedMap[$b->id])) {
10428 return 1;
10429 }
10430
10431 return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
10432 }
10433
10434
10435
10436
10437
10438
10439
10440
10441
10442
10443
10444 protected function replaces(PackageInterface $source, PackageInterface $target)
10445 {
10446 foreach ($source->getReplaces() as $link) {
10447 if ($link->getTarget() === $target->getName()
10448
10449
10450  ) {
10451 return true;
10452 }
10453 }
10454
10455 return false;
10456 }
10457
10458 protected function pruneToBestVersion(Pool $pool, $literals)
10459 {
10460 $operator = $this->preferLowest ? '<' : '>';
10461 $bestLiterals = array($literals[0]);
10462 $bestPackage = $pool->literalToPackage($literals[0]);
10463 foreach ($literals as $i => $literal) {
10464 if (0 === $i) {
10465 continue;
10466 }
10467
10468 $package = $pool->literalToPackage($literal);
10469
10470 if ($this->versionCompare($package, $bestPackage, $operator)) {
10471 $bestPackage = $package;
10472 $bestLiterals = array($literal);
10473 } elseif ($this->versionCompare($package, $bestPackage, '==')) {
10474 $bestLiterals[] = $literal;
10475 }
10476 }
10477
10478 return $bestLiterals;
10479 }
10480
10481
10482
10483
10484 protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
10485 {
10486 $selected = array();
10487
10488 $priority = null;
10489
10490 foreach ($literals as $literal) {
10491 $package = $pool->literalToPackage($literal);
10492
10493 if (isset($installedMap[$package->id])) {
10494 $selected[] = $literal;
10495 continue;
10496 }
10497
10498 if (null === $priority) {
10499 $priority = $this->getPriority($pool, $package);
10500 }
10501
10502 if ($this->getPriority($pool, $package) != $priority) {
10503 break;
10504 }
10505
10506 $selected[] = $literal;
10507 }
10508
10509 return $selected;
10510 }
10511
10512
10513
10514
10515
10516
10517 protected function pruneRemoteAliases(Pool $pool, array $literals)
10518 {
10519 $hasLocalAlias = false;
10520
10521 foreach ($literals as $literal) {
10522 $package = $pool->literalToPackage($literal);
10523
10524 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10525 $hasLocalAlias = true;
10526 break;
10527 }
10528 }
10529
10530 if (!$hasLocalAlias) {
10531 return $literals;
10532 }
10533
10534 $selected = array();
10535 foreach ($literals as $literal) {
10536 $package = $pool->literalToPackage($literal);
10537
10538 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10539 $selected[] = $literal;
10540 }
10541 }
10542
10543 return $selected;
10544 }
10545 }
10546 <?php
10547
10548
10549
10550
10551
10552
10553
10554
10555
10556
10557
10558 namespace Composer\DependencyResolver;
10559
10560 use Composer\Package\PackageInterface;
10561 use Composer\Package\Link;
10562
10563
10564
10565
10566 class GenericRule extends Rule
10567 {
10568 protected $literals;
10569
10570
10571
10572
10573
10574
10575
10576 public function __construct(array $literals, $reason, $reasonData, $job = null)
10577 {
10578 parent::__construct($reason, $reasonData, $job);
10579
10580
10581  sort($literals);
10582
10583 $this->literals = $literals;
10584 }
10585
10586 public function getLiterals()
10587 {
10588 return $this->literals;
10589 }
10590
10591 public function getHash()
10592 {
10593 $data = unpack('ihash', md5(implode(',', $this->literals), true));
10594
10595 return $data['hash'];
10596 }
10597
10598
10599
10600
10601
10602
10603
10604
10605
10606 public function equals(Rule $rule)
10607 {
10608 return $this->literals === $rule->getLiterals();
10609 }
10610
10611 public function isAssertion()
10612 {
10613 return 1 === count($this->literals);
10614 }
10615
10616
10617
10618
10619
10620
10621 public function __toString()
10622 {
10623 $result = ($this->isDisabled()) ? 'disabled(' : '(';
10624
10625 foreach ($this->literals as $i => $literal) {
10626 if ($i != 0) {
10627 $result .= '|';
10628 }
10629 $result .= $literal;
10630 }
10631
10632 $result .= ')';
10633
10634 return $result;
10635 }
10636 }
10637 <?php
10638
10639
10640
10641
10642
10643
10644
10645
10646
10647
10648
10649 namespace Composer\DependencyResolver\Operation;
10650
10651 use Composer\Package\PackageInterface;
10652
10653
10654
10655
10656
10657
10658 class InstallOperation extends SolverOperation
10659 {
10660 protected $package;
10661
10662
10663
10664
10665
10666
10667
10668 public function __construct(PackageInterface $package, $reason = null)
10669 {
10670 parent::__construct($reason);
10671
10672 $this->package = $package;
10673 }
10674
10675
10676
10677
10678
10679
10680 public function getPackage()
10681 {
10682 return $this->package;
10683 }
10684
10685
10686
10687
10688
10689
10690 public function getJobType()
10691 {
10692 return 'install';
10693 }
10694
10695
10696
10697
10698 public function __toString()
10699 {
10700 return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
10701 }
10702 }
10703 <?php
10704
10705
10706
10707
10708
10709
10710
10711
10712
10713
10714
10715 namespace Composer\DependencyResolver\Operation;
10716
10717 use Composer\Package\AliasPackage;
10718 use Composer\Package\PackageInterface;
10719
10720
10721
10722
10723
10724
10725 class MarkAliasInstalledOperation extends SolverOperation
10726 {
10727 protected $package;
10728
10729
10730
10731
10732
10733
10734
10735 public function __construct(AliasPackage $package, $reason = null)
10736 {
10737 parent::__construct($reason);
10738
10739 $this->package = $package;
10740 }
10741
10742
10743
10744
10745
10746
10747 public function getPackage()
10748 {
10749 return $this->package;
10750 }
10751
10752
10753
10754
10755
10756
10757 public function getJobType()
10758 {
10759 return 'markAliasInstalled';
10760 }
10761
10762
10763
10764
10765 public function __toString()
10766 {
10767 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
10768 }
10769 }
10770 <?php
10771
10772
10773
10774
10775
10776
10777
10778
10779
10780
10781
10782 namespace Composer\DependencyResolver\Operation;
10783
10784 use Composer\Package\AliasPackage;
10785 use Composer\Package\PackageInterface;
10786
10787
10788
10789
10790
10791
10792 class MarkAliasUninstalledOperation extends SolverOperation
10793 {
10794 protected $package;
10795
10796
10797
10798
10799
10800
10801
10802 public function __construct(AliasPackage $package, $reason = null)
10803 {
10804 parent::__construct($reason);
10805
10806 $this->package = $package;
10807 }
10808
10809
10810
10811
10812
10813
10814 public function getPackage()
10815 {
10816 return $this->package;
10817 }
10818
10819
10820
10821
10822
10823
10824 public function getJobType()
10825 {
10826 return 'markAliasUninstalled';
10827 }
10828
10829
10830
10831
10832 public function __toString()
10833 {
10834 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
10835 }
10836 }
10837 <?php
10838
10839
10840
10841
10842
10843
10844
10845
10846
10847
10848
10849 namespace Composer\DependencyResolver\Operation;
10850
10851
10852
10853
10854
10855
10856 interface OperationInterface
10857 {
10858
10859
10860
10861
10862
10863 public function getJobType();
10864
10865
10866
10867
10868
10869
10870 public function getReason();
10871
10872
10873
10874
10875
10876
10877 public function __toString();
10878 }
10879 <?php
10880
10881
10882
10883
10884
10885
10886
10887
10888
10889
10890
10891 namespace Composer\DependencyResolver\Operation;
10892
10893 use Composer\Package\PackageInterface;
10894
10895
10896
10897
10898
10899
10900 abstract class SolverOperation implements OperationInterface
10901 {
10902 protected $reason;
10903
10904
10905
10906
10907
10908
10909 public function __construct($reason = null)
10910 {
10911 $this->reason = $reason;
10912 }
10913
10914
10915
10916
10917
10918
10919 public function getReason()
10920 {
10921 return $this->reason;
10922 }
10923
10924 protected function formatVersion(PackageInterface $package)
10925 {
10926 return $package->getFullPrettyVersion();
10927 }
10928 }
10929 <?php
10930
10931
10932
10933
10934
10935
10936
10937
10938
10939
10940
10941 namespace Composer\DependencyResolver\Operation;
10942
10943 use Composer\Package\PackageInterface;
10944
10945
10946
10947
10948
10949
10950 class UninstallOperation extends SolverOperation
10951 {
10952 protected $package;
10953
10954
10955
10956
10957
10958
10959
10960 public function __construct(PackageInterface $package, $reason = null)
10961 {
10962 parent::__construct($reason);
10963
10964 $this->package = $package;
10965 }
10966
10967
10968
10969
10970
10971
10972 public function getPackage()
10973 {
10974 return $this->package;
10975 }
10976
10977
10978
10979
10980
10981
10982 public function getJobType()
10983 {
10984 return 'uninstall';
10985 }
10986
10987
10988
10989
10990 public function __toString()
10991 {
10992 return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
10993 }
10994 }
10995 <?php
10996
10997
10998
10999
11000
11001
11002
11003
11004
11005
11006
11007 namespace Composer\DependencyResolver\Operation;
11008
11009 use Composer\Package\PackageInterface;
11010
11011
11012
11013
11014
11015
11016 class UpdateOperation extends SolverOperation
11017 {
11018 protected $initialPackage;
11019 protected $targetPackage;
11020
11021
11022
11023
11024
11025
11026
11027
11028 public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
11029 {
11030 parent::__construct($reason);
11031
11032 $this->initialPackage = $initial;
11033 $this->targetPackage = $target;
11034 }
11035
11036
11037
11038
11039
11040
11041 public function getInitialPackage()
11042 {
11043 return $this->initialPackage;
11044 }
11045
11046
11047
11048
11049
11050
11051 public function getTargetPackage()
11052 {
11053 return $this->targetPackage;
11054 }
11055
11056
11057
11058
11059
11060
11061 public function getJobType()
11062 {
11063 return 'update';
11064 }
11065
11066
11067
11068
11069 public function __toString()
11070 {
11071 return 'Updating '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
11072 $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
11073 }
11074 }
11075 <?php
11076
11077
11078
11079
11080
11081
11082
11083
11084
11085
11086
11087 namespace Composer\DependencyResolver;
11088
11089 use Composer\Package\PackageInterface;
11090
11091
11092
11093
11094 interface PolicyInterface
11095 {
11096 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
11097
11098 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
11099
11100 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null);
11101 }
11102 <?php
11103
11104
11105
11106
11107
11108
11109
11110
11111
11112
11113
11114 namespace Composer\DependencyResolver;
11115
11116 use Composer\Package\BasePackage;
11117 use Composer\Package\AliasPackage;
11118 use Composer\Package\Version\VersionParser;
11119 use Composer\Semver\Constraint\ConstraintInterface;
11120 use Composer\Semver\Constraint\Constraint;
11121 use Composer\Semver\Constraint\EmptyConstraint;
11122 use Composer\Repository\RepositoryInterface;
11123 use Composer\Repository\CompositeRepository;
11124 use Composer\Repository\ComposerRepository;
11125 use Composer\Repository\InstalledRepositoryInterface;
11126 use Composer\Repository\PlatformRepository;
11127 use Composer\Package\PackageInterface;
11128
11129
11130
11131
11132
11133
11134
11135 class Pool implements \Countable
11136 {
11137 const MATCH_NAME = -1;
11138 const MATCH_NONE = 0;
11139 const MATCH = 1;
11140 const MATCH_PROVIDE = 2;
11141 const MATCH_REPLACE = 3;
11142 const MATCH_FILTERED = 4;
11143
11144 protected $repositories = array();
11145 protected $providerRepos = array();
11146 protected $packages = array();
11147 protected $packageByName = array();
11148 protected $packageByExactName = array();
11149 protected $acceptableStabilities;
11150 protected $stabilityFlags;
11151 protected $versionParser;
11152 protected $providerCache = array();
11153 protected $filterRequires;
11154 protected $whitelist = null;
11155 protected $id = 1;
11156
11157 public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
11158 {
11159 $this->versionParser = new VersionParser;
11160 $this->acceptableStabilities = array();
11161 foreach (BasePackage::$stabilities as $stability => $value) {
11162 if ($value <= BasePackage::$stabilities[$minimumStability]) {
11163 $this->acceptableStabilities[$stability] = $value;
11164 }
11165 }
11166 $this->stabilityFlags = $stabilityFlags;
11167 $this->filterRequires = $filterRequires;
11168 foreach ($filterRequires as $name => $constraint) {
11169 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
11170 unset($this->filterRequires[$name]);
11171 }
11172 }
11173 }
11174
11175 public function setWhitelist($whitelist)
11176 {
11177 $this->whitelist = $whitelist;
11178 $this->providerCache = array();
11179 }
11180
11181
11182
11183
11184
11185
11186
11187 public function addRepository(RepositoryInterface $repo, $rootAliases = array())
11188 {
11189 if ($repo instanceof CompositeRepository) {
11190 $repos = $repo->getRepositories();
11191 } else {
11192 $repos = array($repo);
11193 }
11194
11195 foreach ($repos as $repo) {
11196 $this->repositories[] = $repo;
11197
11198 $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
11199
11200 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
11201 $this->providerRepos[] = $repo;
11202 $repo->setRootAliases($rootAliases);
11203 $repo->resetPackageIds();
11204 } else {
11205 foreach ($repo->getPackages() as $package) {
11206 $names = $package->getNames();
11207 $stability = $package->getStability();
11208 if ($exempt || $this->isPackageAcceptable($names, $stability)) {
11209 $package->setId($this->id++);
11210 $this->packages[] = $package;
11211 $this->packageByExactName[$package->getName()][$package->id] = $package;
11212
11213 foreach ($names as $provided) {
11214 $this->packageByName[$provided][] = $package;
11215 }
11216
11217
11218  $name = $package->getName();
11219 if (isset($rootAliases[$name][$package->getVersion()])) {
11220 $alias = $rootAliases[$name][$package->getVersion()];
11221 if ($package instanceof AliasPackage) {
11222 $package = $package->getAliasOf();
11223 }
11224 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
11225 $aliasPackage->setRootPackageAlias(true);
11226 $aliasPackage->setId($this->id++);
11227
11228 $package->getRepository()->addPackage($aliasPackage);
11229 $this->packages[] = $aliasPackage;
11230 $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
11231
11232 foreach ($aliasPackage->getNames() as $name) {
11233 $this->packageByName[$name][] = $aliasPackage;
11234 }
11235 }
11236 }
11237 }
11238 }
11239 }
11240 }
11241
11242 public function getPriority(RepositoryInterface $repo)
11243 {
11244 $priority = array_search($repo, $this->repositories, true);
11245
11246 if (false === $priority) {
11247 throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
11248 }
11249
11250 return -$priority;
11251 }
11252
11253
11254
11255
11256
11257
11258
11259 public function packageById($id)
11260 {
11261 return $this->packages[$id - 1];
11262 }
11263
11264
11265
11266
11267 public function count()
11268 {
11269 return count($this->packages);
11270 }
11271
11272
11273
11274
11275
11276
11277
11278
11279
11280
11281
11282
11283 public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
11284 {
11285 if ($bypassFilters) {
11286 return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
11287 }
11288
11289 $key = ((int) $mustMatchName).$constraint;
11290 if (isset($this->providerCache[$name][$key])) {
11291 return $this->providerCache[$name][$key];
11292 }
11293
11294 return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
11295 }
11296
11297
11298
11299
11300 private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
11301 {
11302 $candidates = array();
11303
11304 foreach ($this->providerRepos as $repo) {
11305 foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
11306 $candidates[] = $candidate;
11307 if ($candidate->id < 1) {
11308 $candidate->setId($this->id++);
11309 $this->packages[$this->id - 2] = $candidate;
11310 }
11311 }
11312 }
11313
11314 if ($mustMatchName) {
11315 $candidates = array_filter($candidates, function ($candidate) use ($name) {
11316 return $candidate->getName() == $name;
11317 });
11318 if (isset($this->packageByExactName[$name])) {
11319 $candidates = array_merge($candidates, $this->packageByExactName[$name]);
11320 }
11321 } elseif (isset($this->packageByName[$name])) {
11322 $candidates = array_merge($candidates, $this->packageByName[$name]);
11323 }
11324
11325 $matches = $provideMatches = array();
11326 $nameMatch = false;
11327
11328 foreach ($candidates as $candidate) {
11329 $aliasOfCandidate = null;
11330
11331
11332  
11333  if ($candidate instanceof AliasPackage) {
11334 $aliasOfCandidate = $candidate->getAliasOf();
11335 }
11336
11337 if ($this->whitelist !== null && !$bypassFilters && (
11338 (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
11339 ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
11340 )) {
11341 continue;
11342 }
11343 switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
11344 case self::MATCH_NONE:
11345 break;
11346
11347 case self::MATCH_NAME:
11348 $nameMatch = true;
11349 break;
11350
11351 case self::MATCH:
11352 $nameMatch = true;
11353 $matches[] = $candidate;
11354 break;
11355
11356 case self::MATCH_PROVIDE:
11357 $provideMatches[] = $candidate;
11358 break;
11359
11360 case self::MATCH_REPLACE:
11361 $matches[] = $candidate;
11362 break;
11363
11364 case self::MATCH_FILTERED:
11365 break;
11366
11367 default:
11368 throw new \UnexpectedValueException('Unexpected match type');
11369 }
11370 }
11371
11372
11373  if ($nameMatch) {
11374 return $matches;
11375 }
11376
11377 return array_merge($matches, $provideMatches);
11378 }
11379
11380 public function literalToPackage($literal)
11381 {
11382 $packageId = abs($literal);
11383
11384 return $this->packageById($packageId);
11385 }
11386
11387 public function literalToPrettyString($literal, $installedMap)
11388 {
11389 $package = $this->literalToPackage($literal);
11390
11391 if (isset($installedMap[$package->id])) {
11392 $prefix = ($literal > 0 ? 'keep' : 'remove');
11393 } else {
11394 $prefix = ($literal > 0 ? 'install' : 'don\'t install');
11395 }
11396
11397 return $prefix.' '.$package->getPrettyString();
11398 }
11399
11400 public function isPackageAcceptable($name, $stability)
11401 {
11402 foreach ((array) $name as $n) {
11403
11404  if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
11405 return true;
11406 }
11407
11408
11409  if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
11410 return true;
11411 }
11412 }
11413
11414 return false;
11415 }
11416
11417
11418
11419
11420
11421
11422
11423
11424
11425
11426 private function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
11427 {
11428 $candidateName = $candidate->getName();
11429 $candidateVersion = $candidate->getVersion();
11430 $isDev = $candidate->getStability() === 'dev';
11431 $isAlias = $candidate instanceof AliasPackage;
11432
11433 if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
11434 $requireFilter = $this->filterRequires[$name];
11435 } else {
11436 $requireFilter = new EmptyConstraint;
11437 }
11438
11439 if ($candidateName === $name) {
11440 $pkgConstraint = new Constraint('==', $candidateVersion);
11441
11442 if ($constraint === null || $constraint->matches($pkgConstraint)) {
11443 return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
11444 }
11445
11446 return self::MATCH_NAME;
11447 }
11448
11449 $provides = $candidate->getProvides();
11450 $replaces = $candidate->getReplaces();
11451
11452
11453  if (isset($replaces[0]) || isset($provides[0])) {
11454 foreach ($provides as $link) {
11455 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11456 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11457 }
11458 }
11459
11460 foreach ($replaces as $link) {
11461 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11462 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11463 }
11464 }
11465
11466 return self::MATCH_NONE;
11467 }
11468
11469 if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
11470 return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11471 }
11472
11473 if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
11474 return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11475 }
11476
11477 return self::MATCH_NONE;
11478 }
11479 }
11480 <?php
11481
11482
11483
11484
11485
11486
11487
11488
11489
11490
11491
11492 namespace Composer\DependencyResolver;
11493 use Composer\Package\CompletePackageInterface;
11494
11495
11496
11497
11498
11499
11500 class Problem
11501 {
11502
11503
11504
11505
11506 protected $reasonSeen;
11507
11508
11509
11510
11511
11512 protected $reasons = array();
11513
11514 protected $section = 0;
11515
11516 protected $pool;
11517
11518 public function __construct(Pool $pool)
11519 {
11520 $this->pool = $pool;
11521 }
11522
11523
11524
11525
11526
11527
11528 public function addRule(Rule $rule)
11529 {
11530 $this->addReason(spl_object_hash($rule), array(
11531 'rule' => $rule,
11532 'job' => $rule->getJob(),
11533 ));
11534 }
11535
11536
11537
11538
11539
11540
11541 public function getReasons()
11542 {
11543 return $this->reasons;
11544 }
11545
11546
11547
11548
11549
11550
11551
11552 public function getPrettyString(array $installedMap = array())
11553 {
11554 $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
11555
11556 if (count($reasons) === 1) {
11557 reset($reasons);
11558 $reason = current($reasons);
11559
11560 $rule = $reason['rule'];
11561 $job = $reason['job'];
11562
11563 if (isset($job['constraint'])) {
11564 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11565 } else {
11566 $packages = array();
11567 }
11568
11569 if ($job && $job['cmd'] === 'install' && empty($packages)) {
11570
11571
11572  if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') {
11573 $version = phpversion();
11574 $available = $this->pool->whatProvides($job['packageName']);
11575
11576 if (count($available)) {
11577 $firstAvailable = reset($available);
11578 $version = $firstAvailable->getPrettyVersion();
11579 $extra = $firstAvailable->getExtra();
11580 if ($firstAvailable instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) {
11581 $version .= '; ' . $firstAvailable->getDescription();
11582 }
11583 }
11584
11585 $msg = "\n    - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but ';
11586
11587 if (defined('HHVM_VERSION')) {
11588 return $msg . 'your HHVM version does not satisfy that requirement.';
11589 }
11590
11591 if ($job['packageName'] === 'hhvm') {
11592 return $msg . 'you are running this with PHP and not HHVM.';
11593 }
11594
11595 return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
11596 }
11597
11598
11599  if (0 === stripos($job['packageName'], 'ext-')) {
11600 if (false !== strpos($job['packageName'], ' ')) {
11601 return "\n    - The requested PHP extension ".$job['packageName'].' should be required as '.str_replace(' ', '-', $job['packageName']).'.';
11602 }
11603
11604 $ext = substr($job['packageName'], 4);
11605 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
11606
11607 return "\n    - The requested PHP extension ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
11608 }
11609
11610
11611  if (0 === stripos($job['packageName'], 'lib-')) {
11612 if (strtolower($job['packageName']) === 'lib-icu') {
11613 $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.';
11614
11615 return "\n    - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error;
11616 }
11617
11618 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.';
11619 }
11620
11621 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $job['packageName'])) {
11622 $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $job['packageName']);
11623
11624 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.';
11625 }
11626
11627 if ($providers = $this->pool->whatProvides($job['packageName'], $job['constraint'], true, true)) {
11628 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.';
11629 }
11630
11631 if ($providers = $this->pool->whatProvides($job['packageName'], null, true, true)) {
11632 return "\n    - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
11633 }
11634
11635 return "\n    - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.';
11636 }
11637 }
11638
11639 $messages = array();
11640
11641 foreach ($reasons as $reason) {
11642 $rule = $reason['rule'];
11643 $job = $reason['job'];
11644
11645 if ($job) {
11646 $messages[] = $this->jobToText($job);
11647 } elseif ($rule) {
11648 if ($rule instanceof Rule) {
11649 $messages[] = $rule->getPrettyString($this->pool, $installedMap);
11650 }
11651 }
11652 }
11653
11654 return "\n    - ".implode("\n    - ", $messages);
11655 }
11656
11657
11658
11659
11660
11661
11662
11663 protected function addReason($id, $reason)
11664 {
11665 if (!isset($this->reasonSeen[$id])) {
11666 $this->reasonSeen[$id] = true;
11667 $this->reasons[$this->section][] = $reason;
11668 }
11669 }
11670
11671 public function nextSection()
11672 {
11673 $this->section++;
11674 }
11675
11676
11677
11678
11679
11680
11681
11682 protected function jobToText($job)
11683 {
11684 switch ($job['cmd']) {
11685 case 'install':
11686 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11687 if (!$packages) {
11688 return 'No package found to satisfy install request for '.$job['packageName'].$this->constraintToText($job['constraint']);
11689 }
11690
11691 return 'Installation request for '.$job['packageName'].$this->constraintToText($job['constraint']).' -> satisfiable by '.$this->getPackageList($packages).'.';
11692 case 'update':
11693 return 'Update request for '.$job['packageName'].$this->constraintToText($job['constraint']).'.';
11694 case 'remove':
11695 return 'Removal request for '.$job['packageName'].$this->constraintToText($job['constraint']).'';
11696 }
11697
11698 if (isset($job['constraint'])) {
11699 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11700 } else {
11701 $packages = array();
11702 }
11703
11704 return 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.$this->getPackageList($packages).'])';
11705 }
11706
11707 protected function getPackageList($packages)
11708 {
11709 $prepared = array();
11710 foreach ($packages as $package) {
11711 $prepared[$package->getName()]['name'] = $package->getPrettyName();
11712 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
11713 }
11714 foreach ($prepared as $name => $package) {
11715 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
11716 }
11717
11718 return implode(', ', $prepared);
11719 }
11720
11721
11722
11723
11724
11725
11726
11727 protected function constraintToText($constraint)
11728 {
11729 return ($constraint) ? ' '.$constraint->getPrettyString() : '';
11730 }
11731 }
11732 <?php
11733
11734
11735
11736
11737
11738
11739
11740
11741
11742
11743
11744 namespace Composer\DependencyResolver;
11745
11746 use Composer\Semver\Constraint\ConstraintInterface;
11747
11748
11749
11750
11751 class Request
11752 {
11753 protected $jobs;
11754
11755 public function __construct()
11756 {
11757 $this->jobs = array();
11758 }
11759
11760 public function install($packageName, ConstraintInterface $constraint = null)
11761 {
11762 $this->addJob($packageName, 'install', $constraint);
11763 }
11764
11765 public function update($packageName, ConstraintInterface $constraint = null)
11766 {
11767 $this->addJob($packageName, 'update', $constraint);
11768 }
11769
11770 public function remove($packageName, ConstraintInterface $constraint = null)
11771 {
11772 $this->addJob($packageName, 'remove', $constraint);
11773 }
11774
11775
11776
11777
11778
11779
11780
11781
11782
11783 public function fix($packageName, ConstraintInterface $constraint = null)
11784 {
11785 $this->addJob($packageName, 'install', $constraint, true);
11786 }
11787
11788 protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
11789 {
11790 $packageName = strtolower($packageName);
11791
11792 $this->jobs[] = array(
11793 'cmd' => $cmd,
11794 'packageName' => $packageName,
11795 'constraint' => $constraint,
11796 'fixed' => $fixed,
11797 );
11798 }
11799
11800 public function updateAll()
11801 {
11802 $this->jobs[] = array('cmd' => 'update-all');
11803 }
11804
11805 public function getJobs()
11806 {
11807 return $this->jobs;
11808 }
11809 }
11810 <?php
11811
11812
11813
11814
11815
11816
11817
11818
11819
11820
11821
11822 namespace Composer\DependencyResolver;
11823
11824 use Composer\Package\CompletePackage;
11825 use Composer\Package\Link;
11826 use Composer\Package\PackageInterface;
11827
11828
11829
11830
11831
11832 abstract class Rule
11833 {
11834
11835  const RULE_INTERNAL_ALLOW_UPDATE = 1;
11836 const RULE_JOB_INSTALL = 2;
11837 const RULE_JOB_REMOVE = 3;
11838 const RULE_PACKAGE_CONFLICT = 6;
11839 const RULE_PACKAGE_REQUIRES = 7;
11840 const RULE_PACKAGE_OBSOLETES = 8;
11841 const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
11842 const RULE_PACKAGE_SAME_NAME = 10;
11843 const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
11844 const RULE_LEARNED = 12;
11845 const RULE_PACKAGE_ALIAS = 13;
11846
11847
11848  const BITFIELD_TYPE = 0;
11849 const BITFIELD_REASON = 8;
11850 const BITFIELD_DISABLED = 16;
11851
11852 protected $bitfield;
11853 protected $reasonData;
11854
11855
11856
11857
11858
11859
11860 public function __construct($reason, $reasonData, $job = null)
11861 {
11862 $this->reasonData = $reasonData;
11863
11864 if ($job) {
11865 $this->job = $job;
11866 }
11867
11868 $this->bitfield = (0 << self::BITFIELD_DISABLED) |
11869 ($reason << self::BITFIELD_REASON) |
11870 (255 << self::BITFIELD_TYPE);
11871 }
11872
11873 abstract public function getLiterals();
11874
11875 abstract public function getHash();
11876
11877 public function getJob()
11878 {
11879 return isset($this->job) ? $this->job : null;
11880 }
11881
11882 abstract public function equals(Rule $rule);
11883
11884 public function getReason()
11885 {
11886 return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
11887 }
11888
11889 public function getReasonData()
11890 {
11891 return $this->reasonData;
11892 }
11893
11894 public function getRequiredPackage()
11895 {
11896 if ($this->getReason() === self::RULE_JOB_INSTALL) {
11897 return $this->reasonData;
11898 }
11899
11900 if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
11901 return $this->reasonData->getTarget();
11902 }
11903 }
11904
11905 public function setType($type)
11906 {
11907 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
11908 }
11909
11910 public function getType()
11911 {
11912 return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
11913 }
11914
11915 public function disable()
11916 {
11917 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
11918 }
11919
11920 public function enable()
11921 {
11922 $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED);
11923 }
11924
11925 public function isDisabled()
11926 {
11927 return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
11928 }
11929
11930 public function isEnabled()
11931 {
11932 return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
11933 }
11934
11935 abstract public function isAssertion();
11936
11937 public function getPrettyString(Pool $pool, array $installedMap = array())
11938 {
11939 $literals = $this->getLiterals();
11940
11941 $ruleText = '';
11942 foreach ($literals as $i => $literal) {
11943 if ($i != 0) {
11944 $ruleText .= '|';
11945 }
11946 $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
11947 }
11948
11949 switch ($this->getReason()) {
11950 case self::RULE_INTERNAL_ALLOW_UPDATE:
11951 return $ruleText;
11952
11953 case self::RULE_JOB_INSTALL:
11954 return "Install command rule ($ruleText)";
11955
11956 case self::RULE_JOB_REMOVE:
11957 return "Remove command rule ($ruleText)";
11958
11959 case self::RULE_PACKAGE_CONFLICT:
11960 $package1 = $pool->literalToPackage($literals[0]);
11961 $package2 = $pool->literalToPackage($literals[1]);
11962
11963 return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
11964
11965 case self::RULE_PACKAGE_REQUIRES:
11966 $sourceLiteral = array_shift($literals);
11967 $sourcePackage = $pool->literalToPackage($sourceLiteral);
11968
11969 $requires = array();
11970 foreach ($literals as $literal) {
11971 $requires[] = $pool->literalToPackage($literal);
11972 }
11973
11974 $text = $this->reasonData->getPrettyString($sourcePackage);
11975 if ($requires) {
11976 $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
11977 } else {
11978 $targetName = $this->reasonData->getTarget();
11979
11980 if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
11981
11982  if (defined('HHVM_VERSION')) {
11983 return $text . ' -> your HHVM version does not satisfy that requirement.';
11984 }
11985
11986 if ($targetName === 'hhvm') {
11987 return $text . ' -> you are running this with PHP and not HHVM.';
11988 }
11989
11990 $packages = $pool->whatProvides($targetName);
11991 $package = count($packages) ? current($packages) : phpversion();
11992
11993 if (!($package instanceof CompletePackage)) {
11994 return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
11995 }
11996
11997 $extra = $package->getExtra();
11998
11999 if (!empty($extra['config.platform'])) {
12000 $text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
12001 } else {
12002 $text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
12003 }
12004
12005 return $text;
12006 }
12007
12008 if (0 === strpos($targetName, 'ext-')) {
12009
12010  $ext = substr($targetName, 4);
12011 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
12012
12013 return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
12014 }
12015
12016 if (0 === strpos($targetName, 'lib-')) {
12017
12018  $lib = substr($targetName, 4);
12019
12020 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.';
12021 }
12022
12023 if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
12024 return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
12025 }
12026
12027 return $text . ' -> no matching package found.';
12028 }
12029
12030 return $text;
12031
12032 case self::RULE_PACKAGE_OBSOLETES:
12033 return $ruleText;
12034 case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
12035 return $ruleText;
12036 case self::RULE_PACKAGE_SAME_NAME:
12037 return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $literals) . '.';
12038 case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
12039 return $ruleText;
12040 case self::RULE_LEARNED:
12041 return 'Conclusion: '.$ruleText;
12042 case self::RULE_PACKAGE_ALIAS:
12043 return $ruleText;
12044 default:
12045 return '('.$ruleText.')';
12046 }
12047 }
12048
12049
12050
12051
12052
12053
12054
12055 protected function formatPackagesUnique($pool, array $packages)
12056 {
12057 $prepared = array();
12058 foreach ($packages as $package) {
12059 if (!is_object($package)) {
12060 $package = $pool->literalToPackage($package);
12061 }
12062 $prepared[$package->getName()]['name'] = $package->getPrettyName();
12063 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
12064 }
12065 foreach ($prepared as $name => $package) {
12066 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
12067 }
12068
12069 return implode(', ', $prepared);
12070 }
12071 }
12072 <?php
12073
12074
12075
12076
12077
12078
12079
12080
12081
12082
12083
12084 namespace Composer\DependencyResolver;
12085
12086 use Composer\Package\PackageInterface;
12087 use Composer\Package\Link;
12088
12089
12090
12091
12092 class Rule2Literals extends Rule
12093 {
12094 protected $literal1;
12095 protected $literal2;
12096
12097
12098
12099
12100
12101
12102
12103
12104 public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
12105 {
12106 parent::__construct($reason, $reasonData, $job);
12107
12108 if ($literal1 < $literal2) {
12109 $this->literal1 = $literal1;
12110 $this->literal2 = $literal2;
12111 } else {
12112 $this->literal1 = $literal2;
12113 $this->literal2 = $literal1;
12114 }
12115 }
12116
12117 public function getLiterals()
12118 {
12119 return array($this->literal1, $this->literal2);
12120 }
12121
12122 public function getHash()
12123 {
12124 $data = unpack('ihash', md5($this->literal1.','.$this->literal2, true));
12125
12126 return $data['hash'];
12127 }
12128
12129
12130
12131
12132
12133
12134
12135
12136
12137 public function equals(Rule $rule)
12138 {
12139 $literals = $rule->getLiterals();
12140 if (2 != count($literals)) {
12141 return false;
12142 }
12143
12144 if ($this->literal1 !== $literals[0]) {
12145 return false;
12146 }
12147
12148 if ($this->literal2 !== $literals[1]) {
12149 return false;
12150 }
12151
12152 return true;
12153 }
12154
12155 public function isAssertion()
12156 {
12157 return false;
12158 }
12159
12160
12161
12162
12163
12164
12165 public function __toString()
12166 {
12167 $result = ($this->isDisabled()) ? 'disabled(' : '(';
12168
12169 $result .= $this->literal1 . '|' . $this->literal2 . ')';
12170
12171 return $result;
12172 }
12173 }
12174 <?php
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186 namespace Composer\DependencyResolver;
12187
12188
12189
12190
12191 class RuleSet implements \IteratorAggregate, \Countable
12192 {
12193
12194  const TYPE_PACKAGE = 0;
12195 const TYPE_JOB = 1;
12196 const TYPE_LEARNED = 4;
12197
12198
12199
12200
12201
12202
12203 public $ruleById;
12204
12205 protected static $types = array(
12206 255 => 'UNKNOWN',
12207 self::TYPE_PACKAGE => 'PACKAGE',
12208 self::TYPE_JOB => 'JOB',
12209 self::TYPE_LEARNED => 'LEARNED',
12210 );
12211
12212 protected $rules;
12213 protected $nextRuleId;
12214
12215 protected $rulesByHash;
12216
12217 public function __construct()
12218 {
12219 $this->nextRuleId = 0;
12220
12221 foreach ($this->getTypes() as $type) {
12222 $this->rules[$type] = array();
12223 }
12224
12225 $this->rulesByHash = array();
12226 }
12227
12228 public function add(Rule $rule, $type)
12229 {
12230 if (!isset(self::$types[$type])) {
12231 throw new \OutOfBoundsException('Unknown rule type: ' . $type);
12232 }
12233
12234 $hash = $rule->getHash();
12235
12236
12237  if (isset($this->rulesByHash[$hash])) {
12238 $potentialDuplicates = $this->rulesByHash[$hash];
12239 if (is_array($potentialDuplicates)) {
12240 foreach ($potentialDuplicates as $potentialDuplicate) {
12241 if ($rule->equals($potentialDuplicate)) {
12242 return;
12243 }
12244 }
12245 } else {
12246 if ($rule->equals($potentialDuplicates)) {
12247 return;
12248 }
12249 }
12250 }
12251
12252 if (!isset($this->rules[$type])) {
12253 $this->rules[$type] = array();
12254 }
12255
12256 $this->rules[$type][] = $rule;
12257 $this->ruleById[$this->nextRuleId] = $rule;
12258 $rule->setType($type);
12259
12260 $this->nextRuleId++;
12261
12262 if (!isset($this->rulesByHash[$hash])) {
12263 $this->rulesByHash[$hash] = $rule;
12264 } elseif (is_array($this->rulesByHash[$hash])) {
12265 $this->rulesByHash[$hash][] = $rule;
12266 } else {
12267 $originalRule = $this->rulesByHash[$hash];
12268 $this->rulesByHash[$hash] = array($originalRule, $rule);
12269 }
12270 }
12271
12272 public function count()
12273 {
12274 return $this->nextRuleId;
12275 }
12276
12277 public function ruleById($id)
12278 {
12279 return $this->ruleById[$id];
12280 }
12281
12282 public function getRules()
12283 {
12284 return $this->rules;
12285 }
12286
12287 public function getIterator()
12288 {
12289 return new RuleSetIterator($this->getRules());
12290 }
12291
12292 public function getIteratorFor($types)
12293 {
12294 if (!is_array($types)) {
12295 $types = array($types);
12296 }
12297
12298 $allRules = $this->getRules();
12299 $rules = array();
12300
12301 foreach ($types as $type) {
12302 $rules[$type] = $allRules[$type];
12303 }
12304
12305 return new RuleSetIterator($rules);
12306 }
12307
12308 public function getIteratorWithout($types)
12309 {
12310 if (!is_array($types)) {
12311 $types = array($types);
12312 }
12313
12314 $rules = $this->getRules();
12315
12316 foreach ($types as $type) {
12317 unset($rules[$type]);
12318 }
12319
12320 return new RuleSetIterator($rules);
12321 }
12322
12323 public function getTypes()
12324 {
12325 $types = self::$types;
12326 unset($types[255]);
12327
12328 return array_keys($types);
12329 }
12330
12331 public function getPrettyString(Pool $pool = null)
12332 {
12333 $string = "\n";
12334 foreach ($this->rules as $type => $rules) {
12335 $string .= str_pad(self::$types[$type], 8, ' ') . ": ";
12336 foreach ($rules as $rule) {
12337 $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
12338 }
12339 $string .= "\n\n";
12340 }
12341
12342 return $string;
12343 }
12344
12345 public function __toString()
12346 {
12347 return $this->getPrettyString(null);
12348 }
12349 }
12350 <?php
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362 namespace Composer\DependencyResolver;
12363
12364 use Composer\Package\PackageInterface;
12365 use Composer\Package\AliasPackage;
12366 use Composer\Repository\PlatformRepository;
12367
12368
12369
12370
12371 class RuleSetGenerator
12372 {
12373 protected $policy;
12374 protected $pool;
12375 protected $rules;
12376 protected $jobs;
12377 protected $installedMap;
12378 protected $whitelistedMap;
12379 protected $addedMap;
12380
12381 public function __construct(PolicyInterface $policy, Pool $pool)
12382 {
12383 $this->policy = $policy;
12384 $this->pool = $pool;
12385 }
12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
12396
12397
12398
12399
12400
12401 protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
12402 {
12403 $literals = array(-$package->id);
12404
12405 foreach ($providers as $provider) {
12406
12407  if ($provider === $package) {
12408 return null;
12409 }
12410 $literals[] = $provider->id;
12411 }
12412
12413 return new GenericRule($literals, $reason, $reasonData);
12414 }
12415
12416
12417
12418
12419
12420
12421
12422
12423
12424
12425
12426
12427
12428 protected function createInstallOneOfRule(array $packages, $reason, $job)
12429 {
12430 $literals = array();
12431 foreach ($packages as $package) {
12432 $literals[] = $package->id;
12433 }
12434
12435 return new GenericRule($literals, $reason, $job['packageName'], $job);
12436 }
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449 protected function createRemoveRule(PackageInterface $package, $reason, $job)
12450 {
12451 return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
12452 }
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463
12464
12465
12466
12467
12468 protected function createRule2Literals(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
12469 {
12470
12471  if ($issuer === $provider) {
12472 return null;
12473 }
12474
12475 return new Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
12476 }
12477
12478
12479
12480
12481
12482
12483
12484
12485
12486
12487 private function addRule($type, Rule $newRule = null)
12488 {
12489 if (!$newRule) {
12490 return;
12491 }
12492
12493 $this->rules->add($newRule, $type);
12494 }
12495
12496 protected function whitelistFromPackage(PackageInterface $package)
12497 {
12498 $workQueue = new \SplQueue;
12499 $workQueue->enqueue($package);
12500
12501 while (!$workQueue->isEmpty()) {
12502 $package = $workQueue->dequeue();
12503 if (isset($this->whitelistedMap[$package->id])) {
12504 continue;
12505 }
12506
12507 $this->whitelistedMap[$package->id] = true;
12508
12509 foreach ($package->getRequires() as $link) {
12510 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
12511
12512 foreach ($possibleRequires as $require) {
12513 $workQueue->enqueue($require);
12514 }
12515 }
12516
12517 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
12518
12519 foreach ($obsoleteProviders as $provider) {
12520 if ($provider === $package) {
12521 continue;
12522 }
12523
12524 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12525 $workQueue->enqueue($provider);
12526 }
12527 }
12528 }
12529 }
12530
12531 protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
12532 {
12533 $workQueue = new \SplQueue;
12534 $workQueue->enqueue($package);
12535
12536 while (!$workQueue->isEmpty()) {
12537 $package = $workQueue->dequeue();
12538 if (isset($this->addedMap[$package->id])) {
12539 continue;
12540 }
12541
12542 $this->addedMap[$package->id] = true;
12543
12544 foreach ($package->getRequires() as $link) {
12545 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
12546 continue;
12547 }
12548
12549 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12550
12551 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
12552
12553 foreach ($possibleRequires as $require) {
12554 $workQueue->enqueue($require);
12555 }
12556 }
12557
12558 foreach ($package->getConflicts() as $link) {
12559 $possibleConflicts = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12560
12561 foreach ($possibleConflicts as $conflict) {
12562 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $conflict, Rule::RULE_PACKAGE_CONFLICT, $link));
12563 }
12564 }
12565
12566
12567  $isInstalled = (isset($this->installedMap[$package->id]));
12568
12569 foreach ($package->getReplaces() as $link) {
12570 $obsoleteProviders = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12571
12572 foreach ($obsoleteProviders as $provider) {
12573 if ($provider === $package) {
12574 continue;
12575 }
12576
12577 if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12578 $reason = ($isInstalled) ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
12579 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $link));
12580 }
12581 }
12582 }
12583
12584 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null);
12585
12586 foreach ($obsoleteProviders as $provider) {
12587 if ($provider === $package) {
12588 continue;
12589 }
12590
12591 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12592 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
12593 } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12594 $reason = ($package->getName() == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
12595 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRule2Literals($package, $provider, $reason, $package));
12596 }
12597 }
12598 }
12599 }
12600
12601 protected function obsoleteImpossibleForAlias($package, $provider)
12602 {
12603 $packageIsAlias = $package instanceof AliasPackage;
12604 $providerIsAlias = $provider instanceof AliasPackage;
12605
12606 $impossible = (
12607 ($packageIsAlias && $package->getAliasOf() === $provider) ||
12608 ($providerIsAlias && $provider->getAliasOf() === $package) ||
12609 ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
12610 );
12611
12612 return $impossible;
12613 }
12614
12615 protected function whitelistFromJobs()
12616 {
12617 foreach ($this->jobs as $job) {
12618 switch ($job['cmd']) {
12619 case 'install':
12620 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
12621 foreach ($packages as $package) {
12622 $this->whitelistFromPackage($package);
12623 }
12624 break;
12625 }
12626 }
12627 }
12628
12629 protected function addRulesForJobs($ignorePlatformReqs)
12630 {
12631 foreach ($this->jobs as $job) {
12632 switch ($job['cmd']) {
12633 case 'install':
12634 if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
12635 break;
12636 }
12637
12638 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12639 if ($packages) {
12640 foreach ($packages as $package) {
12641 if (!isset($this->installedMap[$package->id])) {
12642 $this->addRulesForPackage($package, $ignorePlatformReqs);
12643 }
12644 }
12645
12646 $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
12647 $this->addRule(RuleSet::TYPE_JOB, $rule);
12648 }
12649 break;
12650 case 'remove':
12651
12652  
12653  $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12654 foreach ($packages as $package) {
12655 $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
12656 $this->addRule(RuleSet::TYPE_JOB, $rule);
12657 }
12658 break;
12659 }
12660 }
12661 }
12662
12663 public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
12664 {
12665 $this->jobs = $jobs;
12666 $this->rules = new RuleSet;
12667 $this->installedMap = $installedMap;
12668
12669 $this->whitelistedMap = array();
12670 foreach ($this->installedMap as $package) {
12671 $this->whitelistFromPackage($package);
12672 }
12673 $this->whitelistFromJobs();
12674
12675 $this->pool->setWhitelist($this->whitelistedMap);
12676
12677 $this->addedMap = array();
12678 foreach ($this->installedMap as $package) {
12679 $this->addRulesForPackage($package, $ignorePlatformReqs);
12680 }
12681
12682 $this->addRulesForJobs($ignorePlatformReqs);
12683
12684 return $this->rules;
12685 }
12686 }
12687 <?php
12688
12689
12690
12691
12692
12693
12694
12695
12696
12697
12698
12699 namespace Composer\DependencyResolver;
12700
12701
12702
12703
12704 class RuleSetIterator implements \Iterator
12705 {
12706 protected $rules;
12707 protected $types;
12708
12709 protected $currentOffset;
12710 protected $currentType;
12711 protected $currentTypeOffset;
12712
12713 public function __construct(array $rules)
12714 {
12715 $this->rules = $rules;
12716 $this->types = array_keys($rules);
12717 sort($this->types);
12718
12719 $this->rewind();
12720 }
12721
12722 public function current()
12723 {
12724 return $this->rules[$this->currentType][$this->currentOffset];
12725 }
12726
12727 public function key()
12728 {
12729 return $this->currentType;
12730 }
12731
12732 public function next()
12733 {
12734 $this->currentOffset++;
12735
12736 if (!isset($this->rules[$this->currentType])) {
12737 return;
12738 }
12739
12740 if ($this->currentOffset >= count($this->rules[$this->currentType])) {
12741 $this->currentOffset = 0;
12742
12743 do {
12744 $this->currentTypeOffset++;
12745
12746 if (!isset($this->types[$this->currentTypeOffset])) {
12747 $this->currentType = -1;
12748 break;
12749 }
12750
12751 $this->currentType = $this->types[$this->currentTypeOffset];
12752 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
12753 }
12754 }
12755
12756 public function rewind()
12757 {
12758 $this->currentOffset = 0;
12759
12760 $this->currentTypeOffset = -1;
12761 $this->currentType = -1;
12762
12763 do {
12764 $this->currentTypeOffset++;
12765
12766 if (!isset($this->types[$this->currentTypeOffset])) {
12767 $this->currentType = -1;
12768 break;
12769 }
12770
12771 $this->currentType = $this->types[$this->currentTypeOffset];
12772 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
12773 }
12774
12775 public function valid()
12776 {
12777 return isset($this->rules[$this->currentType])
12778 && isset($this->rules[$this->currentType][$this->currentOffset]);
12779 }
12780 }
12781 <?php
12782
12783
12784
12785
12786
12787
12788
12789
12790
12791
12792
12793 namespace Composer\DependencyResolver;
12794
12795
12796
12797
12798
12799
12800
12801
12802
12803 class RuleWatchChain extends \SplDoublyLinkedList
12804 {
12805 protected $offset = 0;
12806
12807
12808
12809
12810
12811
12812 public function seek($offset)
12813 {
12814 $this->rewind();
12815 for ($i = 0; $i < $offset; $i++, $this->next());
12816 }
12817
12818
12819
12820
12821
12822
12823
12824
12825
12826 public function remove()
12827 {
12828 $offset = $this->key();
12829 $this->offsetUnset($offset);
12830 $this->seek($offset);
12831 }
12832 }
12833 <?php
12834
12835
12836
12837
12838
12839
12840
12841
12842
12843
12844
12845 namespace Composer\DependencyResolver;
12846
12847
12848
12849
12850
12851
12852
12853
12854
12855
12856
12857 class RuleWatchGraph
12858 {
12859 protected $watchChains = array();
12860
12861
12862
12863
12864
12865
12866
12867
12868
12869
12870
12871
12872
12873 public function insert(RuleWatchNode $node)
12874 {
12875 if ($node->getRule()->isAssertion()) {
12876 return;
12877 }
12878
12879 foreach (array($node->watch1, $node->watch2) as $literal) {
12880 if (!isset($this->watchChains[$literal])) {
12881 $this->watchChains[$literal] = new RuleWatchChain;
12882 }
12883
12884 $this->watchChains[$literal]->unshift($node);
12885 }
12886 }
12887
12888
12889
12890
12891
12892
12893
12894
12895
12896
12897
12898
12899
12900
12901
12902
12903
12904
12905
12906
12907
12908
12909
12910
12911 public function propagateLiteral($decidedLiteral, $level, $decisions)
12912 {
12913
12914  
12915  
12916  $literal = -$decidedLiteral;
12917
12918 if (!isset($this->watchChains[$literal])) {
12919 return null;
12920 }
12921
12922 $chain = $this->watchChains[$literal];
12923
12924 $chain->rewind();
12925 while ($chain->valid()) {
12926 $node = $chain->current();
12927 $otherWatch = $node->getOtherWatch($literal);
12928
12929 if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
12930 $ruleLiterals = $node->getRule()->getLiterals();
12931
12932 $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
12933 return $literal !== $ruleLiteral &&
12934 $otherWatch !== $ruleLiteral &&
12935 !$decisions->conflict($ruleLiteral);
12936 });
12937
12938 if ($alternativeLiterals) {
12939 reset($alternativeLiterals);
12940 $this->moveWatch($literal, current($alternativeLiterals), $node);
12941 continue;
12942 }
12943
12944 if ($decisions->conflict($otherWatch)) {
12945 return $node->getRule();
12946 }
12947
12948 $decisions->decide($otherWatch, $level, $node->getRule());
12949 }
12950
12951 $chain->next();
12952 }
12953
12954 return null;
12955 }
12956
12957
12958
12959
12960
12961
12962
12963
12964
12965
12966 protected function moveWatch($fromLiteral, $toLiteral, $node)
12967 {
12968 if (!isset($this->watchChains[$toLiteral])) {
12969 $this->watchChains[$toLiteral] = new RuleWatchChain;
12970 }
12971
12972 $node->moveWatch($fromLiteral, $toLiteral);
12973 $this->watchChains[$fromLiteral]->remove();
12974 $this->watchChains[$toLiteral]->unshift($node);
12975 }
12976 }
12977 <?php
12978
12979
12980
12981
12982
12983
12984
12985
12986
12987
12988
12989 namespace Composer\DependencyResolver;
12990
12991
12992
12993
12994
12995
12996
12997
12998 class RuleWatchNode
12999 {
13000 public $watch1;
13001 public $watch2;
13002
13003 protected $rule;
13004
13005
13006
13007
13008
13009
13010 public function __construct($rule)
13011 {
13012 $this->rule = $rule;
13013
13014 $literals = $rule->getLiterals();
13015
13016 $this->watch1 = count($literals) > 0 ? $literals[0] : 0;
13017 $this->watch2 = count($literals) > 1 ? $literals[1] : 0;
13018 }
13019
13020
13021
13022
13023
13024
13025
13026
13027
13028 public function watch2OnHighest(Decisions $decisions)
13029 {
13030 $literals = $this->rule->getLiterals();
13031
13032
13033  if (count($literals) < 3) {
13034 return;
13035 }
13036
13037 $watchLevel = 0;
13038
13039 foreach ($literals as $literal) {
13040 $level = $decisions->decisionLevel($literal);
13041
13042 if ($level > $watchLevel) {
13043 $this->watch2 = $literal;
13044 $watchLevel = $level;
13045 }
13046 }
13047 }
13048
13049
13050
13051
13052
13053
13054 public function getRule()
13055 {
13056 return $this->rule;
13057 }
13058
13059
13060
13061
13062
13063
13064
13065 public function getOtherWatch($literal)
13066 {
13067 if ($this->watch1 == $literal) {
13068 return $this->watch2;
13069 }
13070
13071 return $this->watch1;
13072 }
13073
13074
13075
13076
13077
13078
13079
13080 public function moveWatch($from, $to)
13081 {
13082 if ($this->watch1 == $from) {
13083 $this->watch1 = $to;
13084 } else {
13085 $this->watch2 = $to;
13086 }
13087 }
13088 }
13089 <?php
13090
13091
13092
13093
13094
13095
13096
13097
13098
13099
13100
13101 namespace Composer\DependencyResolver;
13102
13103 use Composer\IO\IOInterface;
13104 use Composer\Repository\RepositoryInterface;
13105 use Composer\Repository\PlatformRepository;
13106
13107
13108
13109
13110 class Solver
13111 {
13112 const BRANCH_LITERALS = 0;
13113 const BRANCH_LEVEL = 1;
13114
13115
13116 protected $policy;
13117
13118 protected $pool;
13119
13120 protected $installed;
13121
13122 protected $rules;
13123
13124 protected $ruleSetGenerator;
13125
13126 protected $jobs;
13127
13128
13129 protected $updateMap = array();
13130
13131 protected $watchGraph;
13132
13133 protected $decisions;
13134
13135 protected $installedMap;
13136
13137
13138 protected $propagateIndex;
13139
13140 protected $branches = array();
13141
13142 protected $problems = array();
13143
13144 protected $learnedPool = array();
13145
13146 protected $learnedWhy = array();
13147
13148
13149 protected $io;
13150
13151
13152
13153
13154
13155
13156
13157 public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
13158 {
13159 $this->io = $io;
13160 $this->policy = $policy;
13161 $this->pool = $pool;
13162 $this->installed = $installed;
13163 $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
13164 }
13165
13166
13167
13168
13169 public function getRuleSetSize()
13170 {
13171 return count($this->rules);
13172 }
13173
13174
13175
13176 private function makeAssertionRuleDecisions()
13177 {
13178 $decisionStart = count($this->decisions) - 1;
13179
13180 $rulesCount = count($this->rules);
13181 for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
13182 $rule = $this->rules->ruleById[$ruleIndex];
13183
13184 if (!$rule->isAssertion() || $rule->isDisabled()) {
13185 continue;
13186 }
13187
13188 $literals = $rule->getLiterals();
13189 $literal = $literals[0];
13190
13191 if (!$this->decisions->decided(abs($literal))) {
13192 $this->decisions->decide($literal, 1, $rule);
13193 continue;
13194 }
13195
13196 if ($this->decisions->satisfy($literal)) {
13197 continue;
13198 }
13199
13200
13201  if (RuleSet::TYPE_LEARNED === $rule->getType()) {
13202 $rule->disable();
13203 continue;
13204 }
13205
13206 $conflict = $this->decisions->decisionRule($literal);
13207
13208 if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
13209 $problem = new Problem($this->pool);
13210
13211 $problem->addRule($rule);
13212 $problem->addRule($conflict);
13213 $this->disableProblem($rule);
13214 $this->problems[] = $problem;
13215 continue;
13216 }
13217
13218
13219  $problem = new Problem($this->pool);
13220 $problem->addRule($rule);
13221 $problem->addRule($conflict);
13222
13223
13224  
13225  foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
13226 if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
13227 continue;
13228 }
13229
13230 $assertRuleLiterals = $assertRule->getLiterals();
13231 $assertRuleLiteral = $assertRuleLiterals[0];
13232
13233 if (abs($literal) !== abs($assertRuleLiteral)) {
13234 continue;
13235 }
13236
13237 $problem->addRule($assertRule);
13238 $this->disableProblem($assertRule);
13239 }
13240 $this->problems[] = $problem;
13241
13242 $this->decisions->resetToOffset($decisionStart);
13243 $ruleIndex = -1;
13244 }
13245 }
13246
13247 protected function setupInstalledMap()
13248 {
13249 $this->installedMap = array();
13250 foreach ($this->installed->getPackages() as $package) {
13251 $this->installedMap[$package->id] = $package;
13252 }
13253 }
13254
13255
13256
13257
13258 protected function checkForRootRequireProblems($ignorePlatformReqs)
13259 {
13260 foreach ($this->jobs as $job) {
13261 switch ($job['cmd']) {
13262 case 'update':
13263 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
13264 foreach ($packages as $package) {
13265 if (isset($this->installedMap[$package->id])) {
13266 $this->updateMap[$package->id] = true;
13267 }
13268 }
13269 break;
13270
13271 case 'update-all':
13272 foreach ($this->installedMap as $package) {
13273 $this->updateMap[$package->id] = true;
13274 }
13275 break;
13276
13277 case 'install':
13278 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
13279 break;
13280 }
13281
13282 if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
13283 $problem = new Problem($this->pool);
13284 $problem->addRule(new GenericRule(array(), null, null, $job));
13285 $this->problems[] = $problem;
13286 }
13287 break;
13288 }
13289 }
13290 }
13291
13292
13293
13294
13295
13296
13297 public function solve(Request $request, $ignorePlatformReqs = false)
13298 {
13299 $this->jobs = $request->getJobs();
13300
13301 $this->setupInstalledMap();
13302 $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
13303 $this->checkForRootRequireProblems($ignorePlatformReqs);
13304 $this->decisions = new Decisions($this->pool);
13305 $this->watchGraph = new RuleWatchGraph;
13306
13307 foreach ($this->rules as $rule) {
13308 $this->watchGraph->insert(new RuleWatchNode($rule));
13309 }
13310
13311
13312 $this->makeAssertionRuleDecisions();
13313
13314 $this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
13315 $before = microtime(true);
13316 $this->runSat(true);
13317 $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
13318
13319
13320  foreach ($this->installedMap as $packageId => $void) {
13321 if ($this->decisions->undecided($packageId)) {
13322 $this->decisions->decide(-$packageId, 1, null);
13323 }
13324 }
13325
13326 if ($this->problems) {
13327 throw new SolverProblemsException($this->problems, $this->installedMap);
13328 }
13329
13330 $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
13331
13332 return $transaction->getOperations();
13333 }
13334
13335
13336
13337
13338
13339
13340
13341
13342
13343
13344 protected function propagate($level)
13345 {
13346 while ($this->decisions->validOffset($this->propagateIndex)) {
13347 $decision = $this->decisions->atOffset($this->propagateIndex);
13348
13349 $conflict = $this->watchGraph->propagateLiteral(
13350 $decision[Decisions::DECISION_LITERAL],
13351 $level,
13352 $this->decisions
13353 );
13354
13355 $this->propagateIndex++;
13356
13357 if ($conflict) {
13358 return $conflict;
13359 }
13360 }
13361
13362 return null;
13363 }
13364
13365
13366
13367
13368
13369
13370 private function revert($level)
13371 {
13372 while (!$this->decisions->isEmpty()) {
13373 $literal = $this->decisions->lastLiteral();
13374
13375 if ($this->decisions->undecided($literal)) {
13376 break;
13377 }
13378
13379 $decisionLevel = $this->decisions->decisionLevel($literal);
13380
13381 if ($decisionLevel <= $level) {
13382 break;
13383 }
13384
13385 $this->decisions->revertLast();
13386 $this->propagateIndex = count($this->decisions);
13387 }
13388
13389 while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
13390 array_pop($this->branches);
13391 }
13392 }
13393
13394
13395
13396
13397
13398
13399
13400
13401
13402
13403
13404
13405
13406
13407
13408
13409
13410
13411
13412
13413 private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
13414 {
13415 $level++;
13416
13417 $this->decisions->decide($literal, $level, $rule);
13418
13419 while (true) {
13420 $rule = $this->propagate($level);
13421
13422 if (!$rule) {
13423 break;
13424 }
13425
13426 if ($level == 1) {
13427 return $this->analyzeUnsolvable($rule, $disableRules);
13428 }
13429
13430
13431  list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
13432
13433 if ($newLevel <= 0 || $newLevel >= $level) {
13434 throw new SolverBugException(
13435 "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
13436 );
13437 } elseif (!$newRule) {
13438 throw new SolverBugException(
13439 "No rule was learned from analyzing $rule at level $level."
13440 );
13441 }
13442
13443 $level = $newLevel;
13444
13445 $this->revert($level);
13446
13447 $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
13448
13449 $this->learnedWhy[spl_object_hash($newRule)] = $why;
13450
13451 $ruleNode = new RuleWatchNode($newRule);
13452 $ruleNode->watch2OnHighest($this->decisions);
13453 $this->watchGraph->insert($ruleNode);
13454
13455 $this->decisions->decide($learnLiteral, $level, $newRule);
13456 }
13457
13458 return $level;
13459 }
13460
13461
13462
13463
13464
13465
13466
13467
13468 private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
13469 {
13470
13471  $literals = $this->policy->selectPreferredPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
13472
13473 $selectedLiteral = array_shift($literals);
13474
13475
13476  if (count($literals)) {
13477 $this->branches[] = array($literals, $level);
13478 }
13479
13480 return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
13481 }
13482
13483
13484
13485
13486
13487
13488 protected function analyze($level, Rule $rule)
13489 {
13490 $analyzedRule = $rule;
13491 $ruleLevel = 1;
13492 $num = 0;
13493 $l1num = 0;
13494 $seen = array();
13495 $learnedLiterals = array(null);
13496
13497 $decisionId = count($this->decisions);
13498
13499 $this->learnedPool[] = array();
13500
13501 while (true) {
13502 $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
13503
13504 foreach ($rule->getLiterals() as $literal) {
13505
13506  if ($this->decisions->satisfy($literal)) {
13507 continue;
13508 }
13509
13510 if (isset($seen[abs($literal)])) {
13511 continue;
13512 }
13513 $seen[abs($literal)] = true;
13514
13515 $l = $this->decisions->decisionLevel($literal);
13516
13517 if (1 === $l) {
13518 $l1num++;
13519 } elseif ($level === $l) {
13520 $num++;
13521 } else {
13522
13523  $learnedLiterals[] = $literal;
13524
13525 if ($l > $ruleLevel) {
13526 $ruleLevel = $l;
13527 }
13528 }
13529 }
13530
13531 $l1retry = true;
13532 while ($l1retry) {
13533 $l1retry = false;
13534
13535 if (!$num && !--$l1num) {
13536
13537  break 2;
13538 }
13539
13540 while (true) {
13541 if ($decisionId <= 0) {
13542 throw new SolverBugException(
13543 "Reached invalid decision id $decisionId while looking through $rule for a literal present in the analyzed rule $analyzedRule."
13544 );
13545 }
13546
13547 $decisionId--;
13548
13549 $decision = $this->decisions->atOffset($decisionId);
13550 $literal = $decision[Decisions::DECISION_LITERAL];
13551
13552 if (isset($seen[abs($literal)])) {
13553 break;
13554 }
13555 }
13556
13557 unset($seen[abs($literal)]);
13558
13559 if ($num && 0 === --$num) {
13560 $learnedLiterals[0] = -abs($literal);
13561
13562 if (!$l1num) {
13563 break 2;
13564 }
13565
13566 foreach ($learnedLiterals as $i => $learnedLiteral) {
13567 if ($i !== 0) {
13568 unset($seen[abs($learnedLiteral)]);
13569 }
13570 }
13571
13572  $l1num++;
13573 $l1retry = true;
13574 }
13575 }
13576
13577 $decision = $this->decisions->atOffset($decisionId);
13578 $rule = $decision[Decisions::DECISION_REASON];
13579 }
13580
13581 $why = count($this->learnedPool) - 1;
13582
13583 if (!$learnedLiterals[0]) {
13584 throw new SolverBugException(
13585 "Did not find a learnable literal in analyzed rule $analyzedRule."
13586 );
13587 }
13588
13589 $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why);
13590
13591 return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
13592 }
13593
13594
13595
13596
13597
13598 private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule)
13599 {
13600 $why = spl_object_hash($conflictRule);
13601
13602 if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
13603 $learnedWhy = $this->learnedWhy[$why];
13604 $problemRules = $this->learnedPool[$learnedWhy];
13605
13606 foreach ($problemRules as $problemRule) {
13607 $this->analyzeUnsolvableRule($problem, $problemRule);
13608 }
13609
13610 return;
13611 }
13612
13613 if ($conflictRule->getType() == RuleSet::TYPE_PACKAGE) {
13614
13615  return;
13616 }
13617
13618 $problem->nextSection();
13619 $problem->addRule($conflictRule);
13620 }
13621
13622
13623
13624
13625
13626
13627 private function analyzeUnsolvable(Rule $conflictRule, $disableRules)
13628 {
13629 $problem = new Problem($this->pool);
13630 $problem->addRule($conflictRule);
13631
13632 $this->analyzeUnsolvableRule($problem, $conflictRule);
13633
13634 $this->problems[] = $problem;
13635
13636 $seen = array();
13637 $literals = $conflictRule->getLiterals();
13638
13639 foreach ($literals as $literal) {
13640
13641  if ($this->decisions->satisfy($literal)) {
13642 continue;
13643 }
13644 $seen[abs($literal)] = true;
13645 }
13646
13647 foreach ($this->decisions as $decision) {
13648 $literal = $decision[Decisions::DECISION_LITERAL];
13649
13650
13651  if (!isset($seen[abs($literal)])) {
13652 continue;
13653 }
13654
13655 $why = $decision[Decisions::DECISION_REASON];
13656
13657 $problem->addRule($why);
13658 $this->analyzeUnsolvableRule($problem, $why);
13659
13660 $literals = $why->getLiterals();
13661
13662 foreach ($literals as $literal) {
13663
13664  if ($this->decisions->satisfy($literal)) {
13665 continue;
13666 }
13667 $seen[abs($literal)] = true;
13668 }
13669 }
13670
13671 if ($disableRules) {
13672 foreach ($this->problems[count($this->problems) - 1] as $reason) {
13673 $this->disableProblem($reason['rule']);
13674 }
13675
13676 $this->resetSolver();
13677
13678 return 1;
13679 }
13680
13681 return 0;
13682 }
13683
13684
13685
13686
13687 private function disableProblem(Rule $why)
13688 {
13689 $job = $why->getJob();
13690
13691 if (!$job) {
13692 $why->disable();
13693
13694 return;
13695 }
13696
13697
13698  foreach ($this->rules as $rule) {
13699
13700 if ($job === $rule->getJob()) {
13701 $rule->disable();
13702 }
13703 }
13704 }
13705
13706 private function resetSolver()
13707 {
13708 $this->decisions->reset();
13709
13710 $this->propagateIndex = 0;
13711 $this->branches = array();
13712
13713 $this->enableDisableLearnedRules();
13714 $this->makeAssertionRuleDecisions();
13715 }
13716
13717
13718
13719
13720
13721
13722
13723
13724 private function enableDisableLearnedRules()
13725 {
13726 foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
13727 $why = $this->learnedWhy[spl_object_hash($rule)];
13728 $problemRules = $this->learnedPool[$why];
13729
13730 $foundDisabled = false;
13731 foreach ($problemRules as $problemRule) {
13732 if ($problemRule->isDisabled()) {
13733 $foundDisabled = true;
13734 break;
13735 }
13736 }
13737
13738 if ($foundDisabled && $rule->isEnabled()) {
13739 $rule->disable();
13740 } elseif (!$foundDisabled && $rule->isDisabled()) {
13741 $rule->enable();
13742 }
13743 }
13744 }
13745
13746
13747
13748
13749 private function runSat($disableRules = true)
13750 {
13751 $this->propagateIndex = 0;
13752
13753
13754
13755
13756
13757
13758
13759
13760
13761
13762
13763 $decisionQueue = array();
13764 $decisionSupplementQueue = array();
13765
13766
13767
13768 $disableRules = array();
13769
13770 $level = 1;
13771 $systemLevel = $level + 1;
13772 $installedPos = 0;
13773
13774 while (true) {
13775 if (1 === $level) {
13776 $conflictRule = $this->propagate($level);
13777 if (null !== $conflictRule) {
13778 if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
13779 continue;
13780 }
13781
13782 return;
13783 }
13784 }
13785
13786
13787  if ($level < $systemLevel) {
13788 $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
13789 foreach ($iterator as $rule) {
13790 if ($rule->isEnabled()) {
13791 $decisionQueue = array();
13792 $noneSatisfied = true;
13793
13794 foreach ($rule->getLiterals() as $literal) {
13795 if ($this->decisions->satisfy($literal)) {
13796 $noneSatisfied = false;
13797 break;
13798 }
13799 if ($literal > 0 && $this->decisions->undecided($literal)) {
13800 $decisionQueue[] = $literal;
13801 }
13802 }
13803
13804 if ($noneSatisfied && count($decisionQueue)) {
13805
13806  
13807  if (count($this->installed) != count($this->updateMap)) {
13808 $prunedQueue = array();
13809 foreach ($decisionQueue as $literal) {
13810 if (isset($this->installedMap[abs($literal)])) {
13811 $prunedQueue[] = $literal;
13812 if (isset($this->updateMap[abs($literal)])) {
13813 $prunedQueue = $decisionQueue;
13814 break;
13815 }
13816 }
13817 }
13818 $decisionQueue = $prunedQueue;
13819 }
13820 }
13821
13822 if ($noneSatisfied && count($decisionQueue)) {
13823 $oLevel = $level;
13824 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
13825
13826 if (0 === $level) {
13827 return;
13828 }
13829 if ($level <= $oLevel) {
13830 break;
13831 }
13832 }
13833 }
13834 }
13835
13836 $systemLevel = $level + 1;
13837
13838
13839  $iterator->next();
13840 if ($iterator->valid()) {
13841 continue;
13842 }
13843 }
13844
13845 if ($level < $systemLevel) {
13846 $systemLevel = $level;
13847 }
13848
13849 $rulesCount = count($this->rules);
13850
13851 for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
13852 if ($i == $rulesCount) {
13853 $i = 0;
13854 }
13855
13856 $rule = $this->rules->ruleById[$i];
13857 $literals = $rule->getLiterals();
13858
13859 if ($rule->isDisabled()) {
13860 continue;
13861 }
13862
13863 $decisionQueue = array();
13864
13865
13866  
13867  
13868  
13869  
13870  
13871  foreach ($literals as $literal) {
13872 if ($literal <= 0) {
13873 if (!$this->decisions->decidedInstall(abs($literal))) {
13874 continue 2; 
13875  }
13876 } else {
13877 if ($this->decisions->decidedInstall(abs($literal))) {
13878 continue 2; 
13879  }
13880 if ($this->decisions->undecided(abs($literal))) {
13881 $decisionQueue[] = $literal;
13882 }
13883 }
13884 }
13885
13886
13887  if (count($decisionQueue) < 2) {
13888 continue;
13889 }
13890
13891 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
13892
13893 if (0 === $level) {
13894 return;
13895 }
13896
13897
13898  $rulesCount = count($this->rules);
13899 $n = -1;
13900 }
13901
13902 if ($level < $systemLevel) {
13903 continue;
13904 }
13905
13906
13907  if (count($this->branches)) {
13908 $lastLiteral = null;
13909 $lastLevel = null;
13910 $lastBranchIndex = 0;
13911 $lastBranchOffset = 0;
13912
13913 for ($i = count($this->branches) - 1; $i >= 0; $i--) {
13914 list($literals, $l) = $this->branches[$i];
13915
13916 foreach ($literals as $offset => $literal) {
13917 if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
13918 $lastLiteral = $literal;
13919 $lastBranchIndex = $i;
13920 $lastBranchOffset = $offset;
13921 $lastLevel = $l;
13922 }
13923 }
13924 }
13925
13926 if ($lastLiteral) {
13927 unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
13928
13929 $level = $lastLevel;
13930 $this->revert($level);
13931
13932 $why = $this->decisions->lastReason();
13933
13934 $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
13935
13936 if ($level == 0) {
13937 return;
13938 }
13939
13940 continue;
13941 }
13942 }
13943
13944 break;
13945 }
13946 }
13947 }
13948 <?php
13949
13950
13951
13952
13953
13954
13955
13956
13957
13958
13959
13960 namespace Composer\DependencyResolver;
13961
13962
13963
13964
13965 class SolverBugException extends \RuntimeException
13966 {
13967 public function __construct($message)
13968 {
13969 parent::__construct(
13970 $message."\nThis exception was most likely caused by a bug in Composer.\n".
13971 "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");
13972 }
13973 }
13974 <?php
13975
13976
13977
13978
13979
13980
13981
13982
13983
13984
13985
13986 namespace Composer\DependencyResolver;
13987
13988 use Composer\Util\IniHelper;
13989
13990
13991
13992
13993 class SolverProblemsException extends \RuntimeException
13994 {
13995 protected $problems;
13996 protected $installedMap;
13997
13998 public function __construct(array $problems, array $installedMap)
13999 {
14000 $this->problems = $problems;
14001 $this->installedMap = $installedMap;
14002
14003 parent::__construct($this->createMessage(), 2);
14004 }
14005
14006 protected function createMessage()
14007 {
14008 $text = "\n";
14009 $hasExtensionProblems = false;
14010 foreach ($this->problems as $i => $problem) {
14011 $text .= "  Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
14012
14013 if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
14014 $hasExtensionProblems = true;
14015 }
14016 }
14017
14018 if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
14019 $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.";
14020 }
14021
14022 if ($hasExtensionProblems) {
14023 $text .= $this->createExtensionHint();
14024 }
14025
14026 return $text;
14027 }
14028
14029 public function getProblems()
14030 {
14031 return $this->problems;
14032 }
14033
14034 private function createExtensionHint()
14035 {
14036 $paths = IniHelper::getAll();
14037
14038 if (count($paths) === 1 && empty($paths[0])) {
14039 return '';
14040 }
14041
14042 $text = "\n  To enable extensions, verify that they are enabled in your .ini files:\n    - ";
14043 $text .= implode("\n    - ", $paths);
14044 $text .= "\n  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
14045
14046 return $text;
14047 }
14048
14049 private function hasExtensionProblems(array $reasonSets)
14050 {
14051 foreach ($reasonSets as $reasonSet) {
14052 foreach ($reasonSet as $reason) {
14053 if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
14054 return true;
14055 }
14056 }
14057 }
14058
14059 return false;
14060 }
14061 }
14062 <?php
14063
14064
14065
14066
14067
14068
14069
14070
14071
14072
14073
14074 namespace Composer\DependencyResolver;
14075
14076 use Composer\Package\AliasPackage;
14077
14078
14079
14080
14081 class Transaction
14082 {
14083 protected $policy;
14084 protected $pool;
14085 protected $installedMap;
14086 protected $decisions;
14087 protected $transaction;
14088
14089 public function __construct($policy, $pool, $installedMap, $decisions)
14090 {
14091 $this->policy = $policy;
14092 $this->pool = $pool;
14093 $this->installedMap = $installedMap;
14094 $this->decisions = $decisions;
14095 $this->transaction = array();
14096 }
14097
14098 public function getOperations()
14099 {
14100 $installMeansUpdateMap = $this->findUpdates();
14101
14102 $updateMap = array();
14103 $installMap = array();
14104 $uninstallMap = array();
14105
14106 foreach ($this->decisions as $i => $decision) {
14107 $literal = $decision[Decisions::DECISION_LITERAL];
14108 $reason = $decision[Decisions::DECISION_REASON];
14109
14110 $package = $this->pool->literalToPackage($literal);
14111
14112
14113  if (($literal > 0) == (isset($this->installedMap[$package->id]))) {
14114 continue;
14115 }
14116
14117 if ($literal > 0) {
14118 if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
14119 $source = $installMeansUpdateMap[abs($literal)];
14120
14121 $updateMap[$package->id] = array(
14122 'package' => $package,
14123 'source' => $source,
14124 'reason' => $reason,
14125 );
14126
14127
14128  unset($installMeansUpdateMap[abs($literal)]);
14129 $ignoreRemove[$source->id] = true;
14130 } else {
14131 $installMap[$package->id] = array(
14132 'package' => $package,
14133 'reason' => $reason,
14134 );
14135 }
14136 }
14137 }
14138
14139 foreach ($this->decisions as $i => $decision) {
14140 $literal = $decision[Decisions::DECISION_LITERAL];
14141 $reason = $decision[Decisions::DECISION_REASON];
14142 $package = $this->pool->literalToPackage($literal);
14143
14144 if ($literal <= 0 &&
14145 isset($this->installedMap[$package->id]) &&
14146 !isset($ignoreRemove[$package->id])) {
14147 $uninstallMap[$package->id] = array(
14148 'package' => $package,
14149 'reason' => $reason,
14150 );
14151 }
14152 }
14153
14154 $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
14155
14156 return $this->transaction;
14157 }
14158
14159 protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
14160 {
14161 $queue = array_map(
14162 function ($operation) {
14163 return $operation['package'];
14164 },
14165 $this->findRootPackages($installMap, $updateMap)
14166 );
14167
14168 $visited = array();
14169
14170 while (!empty($queue)) {
14171 $package = array_pop($queue);
14172 $packageId = $package->id;
14173
14174 if (!isset($visited[$packageId])) {
14175 $queue[] = $package;
14176
14177 if ($package instanceof AliasPackage) {
14178 $queue[] = $package->getAliasOf();
14179 } else {
14180 foreach ($package->getRequires() as $link) {
14181 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
14182
14183 foreach ($possibleRequires as $require) {
14184 $queue[] = $require;
14185 }
14186 }
14187 }
14188
14189 $visited[$package->id] = true;
14190 } else {
14191 if (isset($installMap[$packageId])) {
14192 $this->install(
14193 $installMap[$packageId]['package'],
14194 $installMap[$packageId]['reason']
14195 );
14196 unset($installMap[$packageId]);
14197 }
14198 if (isset($updateMap[$packageId])) {
14199 $this->update(
14200 $updateMap[$packageId]['source'],
14201 $updateMap[$packageId]['package'],
14202 $updateMap[$packageId]['reason']
14203 );
14204 unset($updateMap[$packageId]);
14205 }
14206 }
14207 }
14208
14209 foreach ($uninstallMap as $uninstall) {
14210 $this->uninstall($uninstall['package'], $uninstall['reason']);
14211 }
14212 }
14213
14214 protected function findRootPackages($installMap, $updateMap)
14215 {
14216 $packages = $installMap + $updateMap;
14217 $roots = $packages;
14218
14219 foreach ($packages as $packageId => $operation) {
14220 $package = $operation['package'];
14221
14222 if (!isset($roots[$packageId])) {
14223 continue;
14224 }
14225
14226 foreach ($package->getRequires() as $link) {
14227 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
14228
14229 foreach ($possibleRequires as $require) {
14230 if ($require !== $package) {
14231 unset($roots[$require->id]);
14232 }
14233 }
14234 }
14235 }
14236
14237 return $roots;
14238 }
14239
14240 protected function findUpdates()
14241 {
14242 $installMeansUpdateMap = array();
14243
14244 foreach ($this->decisions as $i => $decision) {
14245 $literal = $decision[Decisions::DECISION_LITERAL];
14246 $package = $this->pool->literalToPackage($literal);
14247
14248 if ($package instanceof AliasPackage) {
14249 continue;
14250 }
14251
14252
14253  if ($literal <= 0 && isset($this->installedMap[$package->id])) {
14254 $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
14255
14256 $literals = array($package->id);
14257
14258 foreach ($updates as $update) {
14259 $literals[] = $update->id;
14260 }
14261
14262 foreach ($literals as $updateLiteral) {
14263 if ($updateLiteral !== $literal) {
14264 $installMeansUpdateMap[abs($updateLiteral)] = $package;
14265 }
14266 }
14267 }
14268 }
14269
14270 return $installMeansUpdateMap;
14271 }
14272
14273 protected function install($package, $reason)
14274 {
14275 if ($package instanceof AliasPackage) {
14276 return $this->markAliasInstalled($package, $reason);
14277 }
14278
14279 $this->transaction[] = new Operation\InstallOperation($package, $reason);
14280 }
14281
14282 protected function update($from, $to, $reason)
14283 {
14284 $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
14285 }
14286
14287 protected function uninstall($package, $reason)
14288 {
14289 if ($package instanceof AliasPackage) {
14290 return $this->markAliasUninstalled($package, $reason);
14291 }
14292
14293 $this->transaction[] = new Operation\UninstallOperation($package, $reason);
14294 }
14295
14296 protected function markAliasInstalled($package, $reason)
14297 {
14298 $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
14299 }
14300
14301 protected function markAliasUninstalled($package, $reason)
14302 {
14303 $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
14304 }
14305 }
14306 <?php
14307
14308
14309
14310
14311
14312
14313
14314
14315
14316
14317
14318 namespace Composer\Downloader;
14319
14320 use Composer\Package\PackageInterface;
14321 use Symfony\Component\Finder\Finder;
14322 use Composer\IO\IOInterface;
14323
14324
14325
14326
14327
14328
14329
14330
14331 abstract class ArchiveDownloader extends FileDownloader
14332 {
14333
14334
14335
14336 public function download(PackageInterface $package, $path, $output = true)
14337 {
14338 $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
14339 $retries = 3;
14340 while ($retries--) {
14341 $fileName = parent::download($package, $path, $output);
14342
14343 $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
14344
14345 try {
14346 $this->filesystem->ensureDirectoryExists($temporaryDir);
14347 try {
14348 $this->extract($fileName, $temporaryDir);
14349 } catch (\Exception $e) {
14350
14351  parent::clearLastCacheWrite($package);
14352 throw $e;
14353 }
14354
14355 $this->filesystem->unlink($fileName);
14356
14357 $contentDir = $this->getFolderContent($temporaryDir);
14358
14359
14360  if (1 === count($contentDir) && is_dir(reset($contentDir))) {
14361 $contentDir = $this->getFolderContent((string) reset($contentDir));
14362 }
14363
14364
14365  foreach ($contentDir as $file) {
14366 $file = (string) $file;
14367 $this->filesystem->rename($file, $path . '/' . basename($file));
14368 }
14369
14370 $this->filesystem->removeDirectory($temporaryDir);
14371 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
14372 $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
14373 }
14374 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
14375 $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
14376 }
14377 } catch (\Exception $e) {
14378
14379  $this->filesystem->removeDirectory($path);
14380 $this->filesystem->removeDirectory($temporaryDir);
14381
14382
14383  if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
14384 $this->io->writeError('');
14385 if ($this->io->isDebug()) {
14386 $this->io->writeError('    Invalid zip file ('.$e->getMessage().'), retrying...');
14387 } else {
14388 $this->io->writeError('    Invalid zip file, retrying...');
14389 }
14390 usleep(500000);
14391 continue;
14392 }
14393
14394 throw $e;
14395 }
14396
14397 break;
14398 }
14399 }
14400
14401
14402
14403
14404 protected function getFileName(PackageInterface $package, $path)
14405 {
14406 return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
14407 }
14408
14409
14410
14411
14412
14413
14414
14415
14416
14417 abstract protected function extract($file, $path);
14418
14419
14420
14421
14422
14423
14424
14425 private function getFolderContent($dir)
14426 {
14427 $finder = Finder::create()
14428 ->ignoreVCS(false)
14429 ->ignoreDotFiles(false)
14430 ->notName('.DS_Store')
14431 ->depth(0)
14432 ->in($dir);
14433
14434 return iterator_to_array($finder);
14435 }
14436 }
14437 <?php
14438
14439
14440
14441
14442
14443
14444
14445
14446
14447
14448
14449 namespace Composer\Downloader;
14450
14451 use Composer\Package\PackageInterface;
14452
14453
14454
14455
14456
14457
14458 interface ChangeReportInterface
14459 {
14460
14461
14462
14463
14464
14465
14466
14467 public function getLocalChanges(PackageInterface $package, $path);
14468 }
14469 <?php
14470
14471
14472
14473
14474
14475
14476
14477
14478
14479
14480
14481 namespace Composer\Downloader;
14482
14483 use Composer\Package\PackageInterface;
14484 use Composer\IO\IOInterface;
14485 use Composer\Util\Filesystem;
14486
14487
14488
14489
14490
14491
14492 class DownloadManager
14493 {
14494 private $io;
14495 private $preferDist = false;
14496 private $preferSource = false;
14497 private $packagePreferences = array();
14498 private $filesystem;
14499 private $downloaders = array();
14500
14501
14502
14503
14504
14505
14506
14507
14508 public function __construct(IOInterface $io, $preferSource = false, Filesystem $filesystem = null)
14509 {
14510 $this->io = $io;
14511 $this->preferSource = $preferSource;
14512 $this->filesystem = $filesystem ?: new Filesystem();
14513 }
14514
14515
14516
14517
14518
14519
14520
14521 public function setPreferSource($preferSource)
14522 {
14523 $this->preferSource = $preferSource;
14524
14525 return $this;
14526 }
14527
14528
14529
14530
14531
14532
14533
14534 public function setPreferDist($preferDist)
14535 {
14536 $this->preferDist = $preferDist;
14537
14538 return $this;
14539 }
14540
14541
14542
14543
14544
14545
14546
14547 public function setPreferences(array $preferences)
14548 {
14549 $this->packagePreferences = $preferences;
14550
14551 return $this;
14552 }
14553
14554
14555
14556
14557
14558
14559
14560
14561 public function setOutputProgress($outputProgress)
14562 {
14563 foreach ($this->downloaders as $downloader) {
14564 $downloader->setOutputProgress($outputProgress);
14565 }
14566
14567 return $this;
14568 }
14569
14570
14571
14572
14573
14574
14575
14576
14577 public function setDownloader($type, DownloaderInterface $downloader)
14578 {
14579 $type = strtolower($type);
14580 $this->downloaders[$type] = $downloader;
14581
14582 return $this;
14583 }
14584
14585
14586
14587
14588
14589
14590
14591
14592 public function getDownloader($type)
14593 {
14594 $type = strtolower($type);
14595 if (!isset($this->downloaders[$type])) {
14596 throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
14597 }
14598
14599 return $this->downloaders[$type];
14600 }
14601
14602
14603
14604
14605
14606
14607
14608
14609
14610
14611 public function getDownloaderForInstalledPackage(PackageInterface $package)
14612 {
14613 $installationSource = $package->getInstallationSource();
14614
14615 if ('metapackage' === $package->getType()) {
14616 return;
14617 }
14618
14619 if ('dist' === $installationSource) {
14620 $downloader = $this->getDownloader($package->getDistType());
14621 } elseif ('source' === $installationSource) {
14622 $downloader = $this->getDownloader($package->getSourceType());
14623 } else {
14624 throw new \InvalidArgumentException(
14625 'Package '.$package.' seems not been installed properly'
14626 );
14627 }
14628
14629 if ($installationSource !== $downloader->getInstallationSource()) {
14630 throw new \LogicException(sprintf(
14631 'Downloader "%s" is a %s type downloader and can not be used to download %s for package %s',
14632 get_class($downloader), $downloader->getInstallationSource(), $installationSource, $package
14633 ));
14634 }
14635
14636 return $downloader;
14637 }
14638
14639
14640
14641
14642
14643
14644
14645
14646
14647
14648
14649 public function download(PackageInterface $package, $targetDir, $preferSource = null)
14650 {
14651 $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
14652 $sourceType = $package->getSourceType();
14653 $distType = $package->getDistType();
14654
14655 $sources = array();
14656 if ($sourceType) {
14657 $sources[] = 'source';
14658 }
14659 if ($distType) {
14660 $sources[] = 'dist';
14661 }
14662
14663 if (empty($sources)) {
14664 throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
14665 }
14666
14667 if (!$preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
14668 $sources = array_reverse($sources);
14669 }
14670
14671 $this->filesystem->ensureDirectoryExists($targetDir);
14672
14673 foreach ($sources as $i => $source) {
14674 if (isset($e)) {
14675 $this->io->writeError('    <warning>Now trying to download from ' . $source . '</warning>');
14676 }
14677 $package->setInstallationSource($source);
14678 try {
14679 $downloader = $this->getDownloaderForInstalledPackage($package);
14680 if ($downloader) {
14681 $downloader->download($package, $targetDir);
14682 }
14683 break;
14684 } catch (\RuntimeException $e) {
14685 if ($i === count($sources) - 1) {
14686 throw $e;
14687 }
14688
14689 $this->io->writeError(
14690 '    <warning>Failed to download '.
14691 $package->getPrettyName().
14692 ' from ' . $source . ': '.
14693 $e->getMessage().'</warning>'
14694 );
14695 }
14696 }
14697 }
14698
14699
14700
14701
14702
14703
14704
14705
14706
14707
14708 public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
14709 {
14710 $downloader = $this->getDownloaderForInstalledPackage($initial);
14711 if (!$downloader) {
14712 return;
14713 }
14714
14715 $installationSource = $initial->getInstallationSource();
14716
14717 if ('dist' === $installationSource) {
14718 $initialType = $initial->getDistType();
14719 $targetType = $target->getDistType();
14720 } else {
14721 $initialType = $initial->getSourceType();
14722 $targetType = $target->getSourceType();
14723 }
14724
14725
14726  if ($target->isDev() && 'dist' === $installationSource) {
14727 $downloader->remove($initial, $targetDir);
14728 $this->download($target, $targetDir);
14729
14730 return;
14731 }
14732
14733 if ($initialType === $targetType) {
14734 $target->setInstallationSource($installationSource);
14735 try {
14736 $downloader->update($initial, $target, $targetDir);
14737
14738 return;
14739 } catch (\RuntimeException $e) {
14740 if (!$this->io->isInteractive()) {
14741 throw $e;
14742 }
14743 $this->io->writeError('<error>    Update failed ('.$e->getMessage().')</error>');
14744 if (!$this->io->askConfirmation('    Would you like to try reinstalling the package instead [<comment>yes</comment>]? ', true)) {
14745 throw $e;
14746 }
14747 }
14748 }
14749
14750 $downloader->remove($initial, $targetDir);
14751 $this->download($target, $targetDir, 'source' === $installationSource);
14752 }
14753
14754
14755
14756
14757
14758
14759
14760 public function remove(PackageInterface $package, $targetDir)
14761 {
14762 $downloader = $this->getDownloaderForInstalledPackage($package);
14763 if ($downloader) {
14764 $downloader->remove($package, $targetDir);
14765 }
14766 }
14767
14768
14769
14770
14771
14772
14773
14774
14775 protected function resolvePackageInstallPreference(PackageInterface $package)
14776 {
14777 foreach ($this->packagePreferences as $pattern => $preference) {
14778 $pattern = '{^'.str_replace('\\*', '.*', preg_quote($pattern)).'$}i';
14779 if (preg_match($pattern, $package->getName())) {
14780 if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) {
14781 return 'dist';
14782 }
14783
14784 return 'source';
14785 }
14786 }
14787
14788 return $package->isDev() ? 'source' : 'dist';
14789 }
14790 }
14791 <?php
14792
14793
14794
14795
14796
14797
14798
14799
14800
14801
14802
14803 namespace Composer\Downloader;
14804
14805 use Composer\Package\PackageInterface;
14806
14807
14808
14809
14810
14811
14812
14813 interface DownloaderInterface
14814 {
14815
14816
14817
14818
14819
14820 public function getInstallationSource();
14821
14822
14823
14824
14825
14826
14827
14828 public function download(PackageInterface $package, $path);
14829
14830
14831
14832
14833
14834
14835
14836
14837 public function update(PackageInterface $initial, PackageInterface $target, $path);
14838
14839
14840
14841
14842
14843
14844
14845 public function remove(PackageInterface $package, $path);
14846
14847
14848
14849
14850
14851
14852
14853 public function setOutputProgress($outputProgress);
14854 }
14855 <?php
14856
14857
14858
14859
14860
14861
14862
14863
14864
14865
14866
14867 namespace Composer\Downloader;
14868
14869 use Composer\Package\PackageInterface;
14870
14871
14872
14873
14874
14875
14876 interface DvcsDownloaderInterface
14877 {
14878
14879
14880
14881
14882
14883
14884
14885 public function getUnpushedChanges(PackageInterface $package, $path);
14886 }
14887 <?php
14888
14889
14890
14891
14892
14893
14894
14895
14896
14897
14898
14899 namespace Composer\Downloader;
14900
14901 use Composer\Config;
14902 use Composer\Cache;
14903 use Composer\Factory;
14904 use Composer\IO\IOInterface;
14905 use Composer\Package\PackageInterface;
14906 use Composer\Plugin\PluginEvents;
14907 use Composer\Plugin\PreFileDownloadEvent;
14908 use Composer\EventDispatcher\EventDispatcher;
14909 use Composer\Util\Filesystem;
14910 use Composer\Util\RemoteFilesystem;
14911 use Composer\Util\Url as UrlUtil;
14912
14913
14914
14915
14916
14917
14918
14919
14920
14921 class FileDownloader implements DownloaderInterface
14922 {
14923 protected $io;
14924 protected $config;
14925 protected $rfs;
14926 protected $filesystem;
14927 protected $cache;
14928 protected $outputProgress = true;
14929 private $lastCacheWrites = array();
14930 private $eventDispatcher;
14931
14932
14933
14934
14935
14936
14937
14938
14939
14940
14941
14942 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
14943 {
14944 $this->io = $io;
14945 $this->config = $config;
14946 $this->eventDispatcher = $eventDispatcher;
14947 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
14948 $this->filesystem = $filesystem ?: new Filesystem();
14949 $this->cache = $cache;
14950
14951 if ($this->cache && $this->cache->gcIsNecessary()) {
14952 $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
14953 }
14954 }
14955
14956
14957
14958
14959 public function getInstallationSource()
14960 {
14961 return 'dist';
14962 }
14963
14964
14965
14966
14967 public function download(PackageInterface $package, $path, $output = true)
14968 {
14969 if (!$package->getDistUrl()) {
14970 throw new \InvalidArgumentException('The given package is missing url information');
14971 }
14972
14973 if ($output) {
14974 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
14975 }
14976
14977 $urls = $package->getDistUrls();
14978 while ($url = array_shift($urls)) {
14979 try {
14980 $fileName = $this->doDownload($package, $path, $url);
14981 break;
14982 } catch (\Exception $e) {
14983 if ($this->io->isDebug()) {
14984 $this->io->writeError('');
14985 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
14986 } elseif (count($urls)) {
14987 $this->io->writeError('');
14988 $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
14989 }
14990
14991 if (!count($urls)) {
14992 throw $e;
14993 }
14994 }
14995 }
14996
14997 if ($output) {
14998 $this->io->writeError('');
14999 }
15000
15001 return $fileName;
15002 }
15003
15004 protected function doDownload(PackageInterface $package, $path, $url)
15005 {
15006 $this->filesystem->emptyDirectory($path);
15007
15008 $fileName = $this->getFileName($package, $path);
15009
15010 $processedUrl = $this->processUrl($package, $url);
15011 $hostname = parse_url($processedUrl, PHP_URL_HOST);
15012
15013 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
15014 if ($this->eventDispatcher) {
15015 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
15016 }
15017 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
15018
15019 try {
15020 $checksum = $package->getDistSha1Checksum();
15021 $cacheKey = $this->getCacheKey($package, $processedUrl);
15022
15023
15024  if (!$this->cache || ($checksum && $checksum !== $this->cache->sha1($cacheKey)) || !$this->cache->copyTo($cacheKey, $fileName)) {
15025 if (!$this->outputProgress) {
15026 $this->io->writeError('Downloading', false);
15027 }
15028
15029
15030  $retries = 3;
15031 while ($retries--) {
15032 try {
15033 $rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
15034 break;
15035 } catch (TransportException $e) {
15036
15037  if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
15038 throw $e;
15039 }
15040 $this->io->writeError('');
15041 $this->io->writeError('    Download failed, retrying...', true, IOInterface::VERBOSE);
15042 usleep(500000);
15043 }
15044 }
15045
15046 if (!$this->outputProgress) {
15047 $this->io->writeError(' (<comment>100%</comment>)', false);
15048 }
15049
15050 if ($this->cache) {
15051 $this->lastCacheWrites[$package->getName()] = $cacheKey;
15052 $this->cache->copyFrom($cacheKey, $fileName);
15053 }
15054 } else {
15055 $this->io->writeError('Loading from cache', false);
15056 }
15057
15058 if (!file_exists($fileName)) {
15059 throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
15060 .' directory is writable and you have internet connectivity');
15061 }
15062
15063 if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
15064 throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
15065 }
15066 } catch (\Exception $e) {
15067
15068  $this->filesystem->removeDirectory($path);
15069 $this->clearLastCacheWrite($package);
15070 throw $e;
15071 }
15072
15073 return $fileName;
15074 }
15075
15076
15077
15078
15079 public function setOutputProgress($outputProgress)
15080 {
15081 $this->outputProgress = $outputProgress;
15082
15083 return $this;
15084 }
15085
15086 protected function clearLastCacheWrite(PackageInterface $package)
15087 {
15088 if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
15089 $this->cache->remove($this->lastCacheWrites[$package->getName()]);
15090 unset($this->lastCacheWrites[$package->getName()]);
15091 }
15092 }
15093
15094
15095
15096
15097 public function update(PackageInterface $initial, PackageInterface $target, $path)
15098 {
15099 $name = $target->getName();
15100 $from = $initial->getPrettyVersion();
15101 $to = $target->getPrettyVersion();
15102
15103 $this->io->writeError("  - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
15104
15105 $this->remove($initial, $path, false);
15106 $this->download($target, $path, false);
15107
15108 $this->io->writeError('');
15109 }
15110
15111
15112
15113
15114 public function remove(PackageInterface $package, $path, $output = true)
15115 {
15116 if ($output) {
15117 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
15118 }
15119 if (!$this->filesystem->removeDirectory($path)) {
15120 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
15121 }
15122 }
15123
15124
15125
15126
15127
15128
15129
15130
15131 protected function getFileName(PackageInterface $package, $path)
15132 {
15133 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
15134 }
15135
15136
15137
15138
15139
15140
15141
15142
15143
15144 protected function processUrl(PackageInterface $package, $url)
15145 {
15146 if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
15147 throw new \RuntimeException('You must enable the openssl extension to download files via https');
15148 }
15149
15150 if ($package->getDistReference()) {
15151 $url = UrlUtil::updateDistReference($this->config, $url, $package->getDistReference());
15152 }
15153
15154 return $url;
15155 }
15156
15157 private function getCacheKey(PackageInterface $package, $processedUrl)
15158 {
15159
15160  
15161  
15162  
15163  $cacheKey = sha1($processedUrl);
15164
15165 return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
15166 }
15167 }
15168 <?php
15169
15170
15171
15172
15173
15174
15175
15176
15177
15178
15179
15180 namespace Composer\Downloader;
15181
15182
15183
15184
15185
15186
15187 class FilesystemException extends \Exception
15188 {
15189 public function __construct($message = '', $code = 0, \Exception $previous = null)
15190 {
15191 parent::__construct("Filesystem exception: \n".$message, $code, $previous);
15192 }
15193 }
15194 <?php
15195
15196
15197
15198
15199
15200
15201
15202
15203
15204
15205
15206 namespace Composer\Downloader;
15207
15208 use Composer\Package\PackageInterface;
15209 use Composer\Util\ProcessExecutor;
15210
15211
15212
15213
15214 class FossilDownloader extends VcsDownloader
15215 {
15216
15217
15218
15219 public function doDownload(PackageInterface $package, $path, $url)
15220 {
15221
15222  $this->config->prohibitUrlByConfig($url, $this->io);
15223
15224 $url = ProcessExecutor::escape($url);
15225 $ref = ProcessExecutor::escape($package->getSourceReference());
15226 $repoFile = $path . '.fossil';
15227 $this->io->writeError("Cloning ".$package->getSourceReference());
15228 $command = sprintf('fossil clone %s %s', $url, ProcessExecutor::escape($repoFile));
15229 if (0 !== $this->process->execute($command, $ignoredOutput)) {
15230 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15231 }
15232 $command = sprintf('fossil open %s', ProcessExecutor::escape($repoFile));
15233 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15234 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15235 }
15236 $command = sprintf('fossil update %s', $ref);
15237 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15238 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15239 }
15240 }
15241
15242
15243
15244
15245 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15246 {
15247
15248  $this->config->prohibitUrlByConfig($url, $this->io);
15249
15250 $url = ProcessExecutor::escape($url);
15251 $ref = ProcessExecutor::escape($target->getSourceReference());
15252 $this->io->writeError(" Updating to ".$target->getSourceReference());
15253
15254 if (!$this->hasMetadataRepository($path)) {
15255 throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15256 }
15257
15258 $command = sprintf('fossil pull && fossil up %s', $ref);
15259 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15260 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15261 }
15262 }
15263
15264
15265
15266
15267 public function getLocalChanges(PackageInterface $package, $path)
15268 {
15269 if (!$this->hasMetadataRepository($path)) {
15270 return null;
15271 }
15272
15273 $this->process->execute('fossil changes', $output, realpath($path));
15274
15275 return trim($output) ?: null;
15276 }
15277
15278
15279
15280
15281 protected function getCommitLogs($fromReference, $toReference, $path)
15282 {
15283 $command = sprintf('fossil timeline -t ci -W 0 -n 0 before %s', $toReference);
15284
15285 if (0 !== $this->process->execute($command, $output, realpath($path))) {
15286 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15287 }
15288
15289 $log = '';
15290 $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
15291
15292 foreach ($this->process->splitLines($output) as $line) {
15293 if (preg_match($match, $line)) {
15294 break;
15295 }
15296 $log .= $line;
15297 }
15298
15299 return $log;
15300 }
15301
15302
15303
15304
15305 protected function hasMetadataRepository($path)
15306 {
15307 return is_file($path . '/.fslckout') || is_file($path . '/_FOSSIL_');
15308 }
15309 }
15310 <?php
15311
15312
15313
15314
15315
15316
15317
15318
15319
15320
15321
15322 namespace Composer\Downloader;
15323
15324 use Composer\Config;
15325 use Composer\IO\IOInterface;
15326 use Composer\Package\PackageInterface;
15327 use Composer\Util\Filesystem;
15328 use Composer\Util\Git as GitUtil;
15329 use Composer\Util\Platform;
15330 use Composer\Util\ProcessExecutor;
15331
15332
15333
15334
15335 class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
15336 {
15337 private $hasStashedChanges = false;
15338 private $hasDiscardedChanges = false;
15339 private $gitUtil;
15340
15341 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
15342 {
15343 parent::__construct($io, $config, $process, $fs);
15344 $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
15345 }
15346
15347
15348
15349
15350 public function doDownload(PackageInterface $package, $path, $url)
15351 {
15352 GitUtil::cleanEnv();
15353 $path = $this->normalizePath($path);
15354 $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
15355 $ref = $package->getSourceReference();
15356 $flag = Platform::isWindows() ? '/D ' : '';
15357
15358
15359  $gitVersion = $this->gitUtil->getVersion();
15360 $msg = "Cloning ".$this->getShortHash($ref);
15361
15362 $command = 'git clone --no-checkout %url% %path% && cd '.$flag.'%path% && git remote add composer %url% && git fetch composer';
15363 if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=')) {
15364 $this->io->writeError('', true, IOInterface::DEBUG);
15365 $this->io->writeError(sprintf('    Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
15366 try {
15367 $this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref);
15368 if (is_dir($cachePath)) {
15369 $command =
15370 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% '
15371 . '&& cd '.$flag.'%path% '
15372 . '&& git remote set-url origin %url% && git remote add composer %url%';
15373 $msg = "Cloning ".$this->getShortHash($ref).' from cache';
15374 }
15375 } catch (\RuntimeException $e) {
15376 }
15377 }
15378 $this->io->writeError($msg);
15379
15380 $commandCallable = function ($url) use ($path, $command, $cachePath) {
15381 return str_replace(
15382 array('%url%', '%path%', '%cachePath%'),
15383 array(
15384 ProcessExecutor::escape($url),
15385 ProcessExecutor::escape($path),
15386 ProcessExecutor::escape($cachePath),
15387 ),
15388 $command
15389 );
15390 };
15391
15392 $this->gitUtil->runCommand($commandCallable, $url, $path, true);
15393 if ($url !== $package->getSourceUrl()) {
15394 $this->updateOriginUrl($path, $package->getSourceUrl());
15395 } else {
15396 $this->setPushUrl($path, $url);
15397 }
15398
15399 if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
15400 if ($package->getDistReference() === $package->getSourceReference()) {
15401 $package->setDistReference($newRef);
15402 }
15403 $package->setSourceReference($newRef);
15404 }
15405 }
15406
15407
15408
15409
15410 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15411 {
15412 GitUtil::cleanEnv();
15413 if (!$this->hasMetadataRepository($path)) {
15414 throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15415 }
15416
15417 $updateOriginUrl = false;
15418 if (
15419 0 === $this->process->execute('git remote -v', $output, $path)
15420 && preg_match('{^origin\s+(?P<url>\S+)}m', $output, $originMatch)
15421 && preg_match('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)
15422 ) {
15423 if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
15424 $updateOriginUrl = true;
15425 }
15426 }
15427
15428 $ref = $target->getSourceReference();
15429 $this->io->writeError(" Checking out ".$this->getShortHash($ref));
15430 $command = 'git remote set-url composer %s && git rev-parse --quiet --verify %s || (git fetch composer && git fetch --tags composer)';
15431
15432 $commandCallable = function ($url) use ($command, $ref) {
15433 return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($ref.'^{commit}'));
15434 };
15435
15436 $this->gitUtil->runCommand($commandCallable, $url, $path);
15437 if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
15438 if ($target->getDistReference() === $target->getSourceReference()) {
15439 $target->setDistReference($newRef);
15440 }
15441 $target->setSourceReference($newRef);
15442 }
15443
15444 if ($updateOriginUrl) {
15445 $this->updateOriginUrl($path, $target->getSourceUrl());
15446 }
15447 }
15448
15449
15450
15451
15452 public function getLocalChanges(PackageInterface $package, $path)
15453 {
15454 GitUtil::cleanEnv();
15455 if (!$this->hasMetadataRepository($path)) {
15456 return;
15457 }
15458
15459 $command = 'git status --porcelain --untracked-files=no';
15460 if (0 !== $this->process->execute($command, $output, $path)) {
15461 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15462 }
15463
15464 return trim($output) ?: null;
15465 }
15466
15467 public function getUnpushedChanges(PackageInterface $package, $path)
15468 {
15469 GitUtil::cleanEnv();
15470 $path = $this->normalizePath($path);
15471 if (!$this->hasMetadataRepository($path)) {
15472 return;
15473 }
15474
15475 $command = 'git show-ref --head -d';
15476 if (0 !== $this->process->execute($command, $output, $path)) {
15477 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15478 }
15479
15480 $refs = trim($output);
15481 if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
15482
15483  return;
15484 }
15485
15486 $headRef = $match[1];
15487 if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
15488
15489  return;
15490 }
15491
15492
15493  $branch = $matches[1][0];
15494 $unpushedChanges = null;
15495
15496
15497  for ($i = 0; $i <= 1; $i++) {
15498
15499  foreach ($matches[1] as $candidate) {
15500 if (preg_match('{^[a-f0-9]+ refs/remotes/((?:composer|origin)/'.preg_quote($candidate).')$}mi', $refs, $match)) {
15501 $branch = $candidate;
15502 $remoteBranch = $match[1];
15503 break;
15504 }
15505 }
15506
15507
15508  
15509  
15510  if (!isset($remoteBranch)) {
15511 $unpushedChanges = 'Branch ' . $branch . ' could not be found on the origin remote and appears to be unpushed';
15512 } else {
15513 $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
15514 if (0 !== $this->process->execute($command, $output, $path)) {
15515 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15516 }
15517
15518 $unpushedChanges = trim($output) ?: null;
15519 }
15520
15521
15522  
15523  if ($unpushedChanges && $i === 0) {
15524 $this->process->execute('git fetch composer && git fetch origin', $output, $path);
15525 }
15526
15527
15528  if (!$unpushedChanges) {
15529 break;
15530 }
15531 }
15532
15533 return $unpushedChanges;
15534 }
15535
15536
15537
15538
15539 protected function cleanChanges(PackageInterface $package, $path, $update)
15540 {
15541 GitUtil::cleanEnv();
15542 $path = $this->normalizePath($path);
15543
15544 $unpushed = $this->getUnpushedChanges($package, $path);
15545 if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== true)) {
15546 throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: '."\n".$unpushed);
15547 }
15548
15549 if (!$changes = $this->getLocalChanges($package, $path)) {
15550 return;
15551 }
15552
15553 if (!$this->io->isInteractive()) {
15554 $discardChanges = $this->config->get('discard-changes');
15555 if (true === $discardChanges) {
15556 return $this->discardChanges($path);
15557 }
15558 if ('stash' === $discardChanges) {
15559 if (!$update) {
15560 return parent::cleanChanges($package, $path, $update);
15561 }
15562
15563 return $this->stashChanges($path);
15564 }
15565
15566 return parent::cleanChanges($package, $path, $update);
15567 }
15568
15569 $changes = array_map(function ($elem) {
15570 return '    '.$elem;
15571 }, preg_split('{\s*\r?\n\s*}', $changes));
15572 $this->io->writeError('    <error>The package has modified files:</error>');
15573 $this->io->writeError(array_slice($changes, 0, 10));
15574 if (count($changes) > 10) {
15575 $this->io->writeError('    <info>' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list</info>');
15576 }
15577
15578 while (true) {
15579 switch ($this->io->ask('    <info>Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]?</info> ', '?')) {
15580 case 'y':
15581 $this->discardChanges($path);
15582 break 2;
15583
15584 case 's':
15585 if (!$update) {
15586 goto help;
15587 }
15588
15589 $this->stashChanges($path);
15590 break 2;
15591
15592 case 'n':
15593 throw new \RuntimeException('Update aborted');
15594
15595 case 'v':
15596 $this->io->writeError($changes);
15597 break;
15598
15599 case 'd':
15600 $this->viewDiff($path);
15601 break;
15602
15603 case '?':
15604 default:
15605 help:
15606 $this->io->writeError(array(
15607 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
15608 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
15609 '    v - view modified files',
15610 '    d - view local modifications (diff)',
15611 ));
15612 if ($update) {
15613 $this->io->writeError('    s - stash changes and try to reapply them after the update');
15614 }
15615 $this->io->writeError('    ? - print help');
15616 break;
15617 }
15618 }
15619 }
15620
15621
15622
15623
15624 protected function reapplyChanges($path)
15625 {
15626 $path = $this->normalizePath($path);
15627 if ($this->hasStashedChanges) {
15628 $this->hasStashedChanges = false;
15629 $this->io->writeError('    <info>Re-applying stashed changes</info>');
15630 if (0 !== $this->process->execute('git stash pop', $output, $path)) {
15631 throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
15632 }
15633 }
15634
15635 $this->hasDiscardedChanges = false;
15636 }
15637
15638
15639
15640
15641
15642
15643
15644
15645
15646
15647
15648 protected function updateToCommit($path, $reference, $branch, $date)
15649 {
15650 $force = $this->hasDiscardedChanges || $this->hasStashedChanges ? '-f ' : '';
15651
15652
15653  
15654  
15655  
15656  
15657  $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
15658 $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);
15659
15660 $branches = null;
15661 if (0 === $this->process->execute('git branch -r', $output, $path)) {
15662 $branches = $output;
15663 }
15664
15665
15666  $gitRef = $reference;
15667 if (!preg_match('{^[a-f0-9]{40}$}', $reference)
15668 && $branches
15669 && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
15670 ) {
15671 $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
15672 if (0 === $this->process->execute($command, $output, $path)) {
15673 return;
15674 }
15675 }
15676
15677
15678  if (preg_match('{^[a-f0-9]{40}$}', $reference)) {
15679
15680  if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) {
15681 $branch = 'v' . $branch;
15682 }
15683
15684 $command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
15685 $fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
15686 if (0 === $this->process->execute($command, $output, $path)
15687 || 0 === $this->process->execute($fallbackCommand, $output, $path)
15688 ) {
15689 $command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
15690 if (0 === $this->process->execute($command, $output, $path)) {
15691 return;
15692 }
15693 }
15694 }
15695
15696 $command = sprintf($template, ProcessExecutor::escape($gitRef));
15697 if (0 === $this->process->execute($command, $output, $path)) {
15698 return;
15699 }
15700
15701
15702  if (false !== strpos($this->process->getErrorOutput(), $reference)) {
15703 $this->io->writeError('    <warning>'.$reference.' is gone (history was rewritten?)</warning>');
15704 }
15705
15706 throw new \RuntimeException(GitUtil::sanitizeUrl('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
15707 }
15708
15709 protected function updateOriginUrl($path, $url)
15710 {
15711 $this->process->execute(sprintf('git remote set-url origin %s', ProcessExecutor::escape($url)), $output, $path);
15712 $this->setPushUrl($path, $url);
15713 }
15714
15715 protected function setPushUrl($path, $url)
15716 {
15717
15718  if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
15719 $protocols = $this->config->get('github-protocols');
15720 $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git';
15721 if (!in_array('ssh', $protocols, true)) {
15722 $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
15723 }
15724 $cmd = sprintf('git remote set-url --push origin %s', ProcessExecutor::escape($pushUrl));
15725 $this->process->execute($cmd, $ignoredOutput, $path);
15726 }
15727 }
15728
15729
15730
15731
15732 protected function getCommitLogs($fromReference, $toReference, $path)
15733 {
15734 $path = $this->normalizePath($path);
15735 $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', $fromReference, $toReference);
15736
15737 if (0 !== $this->process->execute($command, $output, $path)) {
15738 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15739 }
15740
15741 return $output;
15742 }
15743
15744
15745
15746
15747
15748 protected function discardChanges($path)
15749 {
15750 $path = $this->normalizePath($path);
15751 if (0 !== $this->process->execute('git reset --hard', $output, $path)) {
15752 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
15753 }
15754
15755 $this->hasDiscardedChanges = true;
15756 }
15757
15758
15759
15760
15761
15762 protected function stashChanges($path)
15763 {
15764 $path = $this->normalizePath($path);
15765 if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
15766 throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
15767 }
15768
15769 $this->hasStashedChanges = true;
15770 }
15771
15772
15773
15774
15775
15776 protected function viewDiff($path)
15777 {
15778 $path = $this->normalizePath($path);
15779 if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
15780 throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
15781 }
15782
15783 $this->io->writeError($output);
15784 }
15785
15786 protected function normalizePath($path)
15787 {
15788 if (Platform::isWindows() && strlen($path) > 0) {
15789 $basePath = $path;
15790 $removed = array();
15791
15792 while (!is_dir($basePath) && $basePath !== '\\') {
15793 array_unshift($removed, basename($basePath));
15794 $basePath = dirname($basePath);
15795 }
15796
15797 if ($basePath === '\\') {
15798 return $path;
15799 }
15800
15801 $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
15802 }
15803
15804 return $path;
15805 }
15806
15807
15808
15809
15810 protected function hasMetadataRepository($path)
15811 {
15812 $path = $this->normalizePath($path);
15813
15814 return is_dir($path.'/.git');
15815 }
15816
15817 protected function getShortHash($reference)
15818 {
15819 if (!$this->io->isVerbose() && preg_match('{^[0-9a-f]{40}$}', $reference)) {
15820 return substr($reference, 0, 10);
15821 }
15822
15823 return $reference;
15824 }
15825 }
15826 <?php
15827
15828
15829
15830
15831
15832
15833
15834
15835
15836
15837
15838 namespace Composer\Downloader;
15839
15840 use Composer\Config;
15841 use Composer\Cache;
15842 use Composer\EventDispatcher\EventDispatcher;
15843 use Composer\Package\PackageInterface;
15844 use Composer\Util\Platform;
15845 use Composer\Util\ProcessExecutor;
15846 use Composer\Util\RemoteFilesystem;
15847 use Composer\IO\IOInterface;
15848
15849
15850
15851
15852
15853
15854 class GzipDownloader extends ArchiveDownloader
15855 {
15856 protected $process;
15857
15858 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
15859 {
15860 $this->process = $process ?: new ProcessExecutor($io);
15861 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
15862 }
15863
15864 protected function extract($file, $path)
15865 {
15866 $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
15867
15868
15869  if (!Platform::isWindows()) {
15870 $command = 'gzip -cd ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
15871
15872 if (0 === $this->process->execute($command, $ignoredOutput)) {
15873 return;
15874 }
15875
15876 if (extension_loaded('zlib')) {
15877
15878  $this->extractUsingExt($file, $targetFilepath);
15879
15880 return;
15881 }
15882
15883 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
15884 throw new \RuntimeException($processError);
15885 }
15886
15887
15888  $this->extractUsingExt($file, $targetFilepath);
15889 }
15890
15891
15892
15893
15894 protected function getFileName(PackageInterface $package, $path)
15895 {
15896 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
15897 }
15898
15899 private function extractUsingExt($file, $targetFilepath)
15900 {
15901 $archiveFile = gzopen($file, 'rb');
15902 $targetFile = fopen($targetFilepath, 'wb');
15903 while ($string = gzread($archiveFile, 4096)) {
15904 fwrite($targetFile, $string, Platform::strlen($string));
15905 }
15906 gzclose($archiveFile);
15907 fclose($targetFile);
15908 }
15909 }
15910 <?php
15911
15912
15913
15914
15915
15916
15917
15918
15919
15920
15921
15922 namespace Composer\Downloader;
15923
15924 use Composer\Package\PackageInterface;
15925 use Composer\Util\ProcessExecutor;
15926
15927
15928
15929
15930 class HgDownloader extends VcsDownloader
15931 {
15932
15933
15934
15935 public function doDownload(PackageInterface $package, $path, $url)
15936 {
15937
15938  $this->config->prohibitUrlByConfig($url, $this->io);
15939
15940 $url = ProcessExecutor::escape($url);
15941 $ref = ProcessExecutor::escape($package->getSourceReference());
15942 $this->io->writeError("Cloning ".$package->getSourceReference());
15943 $command = sprintf('hg clone %s %s', $url, ProcessExecutor::escape($path));
15944 if (0 !== $this->process->execute($command, $ignoredOutput)) {
15945 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15946 }
15947 $command = sprintf('hg up %s', $ref);
15948 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15949 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15950 }
15951 }
15952
15953
15954
15955
15956 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15957 {
15958
15959  $this->config->prohibitUrlByConfig($url, $this->io);
15960
15961 $url = ProcessExecutor::escape($url);
15962 $ref = ProcessExecutor::escape($target->getSourceReference());
15963 $this->io->writeError(" Updating to ".$target->getSourceReference());
15964
15965 if (!$this->hasMetadataRepository($path)) {
15966 throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15967 }
15968
15969 $command = sprintf('hg pull %s && hg up %s', $url, $ref);
15970 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15971 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15972 }
15973 }
15974
15975
15976
15977
15978 public function getLocalChanges(PackageInterface $package, $path)
15979 {
15980 if (!is_dir($path.'/.hg')) {
15981 return null;
15982 }
15983
15984 $this->process->execute('hg st', $output, realpath($path));
15985
15986 return trim($output) ?: null;
15987 }
15988
15989
15990
15991
15992 protected function getCommitLogs($fromReference, $toReference, $path)
15993 {
15994 $command = sprintf('hg log -r %s:%s --style compact', $fromReference, $toReference);
15995
15996 if (0 !== $this->process->execute($command, $output, realpath($path))) {
15997 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15998 }
15999
16000 return $output;
16001 }
16002
16003
16004
16005
16006 protected function hasMetadataRepository($path)
16007 {
16008 return is_dir($path . '/.hg');
16009 }
16010 }
16011 <?php
16012
16013
16014
16015
16016
16017
16018
16019
16020
16021
16022
16023 namespace Composer\Downloader;
16024
16025 use Composer\Package\Archiver\ArchivableFilesFinder;
16026 use Composer\Package\Dumper\ArrayDumper;
16027 use Composer\Package\PackageInterface;
16028 use Composer\Package\Version\VersionGuesser;
16029 use Composer\Package\Version\VersionParser;
16030 use Composer\Util\Platform;
16031 use Composer\Util\ProcessExecutor;
16032 use Composer\Util\Filesystem as ComposerFilesystem;
16033 use Symfony\Component\Filesystem\Exception\IOException;
16034 use Symfony\Component\Filesystem\Filesystem;
16035
16036
16037
16038
16039
16040
16041
16042 class PathDownloader extends FileDownloader implements VcsCapableDownloaderInterface
16043 {
16044 const STRATEGY_SYMLINK = 10;
16045 const STRATEGY_MIRROR = 20;
16046
16047
16048
16049
16050 public function download(PackageInterface $package, $path, $output = true)
16051 {
16052 $url = $package->getDistUrl();
16053 $realUrl = realpath($url);
16054 if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
16055 throw new \RuntimeException(sprintf(
16056 'Source path "%s" is not found for package %s', $url, $package->getName()
16057 ));
16058 }
16059
16060 if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
16061
16062  
16063  
16064  
16065  throw new \RuntimeException(sprintf(
16066 'Package %s cannot install to "%s" inside its source at "%s"',
16067 $package->getName(), realpath($path), $realUrl
16068 ));
16069 }
16070
16071
16072  $transportOptions = $package->getTransportOptions() + array('symlink' => null);
16073
16074
16075  $currentStrategy = self::STRATEGY_SYMLINK;
16076 $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
16077
16078 $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
16079 if ($mirrorPathRepos) {
16080 $currentStrategy = self::STRATEGY_MIRROR;
16081 }
16082
16083 if (true === $transportOptions['symlink']) {
16084 $currentStrategy = self::STRATEGY_SYMLINK;
16085 $allowedStrategies = array(self::STRATEGY_SYMLINK);
16086 } elseif (false === $transportOptions['symlink']) {
16087 $currentStrategy = self::STRATEGY_MIRROR;
16088 $allowedStrategies = array(self::STRATEGY_MIRROR);
16089 }
16090
16091 $fileSystem = new Filesystem();
16092 $this->filesystem->removeDirectory($path);
16093
16094 if ($output) {
16095 $this->io->writeError(sprintf(
16096 '  - Installing <info>%s</info> (<comment>%s</comment>): ',
16097 $package->getName(),
16098 $package->getFullPrettyVersion()
16099 ), false);
16100 }
16101
16102 $isFallback = false;
16103 if (self::STRATEGY_SYMLINK == $currentStrategy) {
16104 try {
16105 if (Platform::isWindows()) {
16106
16107  $this->io->writeError(sprintf('Junctioning from %s', $url), false);
16108 $this->filesystem->junction($realUrl, $path);
16109 } else {
16110 $absolutePath = $path;
16111 if (!$this->filesystem->isAbsolutePath($absolutePath)) {
16112 $absolutePath = getcwd() . DIRECTORY_SEPARATOR . $path;
16113 }
16114 $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
16115 $path = rtrim($path, "/");
16116 $this->io->writeError(sprintf('Symlinking from %s', $url), false);
16117 $fileSystem->symlink($shortestPath, $path);
16118 }
16119 } catch (IOException $e) {
16120 if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
16121 $this->io->writeError('');
16122 $this->io->writeError('    <error>Symlink failed, fallback to use mirroring!</error>');
16123 $currentStrategy = self::STRATEGY_MIRROR;
16124 $isFallback = true;
16125 } else {
16126 throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
16127 }
16128 }
16129 }
16130
16131
16132  if (self::STRATEGY_MIRROR == $currentStrategy) {
16133 $fs = new ComposerFilesystem();
16134 $realUrl = $fs->normalizePath($realUrl);
16135
16136 $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? '    ' : '', $url), false);
16137 $iterator = new ArchivableFilesFinder($realUrl, array());
16138 $fileSystem->mirror($realUrl, $path, $iterator);
16139 }
16140
16141 $this->io->writeError('');
16142 }
16143
16144
16145
16146
16147 public function remove(PackageInterface $package, $path, $output = true)
16148 {
16149
16150
16151
16152
16153
16154 if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
16155 if ($output) {
16156 $this->io->writeError("  - Removing junction for <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
16157 }
16158 if (!$this->filesystem->removeJunction($path)) {
16159 $this->io->writeError("    <warn>Could not remove junction at " . $path . " - is another process locking it?</warn>");
16160 throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
16161 }
16162 } else {
16163 parent::remove($package, $path, $output);
16164 }
16165 }
16166
16167
16168
16169
16170 public function getVcsReference(PackageInterface $package, $path)
16171 {
16172 $parser = new VersionParser;
16173 $guesser = new VersionGuesser($this->config, new ProcessExecutor($this->io), $parser);
16174 $dumper = new ArrayDumper;
16175
16176 $packageConfig = $dumper->dump($package);
16177 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
16178 return $packageVersion['commit'];
16179 }
16180 }
16181 }
16182 <?php
16183
16184
16185
16186
16187
16188
16189
16190
16191
16192
16193
16194 namespace Composer\Downloader;
16195
16196 use Composer\Util\Filesystem;
16197
16198
16199
16200
16201
16202
16203
16204
16205
16206
16207 class PearPackageExtractor
16208 {
16209 private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
16210
16211 private $filesystem;
16212 private $file;
16213
16214 public function __construct($file)
16215 {
16216 if (!is_file($file)) {
16217 throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
16218 }
16219
16220 $this->filesystem = new Filesystem();
16221 $this->file = $file;
16222 }
16223
16224
16225
16226
16227
16228
16229
16230
16231
16232
16233 public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
16234 {
16235 $extractionPath = $target.'/tarball';
16236
16237 try {
16238 $archive = new \PharData($this->file);
16239 $archive->extractTo($extractionPath, null, true);
16240
16241 if (!is_file($this->combine($extractionPath, '/package.xml'))) {
16242 throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
16243 }
16244
16245 $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
16246 $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
16247 $this->filesystem->removeDirectory($extractionPath);
16248 } catch (\Exception $exception) {
16249 throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
16250 }
16251 }
16252
16253
16254
16255
16256
16257
16258
16259
16260
16261
16262 private function copyFiles($files, $source, $target, $roles, $vars)
16263 {
16264 foreach ($files as $file) {
16265 $from = $this->combine($source, $file['from']);
16266 $to = $this->combine($target, $roles[$file['role']]);
16267 $to = $this->combine($to, $file['to']);
16268 $tasks = $file['tasks'];
16269 $this->copyFile($from, $to, $tasks, $vars);
16270 }
16271 }
16272
16273 private function copyFile($from, $to, $tasks, $vars)
16274 {
16275 if (!is_file($from)) {
16276 throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
16277 }
16278
16279 $this->filesystem->ensureDirectoryExists(dirname($to));
16280
16281 if (0 == count($tasks)) {
16282 $copied = copy($from, $to);
16283 } else {
16284 $content = file_get_contents($from);
16285 $replacements = array();
16286 foreach ($tasks as $task) {
16287 $pattern = $task['from'];
16288 $varName = $task['to'];
16289 if (isset($vars[$varName])) {
16290 if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
16291 $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
16292 } else {
16293 $replacements[$pattern] = $vars[$varName];
16294 }
16295 }
16296 }
16297 $content = strtr($content, $replacements);
16298
16299 $copied = file_put_contents($to, $content);
16300 }
16301
16302 if (false === $copied) {
16303 throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
16304 }
16305 }
16306
16307
16308
16309
16310
16311
16312
16313
16314
16315
16316
16317 private function buildCopyActions($source, array $roles, $vars)
16318 {
16319
16320 $package = simplexml_load_string(file_get_contents($this->combine($source, 'package.xml')));
16321 if (false === $package) {
16322 throw new \RuntimeException('Package definition file is not valid.');
16323 }
16324
16325 $packageSchemaVersion = $package['version'];
16326 if ('1.0' == $packageSchemaVersion) {
16327 $children = $package->release->filelist->children();
16328 $packageName = (string) $package->name;
16329 $packageVersion = (string) $package->release->version;
16330 $sourceDir = $packageName . '-' . $packageVersion;
16331 $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
16332 } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
16333 $children = $package->contents->children();
16334 $packageName = (string) $package->name;
16335 $packageVersion = (string) $package->version->release;
16336 $sourceDir = $packageName . '-' . $packageVersion;
16337 $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
16338
16339 $namespaces = $package->getNamespaces();
16340 $package->registerXPathNamespace('ns', $namespaces['']);
16341 $releaseNodes = $package->xpath('ns:phprelease');
16342 $this->applyRelease($result, $releaseNodes, $vars);
16343 } else {
16344 throw new \RuntimeException('Unsupported schema version of package definition file.');
16345 }
16346
16347 return $result;
16348 }
16349
16350 private function applyRelease(&$actions, $releaseNodes, $vars)
16351 {
16352 foreach ($releaseNodes as $releaseNode) {
16353 $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
16354 if ($requiredOs && $vars['os'] != $requiredOs) {
16355 continue;
16356 }
16357
16358 if ($releaseNode->filelist) {
16359 foreach ($releaseNode->filelist->children() as $action) {
16360 if ('install' == $action->getName()) {
16361 $name = (string) $action['name'];
16362 $as = (string) $action['as'];
16363 if (isset($actions[$name])) {
16364 $actions[$name]['to'] = $as;
16365 }
16366 } elseif ('ignore' == $action->getName()) {
16367 $name = (string) $action['name'];
16368 unset($actions[$name]);
16369 } else {
16370
16371  }
16372 }
16373 }
16374 break;
16375 }
16376 }
16377
16378 private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
16379 {
16380 $result = array();
16381
16382
16383  foreach ($children as $child) {
16384
16385 if ($child->getName() == 'dir') {
16386 $dirSource = $this->combine($source, (string) $child['name']);
16387 $dirTarget = $child['baseinstalldir'] ?: $target;
16388 $dirRole = $child['role'] ?: $role;
16389 $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16390 $result = array_merge($result, $dirFiles);
16391 } elseif ($child->getName() == 'file') {
16392 $fileRole = (string) $child['role'] ?: $role;
16393 if (isset($targetRoles[$fileRole])) {
16394 $fileName = (string) ($child['name'] ?: $child[0]); 
16395  $fileSource = $this->combine($source, $fileName);
16396 $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
16397 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16398 $fileTarget = $packageName . '/' . $fileTarget;
16399 }
16400 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
16401 }
16402 }
16403 }
16404
16405 return $result;
16406 }
16407
16408 private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
16409 {
16410 $result = array();
16411
16412
16413  foreach ($children as $child) {
16414
16415 if ('dir' == $child->getName()) {
16416 $dirSource = $this->combine($source, $child['name']);
16417 $dirTarget = $child['baseinstalldir'] ?: $target;
16418 $dirRole = $child['role'] ?: $role;
16419 $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16420 $result = array_merge($result, $dirFiles);
16421 } elseif ('file' == $child->getName()) {
16422 $fileRole = (string) $child['role'] ?: $role;
16423 if (isset($targetRoles[$fileRole])) {
16424 $fileSource = $this->combine($source, (string) $child['name']);
16425 $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
16426 $fileTasks = array();
16427 foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
16428 if ('replace' == $taskNode->getName()) {
16429 $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
16430 }
16431 }
16432 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16433 $fileTarget = $packageName . '/' . $fileTarget;
16434 }
16435 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
16436 }
16437 }
16438 }
16439
16440 return $result;
16441 }
16442
16443 private function combine($left, $right)
16444 {
16445 return rtrim($left, '/') . '/' . ltrim($right, '/');
16446 }
16447 }
16448 <?php
16449
16450
16451
16452
16453
16454
16455
16456
16457
16458
16459
16460 namespace Composer\Downloader;
16461
16462 use Composer\Package\PackageInterface;
16463 use Composer\Repository\VcsRepository;
16464 use Composer\Util\Perforce;
16465
16466
16467
16468
16469 class PerforceDownloader extends VcsDownloader
16470 {
16471
16472 protected $perforce;
16473
16474
16475
16476
16477 public function doDownload(PackageInterface $package, $path, $url)
16478 {
16479 $ref = $package->getSourceReference();
16480 $label = $this->getLabelFromSourceReference($ref);
16481
16482 $this->io->writeError('Cloning ' . $ref);
16483 $this->initPerforce($package, $path, $url);
16484 $this->perforce->setStream($ref);
16485 $this->perforce->p4Login();
16486 $this->perforce->writeP4ClientSpec();
16487 $this->perforce->connectClient();
16488 $this->perforce->syncCodeBase($label);
16489 $this->perforce->cleanupClientSpec();
16490 }
16491
16492 private function getLabelFromSourceReference($ref)
16493 {
16494 $pos = strpos($ref, '@');
16495 if (false !== $pos) {
16496 return substr($ref, $pos + 1);
16497 }
16498
16499 return null;
16500 }
16501
16502 public function initPerforce(PackageInterface $package, $path, $url)
16503 {
16504 if (!empty($this->perforce)) {
16505 $this->perforce->initializePath($path);
16506
16507 return;
16508 }
16509
16510 $repository = $package->getRepository();
16511 $repoConfig = null;
16512 if ($repository instanceof VcsRepository) {
16513 $repoConfig = $this->getRepoConfig($repository);
16514 }
16515 $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
16516 }
16517
16518 private function getRepoConfig(VcsRepository $repository)
16519 {
16520 return $repository->getRepoConfig();
16521 }
16522
16523
16524
16525
16526 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16527 {
16528 $this->doDownload($target, $path, $url);
16529 }
16530
16531
16532
16533
16534 public function getLocalChanges(PackageInterface $package, $path)
16535 {
16536 $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
16537
16538 return;
16539 }
16540
16541
16542
16543
16544 protected function getCommitLogs($fromReference, $toReference, $path)
16545 {
16546 return $this->perforce->getCommitLogs($fromReference, $toReference);
16547 }
16548
16549 public function setPerforce($perforce)
16550 {
16551 $this->perforce = $perforce;
16552 }
16553
16554
16555
16556
16557 protected function hasMetadataRepository($path)
16558 {
16559 return true;
16560 }
16561 }
16562 <?php
16563
16564
16565
16566
16567
16568
16569
16570
16571
16572
16573
16574 namespace Composer\Downloader;
16575
16576
16577
16578
16579
16580
16581 class PharDownloader extends ArchiveDownloader
16582 {
16583
16584
16585
16586 protected function extract($file, $path)
16587 {
16588
16589  $archive = new \Phar($file);
16590 $archive->extractTo($path, null, true);
16591
16592
16593
16594
16595
16596 }
16597 }
16598 <?php
16599
16600
16601
16602
16603
16604
16605
16606
16607
16608
16609
16610 namespace Composer\Downloader;
16611
16612 use Composer\Config;
16613 use Composer\Cache;
16614 use Composer\EventDispatcher\EventDispatcher;
16615 use Composer\Util\IniHelper;
16616 use Composer\Util\Platform;
16617 use Composer\Util\ProcessExecutor;
16618 use Composer\Util\RemoteFilesystem;
16619 use Composer\IO\IOInterface;
16620 use RarArchive;
16621
16622
16623
16624
16625
16626
16627
16628
16629 class RarDownloader extends ArchiveDownloader
16630 {
16631 protected $process;
16632
16633 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
16634 {
16635 $this->process = $process ?: new ProcessExecutor($io);
16636 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
16637 }
16638
16639 protected function extract($file, $path)
16640 {
16641 $processError = null;
16642
16643
16644  if (!Platform::isWindows()) {
16645 $command = 'unrar x ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
16646
16647 if (0 === $this->process->execute($command, $ignoredOutput)) {
16648 return;
16649 }
16650
16651 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
16652 }
16653
16654 if (!class_exists('RarArchive')) {
16655
16656  $iniMessage = IniHelper::getMessage();
16657
16658 $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n"
16659 . $iniMessage . "\n" . $processError;
16660
16661 if (!Platform::isWindows()) {
16662 $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
16663 }
16664
16665 throw new \RuntimeException($error);
16666 }
16667
16668 $rarArchive = RarArchive::open($file);
16669
16670 if (false === $rarArchive) {
16671 throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
16672 }
16673
16674 $entries = $rarArchive->getEntries();
16675
16676 if (false === $entries) {
16677 throw new \RuntimeException('Could not retrieve RAR archive entries');
16678 }
16679
16680 foreach ($entries as $entry) {
16681 if (false === $entry->extract($path)) {
16682 throw new \RuntimeException('Could not extract entry');
16683 }
16684 }
16685
16686 $rarArchive->close();
16687 }
16688 }
16689 <?php
16690
16691
16692
16693
16694
16695
16696
16697
16698
16699
16700
16701 namespace Composer\Downloader;
16702
16703 use Composer\Package\PackageInterface;
16704 use Composer\Util\Svn as SvnUtil;
16705 use Composer\Repository\VcsRepository;
16706 use Composer\Util\ProcessExecutor;
16707
16708
16709
16710
16711
16712 class SvnDownloader extends VcsDownloader
16713 {
16714 protected $cacheCredentials = true;
16715
16716
16717
16718
16719 public function doDownload(PackageInterface $package, $path, $url)
16720 {
16721 SvnUtil::cleanEnv();
16722 $ref = $package->getSourceReference();
16723
16724 $repo = $package->getRepository();
16725 if ($repo instanceof VcsRepository) {
16726 $repoConfig = $repo->getRepoConfig();
16727 if (array_key_exists('svn-cache-credentials', $repoConfig)) {
16728 $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials'];
16729 }
16730 }
16731
16732 $this->io->writeError(" Checking out ".$package->getSourceReference());
16733 $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
16734 }
16735
16736
16737
16738
16739 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16740 {
16741 SvnUtil::cleanEnv();
16742 $ref = $target->getSourceReference();
16743
16744 if (!$this->hasMetadataRepository($path)) {
16745 throw new \RuntimeException('The .svn directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16746 }
16747
16748 $flags = "";
16749 if (0 === $this->process->execute('svn --version', $output)) {
16750 if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match) && version_compare($match[1], '1.7.0', '>=')) {
16751 $flags .= ' --ignore-ancestry';
16752 }
16753 }
16754
16755 $this->io->writeError(" Checking out " . $ref);
16756 $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
16757 }
16758
16759
16760
16761
16762 public function getLocalChanges(PackageInterface $package, $path)
16763 {
16764 if (!$this->hasMetadataRepository($path)) {
16765 return null;
16766 }
16767
16768 $this->process->execute('svn status --ignore-externals', $output, $path);
16769
16770 return preg_match('{^ *[^X ] +}m', $output) ? $output : null;
16771 }
16772
16773
16774
16775
16776
16777
16778
16779
16780
16781
16782
16783
16784
16785 protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
16786 {
16787 $util = new SvnUtil($baseUrl, $this->io, $this->config);
16788 $util->setCacheCredentials($this->cacheCredentials);
16789 try {
16790 return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
16791 } catch (\RuntimeException $e) {
16792 throw new \RuntimeException(
16793 'Package could not be downloaded, '.$e->getMessage()
16794 );
16795 }
16796 }
16797
16798
16799
16800
16801 protected function cleanChanges(PackageInterface $package, $path, $update)
16802 {
16803 if (!$changes = $this->getLocalChanges($package, $path)) {
16804 return;
16805 }
16806
16807 if (!$this->io->isInteractive()) {
16808 if (true === $this->config->get('discard-changes')) {
16809 return $this->discardChanges($path);
16810 }
16811
16812 return parent::cleanChanges($package, $path, $update);
16813 }
16814
16815 $changes = array_map(function ($elem) {
16816 return '    '.$elem;
16817 }, preg_split('{\s*\r?\n\s*}', $changes));
16818 $countChanges = count($changes);
16819 $this->io->writeError(sprintf('    <error>The package has modified file%s:</error>', $countChanges === 1 ? '' : 's'));
16820 $this->io->writeError(array_slice($changes, 0, 10));
16821 if ($countChanges > 10) {
16822 $remaingChanges = $countChanges - 10;
16823 $this->io->writeError(
16824 sprintf(
16825 '    <info>'.$remaingChanges.' more file%s modified, choose "v" to view the full list</info>',
16826 $remaingChanges === 1 ? '' : 's'
16827 )
16828 );
16829 }
16830
16831 while (true) {
16832 switch ($this->io->ask('    <info>Discard changes [y,n,v,?]?</info> ', '?')) {
16833 case 'y':
16834 $this->discardChanges($path);
16835 break 2;
16836
16837 case 'n':
16838 throw new \RuntimeException('Update aborted');
16839
16840 case 'v':
16841 $this->io->writeError($changes);
16842 break;
16843
16844 case '?':
16845 default:
16846 $this->io->writeError(array(
16847 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
16848 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
16849 '    v - view modified files',
16850 '    ? - print help',
16851 ));
16852 break;
16853 }
16854 }
16855 }
16856
16857
16858
16859
16860 protected function getCommitLogs($fromReference, $toReference, $path)
16861 {
16862 if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
16863
16864  $command = sprintf('svn info --non-interactive --xml %s', ProcessExecutor::escape($path));
16865 if (0 !== $this->process->execute($command, $output, $path)) {
16866 throw new \RuntimeException(
16867 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
16868 );
16869 }
16870
16871 $urlPattern = '#<url>(.*)</url>#';
16872 if (preg_match($urlPattern, $output, $matches)) {
16873 $baseUrl = $matches[1];
16874 } else {
16875 throw new \RuntimeException(
16876 'Unable to determine svn url for path '. $path
16877 );
16878 }
16879
16880
16881  $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
16882 $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
16883
16884 $command = sprintf('svn log -r%s:%s --incremental', $fromRevision, $toRevision);
16885
16886 $util = new SvnUtil($baseUrl, $this->io, $this->config);
16887 $util->setCacheCredentials($this->cacheCredentials);
16888 try {
16889 return $util->executeLocal($command, $path, null, $this->io->isVerbose());
16890 } catch (\RuntimeException $e) {
16891 throw new \RuntimeException(
16892 'Failed to execute ' . $command . "\n\n".$e->getMessage()
16893 );
16894 }
16895 }
16896
16897 return "Could not retrieve changes between $fromReference and $toReference due to missing revision information";
16898 }
16899
16900 protected function discardChanges($path)
16901 {
16902 if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
16903 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
16904 }
16905 }
16906
16907
16908
16909
16910 protected function hasMetadataRepository($path)
16911 {
16912 return is_dir($path.'/.svn');
16913 }
16914 }
16915 <?php
16916
16917
16918
16919
16920
16921
16922
16923
16924
16925
16926
16927 namespace Composer\Downloader;
16928
16929
16930
16931
16932
16933
16934 class TarDownloader extends ArchiveDownloader
16935 {
16936
16937
16938
16939 protected function extract($file, $path)
16940 {
16941
16942  $archive = new \PharData($file);
16943 $archive->extractTo($path, null, true);
16944 }
16945 }
16946 <?php
16947
16948
16949
16950
16951
16952
16953
16954
16955
16956
16957
16958 namespace Composer\Downloader;
16959
16960
16961
16962
16963 class TransportException extends \RuntimeException
16964 {
16965 protected $headers;
16966 protected $response;
16967 protected $statusCode;
16968
16969 public function setHeaders($headers)
16970 {
16971 $this->headers = $headers;
16972 }
16973
16974 public function getHeaders()
16975 {
16976 return $this->headers;
16977 }
16978
16979 public function setResponse($response)
16980 {
16981 $this->response = $response;
16982 }
16983
16984 public function getResponse()
16985 {
16986 return $this->response;
16987 }
16988
16989 public function setStatusCode($statusCode)
16990 {
16991 $this->statusCode = $statusCode;
16992 }
16993
16994 public function getStatusCode()
16995 {
16996 return $this->statusCode;
16997 }
16998 }
16999 <?php
17000
17001
17002
17003
17004
17005
17006
17007
17008
17009
17010
17011 namespace Composer\Downloader;
17012
17013 use Composer\Package\PackageInterface;
17014
17015
17016
17017
17018
17019
17020 interface VcsCapableDownloaderInterface
17021 {
17022
17023
17024
17025
17026
17027
17028
17029 public function getVcsReference(PackageInterface $package, $path);
17030 }
17031 <?php
17032
17033
17034
17035
17036
17037
17038
17039
17040
17041
17042
17043 namespace Composer\Downloader;
17044
17045 use Composer\Config;
17046 use Composer\Package\Dumper\ArrayDumper;
17047 use Composer\Package\PackageInterface;
17048 use Composer\Package\Version\VersionGuesser;
17049 use Composer\Package\Version\VersionParser;
17050 use Composer\Util\ProcessExecutor;
17051 use Composer\IO\IOInterface;
17052 use Composer\Util\Filesystem;
17053
17054
17055
17056
17057 abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterface, VcsCapableDownloaderInterface
17058 {
17059
17060 protected $io;
17061
17062 protected $config;
17063
17064 protected $process;
17065
17066 protected $filesystem;
17067
17068 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
17069 {
17070 $this->io = $io;
17071 $this->config = $config;
17072 $this->process = $process ?: new ProcessExecutor($io);
17073 $this->filesystem = $fs ?: new Filesystem($this->process);
17074 }
17075
17076
17077
17078
17079 public function getInstallationSource()
17080 {
17081 return 'source';
17082 }
17083
17084
17085
17086
17087 public function download(PackageInterface $package, $path)
17088 {
17089 if (!$package->getSourceReference()) {
17090 throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
17091 }
17092
17093 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
17094 $this->filesystem->emptyDirectory($path);
17095
17096 $urls = $package->getSourceUrls();
17097 while ($url = array_shift($urls)) {
17098 try {
17099 if (Filesystem::isLocalPath($url)) {
17100
17101  
17102  $needle = 'file://';
17103 $isFileProtocol = false;
17104 if (0 === strpos($url, $needle)) {
17105 $url = substr($url, strlen($needle));
17106 $isFileProtocol = true;
17107 }
17108
17109
17110  if (false !== strpos($url, '%')) {
17111 $url = rawurldecode($url);
17112 }
17113
17114 $url = realpath($url);
17115
17116 if ($isFileProtocol) {
17117 $url = $needle . $url;
17118 }
17119 }
17120 $this->doDownload($package, $path, $url);
17121 break;
17122 } catch (\Exception $e) {
17123
17124  if ($e instanceof \PHPUnit_Framework_Exception) {
17125 throw $e;
17126 }
17127 if ($this->io->isDebug()) {
17128 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
17129 } elseif (count($urls)) {
17130 $this->io->writeError('    Failed, trying the next URL');
17131 }
17132 if (!count($urls)) {
17133 throw $e;
17134 }
17135 }
17136 }
17137 }
17138
17139
17140
17141
17142 public function update(PackageInterface $initial, PackageInterface $target, $path)
17143 {
17144 if (!$target->getSourceReference()) {
17145 throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
17146 }
17147
17148 $name = $target->getName();
17149 if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
17150 if ($target->getSourceType() === 'svn') {
17151 $from = $initial->getSourceReference();
17152 $to = $target->getSourceReference();
17153 } else {
17154 $from = substr($initial->getSourceReference(), 0, 7);
17155 $to = substr($target->getSourceReference(), 0, 7);
17156 }
17157 $name .= ' '.$initial->getPrettyVersion();
17158 } else {
17159 $from = $initial->getFullPrettyVersion();
17160 $to = $target->getFullPrettyVersion();
17161 }
17162
17163 $this->io->writeError("  - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
17164
17165 $this->cleanChanges($initial, $path, true);
17166 $urls = $target->getSourceUrls();
17167
17168 $exception = null;
17169 while ($url = array_shift($urls)) {
17170 try {
17171 if (Filesystem::isLocalPath($url)) {
17172 $url = realpath($url);
17173 }
17174 $this->doUpdate($initial, $target, $path, $url);
17175
17176 $exception = null;
17177 break;
17178 } catch (\Exception $exception) {
17179
17180  if ($exception instanceof \PHPUnit_Framework_Exception) {
17181 throw $exception;
17182 }
17183 if ($this->io->isDebug()) {
17184 $this->io->writeError('Failed: ['.get_class($exception).'] '.$exception->getMessage());
17185 } elseif (count($urls)) {
17186 $this->io->writeError('    Failed, trying the next URL');
17187 }
17188 }
17189 }
17190
17191 $this->reapplyChanges($path);
17192
17193
17194  
17195  if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
17196 $message = 'Pulling in changes:';
17197 $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
17198
17199 if (!trim($logs)) {
17200 $message = 'Rolling back changes:';
17201 $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
17202 }
17203
17204 if (trim($logs)) {
17205 $logs = implode("\n", array_map(function ($line) {
17206 return '      ' . $line;
17207 }, explode("\n", $logs)));
17208
17209
17210  $logs = str_replace('<', '\<', $logs);
17211
17212 $this->io->writeError('    '.$message);
17213 $this->io->writeError($logs);
17214 }
17215 }
17216
17217 if (!$urls && $exception) {
17218 throw $exception;
17219 }
17220 }
17221
17222
17223
17224
17225 public function remove(PackageInterface $package, $path)
17226 {
17227 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
17228 $this->cleanChanges($package, $path, false);
17229 if (!$this->filesystem->removeDirectory($path)) {
17230 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
17231 }
17232 }
17233
17234
17235
17236
17237
17238 public function setOutputProgress($outputProgress)
17239 {
17240 return $this;
17241 }
17242
17243
17244
17245
17246 public function getVcsReference(PackageInterface $package, $path)
17247 {
17248 $parser = new VersionParser;
17249 $guesser = new VersionGuesser($this->config, $this->process, $parser);
17250 $dumper = new ArrayDumper;
17251
17252 $packageConfig = $dumper->dump($package);
17253 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
17254 return $packageVersion['commit'];
17255 }
17256 }
17257
17258
17259
17260
17261
17262
17263
17264
17265
17266
17267 protected function cleanChanges(PackageInterface $package, $path, $update)
17268 {
17269
17270  if (null !== $this->getLocalChanges($package, $path)) {
17271 throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
17272 }
17273 }
17274
17275
17276
17277
17278
17279
17280
17281 protected function reapplyChanges($path)
17282 {
17283 }
17284
17285
17286
17287
17288
17289
17290
17291
17292 abstract protected function doDownload(PackageInterface $package, $path, $url);
17293
17294
17295
17296
17297
17298
17299
17300
17301
17302 abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
17303
17304
17305
17306
17307
17308
17309
17310
17311
17312 abstract protected function getCommitLogs($fromReference, $toReference, $path);
17313
17314
17315
17316
17317
17318
17319
17320
17321 abstract protected function hasMetadataRepository($path);
17322 }
17323 <?php
17324
17325
17326
17327
17328
17329
17330
17331
17332
17333
17334
17335 namespace Composer\Downloader;
17336
17337 use Composer\Config;
17338 use Composer\Cache;
17339 use Composer\EventDispatcher\EventDispatcher;
17340 use Composer\Package\PackageInterface;
17341 use Composer\Util\ProcessExecutor;
17342 use Composer\Util\RemoteFilesystem;
17343 use Composer\IO\IOInterface;
17344
17345
17346
17347
17348
17349
17350
17351 class XzDownloader extends ArchiveDownloader
17352 {
17353 protected $process;
17354
17355 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17356 {
17357 $this->process = $process ?: new ProcessExecutor($io);
17358
17359 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17360 }
17361
17362 protected function extract($file, $path)
17363 {
17364 $command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
17365
17366 if (0 === $this->process->execute($command, $ignoredOutput)) {
17367 return;
17368 }
17369
17370 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
17371
17372 throw new \RuntimeException($processError);
17373 }
17374
17375
17376
17377
17378 protected function getFileName(PackageInterface $package, $path)
17379 {
17380 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
17381 }
17382 }
17383 <?php
17384
17385
17386
17387
17388
17389
17390
17391
17392
17393
17394
17395 namespace Composer\Downloader;
17396
17397 use Composer\Config;
17398 use Composer\Cache;
17399 use Composer\EventDispatcher\EventDispatcher;
17400 use Composer\Package\PackageInterface;
17401 use Composer\Util\IniHelper;
17402 use Composer\Util\Platform;
17403 use Composer\Util\ProcessExecutor;
17404 use Composer\Util\RemoteFilesystem;
17405 use Composer\IO\IOInterface;
17406 use Symfony\Component\Process\ExecutableFinder;
17407 use ZipArchive;
17408
17409
17410
17411
17412 class ZipDownloader extends ArchiveDownloader
17413 {
17414 protected static $hasSystemUnzip;
17415 private static $hasZipArchive;
17416 private static $isWindows;
17417
17418 protected $process;
17419 private $zipArchiveObject;
17420
17421 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17422 {
17423 $this->process = $process ?: new ProcessExecutor($io);
17424 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17425 }
17426
17427
17428
17429
17430 public function download(PackageInterface $package, $path, $output = true)
17431 {
17432 if (null === self::$hasSystemUnzip) {
17433 $finder = new ExecutableFinder;
17434 self::$hasSystemUnzip = (bool) $finder->find('unzip');
17435 }
17436
17437 if (null === self::$hasZipArchive) {
17438 self::$hasZipArchive = class_exists('ZipArchive');
17439 }
17440
17441 if (null === self::$isWindows) {
17442 self::$isWindows = Platform::isWindows();
17443 }
17444
17445 if (!self::$hasZipArchive && !self::$hasSystemUnzip) {
17446
17447  $iniMessage = IniHelper::getMessage();
17448 $error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
17449
17450 throw new \RuntimeException($error);
17451 }
17452
17453 return parent::download($package, $path, $output);
17454 }
17455
17456
17457
17458
17459
17460
17461
17462
17463
17464 protected function extractWithSystemUnzip($file, $path, $isLastChance)
17465 {
17466 if (!self::$hasZipArchive) {
17467
17468  $isLastChance = true;
17469 }
17470
17471 if (!self::$hasSystemUnzip && !$isLastChance) {
17472
17473  
17474  return $this->extractWithZipArchive($file, $path, true);
17475 }
17476
17477 $processError = null;
17478
17479  $overwrite = $isLastChance ? '-o' : '';
17480
17481 $command = 'unzip -qq '.$overwrite.' '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
17482
17483 try {
17484 if (0 === $this->process->execute($command, $ignoredOutput)) {
17485 return true;
17486 }
17487
17488 $processError = new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17489 } catch (\Exception $e) {
17490 $processError = $e;
17491 }
17492
17493 if ($isLastChance) {
17494 throw $processError;
17495 }
17496
17497 $this->io->writeError('    '.$processError->getMessage());
17498 $this->io->writeError('    The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
17499 $this->io->writeError('    Unzip with unzip command failed, falling back to ZipArchive class');
17500
17501 return $this->extractWithZipArchive($file, $path, true);
17502 }
17503
17504
17505
17506
17507
17508
17509
17510
17511
17512 protected function extractWithZipArchive($file, $path, $isLastChance)
17513 {
17514 if (!self::$hasSystemUnzip) {
17515
17516  $isLastChance = true;
17517 }
17518
17519 if (!self::$hasZipArchive && !$isLastChance) {
17520
17521  
17522  return $this->extractWithSystemUnzip($file, $path, true);
17523 }
17524
17525 $processError = null;
17526 $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
17527
17528 try {
17529 if (true === ($retval = $zipArchive->open($file))) {
17530 $extractResult = $zipArchive->extractTo($path);
17531
17532 if (true === $extractResult) {
17533 $zipArchive->close();
17534
17535 return true;
17536 }
17537
17538 $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
17539 } else {
17540 $processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file)."\n"), $retval);
17541 }
17542 } catch (\ErrorException $e) {
17543 $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
17544 } catch (\Exception $e) {
17545 $processError = $e;
17546 }
17547
17548 if ($isLastChance) {
17549 throw $processError;
17550 }
17551
17552 $this->io->writeError('    '.$processError->getMessage());
17553 $this->io->writeError('    Unzip with ZipArchive class failed, falling back to unzip command');
17554
17555 return $this->extractWithSystemUnzip($file, $path, true);
17556 }
17557
17558
17559
17560
17561
17562
17563
17564 public function extract($file, $path)
17565 {
17566
17567  if (self::$isWindows) {
17568 $this->extractWithZipArchive($file, $path, false);
17569 } else {
17570 $this->extractWithSystemUnzip($file, $path, false);
17571 }
17572 }
17573
17574
17575
17576
17577
17578
17579
17580
17581 protected function getErrorMessage($retval, $file)
17582 {
17583 switch ($retval) {
17584 case ZipArchive::ER_EXISTS:
17585 return sprintf("File '%s' already exists.", $file);
17586 case ZipArchive::ER_INCONS:
17587 return sprintf("Zip archive '%s' is inconsistent.", $file);
17588 case ZipArchive::ER_INVAL:
17589 return sprintf("Invalid argument (%s)", $file);
17590 case ZipArchive::ER_MEMORY:
17591 return sprintf("Malloc failure (%s)", $file);
17592 case ZipArchive::ER_NOENT:
17593 return sprintf("No such zip file: '%s'", $file);
17594 case ZipArchive::ER_NOZIP:
17595 return sprintf("'%s' is not a zip archive.", $file);
17596 case ZipArchive::ER_OPEN:
17597 return sprintf("Can't open zip file: %s", $file);
17598 case ZipArchive::ER_READ:
17599 return sprintf("Zip read error (%s)", $file);
17600 case ZipArchive::ER_SEEK:
17601 return sprintf("Zip seek error (%s)", $file);
17602 default:
17603 return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
17604 }
17605 }
17606 }
17607 <?php
17608
17609
17610
17611
17612
17613
17614
17615
17616
17617
17618
17619 namespace Composer\EventDispatcher;
17620
17621
17622
17623
17624
17625
17626 class Event
17627 {
17628
17629
17630
17631 protected $name;
17632
17633
17634
17635
17636 protected $args;
17637
17638
17639
17640
17641 protected $flags;
17642
17643
17644
17645
17646 private $propagationStopped = false;
17647
17648
17649
17650
17651
17652
17653
17654
17655 public function __construct($name, array $args = array(), array $flags = array())
17656 {
17657 $this->name = $name;
17658 $this->args = $args;
17659 $this->flags = $flags;
17660 }
17661
17662
17663
17664
17665
17666
17667 public function getName()
17668 {
17669 return $this->name;
17670 }
17671
17672
17673
17674
17675
17676
17677 public function getArguments()
17678 {
17679 return $this->args;
17680 }
17681
17682
17683
17684
17685
17686
17687 public function getFlags()
17688 {
17689 return $this->flags;
17690 }
17691
17692
17693
17694
17695
17696
17697 public function isPropagationStopped()
17698 {
17699 return $this->propagationStopped;
17700 }
17701
17702
17703
17704
17705 public function stopPropagation()
17706 {
17707 $this->propagationStopped = true;
17708 }
17709 }
17710 <?php
17711
17712
17713
17714
17715
17716
17717
17718
17719
17720
17721
17722 namespace Composer\EventDispatcher;
17723
17724 use Composer\DependencyResolver\PolicyInterface;
17725 use Composer\DependencyResolver\Pool;
17726 use Composer\DependencyResolver\Request;
17727 use Composer\Installer\InstallerEvent;
17728 use Composer\IO\IOInterface;
17729 use Composer\Composer;
17730 use Composer\DependencyResolver\Operation\OperationInterface;
17731 use Composer\Repository\CompositeRepository;
17732 use Composer\Script;
17733 use Composer\Installer\PackageEvent;
17734 use Composer\Installer\BinaryInstaller;
17735 use Composer\Util\ProcessExecutor;
17736 use Composer\Script\Event as ScriptEvent;
17737 use Symfony\Component\Process\PhpExecutableFinder;
17738
17739
17740
17741
17742
17743
17744
17745
17746
17747
17748
17749
17750
17751
17752 class EventDispatcher
17753 {
17754 protected $composer;
17755 protected $io;
17756 protected $loader;
17757 protected $process;
17758 protected $listeners;
17759 private $eventStack;
17760
17761
17762
17763
17764
17765
17766
17767
17768 public function __construct(Composer $composer, IOInterface $io, ProcessExecutor $process = null)
17769 {
17770 $this->composer = $composer;
17771 $this->io = $io;
17772 $this->process = $process ?: new ProcessExecutor($io);
17773 $this->eventStack = array();
17774 }
17775
17776
17777
17778
17779
17780
17781
17782
17783
17784 public function dispatch($eventName, Event $event = null)
17785 {
17786 if (null === $event) {
17787 $event = new Event($eventName);
17788 }
17789
17790 return $this->doDispatch($event);
17791 }
17792
17793
17794
17795
17796
17797
17798
17799
17800
17801
17802
17803 public function dispatchScript($eventName, $devMode = false, $additionalArgs = array(), $flags = array())
17804 {
17805 return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
17806 }
17807
17808
17809
17810
17811
17812
17813
17814
17815
17816
17817
17818
17819
17820
17821
17822
17823 public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
17824 {
17825 return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
17826 }
17827
17828
17829
17830
17831
17832
17833
17834
17835
17836
17837
17838
17839
17840
17841
17842 public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
17843 {
17844 return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
17845 }
17846
17847
17848
17849
17850
17851
17852
17853
17854
17855 protected function doDispatch(Event $event)
17856 {
17857 $pathStr = 'PATH';
17858 if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
17859 $pathStr = 'Path';
17860 }
17861
17862
17863  $binDir = $this->composer->getConfig()->get('bin-dir');
17864 if (is_dir($binDir)) {
17865 $binDir = realpath($binDir);
17866 if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
17867 $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
17868 putenv($pathStr.'='.$_SERVER[$pathStr]);
17869 }
17870 }
17871
17872 $listeners = $this->getListeners($event);
17873
17874 $this->pushEvent($event);
17875
17876 $return = 0;
17877 foreach ($listeners as $callable) {
17878 if (!is_string($callable) && is_callable($callable)) {
17879 $event = $this->checkListenerExpectedEvent($callable, $event);
17880 $return = false === call_user_func($callable, $event) ? 1 : 0;
17881 } elseif ($this->isComposerScript($callable)) {
17882 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
17883 $scriptName = substr($callable, 1);
17884 $args = $event->getArguments();
17885 $flags = $event->getFlags();
17886 if (substr($callable, 0, 10) === '@composer ') {
17887 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
17888 if (0 !== ($exitCode = $this->process->execute($exec))) {
17889 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
17890
17891 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
17892 }
17893 } else {
17894 if (!$this->getListeners(new Event($scriptName))) {
17895 $this->io->writeError(sprintf('<warning>You made a reference to a non-existent script %s</warning>', $callable), true, IOInterface::QUIET);
17896 }
17897
17898 $return = $this->dispatch($scriptName, new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags));
17899 }
17900 } elseif ($this->isPhpScript($callable)) {
17901 $className = substr($callable, 0, strpos($callable, '::'));
17902 $methodName = substr($callable, strpos($callable, '::') + 2);
17903
17904 if (!class_exists($className)) {
17905 $this->io->writeError('<warning>Class '.$className.' is not autoloadable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
17906 continue;
17907 }
17908 if (!is_callable($callable)) {
17909 $this->io->writeError('<warning>Method '.$callable.' is not callable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
17910 continue;
17911 }
17912
17913 try {
17914 $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
17915 } catch (\Exception $e) {
17916 $message = "Script %s handling the %s event terminated with an exception";
17917 $this->io->writeError('<error>'.sprintf($message, $callable, $event->getName()).'</error>', true, IOInterface::QUIET);
17918 throw $e;
17919 }
17920 } else {
17921 $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
17922 $exec = $callable . ($args === '' ? '' : ' '.$args);
17923 if ($this->io->isVerbose()) {
17924 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
17925 } else {
17926 $this->io->writeError(sprintf('> %s', $exec));
17927 }
17928
17929 $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
17930 if ($possibleLocalBinaries) {
17931 foreach ($possibleLocalBinaries as $localExec) {
17932 if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
17933 $caller = BinaryInstaller::determineBinaryCaller($localExec);
17934 $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
17935 break;
17936 }
17937 }
17938 }
17939
17940 if (substr($exec, 0, 5) === '@php ') {
17941 $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
17942 }
17943
17944 if (0 !== ($exitCode = $this->process->execute($exec))) {
17945 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
17946
17947 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
17948 }
17949 }
17950
17951 if ($event->isPropagationStopped()) {
17952 break;
17953 }
17954 }
17955
17956 $this->popEvent();
17957
17958 return $return;
17959 }
17960
17961 protected function getPhpExecCommand()
17962 {
17963 $finder = new PhpExecutableFinder();
17964 $phpPath = $finder->find();
17965 if (!$phpPath) {
17966 throw new \RuntimeException('Failed to locate PHP binary to execute '.$scriptName);
17967 }
17968
17969 $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
17970 $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
17971 $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
17972
17973 return ProcessExecutor::escape($phpPath) . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag;
17974 }
17975
17976
17977
17978
17979
17980
17981 protected function executeEventPhpScript($className, $methodName, Event $event)
17982 {
17983 $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
17984
17985 if ($this->io->isVerbose()) {
17986 $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
17987 } else {
17988 $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
17989 }
17990
17991 return $className::$methodName($event);
17992 }
17993
17994
17995
17996
17997
17998
17999 protected function checkListenerExpectedEvent($target, Event $event)
18000 {
18001 if (in_array($event->getName(), array(
18002 'init',
18003 'command',
18004 'pre-file-download',
18005 ), true)) {
18006 return $event;
18007 }
18008
18009 try {
18010 $reflected = new \ReflectionParameter($target, 0);
18011 } catch (\Exception $e) {
18012 return $event;
18013 }
18014
18015 $typehint = $reflected->getClass();
18016
18017 if (!$typehint instanceof \ReflectionClass) {
18018 return $event;
18019 }
18020
18021 $expected = $typehint->getName();
18022
18023
18024  if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
18025 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);
18026 $event = new \Composer\Script\CommandEvent(
18027 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(), $event->getArguments()
18028 );
18029 }
18030 if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
18031 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);
18032 $event = new \Composer\Script\PackageEvent(
18033 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
18034 $event->getPolicy(), $event->getPool(), $event->getInstalledRepo(), $event->getRequest(),
18035 $event->getOperations(), $event->getOperation()
18036 );
18037 }
18038 if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
18039 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);
18040 $event = new \Composer\Script\Event(
18041 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
18042 $event->getArguments(), $event->getFlags()
18043 );
18044 }
18045
18046 return $event;
18047 }
18048
18049 private function serializeCallback($cb)
18050 {
18051 if (is_array($cb) && count($cb) === 2) {
18052 if (is_object($cb[0])) {
18053 $cb[0] = get_class($cb[0]);
18054 }
18055 if (is_string($cb[0]) && is_string($cb[1])) {
18056 $cb = implode('::', $cb);
18057 }
18058 }
18059 if (is_string($cb)) {
18060 return $cb;
18061 }
18062
18063 return var_export($cb, true);
18064 }
18065
18066
18067
18068
18069
18070
18071
18072
18073 public function addListener($eventName, $listener, $priority = 0)
18074 {
18075 $this->listeners[$eventName][$priority][] = $listener;
18076 }
18077
18078
18079
18080
18081
18082
18083
18084
18085 public function addSubscriber(EventSubscriberInterface $subscriber)
18086 {
18087 foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
18088 if (is_string($params)) {
18089 $this->addListener($eventName, array($subscriber, $params));
18090 } elseif (is_string($params[0])) {
18091 $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
18092 } else {
18093 foreach ($params as $listener) {
18094 $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
18095 }
18096 }
18097 }
18098 }
18099
18100
18101
18102
18103
18104
18105
18106 protected function getListeners(Event $event)
18107 {
18108 $scriptListeners = $this->getScriptListeners($event);
18109
18110 if (!isset($this->listeners[$event->getName()][0])) {
18111 $this->listeners[$event->getName()][0] = array();
18112 }
18113 krsort($this->listeners[$event->getName()]);
18114
18115 $listeners = $this->listeners;
18116 $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
18117
18118 return call_user_func_array('array_merge', $listeners[$event->getName()]);
18119 }
18120
18121
18122
18123
18124
18125
18126
18127 public function hasEventListeners(Event $event)
18128 {
18129 $listeners = $this->getListeners($event);
18130
18131 return count($listeners) > 0;
18132 }
18133
18134
18135
18136
18137
18138
18139
18140 protected function getScriptListeners(Event $event)
18141 {
18142 $package = $this->composer->getPackage();
18143 $scripts = $package->getScripts();
18144
18145 if (empty($scripts[$event->getName()])) {
18146 return array();
18147 }
18148
18149 if ($this->loader) {
18150 $this->loader->unregister();
18151 }
18152
18153 $generator = $this->composer->getAutoloadGenerator();
18154 if ($event instanceof ScriptEvent) {
18155 $generator->setDevMode($event->isDevMode());
18156 }
18157
18158 $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
18159 $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
18160 $map = $generator->parseAutoloads($packageMap, $package);
18161 $this->loader = $generator->createLoader($map);
18162 $this->loader->register();
18163
18164 return $scripts[$event->getName()];
18165 }
18166
18167
18168
18169
18170
18171
18172
18173 protected function isPhpScript($callable)
18174 {
18175 return false === strpos($callable, ' ') && false !== strpos($callable, '::');
18176 }
18177
18178
18179
18180
18181
18182
18183
18184 protected function isComposerScript($callable)
18185 {
18186 return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5);
18187 }
18188
18189
18190
18191
18192
18193
18194
18195
18196 protected function pushEvent(Event $event)
18197 {
18198 $eventName = $event->getName();
18199 if (in_array($eventName, $this->eventStack)) {
18200 throw new \RuntimeException(sprintf("Circular call to script handler '%s' detected", $eventName));
18201 }
18202
18203 return array_push($this->eventStack, $eventName);
18204 }
18205
18206
18207
18208
18209
18210
18211 protected function popEvent()
18212 {
18213 return array_pop($this->eventStack);
18214 }
18215 }
18216 <?php
18217
18218
18219
18220
18221
18222
18223
18224
18225
18226
18227
18228 namespace Composer\EventDispatcher;
18229
18230
18231
18232
18233
18234
18235
18236
18237
18238
18239
18240
18241
18242 interface EventSubscriberInterface
18243 {
18244
18245
18246
18247
18248
18249
18250
18251
18252
18253
18254
18255
18256
18257
18258
18259
18260
18261
18262 public static function getSubscribedEvents();
18263 }
18264 <?php
18265
18266
18267
18268
18269
18270
18271
18272
18273
18274
18275
18276 namespace Composer\EventDispatcher;
18277
18278
18279
18280
18281 class ScriptExecutionException extends \RuntimeException
18282 {
18283 }
18284 <?php
18285
18286
18287
18288
18289
18290
18291
18292
18293
18294
18295
18296 namespace Composer\Exception;
18297
18298
18299
18300
18301 class NoSslException extends \RuntimeException
18302 {
18303 }
18304 <?php
18305
18306
18307
18308
18309
18310
18311
18312
18313
18314
18315
18316 namespace Composer;
18317
18318 use Composer\Config\JsonConfigSource;
18319 use Composer\Json\JsonFile;
18320 use Composer\IO\IOInterface;
18321 use Composer\Package\Archiver;
18322 use Composer\Package\Version\VersionGuesser;
18323 use Composer\Repository\RepositoryManager;
18324 use Composer\Repository\RepositoryFactory;
18325 use Composer\Repository\WritableRepositoryInterface;
18326 use Composer\Util\Filesystem;
18327 use Composer\Util\Platform;
18328 use Composer\Util\ProcessExecutor;
18329 use Composer\Util\RemoteFilesystem;
18330 use Composer\Util\Silencer;
18331 use Composer\Plugin\PluginEvents;
18332 use Composer\EventDispatcher\Event;
18333 use Seld\JsonLint\DuplicateKeyException;
18334 use Symfony\Component\Console\Formatter\OutputFormatter;
18335 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
18336 use Symfony\Component\Console\Output\ConsoleOutput;
18337 use Composer\EventDispatcher\EventDispatcher;
18338 use Composer\Autoload\AutoloadGenerator;
18339 use Composer\Package\Version\VersionParser;
18340 use Composer\Downloader\TransportException;
18341 use Seld\JsonLint\JsonParser;
18342
18343
18344
18345
18346
18347
18348
18349
18350
18351 class Factory
18352 {
18353
18354
18355
18356
18357 protected static function getHomeDir()
18358 {
18359 $home = getenv('COMPOSER_HOME');
18360 if ($home) {
18361 return $home;
18362 }
18363
18364 if (Platform::isWindows()) {
18365 if (!getenv('APPDATA')) {
18366 throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
18367 }
18368
18369 return rtrim(strtr(getenv('APPDATA'), '\\', '/'), '/') . '/Composer';
18370 }
18371
18372 $userDir = self::getUserDir();
18373 if (is_dir($userDir . '/.composer')) {
18374 return $userDir . '/.composer';
18375 }
18376
18377 if (self::useXdg()) {
18378
18379  $xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
18380
18381 return $xdgConfig . '/composer';
18382 }
18383
18384 return $userDir . '/.composer';
18385 }
18386
18387
18388
18389
18390
18391 protected static function getCacheDir($home)
18392 {
18393 $cacheDir = getenv('COMPOSER_CACHE_DIR');
18394 if ($cacheDir) {
18395 return $cacheDir;
18396 }
18397
18398 $homeEnv = getenv('COMPOSER_HOME');
18399 if ($homeEnv) {
18400 return $homeEnv . '/cache';
18401 }
18402
18403 if (Platform::isWindows()) {
18404 if ($cacheDir = getenv('LOCALAPPDATA')) {
18405 $cacheDir .= '/Composer';
18406 } else {
18407 $cacheDir = $home . '/cache';
18408 }
18409
18410 return rtrim(strtr($cacheDir, '\\', '/'), '/');
18411 }
18412
18413 $userDir = self::getUserDir();
18414 if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
18415 return $home . '/cache';
18416 }
18417
18418 if (self::useXdg()) {
18419 $xdgCache = getenv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
18420
18421 return $xdgCache . '/composer';
18422 }
18423
18424 return $home . '/cache';
18425 }
18426
18427
18428
18429
18430
18431 protected static function getDataDir($home)
18432 {
18433 $homeEnv = getenv('COMPOSER_HOME');
18434 if ($homeEnv) {
18435 return $homeEnv;
18436 }
18437
18438 if (Platform::isWindows()) {
18439 return strtr($home, '\\', '/');
18440 }
18441
18442 $userDir = self::getUserDir();
18443 if ($home !== $userDir . '/.composer' && self::useXdg()) {
18444 $xdgData = getenv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
18445
18446 return $xdgData . '/composer';
18447 }
18448
18449 return $home;
18450 }
18451
18452
18453
18454
18455
18456 public static function createConfig(IOInterface $io = null, $cwd = null)
18457 {
18458 $cwd = $cwd ?: getcwd();
18459
18460 $config = new Config(true, $cwd);
18461
18462
18463  $home = self::getHomeDir();
18464 $config->merge(array('config' => array(
18465 'home' => $home,
18466 'cache-dir' => self::getCacheDir($home),
18467 'data-dir' => self::getDataDir($home),
18468 )));
18469
18470 $htaccessProtect = (bool) $config->get('htaccess-protect');
18471 if ($htaccessProtect) {
18472
18473  
18474  
18475  $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
18476 foreach ($dirs as $dir) {
18477 if (!file_exists($dir . '/.htaccess')) {
18478 if (!is_dir($dir)) {
18479 Silencer::call('mkdir', $dir, 0777, true);
18480 }
18481 Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
18482 }
18483 }
18484 }
18485
18486
18487  $file = new JsonFile($config->get('home').'/config.json');
18488 if ($file->exists()) {
18489 if ($io && $io->isDebug()) {
18490 $io->writeError('Loading config file ' . $file->getPath());
18491 }
18492 $config->merge($file->read());
18493 }
18494 $config->setConfigSource(new JsonConfigSource($file));
18495
18496
18497  $file = new JsonFile($config->get('home').'/auth.json');
18498 if ($file->exists()) {
18499 if ($io && $io->isDebug()) {
18500 $io->writeError('Loading config file ' . $file->getPath());
18501 }
18502 $config->merge(array('config' => $file->read()));
18503 }
18504 $config->setAuthConfigSource(new JsonConfigSource($file, true));
18505
18506
18507  if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
18508 $authData = json_decode($composerAuthEnv, true);
18509
18510 if (null === $authData) {
18511 throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
18512 }
18513
18514 if ($io && $io->isDebug()) {
18515 $io->writeError('Loading auth config from COMPOSER_AUTH');
18516 }
18517 $config->merge(array('config' => $authData));
18518 }
18519
18520 return $config;
18521 }
18522
18523 public static function getComposerFile()
18524 {
18525 return trim(getenv('COMPOSER')) ?: './composer.json';
18526 }
18527
18528 public static function createAdditionalStyles()
18529 {
18530 return array(
18531 'highlight' => new OutputFormatterStyle('red'),
18532 'warning' => new OutputFormatterStyle('black', 'yellow'),
18533 );
18534 }
18535
18536
18537
18538
18539
18540
18541 public static function createOutput()
18542 {
18543 $styles = self::createAdditionalStyles();
18544 $formatter = new OutputFormatter(false, $styles);
18545
18546 return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
18547 }
18548
18549
18550
18551
18552 public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
18553 {
18554 return RepositoryFactory::defaultRepos($io, $config, $rm);
18555 }
18556
18557
18558
18559
18560
18561
18562
18563
18564
18565
18566
18567
18568
18569 public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
18570 {
18571 $cwd = $cwd ?: getcwd();
18572
18573
18574  if (null === $localConfig) {
18575 $localConfig = static::getComposerFile();
18576 }
18577
18578 if (is_string($localConfig)) {
18579 $composerFile = $localConfig;
18580
18581 $file = new JsonFile($localConfig, null, $io);
18582
18583 if (!$file->exists()) {
18584 if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
18585 $message = 'Composer could not find a composer.json file in '.$cwd;
18586 } else {
18587 $message = 'Composer could not find the config file: '.$localConfig;
18588 }
18589 $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section';
18590 throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
18591 }
18592
18593 $file->validateSchema(JsonFile::LAX_SCHEMA);
18594 $jsonParser = new JsonParser;
18595 try {
18596 $jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS);
18597 } catch (DuplicateKeyException $e) {
18598 $details = $e->getDetails();
18599 $io->writeError('<warning>Key '.$details['key'].' is a duplicate in '.$localConfig.' at line '.$details['line'].'</warning>');
18600 }
18601
18602 $localConfig = $file->read();
18603 }
18604
18605
18606  $config = static::createConfig($io, $cwd);
18607 $config->merge($localConfig);
18608 if (isset($composerFile)) {
18609 $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
18610 $config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
18611
18612 $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
18613 if ($localAuthFile->exists()) {
18614 $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
18615 $config->merge(array('config' => $localAuthFile->read()));
18616 $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
18617 }
18618 }
18619
18620 $vendorDir = $config->get('vendor-dir');
18621
18622
18623  $composer = new Composer();
18624 $composer->setConfig($config);
18625
18626 if ($fullLoad) {
18627
18628  $io->loadConfiguration($config);
18629 }
18630
18631 $rfs = self::createRemoteFilesystem($io, $config);
18632
18633
18634  $dispatcher = new EventDispatcher($composer, $io);
18635 $composer->setEventDispatcher($dispatcher);
18636
18637
18638  $rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
18639 $composer->setRepositoryManager($rm);
18640
18641
18642  $this->addLocalRepository($io, $rm, $vendorDir);
18643
18644
18645  
18646  if (!$fullLoad && !isset($localConfig['version'])) {
18647 $localConfig['version'] = '1.0.0';
18648 }
18649
18650
18651  $parser = new VersionParser;
18652 $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
18653 $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser);
18654 $package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
18655 $composer->setPackage($package);
18656
18657
18658  $im = $this->createInstallationManager();
18659 $composer->setInstallationManager($im);
18660
18661 if ($fullLoad) {
18662
18663  $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
18664 $composer->setDownloadManager($dm);
18665
18666
18667  $generator = new AutoloadGenerator($dispatcher, $io);
18668 $composer->setAutoloadGenerator($generator);
18669
18670
18671  $am = $this->createArchiveManager($config, $dm);
18672 $composer->setArchiveManager($am);
18673 }
18674
18675
18676  $this->createDefaultInstallers($im, $composer, $io);
18677
18678 if ($fullLoad) {
18679 $globalComposer = null;
18680 if (realpath($config->get('home')) !== $cwd) {
18681 $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
18682 }
18683
18684 $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
18685 $composer->setPluginManager($pm);
18686
18687 $pm->loadInstalledPlugins();
18688 }
18689
18690
18691  if ($fullLoad && isset($composerFile)) {
18692 $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
18693 ? substr($composerFile, 0, -4).'lock'
18694 : $composerFile . '.lock';
18695
18696 $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile));
18697 $composer->setLocker($locker);
18698 }
18699
18700 if ($fullLoad) {
18701 $initEvent = new Event(PluginEvents::INIT);
18702 $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent);
18703
18704
18705  
18706  if ($rm->getLocalRepository()) {
18707 $this->purgePackages($rm->getLocalRepository(), $im);
18708 }
18709 }
18710
18711 return $composer;
18712 }
18713
18714
18715
18716
18717
18718
18719 public static function createGlobal(IOInterface $io, $disablePlugins = false)
18720 {
18721 $factory = new static();
18722
18723 return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, true);
18724 }
18725
18726
18727
18728
18729
18730 protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir)
18731 {
18732 $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io)));
18733 }
18734
18735
18736
18737
18738
18739 protected function createGlobalComposer(IOInterface $io, Config $config, $disablePlugins, $fullLoad = false)
18740 {
18741 $composer = null;
18742 try {
18743 $composer = $this->createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad);
18744 } catch (\Exception $e) {
18745 $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
18746 }
18747
18748 return $composer;
18749 }
18750
18751
18752
18753
18754
18755
18756
18757 public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
18758 {
18759 $cache = null;
18760 if ($config->get('cache-files-ttl') > 0) {
18761 $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
18762 }
18763
18764 $dm = new Downloader\DownloadManager($io);
18765 switch ($preferred = $config->get('preferred-install')) {
18766 case 'dist':
18767 $dm->setPreferDist(true);
18768 break;
18769 case 'source':
18770 $dm->setPreferSource(true);
18771 break;
18772 case 'auto':
18773 default:
18774
18775  break;
18776 }
18777
18778 if (is_array($preferred)) {
18779 $dm->setPreferences($preferred);
18780 }
18781
18782 $executor = new ProcessExecutor($io);
18783 $fs = new Filesystem($executor);
18784
18785 $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs));
18786 $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs));
18787 $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $executor, $fs));
18788 $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs));
18789 $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
18790 $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18791 $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18792 $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18793 $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18794 $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18795 $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18796 $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18797 $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18798
18799 return $dm;
18800 }
18801
18802
18803
18804
18805
18806
18807 public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
18808 {
18809 if (null === $dm) {
18810 $io = new IO\NullIO();
18811 $io->loadConfiguration($config);
18812 $dm = $this->createDownloadManager($io, $config);
18813 }
18814
18815 $am = new Archiver\ArchiveManager($dm);
18816 $am->addArchiver(new Archiver\ZipArchiver);
18817 $am->addArchiver(new Archiver\PharArchiver);
18818
18819 return $am;
18820 }
18821
18822
18823
18824
18825
18826
18827
18828
18829 protected function createPluginManager(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
18830 {
18831 return new Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
18832 }
18833
18834
18835
18836
18837 protected function createInstallationManager()
18838 {
18839 return new Installer\InstallationManager();
18840 }
18841
18842
18843
18844
18845
18846
18847 protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
18848 {
18849 $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
18850 $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
18851 $im->addInstaller(new Installer\PluginInstaller($io, $composer));
18852 $im->addInstaller(new Installer\MetapackageInstaller($io));
18853 }
18854
18855
18856
18857
18858
18859 protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
18860 {
18861 foreach ($repo->getPackages() as $package) {
18862 if (!$im->isPackageInstalled($repo, $package)) {
18863 $repo->removePackage($package);
18864 }
18865 }
18866 }
18867
18868
18869
18870
18871
18872
18873
18874
18875 public static function create(IOInterface $io, $config = null, $disablePlugins = false)
18876 {
18877 $factory = new static();
18878
18879 return $factory->createComposer($io, $config, $disablePlugins);
18880 }
18881
18882
18883
18884
18885
18886
18887
18888 public static function createRemoteFilesystem(IOInterface $io, Config $config = null, $options = array())
18889 {
18890 static $warned = false;
18891 $disableTls = false;
18892 if ($config && $config->get('disable-tls') === true) {
18893 if (!$warned) {
18894 $io->write('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
18895 }
18896 $warned = true;
18897 $disableTls = true;
18898 } elseif (!extension_loaded('openssl')) {
18899 throw new Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. '
18900 . '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.');
18901 }
18902 $remoteFilesystemOptions = array();
18903 if ($disableTls === false) {
18904 if ($config && $config->get('cafile')) {
18905 $remoteFilesystemOptions['ssl']['cafile'] = $config->get('cafile');
18906 }
18907 if ($config && $config->get('capath')) {
18908 $remoteFilesystemOptions['ssl']['capath'] = $config->get('capath');
18909 }
18910 $remoteFilesystemOptions = array_replace_recursive($remoteFilesystemOptions, $options);
18911 }
18912 try {
18913 $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);
18914 } catch (TransportException $e) {
18915 if (false !== strpos($e->getMessage(), 'cafile')) {
18916 $io->write('<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>');
18917 $io->write('<error>A valid CA certificate file is required for SSL/TLS protection.</error>');
18918 if (PHP_VERSION_ID < 50600) {
18919 $io->write('<error>It is recommended you upgrade to PHP 5.6+ which can detect your system CA file automatically.</error>');
18920 }
18921 $io->write('<error>You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.</error>');
18922 }
18923 throw $e;
18924 }
18925
18926 return $remoteFilesystem;
18927 }
18928
18929
18930
18931
18932 private static function useXdg()
18933 {
18934 foreach (array_keys($_SERVER) as $key) {
18935 if (substr($key, 0, 4) === 'XDG_') {
18936 return true;
18937 }
18938 }
18939
18940 return false;
18941 }
18942
18943
18944
18945
18946
18947 private static function getUserDir()
18948 {
18949 $home = getenv('HOME');
18950 if (!$home) {
18951 throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
18952 }
18953
18954 return rtrim(strtr($home, '\\', '/'), '/');
18955 }
18956 }
18957 <?php
18958
18959
18960
18961
18962
18963
18964
18965
18966
18967
18968
18969 namespace Composer\IO;
18970
18971 use Composer\Config;
18972 use Composer\Util\ProcessExecutor;
18973 use Psr\Log\LoggerInterface;
18974 use Psr\Log\LogLevel;
18975
18976 abstract class BaseIO implements IOInterface, LoggerInterface
18977 {
18978 protected $authentications = array();
18979
18980
18981
18982
18983 public function getAuthentications()
18984 {
18985 return $this->authentications;
18986 }
18987
18988
18989
18990
18991 public function hasAuthentication($repositoryName)
18992 {
18993 return isset($this->authentications[$repositoryName]);
18994 }
18995
18996
18997
18998
18999 public function getAuthentication($repositoryName)
19000 {
19001 if (isset($this->authentications[$repositoryName])) {
19002 return $this->authentications[$repositoryName];
19003 }
19004
19005 return array('username' => null, 'password' => null);
19006 }
19007
19008
19009
19010
19011 public function setAuthentication($repositoryName, $username, $password = null)
19012 {
19013 $this->authentications[$repositoryName] = array('username' => $username, 'password' => $password);
19014 }
19015
19016
19017
19018
19019
19020
19021
19022
19023 protected function checkAndSetAuthentication($repositoryName, $username, $password = null)
19024 {
19025 if ($this->hasAuthentication($repositoryName)) {
19026 $auth = $this->getAuthentication($repositoryName);
19027 if ($auth['username'] === $username && $auth['password'] === $password) {
19028 return;
19029 }
19030
19031 $this->writeError(
19032 sprintf(
19033 "<warning>Warning: You should avoid overwriting already defined auth settings for %s.</warning>",
19034 $repositoryName
19035 )
19036 );
19037 }
19038 $this->setAuthentication($repositoryName, $username, $password);
19039 }
19040
19041
19042
19043
19044 public function loadConfiguration(Config $config)
19045 {
19046 $bitbucketOauth = $config->get('bitbucket-oauth') ?: array();
19047 $githubOauth = $config->get('github-oauth') ?: array();
19048 $gitlabOauth = $config->get('gitlab-oauth') ?: array();
19049 $gitlabToken = $config->get('gitlab-token') ?: array();
19050 $httpBasic = $config->get('http-basic') ?: array();
19051
19052
19053
19054 foreach ($bitbucketOauth as $domain => $cred) {
19055 $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']);
19056 }
19057
19058 foreach ($githubOauth as $domain => $token) {
19059 if (!preg_match('{^[.a-z0-9]+$}', $token)) {
19060 throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
19061 }
19062 $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic');
19063 }
19064
19065 foreach ($gitlabOauth as $domain => $token) {
19066 $this->checkAndSetAuthentication($domain, $token, 'oauth2');
19067 }
19068
19069 foreach ($gitlabToken as $domain => $token) {
19070 $this->checkAndSetAuthentication($domain, $token, 'private-token');
19071 }
19072
19073
19074  foreach ($httpBasic as $domain => $cred) {
19075 $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
19076 }
19077
19078
19079  ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
19080 }
19081
19082
19083
19084
19085
19086
19087
19088
19089 public function emergency($message, array $context = array())
19090 {
19091 return $this->log(LogLevel::EMERGENCY, $message, $context);
19092 }
19093
19094
19095
19096
19097
19098
19099
19100
19101
19102
19103
19104 public function alert($message, array $context = array())
19105 {
19106 return $this->log(LogLevel::ALERT, $message, $context);
19107 }
19108
19109
19110
19111
19112
19113
19114
19115
19116
19117
19118 public function critical($message, array $context = array())
19119 {
19120 return $this->log(LogLevel::CRITICAL, $message, $context);
19121 }
19122
19123
19124
19125
19126
19127
19128
19129
19130
19131 public function error($message, array $context = array())
19132 {
19133 return $this->log(LogLevel::ERROR, $message, $context);
19134 }
19135
19136
19137
19138
19139
19140
19141
19142
19143
19144
19145
19146 public function warning($message, array $context = array())
19147 {
19148 return $this->log(LogLevel::WARNING, $message, $context);
19149 }
19150
19151
19152
19153
19154
19155
19156
19157
19158 public function notice($message, array $context = array())
19159 {
19160 return $this->log(LogLevel::NOTICE, $message, $context);
19161 }
19162
19163
19164
19165
19166
19167
19168
19169
19170
19171
19172 public function info($message, array $context = array())
19173 {
19174 return $this->log(LogLevel::INFO, $message, $context);
19175 }
19176
19177
19178
19179
19180
19181
19182
19183
19184 public function debug($message, array $context = array())
19185 {
19186 return $this->log(LogLevel::DEBUG, $message, $context);
19187 }
19188
19189
19190
19191
19192
19193
19194
19195
19196
19197 public function log($level, $message, array $context = array())
19198 {
19199 if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
19200 $this->writeError('<error>'.$message.'</error>', true, self::NORMAL);
19201 } elseif ($level === LogLevel::WARNING) {
19202 $this->writeError('<warning>'.$message.'</warning>', true, self::NORMAL);
19203 } elseif ($level === LogLevel::NOTICE) {
19204 $this->writeError('<info>'.$message.'</info>', true, self::VERBOSE);
19205 } elseif ($level === LogLevel::INFO) {
19206 $this->writeError('<info>'.$message.'</info>', true, self::VERY_VERBOSE);
19207 } else {
19208 $this->writeError($message, true, self::DEBUG);
19209 }
19210 }
19211 }
19212 <?php
19213
19214
19215
19216
19217
19218
19219
19220
19221
19222
19223
19224 namespace Composer\IO;
19225
19226 use Symfony\Component\Console\Output\StreamOutput;
19227 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
19228 use Symfony\Component\Console\Input\StringInput;
19229 use Symfony\Component\Console\Helper\HelperSet;
19230
19231
19232
19233
19234 class BufferIO extends ConsoleIO
19235 {
19236
19237
19238
19239
19240
19241 public function __construct($input = '', $verbosity = StreamOutput::VERBOSITY_NORMAL, OutputFormatterInterface $formatter = null)
19242 {
19243 $input = new StringInput($input);
19244 $input->setInteractive(false);
19245
19246 $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
19247
19248 parent::__construct($input, $output, new HelperSet(array()));
19249 }
19250
19251 public function getOutput()
19252 {
19253 fseek($this->output->getStream(), 0);
19254
19255 $output = stream_get_contents($this->output->getStream());
19256
19257 $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) {
19258 $pre = strip_tags($matches[1]);
19259
19260 if (strlen($pre) === strlen($matches[2])) {
19261 return '';
19262 }
19263
19264
19265  return rtrim($matches[1])."\n";
19266 }, $output);
19267
19268 return $output;
19269 }
19270 }
19271 <?php
19272
19273
19274
19275
19276
19277
19278
19279
19280
19281
19282
19283 namespace Composer\IO;
19284
19285 use Composer\Question\StrictConfirmationQuestion;
19286 use Symfony\Component\Console\Helper\HelperSet;
19287 use Symfony\Component\Console\Input\InputInterface;
19288 use Symfony\Component\Console\Output\ConsoleOutputInterface;
19289 use Symfony\Component\Console\Output\OutputInterface;
19290 use Symfony\Component\Console\Question\ChoiceQuestion;
19291 use Symfony\Component\Console\Question\Question;
19292
19293
19294
19295
19296
19297
19298
19299 class ConsoleIO extends BaseIO
19300 {
19301
19302 protected $input;
19303
19304 protected $output;
19305
19306 protected $helperSet;
19307
19308 protected $lastMessage;
19309
19310 protected $lastMessageErr;
19311
19312
19313 private $startTime;
19314
19315 private $verbosityMap;
19316
19317
19318
19319
19320
19321
19322
19323
19324 public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
19325 {
19326 $this->input = $input;
19327 $this->output = $output;
19328 $this->helperSet = $helperSet;
19329 $this->verbosityMap = array(
19330 self::QUIET => OutputInterface::VERBOSITY_QUIET,
19331 self::NORMAL => OutputInterface::VERBOSITY_NORMAL,
19332 self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
19333 self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
19334 self::DEBUG => OutputInterface::VERBOSITY_DEBUG,
19335 );
19336 }
19337
19338
19339
19340
19341 public function enableDebugging($startTime)
19342 {
19343 $this->startTime = $startTime;
19344 }
19345
19346
19347
19348
19349 public function isInteractive()
19350 {
19351 return $this->input->isInteractive();
19352 }
19353
19354
19355
19356
19357 public function isDecorated()
19358 {
19359 return $this->output->isDecorated();
19360 }
19361
19362
19363
19364
19365 public function isVerbose()
19366 {
19367 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
19368 }
19369
19370
19371
19372
19373 public function isVeryVerbose()
19374 {
19375 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
19376 }
19377
19378
19379
19380
19381 public function isDebug()
19382 {
19383 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
19384 }
19385
19386
19387
19388
19389 public function write($messages, $newline = true, $verbosity = self::NORMAL)
19390 {
19391 $this->doWrite($messages, $newline, false, $verbosity);
19392 }
19393
19394
19395
19396
19397 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
19398 {
19399 $this->doWrite($messages, $newline, true, $verbosity);
19400 }
19401
19402
19403
19404
19405
19406
19407
19408 private function doWrite($messages, $newline, $stderr, $verbosity)
19409 {
19410 $sfVerbosity = $this->verbosityMap[$verbosity];
19411 if ($sfVerbosity > $this->output->getVerbosity()) {
19412 return;
19413 }
19414
19415
19416  
19417  
19418  if (OutputInterface::VERBOSITY_QUIET === 0) {
19419 $sfVerbosity = OutputInterface::OUTPUT_NORMAL;
19420 }
19421
19422 if (null !== $this->startTime) {
19423 $memoryUsage = memory_get_usage() / 1024 / 1024;
19424 $timeSpent = microtime(true) - $this->startTime;
19425 $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
19426 return sprintf('[%.1fMB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
19427 }, (array) $messages);
19428 }
19429
19430 if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
19431 $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
19432 $this->lastMessageErr = implode($newline ? "\n" : '', (array) $messages);
19433
19434 return;
19435 }
19436
19437 $this->output->write($messages, $newline, $sfVerbosity);
19438 $this->lastMessage = implode($newline ? "\n" : '', (array) $messages);
19439 }
19440
19441
19442
19443
19444 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19445 {
19446 $this->doOverwrite($messages, $newline, $size, false, $verbosity);
19447 }
19448
19449
19450
19451
19452 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19453 {
19454 $this->doOverwrite($messages, $newline, $size, true, $verbosity);
19455 }
19456
19457
19458
19459
19460
19461
19462
19463
19464 private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
19465 {
19466
19467  $messages = implode($newline ? "\n" : '', (array) $messages);
19468
19469
19470  if (!isset($size)) {
19471
19472  $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
19473 }
19474
19475  $this->doWrite(str_repeat("\x08", $size), false, $stderr, $verbosity);
19476
19477
19478  $this->doWrite($messages, false, $stderr, $verbosity);
19479
19480
19481  
19482  
19483  $fill = $size - strlen(strip_tags($messages));
19484 if ($fill > 0) {
19485
19486  $this->doWrite(str_repeat(' ', $fill), false, $stderr, $verbosity);
19487
19488  $this->doWrite(str_repeat("\x08", $fill), false, $stderr, $verbosity);
19489 }
19490
19491 if ($newline) {
19492 $this->doWrite('', true, $stderr, $verbosity);
19493 }
19494
19495 if ($stderr) {
19496 $this->lastMessageErr = $messages;
19497 } else {
19498 $this->lastMessage = $messages;
19499 }
19500 }
19501
19502
19503
19504
19505 public function ask($question, $default = null)
19506 {
19507
19508 $helper = $this->helperSet->get('question');
19509 $question = new Question($question, $default);
19510
19511 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19512 }
19513
19514
19515
19516
19517 public function askConfirmation($question, $default = true)
19518 {
19519
19520 $helper = $this->helperSet->get('question');
19521 $question = new StrictConfirmationQuestion($question, $default);
19522
19523 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19524 }
19525
19526
19527
19528
19529 public function askAndValidate($question, $validator, $attempts = null, $default = null)
19530 {
19531
19532 $helper = $this->helperSet->get('question');
19533 $question = new Question($question, $default);
19534 $question->setValidator($validator);
19535 $question->setMaxAttempts($attempts);
19536
19537 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19538 }
19539
19540
19541
19542
19543 public function askAndHideAnswer($question)
19544 {
19545 $this->writeError($question, false);
19546
19547 return \Seld\CliPrompt\CliPrompt::hiddenPrompt(true);
19548 }
19549
19550
19551
19552
19553 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
19554 {
19555
19556 $helper = $this->helperSet->get('question');
19557 $question = new ChoiceQuestion($question, $choices, $default);
19558 $question->setMaxAttempts($attempts ?: null); 
19559  $question->setErrorMessage($errorMessage);
19560 $question->setMultiselect($multiselect);
19561
19562 $result = $helper->ask($this->input, $this->getErrorOutput(), $question);
19563
19564 $results = array();
19565 foreach ($choices as $index => $choice) {
19566 if (in_array($choice, $result, true)) {
19567 $results[] = (string) $index;
19568 }
19569 }
19570
19571 return $results;
19572 }
19573
19574
19575
19576
19577 private function getErrorOutput()
19578 {
19579 if ($this->output instanceof ConsoleOutputInterface) {
19580 return $this->output->getErrorOutput();
19581 }
19582
19583 return $this->output;
19584 }
19585 }
19586 <?php
19587
19588
19589
19590
19591
19592
19593
19594
19595
19596
19597
19598 namespace Composer\IO;
19599
19600 use Composer\Config;
19601
19602
19603
19604
19605
19606
19607 interface IOInterface
19608 {
19609 const QUIET = 1;
19610 const NORMAL = 2;
19611 const VERBOSE = 4;
19612 const VERY_VERBOSE = 8;
19613 const DEBUG = 16;
19614
19615
19616
19617
19618
19619
19620 public function isInteractive();
19621
19622
19623
19624
19625
19626
19627 public function isVerbose();
19628
19629
19630
19631
19632
19633
19634 public function isVeryVerbose();
19635
19636
19637
19638
19639
19640
19641 public function isDebug();
19642
19643
19644
19645
19646
19647
19648 public function isDecorated();
19649
19650
19651
19652
19653
19654
19655
19656
19657 public function write($messages, $newline = true, $verbosity = self::NORMAL);
19658
19659
19660
19661
19662
19663
19664
19665
19666 public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
19667
19668
19669
19670
19671
19672
19673
19674
19675
19676 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
19677
19678
19679
19680
19681
19682
19683
19684
19685
19686 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
19687
19688
19689
19690
19691
19692
19693
19694
19695
19696
19697 public function ask($question, $default = null);
19698
19699
19700
19701
19702
19703
19704
19705
19706
19707
19708
19709 public function askConfirmation($question, $default = true);
19710
19711
19712
19713
19714
19715
19716
19717
19718
19719
19720
19721
19722
19723
19724
19725
19726 public function askAndValidate($question, $validator, $attempts = null, $default = null);
19727
19728
19729
19730
19731
19732
19733
19734
19735 public function askAndHideAnswer($question);
19736
19737
19738
19739
19740
19741
19742
19743
19744
19745
19746
19747
19748
19749
19750 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
19751
19752
19753
19754
19755
19756
19757 public function getAuthentications();
19758
19759
19760
19761
19762
19763
19764
19765
19766 public function hasAuthentication($repositoryName);
19767
19768
19769
19770
19771
19772
19773
19774
19775 public function getAuthentication($repositoryName);
19776
19777
19778
19779
19780
19781
19782
19783
19784 public function setAuthentication($repositoryName, $username, $password = null);
19785
19786
19787
19788
19789
19790
19791 public function loadConfiguration(Config $config);
19792 }
19793 <?php
19794
19795
19796
19797
19798
19799
19800
19801
19802
19803
19804
19805 namespace Composer\IO;
19806
19807
19808
19809
19810
19811
19812 class NullIO extends BaseIO
19813 {
19814
19815
19816
19817 public function isInteractive()
19818 {
19819 return false;
19820 }
19821
19822
19823
19824
19825 public function isVerbose()
19826 {
19827 return false;
19828 }
19829
19830
19831
19832
19833 public function isVeryVerbose()
19834 {
19835 return false;
19836 }
19837
19838
19839
19840
19841 public function isDebug()
19842 {
19843 return false;
19844 }
19845
19846
19847
19848
19849 public function isDecorated()
19850 {
19851 return false;
19852 }
19853
19854
19855
19856
19857 public function write($messages, $newline = true, $verbosity = self::NORMAL)
19858 {
19859 }
19860
19861
19862
19863
19864 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
19865 {
19866 }
19867
19868
19869
19870
19871 public function overwrite($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
19872 {
19873 }
19874
19875
19876
19877
19878 public function overwriteError($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
19879 {
19880 }
19881
19882
19883
19884
19885 public function ask($question, $default = null)
19886 {
19887 return $default;
19888 }
19889
19890
19891
19892
19893 public function askConfirmation($question, $default = true)
19894 {
19895 return $default;
19896 }
19897
19898
19899
19900
19901 public function askAndValidate($question, $validator, $attempts = false, $default = null)
19902 {
19903 return $default;
19904 }
19905
19906
19907
19908
19909 public function askAndHideAnswer($question)
19910 {
19911 return null;
19912 }
19913
19914
19915
19916
19917 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
19918 {
19919 return $default;
19920 }
19921 }
19922 <?php
19923
19924
19925
19926
19927
19928
19929
19930
19931
19932
19933
19934 namespace Composer;
19935
19936 use Composer\Autoload\AutoloadGenerator;
19937 use Composer\DependencyResolver\DefaultPolicy;
19938 use Composer\DependencyResolver\Operation\UpdateOperation;
19939 use Composer\DependencyResolver\Operation\InstallOperation;
19940 use Composer\DependencyResolver\Operation\UninstallOperation;
19941 use Composer\DependencyResolver\Operation\OperationInterface;
19942 use Composer\DependencyResolver\PolicyInterface;
19943 use Composer\DependencyResolver\Pool;
19944 use Composer\DependencyResolver\Request;
19945 use Composer\DependencyResolver\Rule;
19946 use Composer\DependencyResolver\Solver;
19947 use Composer\DependencyResolver\SolverProblemsException;
19948 use Composer\Downloader\DownloadManager;
19949 use Composer\EventDispatcher\EventDispatcher;
19950 use Composer\Installer\InstallationManager;
19951 use Composer\Installer\InstallerEvents;
19952 use Composer\Installer\NoopInstaller;
19953 use Composer\Installer\SuggestedPackagesReporter;
19954 use Composer\IO\IOInterface;
19955 use Composer\Package\AliasPackage;
19956 use Composer\Package\CompletePackage;
19957 use Composer\Package\Link;
19958 use Composer\Package\Loader\ArrayLoader;
19959 use Composer\Package\Dumper\ArrayDumper;
19960 use Composer\Semver\Constraint\Constraint;
19961 use Composer\Package\Locker;
19962 use Composer\Package\PackageInterface;
19963 use Composer\Package\RootPackageInterface;
19964 use Composer\Repository\CompositeRepository;
19965 use Composer\Repository\InstalledArrayRepository;
19966 use Composer\Repository\PlatformRepository;
19967 use Composer\Repository\RepositoryInterface;
19968 use Composer\Repository\RepositoryManager;
19969 use Composer\Repository\WritableRepositoryInterface;
19970 use Composer\Script\ScriptEvents;
19971
19972
19973
19974
19975
19976
19977
19978 class Installer
19979 {
19980
19981
19982
19983 protected $io;
19984
19985
19986
19987
19988 protected $config;
19989
19990
19991
19992
19993 protected $package;
19994
19995
19996
19997
19998 protected $downloadManager;
19999
20000
20001
20002
20003 protected $repositoryManager;
20004
20005
20006
20007
20008 protected $locker;
20009
20010
20011
20012
20013 protected $installationManager;
20014
20015
20016
20017
20018 protected $eventDispatcher;
20019
20020
20021
20022
20023 protected $autoloadGenerator;
20024
20025 protected $preferSource = false;
20026 protected $preferDist = false;
20027 protected $optimizeAutoloader = false;
20028 protected $classMapAuthoritative = false;
20029 protected $apcuAutoloader = false;
20030 protected $devMode = false;
20031 protected $dryRun = false;
20032 protected $verbose = false;
20033 protected $update = false;
20034 protected $dumpAutoloader = true;
20035 protected $runScripts = true;
20036 protected $ignorePlatformReqs = false;
20037 protected $preferStable = false;
20038 protected $preferLowest = false;
20039 protected $skipSuggest = false;
20040 protected $writeLock = true;
20041 protected $executeOperations = true;
20042
20043
20044
20045
20046
20047
20048 protected $updateWhitelist = null;
20049 protected $whitelistDependencies = false; 
20050  protected $whitelistAllDependencies = false;
20051
20052
20053
20054
20055 protected $suggestedPackagesReporter;
20056
20057
20058
20059
20060 protected $additionalInstalledRepository;
20061
20062
20063
20064
20065
20066
20067
20068
20069
20070
20071
20072
20073
20074
20075 public function __construct(IOInterface $io, Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
20076 {
20077 $this->io = $io;
20078 $this->config = $config;
20079 $this->package = $package;
20080 $this->downloadManager = $downloadManager;
20081 $this->repositoryManager = $repositoryManager;
20082 $this->locker = $locker;
20083 $this->installationManager = $installationManager;
20084 $this->eventDispatcher = $eventDispatcher;
20085 $this->autoloadGenerator = $autoloadGenerator;
20086 }
20087
20088
20089
20090
20091
20092
20093
20094 public function run()
20095 {
20096
20097  
20098  
20099  
20100  gc_collect_cycles();
20101 gc_disable();
20102
20103
20104  if (!$this->update && !$this->locker->isLocked()) {
20105 $this->update = true;
20106 }
20107
20108 if ($this->dryRun) {
20109 $this->verbose = true;
20110 $this->runScripts = false;
20111 $this->executeOperations = false;
20112 $this->writeLock = false;
20113 $this->dumpAutoloader = false;
20114 $this->installationManager->addInstaller(new NoopInstaller);
20115 $this->mockLocalRepositories($this->repositoryManager);
20116 }
20117
20118 if ($this->runScripts) {
20119 $devMode = (int) $this->devMode;
20120 putenv("COMPOSER_DEV_MODE=$devMode");
20121
20122
20123  $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
20124 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
20125 }
20126
20127 $this->downloadManager->setPreferSource($this->preferSource);
20128 $this->downloadManager->setPreferDist($this->preferDist);
20129
20130
20131  $localRepo = $this->repositoryManager->getLocalRepository();
20132 if ($this->update) {
20133 $platformOverrides = $this->config->get('platform') ?: array();
20134 } else {
20135 $platformOverrides = $this->locker->getPlatformOverrides();
20136 }
20137 $platformRepo = new PlatformRepository(array(), $platformOverrides);
20138 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
20139
20140 $aliases = $this->getRootAliases();
20141 $this->aliasPlatformPackages($platformRepo, $aliases);
20142
20143 if (!$this->suggestedPackagesReporter) {
20144 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
20145 }
20146
20147 try {
20148 list($res, $devPackages) = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases);
20149 if ($res !== 0) {
20150 return $res;
20151 }
20152 } catch (\Exception $e) {
20153 if ($this->executeOperations) {
20154 $this->installationManager->notifyInstalls($this->io);
20155 }
20156
20157 throw $e;
20158 }
20159 if ($this->executeOperations) {
20160 $this->installationManager->notifyInstalls($this->io);
20161 }
20162
20163
20164  if ($this->devMode && !$this->skipSuggest) {
20165 $this->suggestedPackagesReporter->output($installedRepo);
20166 }
20167
20168
20169  foreach ($localRepo->getPackages() as $package) {
20170 if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
20171 continue;
20172 }
20173
20174 $replacement = (is_string($package->getReplacementPackage()))
20175 ? 'Use ' . $package->getReplacementPackage() . ' instead'
20176 : 'No replacement was suggested';
20177
20178 $this->io->writeError(
20179 sprintf(
20180 "<warning>Package %s is abandoned, you should avoid using it. %s.</warning>",
20181 $package->getPrettyName(),
20182 $replacement
20183 )
20184 );
20185 }
20186
20187
20188  if ($this->update && $this->writeLock) {
20189 $localRepo->reload();
20190
20191 $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
20192 $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires());
20193
20194 $updatedLock = $this->locker->setLockData(
20195 array_diff($localRepo->getCanonicalPackages(), $devPackages),
20196 $devPackages,
20197 $platformReqs,
20198 $platformDevReqs,
20199 $aliases,
20200 $this->package->getMinimumStability(),
20201 $this->package->getStabilityFlags(),
20202 $this->preferStable || $this->package->getPreferStable(),
20203 $this->preferLowest,
20204 $this->config->get('platform') ?: array()
20205 );
20206 if ($updatedLock) {
20207 $this->io->writeError('<info>Writing lock file</info>');
20208 }
20209 }
20210
20211 if ($this->dumpAutoloader) {
20212
20213  if ($this->optimizeAutoloader) {
20214 $this->io->writeError('<info>Generating optimized autoload files</info>');
20215 } else {
20216 $this->io->writeError('<info>Generating autoload files</info>');
20217 }
20218
20219 $this->autoloadGenerator->setDevMode($this->devMode);
20220 $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
20221 $this->autoloadGenerator->setApcu($this->apcuAutoloader);
20222 $this->autoloadGenerator->setRunScripts($this->runScripts);
20223 $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
20224 }
20225
20226 if ($this->executeOperations) {
20227
20228  foreach ($localRepo->getPackages() as $package) {
20229 $this->installationManager->ensureBinariesPresence($package);
20230 }
20231
20232 $vendorDir = $this->config->get('vendor-dir');
20233 if (is_dir($vendorDir)) {
20234
20235  
20236  @touch($vendorDir);
20237 }
20238 }
20239
20240 if ($this->runScripts) {
20241
20242  $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
20243 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
20244 }
20245
20246
20247  if (!defined('HHVM_VERSION')) {
20248 gc_enable();
20249 }
20250
20251 return 0;
20252 }
20253
20254
20255
20256
20257
20258
20259
20260
20261 protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases)
20262 {
20263
20264  $lockedRepository = null;
20265 $repositories = null;
20266
20267
20268  
20269  
20270  if (!$this->update || (!empty($this->updateWhitelist) && $this->locker->isLocked())) {
20271 try {
20272 $lockedRepository = $this->locker->getLockedRepository($this->devMode);
20273 } catch (\RuntimeException $e) {
20274
20275  if ($this->package->getDevRequires()) {
20276 throw $e;
20277 }
20278
20279  $lockedRepository = $this->locker->getLockedRepository();
20280 }
20281 }
20282
20283 $this->whitelistUpdateDependencies(
20284 $lockedRepository ?: $localRepo,
20285 $this->package->getRequires(),
20286 $this->package->getDevRequires()
20287 );
20288
20289 $this->io->writeError('<info>Loading composer repositories with package information</info>');
20290
20291
20292  $policy = $this->createPolicy();
20293 $pool = $this->createPool($this->update ? null : $lockedRepository);
20294 $pool->addRepository($installedRepo, $aliases);
20295 if ($this->update) {
20296 $repositories = $this->repositoryManager->getRepositories();
20297 foreach ($repositories as $repository) {
20298 $pool->addRepository($repository, $aliases);
20299 }
20300 }
20301
20302  
20303  
20304  if ($lockedRepository) {
20305 $pool->addRepository($lockedRepository, $aliases);
20306 }
20307
20308
20309  $request = $this->createRequest($this->package, $platformRepo);
20310
20311 if ($this->update) {
20312
20313  $removedUnstablePackages = array();
20314 foreach ($localRepo->getPackages() as $package) {
20315 if (
20316 !$pool->isPackageAcceptable($package->getNames(), $package->getStability())
20317 && $this->installationManager->isPackageInstalled($localRepo, $package)
20318 ) {
20319 $removedUnstablePackages[$package->getName()] = true;
20320 $request->remove($package->getName(), new Constraint('=', $package->getVersion()));
20321 }
20322 }
20323
20324 $this->io->writeError('<info>Updating dependencies'.($this->devMode ? ' (including require-dev)' : '').'</info>');
20325
20326 $request->updateAll();
20327
20328 $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
20329
20330 foreach ($links as $link) {
20331 $request->install($link->getTarget(), $link->getConstraint());
20332 }
20333
20334
20335  
20336  if ($this->updateWhitelist) {
20337 $currentPackages = $this->getCurrentPackages($installedRepo);
20338
20339
20340  $candidates = array();
20341 foreach ($links as $link) {
20342 $candidates[$link->getTarget()] = true;
20343 $rootRequires[$link->getTarget()] = $link;
20344 }
20345 foreach ($currentPackages as $package) {
20346 $candidates[$package->getName()] = true;
20347 }
20348
20349
20350  foreach ($candidates as $candidate => $dummy) {
20351 foreach ($currentPackages as $curPackage) {
20352 if ($curPackage->getName() === $candidate) {
20353 if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
20354 $constraint = new Constraint('=', $curPackage->getVersion());
20355 $description = $this->locker->isLocked() ? '(locked at' : '(installed at';
20356 $requiredAt = isset($rootRequires[$candidate]) ? ', required as ' . $rootRequires[$candidate]->getPrettyConstraint() : '';
20357 $constraint->setPrettyString($description . ' ' . $curPackage->getPrettyVersion() . $requiredAt . ')');
20358 $request->install($curPackage->getName(), $constraint);
20359 }
20360 break;
20361 }
20362 }
20363 }
20364 }
20365 } else {
20366 $this->io->writeError('<info>Installing dependencies'.($this->devMode ? ' (including require-dev)' : '').' from lock file</info>');
20367
20368 if (!$this->locker->isFresh()) {
20369 $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);
20370 }
20371
20372 foreach ($lockedRepository->getPackages() as $package) {
20373 $version = $package->getVersion();
20374 if (isset($aliases[$package->getName()][$version])) {
20375 $version = $aliases[$package->getName()][$version]['alias_normalized'];
20376 }
20377 $constraint = new Constraint('=', $version);
20378 $constraint->setPrettyString($package->getPrettyVersion());
20379 $request->install($package->getName(), $constraint);
20380 }
20381
20382 foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
20383 $request->install($link->getTarget(), $link->getConstraint());
20384 }
20385 }
20386
20387
20388  $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-links');
20389
20390
20391  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
20392 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
20393 try {
20394 $operations = $solver->solve($request, $this->ignorePlatformReqs);
20395 } catch (SolverProblemsException $e) {
20396 $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
20397 $this->io->writeError($e->getMessage());
20398 if ($this->update && !$this->devMode) {
20399 $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);
20400 }
20401
20402 return array(max(1, $e->getCode()), array());
20403 }
20404
20405
20406  $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-updates', $operations);
20407
20408 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
20409
20410 $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
20411 $this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies", true, IOInterface::VERBOSE);
20412
20413
20414  if (!$operations) {
20415 $this->io->writeError('Nothing to install or update');
20416 }
20417
20418 $operations = $this->movePluginsToFront($operations);
20419 $operations = $this->moveUninstallsToFront($operations);
20420
20421
20422  
20423  if ($this->update) {
20424 $devPackages = $this->extractDevPackages($operations, $localRepo, $platformRepo, $aliases);
20425 if (!$this->devMode) {
20426 $operations = $this->filterDevPackageOperations($devPackages, $operations, $localRepo);
20427 }
20428 } else {
20429 $devPackages = null;
20430 }
20431
20432 if ($operations) {
20433 $installs = $updates = $uninstalls = array();
20434 foreach ($operations as $operation) {
20435 if ($operation instanceof InstallOperation) {
20436 $installs[] = $operation->getPackage()->getPrettyName().':'.$operation->getPackage()->getFullPrettyVersion();
20437 } elseif ($operation instanceof UpdateOperation) {
20438 $updates[] = $operation->getTargetPackage()->getPrettyName().':'.$operation->getTargetPackage()->getFullPrettyVersion();
20439 } elseif ($operation instanceof UninstallOperation) {
20440 $uninstalls[] = $operation->getPackage()->getPrettyName();
20441 }
20442 }
20443
20444 $this->io->writeError(
20445 sprintf("<info>Package operations: %d install%s, %d update%s, %d removal%s</info>",
20446 count($installs),
20447 1 === count($installs) ? '' : 's',
20448 count($updates),
20449 1 === count($updates) ? '' : 's',
20450 count($uninstalls),
20451 1 === count($uninstalls) ? '' : 's')
20452 );
20453 if ($installs) {
20454 $this->io->writeError("Installs: ".implode(', ', $installs), true, IOInterface::VERBOSE);
20455 }
20456 if ($updates) {
20457 $this->io->writeError("Updates: ".implode(', ', $updates), true, IOInterface::VERBOSE);
20458 }
20459 if ($uninstalls) {
20460 $this->io->writeError("Removals: ".implode(', ', $uninstalls), true, IOInterface::VERBOSE);
20461 }
20462 }
20463
20464 foreach ($operations as $operation) {
20465
20466  if ('install' === $operation->getJobType()) {
20467 $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
20468 }
20469
20470
20471  if ($this->update) {
20472 $package = null;
20473 if ('update' === $operation->getJobType()) {
20474 $package = $operation->getTargetPackage();
20475 } elseif ('install' === $operation->getJobType()) {
20476 $package = $operation->getPackage();
20477 }
20478 if ($package && $package->isDev()) {
20479 $references = $this->package->getReferences();
20480 if (isset($references[$package->getName()])) {
20481 $this->updateInstallReferences($package, $references[$package->getName()]);
20482 }
20483 }
20484 if ('update' === $operation->getJobType()
20485 && $operation->getTargetPackage()->isDev()
20486 && $operation->getTargetPackage()->getVersion() === $operation->getInitialPackage()->getVersion()
20487 && (!$operation->getTargetPackage()->getSourceReference() || $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference())
20488 && (!$operation->getTargetPackage()->getDistReference() || $operation->getTargetPackage()->getDistReference() === $operation->getInitialPackage()->getDistReference())
20489 ) {
20490 $this->io->writeError('  - Skipping update of '. $operation->getTargetPackage()->getPrettyName().' to the same reference-locked version', true, IOInterface::DEBUG);
20491 $this->io->writeError('', true, IOInterface::DEBUG);
20492
20493 continue;
20494 }
20495 }
20496
20497 $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($operation->getJobType());
20498 if (defined($event) && $this->runScripts) {
20499 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20500 }
20501
20502
20503  if (!$this->executeOperations && false === strpos($operation->getJobType(), 'Alias')) {
20504 $this->io->writeError('  - ' . $operation);
20505 } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
20506 $this->io->writeError('  - ' . $operation);
20507 }
20508
20509 $this->installationManager->execute($localRepo, $operation);
20510
20511
20512  if ($this->verbose && $this->io->isVeryVerbose() && in_array($operation->getJobType(), array('install', 'update'))) {
20513 $reason = $operation->getReason();
20514 if ($reason instanceof Rule) {
20515 switch ($reason->getReason()) {
20516 case Rule::RULE_JOB_INSTALL:
20517 $this->io->writeError('    REASON: Required by the root package: '.$reason->getPrettyString($pool));
20518 $this->io->writeError('');
20519 break;
20520 case Rule::RULE_PACKAGE_REQUIRES:
20521 $this->io->writeError('    REASON: '.$reason->getPrettyString($pool));
20522 $this->io->writeError('');
20523 break;
20524 }
20525 }
20526 }
20527
20528 $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($operation->getJobType());
20529 if (defined($event) && $this->runScripts) {
20530 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20531 }
20532
20533 if ($this->executeOperations || $this->writeLock) {
20534 $localRepo->write();
20535 }
20536 }
20537
20538 if ($this->executeOperations) {
20539
20540  $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
20541 $localRepo->write();
20542 }
20543
20544 return array(0, $devPackages);
20545 }
20546
20547
20548
20549
20550
20551
20552
20553
20554
20555
20556
20557 private function extractDevPackages(array $operations, RepositoryInterface $localRepo, PlatformRepository $platformRepo, array $aliases)
20558 {
20559 if (!$this->package->getDevRequires()) {
20560 return array();
20561 }
20562
20563
20564  $tempLocalRepo = clone $localRepo;
20565 foreach ($operations as $operation) {
20566 switch ($operation->getJobType()) {
20567 case 'install':
20568 case 'markAliasInstalled':
20569 if (!$tempLocalRepo->hasPackage($operation->getPackage())) {
20570 $tempLocalRepo->addPackage(clone $operation->getPackage());
20571 }
20572 break;
20573
20574 case 'uninstall':
20575 case 'markAliasUninstalled':
20576 $tempLocalRepo->removePackage($operation->getPackage());
20577 break;
20578
20579 case 'update':
20580 $tempLocalRepo->removePackage($operation->getInitialPackage());
20581 if (!$tempLocalRepo->hasPackage($operation->getTargetPackage())) {
20582 $tempLocalRepo->addPackage(clone $operation->getTargetPackage());
20583 }
20584 break;
20585
20586 default:
20587 throw new \LogicException('Unknown type: '.$operation->getJobType());
20588 }
20589 }
20590
20591
20592  
20593  
20594  $localRepo = new InstalledArrayRepository(array());
20595 $loader = new ArrayLoader(null, true);
20596 $dumper = new ArrayDumper();
20597 foreach ($tempLocalRepo->getCanonicalPackages() as $pkg) {
20598 $localRepo->addPackage($loader->load($dumper->dump($pkg)));
20599 }
20600 unset($tempLocalRepo, $loader, $dumper);
20601
20602 $policy = $this->createPolicy();
20603 $pool = $this->createPool();
20604 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
20605 $pool->addRepository($installedRepo, $aliases);
20606
20607
20608  $request = $this->createRequest($this->package, $platformRepo);
20609 $request->updateAll();
20610 foreach ($this->package->getRequires() as $link) {
20611 $request->install($link->getTarget(), $link->getConstraint());
20612 }
20613
20614
20615  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
20616 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
20617 $ops = $solver->solve($request, $this->ignorePlatformReqs);
20618 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
20619
20620 $devPackages = array();
20621 foreach ($ops as $op) {
20622 if ($op->getJobType() === 'uninstall') {
20623 $devPackages[] = $op->getPackage();
20624 }
20625 }
20626
20627 return $devPackages;
20628 }
20629
20630
20631
20632
20633 private function filterDevPackageOperations(array $devPackages, array $operations, RepositoryInterface $localRepo)
20634 {
20635 $finalOps = array();
20636 $packagesToSkip = array();
20637 foreach ($devPackages as $pkg) {
20638 $packagesToSkip[$pkg->getName()] = true;
20639 if ($installedDevPkg = $localRepo->findPackage($pkg->getName(), '*')) {
20640 $finalOps[] = new UninstallOperation($installedDevPkg, 'non-dev install removing it');
20641 }
20642 }
20643
20644
20645  foreach ($operations as $op) {
20646 $package = $op->getJobType() === 'update' ? $op->getTargetPackage() : $op->getPackage();
20647 if (isset($packagesToSkip[$package->getName()])) {
20648 continue;
20649 }
20650
20651 $finalOps[] = $op;
20652 }
20653
20654 return $finalOps;
20655 }
20656
20657
20658
20659
20660
20661
20662
20663
20664
20665
20666
20667
20668
20669
20670 private function movePluginsToFront(array $operations)
20671 {
20672 $pluginsNoDeps = array();
20673 $pluginsWithDeps = array();
20674 $pluginRequires = array();
20675
20676 foreach (array_reverse($operations, true) as $idx => $op) {
20677 if ($op instanceof InstallOperation) {
20678 $package = $op->getPackage();
20679 } elseif ($op instanceof UpdateOperation) {
20680 $package = $op->getTargetPackage();
20681 } else {
20682 continue;
20683 }
20684
20685
20686  $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
20687
20688
20689  if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
20690
20691  $requires = array_filter(array_keys($package->getRequires()), function ($req) {
20692 return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
20693 });
20694
20695
20696  if ($isPlugin && !count($requires)) {
20697
20698  array_unshift($pluginsNoDeps, $op);
20699 } else {
20700
20701  $pluginRequires = array_merge($pluginRequires, $requires);
20702
20703  array_unshift($pluginsWithDeps, $op);
20704 }
20705
20706 unset($operations[$idx]);
20707 }
20708 }
20709
20710 return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
20711 }
20712
20713
20714
20715
20716
20717
20718
20719
20720 private function moveUninstallsToFront(array $operations)
20721 {
20722 $uninstOps = array();
20723 foreach ($operations as $idx => $op) {
20724 if ($op instanceof UninstallOperation) {
20725 $uninstOps[] = $op;
20726 unset($operations[$idx]);
20727 }
20728 }
20729
20730 return array_merge($uninstOps, $operations);
20731 }
20732
20733
20734
20735
20736 private function createInstalledRepo(RepositoryInterface $localRepo, PlatformRepository $platformRepo)
20737 {
20738
20739  
20740  
20741  $installedRootPackage = clone $this->package;
20742 $installedRootPackage->setRequires(array());
20743 $installedRootPackage->setDevRequires(array());
20744
20745 $repos = array(
20746 $localRepo,
20747 new InstalledArrayRepository(array($installedRootPackage)),
20748 $platformRepo,
20749 );
20750 $installedRepo = new CompositeRepository($repos);
20751 if ($this->additionalInstalledRepository) {
20752 $installedRepo->addRepository($this->additionalInstalledRepository);
20753 }
20754
20755 return $installedRepo;
20756 }
20757
20758
20759
20760
20761
20762 private function createPool(RepositoryInterface $lockedRepository = null)
20763 {
20764 if ($this->update) {
20765 $minimumStability = $this->package->getMinimumStability();
20766 $stabilityFlags = $this->package->getStabilityFlags();
20767
20768 $requires = array_merge($this->package->getRequires(), $this->package->getDevRequires());
20769 } else {
20770 $minimumStability = $this->locker->getMinimumStability();
20771 $stabilityFlags = $this->locker->getStabilityFlags();
20772
20773 $requires = array();
20774 foreach ($lockedRepository->getPackages() as $package) {
20775 $constraint = new Constraint('=', $package->getVersion());
20776 $constraint->setPrettyString($package->getPrettyVersion());
20777 $requires[$package->getName()] = $constraint;
20778 }
20779 }
20780
20781 $rootConstraints = array();
20782 foreach ($requires as $req => $constraint) {
20783
20784  if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
20785 continue;
20786 }
20787 if ($constraint instanceof Link) {
20788 $rootConstraints[$req] = $constraint->getConstraint();
20789 } else {
20790 $rootConstraints[$req] = $constraint;
20791 }
20792 }
20793
20794 return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
20795 }
20796
20797
20798
20799
20800 private function createPolicy()
20801 {
20802 $preferStable = null;
20803 $preferLowest = null;
20804 if (!$this->update) {
20805 $preferStable = $this->locker->getPreferStable();
20806 $preferLowest = $this->locker->getPreferLowest();
20807 }
20808
20809  
20810  if (null === $preferStable) {
20811 $preferStable = $this->preferStable || $this->package->getPreferStable();
20812 }
20813 if (null === $preferLowest) {
20814 $preferLowest = $this->preferLowest;
20815 }
20816
20817 return new DefaultPolicy($preferStable, $preferLowest);
20818 }
20819
20820
20821
20822
20823
20824
20825 private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
20826 {
20827 $request = new Request();
20828
20829 $constraint = new Constraint('=', $rootPackage->getVersion());
20830 $constraint->setPrettyString($rootPackage->getPrettyVersion());
20831 $request->install($rootPackage->getName(), $constraint);
20832
20833 $fixedPackages = $platformRepo->getPackages();
20834 if ($this->additionalInstalledRepository) {
20835 $additionalFixedPackages = $this->additionalInstalledRepository->getPackages();
20836 $fixedPackages = array_merge($fixedPackages, $additionalFixedPackages);
20837 }
20838
20839
20840  
20841  $provided = $rootPackage->getProvides();
20842 foreach ($fixedPackages as $package) {
20843 $constraint = new Constraint('=', $package->getVersion());
20844 $constraint->setPrettyString($package->getPrettyVersion());
20845
20846
20847  if ($package->getRepository() !== $platformRepo
20848 || !isset($provided[$package->getName()])
20849 || !$provided[$package->getName()]->getConstraint()->matches($constraint)
20850 ) {
20851 $request->fix($package->getName(), $constraint);
20852 }
20853 }
20854
20855 return $request;
20856 }
20857
20858
20859
20860
20861
20862
20863
20864
20865
20866
20867
20868
20869 private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $task, array $operations = null)
20870 {
20871 if ($task === 'force-updates' && null === $operations) {
20872 throw new \InvalidArgumentException('Missing operations argument');
20873 }
20874 if ($task === 'force-links') {
20875 $operations = array();
20876 }
20877
20878 if ($this->update && $this->updateWhitelist) {
20879 $currentPackages = $this->getCurrentPackages($installedRepo);
20880 }
20881
20882 foreach ($localRepo->getCanonicalPackages() as $package) {
20883
20884  if (!$package->isDev()) {
20885 continue;
20886 }
20887
20888
20889  foreach ($operations as $operation) {
20890 if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
20891 || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
20892 ) {
20893 continue 2;
20894 }
20895 }
20896
20897 if ($this->update) {
20898
20899  if ($this->updateWhitelist && !$this->isUpdateable($package)) {
20900
20901  foreach ($currentPackages as $curPackage) {
20902 if ($curPackage->isDev() && $curPackage->getName() === $package->getName() && $curPackage->getVersion() === $package->getVersion()) {
20903 if ($task === 'force-links') {
20904 $package->setRequires($curPackage->getRequires());
20905 $package->setConflicts($curPackage->getConflicts());
20906 $package->setProvides($curPackage->getProvides());
20907 $package->setReplaces($curPackage->getReplaces());
20908 } elseif ($task === 'force-updates') {
20909 if (($curPackage->getSourceReference() && $curPackage->getSourceReference() !== $package->getSourceReference())
20910 || ($curPackage->getDistReference() && $curPackage->getDistReference() !== $package->getDistReference())
20911 ) {
20912 $operations[] = new UpdateOperation($package, $curPackage);
20913 }
20914 }
20915
20916 break;
20917 }
20918 }
20919
20920 continue;
20921 }
20922
20923
20924  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
20925 foreach ($matches as $index => $match) {
20926
20927  if (!in_array($match->getRepository(), $repositories, true)) {
20928 unset($matches[$index]);
20929 continue;
20930 }
20931
20932
20933  if ($match->getName() !== $package->getName()) {
20934 unset($matches[$index]);
20935 continue;
20936 }
20937
20938 $matches[$index] = $match->getId();
20939 }
20940
20941
20942  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
20943 $newPackage = $pool->literalToPackage($matches[0]);
20944
20945 if ($task === 'force-links' && $newPackage) {
20946 $package->setRequires($newPackage->getRequires());
20947 $package->setConflicts($newPackage->getConflicts());
20948 $package->setProvides($newPackage->getProvides());
20949 $package->setReplaces($newPackage->getReplaces());
20950 }
20951
20952 if ($task === 'force-updates' && $newPackage && (
20953 (($newPackage->getSourceReference() && $newPackage->getSourceReference() !== $package->getSourceReference())
20954 || ($newPackage->getDistReference() && $newPackage->getDistReference() !== $package->getDistReference())
20955 )
20956 )) {
20957 $operations[] = new UpdateOperation($package, $newPackage);
20958
20959 continue;
20960 }
20961 }
20962
20963 if ($task === 'force-updates') {
20964
20965  $references = $this->package->getReferences();
20966
20967 if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
20968
20969  $operations[] = new UpdateOperation($package, clone $package);
20970 }
20971 }
20972 } else {
20973
20974  foreach ($lockedRepository->findPackages($package->getName()) as $lockedPackage) {
20975 if ($lockedPackage->isDev() && $lockedPackage->getVersion() === $package->getVersion()) {
20976 if ($task === 'force-links') {
20977 $package->setRequires($lockedPackage->getRequires());
20978 $package->setConflicts($lockedPackage->getConflicts());
20979 $package->setProvides($lockedPackage->getProvides());
20980 $package->setReplaces($lockedPackage->getReplaces());
20981 } elseif ($task === 'force-updates') {
20982 if (($lockedPackage->getSourceReference() && $lockedPackage->getSourceReference() !== $package->getSourceReference())
20983 || ($lockedPackage->getDistReference() && $lockedPackage->getDistReference() !== $package->getDistReference())
20984 ) {
20985 $operations[] = new UpdateOperation($package, $lockedPackage);
20986 }
20987 }
20988
20989 break;
20990 }
20991 }
20992 }
20993 }
20994
20995 return $operations;
20996 }
20997
20998
20999
21000
21001
21002
21003 private function getCurrentPackages($installedRepo)
21004 {
21005 if ($this->locker->isLocked()) {
21006 try {
21007 return $this->locker->getLockedRepository(true)->getPackages();
21008 } catch (\RuntimeException $e) {
21009
21010  return $this->locker->getLockedRepository()->getPackages();
21011 }
21012 }
21013
21014 return $installedRepo->getPackages();
21015 }
21016
21017
21018
21019
21020 private function getRootAliases()
21021 {
21022 if ($this->update) {
21023 $aliases = $this->package->getAliases();
21024 } else {
21025 $aliases = $this->locker->getAliases();
21026 }
21027
21028 $normalizedAliases = array();
21029
21030 foreach ($aliases as $alias) {
21031 $normalizedAliases[$alias['package']][$alias['version']] = array(
21032 'alias' => $alias['alias'],
21033 'alias_normalized' => $alias['alias_normalized'],
21034 );
21035 }
21036
21037 return $normalizedAliases;
21038 }
21039
21040
21041
21042
21043
21044
21045
21046 private function processPackageUrls($pool, $policy, $localRepo, $repositories)
21047 {
21048 if (!$this->update) {
21049 return;
21050 }
21051
21052 $rootRefs = $this->package->getReferences();
21053
21054 foreach ($localRepo->getCanonicalPackages() as $package) {
21055
21056  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
21057 foreach ($matches as $index => $match) {
21058
21059  if (!in_array($match->getRepository(), $repositories, true)) {
21060 unset($matches[$index]);
21061 continue;
21062 }
21063
21064
21065  if ($match->getName() !== $package->getName()) {
21066 unset($matches[$index]);
21067 continue;
21068 }
21069
21070 $matches[$index] = $match->getId();
21071 }
21072
21073
21074  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
21075 $newPackage = $pool->literalToPackage($matches[0]);
21076
21077
21078  $sourceUrl = $package->getSourceUrl();
21079 $newSourceUrl = $newPackage->getSourceUrl();
21080 $newReference = $newPackage->getSourceReference();
21081
21082 if ($package->isDev() && isset($rootRefs[$package->getName()]) && $package->getSourceReference() === $rootRefs[$package->getName()]) {
21083 $newReference = $rootRefs[$package->getName()];
21084 }
21085
21086 $this->updatePackageUrl($package, $newSourceUrl, $newPackage->getSourceType(), $newReference, $newPackage->getDistUrl());
21087
21088 if ($package instanceof CompletePackage && $newPackage instanceof CompletePackage) {
21089 $package->setAbandoned($newPackage->getReplacementPackage() ?: $newPackage->isAbandoned());
21090 }
21091
21092 $package->setDistMirrors($newPackage->getDistMirrors());
21093 $package->setSourceMirrors($newPackage->getSourceMirrors());
21094 }
21095 }
21096 }
21097
21098 private function updatePackageUrl(PackageInterface $package, $sourceUrl, $sourceType, $sourceReference, $distUrl)
21099 {
21100 $oldSourceRef = $package->getSourceReference();
21101
21102 if ($package->getSourceUrl() !== $sourceUrl) {
21103 $package->setSourceType($sourceType);
21104 $package->setSourceUrl($sourceUrl);
21105 $package->setSourceReference($sourceReference);
21106 }
21107
21108
21109  
21110  if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $distUrl)) {
21111 $package->setDistUrl($distUrl);
21112 $this->updateInstallReferences($package, $sourceReference);
21113 }
21114
21115 if ($this->updateWhitelist && !$this->isUpdateable($package)) {
21116 $this->updateInstallReferences($package, $oldSourceRef);
21117 }
21118 }
21119
21120 private function updateInstallReferences(PackageInterface $package, $reference)
21121 {
21122 if (!$reference) {
21123 return;
21124 }
21125
21126 $package->setSourceReference($reference);
21127
21128 if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $package->getDistUrl())) {
21129 $package->setDistReference($reference);
21130 $package->setDistUrl(preg_replace('{(?<=/)[a-f0-9]{40}(?=/|$)}i', $reference, $package->getDistUrl()));
21131 } elseif ($package->getDistReference()) { 
21132  $package->setDistReference($reference);
21133 }
21134 }
21135
21136
21137
21138
21139
21140 private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
21141 {
21142 foreach ($aliases as $package => $versions) {
21143 foreach ($versions as $version => $alias) {
21144 $packages = $platformRepo->findPackages($package, $version);
21145 foreach ($packages as $package) {
21146 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
21147 $aliasPackage->setRootPackageAlias(true);
21148 $platformRepo->addPackage($aliasPackage);
21149 }
21150 }
21151 }
21152 }
21153
21154
21155
21156
21157
21158 private function isUpdateable(PackageInterface $package)
21159 {
21160 if (!$this->updateWhitelist) {
21161 throw new \LogicException('isUpdateable should only be called when a whitelist is present');
21162 }
21163
21164 foreach ($this->updateWhitelist as $whiteListedPattern => $void) {
21165 $patternRegexp = $this->packageNameToRegexp($whiteListedPattern);
21166 if (preg_match($patternRegexp, $package->getName())) {
21167 return true;
21168 }
21169 }
21170
21171 return false;
21172 }
21173
21174
21175
21176
21177
21178
21179
21180 private function packageNameToRegexp($whiteListedPattern)
21181 {
21182 $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern));
21183
21184 return "{^" . $cleanedWhiteListedPattern . "$}i";
21185 }
21186
21187
21188
21189
21190
21191 private function extractPlatformRequirements($links)
21192 {
21193 $platformReqs = array();
21194 foreach ($links as $link) {
21195 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
21196 $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
21197 }
21198 }
21199
21200 return $platformReqs;
21201 }
21202
21203
21204
21205
21206
21207
21208
21209
21210
21211
21212
21213
21214
21215
21216 private function whitelistUpdateDependencies($localOrLockRepo, array $rootRequires, array $rootDevRequires)
21217 {
21218 if (!$this->updateWhitelist) {
21219 return;
21220 }
21221
21222 $rootRequires = array_merge($rootRequires, $rootDevRequires);
21223
21224 $requiredPackageNames = array();
21225 foreach ($rootRequires as $require) {
21226 $requiredPackageNames[] = $require->getTarget();
21227 }
21228
21229 $skipPackages = array();
21230 if (!$this->whitelistAllDependencies) {
21231 foreach ($rootRequires as $require) {
21232 $skipPackages[$require->getTarget()] = true;
21233 }
21234 }
21235
21236 $pool = new Pool('dev');
21237 $pool->addRepository($localOrLockRepo);
21238
21239 $seen = array();
21240
21241 $rootRequiredPackageNames = array_keys($rootRequires);
21242
21243 foreach ($this->updateWhitelist as $packageName => $void) {
21244 $packageQueue = new \SplQueue;
21245
21246 $depPackages = $pool->whatProvides($packageName);
21247
21248 $nameMatchesRequiredPackage = in_array($packageName, $requiredPackageNames, true);
21249
21250
21251  if (!$nameMatchesRequiredPackage) {
21252 $whitelistPatternRegexp = $this->packageNameToRegexp($packageName);
21253 foreach ($rootRequiredPackageNames as $rootRequiredPackageName) {
21254 if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) {
21255 $nameMatchesRequiredPackage = true;
21256 break;
21257 }
21258 }
21259 }
21260
21261 if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) {
21262 $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
21263 }
21264
21265 foreach ($depPackages as $depPackage) {
21266 $packageQueue->enqueue($depPackage);
21267 }
21268
21269 while (!$packageQueue->isEmpty()) {
21270 $package = $packageQueue->dequeue();
21271 if (isset($seen[$package->getId()])) {
21272 continue;
21273 }
21274
21275 $seen[$package->getId()] = true;
21276 $this->updateWhitelist[$package->getName()] = true;
21277
21278 if (!$this->whitelistDependencies && !$this->whitelistAllDependencies) {
21279 continue;
21280 }
21281
21282 $requires = $package->getRequires();
21283
21284 foreach ($requires as $require) {
21285 $requirePackages = $pool->whatProvides($require->getTarget());
21286
21287 foreach ($requirePackages as $requirePackage) {
21288 if (isset($this->updateWhitelist[$requirePackage->getName()])) {
21289 continue;
21290 }
21291
21292 if (isset($skipPackages[$requirePackage->getName()])) {
21293 $this->io->writeError('<warning>Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.</warning>');
21294 continue;
21295 }
21296
21297 $packageQueue->enqueue($requirePackage);
21298 }
21299 }
21300 }
21301 }
21302 }
21303
21304
21305
21306
21307
21308
21309
21310
21311 private function mockLocalRepositories(RepositoryManager $rm)
21312 {
21313 $packages = array();
21314 foreach ($rm->getLocalRepository()->getPackages() as $package) {
21315 $packages[(string) $package] = clone $package;
21316 }
21317 foreach ($packages as $key => $package) {
21318 if ($package instanceof AliasPackage) {
21319 $alias = (string) $package->getAliasOf();
21320 $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
21321 }
21322 }
21323 $rm->setLocalRepository(
21324 new InstalledArrayRepository($packages)
21325 );
21326 }
21327
21328
21329
21330
21331
21332
21333
21334
21335 public static function create(IOInterface $io, Composer $composer)
21336 {
21337 return new static(
21338 $io,
21339 $composer->getConfig(),
21340 $composer->getPackage(),
21341 $composer->getDownloadManager(),
21342 $composer->getRepositoryManager(),
21343 $composer->getLocker(),
21344 $composer->getInstallationManager(),
21345 $composer->getEventDispatcher(),
21346 $composer->getAutoloadGenerator()
21347 );
21348 }
21349
21350
21351
21352
21353
21354 public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
21355 {
21356 $this->additionalInstalledRepository = $additionalInstalledRepository;
21357
21358 return $this;
21359 }
21360
21361
21362
21363
21364
21365
21366
21367 public function setDryRun($dryRun = true)
21368 {
21369 $this->dryRun = (bool) $dryRun;
21370
21371 return $this;
21372 }
21373
21374
21375
21376
21377
21378
21379 public function isDryRun()
21380 {
21381 return $this->dryRun;
21382 }
21383
21384
21385
21386
21387
21388
21389
21390 public function setPreferSource($preferSource = true)
21391 {
21392 $this->preferSource = (bool) $preferSource;
21393
21394 return $this;
21395 }
21396
21397
21398
21399
21400
21401
21402
21403 public function setPreferDist($preferDist = true)
21404 {
21405 $this->preferDist = (bool) $preferDist;
21406
21407 return $this;
21408 }
21409
21410
21411
21412
21413
21414
21415
21416 public function setOptimizeAutoloader($optimizeAutoloader = false)
21417 {
21418 $this->optimizeAutoloader = (bool) $optimizeAutoloader;
21419 if (!$this->optimizeAutoloader) {
21420
21421  
21422  $this->setClassMapAuthoritative(false);
21423 }
21424
21425 return $this;
21426 }
21427
21428
21429
21430
21431
21432
21433
21434
21435 public function setClassMapAuthoritative($classMapAuthoritative = false)
21436 {
21437 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
21438 if ($this->classMapAuthoritative) {
21439
21440  $this->setOptimizeAutoloader(true);
21441 }
21442
21443 return $this;
21444 }
21445
21446
21447
21448
21449
21450
21451
21452 public function setApcuAutoloader($apcuAutoloader = false)
21453 {
21454 $this->apcuAutoloader = (bool) $apcuAutoloader;
21455
21456 return $this;
21457 }
21458
21459
21460
21461
21462
21463
21464
21465 public function setUpdate($update = true)
21466 {
21467 $this->update = (bool) $update;
21468
21469 return $this;
21470 }
21471
21472
21473
21474
21475
21476
21477
21478 public function setDevMode($devMode = true)
21479 {
21480 $this->devMode = (bool) $devMode;
21481
21482 return $this;
21483 }
21484
21485
21486
21487
21488
21489
21490
21491
21492
21493 public function setDumpAutoloader($dumpAutoloader = true)
21494 {
21495 $this->dumpAutoloader = (bool) $dumpAutoloader;
21496
21497 return $this;
21498 }
21499
21500
21501
21502
21503
21504
21505
21506
21507
21508 public function setRunScripts($runScripts = true)
21509 {
21510 $this->runScripts = (bool) $runScripts;
21511
21512 return $this;
21513 }
21514
21515
21516
21517
21518
21519
21520
21521 public function setConfig(Config $config)
21522 {
21523 $this->config = $config;
21524
21525 return $this;
21526 }
21527
21528
21529
21530
21531
21532
21533
21534 public function setVerbose($verbose = true)
21535 {
21536 $this->verbose = (bool) $verbose;
21537
21538 return $this;
21539 }
21540
21541
21542
21543
21544
21545
21546 public function isVerbose()
21547 {
21548 return $this->verbose;
21549 }
21550
21551
21552
21553
21554
21555
21556
21557 public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
21558 {
21559 $this->ignorePlatformReqs = (bool) $ignorePlatformReqs;
21560
21561 return $this;
21562 }
21563
21564
21565
21566
21567
21568
21569
21570
21571 public function setUpdateWhitelist(array $packages)
21572 {
21573 $this->updateWhitelist = array_flip(array_map('strtolower', $packages));
21574
21575 return $this;
21576 }
21577
21578
21579
21580
21581 public function setWhitelistDependencies($updateDependencies = true)
21582 {
21583 return $this->setWhitelistTransitiveDependencies($updateDependencies);
21584 }
21585
21586
21587
21588
21589
21590
21591
21592
21593
21594
21595 public function setWhitelistTransitiveDependencies($updateTransitiveDependencies = true)
21596 {
21597 $this->whitelistDependencies = (bool) $updateTransitiveDependencies;
21598
21599 return $this;
21600 }
21601
21602
21603
21604
21605
21606
21607
21608
21609
21610
21611 public function setWhitelistAllDependencies($updateAllDependencies = true)
21612 {
21613 $this->whitelistAllDependencies = (bool) $updateAllDependencies;
21614
21615 return $this;
21616 }
21617
21618
21619
21620
21621
21622
21623
21624 public function setPreferStable($preferStable = true)
21625 {
21626 $this->preferStable = (bool) $preferStable;
21627
21628 return $this;
21629 }
21630
21631
21632
21633
21634
21635
21636
21637 public function setPreferLowest($preferLowest = true)
21638 {
21639 $this->preferLowest = (bool) $preferLowest;
21640
21641 return $this;
21642 }
21643
21644
21645
21646
21647
21648
21649
21650
21651
21652 public function setWriteLock($writeLock = true)
21653 {
21654 $this->writeLock = (bool) $writeLock;
21655
21656 return $this;
21657 }
21658
21659
21660
21661
21662
21663
21664
21665
21666
21667 public function setExecuteOperations($executeOperations = true)
21668 {
21669 $this->executeOperations = (bool) $executeOperations;
21670
21671 return $this;
21672 }
21673
21674
21675
21676
21677
21678
21679
21680 public function setSkipSuggest($skipSuggest = true)
21681 {
21682 $this->skipSuggest = (bool) $skipSuggest;
21683
21684 return $this;
21685 }
21686
21687
21688
21689
21690
21691
21692
21693
21694
21695
21696 public function disablePlugins()
21697 {
21698 $this->installationManager->disablePlugins();
21699
21700 return $this;
21701 }
21702
21703
21704
21705
21706
21707 public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter)
21708 {
21709 $this->suggestedPackagesReporter = $suggestedPackagesReporter;
21710
21711 return $this;
21712 }
21713 }
21714 <?php
21715
21716
21717
21718
21719
21720
21721
21722
21723
21724
21725
21726 namespace Composer\Installer;
21727
21728 use Composer\IO\IOInterface;
21729 use Composer\Package\PackageInterface;
21730 use Composer\Util\Filesystem;
21731 use Composer\Util\Platform;
21732 use Composer\Util\ProcessExecutor;
21733 use Composer\Util\Silencer;
21734
21735
21736
21737
21738
21739
21740
21741
21742 class BinaryInstaller
21743 {
21744 protected $binDir;
21745 protected $binCompat;
21746 protected $io;
21747 protected $filesystem;
21748
21749
21750
21751
21752
21753
21754
21755 public function __construct(IOInterface $io, $binDir, $binCompat, Filesystem $filesystem = null)
21756 {
21757 $this->binDir = $binDir;
21758 $this->binCompat = $binCompat;
21759 $this->io = $io;
21760 $this->filesystem = $filesystem ?: new Filesystem();
21761 }
21762
21763 public function installBinaries(PackageInterface $package, $installPath, $warnOnOverwrite = true)
21764 {
21765 $binaries = $this->getBinaries($package);
21766 if (!$binaries) {
21767 return;
21768 }
21769 foreach ($binaries as $bin) {
21770 $binPath = $installPath.'/'.$bin;
21771 if (!file_exists($binPath)) {
21772 $this->io->writeError('    <warning>Skipped installation of bin '.$bin.' for package '.$package->getName().': file not found in package</warning>');
21773 continue;
21774 }
21775
21776
21777  
21778  
21779  
21780  $binPath = realpath($binPath);
21781
21782 $this->initializeBinDir();
21783 $link = $this->binDir.'/'.basename($bin);
21784 if (file_exists($link)) {
21785 if (is_link($link)) {
21786
21787  
21788  
21789  Silencer::call('chmod', $link, 0777 & ~umask());
21790 }
21791 if ($warnOnOverwrite) {
21792 $this->io->writeError('    Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
21793 }
21794 continue;
21795 }
21796
21797 if ($this->binCompat === "auto") {
21798 if (Platform::isWindows()) {
21799 $this->installFullBinaries($binPath, $link, $bin, $package);
21800 } else {
21801 $this->installSymlinkBinaries($binPath, $link);
21802 }
21803 } elseif ($this->binCompat === "full") {
21804 $this->installFullBinaries($binPath, $link, $bin, $package);
21805 }
21806 Silencer::call('chmod', $link, 0777 & ~umask());
21807 }
21808 }
21809
21810 public function removeBinaries(PackageInterface $package)
21811 {
21812 $this->initializeBinDir();
21813
21814 $binaries = $this->getBinaries($package);
21815 if (!$binaries) {
21816 return;
21817 }
21818 foreach ($binaries as $bin) {
21819 $link = $this->binDir.'/'.basename($bin);
21820 if (is_link($link) || file_exists($link)) {
21821 $this->filesystem->unlink($link);
21822 }
21823 if (file_exists($link.'.bat')) {
21824 $this->filesystem->unlink($link.'.bat');
21825 }
21826 }
21827
21828
21829  if ((is_dir($this->binDir)) && ($this->filesystem->isDirEmpty($this->binDir))) {
21830 Silencer::call('rmdir', $this->binDir);
21831 }
21832 }
21833
21834 public static function determineBinaryCaller($bin)
21835 {
21836 if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
21837 return 'call';
21838 }
21839
21840 $handle = fopen($bin, 'r');
21841 $line = fgets($handle);
21842 fclose($handle);
21843 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
21844 return trim($match[1]);
21845 }
21846
21847 return 'php';
21848 }
21849
21850 protected function getBinaries(PackageInterface $package)
21851 {
21852 return $package->getBinaries();
21853 }
21854
21855 protected function installFullBinaries($binPath, $link, $bin, PackageInterface $package)
21856 {
21857
21858  if ('.bat' !== substr($binPath, -4)) {
21859 $this->installUnixyProxyBinaries($binPath, $link);
21860 @chmod($link, 0777 & ~umask());
21861 $link .= '.bat';
21862 if (file_exists($link)) {
21863 $this->io->writeError('    Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
21864 }
21865 }
21866 if (!file_exists($link)) {
21867 file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
21868 }
21869 }
21870
21871 protected function installSymlinkBinaries($binPath, $link)
21872 {
21873 if (!$this->filesystem->relativeSymlink($binPath, $link)) {
21874 $this->installUnixyProxyBinaries($binPath, $link);
21875 }
21876 }
21877
21878 protected function installUnixyProxyBinaries($binPath, $link)
21879 {
21880 file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
21881 }
21882
21883 protected function initializeBinDir()
21884 {
21885 $this->filesystem->ensureDirectoryExists($this->binDir);
21886 $this->binDir = realpath($this->binDir);
21887 }
21888
21889 protected function generateWindowsProxyCode($bin, $link)
21890 {
21891 $binPath = $this->filesystem->findShortestPath($link, $bin);
21892 $caller = self::determineBinaryCaller($bin);
21893
21894 return "@ECHO OFF\r\n".
21895 "setlocal DISABLEDELAYEDEXPANSION\r\n".
21896 "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"\'')."\r\n".
21897 "{$caller} \"%BIN_TARGET%\" %*\r\n";
21898 }
21899
21900 protected function generateUnixyProxyCode($bin, $link)
21901 {
21902 $binPath = $this->filesystem->findShortestPath($link, $bin);
21903
21904 $binDir = ProcessExecutor::escape(dirname($binPath));
21905 $binFile = basename($binPath);
21906
21907 $proxyCode = <<<PROXY
21908 #!/usr/bin/env sh
21909
21910 dir=\$(cd "\${0%[/\\\\]*}" > /dev/null; cd $binDir && pwd)
21911
21912 if [ -d /proc/cygdrive ] && [[ \$(which php) == \$(readlink -n /proc/cygdrive)/* ]]; then
21913    # We are in Cgywin using Windows php, so the path must be translated
21914    dir=\$(cygpath -m "\$dir");
21915 fi
21916
21917 "\${dir}/$binFile" "\$@"
21918
21919 PROXY;
21920
21921 return $proxyCode;
21922 }
21923 }
21924 <?php
21925
21926
21927
21928
21929
21930
21931
21932
21933
21934
21935
21936 namespace Composer\Installer;
21937
21938 use Composer\Package\PackageInterface;
21939
21940
21941
21942
21943
21944
21945 interface BinaryPresenceInterface
21946 {
21947
21948
21949
21950
21951
21952 public function ensureBinariesPresence(PackageInterface $package);
21953 }
21954 <?php
21955
21956
21957
21958
21959
21960
21961
21962
21963
21964
21965
21966 namespace Composer\Installer;
21967
21968 use Composer\IO\IOInterface;
21969 use Composer\Package\PackageInterface;
21970 use Composer\Package\AliasPackage;
21971 use Composer\Repository\RepositoryInterface;
21972 use Composer\Repository\InstalledRepositoryInterface;
21973 use Composer\DependencyResolver\Operation\OperationInterface;
21974 use Composer\DependencyResolver\Operation\InstallOperation;
21975 use Composer\DependencyResolver\Operation\UpdateOperation;
21976 use Composer\DependencyResolver\Operation\UninstallOperation;
21977 use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
21978 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
21979 use Composer\Util\StreamContextFactory;
21980
21981
21982
21983
21984
21985
21986
21987
21988 class InstallationManager
21989 {
21990 private $installers = array();
21991 private $cache = array();
21992 private $notifiablePackages = array();
21993
21994 public function reset()
21995 {
21996 $this->notifiablePackages = array();
21997 }
21998
21999
22000
22001
22002
22003
22004 public function addInstaller(InstallerInterface $installer)
22005 {
22006 array_unshift($this->installers, $installer);
22007 $this->cache = array();
22008 }
22009
22010
22011
22012
22013
22014
22015 public function removeInstaller(InstallerInterface $installer)
22016 {
22017 if (false !== ($key = array_search($installer, $this->installers, true))) {
22018 array_splice($this->installers, $key, 1);
22019 $this->cache = array();
22020 }
22021 }
22022
22023
22024
22025
22026
22027
22028
22029
22030 public function disablePlugins()
22031 {
22032 foreach ($this->installers as $i => $installer) {
22033 if (!$installer instanceof PluginInstaller) {
22034 continue;
22035 }
22036
22037 unset($this->installers[$i]);
22038 }
22039 }
22040
22041
22042
22043
22044
22045
22046
22047
22048
22049 public function getInstaller($type)
22050 {
22051 $type = strtolower($type);
22052
22053 if (isset($this->cache[$type])) {
22054 return $this->cache[$type];
22055 }
22056
22057 foreach ($this->installers as $installer) {
22058 if ($installer->supports($type)) {
22059 return $this->cache[$type] = $installer;
22060 }
22061 }
22062
22063 throw new \InvalidArgumentException('Unknown installer type: '.$type);
22064 }
22065
22066
22067
22068
22069
22070
22071
22072
22073
22074 public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22075 {
22076 if ($package instanceof AliasPackage) {
22077 return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
22078 }
22079
22080 return $this->getInstaller($package->getType())->isInstalled($repo, $package);
22081 }
22082
22083
22084
22085
22086
22087
22088
22089 public function ensureBinariesPresence(PackageInterface $package)
22090 {
22091 try {
22092 $installer = $this->getInstaller($package->getType());
22093 } catch (\InvalidArgumentException $e) {
22094
22095  return;
22096 }
22097
22098
22099  if ($installer instanceof BinaryPresenceInterface) {
22100 $installer->ensureBinariesPresence($package);
22101 }
22102 }
22103
22104
22105
22106
22107
22108
22109
22110 public function execute(RepositoryInterface $repo, OperationInterface $operation)
22111 {
22112 $method = $operation->getJobType();
22113 $this->$method($repo, $operation);
22114 }
22115
22116
22117
22118
22119
22120
22121
22122 public function install(RepositoryInterface $repo, InstallOperation $operation)
22123 {
22124 $package = $operation->getPackage();
22125 $installer = $this->getInstaller($package->getType());
22126 $installer->install($repo, $package);
22127 $this->markForNotification($package);
22128 }
22129
22130
22131
22132
22133
22134
22135
22136 public function update(RepositoryInterface $repo, UpdateOperation $operation)
22137 {
22138 $initial = $operation->getInitialPackage();
22139 $target = $operation->getTargetPackage();
22140
22141 $initialType = $initial->getType();
22142 $targetType = $target->getType();
22143
22144 if ($initialType === $targetType) {
22145 $installer = $this->getInstaller($initialType);
22146 $installer->update($repo, $initial, $target);
22147 $this->markForNotification($target);
22148 } else {
22149 $this->getInstaller($initialType)->uninstall($repo, $initial);
22150 $this->getInstaller($targetType)->install($repo, $target);
22151 }
22152 }
22153
22154
22155
22156
22157
22158
22159
22160 public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
22161 {
22162 $package = $operation->getPackage();
22163 $installer = $this->getInstaller($package->getType());
22164 $installer->uninstall($repo, $package);
22165 }
22166
22167
22168
22169
22170
22171
22172
22173 public function markAliasInstalled(RepositoryInterface $repo, MarkAliasInstalledOperation $operation)
22174 {
22175 $package = $operation->getPackage();
22176
22177 if (!$repo->hasPackage($package)) {
22178 $repo->addPackage(clone $package);
22179 }
22180 }
22181
22182
22183
22184
22185
22186
22187
22188 public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
22189 {
22190 $package = $operation->getPackage();
22191
22192 $repo->removePackage($package);
22193 }
22194
22195
22196
22197
22198
22199
22200
22201 public function getInstallPath(PackageInterface $package)
22202 {
22203 $installer = $this->getInstaller($package->getType());
22204
22205 return $installer->getInstallPath($package);
22206 }
22207
22208 public function notifyInstalls(IOInterface $io)
22209 {
22210 foreach ($this->notifiablePackages as $repoUrl => $packages) {
22211 $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
22212 if ($io->hasAuthentication($repositoryName)) {
22213 $auth = $io->getAuthentication($repositoryName);
22214 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
22215 $authHeader = 'Authorization: Basic '.$authStr;
22216 }
22217
22218
22219  if (strpos($repoUrl, '%package%')) {
22220 foreach ($packages as $package) {
22221 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
22222
22223 $params = array(
22224 'version' => $package->getPrettyVersion(),
22225 'version_normalized' => $package->getVersion(),
22226 );
22227 $opts = array('http' =>
22228 array(
22229 'method' => 'POST',
22230 'header' => array('Content-type: application/x-www-form-urlencoded'),
22231 'content' => http_build_query($params, '', '&'),
22232 'timeout' => 3,
22233 ),
22234 );
22235 if (isset($authHeader)) {
22236 $opts['http']['header'][] = $authHeader;
22237 }
22238
22239 $context = StreamContextFactory::getContext($url, $opts);
22240 @file_get_contents($url, false, $context);
22241 }
22242
22243 continue;
22244 }
22245
22246 $postData = array('downloads' => array());
22247 foreach ($packages as $package) {
22248 $postData['downloads'][] = array(
22249 'name' => $package->getPrettyName(),
22250 'version' => $package->getVersion(),
22251 );
22252 }
22253
22254 $opts = array('http' =>
22255 array(
22256 'method' => 'POST',
22257 'header' => array('Content-Type: application/json'),
22258 'content' => json_encode($postData),
22259 'timeout' => 6,
22260 ),
22261 );
22262 if (isset($authHeader)) {
22263 $opts['http']['header'][] = $authHeader;
22264 }
22265
22266 $context = StreamContextFactory::getContext($repoUrl, $opts);
22267 @file_get_contents($repoUrl, false, $context);
22268 }
22269
22270 $this->reset();
22271 }
22272
22273 private function markForNotification(PackageInterface $package)
22274 {
22275 if ($package->getNotificationUrl()) {
22276 $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
22277 }
22278 }
22279 }
22280 <?php
22281
22282
22283
22284
22285
22286
22287
22288
22289
22290
22291
22292 namespace Composer\Installer;
22293
22294 use Composer\Composer;
22295 use Composer\DependencyResolver\PolicyInterface;
22296 use Composer\DependencyResolver\Operation\OperationInterface;
22297 use Composer\DependencyResolver\Pool;
22298 use Composer\DependencyResolver\Request;
22299 use Composer\EventDispatcher\Event;
22300 use Composer\IO\IOInterface;
22301 use Composer\Repository\CompositeRepository;
22302
22303
22304
22305
22306
22307
22308 class InstallerEvent extends Event
22309 {
22310
22311
22312
22313 private $composer;
22314
22315
22316
22317
22318 private $io;
22319
22320
22321
22322
22323 private $devMode;
22324
22325
22326
22327
22328 private $policy;
22329
22330
22331
22332
22333 private $pool;
22334
22335
22336
22337
22338 private $installedRepo;
22339
22340
22341
22342
22343 private $request;
22344
22345
22346
22347
22348 private $operations;
22349
22350
22351
22352
22353
22354
22355
22356
22357
22358
22359
22360
22361
22362
22363 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
22364 {
22365 parent::__construct($eventName);
22366
22367 $this->composer = $composer;
22368 $this->io = $io;
22369 $this->devMode = $devMode;
22370 $this->policy = $policy;
22371 $this->pool = $pool;
22372 $this->installedRepo = $installedRepo;
22373 $this->request = $request;
22374 $this->operations = $operations;
22375 }
22376
22377
22378
22379
22380 public function getComposer()
22381 {
22382 return $this->composer;
22383 }
22384
22385
22386
22387
22388 public function getIO()
22389 {
22390 return $this->io;
22391 }
22392
22393
22394
22395
22396 public function isDevMode()
22397 {
22398 return $this->devMode;
22399 }
22400
22401
22402
22403
22404 public function getPolicy()
22405 {
22406 return $this->policy;
22407 }
22408
22409
22410
22411
22412 public function getPool()
22413 {
22414 return $this->pool;
22415 }
22416
22417
22418
22419
22420 public function getInstalledRepo()
22421 {
22422 return $this->installedRepo;
22423 }
22424
22425
22426
22427
22428 public function getRequest()
22429 {
22430 return $this->request;
22431 }
22432
22433
22434
22435
22436 public function getOperations()
22437 {
22438 return $this->operations;
22439 }
22440 }
22441 <?php
22442
22443
22444
22445
22446
22447
22448
22449
22450
22451
22452
22453 namespace Composer\Installer;
22454
22455
22456
22457
22458
22459
22460 class InstallerEvents
22461 {
22462
22463
22464
22465
22466
22467
22468
22469
22470
22471 const PRE_DEPENDENCIES_SOLVING = 'pre-dependencies-solving';
22472
22473
22474
22475
22476
22477
22478
22479
22480
22481
22482 const POST_DEPENDENCIES_SOLVING = 'post-dependencies-solving';
22483 }
22484 <?php
22485
22486
22487
22488
22489
22490
22491
22492
22493
22494
22495
22496 namespace Composer\Installer;
22497
22498 use Composer\Package\PackageInterface;
22499 use Composer\Repository\InstalledRepositoryInterface;
22500 use InvalidArgumentException;
22501
22502
22503
22504
22505
22506
22507
22508 interface InstallerInterface
22509 {
22510
22511
22512
22513
22514
22515
22516 public function supports($packageType);
22517
22518
22519
22520
22521
22522
22523
22524
22525
22526 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
22527
22528
22529
22530
22531
22532
22533
22534 public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
22535
22536
22537
22538
22539
22540
22541
22542
22543
22544
22545 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
22546
22547
22548
22549
22550
22551
22552
22553 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
22554
22555
22556
22557
22558
22559
22560
22561 public function getInstallPath(PackageInterface $package);
22562 }
22563 <?php
22564
22565
22566
22567
22568
22569
22570
22571
22572
22573
22574
22575 namespace Composer\Installer;
22576
22577 use Composer\Composer;
22578 use Composer\IO\IOInterface;
22579 use Composer\Repository\InstalledRepositoryInterface;
22580 use Composer\Package\PackageInterface;
22581 use Composer\Util\Filesystem;
22582 use Composer\Util\Silencer;
22583
22584
22585
22586
22587
22588
22589
22590 class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
22591 {
22592 protected $composer;
22593 protected $vendorDir;
22594 protected $binDir;
22595 protected $downloadManager;
22596 protected $io;
22597 protected $type;
22598 protected $filesystem;
22599 protected $binCompat;
22600 protected $binaryInstaller;
22601
22602
22603
22604
22605
22606
22607
22608
22609
22610
22611 public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null, BinaryInstaller $binaryInstaller = null)
22612 {
22613 $this->composer = $composer;
22614 $this->downloadManager = $composer->getDownloadManager();
22615 $this->io = $io;
22616 $this->type = $type;
22617
22618 $this->filesystem = $filesystem ?: new Filesystem();
22619 $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
22620 $this->binaryInstaller = $binaryInstaller ?: new BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem);
22621 }
22622
22623
22624
22625
22626 public function supports($packageType)
22627 {
22628 return $packageType === $this->type || null === $this->type;
22629 }
22630
22631
22632
22633
22634 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22635 {
22636 return $repo->hasPackage($package) && is_readable($this->getInstallPath($package));
22637 }
22638
22639
22640
22641
22642 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22643 {
22644 $this->initializeVendorDir();
22645 $downloadPath = $this->getInstallPath($package);
22646
22647
22648  if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
22649 $this->binaryInstaller->removeBinaries($package);
22650 }
22651
22652 $this->installCode($package);
22653 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package));
22654 if (!$repo->hasPackage($package)) {
22655 $repo->addPackage(clone $package);
22656 }
22657 }
22658
22659
22660
22661
22662 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22663 {
22664 if (!$repo->hasPackage($initial)) {
22665 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22666 }
22667
22668 $this->initializeVendorDir();
22669
22670 $this->binaryInstaller->removeBinaries($initial);
22671 $this->updateCode($initial, $target);
22672 $this->binaryInstaller->installBinaries($target, $this->getInstallPath($target));
22673 $repo->removePackage($initial);
22674 if (!$repo->hasPackage($target)) {
22675 $repo->addPackage(clone $target);
22676 }
22677 }
22678
22679
22680
22681
22682 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22683 {
22684 if (!$repo->hasPackage($package)) {
22685 throw new \InvalidArgumentException('Package is not installed: '.$package);
22686 }
22687
22688 $this->removeCode($package);
22689 $this->binaryInstaller->removeBinaries($package);
22690 $repo->removePackage($package);
22691
22692 $downloadPath = $this->getPackageBasePath($package);
22693 if (strpos($package->getName(), '/')) {
22694 $packageVendorDir = dirname($downloadPath);
22695 if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
22696 Silencer::call('rmdir', $packageVendorDir);
22697 }
22698 }
22699 }
22700
22701
22702
22703
22704 public function getInstallPath(PackageInterface $package)
22705 {
22706 $this->initializeVendorDir();
22707
22708 $basePath = ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
22709 $targetDir = $package->getTargetDir();
22710
22711 return $basePath . ($targetDir ? '/'.$targetDir : '');
22712 }
22713
22714
22715
22716
22717
22718
22719 public function ensureBinariesPresence(PackageInterface $package)
22720 {
22721 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), false);
22722 }
22723
22724
22725
22726
22727
22728
22729
22730
22731
22732
22733 protected function getPackageBasePath(PackageInterface $package)
22734 {
22735 $installPath = $this->getInstallPath($package);
22736 $targetDir = $package->getTargetDir();
22737
22738 if ($targetDir) {
22739 return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath);
22740 }
22741
22742 return $installPath;
22743 }
22744
22745 protected function installCode(PackageInterface $package)
22746 {
22747 $downloadPath = $this->getInstallPath($package);
22748 $this->downloadManager->download($package, $downloadPath);
22749 }
22750
22751 protected function updateCode(PackageInterface $initial, PackageInterface $target)
22752 {
22753 $initialDownloadPath = $this->getInstallPath($initial);
22754 $targetDownloadPath = $this->getInstallPath($target);
22755 if ($targetDownloadPath !== $initialDownloadPath) {
22756
22757  
22758  if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
22759 || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
22760 ) {
22761 $this->removeCode($initial);
22762 $this->installCode($target);
22763
22764 return;
22765 }
22766
22767 $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
22768 }
22769 $this->downloadManager->update($initial, $target, $targetDownloadPath);
22770 }
22771
22772 protected function removeCode(PackageInterface $package)
22773 {
22774 $downloadPath = $this->getPackageBasePath($package);
22775 $this->downloadManager->remove($package, $downloadPath);
22776 }
22777
22778 protected function initializeVendorDir()
22779 {
22780 $this->filesystem->ensureDirectoryExists($this->vendorDir);
22781 $this->vendorDir = realpath($this->vendorDir);
22782 }
22783 }
22784 <?php
22785
22786
22787
22788
22789
22790
22791
22792
22793
22794
22795
22796 namespace Composer\Installer;
22797
22798 use Composer\Repository\InstalledRepositoryInterface;
22799 use Composer\Package\PackageInterface;
22800
22801
22802
22803
22804
22805
22806 class MetapackageInstaller implements InstallerInterface
22807 {
22808
22809
22810
22811 public function supports($packageType)
22812 {
22813 return $packageType === 'metapackage';
22814 }
22815
22816
22817
22818
22819 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22820 {
22821 return $repo->hasPackage($package);
22822 }
22823
22824
22825
22826
22827 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22828 {
22829 $repo->addPackage(clone $package);
22830 }
22831
22832
22833
22834
22835 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22836 {
22837 if (!$repo->hasPackage($initial)) {
22838 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22839 }
22840
22841 $repo->removePackage($initial);
22842 $repo->addPackage(clone $target);
22843 }
22844
22845
22846
22847
22848 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22849 {
22850 if (!$repo->hasPackage($package)) {
22851 throw new \InvalidArgumentException('Package is not installed: '.$package);
22852 }
22853
22854 $repo->removePackage($package);
22855 }
22856
22857
22858
22859
22860 public function getInstallPath(PackageInterface $package)
22861 {
22862 return '';
22863 }
22864 }
22865 <?php
22866
22867
22868
22869
22870
22871
22872
22873
22874
22875
22876
22877 namespace Composer\Installer;
22878
22879 use Composer\Repository\InstalledRepositoryInterface;
22880 use Composer\Package\PackageInterface;
22881
22882
22883
22884
22885
22886
22887
22888
22889 class NoopInstaller implements InstallerInterface
22890 {
22891
22892
22893
22894 public function supports($packageType)
22895 {
22896 return true;
22897 }
22898
22899
22900
22901
22902 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22903 {
22904 return $repo->hasPackage($package);
22905 }
22906
22907
22908
22909
22910 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22911 {
22912 if (!$repo->hasPackage($package)) {
22913 $repo->addPackage(clone $package);
22914 }
22915 }
22916
22917
22918
22919
22920 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22921 {
22922 if (!$repo->hasPackage($initial)) {
22923 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22924 }
22925
22926 $repo->removePackage($initial);
22927 if (!$repo->hasPackage($target)) {
22928 $repo->addPackage(clone $target);
22929 }
22930 }
22931
22932
22933
22934
22935 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22936 {
22937 if (!$repo->hasPackage($package)) {
22938 throw new \InvalidArgumentException('Package is not installed: '.$package);
22939 }
22940 $repo->removePackage($package);
22941 }
22942
22943
22944
22945
22946 public function getInstallPath(PackageInterface $package)
22947 {
22948 $targetDir = $package->getTargetDir();
22949
22950 return $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
22951 }
22952 }
22953 <?php
22954
22955
22956
22957
22958
22959
22960
22961
22962
22963
22964
22965 namespace Composer\Installer;
22966
22967 use Composer\Composer;
22968 use Composer\IO\IOInterface;
22969 use Composer\DependencyResolver\Operation\OperationInterface;
22970 use Composer\DependencyResolver\PolicyInterface;
22971 use Composer\DependencyResolver\Pool;
22972 use Composer\DependencyResolver\Request;
22973 use Composer\Repository\CompositeRepository;
22974
22975
22976
22977
22978
22979
22980 class PackageEvent extends InstallerEvent
22981 {
22982
22983
22984
22985 private $operation;
22986
22987
22988
22989
22990
22991
22992
22993
22994
22995
22996
22997
22998
22999
23000
23001 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
23002 {
23003 parent::__construct($eventName, $composer, $io, $devMode, $policy, $pool, $installedRepo, $request, $operations);
23004
23005 $this->operation = $operation;
23006 }
23007
23008
23009
23010
23011
23012
23013 public function getOperation()
23014 {
23015 return $this->operation;
23016 }
23017 }
23018 <?php
23019
23020
23021
23022
23023
23024
23025
23026
23027
23028
23029
23030 namespace Composer\Installer;
23031
23032
23033
23034
23035
23036
23037 class PackageEvents
23038 {
23039
23040
23041
23042
23043
23044
23045
23046 const PRE_PACKAGE_INSTALL = 'pre-package-install';
23047
23048
23049
23050
23051
23052
23053
23054
23055 const POST_PACKAGE_INSTALL = 'post-package-install';
23056
23057
23058
23059
23060
23061
23062
23063
23064 const PRE_PACKAGE_UPDATE = 'pre-package-update';
23065
23066
23067
23068
23069
23070
23071
23072
23073 const POST_PACKAGE_UPDATE = 'post-package-update';
23074
23075
23076
23077
23078
23079
23080
23081
23082 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
23083
23084
23085
23086
23087
23088
23089
23090
23091 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
23092 }
23093 <?php
23094
23095
23096
23097
23098
23099
23100
23101
23102
23103
23104
23105 namespace Composer\Installer;
23106
23107 use Composer\IO\IOInterface;
23108 use Composer\Package\PackageInterface;
23109 use Composer\Util\Filesystem;
23110 use Composer\Util\ProcessExecutor;
23111
23112
23113
23114
23115
23116
23117 class PearBinaryInstaller extends BinaryInstaller
23118 {
23119 private $installer;
23120 private $vendorDir;
23121
23122
23123
23124
23125
23126
23127
23128
23129
23130 public function __construct(IOInterface $io, $binDir, $vendorDir, $binCompat, Filesystem $filesystem, PearInstaller $installer)
23131 {
23132 parent::__construct($io, $binDir, $binCompat, $filesystem);
23133 $this->installer = $installer;
23134 $this->vendorDir = $vendorDir;
23135 }
23136
23137 protected function getBinaries(PackageInterface $package)
23138 {
23139 $binariesPath = $this->installer->getInstallPath($package) . '/bin/';
23140 $binaries = array();
23141 if (file_exists($binariesPath)) {
23142 foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::CURRENT_AS_FILEINFO) as $fileName => $value) {
23143 if (!$value->isDir()) {
23144 $binaries[] = 'bin/'.$fileName;
23145 }
23146 }
23147 }
23148
23149 return $binaries;
23150 }
23151
23152 protected function initializeBinDir()
23153 {
23154 parent::initializeBinDir();
23155 file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode());
23156 @chmod($this->binDir.'/composer-php', 0777);
23157 file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode());
23158 @chmod($this->binDir.'/composer-php.bat', 0777);
23159 }
23160
23161 protected function generateWindowsProxyCode($bin, $link)
23162 {
23163 $binPath = $this->filesystem->findShortestPath($link, $bin);
23164 if ('.bat' === substr($bin, -4)) {
23165 $caller = 'call';
23166 } else {
23167 $handle = fopen($bin, 'r');
23168 $line = fgets($handle);
23169 fclose($handle);
23170 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
23171 $caller = trim($match[1]);
23172 } else {
23173 $caller = 'php';
23174 }
23175
23176 if ($caller === 'php') {
23177 return "@echo off\r\n".
23178 "pushd .\r\n".
23179 "cd %~dp0\r\n".
23180 "set PHP_PROXY=%CD%\\composer-php.bat\r\n".
23181 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
23182 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
23183 "popd\r\n".
23184 "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n";
23185 }
23186 }
23187
23188 return "@echo off\r\n".
23189 "pushd .\r\n".
23190 "cd %~dp0\r\n".
23191 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
23192 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
23193 "popd\r\n".
23194 $caller." \"%BIN_TARGET%\" %*\r\n";
23195 }
23196
23197 private function generateWindowsPhpProxyCode()
23198 {
23199 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
23200
23201 return
23202 "@echo off\r\n" .
23203 "setlocal enabledelayedexpansion\r\n" .
23204 "set BIN_DIR=%~dp0\r\n" .
23205 "set VENDOR_DIR=%BIN_DIR%\\".$binToVendor."\r\n" .
23206 "set DIRS=.\r\n" .
23207 "FOR /D %%V IN (%VENDOR_DIR%\\*) DO (\r\n" .
23208 "    FOR /D %%P IN (%%V\\*) DO (\r\n" .
23209 "        set DIRS=!DIRS!;%%~fP\r\n" .
23210 "    )\r\n" .
23211 ")\r\n" .
23212 "php.exe -d include_path=!DIRS! %*\r\n";
23213 }
23214
23215 private function generateUnixyPhpProxyCode()
23216 {
23217 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
23218
23219 return
23220 "#!/usr/bin/env sh\n".
23221 "SRC_DIR=`pwd`\n".
23222 "BIN_DIR=`dirname $0`\n".
23223 "VENDOR_DIR=\$BIN_DIR/".escapeshellarg($binToVendor)."\n".
23224 "DIRS=\"\"\n".
23225 "for vendor in \$VENDOR_DIR/*; do\n".
23226 "    if [ -d \"\$vendor\" ]; then\n".
23227 "        for package in \$vendor/*; do\n".
23228 "            if [ -d \"\$package\" ]; then\n".
23229 "                DIRS=\"\${DIRS}:\${package}\"\n".
23230 "            fi\n".
23231 "        done\n".
23232 "    fi\n".
23233 "done\n".
23234 "php -d include_path=\".\$DIRS\" $@\n";
23235 }
23236 }
23237 <?php
23238
23239
23240
23241
23242
23243
23244
23245
23246
23247
23248
23249 namespace Composer\Installer;
23250
23251 use Composer\IO\IOInterface;
23252 use Composer\Composer;
23253 use Composer\Downloader\PearPackageExtractor;
23254 use Composer\Repository\InstalledRepositoryInterface;
23255 use Composer\Package\PackageInterface;
23256 use Composer\Util\Platform;
23257 use Composer\Util\Filesystem;
23258
23259
23260
23261
23262
23263
23264
23265 class PearInstaller extends LibraryInstaller
23266 {
23267
23268
23269
23270
23271
23272
23273
23274 public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
23275 {
23276 $filesystem = new Filesystem();
23277 $binaryInstaller = new PearBinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), rtrim($composer->getConfig()->get('vendor-dir'), '/'), $composer->getConfig()->get('bin-compat'), $filesystem, $this);
23278
23279 parent::__construct($io, $composer, $type, $filesystem, $binaryInstaller);
23280 }
23281
23282
23283
23284
23285 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23286 {
23287 $this->uninstall($repo, $initial);
23288 $this->install($repo, $target);
23289 }
23290
23291 protected function installCode(PackageInterface $package)
23292 {
23293 parent::installCode($package);
23294
23295 $isWindows = Platform::isWindows();
23296 $php_bin = $this->binDir . ($isWindows ? '/composer-php.bat' : '/composer-php');
23297
23298 if (!$isWindows) {
23299 $php_bin = '/usr/bin/env ' . $php_bin;
23300 }
23301
23302 $installPath = $this->getInstallPath($package);
23303 $vars = array(
23304 'os' => $isWindows ? 'windows' : 'linux',
23305 'php_bin' => $php_bin,
23306 'pear_php' => $installPath,
23307 'php_dir' => $installPath,
23308 'bin_dir' => $installPath . '/bin',
23309 'data_dir' => $installPath . '/data',
23310 'version' => $package->getPrettyVersion(),
23311 );
23312
23313 $packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
23314 $pearExtractor = new PearPackageExtractor($packageArchive);
23315 $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
23316
23317 $this->io->writeError('    Cleaning up', true, IOInterface::VERBOSE);
23318 $this->filesystem->unlink($packageArchive);
23319 }
23320 }
23321 <?php
23322
23323
23324
23325
23326
23327
23328
23329
23330
23331
23332
23333 namespace Composer\Installer;
23334
23335 use Composer\Composer;
23336 use Composer\IO\IOInterface;
23337 use Composer\Repository\InstalledRepositoryInterface;
23338 use Composer\Package\PackageInterface;
23339
23340
23341
23342
23343
23344
23345
23346 class PluginInstaller extends LibraryInstaller
23347 {
23348 private $installationManager;
23349
23350
23351
23352
23353
23354
23355
23356
23357 public function __construct(IOInterface $io, Composer $composer, $type = 'library')
23358 {
23359 parent::__construct($io, $composer, 'composer-plugin');
23360 $this->installationManager = $composer->getInstallationManager();
23361 }
23362
23363
23364
23365
23366 public function supports($packageType)
23367 {
23368 return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
23369 }
23370
23371
23372
23373
23374 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23375 {
23376 $extra = $package->getExtra();
23377 if (empty($extra['class'])) {
23378 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
23379 }
23380
23381 parent::install($repo, $package);
23382 try {
23383 $this->composer->getPluginManager()->registerPackage($package, true);
23384 } catch (\Exception $e) {
23385
23386  $this->io->writeError('Plugin installation failed, rolling back');
23387 parent::uninstall($repo, $package);
23388 throw $e;
23389 }
23390 }
23391
23392
23393
23394
23395 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23396 {
23397 $extra = $target->getExtra();
23398 if (empty($extra['class'])) {
23399 throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
23400 }
23401
23402 parent::update($repo, $initial, $target);
23403 $this->composer->getPluginManager()->registerPackage($target, true);
23404 }
23405 }
23406 <?php
23407
23408
23409
23410
23411
23412
23413
23414
23415
23416
23417
23418 namespace Composer\Installer;
23419
23420 use Composer\Package\PackageInterface;
23421 use Composer\Downloader\DownloadManager;
23422 use Composer\Repository\InstalledRepositoryInterface;
23423 use Composer\Util\Filesystem;
23424
23425
23426
23427
23428
23429
23430
23431 class ProjectInstaller implements InstallerInterface
23432 {
23433 private $installPath;
23434 private $downloadManager;
23435 private $filesystem;
23436
23437 public function __construct($installPath, DownloadManager $dm)
23438 {
23439 $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/';
23440 $this->downloadManager = $dm;
23441 $this->filesystem = new Filesystem;
23442 }
23443
23444
23445
23446
23447
23448
23449
23450 public function supports($packageType)
23451 {
23452 return true;
23453 }
23454
23455
23456
23457
23458 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23459 {
23460 return false;
23461 }
23462
23463
23464
23465
23466 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23467 {
23468 $installPath = $this->installPath;
23469 if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
23470 throw new \InvalidArgumentException("Project directory $installPath is not empty.");
23471 }
23472 if (!is_dir($installPath)) {
23473 mkdir($installPath, 0777, true);
23474 }
23475 $this->downloadManager->download($package, $installPath);
23476 }
23477
23478
23479
23480
23481 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23482 {
23483 throw new \InvalidArgumentException("not supported");
23484 }
23485
23486
23487
23488
23489 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23490 {
23491 throw new \InvalidArgumentException("not supported");
23492 }
23493
23494
23495
23496
23497
23498
23499
23500 public function getInstallPath(PackageInterface $package)
23501 {
23502 return $this->installPath;
23503 }
23504 }
23505 <?php
23506
23507
23508
23509
23510
23511
23512
23513
23514
23515
23516
23517 namespace Composer\Installer;
23518
23519 use Composer\IO\IOInterface;
23520 use Composer\Package\PackageInterface;
23521 use Composer\Repository\RepositoryInterface;
23522 use Symfony\Component\Console\Formatter\OutputFormatter;
23523
23524
23525
23526
23527
23528
23529 class SuggestedPackagesReporter
23530 {
23531
23532
23533
23534 protected $suggestedPackages = array();
23535
23536
23537
23538
23539 private $io;
23540
23541 public function __construct(IOInterface $io)
23542 {
23543 $this->io = $io;
23544 }
23545
23546
23547
23548
23549 public function getPackages()
23550 {
23551 return $this->suggestedPackages;
23552 }
23553
23554
23555
23556
23557
23558
23559
23560
23561
23562
23563
23564
23565 public function addPackage($source, $target, $reason)
23566 {
23567 $this->suggestedPackages[] = array(
23568 'source' => $source,
23569 'target' => $target,
23570 'reason' => $reason,
23571 );
23572
23573 return $this;
23574 }
23575
23576
23577
23578
23579
23580
23581
23582 public function addSuggestionsFromPackage(PackageInterface $package)
23583 {
23584 $source = $package->getPrettyName();
23585 foreach ($package->getSuggests() as $target => $reason) {
23586 $this->addPackage(
23587 $source,
23588 $target,
23589 $reason
23590 );
23591 }
23592
23593 return $this;
23594 }
23595
23596
23597
23598
23599
23600
23601
23602
23603 public function output(RepositoryInterface $installedRepo = null)
23604 {
23605 $suggestedPackages = $this->getPackages();
23606 $installedPackages = array();
23607 if (null !== $installedRepo && ! empty($suggestedPackages)) {
23608 foreach ($installedRepo->getPackages() as $package) {
23609 $installedPackages = array_merge(
23610 $installedPackages,
23611 $package->getNames()
23612 );
23613 }
23614 }
23615
23616 foreach ($suggestedPackages as $suggestion) {
23617 if (in_array($suggestion['target'], $installedPackages)) {
23618 continue;
23619 }
23620
23621 $this->io->writeError(sprintf(
23622 '%s suggests installing %s (%s)',
23623 $suggestion['source'],
23624 $this->escapeOutput($suggestion['target']),
23625 $this->escapeOutput($suggestion['reason'])
23626 ));
23627 }
23628
23629 return $this;
23630 }
23631
23632
23633
23634
23635
23636 private function escapeOutput($string)
23637 {
23638 return OutputFormatter::escape(
23639 $this->removeControlCharacters($string)
23640 );
23641 }
23642
23643
23644
23645
23646
23647 private function removeControlCharacters($string)
23648 {
23649 return preg_replace(
23650 '/[[:cntrl:]]/',
23651 '',
23652 str_replace("\n", ' ', $string)
23653 );
23654 }
23655 }
23656 <?php
23657
23658
23659
23660
23661
23662
23663
23664
23665
23666
23667
23668 namespace Composer\Json;
23669
23670 use JsonSchema\Validator;
23671 use Seld\JsonLint\JsonParser;
23672 use Seld\JsonLint\ParsingException;
23673 use Composer\Util\RemoteFilesystem;
23674 use Composer\IO\IOInterface;
23675 use Composer\Downloader\TransportException;
23676
23677
23678
23679
23680
23681
23682
23683 class JsonFile
23684 {
23685 const LAX_SCHEMA = 1;
23686 const STRICT_SCHEMA = 2;
23687
23688 const JSON_UNESCAPED_SLASHES = 64;
23689 const JSON_PRETTY_PRINT = 128;
23690 const JSON_UNESCAPED_UNICODE = 256;
23691
23692 private $path;
23693 private $rfs;
23694 private $io;
23695
23696
23697
23698
23699
23700
23701
23702
23703
23704 public function __construct($path, RemoteFilesystem $rfs = null, IOInterface $io = null)
23705 {
23706 $this->path = $path;
23707
23708 if (null === $rfs && preg_match('{^https?://}i', $path)) {
23709 throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed');
23710 }
23711 $this->rfs = $rfs;
23712 $this->io = $io;
23713 }
23714
23715
23716
23717
23718 public function getPath()
23719 {
23720 return $this->path;
23721 }
23722
23723
23724
23725
23726
23727
23728 public function exists()
23729 {
23730 return is_file($this->path);
23731 }
23732
23733
23734
23735
23736
23737
23738
23739 public function read()
23740 {
23741 try {
23742 if ($this->rfs) {
23743 $json = $this->rfs->getContents($this->path, $this->path, false);
23744 } else {
23745 if ($this->io && $this->io->isDebug()) {
23746 $this->io->writeError('Reading ' . $this->path);
23747 }
23748 $json = file_get_contents($this->path);
23749 }
23750 } catch (TransportException $e) {
23751 throw new \RuntimeException($e->getMessage(), 0, $e);
23752 } catch (\Exception $e) {
23753 throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
23754 }
23755
23756 return static::parseJson($json, $this->path);
23757 }
23758
23759
23760
23761
23762
23763
23764
23765
23766 public function write(array $hash, $options = 448)
23767 {
23768 $dir = dirname($this->path);
23769 if (!is_dir($dir)) {
23770 if (file_exists($dir)) {
23771 throw new \UnexpectedValueException(
23772 $dir.' exists and is not a directory.'
23773 );
23774 }
23775 if (!@mkdir($dir, 0777, true)) {
23776 throw new \UnexpectedValueException(
23777 $dir.' does not exist and could not be created.'
23778 );
23779 }
23780 }
23781
23782 $retries = 3;
23783 while ($retries--) {
23784 try {
23785 file_put_contents($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : ''));
23786 break;
23787 } catch (\Exception $e) {
23788 if ($retries) {
23789 usleep(500000);
23790 continue;
23791 }
23792
23793 throw $e;
23794 }
23795 }
23796 }
23797
23798
23799
23800
23801
23802
23803
23804
23805 public function validateSchema($schema = self::STRICT_SCHEMA)
23806 {
23807 $content = file_get_contents($this->path);
23808 $data = json_decode($content);
23809
23810 if (null === $data && 'null' !== $content) {
23811 self::validateSyntax($content, $this->path);
23812 }
23813
23814 $schemaFile = __DIR__ . '/../../../res/composer-schema.json';
23815
23816
23817  if (false === strpos($schemaFile, '://')) {
23818 $schemaFile = 'file://' . $schemaFile;
23819 }
23820
23821 $schemaData = (object) array('$ref' => $schemaFile);
23822
23823 if ($schema === self::LAX_SCHEMA) {
23824 $schemaData->additionalProperties = true;
23825 $schemaData->required = array();
23826 }
23827
23828 $validator = new Validator();
23829 $validator->check($data, $schemaData);
23830
23831
23832
23833 if (!$validator->isValid()) {
23834 $errors = array();
23835 foreach ((array) $validator->getErrors() as $error) {
23836 $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
23837 }
23838 throw new JsonValidationException('"'.$this->path.'" does not match the expected JSON schema', $errors);
23839 }
23840
23841 return true;
23842 }
23843
23844
23845
23846
23847
23848
23849
23850
23851 public static function encode($data, $options = 448)
23852 {
23853 if (PHP_VERSION_ID >= 50400) {
23854 $json = json_encode($data, $options);
23855 if (false === $json) {
23856 self::throwEncodeError(json_last_error());
23857 }
23858
23859
23860  if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
23861 $json = preg_replace('/\[\s+\]/', '[]', $json);
23862 $json = preg_replace('/\{\s+\}/', '{}', $json);
23863 }
23864
23865 return $json;
23866 }
23867
23868 $json = json_encode($data);
23869 if (false === $json) {
23870 self::throwEncodeError(json_last_error());
23871 }
23872
23873 $prettyPrint = (bool) ($options & self::JSON_PRETTY_PRINT);
23874 $unescapeUnicode = (bool) ($options & self::JSON_UNESCAPED_UNICODE);
23875 $unescapeSlashes = (bool) ($options & self::JSON_UNESCAPED_SLASHES);
23876
23877 if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes) {
23878 return $json;
23879 }
23880
23881 return JsonFormatter::format($json, $unescapeUnicode, $unescapeSlashes);
23882 }
23883
23884
23885
23886
23887
23888
23889
23890 private static function throwEncodeError($code)
23891 {
23892 switch ($code) {
23893 case JSON_ERROR_DEPTH:
23894 $msg = 'Maximum stack depth exceeded';
23895 break;
23896 case JSON_ERROR_STATE_MISMATCH:
23897 $msg = 'Underflow or the modes mismatch';
23898 break;
23899 case JSON_ERROR_CTRL_CHAR:
23900 $msg = 'Unexpected control character found';
23901 break;
23902 case JSON_ERROR_UTF8:
23903 $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
23904 break;
23905 default:
23906 $msg = 'Unknown error';
23907 }
23908
23909 throw new \RuntimeException('JSON encoding failed: '.$msg);
23910 }
23911
23912
23913
23914
23915
23916
23917
23918
23919
23920 public static function parseJson($json, $file = null)
23921 {
23922 if (null === $json) {
23923 return;
23924 }
23925 $data = json_decode($json, true);
23926 if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
23927 self::validateSyntax($json, $file);
23928 }
23929
23930 return $data;
23931 }
23932
23933
23934
23935
23936
23937
23938
23939
23940
23941
23942
23943 protected static function validateSyntax($json, $file = null)
23944 {
23945 $parser = new JsonParser();
23946 $result = $parser->lint($json);
23947 if (null === $result) {
23948 if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
23949 throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
23950 }
23951
23952 return true;
23953 }
23954
23955 throw new ParsingException('"'.$file.'" does not contain valid JSON'."\n".$result->getMessage(), $result->getDetails());
23956 }
23957 }
23958 <?php
23959
23960
23961
23962
23963
23964
23965
23966
23967
23968
23969
23970 namespace Composer\Json;
23971
23972
23973
23974
23975
23976
23977
23978
23979
23980 class JsonFormatter
23981 {
23982
23983
23984
23985
23986
23987
23988
23989
23990
23991
23992
23993
23994 public static function format($json, $unescapeUnicode, $unescapeSlashes)
23995 {
23996 $result = '';
23997 $pos = 0;
23998 $strLen = strlen($json);
23999 $indentStr = '    ';
24000 $newLine = "\n";
24001 $outOfQuotes = true;
24002 $buffer = '';
24003 $noescape = true;
24004
24005 for ($i = 0; $i < $strLen; $i++) {
24006
24007  $char = substr($json, $i, 1);
24008
24009
24010  if ('"' === $char && $noescape) {
24011 $outOfQuotes = !$outOfQuotes;
24012 }
24013
24014 if (!$outOfQuotes) {
24015 $buffer .= $char;
24016 $noescape = '\\' === $char ? !$noescape : true;
24017 continue;
24018 } elseif ('' !== $buffer) {
24019 if ($unescapeSlashes) {
24020 $buffer = str_replace('\\/', '/', $buffer);
24021 }
24022
24023 if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
24024
24025  $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) {
24026 $l = strlen($match[1]);
24027
24028 if ($l % 2) {
24029 return str_repeat('\\', $l - 1) . mb_convert_encoding(
24030 pack('H*', $match[2]),
24031 'UTF-8',
24032 'UCS-2BE'
24033 );
24034 }
24035
24036 return $match[0];
24037 }, $buffer);
24038 }
24039
24040 $result .= $buffer.$char;
24041 $buffer = '';
24042 continue;
24043 }
24044
24045 if (':' === $char) {
24046
24047  $char .= ' ';
24048 } elseif (('}' === $char || ']' === $char)) {
24049 $pos--;
24050 $prevChar = substr($json, $i - 1, 1);
24051
24052 if ('{' !== $prevChar && '[' !== $prevChar) {
24053
24054  
24055  $result .= $newLine;
24056 for ($j = 0; $j < $pos; $j++) {
24057 $result .= $indentStr;
24058 }
24059 } else {
24060
24061  $result = rtrim($result);
24062 }
24063 }
24064
24065 $result .= $char;
24066
24067
24068  
24069  if (',' === $char || '{' === $char || '[' === $char) {
24070 $result .= $newLine;
24071
24072 if ('{' === $char || '[' === $char) {
24073 $pos++;
24074 }
24075
24076 for ($j = 0; $j < $pos; $j++) {
24077 $result .= $indentStr;
24078 }
24079 }
24080 }
24081
24082 return $result;
24083 }
24084 }
24085 <?php
24086
24087
24088
24089
24090
24091
24092
24093
24094
24095
24096
24097 namespace Composer\Json;
24098
24099 use Composer\Repository\PlatformRepository;
24100
24101
24102
24103
24104 class JsonManipulator
24105 {
24106 private static $DEFINES = '(?(DEFINE)
24107        (?<number>   -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
24108        (?<boolean>   true | false | null )
24109        (?<string>    " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
24110        (?<array>     \[  (?:  (?&json) \s* (?: , (?&json) \s* )*  )?  \s* \] )
24111        (?<pair>      \s* (?&string) \s* : (?&json) \s* )
24112        (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
24113        (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
24114     )';
24115
24116 private $contents;
24117 private $newline;
24118 private $indent;
24119
24120 public function __construct($contents)
24121 {
24122 $contents = trim($contents);
24123 if ($contents === '') {
24124 $contents = '{}';
24125 }
24126 if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) {
24127 throw new \InvalidArgumentException('The json file must be an object ({})');
24128 }
24129 $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
24130 $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
24131 $this->detectIndenting();
24132 }
24133
24134 public function getContents()
24135 {
24136 return $this->contents . $this->newline;
24137 }
24138
24139 public function addLink($type, $package, $constraint, $sortPackages = false)
24140 {
24141 $decoded = JsonFile::parseJson($this->contents);
24142
24143
24144  if (!isset($decoded[$type])) {
24145 return $this->addMainKey($type, array($package => $constraint));
24146 }
24147
24148 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24149 '(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
24150 if (!$this->pregMatch($regex, $this->contents, $matches)) {
24151 return false;
24152 }
24153
24154 $links = $matches['value'];
24155
24156
24157  $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
24158 $regex = '{'.self::$DEFINES.'"(?P<package>'.$packageRegex.')"(\s*:\s*)(?&string)}ix';
24159 if ($this->pregMatch($regex, $links, $packageMatches)) {
24160
24161  $existingPackage = $packageMatches['package'];
24162 $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage));
24163 $links = preg_replace_callback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P<separator>\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) {
24164 return JsonFile::encode(str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"';
24165 }, $links);
24166 } else {
24167 if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
24168
24169  $links = preg_replace(
24170 '{'.preg_quote($match[1]).'$}',
24171
24172  addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
24173 $links
24174 );
24175 } else {
24176
24177  $links = '{' . $this->newline .
24178 $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
24179 $this->indent . '}';
24180 }
24181 }
24182
24183 if (true === $sortPackages) {
24184 $requirements = json_decode($links, true);
24185 $this->sortPackages($requirements);
24186 $links = $this->format($requirements);
24187 }
24188
24189 $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end'];
24190
24191 return true;
24192 }
24193
24194
24195
24196
24197
24198
24199
24200
24201 private function sortPackages(array &$packages = array())
24202 {
24203 $prefix = function ($requirement) {
24204 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) {
24205 return preg_replace(
24206 array(
24207 '/^php/',
24208 '/^hhvm/',
24209 '/^ext/',
24210 '/^lib/',
24211 '/^\D/',
24212 ),
24213 array(
24214 '0-$0',
24215 '1-$0',
24216 '2-$0',
24217 '3-$0',
24218 '4-$0',
24219 ),
24220 $requirement
24221 );
24222 }
24223
24224 return '5-'.$requirement;
24225 };
24226
24227 uksort($packages, function ($a, $b) use ($prefix) {
24228 return strnatcmp($prefix($a), $prefix($b));
24229 });
24230 }
24231
24232 public function addRepository($name, $config)
24233 {
24234 return $this->addSubNode('repositories', $name, $config);
24235 }
24236
24237 public function removeRepository($name)
24238 {
24239 return $this->removeSubNode('repositories', $name);
24240 }
24241
24242 public function addConfigSetting($name, $value)
24243 {
24244 return $this->addSubNode('config', $name, $value);
24245 }
24246
24247 public function removeConfigSetting($name)
24248 {
24249 return $this->removeSubNode('config', $name);
24250 }
24251
24252 public function addProperty($name, $value)
24253 {
24254 if (substr($name, 0, 6) === 'extra.') {
24255 return $this->addSubNode('extra', substr($name, 6), $value);
24256 }
24257
24258 return $this->addMainKey($name, $value);
24259 }
24260
24261 public function removeProperty($name)
24262 {
24263 if (substr($name, 0, 6) === 'extra.') {
24264 return $this->removeSubNode('extra', substr($name, 6));
24265 }
24266
24267 return $this->removeMainKey($name);
24268 }
24269
24270 public function addSubNode($mainNode, $name, $value)
24271 {
24272 $decoded = JsonFile::parseJson($this->contents);
24273
24274 $subName = null;
24275 if (in_array($mainNode, array('config', 'extra')) && false !== strpos($name, '.')) {
24276 list($name, $subName) = explode('.', $name, 2);
24277 }
24278
24279
24280  if (!isset($decoded[$mainNode])) {
24281 if ($subName !== null) {
24282 $this->addMainKey($mainNode, array($name => array($subName => $value)));
24283 } else {
24284 $this->addMainKey($mainNode, array($name => $value));
24285 }
24286
24287 return true;
24288 }
24289
24290
24291  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
24292 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
24293
24294 try {
24295 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
24296 return false;
24297 }
24298 } catch (\RuntimeException $e) {
24299 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
24300 return false;
24301 }
24302 throw $e;
24303 }
24304
24305 $children = $match['content'];
24306
24307  if (!@json_decode($children)) {
24308 return false;
24309 }
24310
24311 $that = $this;
24312
24313
24314  $childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
24315 if ($this->pregMatch($childRegex, $children, $matches)) {
24316 $children = preg_replace_callback($childRegex, function ($matches) use ($name, $subName, $value, $that) {
24317 if ($subName !== null) {
24318 $curVal = json_decode($matches['content'], true);
24319 if (!is_array($curVal)) {
24320 $curVal = array();
24321 }
24322 $curVal[$subName] = $value;
24323 $value = $curVal;
24324 }
24325
24326 return $matches['start'] . $that->format($value, 1) . $matches['end'];
24327 }, $children);
24328 } else {
24329 $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
24330
24331 $whitespace = '';
24332 if (!empty($match['trailingspace'])) {
24333 $whitespace = $match['trailingspace'];
24334 }
24335
24336 if (!empty($match['content'])) {
24337 if ($subName !== null) {
24338 $value = array($subName => $value);
24339 }
24340
24341
24342  $children = preg_replace(
24343 '#'.$whitespace.'}$#',
24344 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}', '\\$'),
24345 $children
24346 );
24347 } else {
24348 if ($subName !== null) {
24349 $value = array($subName => $value);
24350 }
24351
24352
24353  $children = '{' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}';
24354 }
24355 }
24356
24357 $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) {
24358 return $m['start'] . $children . $m['end'];
24359 }, $this->contents);
24360
24361 return true;
24362 }
24363
24364 public function removeSubNode($mainNode, $name)
24365 {
24366 $decoded = JsonFile::parseJson($this->contents);
24367
24368
24369  if (empty($decoded[$mainNode])) {
24370 return true;
24371 }
24372
24373
24374  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
24375 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
24376 try {
24377 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
24378 return false;
24379 }
24380 } catch (\RuntimeException $e) {
24381 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
24382 return false;
24383 }
24384 throw $e;
24385 }
24386
24387 $children = $match['content'];
24388
24389
24390  if (!@json_decode($children, true)) {
24391 return false;
24392 }
24393
24394 $subName = null;
24395 if (in_array($mainNode, array('config', 'extra')) && false !== strpos($name, '.')) {
24396 list($name, $subName) = explode('.', $name, 2);
24397 }
24398
24399
24400  if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
24401 return true;
24402 }
24403
24404
24405  if ($this->pregMatch('{"'.preg_quote($name).'"\s*:}i', $children)) {
24406
24407  if (preg_match_all('{'.self::$DEFINES.'"'.preg_quote($name).'"\s*:\s*(?:(?&json))}x', $children, $matches)) {
24408 $bestMatch = '';
24409 foreach ($matches[0] as $match) {
24410 if (strlen($bestMatch) < strlen($match)) {
24411 $bestMatch = $match;
24412 }
24413 }
24414 $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count);
24415 if (1 !== $count) {
24416 $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count);
24417 if (1 !== $count) {
24418 return false;
24419 }
24420 }
24421 }
24422 } else {
24423 $childrenClean = $children;
24424 }
24425
24426
24427  $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $childrenClean, $match);
24428 if (empty($match['content'])) {
24429 $newline = $this->newline;
24430 $indent = $this->indent;
24431
24432 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($indent, $newline) {
24433 return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
24434 }, $this->contents);
24435
24436
24437  if ($subName !== null) {
24438 $curVal = json_decode($children, true);
24439 unset($curVal[$name][$subName]);
24440 $this->addSubNode($mainNode, $name, $curVal[$name]);
24441 }
24442
24443 return true;
24444 }
24445
24446 $that = $this;
24447 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
24448 if ($subName !== null) {
24449 $curVal = json_decode($matches['content'], true);
24450 unset($curVal[$name][$subName]);
24451 $childrenClean = $that->format($curVal, 0);
24452 }
24453
24454 return $matches['start'] . $childrenClean . $matches['end'];
24455 }, $this->contents);
24456
24457 return true;
24458 }
24459
24460 public function addMainKey($key, $content)
24461 {
24462 $decoded = JsonFile::parseJson($this->contents);
24463 $content = $this->format($content);
24464
24465
24466  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24467 '(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}sx';
24468 if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
24469
24470  if (!@json_decode('{'.$matches['key'].'}')) {
24471 return false;
24472 }
24473
24474 $this->contents = $matches['start'] . JsonFile::encode($key).': '.$content . $matches['end'];
24475
24476 return true;
24477 }
24478
24479
24480  if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
24481 $this->contents = preg_replace(
24482 '#'.$match[1].'\}$#',
24483 addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'),
24484 $this->contents
24485 );
24486
24487 return true;
24488 }
24489
24490
24491  $this->contents = preg_replace(
24492 '#\}$#',
24493 addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'),
24494 $this->contents
24495 );
24496
24497 return true;
24498 }
24499
24500 public function removeMainKey($key)
24501 {
24502 $decoded = JsonFile::parseJson($this->contents);
24503
24504 if (!array_key_exists($key, $decoded)) {
24505 return true;
24506 }
24507
24508
24509  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24510 '(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
24511 if ($this->pregMatch($regex, $this->contents, $matches)) {
24512
24513  if (!@json_decode('{'.$matches['removal'].'}')) {
24514 return false;
24515 }
24516
24517
24518  if (preg_match('#,\s*$#', $matches['start']) && preg_match('#^\}$#', $matches['end'])) {
24519 $matches['start'] = rtrim(preg_replace('#,(\s*)$#', '$1', $matches['start']), $this->indent);
24520 }
24521
24522 $this->contents = $matches['start'] . $matches['end'];
24523 if (preg_match('#^\{\s*\}\s*$#', $this->contents)) {
24524 $this->contents = "{\n}";
24525 }
24526
24527 return true;
24528 }
24529
24530 return false;
24531 }
24532
24533 public function format($data, $depth = 0)
24534 {
24535 if (is_array($data)) {
24536 reset($data);
24537
24538 if (is_numeric(key($data))) {
24539 foreach ($data as $key => $val) {
24540 $data[$key] = $this->format($val, $depth + 1);
24541 }
24542
24543 return '['.implode(', ', $data).']';
24544 }
24545
24546 $out = '{' . $this->newline;
24547 $elems = array();
24548 foreach ($data as $key => $val) {
24549 $elems[] = str_repeat($this->indent, $depth + 2) . JsonFile::encode($key). ': '.$this->format($val, $depth + 1);
24550 }
24551
24552 return $out . implode(','.$this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
24553 }
24554
24555 return JsonFile::encode($data);
24556 }
24557
24558 protected function detectIndenting()
24559 {
24560 if ($this->pregMatch('{^([ \t]+)"}m', $this->contents, $match)) {
24561 $this->indent = $match[1];
24562 } else {
24563 $this->indent = '    ';
24564 }
24565 }
24566
24567 protected function pregMatch($re, $str, &$matches = array())
24568 {
24569 $count = preg_match($re, $str, $matches);
24570
24571 if ($count === false) {
24572 switch (preg_last_error()) {
24573 case PREG_NO_ERROR:
24574 throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR);
24575 case PREG_INTERNAL_ERROR:
24576 throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR);
24577 case PREG_BACKTRACK_LIMIT_ERROR:
24578 throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR);
24579 case PREG_RECURSION_LIMIT_ERROR:
24580 throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR);
24581 case PREG_BAD_UTF8_ERROR:
24582 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR);
24583 case PREG_BAD_UTF8_OFFSET_ERROR:
24584 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR);
24585 case 6: 
24586  if (PHP_VERSION_ID > 70000) {
24587 throw new \RuntimeException('Failed to execute regex: PREG_JIT_STACKLIMIT_ERROR', 6);
24588 }
24589
24590
24591 default:
24592 throw new \RuntimeException('Failed to execute regex: Unknown error');
24593 }
24594 }
24595
24596 return $count;
24597 }
24598 }
24599 <?php
24600
24601
24602
24603
24604
24605
24606
24607
24608
24609
24610
24611 namespace Composer\Json;
24612
24613 use Exception;
24614
24615
24616
24617
24618 class JsonValidationException extends Exception
24619 {
24620 protected $errors;
24621
24622 public function __construct($message, $errors = array(), Exception $previous = null)
24623 {
24624 $this->errors = $errors;
24625 parent::__construct($message, 0, $previous);
24626 }
24627
24628 public function getErrors()
24629 {
24630 return $this->errors;
24631 }
24632 }
24633 <?php
24634
24635
24636
24637
24638
24639
24640
24641
24642
24643
24644
24645 namespace Composer\Package;
24646
24647 use Composer\Semver\Constraint\Constraint;
24648 use Composer\Package\Version\VersionParser;
24649
24650
24651
24652
24653 class AliasPackage extends BasePackage implements CompletePackageInterface
24654 {
24655 protected $version;
24656 protected $prettyVersion;
24657 protected $dev;
24658 protected $rootPackageAlias = false;
24659 protected $stability;
24660
24661
24662 protected $aliasOf;
24663
24664 protected $requires;
24665
24666 protected $devRequires;
24667
24668 protected $conflicts;
24669
24670 protected $provides;
24671
24672 protected $replaces;
24673
24674
24675
24676
24677
24678
24679
24680
24681 public function __construct(PackageInterface $aliasOf, $version, $prettyVersion)
24682 {
24683 parent::__construct($aliasOf->getName());
24684
24685 $this->version = $version;
24686 $this->prettyVersion = $prettyVersion;
24687 $this->aliasOf = $aliasOf;
24688 $this->stability = VersionParser::parseStability($version);
24689 $this->dev = $this->stability === 'dev';
24690
24691 foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) {
24692 $links = $aliasOf->{'get' . ucfirst($type)}();
24693 $this->$type = $this->replaceSelfVersionDependencies($links, $type);
24694 }
24695 }
24696
24697
24698
24699
24700 public function getAliasOf()
24701 {
24702 return $this->aliasOf;
24703 }
24704
24705
24706
24707
24708 public function getVersion()
24709 {
24710 return $this->version;
24711 }
24712
24713
24714
24715
24716 public function getStability()
24717 {
24718 return $this->stability;
24719 }
24720
24721
24722
24723
24724 public function getPrettyVersion()
24725 {
24726 return $this->prettyVersion;
24727 }
24728
24729
24730
24731
24732 public function isDev()
24733 {
24734 return $this->dev;
24735 }
24736
24737
24738
24739
24740 public function getRequires()
24741 {
24742 return $this->requires;
24743 }
24744
24745
24746
24747
24748 public function getConflicts()
24749 {
24750 return $this->conflicts;
24751 }
24752
24753
24754
24755
24756 public function getProvides()
24757 {
24758 return $this->provides;
24759 }
24760
24761
24762
24763
24764 public function getReplaces()
24765 {
24766 return $this->replaces;
24767 }
24768
24769
24770
24771
24772 public function getDevRequires()
24773 {
24774 return $this->devRequires;
24775 }
24776
24777
24778
24779
24780
24781
24782
24783
24784
24785
24786 public function setRootPackageAlias($value)
24787 {
24788 return $this->rootPackageAlias = $value;
24789 }
24790
24791
24792
24793
24794
24795 public function isRootPackageAlias()
24796 {
24797 return $this->rootPackageAlias;
24798 }
24799
24800
24801
24802
24803
24804
24805
24806 protected function replaceSelfVersionDependencies(array $links, $linkType)
24807 {
24808 if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
24809 $newLinks = array();
24810 foreach ($links as $link) {
24811
24812  if ('self.version' === $link->getPrettyConstraint()) {
24813 $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
24814 }
24815 }
24816 $links = array_merge($links, $newLinks);
24817 } else {
24818 foreach ($links as $index => $link) {
24819 if ('self.version' === $link->getPrettyConstraint()) {
24820 $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
24821 }
24822 }
24823 }
24824
24825 return $links;
24826 }
24827
24828
24829
24830
24831
24832 public function getType()
24833 {
24834 return $this->aliasOf->getType();
24835 }
24836
24837 public function getTargetDir()
24838 {
24839 return $this->aliasOf->getTargetDir();
24840 }
24841
24842 public function getExtra()
24843 {
24844 return $this->aliasOf->getExtra();
24845 }
24846
24847 public function setInstallationSource($type)
24848 {
24849 $this->aliasOf->setInstallationSource($type);
24850 }
24851
24852 public function getInstallationSource()
24853 {
24854 return $this->aliasOf->getInstallationSource();
24855 }
24856
24857 public function getSourceType()
24858 {
24859 return $this->aliasOf->getSourceType();
24860 }
24861
24862 public function getSourceUrl()
24863 {
24864 return $this->aliasOf->getSourceUrl();
24865 }
24866
24867 public function getSourceUrls()
24868 {
24869 return $this->aliasOf->getSourceUrls();
24870 }
24871
24872 public function getSourceReference()
24873 {
24874 return $this->aliasOf->getSourceReference();
24875 }
24876
24877 public function setSourceReference($reference)
24878 {
24879 return $this->aliasOf->setSourceReference($reference);
24880 }
24881
24882 public function setSourceMirrors($mirrors)
24883 {
24884 return $this->aliasOf->setSourceMirrors($mirrors);
24885 }
24886
24887 public function getSourceMirrors()
24888 {
24889 return $this->aliasOf->getSourceMirrors();
24890 }
24891
24892 public function getDistType()
24893 {
24894 return $this->aliasOf->getDistType();
24895 }
24896
24897 public function getDistUrl()
24898 {
24899 return $this->aliasOf->getDistUrl();
24900 }
24901
24902 public function getDistUrls()
24903 {
24904 return $this->aliasOf->getDistUrls();
24905 }
24906
24907 public function getDistReference()
24908 {
24909 return $this->aliasOf->getDistReference();
24910 }
24911
24912 public function setDistReference($reference)
24913 {
24914 return $this->aliasOf->setDistReference($reference);
24915 }
24916
24917 public function getDistSha1Checksum()
24918 {
24919 return $this->aliasOf->getDistSha1Checksum();
24920 }
24921
24922 public function setTransportOptions(array $options)
24923 {
24924 return $this->aliasOf->setTransportOptions($options);
24925 }
24926
24927 public function getTransportOptions()
24928 {
24929 return $this->aliasOf->getTransportOptions();
24930 }
24931
24932 public function setDistMirrors($mirrors)
24933 {
24934 return $this->aliasOf->setDistMirrors($mirrors);
24935 }
24936
24937 public function getDistMirrors()
24938 {
24939 return $this->aliasOf->getDistMirrors();
24940 }
24941
24942 public function getScripts()
24943 {
24944 return $this->aliasOf->getScripts();
24945 }
24946
24947 public function getLicense()
24948 {
24949 return $this->aliasOf->getLicense();
24950 }
24951
24952 public function getAutoload()
24953 {
24954 return $this->aliasOf->getAutoload();
24955 }
24956
24957 public function getDevAutoload()
24958 {
24959 return $this->aliasOf->getDevAutoload();
24960 }
24961
24962 public function getIncludePaths()
24963 {
24964 return $this->aliasOf->getIncludePaths();
24965 }
24966
24967 public function getRepositories()
24968 {
24969 return $this->aliasOf->getRepositories();
24970 }
24971
24972 public function getReleaseDate()
24973 {
24974 return $this->aliasOf->getReleaseDate();
24975 }
24976
24977 public function getBinaries()
24978 {
24979 return $this->aliasOf->getBinaries();
24980 }
24981
24982 public function getKeywords()
24983 {
24984 return $this->aliasOf->getKeywords();
24985 }
24986
24987 public function getDescription()
24988 {
24989 return $this->aliasOf->getDescription();
24990 }
24991
24992 public function getHomepage()
24993 {
24994 return $this->aliasOf->getHomepage();
24995 }
24996
24997 public function getSuggests()
24998 {
24999 return $this->aliasOf->getSuggests();
25000 }
25001
25002 public function getAuthors()
25003 {
25004 return $this->aliasOf->getAuthors();
25005 }
25006
25007 public function getSupport()
25008 {
25009 return $this->aliasOf->getSupport();
25010 }
25011
25012 public function getNotificationUrl()
25013 {
25014 return $this->aliasOf->getNotificationUrl();
25015 }
25016
25017 public function getArchiveExcludes()
25018 {
25019 return $this->aliasOf->getArchiveExcludes();
25020 }
25021
25022 public function isAbandoned()
25023 {
25024 return $this->aliasOf->isAbandoned();
25025 }
25026
25027 public function getReplacementPackage()
25028 {
25029 return $this->aliasOf->getReplacementPackage();
25030 }
25031
25032 public function __toString()
25033 {
25034 return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
25035 }
25036 }
25037 <?php
25038
25039
25040
25041
25042
25043
25044
25045
25046
25047
25048
25049 namespace Composer\Package\Archiver;
25050
25051 use FilterIterator;
25052 use PharData;
25053
25054 class ArchivableFilesFilter extends FilterIterator
25055 {
25056 private $dirs = array();
25057
25058
25059
25060
25061 public function accept()
25062 {
25063 $file = $this->getInnerIterator()->current();
25064 if ($file->isDir()) {
25065 $this->dirs[] = (string) $file;
25066
25067 return false;
25068 }
25069
25070 return true;
25071 }
25072
25073 public function addEmptyDir(PharData $phar, $sources)
25074 {
25075 foreach ($this->dirs as $filepath) {
25076 $localname = str_replace($sources . "/", '', $filepath);
25077 $phar->addEmptyDir($localname);
25078 }
25079 }
25080 }
25081 <?php
25082
25083
25084
25085
25086
25087
25088
25089
25090
25091
25092
25093 namespace Composer\Package\Archiver;
25094
25095 use Composer\Util\Filesystem;
25096 use FilesystemIterator;
25097 use Symfony\Component\Finder\Finder;
25098 use Symfony\Component\Finder\SplFileInfo;
25099
25100
25101
25102
25103
25104
25105
25106
25107
25108 class ArchivableFilesFinder extends \FilterIterator
25109 {
25110
25111
25112
25113 protected $finder;
25114
25115
25116
25117
25118
25119
25120
25121
25122 public function __construct($sources, array $excludes, $ignoreFilters = false)
25123 {
25124 $fs = new Filesystem();
25125
25126 $sources = $fs->normalizePath($sources);
25127
25128 if ($ignoreFilters) {
25129 $filters = array();
25130 } else {
25131 $filters = array(
25132 new HgExcludeFilter($sources),
25133 new GitExcludeFilter($sources),
25134 new ComposerExcludeFilter($sources, $excludes),
25135 );
25136 }
25137
25138 $this->finder = new Finder();
25139
25140 $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
25141 if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) {
25142 return false;
25143 }
25144
25145 $relativePath = preg_replace(
25146 '#^'.preg_quote($sources, '#').'#',
25147 '',
25148 $fs->normalizePath($file->getRealPath())
25149 );
25150
25151 $exclude = false;
25152 foreach ($filters as $filter) {
25153 $exclude = $filter->filter($relativePath, $exclude);
25154 }
25155
25156 return !$exclude;
25157 };
25158
25159 if (method_exists($filter, 'bindTo')) {
25160 $filter = $filter->bindTo(null);
25161 }
25162
25163 $this->finder
25164 ->in($sources)
25165 ->filter($filter)
25166 ->ignoreVCS(true)
25167 ->ignoreDotFiles(false);
25168
25169 parent::__construct($this->finder->getIterator());
25170 }
25171
25172 public function accept()
25173 {
25174
25175 $current = $this->getInnerIterator()->current();
25176
25177 if (!$current->isDir()) {
25178 return true;
25179 }
25180
25181 $iterator = new FilesystemIterator($current, FilesystemIterator::SKIP_DOTS);
25182
25183 return !$iterator->valid();
25184 }
25185 }
25186 <?php
25187
25188
25189
25190
25191
25192
25193
25194
25195
25196
25197
25198 namespace Composer\Package\Archiver;
25199
25200 use Composer\Downloader\DownloadManager;
25201 use Composer\Package\PackageInterface;
25202 use Composer\Package\RootPackageInterface;
25203 use Composer\Util\Filesystem;
25204 use Composer\Json\JsonFile;
25205
25206
25207
25208
25209
25210 class ArchiveManager
25211 {
25212 protected $downloadManager;
25213
25214 protected $archivers = array();
25215
25216
25217
25218
25219 protected $overwriteFiles = true;
25220
25221
25222
25223
25224 public function __construct(DownloadManager $downloadManager)
25225 {
25226 $this->downloadManager = $downloadManager;
25227 }
25228
25229
25230
25231
25232 public function addArchiver(ArchiverInterface $archiver)
25233 {
25234 $this->archivers[] = $archiver;
25235 }
25236
25237
25238
25239
25240
25241
25242
25243
25244 public function setOverwriteFiles($overwriteFiles)
25245 {
25246 $this->overwriteFiles = $overwriteFiles;
25247
25248 return $this;
25249 }
25250
25251
25252
25253
25254
25255
25256
25257
25258 public function getPackageFilename(PackageInterface $package)
25259 {
25260 $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
25261
25262 if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
25263 $nameParts = array_merge($nameParts, array($package->getDistReference(), $package->getDistType()));
25264 } else {
25265 $nameParts = array_merge($nameParts, array($package->getPrettyVersion(), $package->getDistReference()));
25266 }
25267
25268 if ($package->getSourceReference()) {
25269 $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
25270 }
25271
25272 $name = implode('-', array_filter($nameParts, function ($p) {
25273 return !empty($p);
25274 }));
25275
25276 return str_replace('/', '-', $name);
25277 }
25278
25279
25280
25281
25282
25283
25284
25285
25286
25287
25288
25289
25290
25291
25292 public function archive(PackageInterface $package, $format, $targetDir, $fileName = null, $ignoreFilters = false)
25293 {
25294 if (empty($format)) {
25295 throw new \InvalidArgumentException('Format must be specified');
25296 }
25297
25298
25299  $usableArchiver = null;
25300 foreach ($this->archivers as $archiver) {
25301 if ($archiver->supports($format, $package->getSourceType())) {
25302 $usableArchiver = $archiver;
25303 break;
25304 }
25305 }
25306
25307
25308  if (null === $usableArchiver) {
25309 throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
25310 }
25311
25312 $filesystem = new Filesystem();
25313 if (null === $fileName) {
25314 $packageName = $this->getPackageFilename($package);
25315 } else {
25316 $packageName = $fileName;
25317 }
25318
25319
25320  $filesystem->ensureDirectoryExists($targetDir);
25321 $target = realpath($targetDir).'/'.$packageName.'.'.$format;
25322 $filesystem->ensureDirectoryExists(dirname($target));
25323
25324 if (!$this->overwriteFiles && file_exists($target)) {
25325 return $target;
25326 }
25327
25328 if ($package instanceof RootPackageInterface) {
25329 $sourcePath = realpath('.');
25330 } else {
25331
25332  $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
25333 $filesystem->ensureDirectoryExists($sourcePath);
25334
25335
25336  $this->downloadManager->download($package, $sourcePath);
25337
25338
25339  if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
25340 $jsonFile = new JsonFile($composerJsonPath);
25341 $jsonData = $jsonFile->read();
25342 if (!empty($jsonData['archive']['exclude'])) {
25343 $package->setArchiveExcludes($jsonData['archive']['exclude']);
25344 }
25345 }
25346 }
25347
25348
25349  $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
25350 $filesystem->ensureDirectoryExists(dirname($tempTarget));
25351
25352 $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes(), $ignoreFilters);
25353 $filesystem->rename($archivePath, $target);
25354
25355
25356  if (!$package instanceof RootPackageInterface) {
25357 $filesystem->removeDirectory($sourcePath);
25358 }
25359 $filesystem->remove($tempTarget);
25360
25361 return $target;
25362 }
25363 }
25364 <?php
25365
25366
25367
25368
25369
25370
25371
25372
25373
25374
25375
25376 namespace Composer\Package\Archiver;
25377
25378
25379
25380
25381
25382
25383 interface ArchiverInterface
25384 {
25385
25386
25387
25388
25389
25390
25391
25392
25393
25394
25395 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false);
25396
25397
25398
25399
25400
25401
25402
25403
25404
25405 public function supports($format, $sourceType);
25406 }
25407 <?php
25408
25409
25410
25411
25412
25413
25414
25415
25416
25417
25418
25419 namespace Composer\Package\Archiver;
25420
25421 use Symfony\Component\Finder;
25422
25423
25424
25425
25426 abstract class BaseExcludeFilter
25427 {
25428
25429
25430
25431 protected $sourcePath;
25432
25433
25434
25435
25436 protected $excludePatterns;
25437
25438
25439
25440
25441 public function __construct($sourcePath)
25442 {
25443 $this->sourcePath = $sourcePath;
25444 $this->excludePatterns = array();
25445 }
25446
25447
25448
25449
25450
25451
25452
25453
25454
25455
25456
25457 public function filter($relativePath, $exclude)
25458 {
25459 foreach ($this->excludePatterns as $patternData) {
25460 list($pattern, $negate, $stripLeadingSlash) = $patternData;
25461
25462 if ($stripLeadingSlash) {
25463 $path = substr($relativePath, 1);
25464 } else {
25465 $path = $relativePath;
25466 }
25467
25468 if (preg_match($pattern, $path)) {
25469 $exclude = !$negate;
25470 }
25471 }
25472
25473 return $exclude;
25474 }
25475
25476
25477
25478
25479
25480
25481
25482
25483
25484 protected function parseLines(array $lines, $lineParser)
25485 {
25486 return array_filter(
25487 array_map(
25488 function ($line) use ($lineParser) {
25489 $line = trim($line);
25490
25491 if (!$line || 0 === strpos($line, '#')) {
25492 return null;
25493 }
25494
25495 return call_user_func($lineParser, $line);
25496 },
25497 $lines
25498 ),
25499 function ($pattern) {
25500 return $pattern !== null;
25501 }
25502 );
25503 }
25504
25505
25506
25507
25508
25509
25510
25511
25512 protected function generatePatterns($rules)
25513 {
25514 $patterns = array();
25515 foreach ($rules as $rule) {
25516 $patterns[] = $this->generatePattern($rule);
25517 }
25518
25519 return $patterns;
25520 }
25521
25522
25523
25524
25525
25526
25527
25528
25529 protected function generatePattern($rule)
25530 {
25531 $negate = false;
25532 $pattern = '{';
25533
25534 if (strlen($rule) && $rule[0] === '!') {
25535 $negate = true;
25536 $rule = substr($rule, 1);
25537 }
25538
25539 if (strlen($rule) && $rule[0] === '/') {
25540 $pattern .= '^/';
25541 $rule = substr($rule, 1);
25542 } elseif (strlen($rule) - 1 === strpos($rule, '/')) {
25543 $pattern .= '/';
25544 $rule = substr($rule, 0, -1);
25545 } elseif (false === strpos($rule, '/')) {
25546 $pattern .= '/';
25547 }
25548
25549
25550  $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
25551
25552 return array($pattern . '}', $negate, false);
25553 }
25554 }
25555 <?php
25556
25557
25558
25559
25560
25561
25562
25563
25564
25565
25566
25567 namespace Composer\Package\Archiver;
25568
25569
25570
25571
25572
25573
25574 class ComposerExcludeFilter extends BaseExcludeFilter
25575 {
25576
25577
25578
25579
25580 public function __construct($sourcePath, array $excludeRules)
25581 {
25582 parent::__construct($sourcePath);
25583 $this->excludePatterns = $this->generatePatterns($excludeRules);
25584 }
25585 }
25586 <?php
25587
25588
25589
25590
25591
25592
25593
25594
25595
25596
25597
25598 namespace Composer\Package\Archiver;
25599
25600
25601
25602
25603
25604
25605
25606
25607 class GitExcludeFilter extends BaseExcludeFilter
25608 {
25609
25610
25611
25612
25613
25614 public function __construct($sourcePath)
25615 {
25616 parent::__construct($sourcePath);
25617
25618 if (file_exists($sourcePath.'/.gitignore')) {
25619 $this->excludePatterns = $this->parseLines(
25620 file($sourcePath.'/.gitignore'),
25621 array($this, 'parseGitIgnoreLine')
25622 );
25623 }
25624 if (file_exists($sourcePath.'/.gitattributes')) {
25625 $this->excludePatterns = array_merge(
25626 $this->excludePatterns,
25627 $this->parseLines(
25628 file($sourcePath.'/.gitattributes'),
25629 array($this, 'parseGitAttributesLine')
25630 ));
25631 }
25632 }
25633
25634
25635
25636
25637
25638
25639
25640
25641 public function parseGitIgnoreLine($line)
25642 {
25643 return $this->generatePattern($line);
25644 }
25645
25646
25647
25648
25649
25650
25651
25652
25653 public function parseGitAttributesLine($line)
25654 {
25655 $parts = preg_split('#\s+#', $line);
25656
25657 if (count($parts) == 2 && $parts[1] === 'export-ignore') {
25658 return $this->generatePattern($parts[0]);
25659 }
25660
25661 return null;
25662 }
25663 }
25664 <?php
25665
25666
25667
25668
25669
25670
25671
25672
25673
25674
25675
25676 namespace Composer\Package\Archiver;
25677
25678 use Symfony\Component\Finder;
25679
25680
25681
25682
25683
25684
25685 class HgExcludeFilter extends BaseExcludeFilter
25686 {
25687 const HG_IGNORE_REGEX = 1;
25688 const HG_IGNORE_GLOB = 2;
25689
25690
25691
25692
25693
25694 protected $patternMode;
25695
25696
25697
25698
25699
25700
25701 public function __construct($sourcePath)
25702 {
25703 parent::__construct($sourcePath);
25704
25705 $this->patternMode = self::HG_IGNORE_REGEX;
25706
25707 if (file_exists($sourcePath.'/.hgignore')) {
25708 $this->excludePatterns = $this->parseLines(
25709 file($sourcePath.'/.hgignore'),
25710 array($this, 'parseHgIgnoreLine')
25711 );
25712 }
25713 }
25714
25715
25716
25717
25718
25719
25720
25721
25722 public function parseHgIgnoreLine($line)
25723 {
25724 if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) {
25725 if ($matches[1] === 'glob') {
25726 $this->patternMode = self::HG_IGNORE_GLOB;
25727 } else {
25728 $this->patternMode = self::HG_IGNORE_REGEX;
25729 }
25730
25731 return null;
25732 }
25733
25734 if ($this->patternMode == self::HG_IGNORE_GLOB) {
25735 return $this->patternFromGlob($line);
25736 }
25737
25738 return $this->patternFromRegex($line);
25739 }
25740
25741
25742
25743
25744
25745
25746
25747
25748 protected function patternFromGlob($line)
25749 {
25750 $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#';
25751 $pattern = str_replace('[^/]*', '.*', $pattern);
25752
25753 return array($pattern, false, true);
25754 }
25755
25756
25757
25758
25759
25760
25761
25762
25763 public function patternFromRegex($line)
25764 {
25765
25766  $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#';
25767
25768 return array($pattern, false, true);
25769 }
25770 }
25771 <?php
25772
25773
25774
25775
25776
25777
25778
25779
25780
25781
25782
25783 namespace Composer\Package\Archiver;
25784
25785
25786
25787
25788
25789
25790 class PharArchiver implements ArchiverInterface
25791 {
25792 protected static $formats = array(
25793 'zip' => \Phar::ZIP,
25794 'tar' => \Phar::TAR,
25795 'tar.gz' => \Phar::TAR,
25796 'tar.bz2' => \Phar::TAR,
25797 );
25798
25799 protected static $compressFormats = array(
25800 'tar.gz' => \Phar::GZ,
25801 'tar.bz2' => \Phar::BZ2,
25802 );
25803
25804
25805
25806
25807 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
25808 {
25809 $sources = realpath($sources);
25810
25811
25812  if (file_exists($target)) {
25813 unlink($target);
25814 }
25815
25816 try {
25817 $filename = substr($target, 0, strrpos($target, $format) - 1);
25818
25819
25820  if (isset(static::$compressFormats[$format])) {
25821
25822  $target = $filename . '.tar';
25823 }
25824
25825 $phar = new \PharData($target, null, null, static::$formats[$format]);
25826 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
25827 $filesOnly = new ArchivableFilesFilter($files);
25828 $phar->buildFromIterator($filesOnly, $sources);
25829 $filesOnly->addEmptyDir($phar, $sources);
25830
25831 if (isset(static::$compressFormats[$format])) {
25832
25833  if (!$phar->canCompress(static::$compressFormats[$format])) {
25834 throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
25835 }
25836
25837
25838  unlink($target);
25839
25840
25841  $phar->compress(static::$compressFormats[$format]);
25842
25843
25844  $target = $filename . '.' . $format;
25845 }
25846
25847 return $target;
25848 } catch (\UnexpectedValueException $e) {
25849 $message = sprintf("Could not create archive '%s' from '%s': %s",
25850 $target,
25851 $sources,
25852 $e->getMessage()
25853 );
25854
25855 throw new \RuntimeException($message, $e->getCode(), $e);
25856 }
25857 }
25858
25859
25860
25861
25862 public function supports($format, $sourceType)
25863 {
25864 return isset(static::$formats[$format]);
25865 }
25866 }
25867 <?php
25868
25869
25870
25871
25872
25873
25874
25875
25876
25877
25878
25879 namespace Composer\Package\Archiver;
25880
25881 use ZipArchive;
25882 use Composer\Util\Filesystem;
25883
25884
25885
25886
25887 class ZipArchiver implements ArchiverInterface
25888 {
25889 protected static $formats = array(
25890 'zip' => 1,
25891 );
25892
25893
25894
25895
25896 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
25897 {
25898 $fs = new Filesystem();
25899 $sources = $fs->normalizePath($sources);
25900
25901 $zip = new ZipArchive();
25902 $res = $zip->open($target, ZipArchive::CREATE);
25903 if ($res === true) {
25904 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
25905 foreach ($files as $file) {
25906
25907 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
25908 $localname = str_replace($sources.'/', '', $filepath);
25909 if ($file->isDir()) {
25910 $zip->addEmptyDir($localname);
25911 } else {
25912 $zip->addFile($filepath, $localname);
25913 }
25914 }
25915 if ($zip->close()) {
25916 return $target;
25917 }
25918 }
25919 $message = sprintf("Could not create archive '%s' from '%s': %s",
25920 $target,
25921 $sources,
25922 $zip->getStatusString()
25923 );
25924 throw new \RuntimeException($message);
25925 }
25926
25927
25928
25929
25930 public function supports($format, $sourceType)
25931 {
25932 return isset(static::$formats[$format]) && $this->compressionAvailable();
25933 }
25934
25935 private function compressionAvailable()
25936 {
25937 return class_exists('ZipArchive');
25938 }
25939 }
25940 <?php
25941
25942
25943
25944
25945
25946
25947
25948
25949
25950
25951
25952 namespace Composer\Package;
25953
25954 use Composer\Repository\RepositoryInterface;
25955 use Composer\Repository\PlatformRepository;
25956
25957
25958
25959
25960
25961
25962 abstract class BasePackage implements PackageInterface
25963 {
25964 public static $supportedLinkTypes = array(
25965 'require' => array('description' => 'requires', 'method' => 'requires'),
25966 'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
25967 'provide' => array('description' => 'provides', 'method' => 'provides'),
25968 'replace' => array('description' => 'replaces', 'method' => 'replaces'),
25969 'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
25970 );
25971
25972 const STABILITY_STABLE = 0;
25973 const STABILITY_RC = 5;
25974 const STABILITY_BETA = 10;
25975 const STABILITY_ALPHA = 15;
25976 const STABILITY_DEV = 20;
25977
25978 public static $stabilities = array(
25979 'stable' => self::STABILITY_STABLE,
25980 'RC' => self::STABILITY_RC,
25981 'beta' => self::STABILITY_BETA,
25982 'alpha' => self::STABILITY_ALPHA,
25983 'dev' => self::STABILITY_DEV,
25984 );
25985
25986
25987
25988
25989
25990 public $id;
25991
25992 protected $name;
25993
25994 protected $prettyName;
25995
25996 protected $repository;
25997
25998 protected $transportOptions = array();
25999
26000
26001
26002
26003
26004
26005 public function __construct($name)
26006 {
26007 $this->prettyName = $name;
26008 $this->name = strtolower($name);
26009 $this->id = -1;
26010 }
26011
26012
26013
26014
26015 public function getName()
26016 {
26017 return $this->name;
26018 }
26019
26020
26021
26022
26023 public function getPrettyName()
26024 {
26025 return $this->prettyName;
26026 }
26027
26028
26029
26030
26031 public function getNames()
26032 {
26033 $names = array(
26034 $this->getName() => true,
26035 );
26036
26037 foreach ($this->getProvides() as $link) {
26038 $names[$link->getTarget()] = true;
26039 }
26040
26041 foreach ($this->getReplaces() as $link) {
26042 $names[$link->getTarget()] = true;
26043 }
26044
26045 return array_keys($names);
26046 }
26047
26048
26049
26050
26051 public function setId($id)
26052 {
26053 $this->id = $id;
26054 }
26055
26056
26057
26058
26059 public function getId()
26060 {
26061 return $this->id;
26062 }
26063
26064
26065
26066
26067 public function setRepository(RepositoryInterface $repository)
26068 {
26069 if ($this->repository && $repository !== $this->repository) {
26070 throw new \LogicException('A package can only be added to one repository');
26071 }
26072 $this->repository = $repository;
26073 }
26074
26075
26076
26077
26078 public function getRepository()
26079 {
26080 return $this->repository;
26081 }
26082
26083
26084
26085
26086 public function getTransportOptions()
26087 {
26088 return $this->transportOptions;
26089 }
26090
26091
26092
26093
26094
26095
26096 public function setTransportOptions(array $options)
26097 {
26098 $this->transportOptions = $options;
26099 }
26100
26101
26102
26103
26104
26105
26106 public function isPlatform()
26107 {
26108 return $this->getRepository() instanceof PlatformRepository;
26109 }
26110
26111
26112
26113
26114
26115
26116 public function getUniqueName()
26117 {
26118 return $this->getName().'-'.$this->getVersion();
26119 }
26120
26121 public function equals(PackageInterface $package)
26122 {
26123 $self = $this;
26124 if ($this instanceof AliasPackage) {
26125 $self = $this->getAliasOf();
26126 }
26127 if ($package instanceof AliasPackage) {
26128 $package = $package->getAliasOf();
26129 }
26130
26131 return $package === $self;
26132 }
26133
26134
26135
26136
26137
26138
26139 public function __toString()
26140 {
26141 return $this->getUniqueName();
26142 }
26143
26144 public function getPrettyString()
26145 {
26146 return $this->getPrettyName().' '.$this->getPrettyVersion();
26147 }
26148
26149
26150
26151
26152 public function getFullPrettyVersion($truncate = true)
26153 {
26154 if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
26155 return $this->getPrettyVersion();
26156 }
26157
26158
26159  if ($truncate && strlen($this->getSourceReference()) === 40) {
26160 return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
26161 }
26162
26163 return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
26164 }
26165
26166 public function getStabilityPriority()
26167 {
26168 return self::$stabilities[$this->getStability()];
26169 }
26170
26171 public function __clone()
26172 {
26173 $this->repository = null;
26174 $this->id = -1;
26175 }
26176 }
26177 <?php
26178
26179
26180
26181
26182
26183
26184
26185
26186
26187
26188
26189 namespace Composer\Package;
26190
26191
26192
26193
26194
26195
26196 class CompletePackage extends Package implements CompletePackageInterface
26197 {
26198 protected $repositories;
26199 protected $license = array();
26200 protected $keywords;
26201 protected $authors;
26202 protected $description;
26203 protected $homepage;
26204 protected $scripts = array();
26205 protected $support = array();
26206 protected $abandoned = false;
26207
26208
26209
26210
26211 public function setScripts(array $scripts)
26212 {
26213 $this->scripts = $scripts;
26214 }
26215
26216
26217
26218
26219 public function getScripts()
26220 {
26221 return $this->scripts;
26222 }
26223
26224
26225
26226
26227
26228
26229 public function setRepositories($repositories)
26230 {
26231 $this->repositories = $repositories;
26232 }
26233
26234
26235
26236
26237 public function getRepositories()
26238 {
26239 return $this->repositories;
26240 }
26241
26242
26243
26244
26245
26246
26247 public function setLicense(array $license)
26248 {
26249 $this->license = $license;
26250 }
26251
26252
26253
26254
26255 public function getLicense()
26256 {
26257 return $this->license;
26258 }
26259
26260
26261
26262
26263
26264
26265 public function setKeywords(array $keywords)
26266 {
26267 $this->keywords = $keywords;
26268 }
26269
26270
26271
26272
26273 public function getKeywords()
26274 {
26275 return $this->keywords;
26276 }
26277
26278
26279
26280
26281
26282
26283 public function setAuthors(array $authors)
26284 {
26285 $this->authors = $authors;
26286 }
26287
26288
26289
26290
26291 public function getAuthors()
26292 {
26293 return $this->authors;
26294 }
26295
26296
26297
26298
26299
26300
26301 public function setDescription($description)
26302 {
26303 $this->description = $description;
26304 }
26305
26306
26307
26308
26309 public function getDescription()
26310 {
26311 return $this->description;
26312 }
26313
26314
26315
26316
26317
26318
26319 public function setHomepage($homepage)
26320 {
26321 $this->homepage = $homepage;
26322 }
26323
26324
26325
26326
26327 public function getHomepage()
26328 {
26329 return $this->homepage;
26330 }
26331
26332
26333
26334
26335
26336
26337 public function setSupport(array $support)
26338 {
26339 $this->support = $support;
26340 }
26341
26342
26343
26344
26345 public function getSupport()
26346 {
26347 return $this->support;
26348 }
26349
26350
26351
26352
26353 public function isAbandoned()
26354 {
26355 return (bool) $this->abandoned;
26356 }
26357
26358
26359
26360
26361 public function setAbandoned($abandoned)
26362 {
26363 $this->abandoned = $abandoned;
26364 }
26365
26366
26367
26368
26369
26370
26371 public function getReplacementPackage()
26372 {
26373 return is_string($this->abandoned) ? $this->abandoned : null;
26374 }
26375 }
26376 <?php
26377
26378
26379
26380
26381
26382
26383
26384
26385
26386
26387
26388 namespace Composer\Package;
26389
26390
26391
26392
26393
26394
26395 interface CompletePackageInterface extends PackageInterface
26396 {
26397
26398
26399
26400
26401
26402 public function getScripts();
26403
26404
26405
26406
26407
26408
26409
26410
26411 public function getRepositories();
26412
26413
26414
26415
26416
26417
26418 public function getLicense();
26419
26420
26421
26422
26423
26424
26425 public function getKeywords();
26426
26427
26428
26429
26430
26431
26432 public function getDescription();
26433
26434
26435
26436
26437
26438
26439 public function getHomepage();
26440
26441
26442
26443
26444
26445
26446
26447
26448 public function getAuthors();
26449
26450
26451
26452
26453
26454
26455 public function getSupport();
26456
26457
26458
26459
26460
26461
26462 public function isAbandoned();
26463
26464
26465
26466
26467
26468
26469 public function getReplacementPackage();
26470 }
26471 <?php
26472
26473
26474
26475
26476
26477
26478
26479
26480
26481
26482
26483 namespace Composer\Package\Dumper;
26484
26485 use Composer\Package\BasePackage;
26486 use Composer\Package\PackageInterface;
26487 use Composer\Package\CompletePackageInterface;
26488 use Composer\Package\RootPackageInterface;
26489
26490
26491
26492
26493
26494 class ArrayDumper
26495 {
26496 public function dump(PackageInterface $package)
26497 {
26498 $keys = array(
26499 'binaries' => 'bin',
26500 'type',
26501 'extra',
26502 'installationSource' => 'installation-source',
26503 'autoload',
26504 'devAutoload' => 'autoload-dev',
26505 'notificationUrl' => 'notification-url',
26506 'includePaths' => 'include-path',
26507 );
26508
26509 $data = array();
26510 $data['name'] = $package->getPrettyName();
26511 $data['version'] = $package->getPrettyVersion();
26512 $data['version_normalized'] = $package->getVersion();
26513
26514 if ($package->getTargetDir()) {
26515 $data['target-dir'] = $package->getTargetDir();
26516 }
26517
26518 if ($package->getSourceType()) {
26519 $data['source']['type'] = $package->getSourceType();
26520 $data['source']['url'] = $package->getSourceUrl();
26521 $data['source']['reference'] = $package->getSourceReference();
26522 if ($mirrors = $package->getSourceMirrors()) {
26523 $data['source']['mirrors'] = $mirrors;
26524 }
26525 }
26526
26527 if ($package->getDistType()) {
26528 $data['dist']['type'] = $package->getDistType();
26529 $data['dist']['url'] = $package->getDistUrl();
26530 $data['dist']['reference'] = $package->getDistReference();
26531 $data['dist']['shasum'] = $package->getDistSha1Checksum();
26532 if ($mirrors = $package->getDistMirrors()) {
26533 $data['dist']['mirrors'] = $mirrors;
26534 }
26535 }
26536
26537 if ($package->getArchiveExcludes()) {
26538 $data['archive']['exclude'] = $package->getArchiveExcludes();
26539 }
26540
26541 foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
26542 if ($links = $package->{'get'.ucfirst($opts['method'])}()) {
26543 foreach ($links as $link) {
26544 $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
26545 }
26546 ksort($data[$type]);
26547 }
26548 }
26549
26550 if ($packages = $package->getSuggests()) {
26551 ksort($packages);
26552 $data['suggest'] = $packages;
26553 }
26554
26555 if ($package->getReleaseDate()) {
26556 $data['time'] = $package->getReleaseDate()->format(DATE_RFC3339);
26557 }
26558
26559 $data = $this->dumpValues($package, $keys, $data);
26560
26561 if ($package instanceof CompletePackageInterface) {
26562 $keys = array(
26563 'scripts',
26564 'license',
26565 'authors',
26566 'description',
26567 'homepage',
26568 'keywords',
26569 'repositories',
26570 'support',
26571 );
26572
26573 $data = $this->dumpValues($package, $keys, $data);
26574
26575 if (isset($data['keywords']) && is_array($data['keywords'])) {
26576 sort($data['keywords']);
26577 }
26578
26579 if ($package->isAbandoned()) {
26580 $data['abandoned'] = $package->getReplacementPackage() ?: true;
26581 }
26582 }
26583
26584 if ($package instanceof RootPackageInterface) {
26585 $minimumStability = $package->getMinimumStability();
26586 if ($minimumStability) {
26587 $data['minimum-stability'] = $minimumStability;
26588 }
26589 }
26590
26591 if (count($package->getTransportOptions()) > 0) {
26592 $data['transport-options'] = $package->getTransportOptions();
26593 }
26594
26595 return $data;
26596 }
26597
26598 private function dumpValues(PackageInterface $package, array $keys, array $data)
26599 {
26600 foreach ($keys as $method => $key) {
26601 if (is_numeric($method)) {
26602 $method = $key;
26603 }
26604
26605 $getter = 'get'.ucfirst($method);
26606 $value = $package->$getter();
26607
26608 if (null !== $value && !(is_array($value) && 0 === count($value))) {
26609 $data[$key] = $value;
26610 }
26611 }
26612
26613 return $data;
26614 }
26615 }
26616 <?php
26617
26618
26619
26620
26621
26622
26623
26624
26625
26626
26627
26628 namespace Composer\Package;
26629
26630 use Composer\Semver\Constraint\ConstraintInterface;
26631
26632
26633
26634
26635
26636
26637 class Link
26638 {
26639
26640
26641
26642 protected $source;
26643
26644
26645
26646
26647 protected $target;
26648
26649
26650
26651
26652 protected $constraint;
26653
26654
26655
26656
26657 protected $description;
26658
26659
26660
26661
26662 protected $prettyConstraint;
26663
26664
26665
26666
26667
26668
26669
26670
26671
26672
26673 public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
26674 {
26675 $this->source = strtolower($source);
26676 $this->target = strtolower($target);
26677 $this->constraint = $constraint;
26678 $this->description = $description;
26679 $this->prettyConstraint = $prettyConstraint;
26680 }
26681
26682
26683
26684
26685 public function getDescription()
26686 {
26687 return $this->description;
26688 }
26689
26690
26691
26692
26693 public function getSource()
26694 {
26695 return $this->source;
26696 }
26697
26698
26699
26700
26701 public function getTarget()
26702 {
26703 return $this->target;
26704 }
26705
26706
26707
26708
26709 public function getConstraint()
26710 {
26711 return $this->constraint;
26712 }
26713
26714
26715
26716
26717
26718 public function getPrettyConstraint()
26719 {
26720 if (null === $this->prettyConstraint) {
26721 throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
26722 }
26723
26724 return $this->prettyConstraint;
26725 }
26726
26727
26728
26729
26730 public function __toString()
26731 {
26732 return $this->source.' '.$this->description.' '.$this->target.' ('.$this->constraint.')';
26733 }
26734
26735
26736
26737
26738
26739 public function getPrettyString(PackageInterface $sourcePackage)
26740 {
26741 return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
26742 }
26743 }
26744 <?php
26745
26746
26747
26748
26749
26750
26751
26752
26753
26754
26755
26756 namespace Composer\Package\LinkConstraint;
26757
26758 use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint;
26759
26760 trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
26761
26762
26763
26764
26765 class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
26766 {
26767 }
26768 <?php
26769
26770
26771
26772
26773
26774
26775
26776
26777
26778
26779
26780 namespace Composer\Package\LinkConstraint;
26781
26782 use Composer\Semver\Constraint\ConstraintInterface;
26783
26784 trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
26785
26786
26787
26788
26789 interface LinkConstraintInterface extends ConstraintInterface
26790 {
26791 }
26792 <?php
26793
26794
26795
26796
26797
26798
26799
26800
26801
26802
26803
26804 namespace Composer\Package\LinkConstraint;
26805
26806 use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint;
26807
26808 trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
26809
26810
26811
26812
26813 class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface
26814 {
26815 }
26816 <?php
26817
26818
26819
26820
26821
26822
26823
26824
26825
26826
26827
26828 namespace Composer\Package\LinkConstraint;
26829
26830 use Composer\Semver\Constraint\AbstractConstraint;
26831
26832 trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, there is no replacement for it.', E_USER_DEPRECATED);
26833
26834
26835
26836
26837 abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
26838 {
26839 }
26840 <?php
26841
26842
26843
26844
26845
26846
26847
26848
26849
26850
26851
26852 namespace Composer\Package\LinkConstraint;
26853
26854 use Composer\Semver\Constraint\Constraint;
26855
26856 trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
26857
26858
26859
26860
26861 class VersionConstraint extends Constraint implements LinkConstraintInterface
26862 {
26863 }
26864 <?php
26865
26866
26867
26868
26869
26870
26871
26872
26873
26874
26875
26876 namespace Composer\Package\Loader;
26877
26878 use Composer\Package;
26879 use Composer\Package\AliasPackage;
26880 use Composer\Package\Link;
26881 use Composer\Package\RootAliasPackage;
26882 use Composer\Package\RootPackageInterface;
26883 use Composer\Package\Version\VersionParser;
26884 use Composer\Semver\VersionParser as SemverVersionParser;
26885
26886
26887
26888
26889
26890 class ArrayLoader implements LoaderInterface
26891 {
26892 protected $versionParser;
26893 protected $loadOptions;
26894
26895 public function __construct(SemverVersionParser $parser = null, $loadOptions = false)
26896 {
26897 if (!$parser) {
26898 $parser = new VersionParser;
26899 }
26900 $this->versionParser = $parser;
26901 $this->loadOptions = $loadOptions;
26902 }
26903
26904 public function load(array $config, $class = 'Composer\Package\CompletePackage')
26905 {
26906 if (!isset($config['name'])) {
26907 throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
26908 }
26909 if (!isset($config['version'])) {
26910 throw new \UnexpectedValueException('Package '.$config['name'].' has no version defined.');
26911 }
26912
26913
26914  if (isset($config['version_normalized'])) {
26915 $version = $config['version_normalized'];
26916 } else {
26917 $version = $this->versionParser->normalize($config['version']);
26918 }
26919 $package = new $class($config['name'], $version, $config['version']);
26920 $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
26921
26922 if (isset($config['target-dir'])) {
26923 $package->setTargetDir($config['target-dir']);
26924 }
26925
26926 if (isset($config['extra']) && is_array($config['extra'])) {
26927 $package->setExtra($config['extra']);
26928 }
26929
26930 if (isset($config['bin'])) {
26931 foreach ((array) $config['bin'] as $key => $bin) {
26932 $config['bin'][$key] = ltrim($bin, '/');
26933 }
26934 $package->setBinaries((array) $config['bin']);
26935 }
26936
26937 if (isset($config['installation-source'])) {
26938 $package->setInstallationSource($config['installation-source']);
26939 }
26940
26941 if (isset($config['source'])) {
26942 if (!isset($config['source']['type']) || !isset($config['source']['url']) || !isset($config['source']['reference'])) {
26943 throw new \UnexpectedValueException(sprintf(
26944 "Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.",
26945 $config['name'],
26946 json_encode($config['source'])
26947 ));
26948 }
26949 $package->setSourceType($config['source']['type']);
26950 $package->setSourceUrl($config['source']['url']);
26951 $package->setSourceReference($config['source']['reference']);
26952 if (isset($config['source']['mirrors'])) {
26953 $package->setSourceMirrors($config['source']['mirrors']);
26954 }
26955 }
26956
26957 if (isset($config['dist'])) {
26958 if (!isset($config['dist']['type'])
26959 || !isset($config['dist']['url'])) {
26960 throw new \UnexpectedValueException(sprintf(
26961 "Package %s's dist key should be specified as ".
26962 "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.",
26963 $config['name'],
26964 json_encode($config['dist'])
26965 ));
26966 }
26967 $package->setDistType($config['dist']['type']);
26968 $package->setDistUrl($config['dist']['url']);
26969 $package->setDistReference(isset($config['dist']['reference']) ? $config['dist']['reference'] : null);
26970 $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
26971 if (isset($config['dist']['mirrors'])) {
26972 $package->setDistMirrors($config['dist']['mirrors']);
26973 }
26974 }
26975
26976 foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
26977 if (isset($config[$type])) {
26978 $method = 'set'.ucfirst($opts['method']);
26979 $package->{$method}(
26980 $this->parseLinks(
26981 $package->getName(),
26982 $package->getPrettyVersion(),
26983 $opts['description'],
26984 $config[$type]
26985 )
26986 );
26987 }
26988 }
26989
26990 if (isset($config['suggest']) && is_array($config['suggest'])) {
26991 foreach ($config['suggest'] as $target => $reason) {
26992 if ('self.version' === trim($reason)) {
26993 $config['suggest'][$target] = $package->getPrettyVersion();
26994 }
26995 }
26996 $package->setSuggests($config['suggest']);
26997 }
26998
26999 if (isset($config['autoload'])) {
27000 $package->setAutoload($config['autoload']);
27001 }
27002
27003 if (isset($config['autoload-dev'])) {
27004 $package->setDevAutoload($config['autoload-dev']);
27005 }
27006
27007 if (isset($config['include-path'])) {
27008 $package->setIncludePaths($config['include-path']);
27009 }
27010
27011 if (!empty($config['time'])) {
27012 $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
27013
27014 try {
27015 $date = new \DateTime($time, new \DateTimeZone('UTC'));
27016 $package->setReleaseDate($date);
27017 } catch (\Exception $e) {
27018 }
27019 }
27020
27021 if (!empty($config['notification-url'])) {
27022 $package->setNotificationUrl($config['notification-url']);
27023 }
27024
27025 if (!empty($config['archive']['exclude'])) {
27026 $package->setArchiveExcludes($config['archive']['exclude']);
27027 }
27028
27029 if ($package instanceof Package\CompletePackageInterface) {
27030 if (isset($config['scripts']) && is_array($config['scripts'])) {
27031 foreach ($config['scripts'] as $event => $listeners) {
27032 $config['scripts'][$event] = (array) $listeners;
27033 }
27034 if (isset($config['scripts']['composer'])) {
27035 trigger_error('The `composer` script name is reserved for internal use, please avoid defining it', E_USER_DEPRECATED);
27036 }
27037 $package->setScripts($config['scripts']);
27038 }
27039
27040 if (!empty($config['description']) && is_string($config['description'])) {
27041 $package->setDescription($config['description']);
27042 }
27043
27044 if (!empty($config['homepage']) && is_string($config['homepage'])) {
27045 $package->setHomepage($config['homepage']);
27046 }
27047
27048 if (!empty($config['keywords']) && is_array($config['keywords'])) {
27049 $package->setKeywords($config['keywords']);
27050 }
27051
27052 if (!empty($config['license'])) {
27053 $package->setLicense(is_array($config['license']) ? $config['license'] : array($config['license']));
27054 }
27055
27056 if (!empty($config['authors']) && is_array($config['authors'])) {
27057 $package->setAuthors($config['authors']);
27058 }
27059
27060 if (isset($config['support'])) {
27061 $package->setSupport($config['support']);
27062 }
27063
27064 if (isset($config['abandoned'])) {
27065 $package->setAbandoned($config['abandoned']);
27066 }
27067 }
27068
27069 if ($aliasNormalized = $this->getBranchAlias($config)) {
27070 if ($package instanceof RootPackageInterface) {
27071 $package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
27072 } else {
27073 $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
27074 }
27075 }
27076
27077 if ($this->loadOptions && isset($config['transport-options'])) {
27078 $package->setTransportOptions($config['transport-options']);
27079 }
27080
27081 return $package;
27082 }
27083
27084
27085
27086
27087
27088
27089
27090
27091 public function parseLinks($source, $sourceVersion, $description, $links)
27092 {
27093 $res = array();
27094 foreach ($links as $target => $constraint) {
27095 if (!is_string($constraint)) {
27096 throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($constraint) . ' (' . var_export($constraint, true) . ')');
27097 }
27098 if ('self.version' === $constraint) {
27099 $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
27100 } else {
27101 $parsedConstraint = $this->versionParser->parseConstraints($constraint);
27102 }
27103
27104 $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
27105 }
27106
27107 return $res;
27108 }
27109
27110
27111
27112
27113
27114
27115
27116 public function getBranchAlias(array $config)
27117 {
27118 if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
27119 || !isset($config['extra']['branch-alias'])
27120 || !is_array($config['extra']['branch-alias'])
27121 ) {
27122 return;
27123 }
27124
27125 foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
27126
27127  if ('-dev' !== substr($targetBranch, -4)) {
27128 continue;
27129 }
27130
27131
27132  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
27133 if ('-dev' !== substr($validatedTargetBranch, -4)) {
27134 continue;
27135 }
27136
27137
27138  if (strtolower($config['version']) !== strtolower($sourceBranch)) {
27139 continue;
27140 }
27141
27142
27143  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
27144 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
27145 && (stripos($targetPrefix, $sourcePrefix) !== 0)
27146 ) {
27147 continue;
27148 }
27149
27150 return $validatedTargetBranch;
27151 }
27152 }
27153 }
27154 <?php
27155
27156
27157
27158
27159
27160
27161
27162
27163
27164
27165
27166 namespace Composer\Package\Loader;
27167
27168
27169
27170
27171 class InvalidPackageException extends \Exception
27172 {
27173 private $errors;
27174 private $warnings;
27175 private $data;
27176
27177 public function __construct(array $errors, array $warnings, array $data)
27178 {
27179 $this->errors = $errors;
27180 $this->warnings = $warnings;
27181 $this->data = $data;
27182 parent::__construct("Invalid package information: \n".implode("\n", array_merge($errors, $warnings)));
27183 }
27184
27185 public function getData()
27186 {
27187 return $this->data;
27188 }
27189
27190 public function getErrors()
27191 {
27192 return $this->errors;
27193 }
27194
27195 public function getWarnings()
27196 {
27197 return $this->warnings;
27198 }
27199 }
27200 <?php
27201
27202
27203
27204
27205
27206
27207
27208
27209
27210
27211
27212 namespace Composer\Package\Loader;
27213
27214 use Composer\Json\JsonFile;
27215
27216
27217
27218
27219 class JsonLoader
27220 {
27221 private $loader;
27222
27223 public function __construct(LoaderInterface $loader)
27224 {
27225 $this->loader = $loader;
27226 }
27227
27228
27229
27230
27231
27232 public function load($json)
27233 {
27234 if ($json instanceof JsonFile) {
27235 $config = $json->read();
27236 } elseif (file_exists($json)) {
27237 $config = JsonFile::parseJson(file_get_contents($json), $json);
27238 } elseif (is_string($json)) {
27239 $config = JsonFile::parseJson($json);
27240 }
27241
27242 return $this->loader->load($config);
27243 }
27244 }
27245 <?php
27246
27247
27248
27249
27250
27251
27252
27253
27254
27255
27256
27257 namespace Composer\Package\Loader;
27258
27259
27260
27261
27262
27263
27264 interface LoaderInterface
27265 {
27266
27267
27268
27269
27270
27271
27272
27273 public function load(array $package, $class = 'Composer\Package\CompletePackage');
27274 }
27275 <?php
27276
27277
27278
27279
27280
27281
27282
27283
27284
27285
27286
27287 namespace Composer\Package\Loader;
27288
27289 use Composer\Package\BasePackage;
27290 use Composer\Package\AliasPackage;
27291 use Composer\Config;
27292 use Composer\Package\RootPackageInterface;
27293 use Composer\Repository\RepositoryFactory;
27294 use Composer\Package\Version\VersionGuesser;
27295 use Composer\Package\Version\VersionParser;
27296 use Composer\Repository\RepositoryManager;
27297 use Composer\Util\ProcessExecutor;
27298
27299
27300
27301
27302
27303
27304
27305
27306 class RootPackageLoader extends ArrayLoader
27307 {
27308
27309
27310
27311 private $manager;
27312
27313
27314
27315
27316 private $config;
27317
27318
27319
27320
27321 private $versionGuesser;
27322
27323 public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null)
27324 {
27325 parent::__construct($parser);
27326
27327 $this->manager = $manager;
27328 $this->config = $config;
27329 $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
27330 }
27331
27332
27333
27334
27335
27336
27337
27338 public function load(array $config, $class = 'Composer\Package\RootPackage', $cwd = null)
27339 {
27340 if (!isset($config['name'])) {
27341 $config['name'] = '__root__';
27342 }
27343 $autoVersioned = false;
27344 if (!isset($config['version'])) {
27345 $commit = null;
27346
27347
27348  if (getenv('COMPOSER_ROOT_VERSION')) {
27349 $config['version'] = getenv('COMPOSER_ROOT_VERSION');
27350 } else {
27351 $versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
27352 if ($versionData) {
27353 $config['version'] = $versionData['pretty_version'];
27354 $config['version_normalized'] = $versionData['version'];
27355 $commit = $versionData['commit'];
27356 }
27357 }
27358
27359 if (!isset($config['version'])) {
27360 $config['version'] = '1.0.0';
27361 $autoVersioned = true;
27362 }
27363
27364 if ($commit) {
27365 $config['source'] = array(
27366 'type' => '',
27367 'url' => '',
27368 'reference' => $commit,
27369 );
27370 $config['dist'] = array(
27371 'type' => '',
27372 'url' => '',
27373 'reference' => $commit,
27374 );
27375 }
27376 }
27377
27378 $realPackage = $package = parent::load($config, $class);
27379 if ($realPackage instanceof AliasPackage) {
27380 $realPackage = $package->getAliasOf();
27381 }
27382
27383 if ($autoVersioned) {
27384 $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
27385 }
27386
27387 if (isset($config['minimum-stability'])) {
27388 $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
27389 }
27390
27391 $aliases = array();
27392 $stabilityFlags = array();
27393 $references = array();
27394 foreach (array('require', 'require-dev') as $linkType) {
27395 if (isset($config[$linkType])) {
27396 $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
27397 $method = 'get'.ucfirst($linkInfo['method']);
27398 $links = array();
27399 foreach ($realPackage->$method() as $link) {
27400 $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
27401 }
27402 $aliases = $this->extractAliases($links, $aliases);
27403 $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
27404 $references = $this->extractReferences($links, $references);
27405 }
27406 }
27407
27408 if (isset($links[$config['name']])) {
27409 throw new \InvalidArgumentException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL .
27410 'Did you accidentally name your root package after an external package?', $config['name']));
27411 }
27412
27413 $realPackage->setAliases($aliases);
27414 $realPackage->setStabilityFlags($stabilityFlags);
27415 $realPackage->setReferences($references);
27416
27417 if (isset($config['prefer-stable'])) {
27418 $realPackage->setPreferStable((bool) $config['prefer-stable']);
27419 }
27420
27421 if (isset($config['config'])) {
27422 $realPackage->setConfig($config['config']);
27423 }
27424
27425 $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
27426 foreach ($repos as $repo) {
27427 $this->manager->addRepository($repo);
27428 }
27429 $realPackage->setRepositories($this->config->getRepositories());
27430
27431 return $package;
27432 }
27433
27434 private function extractAliases(array $requires, array $aliases)
27435 {
27436 foreach ($requires as $reqName => $reqVersion) {
27437 if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
27438 $aliases[] = array(
27439 'package' => strtolower($reqName),
27440 'version' => $this->versionParser->normalize($match[1], $reqVersion),
27441 'alias' => $match[2],
27442 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
27443 );
27444 }
27445 }
27446
27447 return $aliases;
27448 }
27449
27450 private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
27451 {
27452 $stabilities = BasePackage::$stabilities;
27453 $minimumStability = $stabilities[$minimumStability];
27454 foreach ($requires as $reqName => $reqVersion) {
27455 $constraints = array();
27456
27457
27458  $orSplit = preg_split('{\s*\|\|?\s*}', trim($reqVersion));
27459 foreach ($orSplit as $orConstraint) {
27460 $andSplit = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
27461 foreach ($andSplit as $andConstraint) {
27462 $constraints[] = $andConstraint;
27463 }
27464 }
27465
27466
27467  $match = false;
27468 foreach ($constraints as $constraint) {
27469 if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
27470 $name = strtolower($reqName);
27471 $stability = $stabilities[VersionParser::normalizeStability($match[1])];
27472
27473 if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
27474 continue;
27475 }
27476 $stabilityFlags[$name] = $stability;
27477 $match = true;
27478 }
27479 }
27480
27481 if ($match) {
27482 continue;
27483 }
27484
27485 foreach ($constraints as $constraint) {
27486
27487  
27488  $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
27489 if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
27490 $name = strtolower($reqName);
27491 $stability = $stabilities[$stabilityName];
27492 if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
27493 continue;
27494 }
27495 $stabilityFlags[$name] = $stability;
27496 }
27497 }
27498 }
27499
27500 return $stabilityFlags;
27501 }
27502
27503 private function extractReferences(array $requires, array $references)
27504 {
27505 foreach ($requires as $reqName => $reqVersion) {
27506 $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
27507 if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === ($stabilityName = VersionParser::parseStability($reqVersion))) {
27508 $name = strtolower($reqName);
27509 $references[$name] = $match[1];
27510 }
27511 }
27512
27513 return $references;
27514 }
27515 }
27516 <?php
27517
27518
27519
27520
27521
27522
27523
27524
27525
27526
27527
27528 namespace Composer\Package\Loader;
27529
27530 use Composer\Package;
27531 use Composer\Package\BasePackage;
27532 use Composer\Semver\Constraint\Constraint;
27533 use Composer\Package\Version\VersionParser;
27534 use Composer\Repository\PlatformRepository;
27535 use Composer\Spdx\SpdxLicenses;
27536
27537
27538
27539
27540 class ValidatingArrayLoader implements LoaderInterface
27541 {
27542 const CHECK_ALL = 3;
27543 const CHECK_UNBOUND_CONSTRAINTS = 1;
27544 const CHECK_STRICT_CONSTRAINTS = 2;
27545
27546 private $loader;
27547 private $versionParser;
27548 private $errors;
27549 private $warnings;
27550 private $config;
27551 private $strictName;
27552 private $flags;
27553
27554 public function __construct(LoaderInterface $loader, $strictName = true, VersionParser $parser = null, $flags = 0)
27555 {
27556 $this->loader = $loader;
27557 $this->versionParser = $parser ?: new VersionParser();
27558 $this->strictName = $strictName;
27559 $this->flags = $flags;
27560 }
27561
27562 public function load(array $config, $class = 'Composer\Package\CompletePackage')
27563 {
27564 $this->errors = array();
27565 $this->warnings = array();
27566 $this->config = $config;
27567
27568 if ($this->strictName) {
27569 $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
27570 } else {
27571 $this->validateString('name', true);
27572 }
27573
27574 if (!empty($this->config['version'])) {
27575 try {
27576 $this->versionParser->normalize($this->config['version']);
27577 } catch (\Exception $e) {
27578 $this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
27579 unset($this->config['version']);
27580 }
27581 }
27582
27583 if (!empty($this->config['config']['platform'])) {
27584 foreach ((array) $this->config['config']['platform'] as $key => $platform) {
27585 try {
27586 $this->versionParser->normalize($platform);
27587 } catch (\Exception $e) {
27588 $this->errors[] = 'config.platform.' . $key . ' : invalid value ('.$platform.'): '.$e->getMessage();
27589 }
27590 }
27591 }
27592
27593 $this->validateRegex('type', '[A-Za-z0-9-]+');
27594 $this->validateString('target-dir');
27595 $this->validateArray('extra');
27596
27597 if (isset($this->config['bin'])) {
27598 if (is_string($this->config['bin'])) {
27599 $this->validateString('bin');
27600 } else {
27601 $this->validateFlatArray('bin');
27602 }
27603 }
27604
27605 $this->validateArray('scripts'); 
27606  $this->validateString('description');
27607 $this->validateUrl('homepage');
27608 $this->validateFlatArray('keywords', '[\p{N}\p{L} ._-]+');
27609
27610 $releaseDate = null;
27611 $this->validateString('time');
27612 if (!empty($this->config['time'])) {
27613 try {
27614 $releaseDate = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
27615 } catch (\Exception $e) {
27616 $this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
27617 unset($this->config['time']);
27618 }
27619 }
27620
27621 if (isset($this->config['license'])) {
27622 if (is_string($this->config['license'])) {
27623 $this->validateRegex('license', '[A-Za-z0-9+. ()-]+');
27624 } else {
27625 $this->validateFlatArray('license', '[A-Za-z0-9+. ()-]+');
27626 }
27627
27628 if (is_array($this->config['license']) || is_string($this->config['license'])) {
27629 $licenses = (array) $this->config['license'];
27630
27631
27632  foreach ($licenses as $key => $license) {
27633 if ('proprietary' === $license) {
27634 unset($licenses[$key]);
27635 }
27636 }
27637
27638 $licenseValidator = new SpdxLicenses();
27639 if (count($licenses) === 1 && !$licenseValidator->validate($licenses) && $licenseValidator->validate(trim($licenses[0]))) {
27640 $this->warnings[] = sprintf(
27641 'License %s must not contain extra spaces, make sure to trim it.',
27642 json_encode($this->config['license'])
27643 );
27644 } elseif (array() !== $licenses && !$licenseValidator->validate($licenses)) {
27645 $this->warnings[] = sprintf(
27646 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.' . PHP_EOL .
27647 'If the software is closed-source, you may use "proprietary" as license.',
27648 json_encode($this->config['license'])
27649 );
27650 } else if (!$releaseDate || $releaseDate->format('Y-m-d H:i:s') >= '2018-01-20 00:00:00') { 
27651  foreach ($licenses as $license) {
27652 $spdxLicense = $licenseValidator->getLicenseByIdentifier($license);
27653 if ($spdxLicense && $spdxLicense[3]) {
27654 if (preg_match('{^[AL]?GPL-[123](\.[01])?\+$}i', $license)) {
27655 $this->warnings[] = sprintf(
27656 'License "%s" is a deprecated SPDX license identifier, use "'.str_replace('+', '', $license).'-or-later" instead',
27657 $license
27658 );
27659 } elseif (preg_match('{^[AL]?GPL-[123](\.[01])?$}i', $license)) {
27660 $this->warnings[] = sprintf(
27661 'License "%s" is a deprecated SPDX license identifier, use "'.$license.'-only" or "'.$license.'-or-later" instead',
27662 $license
27663 );
27664 } else {
27665 $this->warnings[] = sprintf(
27666 'License "%s" is a deprecated SPDX license identifier, see https://spdx.org/licenses/',
27667 $license
27668 );
27669 }
27670 }
27671 }
27672 }
27673 }
27674 }
27675
27676 if ($this->validateArray('authors') && !empty($this->config['authors'])) {
27677 foreach ($this->config['authors'] as $key => $author) {
27678 if (!is_array($author)) {
27679 $this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
27680 unset($this->config['authors'][$key]);
27681 continue;
27682 }
27683 foreach (array('homepage', 'email', 'name', 'role') as $authorData) {
27684 if (isset($author[$authorData]) && !is_string($author[$authorData])) {
27685 $this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
27686 unset($this->config['authors'][$key][$authorData]);
27687 }
27688 }
27689 if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
27690 $this->warnings[] = 'authors.'.$key.'.homepage : invalid value ('.$author['homepage'].'), must be an http/https URL';
27691 unset($this->config['authors'][$key]['homepage']);
27692 }
27693 if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
27694 $this->warnings[] = 'authors.'.$key.'.email : invalid value ('.$author['email'].'), must be a valid email address';
27695 unset($this->config['authors'][$key]['email']);
27696 }
27697 if (empty($this->config['authors'][$key])) {
27698 unset($this->config['authors'][$key]);
27699 }
27700 }
27701 if (empty($this->config['authors'])) {
27702 unset($this->config['authors']);
27703 }
27704 }
27705
27706 if ($this->validateArray('support') && !empty($this->config['support'])) {
27707 foreach (array('issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss') as $key) {
27708 if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
27709 $this->errors[] = 'support.'.$key.' : invalid value, must be a string';
27710 unset($this->config['support'][$key]);
27711 }
27712 }
27713
27714 if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], FILTER_VALIDATE_EMAIL)) {
27715 $this->warnings[] = 'support.email : invalid value ('.$this->config['support']['email'].'), must be a valid email address';
27716 unset($this->config['support']['email']);
27717 }
27718
27719 if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) {
27720 $this->warnings[] = 'support.irc : invalid value ('.$this->config['support']['irc'].'), must be a irc://<server>/<channel> URL';
27721 unset($this->config['support']['irc']);
27722 }
27723
27724 foreach (array('issues', 'forum', 'wiki', 'source', 'docs') as $key) {
27725 if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
27726 $this->warnings[] = 'support.'.$key.' : invalid value ('.$this->config['support'][$key].'), must be an http/https URL';
27727 unset($this->config['support'][$key]);
27728 }
27729 }
27730 if (empty($this->config['support'])) {
27731 unset($this->config['support']);
27732 }
27733 }
27734
27735 $unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master'));
27736 $stableConstraint = new Constraint('=', '1.0.0');
27737
27738 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
27739 if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
27740 foreach ($this->config[$linkType] as $package => $constraint) {
27741 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
27742 $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
27743 }
27744 if (!is_string($constraint)) {
27745 $this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
27746 unset($this->config[$linkType][$package]);
27747 } elseif ('self.version' !== $constraint) {
27748 try {
27749 $linkConstraint = $this->versionParser->parseConstraints($constraint);
27750 } catch (\Exception $e) {
27751 $this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
27752 unset($this->config[$linkType][$package]);
27753 continue;
27754 }
27755
27756
27757  if (
27758 ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS)
27759 && 'require' === $linkType
27760 && $linkConstraint->matches($unboundConstraint)
27761 && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $package)
27762 ) {
27763 $this->warnings[] = $linkType.'.'.$package.' : unbound version constraints ('.$constraint.') should be avoided';
27764 } elseif (
27765
27766  ($this->flags & self::CHECK_STRICT_CONSTRAINTS)
27767 && 'require' === $linkType
27768 && substr($linkConstraint, 0, 1) === '='
27769 && $stableConstraint->versionCompare($stableConstraint, $linkConstraint, '<=')
27770 ) {
27771 $this->warnings[] = $linkType.'.'.$package.' : exact version constraints ('.$constraint.') should be avoided if the package follows semantic versioning';
27772 }
27773 }
27774 }
27775 }
27776 }
27777
27778 if ($this->validateArray('suggest') && !empty($this->config['suggest'])) {
27779 foreach ($this->config['suggest'] as $package => $description) {
27780 if (!is_string($description)) {
27781 $this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
27782 unset($this->config['suggest'][$package]);
27783 }
27784 }
27785 }
27786
27787 if ($this->validateString('minimum-stability') && !empty($this->config['minimum-stability'])) {
27788 if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
27789 $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
27790 unset($this->config['minimum-stability']);
27791 }
27792 }
27793
27794 if ($this->validateArray('autoload') && !empty($this->config['autoload'])) {
27795 $types = array('psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap');
27796 foreach ($this->config['autoload'] as $type => $typeConfig) {
27797 if (!in_array($type, $types)) {
27798 $this->errors[] = 'autoload : invalid value ('.$type.'), must be one of '.implode(', ', $types);
27799 unset($this->config['autoload'][$type]);
27800 }
27801 if ($type === 'psr-4') {
27802 foreach ($typeConfig as $namespace => $dirs) {
27803 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
27804 $this->errors[] = 'autoload.psr-4 : invalid value ('.$namespace.'), namespaces must end with a namespace separator, should be '.$namespace.'\\\\';
27805 }
27806 }
27807 }
27808 }
27809 }
27810
27811 if (!empty($this->config['autoload']['psr-4']) && !empty($this->config['target-dir'])) {
27812 $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
27813
27814  
27815  unset($this->config['autoload']['psr-4']);
27816 }
27817
27818
27819  
27820
27821
27822  
27823
27824 $this->validateFlatArray('include-path');
27825 $this->validateArray('transport-options');
27826
27827
27828  if (isset($this->config['extra']['branch-alias'])) {
27829 if (!is_array($this->config['extra']['branch-alias'])) {
27830 $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
27831 } else {
27832 foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
27833
27834  if ('-dev' !== substr($targetBranch, -4)) {
27835 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must end in -dev';
27836 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27837
27838 continue;
27839 }
27840
27841
27842  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
27843 if ('-dev' !== substr($validatedTargetBranch, -4)) {
27844 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
27845 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27846
27847 continue;
27848 }
27849
27850
27851  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
27852 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
27853 && (stripos($targetPrefix, $sourcePrefix) !== 0)
27854 ) {
27855 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
27856 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27857 }
27858 }
27859 }
27860 }
27861
27862 if ($this->errors) {
27863 throw new InvalidPackageException($this->errors, $this->warnings, $config);
27864 }
27865
27866 $package = $this->loader->load($this->config, $class);
27867 $this->config = null;
27868
27869 return $package;
27870 }
27871
27872 public function getWarnings()
27873 {
27874 return $this->warnings;
27875 }
27876
27877 public function getErrors()
27878 {
27879 return $this->errors;
27880 }
27881
27882 private function validateRegex($property, $regex, $mandatory = false)
27883 {
27884 if (!$this->validateString($property, $mandatory)) {
27885 return false;
27886 }
27887
27888 if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) {
27889 $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex;
27890 if ($mandatory) {
27891 $this->errors[] = $message;
27892 } else {
27893 $this->warnings[] = $message;
27894 }
27895 unset($this->config[$property]);
27896
27897 return false;
27898 }
27899
27900 return true;
27901 }
27902
27903 private function validateString($property, $mandatory = false)
27904 {
27905 if (isset($this->config[$property]) && !is_string($this->config[$property])) {
27906 $this->errors[] = $property.' : should be a string, '.gettype($this->config[$property]).' given';
27907 unset($this->config[$property]);
27908
27909 return false;
27910 }
27911
27912 if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
27913 if ($mandatory) {
27914 $this->errors[] = $property.' : must be present';
27915 }
27916 unset($this->config[$property]);
27917
27918 return false;
27919 }
27920
27921 return true;
27922 }
27923
27924 private function validateArray($property, $mandatory = false)
27925 {
27926 if (isset($this->config[$property]) && !is_array($this->config[$property])) {
27927 $this->errors[] = $property.' : should be an array, '.gettype($this->config[$property]).' given';
27928 unset($this->config[$property]);
27929
27930 return false;
27931 }
27932
27933 if (!isset($this->config[$property]) || !count($this->config[$property])) {
27934 if ($mandatory) {
27935 $this->errors[] = $property.' : must be present and contain at least one element';
27936 }
27937 unset($this->config[$property]);
27938
27939 return false;
27940 }
27941
27942 return true;
27943 }
27944
27945 private function validateFlatArray($property, $regex = null, $mandatory = false)
27946 {
27947 if (!$this->validateArray($property, $mandatory)) {
27948 return false;
27949 }
27950
27951 $pass = true;
27952 foreach ($this->config[$property] as $key => $value) {
27953 if (!is_string($value) && !is_numeric($value)) {
27954 $this->errors[] = $property.'.'.$key.' : must be a string or int, '.gettype($value).' given';
27955 unset($this->config[$property][$key]);
27956 $pass = false;
27957
27958 continue;
27959 }
27960
27961 if ($regex && !preg_match('{^'.$regex.'$}u', $value)) {
27962 $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex;
27963 unset($this->config[$property][$key]);
27964 $pass = false;
27965 }
27966 }
27967
27968 return $pass;
27969 }
27970
27971 private function validateUrl($property, $mandatory = false)
27972 {
27973 if (!$this->validateString($property, $mandatory)) {
27974 return false;
27975 }
27976
27977 if (!$this->filterUrl($this->config[$property])) {
27978 $this->warnings[] = $property.' : invalid value ('.$this->config[$property].'), must be an http/https URL';
27979 unset($this->config[$property]);
27980
27981 return false;
27982 }
27983
27984 return true;
27985 }
27986
27987 private function filterUrl($value, array $schemes = array('http', 'https'))
27988 {
27989 if ($value === '') {
27990 return true;
27991 }
27992
27993 $bits = parse_url($value);
27994 if (empty($bits['scheme']) || empty($bits['host'])) {
27995 return false;
27996 }
27997
27998 if (!in_array($bits['scheme'], $schemes, true)) {
27999 return false;
28000 }
28001
28002 return true;
28003 }
28004 }
28005 <?php
28006
28007
28008
28009
28010
28011
28012
28013
28014
28015
28016
28017 namespace Composer\Package;
28018
28019 use Composer\Json\JsonFile;
28020 use Composer\Installer\InstallationManager;
28021 use Composer\Repository\RepositoryManager;
28022 use Composer\Util\ProcessExecutor;
28023 use Composer\Repository\ArrayRepository;
28024 use Composer\Package\Dumper\ArrayDumper;
28025 use Composer\Package\Loader\ArrayLoader;
28026 use Composer\Util\Git as GitUtil;
28027 use Composer\IO\IOInterface;
28028 use Seld\JsonLint\ParsingException;
28029
28030
28031
28032
28033
28034
28035
28036 class Locker
28037 {
28038 private $lockFile;
28039 private $repositoryManager;
28040 private $installationManager;
28041 private $hash;
28042 private $contentHash;
28043 private $loader;
28044 private $dumper;
28045 private $process;
28046 private $lockDataCache;
28047
28048
28049
28050
28051
28052
28053
28054
28055
28056
28057 public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
28058 {
28059 $this->lockFile = $lockFile;
28060 $this->repositoryManager = $repositoryManager;
28061 $this->installationManager = $installationManager;
28062 $this->hash = md5($composerFileContents);
28063 $this->contentHash = self::getContentHash($composerFileContents);
28064 $this->loader = new ArrayLoader(null, true);
28065 $this->dumper = new ArrayDumper();
28066 $this->process = new ProcessExecutor($io);
28067 }
28068
28069
28070
28071
28072
28073
28074
28075
28076 public static function getContentHash($composerFileContents)
28077 {
28078 $content = json_decode($composerFileContents, true);
28079
28080 $relevantKeys = array(
28081 'name',
28082 'version',
28083 'require',
28084 'require-dev',
28085 'conflict',
28086 'replace',
28087 'provide',
28088 'minimum-stability',
28089 'prefer-stable',
28090 'repositories',
28091 'extra',
28092 );
28093
28094 $relevantContent = array();
28095
28096 foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
28097 $relevantContent[$key] = $content[$key];
28098 }
28099 if (isset($content['config']['platform'])) {
28100 $relevantContent['config']['platform'] = $content['config']['platform'];
28101 }
28102
28103 ksort($relevantContent);
28104
28105 return md5(json_encode($relevantContent));
28106 }
28107
28108
28109
28110
28111
28112
28113 public function isLocked()
28114 {
28115 if (!$this->lockFile->exists()) {
28116 return false;
28117 }
28118
28119 $data = $this->getLockData();
28120
28121 return isset($data['packages']);
28122 }
28123
28124
28125
28126
28127
28128
28129 public function isFresh()
28130 {
28131 $lock = $this->lockFile->read();
28132
28133 if (!empty($lock['content-hash'])) {
28134
28135  return $this->contentHash === $lock['content-hash'];
28136 }
28137
28138
28139  if (!empty($lock['hash'])) {
28140 return $this->hash === $lock['hash'];
28141 }
28142
28143
28144  return false;
28145 }
28146
28147
28148
28149
28150
28151
28152
28153
28154 public function getLockedRepository($withDevReqs = false)
28155 {
28156 $lockData = $this->getLockData();
28157 $packages = new ArrayRepository();
28158
28159 $lockedPackages = $lockData['packages'];
28160 if ($withDevReqs) {
28161 if (isset($lockData['packages-dev'])) {
28162 $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
28163 } else {
28164 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.');
28165 }
28166 }
28167
28168 if (empty($lockedPackages)) {
28169 return $packages;
28170 }
28171
28172 if (isset($lockedPackages[0]['name'])) {
28173 foreach ($lockedPackages as $info) {
28174 $packages->addPackage($this->loader->load($info));
28175 }
28176
28177 return $packages;
28178 }
28179
28180 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.');
28181 }
28182
28183
28184
28185
28186
28187
28188
28189 public function getPlatformRequirements($withDevReqs = false)
28190 {
28191 $lockData = $this->getLockData();
28192 $requirements = array();
28193
28194 if (!empty($lockData['platform'])) {
28195 $requirements = $this->loader->parseLinks(
28196 '__ROOT__',
28197 '1.0.0',
28198 'requires',
28199 isset($lockData['platform']) ? $lockData['platform'] : array()
28200 );
28201 }
28202
28203 if ($withDevReqs && !empty($lockData['platform-dev'])) {
28204 $devRequirements = $this->loader->parseLinks(
28205 '__ROOT__',
28206 '1.0.0',
28207 'requires',
28208 isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
28209 );
28210
28211 $requirements = array_merge($requirements, $devRequirements);
28212 }
28213
28214 return $requirements;
28215 }
28216
28217 public function getMinimumStability()
28218 {
28219 $lockData = $this->getLockData();
28220
28221 return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'stable';
28222 }
28223
28224 public function getStabilityFlags()
28225 {
28226 $lockData = $this->getLockData();
28227
28228 return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
28229 }
28230
28231 public function getPreferStable()
28232 {
28233 $lockData = $this->getLockData();
28234
28235
28236  
28237  return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null;
28238 }
28239
28240 public function getPreferLowest()
28241 {
28242 $lockData = $this->getLockData();
28243
28244
28245  
28246  return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
28247 }
28248
28249 public function getPlatformOverrides()
28250 {
28251 $lockData = $this->getLockData();
28252
28253 return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
28254 }
28255
28256 public function getAliases()
28257 {
28258 $lockData = $this->getLockData();
28259
28260 return isset($lockData['aliases']) ? $lockData['aliases'] : array();
28261 }
28262
28263 public function getLockData()
28264 {
28265 if (null !== $this->lockDataCache) {
28266 return $this->lockDataCache;
28267 }
28268
28269 if (!$this->lockFile->exists()) {
28270 throw new \LogicException('No lockfile found. Unable to read locked packages');
28271 }
28272
28273 return $this->lockDataCache = $this->lockFile->read();
28274 }
28275
28276
28277
28278
28279
28280
28281
28282
28283
28284
28285
28286
28287
28288
28289
28290
28291
28292 public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest, array $platformOverrides)
28293 {
28294 $lock = array(
28295 '_readme' => array('This file locks the dependencies of your project to a known state',
28296 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file',
28297 'This file is @gener'.'ated automatically', ),
28298 'content-hash' => $this->contentHash,
28299 'packages' => null,
28300 'packages-dev' => null,
28301 'aliases' => array(),
28302 'minimum-stability' => $minimumStability,
28303 'stability-flags' => $stabilityFlags,
28304 'prefer-stable' => $preferStable,
28305 'prefer-lowest' => $preferLowest,
28306 );
28307
28308 foreach ($aliases as $package => $versions) {
28309 foreach ($versions as $version => $alias) {
28310 $lock['aliases'][] = array(
28311 'alias' => $alias['alias'],
28312 'alias_normalized' => $alias['alias_normalized'],
28313 'version' => $version,
28314 'package' => $package,
28315 );
28316 }
28317 }
28318
28319 $lock['packages'] = $this->lockPackages($packages);
28320 if (null !== $devPackages) {
28321 $lock['packages-dev'] = $this->lockPackages($devPackages);
28322 }
28323
28324 $lock['platform'] = $platformReqs;
28325 $lock['platform-dev'] = $platformDevReqs;
28326 if ($platformOverrides) {
28327 $lock['platform-overrides'] = $platformOverrides;
28328 }
28329
28330 if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
28331 if ($this->lockFile->exists()) {
28332 unlink($this->lockFile->getPath());
28333 }
28334
28335 return false;
28336 }
28337
28338 try {
28339 $isLocked = $this->isLocked();
28340 } catch (ParsingException $e) {
28341 $isLocked = false;
28342 }
28343 if (!$isLocked || $lock !== $this->getLockData()) {
28344 $this->lockFile->write($lock);
28345 $this->lockDataCache = null;
28346
28347 return true;
28348 }
28349
28350 return false;
28351 }
28352
28353 private function lockPackages(array $packages)
28354 {
28355 $locked = array();
28356
28357 foreach ($packages as $package) {
28358 if ($package instanceof AliasPackage) {
28359 continue;
28360 }
28361
28362 $name = $package->getPrettyName();
28363 $version = $package->getPrettyVersion();
28364
28365 if (!$name || !$version) {
28366 throw new \LogicException(sprintf(
28367 'Package "%s" has no version or name and can not be locked', $package
28368 ));
28369 }
28370
28371 $spec = $this->dumper->dump($package);
28372 unset($spec['version_normalized']);
28373
28374
28375  $time = isset($spec['time']) ? $spec['time'] : null;
28376 unset($spec['time']);
28377 if ($package->isDev() && $package->getInstallationSource() === 'source') {
28378
28379  $time = $this->getPackageTime($package) ?: $time;
28380 }
28381 if (null !== $time) {
28382 $spec['time'] = $time;
28383 }
28384
28385 unset($spec['installation-source']);
28386
28387 $locked[] = $spec;
28388 }
28389
28390 usort($locked, function ($a, $b) {
28391 $comparison = strcmp($a['name'], $b['name']);
28392
28393 if (0 !== $comparison) {
28394 return $comparison;
28395 }
28396
28397
28398  return strcmp($a['version'], $b['version']);
28399 });
28400
28401 return $locked;
28402 }
28403
28404
28405
28406
28407
28408
28409
28410 private function getPackageTime(PackageInterface $package)
28411 {
28412 if (!function_exists('proc_open')) {
28413 return null;
28414 }
28415
28416 $path = realpath($this->installationManager->getInstallPath($package));
28417 $sourceType = $package->getSourceType();
28418 $datetime = null;
28419
28420 if ($path && in_array($sourceType, array('git', 'hg'))) {
28421 $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
28422 switch ($sourceType) {
28423 case 'git':
28424 GitUtil::cleanEnv();
28425
28426 if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
28427 $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
28428 }
28429 break;
28430
28431 case 'hg':
28432 if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
28433 $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
28434 }
28435 break;
28436 }
28437 }
28438
28439 return $datetime ? $datetime->format(DATE_RFC3339) : null;
28440 }
28441 }
28442 <?php
28443
28444
28445
28446
28447
28448
28449
28450
28451
28452
28453
28454 namespace Composer\Package;
28455
28456 use Composer\Package\Version\VersionParser;
28457 use Composer\Util\ComposerMirror;
28458
28459
28460
28461
28462
28463
28464 class Package extends BasePackage
28465 {
28466 protected $type;
28467 protected $targetDir;
28468 protected $installationSource;
28469 protected $sourceType;
28470 protected $sourceUrl;
28471 protected $sourceReference;
28472 protected $sourceMirrors;
28473 protected $distType;
28474 protected $distUrl;
28475 protected $distReference;
28476 protected $distSha1Checksum;
28477 protected $distMirrors;
28478 protected $version;
28479 protected $prettyVersion;
28480 protected $releaseDate;
28481 protected $extra = array();
28482 protected $binaries = array();
28483 protected $dev;
28484 protected $stability;
28485 protected $notificationUrl;
28486
28487
28488 protected $requires = array();
28489
28490 protected $conflicts = array();
28491
28492 protected $provides = array();
28493
28494 protected $replaces = array();
28495
28496 protected $devRequires = array();
28497 protected $suggests = array();
28498 protected $autoload = array();
28499 protected $devAutoload = array();
28500 protected $includePaths = array();
28501 protected $archiveExcludes = array();
28502
28503
28504
28505
28506
28507
28508
28509
28510 public function __construct($name, $version, $prettyVersion)
28511 {
28512 parent::__construct($name);
28513
28514 $this->version = $version;
28515 $this->prettyVersion = $prettyVersion;
28516
28517 $this->stability = VersionParser::parseStability($version);
28518 $this->dev = $this->stability === 'dev';
28519 }
28520
28521
28522
28523
28524 public function isDev()
28525 {
28526 return $this->dev;
28527 }
28528
28529
28530
28531
28532 public function setType($type)
28533 {
28534 $this->type = $type;
28535 }
28536
28537
28538
28539
28540 public function getType()
28541 {
28542 return $this->type ?: 'library';
28543 }
28544
28545
28546
28547
28548 public function getStability()
28549 {
28550 return $this->stability;
28551 }
28552
28553
28554
28555
28556 public function setTargetDir($targetDir)
28557 {
28558 $this->targetDir = $targetDir;
28559 }
28560
28561
28562
28563
28564 public function getTargetDir()
28565 {
28566 if (null === $this->targetDir) {
28567 return;
28568 }
28569
28570 return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
28571 }
28572
28573
28574
28575
28576 public function setExtra(array $extra)
28577 {
28578 $this->extra = $extra;
28579 }
28580
28581
28582
28583
28584 public function getExtra()
28585 {
28586 return $this->extra;
28587 }
28588
28589
28590
28591
28592 public function setBinaries(array $binaries)
28593 {
28594 $this->binaries = $binaries;
28595 }
28596
28597
28598
28599
28600 public function getBinaries()
28601 {
28602 return $this->binaries;
28603 }
28604
28605
28606
28607
28608 public function setInstallationSource($type)
28609 {
28610 $this->installationSource = $type;
28611 }
28612
28613
28614
28615
28616 public function getInstallationSource()
28617 {
28618 return $this->installationSource;
28619 }
28620
28621
28622
28623
28624 public function setSourceType($type)
28625 {
28626 $this->sourceType = $type;
28627 }
28628
28629
28630
28631
28632 public function getSourceType()
28633 {
28634 return $this->sourceType;
28635 }
28636
28637
28638
28639
28640 public function setSourceUrl($url)
28641 {
28642 $this->sourceUrl = $url;
28643 }
28644
28645
28646
28647
28648 public function getSourceUrl()
28649 {
28650 return $this->sourceUrl;
28651 }
28652
28653
28654
28655
28656 public function setSourceReference($reference)
28657 {
28658 $this->sourceReference = $reference;
28659 }
28660
28661
28662
28663
28664 public function getSourceReference()
28665 {
28666 return $this->sourceReference;
28667 }
28668
28669
28670
28671
28672 public function setSourceMirrors($mirrors)
28673 {
28674 $this->sourceMirrors = $mirrors;
28675 }
28676
28677
28678
28679
28680 public function getSourceMirrors()
28681 {
28682 return $this->sourceMirrors;
28683 }
28684
28685
28686
28687
28688 public function getSourceUrls()
28689 {
28690 return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
28691 }
28692
28693
28694
28695
28696 public function setDistType($type)
28697 {
28698 $this->distType = $type;
28699 }
28700
28701
28702
28703
28704 public function getDistType()
28705 {
28706 return $this->distType;
28707 }
28708
28709
28710
28711
28712 public function setDistUrl($url)
28713 {
28714 $this->distUrl = $url;
28715 }
28716
28717
28718
28719
28720 public function getDistUrl()
28721 {
28722 return $this->distUrl;
28723 }
28724
28725
28726
28727
28728 public function setDistReference($reference)
28729 {
28730 $this->distReference = $reference;
28731 }
28732
28733
28734
28735
28736 public function getDistReference()
28737 {
28738 return $this->distReference;
28739 }
28740
28741
28742
28743
28744 public function setDistSha1Checksum($sha1checksum)
28745 {
28746 $this->distSha1Checksum = $sha1checksum;
28747 }
28748
28749
28750
28751
28752 public function getDistSha1Checksum()
28753 {
28754 return $this->distSha1Checksum;
28755 }
28756
28757
28758
28759
28760 public function setDistMirrors($mirrors)
28761 {
28762 $this->distMirrors = $mirrors;
28763 }
28764
28765
28766
28767
28768 public function getDistMirrors()
28769 {
28770 return $this->distMirrors;
28771 }
28772
28773
28774
28775
28776 public function getDistUrls()
28777 {
28778 return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
28779 }
28780
28781
28782
28783
28784 public function getVersion()
28785 {
28786 return $this->version;
28787 }
28788
28789
28790
28791
28792 public function getPrettyVersion()
28793 {
28794 return $this->prettyVersion;
28795 }
28796
28797
28798
28799
28800
28801
28802 public function setReleaseDate(\DateTime $releaseDate)
28803 {
28804 $this->releaseDate = $releaseDate;
28805 }
28806
28807
28808
28809
28810 public function getReleaseDate()
28811 {
28812 return $this->releaseDate;
28813 }
28814
28815
28816
28817
28818
28819
28820 public function setRequires(array $requires)
28821 {
28822 $this->requires = $requires;
28823 }
28824
28825
28826
28827
28828 public function getRequires()
28829 {
28830 return $this->requires;
28831 }
28832
28833
28834
28835
28836
28837
28838 public function setConflicts(array $conflicts)
28839 {
28840 $this->conflicts = $conflicts;
28841 }
28842
28843
28844
28845
28846 public function getConflicts()
28847 {
28848 return $this->conflicts;
28849 }
28850
28851
28852
28853
28854
28855
28856 public function setProvides(array $provides)
28857 {
28858 $this->provides = $provides;
28859 }
28860
28861
28862
28863
28864 public function getProvides()
28865 {
28866 return $this->provides;
28867 }
28868
28869
28870
28871
28872
28873
28874 public function setReplaces(array $replaces)
28875 {
28876 $this->replaces = $replaces;
28877 }
28878
28879
28880
28881
28882 public function getReplaces()
28883 {
28884 return $this->replaces;
28885 }
28886
28887
28888
28889
28890
28891
28892 public function setDevRequires(array $devRequires)
28893 {
28894 $this->devRequires = $devRequires;
28895 }
28896
28897
28898
28899
28900 public function getDevRequires()
28901 {
28902 return $this->devRequires;
28903 }
28904
28905
28906
28907
28908
28909
28910 public function setSuggests(array $suggests)
28911 {
28912 $this->suggests = $suggests;
28913 }
28914
28915
28916
28917
28918 public function getSuggests()
28919 {
28920 return $this->suggests;
28921 }
28922
28923
28924
28925
28926
28927
28928 public function setAutoload(array $autoload)
28929 {
28930 $this->autoload = $autoload;
28931 }
28932
28933
28934
28935
28936 public function getAutoload()
28937 {
28938 return $this->autoload;
28939 }
28940
28941
28942
28943
28944
28945
28946 public function setDevAutoload(array $devAutoload)
28947 {
28948 $this->devAutoload = $devAutoload;
28949 }
28950
28951
28952
28953
28954 public function getDevAutoload()
28955 {
28956 return $this->devAutoload;
28957 }
28958
28959
28960
28961
28962
28963
28964 public function setIncludePaths(array $includePaths)
28965 {
28966 $this->includePaths = $includePaths;
28967 }
28968
28969
28970
28971
28972 public function getIncludePaths()
28973 {
28974 return $this->includePaths;
28975 }
28976
28977
28978
28979
28980
28981
28982 public function setNotificationUrl($notificationUrl)
28983 {
28984 $this->notificationUrl = $notificationUrl;
28985 }
28986
28987
28988
28989
28990 public function getNotificationUrl()
28991 {
28992 return $this->notificationUrl;
28993 }
28994
28995
28996
28997
28998
28999
29000 public function setArchiveExcludes(array $excludes)
29001 {
29002 $this->archiveExcludes = $excludes;
29003 }
29004
29005
29006
29007
29008 public function getArchiveExcludes()
29009 {
29010 return $this->archiveExcludes;
29011 }
29012
29013
29014
29015
29016
29017
29018
29019
29020 public function replaceVersion($version, $prettyVersion)
29021 {
29022 $this->version = $version;
29023 $this->prettyVersion = $prettyVersion;
29024
29025 $this->stability = VersionParser::parseStability($version);
29026 $this->dev = $this->stability === 'dev';
29027 }
29028
29029 protected function getUrls($url, $mirrors, $ref, $type, $urlType)
29030 {
29031 if (!$url) {
29032 return array();
29033 }
29034 $urls = array($url);
29035 if ($mirrors) {
29036 foreach ($mirrors as $mirror) {
29037 if ($urlType === 'dist') {
29038 $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type);
29039 } elseif ($urlType === 'source' && $type === 'git') {
29040 $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
29041 } elseif ($urlType === 'source' && $type === 'hg') {
29042 $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
29043 }
29044 if (!in_array($mirrorUrl, $urls)) {
29045 $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
29046 $func($urls, $mirrorUrl);
29047 }
29048 }
29049 }
29050
29051 return $urls;
29052 }
29053 }
29054 <?php
29055
29056
29057
29058
29059
29060
29061
29062
29063
29064
29065
29066 namespace Composer\Package;
29067
29068 use Composer\Repository\RepositoryInterface;
29069
29070
29071
29072
29073
29074
29075 interface PackageInterface
29076 {
29077
29078
29079
29080
29081
29082 public function getName();
29083
29084
29085
29086
29087
29088
29089 public function getPrettyName();
29090
29091
29092
29093
29094
29095
29096
29097
29098
29099 public function getNames();
29100
29101
29102
29103
29104
29105
29106 public function setId($id);
29107
29108
29109
29110
29111
29112
29113 public function getId();
29114
29115
29116
29117
29118
29119
29120 public function isDev();
29121
29122
29123
29124
29125
29126
29127 public function getType();
29128
29129
29130
29131
29132
29133
29134 public function getTargetDir();
29135
29136
29137
29138
29139
29140
29141 public function getExtra();
29142
29143
29144
29145
29146
29147
29148 public function setInstallationSource($type);
29149
29150
29151
29152
29153
29154
29155 public function getInstallationSource();
29156
29157
29158
29159
29160
29161
29162 public function getSourceType();
29163
29164
29165
29166
29167
29168
29169 public function getSourceUrl();
29170
29171
29172
29173
29174
29175
29176 public function getSourceUrls();
29177
29178
29179
29180
29181
29182
29183 public function getSourceReference();
29184
29185
29186
29187
29188
29189
29190 public function getSourceMirrors();
29191
29192
29193
29194
29195
29196
29197 public function getDistType();
29198
29199
29200
29201
29202
29203
29204 public function getDistUrl();
29205
29206
29207
29208
29209
29210
29211 public function getDistUrls();
29212
29213
29214
29215
29216
29217
29218 public function getDistReference();
29219
29220
29221
29222
29223
29224
29225 public function getDistSha1Checksum();
29226
29227
29228
29229
29230
29231
29232 public function getDistMirrors();
29233
29234
29235
29236
29237
29238
29239 public function getVersion();
29240
29241
29242
29243
29244
29245
29246 public function getPrettyVersion();
29247
29248
29249
29250
29251
29252
29253
29254
29255
29256 public function getFullPrettyVersion($truncate = true);
29257
29258
29259
29260
29261
29262
29263 public function getReleaseDate();
29264
29265
29266
29267
29268
29269
29270 public function getStability();
29271
29272
29273
29274
29275
29276
29277
29278 public function getRequires();
29279
29280
29281
29282
29283
29284
29285
29286 public function getConflicts();
29287
29288
29289
29290
29291
29292
29293
29294 public function getProvides();
29295
29296
29297
29298
29299
29300
29301
29302 public function getReplaces();
29303
29304
29305
29306
29307
29308
29309
29310 public function getDevRequires();
29311
29312
29313
29314
29315
29316
29317
29318 public function getSuggests();
29319
29320
29321
29322
29323
29324
29325
29326
29327
29328
29329
29330 public function getAutoload();
29331
29332
29333
29334
29335
29336
29337
29338
29339
29340
29341
29342 public function getDevAutoload();
29343
29344
29345
29346
29347
29348
29349
29350 public function getIncludePaths();
29351
29352
29353
29354
29355
29356
29357 public function setRepository(RepositoryInterface $repository);
29358
29359
29360
29361
29362
29363
29364 public function getRepository();
29365
29366
29367
29368
29369
29370
29371 public function getBinaries();
29372
29373
29374
29375
29376
29377
29378 public function getUniqueName();
29379
29380
29381
29382
29383
29384
29385 public function getNotificationUrl();
29386
29387
29388
29389
29390
29391
29392 public function __toString();
29393
29394
29395
29396
29397
29398
29399 public function getPrettyString();
29400
29401
29402
29403
29404
29405
29406 public function getArchiveExcludes();
29407
29408
29409
29410
29411
29412
29413 public function getTransportOptions();
29414 }
29415 <?php
29416
29417
29418
29419
29420
29421
29422
29423
29424
29425
29426
29427 namespace Composer\Package;
29428
29429
29430
29431
29432 class RootAliasPackage extends AliasPackage implements RootPackageInterface
29433 {
29434 public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
29435 {
29436 parent::__construct($aliasOf, $version, $prettyVersion);
29437 }
29438
29439
29440
29441
29442 public function getAliases()
29443 {
29444 return $this->aliasOf->getAliases();
29445 }
29446
29447
29448
29449
29450 public function getMinimumStability()
29451 {
29452 return $this->aliasOf->getMinimumStability();
29453 }
29454
29455
29456
29457
29458 public function getStabilityFlags()
29459 {
29460 return $this->aliasOf->getStabilityFlags();
29461 }
29462
29463
29464
29465
29466 public function getReferences()
29467 {
29468 return $this->aliasOf->getReferences();
29469 }
29470
29471
29472
29473
29474 public function getPreferStable()
29475 {
29476 return $this->aliasOf->getPreferStable();
29477 }
29478
29479
29480
29481
29482 public function getConfig()
29483 {
29484 return $this->aliasOf->getConfig();
29485 }
29486
29487
29488
29489
29490 public function setRequires(array $require)
29491 {
29492 $this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
29493
29494 $this->aliasOf->setRequires($require);
29495 }
29496
29497
29498
29499
29500 public function setDevRequires(array $devRequire)
29501 {
29502 $this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
29503
29504 $this->aliasOf->setDevRequires($devRequire);
29505 }
29506
29507
29508
29509
29510 public function setConflicts(array $conflicts)
29511 {
29512 $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, 'conflicts');
29513 $this->aliasOf->setConflicts($conflicts);
29514 }
29515
29516
29517
29518
29519 public function setProvides(array $provides)
29520 {
29521 $this->provides = $this->replaceSelfVersionDependencies($provides, 'provides');
29522 $this->aliasOf->setProvides($provides);
29523 }
29524
29525
29526
29527
29528 public function setReplaces(array $replaces)
29529 {
29530 $this->replaces = $this->replaceSelfVersionDependencies($replaces, 'replaces');
29531 $this->aliasOf->setReplaces($replaces);
29532 }
29533
29534
29535
29536
29537 public function setRepositories($repositories)
29538 {
29539 $this->aliasOf->setRepositories($repositories);
29540 }
29541
29542
29543
29544
29545 public function setAutoload(array $autoload)
29546 {
29547 $this->aliasOf->setAutoload($autoload);
29548 }
29549
29550
29551
29552
29553 public function setDevAutoload(array $devAutoload)
29554 {
29555 $this->aliasOf->setDevAutoload($devAutoload);
29556 }
29557
29558
29559
29560
29561 public function setStabilityFlags(array $stabilityFlags)
29562 {
29563 $this->aliasOf->setStabilityFlags($stabilityFlags);
29564 }
29565
29566
29567
29568
29569 public function setSuggests(array $suggests)
29570 {
29571 $this->aliasOf->setSuggests($suggests);
29572 }
29573
29574
29575
29576
29577 public function setExtra(array $extra)
29578 {
29579 $this->aliasOf->setExtra($extra);
29580 }
29581
29582 public function __clone()
29583 {
29584 parent::__clone();
29585 $this->aliasOf = clone $this->aliasOf;
29586 }
29587 }
29588 <?php
29589
29590
29591
29592
29593
29594
29595
29596
29597
29598
29599
29600 namespace Composer\Package;
29601
29602
29603
29604
29605
29606
29607 class RootPackage extends CompletePackage implements RootPackageInterface
29608 {
29609 protected $minimumStability = 'stable';
29610 protected $preferStable = false;
29611 protected $stabilityFlags = array();
29612 protected $config = array();
29613 protected $references = array();
29614 protected $aliases = array();
29615
29616
29617
29618
29619
29620
29621 public function setMinimumStability($minimumStability)
29622 {
29623 $this->minimumStability = $minimumStability;
29624 }
29625
29626
29627
29628
29629 public function getMinimumStability()
29630 {
29631 return $this->minimumStability;
29632 }
29633
29634
29635
29636
29637
29638
29639 public function setStabilityFlags(array $stabilityFlags)
29640 {
29641 $this->stabilityFlags = $stabilityFlags;
29642 }
29643
29644
29645
29646
29647 public function getStabilityFlags()
29648 {
29649 return $this->stabilityFlags;
29650 }
29651
29652
29653
29654
29655
29656
29657 public function setPreferStable($preferStable)
29658 {
29659 $this->preferStable = $preferStable;
29660 }
29661
29662
29663
29664
29665 public function getPreferStable()
29666 {
29667 return $this->preferStable;
29668 }
29669
29670
29671
29672
29673
29674
29675 public function setConfig(array $config)
29676 {
29677 $this->config = $config;
29678 }
29679
29680
29681
29682
29683 public function getConfig()
29684 {
29685 return $this->config;
29686 }
29687
29688
29689
29690
29691
29692
29693 public function setReferences(array $references)
29694 {
29695 $this->references = $references;
29696 }
29697
29698
29699
29700
29701 public function getReferences()
29702 {
29703 return $this->references;
29704 }
29705
29706
29707
29708
29709
29710
29711 public function setAliases(array $aliases)
29712 {
29713 $this->aliases = $aliases;
29714 }
29715
29716
29717
29718
29719 public function getAliases()
29720 {
29721 return $this->aliases;
29722 }
29723 }
29724 <?php
29725
29726
29727
29728
29729
29730
29731
29732
29733
29734
29735
29736 namespace Composer\Package;
29737
29738
29739
29740
29741
29742
29743 interface RootPackageInterface extends CompletePackageInterface
29744 {
29745
29746
29747
29748
29749
29750 public function getAliases();
29751
29752
29753
29754
29755
29756
29757 public function getMinimumStability();
29758
29759
29760
29761
29762
29763
29764
29765
29766 public function getStabilityFlags();
29767
29768
29769
29770
29771
29772
29773
29774
29775 public function getReferences();
29776
29777
29778
29779
29780
29781
29782 public function getPreferStable();
29783
29784
29785
29786
29787
29788
29789 public function getConfig();
29790
29791
29792
29793
29794
29795
29796 public function setRequires(array $requires);
29797
29798
29799
29800
29801
29802
29803 public function setDevRequires(array $devRequires);
29804
29805
29806
29807
29808
29809
29810 public function setConflicts(array $conflicts);
29811
29812
29813
29814
29815
29816
29817 public function setProvides(array $provides);
29818
29819
29820
29821
29822
29823
29824 public function setReplaces(array $replaces);
29825
29826
29827
29828
29829
29830
29831 public function setRepositories($repositories);
29832
29833
29834
29835
29836
29837
29838 public function setAutoload(array $autoload);
29839
29840
29841
29842
29843
29844
29845 public function setDevAutoload(array $devAutoload);
29846
29847
29848
29849
29850
29851
29852 public function setStabilityFlags(array $stabilityFlags);
29853
29854
29855
29856
29857
29858
29859 public function setSuggests(array $suggests);
29860
29861
29862
29863
29864 public function setExtra(array $extra);
29865 }
29866 <?php
29867
29868
29869
29870
29871
29872
29873
29874
29875
29876
29877
29878 namespace Composer\Package\Version;
29879
29880 use Composer\Config;
29881 use Composer\Repository\Vcs\HgDriver;
29882 use Composer\IO\NullIO;
29883 use Composer\Semver\VersionParser as SemverVersionParser;
29884 use Composer\Util\Git as GitUtil;
29885 use Composer\Util\ProcessExecutor;
29886 use Composer\Util\Svn as SvnUtil;
29887
29888
29889
29890
29891
29892
29893
29894 class VersionGuesser
29895 {
29896
29897
29898
29899 private $config;
29900
29901
29902
29903
29904 private $process;
29905
29906
29907
29908
29909 private $versionParser;
29910
29911
29912
29913
29914
29915
29916 public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
29917 {
29918 $this->config = $config;
29919 $this->process = $process;
29920 $this->versionParser = $versionParser;
29921 }
29922
29923
29924
29925
29926
29927
29928
29929 public function guessVersion(array $packageConfig, $path)
29930 {
29931 if (function_exists('proc_open')) {
29932 $versionData = $this->guessGitVersion($packageConfig, $path);
29933 if (null !== $versionData && null !== $versionData['version']) {
29934 return $this->postprocess($versionData);
29935 }
29936
29937 $versionData = $this->guessHgVersion($packageConfig, $path);
29938 if (null !== $versionData && null !== $versionData['version']) {
29939 return $this->postprocess($versionData);
29940 }
29941
29942 $versionData = $this->guessFossilVersion($packageConfig, $path);
29943 if (null !== $versionData && null !== $versionData['version']) {
29944 return $this->postprocess($versionData);
29945 }
29946
29947 $versionData = $this->guessSvnVersion($packageConfig, $path);
29948 if (null !== $versionData && null !== $versionData['version']) {
29949 return $this->postprocess($versionData);
29950 }
29951 }
29952 }
29953
29954 private function postprocess(array $versionData)
29955 {
29956 if ('-dev' === substr($versionData['version'], -4) && preg_match('{\.9{7}}', $versionData['version'])) {
29957 $versionData['pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['version']);
29958 }
29959
29960 return $versionData;
29961 }
29962
29963 private function guessGitVersion(array $packageConfig, $path)
29964 {
29965 GitUtil::cleanEnv();
29966 $commit = null;
29967 $version = null;
29968 $prettyVersion = null;
29969 $isDetached = false;
29970
29971
29972  if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
29973 $branches = array();
29974 $isFeatureBranch = false;
29975
29976
29977  foreach ($this->process->splitLines($output) as $branch) {
29978 if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
29979 if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ' || substr($match[1], 0, 17) === '(HEAD detached at') {
29980 $version = 'dev-' . $match[2];
29981 $prettyVersion = $version;
29982 $isFeatureBranch = true;
29983 $isDetached = true;
29984 } else {
29985 $version = $this->versionParser->normalizeBranch($match[1]);
29986 $prettyVersion = 'dev-' . $match[1];
29987 $isFeatureBranch = 0 === strpos($version, 'dev-');
29988 }
29989
29990 if ($match[2]) {
29991 $commit = $match[2];
29992 }
29993 }
29994
29995 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
29996 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
29997 $branches[] = $match[1];
29998 }
29999 }
30000 }
30001
30002 if ($isFeatureBranch) {
30003
30004  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
30005 $version = $result['version'];
30006 $prettyVersion = $result['pretty_version'];
30007 }
30008 }
30009
30010 if (!$version || $isDetached) {
30011 $result = $this->versionFromGitTags($path);
30012 if ($result) {
30013 $version = $result['version'];
30014 $prettyVersion = $result['pretty_version'];
30015 }
30016 }
30017
30018 if (!$commit) {
30019 $command = 'git log --pretty="%H" -n1 HEAD';
30020 if (0 === $this->process->execute($command, $output, $path)) {
30021 $commit = trim($output) ?: null;
30022 }
30023 }
30024
30025 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion);
30026 }
30027
30028 private function versionFromGitTags($path)
30029 {
30030
30031  if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
30032 try {
30033 $version = $this->versionParser->normalize(trim($output));
30034
30035 return array('version' => $version, 'pretty_version' => trim($output));
30036 } catch (\Exception $e) {
30037 }
30038 }
30039
30040 return null;
30041 }
30042
30043 private function guessHgVersion(array $packageConfig, $path)
30044 {
30045
30046  if (0 === $this->process->execute('hg branch', $output, $path)) {
30047 $branch = trim($output);
30048 $version = $this->versionParser->normalizeBranch($branch);
30049 $isFeatureBranch = 0 === strpos($version, 'dev-');
30050
30051 if ('9999999-dev' === $version) {
30052 $version = 'dev-' . $branch;
30053 }
30054
30055 if (!$isFeatureBranch) {
30056 return array('version' => $version, 'commit' => null, 'pretty_version' => $version);
30057 }
30058
30059
30060  $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process);
30061 $branches = array_keys($driver->getBranches());
30062
30063
30064  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
30065 $result['commit'] = '';
30066
30067 return $result;
30068 }
30069 }
30070
30071 private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path)
30072 {
30073 $prettyVersion = $version;
30074
30075
30076  
30077  if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version]))
30078 || strpos(json_encode($packageConfig), '"self.version"')
30079 ) {
30080 $branch = preg_replace('{^dev-}', '', $version);
30081 $length = PHP_INT_MAX;
30082
30083 $nonFeatureBranches = '';
30084 if (!empty($packageConfig['non-feature-branches'])) {
30085 $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
30086 }
30087
30088 foreach ($branches as $candidate) {
30089
30090  if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
30091 break;
30092 }
30093
30094
30095  if ($candidate === $branch || !preg_match('{^(' . $nonFeatureBranches . '|master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
30096 continue;
30097 }
30098
30099 $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
30100 if (0 !== $this->process->execute($cmdLine, $output, $path)) {
30101 continue;
30102 }
30103
30104 if (strlen($output) < $length) {
30105 $length = strlen($output);
30106 $version = $this->versionParser->normalizeBranch($candidate);
30107 $prettyVersion = 'dev-' . $match[1];
30108 if ('9999999-dev' === $version) {
30109 $version = $prettyVersion;
30110 }
30111 }
30112 }
30113 }
30114
30115 return array('version' => $version, 'pretty_version' => $prettyVersion);
30116 }
30117
30118 private function guessFossilVersion(array $packageConfig, $path)
30119 {
30120 $version = null;
30121 $prettyVersion = null;
30122
30123
30124  if (0 === $this->process->execute('fossil branch list', $output, $path)) {
30125 $branch = trim($output);
30126 $version = $this->versionParser->normalizeBranch($branch);
30127 $prettyVersion = 'dev-' . $branch;
30128
30129 if ('9999999-dev' === $version) {
30130 $version = $prettyVersion;
30131 }
30132 }
30133
30134
30135  if (0 === $this->process->execute('fossil tag list', $output, $path)) {
30136 try {
30137 $version = $this->versionParser->normalize(trim($output));
30138 $prettyVersion = trim($output);
30139 } catch (\Exception $e) {
30140 }
30141 }
30142
30143 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
30144 }
30145
30146 private function guessSvnVersion(array $packageConfig, $path)
30147 {
30148 SvnUtil::cleanEnv();
30149
30150
30151  if (0 === $this->process->execute('svn info --xml', $output, $path)) {
30152 $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
30153 $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
30154 $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
30155
30156 $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
30157
30158 if (preg_match($urlPattern, $output, $matches)) {
30159 if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
30160
30161  $version = $this->versionParser->normalizeBranch($matches[3]);
30162 $prettyVersion = 'dev-' . $matches[3];
30163 if ('9999999-dev' === $version) {
30164 $version = $prettyVersion;
30165 }
30166
30167 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
30168 }
30169
30170 $prettyVersion = trim($matches[1]);
30171 $version = $this->versionParser->normalize($prettyVersion);
30172
30173 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
30174 }
30175 }
30176 }
30177 }
30178 <?php
30179
30180
30181
30182
30183
30184
30185
30186
30187
30188
30189
30190 namespace Composer\Package\Version;
30191
30192 use Composer\Repository\PlatformRepository;
30193 use Composer\Semver\VersionParser as SemverVersionParser;
30194
30195 class VersionParser extends SemverVersionParser
30196 {
30197 private static $constraints = array();
30198
30199
30200
30201
30202 public function parseConstraints($constraints)
30203 {
30204 if (!isset(self::$constraints[$constraints])) {
30205 self::$constraints[$constraints] = parent::parseConstraints($constraints);
30206 }
30207
30208 return self::$constraints[$constraints];
30209 }
30210
30211
30212
30213
30214
30215
30216
30217
30218
30219
30220
30221 public function parseNameVersionPairs(array $pairs)
30222 {
30223 $pairs = array_values($pairs);
30224 $result = array();
30225
30226 for ($i = 0, $count = count($pairs); $i < $count; $i++) {
30227 $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
30228 if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/') && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $pairs[$i + 1])) {
30229 $pair .= ' '.$pairs[$i + 1];
30230 $i++;
30231 }
30232
30233 if (strpos($pair, ' ')) {
30234 list($name, $version) = explode(' ', $pair, 2);
30235 $result[] = array('name' => $name, 'version' => $version);
30236 } else {
30237 $result[] = array('name' => $pair);
30238 }
30239 }
30240
30241 return $result;
30242 }
30243 }
30244 <?php
30245
30246
30247
30248
30249
30250
30251
30252
30253
30254
30255
30256 namespace Composer\Package\Version;
30257
30258 use Composer\DependencyResolver\Pool;
30259 use Composer\Package\BasePackage;
30260 use Composer\Package\PackageInterface;
30261 use Composer\Package\Loader\ArrayLoader;
30262 use Composer\Package\Dumper\ArrayDumper;
30263 use Composer\Semver\Constraint\Constraint;
30264
30265
30266
30267
30268
30269
30270
30271 class VersionSelector
30272 {
30273 private $pool;
30274
30275 private $parser;
30276
30277 public function __construct(Pool $pool)
30278 {
30279 $this->pool = $pool;
30280 }
30281
30282
30283
30284
30285
30286
30287
30288
30289
30290
30291
30292 public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
30293 {
30294 $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
30295 $candidates = $this->pool->whatProvides(strtolower($packageName), $constraint, true);
30296
30297 if ($targetPhpVersion) {
30298 $phpConstraint = new Constraint('==', $this->getParser()->normalize($targetPhpVersion));
30299 $candidates = array_filter($candidates, function ($pkg) use ($phpConstraint) {
30300 $reqs = $pkg->getRequires();
30301
30302 return !isset($reqs['php']) || $reqs['php']->getConstraint()->matches($phpConstraint);
30303 });
30304 }
30305
30306 if (!$candidates) {
30307 return false;
30308 }
30309
30310
30311  $package = reset($candidates);
30312 $minPriority = BasePackage::$stabilities[$preferredStability];
30313 foreach ($candidates as $candidate) {
30314 $candidatePriority = $candidate->getStabilityPriority();
30315 $currentPriority = $package->getStabilityPriority();
30316
30317
30318  
30319  if ($minPriority < $candidatePriority && $currentPriority < $candidatePriority) {
30320 continue;
30321 }
30322
30323
30324  
30325  if ($minPriority < $candidatePriority && $candidatePriority < $currentPriority) {
30326 $package = $candidate;
30327 continue;
30328 }
30329
30330
30331  
30332  if ($minPriority >= $candidatePriority && $minPriority < $currentPriority) {
30333 $package = $candidate;
30334 continue;
30335 }
30336
30337
30338  if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) {
30339 $package = $candidate;
30340 }
30341 }
30342
30343 return $package;
30344 }
30345
30346
30347
30348
30349
30350
30351
30352
30353
30354
30355
30356
30357
30358
30359
30360
30361 public function findRecommendedRequireVersion(PackageInterface $package)
30362 {
30363 $version = $package->getVersion();
30364 if (!$package->isDev()) {
30365 return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
30366 }
30367
30368 $loader = new ArrayLoader($this->getParser());
30369 $dumper = new ArrayDumper();
30370 $extra = $loader->getBranchAlias($dumper->dump($package));
30371 if ($extra) {
30372 $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
30373 if ($count) {
30374 $extra = str_replace('.9999999', '.0', $extra);
30375
30376 return $this->transformVersion($extra, $extra, 'dev');
30377 }
30378 }
30379
30380 return $package->getPrettyVersion();
30381 }
30382
30383 private function transformVersion($version, $prettyVersion, $stability)
30384 {
30385
30386  
30387  $semanticVersionParts = explode('.', $version);
30388
30389
30390  if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
30391
30392  if ($semanticVersionParts[0] === '0') {
30393 unset($semanticVersionParts[3]);
30394 } else {
30395 unset($semanticVersionParts[2], $semanticVersionParts[3]);
30396 }
30397 $version = implode('.', $semanticVersionParts);
30398 } else {
30399 return $prettyVersion;
30400 }
30401
30402
30403  if ($stability != 'stable') {
30404 $version .= '@'.$stability;
30405 }
30406
30407
30408  return '^' . $version;
30409 }
30410
30411 private function getParser()
30412 {
30413 if ($this->parser === null) {
30414 $this->parser = new VersionParser();
30415 }
30416
30417 return $this->parser;
30418 }
30419 }
30420 <?php
30421
30422
30423
30424
30425
30426
30427
30428
30429
30430
30431
30432 namespace Composer\Plugin\Capability;
30433
30434
30435
30436
30437
30438
30439
30440 interface Capability
30441 {
30442 }
30443 <?php
30444
30445
30446
30447
30448
30449
30450
30451
30452
30453
30454
30455 namespace Composer\Plugin\Capability;
30456
30457
30458
30459
30460
30461
30462
30463
30464
30465
30466
30467 interface CommandProvider extends Capability
30468 {
30469
30470
30471
30472
30473
30474 public function getCommands();
30475 }
30476 <?php
30477
30478
30479
30480
30481
30482
30483
30484
30485
30486
30487
30488 namespace Composer\Plugin;
30489
30490
30491
30492
30493
30494
30495
30496
30497 interface Capable
30498 {
30499
30500
30501
30502
30503
30504
30505
30506
30507
30508
30509
30510
30511
30512
30513
30514
30515
30516
30517 public function getCapabilities();
30518 }
30519 <?php
30520
30521
30522
30523
30524
30525
30526
30527
30528
30529
30530
30531 namespace Composer\Plugin;
30532
30533 use Composer\EventDispatcher\Event;
30534 use Symfony\Component\Console\Input\InputInterface;
30535 use Symfony\Component\Console\Output\OutputInterface;
30536
30537
30538
30539
30540
30541
30542 class CommandEvent extends Event
30543 {
30544
30545
30546
30547 private $commandName;
30548
30549
30550
30551
30552 private $input;
30553
30554
30555
30556
30557 private $output;
30558
30559
30560
30561
30562
30563
30564
30565
30566
30567
30568
30569 public function __construct($name, $commandName, $input, $output, array $args = array(), array $flags = array())
30570 {
30571 parent::__construct($name, $args, $flags);
30572 $this->commandName = $commandName;
30573 $this->input = $input;
30574 $this->output = $output;
30575 }
30576
30577
30578
30579
30580
30581
30582 public function getInput()
30583 {
30584 return $this->input;
30585 }
30586
30587
30588
30589
30590
30591
30592 public function getOutput()
30593 {
30594 return $this->output;
30595 }
30596
30597
30598
30599
30600
30601
30602 public function getCommandName()
30603 {
30604 return $this->commandName;
30605 }
30606 }
30607 <?php
30608
30609
30610
30611
30612
30613
30614
30615
30616
30617
30618
30619 namespace Composer\Plugin;
30620
30621
30622
30623
30624
30625
30626 class PluginEvents
30627 {
30628
30629
30630
30631
30632
30633
30634
30635
30636 const INIT = 'init';
30637
30638
30639
30640
30641
30642
30643
30644
30645
30646 const COMMAND = 'command';
30647
30648
30649
30650
30651
30652
30653
30654
30655
30656 const PRE_FILE_DOWNLOAD = 'pre-file-download';
30657 }
30658 <?php
30659
30660
30661
30662
30663
30664
30665
30666
30667
30668
30669
30670 namespace Composer\Plugin;
30671
30672 use Composer\Composer;
30673 use Composer\IO\IOInterface;
30674
30675
30676
30677
30678
30679
30680 interface PluginInterface
30681 {
30682
30683
30684
30685
30686
30687 const PLUGIN_API_VERSION = '1.1.0';
30688
30689
30690
30691
30692
30693
30694
30695 public function activate(Composer $composer, IOInterface $io);
30696 }
30697 <?php
30698
30699
30700
30701
30702
30703
30704
30705
30706
30707
30708
30709 namespace Composer\Plugin;
30710
30711 use Composer\Composer;
30712 use Composer\EventDispatcher\EventSubscriberInterface;
30713 use Composer\IO\IOInterface;
30714 use Composer\Package\Package;
30715 use Composer\Package\Version\VersionParser;
30716 use Composer\Repository\RepositoryInterface;
30717 use Composer\Package\AliasPackage;
30718 use Composer\Package\PackageInterface;
30719 use Composer\Package\Link;
30720 use Composer\Semver\Constraint\Constraint;
30721 use Composer\DependencyResolver\Pool;
30722 use Composer\Plugin\Capability\Capability;
30723
30724
30725
30726
30727
30728
30729
30730 class PluginManager
30731 {
30732 protected $composer;
30733 protected $io;
30734 protected $globalComposer;
30735 protected $versionParser;
30736 protected $disablePlugins = false;
30737
30738 protected $plugins = array();
30739 protected $registeredPlugins = array();
30740
30741 private static $classCounter = 0;
30742
30743
30744
30745
30746
30747
30748
30749
30750
30751 public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
30752 {
30753 $this->io = $io;
30754 $this->composer = $composer;
30755 $this->globalComposer = $globalComposer;
30756 $this->versionParser = new VersionParser();
30757 $this->disablePlugins = $disablePlugins;
30758 }
30759
30760
30761
30762
30763 public function loadInstalledPlugins()
30764 {
30765 if ($this->disablePlugins) {
30766 return;
30767 }
30768
30769 $repo = $this->composer->getRepositoryManager()->getLocalRepository();
30770 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
30771 if ($repo) {
30772 $this->loadRepository($repo);
30773 }
30774 if ($globalRepo) {
30775 $this->loadRepository($globalRepo);
30776 }
30777 }
30778
30779
30780
30781
30782
30783
30784 public function getPlugins()
30785 {
30786 return $this->plugins;
30787 }
30788
30789
30790
30791
30792
30793
30794 public function getGlobalComposer()
30795 {
30796 return $this->globalComposer;
30797 }
30798
30799
30800
30801
30802
30803
30804
30805
30806
30807
30808
30809
30810 public function registerPackage(PackageInterface $package, $failOnMissingClasses = false)
30811 {
30812 if ($this->disablePlugins) {
30813 return;
30814 }
30815
30816 if ($package->getType() === 'composer-plugin') {
30817 $requiresComposer = null;
30818 foreach ($package->getRequires() as $link) { 
30819 if ('composer-plugin-api' === $link->getTarget()) {
30820 $requiresComposer = $link->getConstraint();
30821 break;
30822 }
30823 }
30824
30825 if (!$requiresComposer) {
30826 throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
30827 }
30828
30829 $currentPluginApiVersion = $this->getPluginApiVersion();
30830 $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
30831
30832 if ($requiresComposer->getPrettyString() === '1.0.0' && $this->getPluginApiVersion() === '1.0.0') {
30833 $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>');
30834 } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) {
30835 $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>');
30836
30837 return;
30838 }
30839 }
30840
30841 $oldInstallerPlugin = ($package->getType() === 'composer-installer');
30842
30843 if (in_array($package->getName(), $this->registeredPlugins)) {
30844 return;
30845 }
30846
30847 $extra = $package->getExtra();
30848 if (empty($extra['class'])) {
30849 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
30850 }
30851 $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
30852
30853 $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
30854 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
30855
30856 $pool = new Pool('dev');
30857 $pool->addRepository($localRepo);
30858 if ($globalRepo) {
30859 $pool->addRepository($globalRepo);
30860 }
30861
30862 $autoloadPackages = array($package->getName() => $package);
30863 $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package);
30864
30865 $generator = $this->composer->getAutoloadGenerator();
30866 $autoloads = array();
30867 foreach ($autoloadPackages as $autoloadPackage) {
30868 $downloadPath = $this->getInstallPath($autoloadPackage, ($globalRepo && $globalRepo->hasPackage($autoloadPackage)));
30869 $autoloads[] = array($autoloadPackage, $downloadPath);
30870 }
30871
30872 $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0'));
30873 $classLoader = $generator->createLoader($map);
30874 $classLoader->register();
30875
30876 foreach ($classes as $class) {
30877 if (class_exists($class, false)) {
30878 $class = trim($class, '\\');
30879 $path = $classLoader->findFile($class);
30880 $code = file_get_contents($path);
30881 $separatorPos = strrpos($class, '\\');
30882 $className = $class;
30883 if ($separatorPos) {
30884 $className = substr($class, $separatorPos + 1);
30885 }
30886 $code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
30887 $code = str_replace('__FILE__', var_export($path, true), $code);
30888 $code = str_replace('__DIR__', var_export(dirname($path), true), $code);
30889 $code = str_replace('__CLASS__', var_export($class, true), $code);
30890 $code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
30891 eval($code);
30892 $class .= '_composer_tmp'.self::$classCounter;
30893 self::$classCounter++;
30894 }
30895
30896 if ($oldInstallerPlugin) {
30897 $installer = new $class($this->io, $this->composer);
30898 $this->composer->getInstallationManager()->addInstaller($installer);
30899 } elseif (class_exists($class)) {
30900 $plugin = new $class();
30901 $this->addPlugin($plugin);
30902 $this->registeredPlugins[] = $package->getName();
30903 } elseif ($failOnMissingClasses) {
30904 throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
30905 }
30906 }
30907 }
30908
30909
30910
30911
30912
30913
30914 protected function getPluginApiVersion()
30915 {
30916 return PluginInterface::PLUGIN_API_VERSION;
30917 }
30918
30919
30920
30921
30922
30923
30924
30925
30926
30927
30928 public function addPlugin(PluginInterface $plugin)
30929 {
30930 $this->io->writeError('Loading plugin '.get_class($plugin), true, IOInterface::DEBUG);
30931 $this->plugins[] = $plugin;
30932 $plugin->activate($this->composer, $this->io);
30933
30934 if ($plugin instanceof EventSubscriberInterface) {
30935 $this->composer->getEventDispatcher()->addSubscriber($plugin);
30936 }
30937 }
30938
30939
30940
30941
30942
30943
30944
30945
30946
30947
30948
30949
30950 private function loadRepository(RepositoryInterface $repo)
30951 {
30952 foreach ($repo->getPackages() as $package) { 
30953 if ($package instanceof AliasPackage) {
30954 continue;
30955 }
30956 if ('composer-plugin' === $package->getType()) {
30957 $this->registerPackage($package);
30958
30959  } elseif ('composer-installer' === $package->getType()) {
30960 $this->registerPackage($package);
30961 }
30962 }
30963 }
30964
30965
30966
30967
30968
30969
30970
30971
30972
30973
30974 private function collectDependencies(Pool $pool, array $collected, PackageInterface $package)
30975 {
30976 $requires = array_merge(
30977 $package->getRequires(),
30978 $package->getDevRequires()
30979 );
30980
30981 foreach ($requires as $requireLink) {
30982 $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink);
30983 if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) {
30984 $collected[$requiredPackage->getName()] = $requiredPackage;
30985 $collected = $this->collectDependencies($pool, $collected, $requiredPackage);
30986 }
30987 }
30988
30989 return $collected;
30990 }
30991
30992
30993
30994
30995
30996
30997
30998
30999
31000
31001
31002 private function lookupInstalledPackage(Pool $pool, Link $link)
31003 {
31004 $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint());
31005
31006 return (!empty($packages)) ? $packages[0] : null;
31007 }
31008
31009
31010
31011
31012
31013
31014
31015
31016
31017 private function getInstallPath(PackageInterface $package, $global = false)
31018 {
31019 if (!$global) {
31020 return $this->composer->getInstallationManager()->getInstallPath($package);
31021 }
31022
31023 return $this->globalComposer->getInstallationManager()->getInstallPath($package);
31024 }
31025
31026
31027
31028
31029
31030
31031
31032 protected function getCapabilityImplementationClassName(PluginInterface $plugin, $capability)
31033 {
31034 if (!($plugin instanceof Capable)) {
31035 return null;
31036 }
31037
31038 $capabilities = (array) $plugin->getCapabilities();
31039
31040 if (!empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability])) {
31041 return trim($capabilities[$capability]);
31042 }
31043
31044 if (
31045 array_key_exists($capability, $capabilities)
31046 && (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))
31047 ) {
31048 throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], 1));
31049 }
31050 }
31051
31052
31053
31054
31055
31056
31057
31058
31059
31060 public function getPluginCapability(PluginInterface $plugin, $capabilityClassName, array $ctorArgs = array())
31061 {
31062 if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) {
31063 if (!class_exists($capabilityClass)) {
31064 throw new \RuntimeException("Cannot instantiate Capability, as class $capabilityClass from plugin ".get_class($plugin)." does not exist.");
31065 }
31066
31067 $ctorArgs['plugin'] = $plugin;
31068 $capabilityObj = new $capabilityClass($ctorArgs);
31069
31070
31071  if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) {
31072 throw new \RuntimeException(
31073 'Class ' . $capabilityClass . ' must implement both Composer\Plugin\Capability\Capability and '. $capabilityClassName . '.'
31074 );
31075 }
31076
31077 return $capabilityObj;
31078 }
31079 }
31080
31081
31082
31083
31084
31085
31086
31087
31088 public function getPluginCapabilities($capabilityClassName, array $ctorArgs = array())
31089 {
31090 $capabilities = array();
31091 foreach ($this->getPlugins() as $plugin) {
31092 if ($capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs)) {
31093 $capabilities[] = $capability;
31094 }
31095 }
31096
31097 return $capabilities;
31098 }
31099 }
31100 <?php
31101
31102
31103
31104
31105
31106
31107
31108
31109
31110
31111
31112 namespace Composer\Plugin;
31113
31114 use Composer\EventDispatcher\Event;
31115 use Composer\Util\RemoteFilesystem;
31116
31117
31118
31119
31120
31121
31122 class PreFileDownloadEvent extends Event
31123 {
31124
31125
31126
31127 private $rfs;
31128
31129
31130
31131
31132 private $processedUrl;
31133
31134
31135
31136
31137
31138
31139
31140
31141 public function __construct($name, RemoteFilesystem $rfs, $processedUrl)
31142 {
31143 parent::__construct($name);
31144 $this->rfs = $rfs;
31145 $this->processedUrl = $processedUrl;
31146 }
31147
31148
31149
31150
31151
31152
31153 public function getRemoteFilesystem()
31154 {
31155 return $this->rfs;
31156 }
31157
31158
31159
31160
31161
31162
31163 public function setRemoteFilesystem(RemoteFilesystem $rfs)
31164 {
31165 $this->rfs = $rfs;
31166 }
31167
31168
31169
31170
31171
31172
31173 public function getProcessedUrl()
31174 {
31175 return $this->processedUrl;
31176 }
31177 }
31178 <?php
31179
31180
31181
31182
31183
31184
31185
31186
31187
31188
31189
31190 namespace Composer\Question;
31191
31192 use Symfony\Component\Console\Exception\InvalidArgumentException;
31193 use Symfony\Component\Console\Question\Question;
31194
31195
31196
31197
31198
31199
31200
31201
31202 class StrictConfirmationQuestion extends Question
31203 {
31204 private $trueAnswerRegex;
31205 private $falseAnswerRegex;
31206
31207
31208
31209
31210
31211
31212
31213
31214
31215 public function __construct($question, $default = true, $trueAnswerRegex = '/^y(?:es)?$/i', $falseAnswerRegex = '/^no?$/i')
31216 {
31217 parent::__construct($question, (bool) $default);
31218
31219 $this->trueAnswerRegex = $trueAnswerRegex;
31220 $this->falseAnswerRegex = $falseAnswerRegex;
31221 $this->setNormalizer($this->getDefaultNormalizer());
31222 $this->setValidator($this->getDefaultValidator());
31223 }
31224
31225
31226
31227
31228
31229
31230 private function getDefaultNormalizer()
31231 {
31232 $default = $this->getDefault();
31233 $trueRegex = $this->trueAnswerRegex;
31234 $falseRegex = $this->falseAnswerRegex;
31235
31236 return function ($answer) use ($default, $trueRegex, $falseRegex) {
31237 if (is_bool($answer)) {
31238 return $answer;
31239 }
31240 if (empty($answer) && !empty($default)) {
31241 return $default;
31242 }
31243
31244 if (preg_match($trueRegex, $answer)) {
31245 return true;
31246 }
31247
31248 if (preg_match($falseRegex, $answer)) {
31249 return false;
31250 }
31251
31252 return null;
31253 };
31254 }
31255
31256
31257
31258
31259
31260
31261 private function getDefaultValidator()
31262 {
31263 return function ($answer) {
31264 if (!is_bool($answer)) {
31265 throw new InvalidArgumentException('Please answer yes, y, no, or n.');
31266 }
31267
31268 return $answer;
31269 };
31270 }
31271 }
31272 <?php
31273
31274
31275
31276
31277
31278
31279
31280
31281
31282
31283
31284 namespace Composer\Repository;
31285
31286 use Composer\Package\AliasPackage;
31287 use Composer\Package\PackageInterface;
31288 use Composer\Package\CompletePackageInterface;
31289 use Composer\Package\Version\VersionParser;
31290 use Composer\Semver\Constraint\ConstraintInterface;
31291 use Composer\Semver\Constraint\Constraint;
31292
31293
31294
31295
31296
31297
31298 class ArrayRepository extends BaseRepository
31299 {
31300
31301 protected $packages;
31302
31303 public function __construct(array $packages = array())
31304 {
31305 foreach ($packages as $package) {
31306 $this->addPackage($package);
31307 }
31308 }
31309
31310
31311
31312
31313 public function findPackage($name, $constraint)
31314 {
31315 $name = strtolower($name);
31316
31317 if (!$constraint instanceof ConstraintInterface) {
31318 $versionParser = new VersionParser();
31319 $constraint = $versionParser->parseConstraints($constraint);
31320 }
31321
31322 foreach ($this->getPackages() as $package) {
31323 if ($name === $package->getName()) {
31324 $pkgConstraint = new Constraint('==', $package->getVersion());
31325 if ($constraint->matches($pkgConstraint)) {
31326 return $package;
31327 }
31328 }
31329 }
31330
31331 return null;
31332 }
31333
31334
31335
31336
31337 public function findPackages($name, $constraint = null)
31338 {
31339
31340  $name = strtolower($name);
31341 $packages = array();
31342
31343 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
31344 $versionParser = new VersionParser();
31345 $constraint = $versionParser->parseConstraints($constraint);
31346 }
31347
31348 foreach ($this->getPackages() as $package) {
31349 if ($name === $package->getName()) {
31350 $pkgConstraint = new Constraint('==', $package->getVersion());
31351 if (null === $constraint || $constraint->matches($pkgConstraint)) {
31352 $packages[] = $package;
31353 }
31354 }
31355 }
31356
31357 return $packages;
31358 }
31359
31360
31361
31362
31363 public function search($query, $mode = 0, $type = null)
31364 {
31365 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
31366
31367 $matches = array();
31368 foreach ($this->getPackages() as $package) {
31369 $name = $package->getName();
31370 if (isset($matches[$name])) {
31371 continue;
31372 }
31373 if (preg_match($regex, $name)
31374 || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
31375 ) {
31376 if (null !== $type && $package->getType() !== $type) {
31377 continue;
31378 }
31379
31380 $matches[$name] = array(
31381 'name' => $package->getPrettyName(),
31382 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null,
31383 );
31384 }
31385 }
31386
31387 return array_values($matches);
31388 }
31389
31390
31391
31392
31393 public function hasPackage(PackageInterface $package)
31394 {
31395 $packageId = $package->getUniqueName();
31396
31397 foreach ($this->getPackages() as $repoPackage) {
31398 if ($packageId === $repoPackage->getUniqueName()) {
31399 return true;
31400 }
31401 }
31402
31403 return false;
31404 }
31405
31406
31407
31408
31409
31410
31411 public function addPackage(PackageInterface $package)
31412 {
31413 if (null === $this->packages) {
31414 $this->initialize();
31415 }
31416 $package->setRepository($this);
31417 $this->packages[] = $package;
31418
31419 if ($package instanceof AliasPackage) {
31420 $aliasedPackage = $package->getAliasOf();
31421 if (null === $aliasedPackage->getRepository()) {
31422 $this->addPackage($aliasedPackage);
31423 }
31424 }
31425 }
31426
31427 protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
31428 {
31429 return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
31430 }
31431
31432
31433
31434
31435
31436
31437 public function removePackage(PackageInterface $package)
31438 {
31439 $packageId = $package->getUniqueName();
31440
31441 foreach ($this->getPackages() as $key => $repoPackage) {
31442 if ($packageId === $repoPackage->getUniqueName()) {
31443 array_splice($this->packages, $key, 1);
31444
31445 return;
31446 }
31447 }
31448 }
31449
31450
31451
31452
31453 public function getPackages()
31454 {
31455 if (null === $this->packages) {
31456 $this->initialize();
31457 }
31458
31459 return $this->packages;
31460 }
31461
31462
31463
31464
31465
31466
31467 public function count()
31468 {
31469 return count($this->packages);
31470 }
31471
31472
31473
31474
31475 protected function initialize()
31476 {
31477 $this->packages = array();
31478 }
31479 }
31480 <?php
31481
31482
31483
31484
31485
31486
31487
31488
31489
31490
31491
31492 namespace Composer\Repository;
31493
31494 use Composer\IO\IOInterface;
31495 use Composer\Json\JsonFile;
31496 use Composer\Package\Loader\ArrayLoader;
31497 use Composer\Package\Loader\LoaderInterface;
31498
31499
31500
31501
31502 class ArtifactRepository extends ArrayRepository implements ConfigurableRepositoryInterface
31503 {
31504
31505 protected $loader;
31506
31507 protected $lookup;
31508 protected $repoConfig;
31509 private $io;
31510
31511 public function __construct(array $repoConfig, IOInterface $io)
31512 {
31513 parent::__construct();
31514 if (!extension_loaded('zip')) {
31515 throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
31516 }
31517
31518 $this->loader = new ArrayLoader();
31519 $this->lookup = $repoConfig['url'];
31520 $this->io = $io;
31521 $this->repoConfig = $repoConfig;
31522 }
31523
31524 public function getRepoConfig()
31525 {
31526 return $this->repoConfig;
31527 }
31528
31529 protected function initialize()
31530 {
31531 parent::initialize();
31532
31533 $this->scanDirectory($this->lookup);
31534 }
31535
31536 private function scanDirectory($path)
31537 {
31538 $io = $this->io;
31539
31540 $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
31541 $iterator = new \RecursiveIteratorIterator($directory);
31542 $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i');
31543 foreach ($regex as $file) {
31544
31545 if (!$file->isFile()) {
31546 continue;
31547 }
31548
31549 $package = $this->getComposerInformation($file);
31550 if (!$package) {
31551 $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", true, IOInterface::VERBOSE);
31552 continue;
31553 }
31554
31555 $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
31556 $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), true, IOInterface::VERBOSE);
31557
31558 $this->addPackage($package);
31559 }
31560 }
31561
31562
31563
31564
31565
31566
31567
31568
31569 private function locateFile(\ZipArchive $zip, $filename)
31570 {
31571 $indexOfShortestMatch = false;
31572 $lengthOfShortestMatch = -1;
31573
31574 for ($i = 0; $i < $zip->numFiles; $i++) {
31575 $stat = $zip->statIndex($i);
31576 if (strcmp(basename($stat['name']), $filename) === 0) {
31577 $directoryName = dirname($stat['name']);
31578 if ($directoryName == '.') {
31579
31580  
31581  return $i;
31582 }
31583
31584 if (strpos($directoryName, '\\') !== false ||
31585 strpos($directoryName, '/') !== false) {
31586
31587  continue;
31588 }
31589
31590 $length = strlen($stat['name']);
31591 if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) {
31592
31593  $contents = $zip->getFromIndex($i);
31594 if ($contents !== false) {
31595 $indexOfShortestMatch = $i;
31596 $lengthOfShortestMatch = $length;
31597 }
31598 }
31599 }
31600 }
31601
31602 return $indexOfShortestMatch;
31603 }
31604
31605 private function getComposerInformation(\SplFileInfo $file)
31606 {
31607 $zip = new \ZipArchive();
31608 $zip->open($file->getPathname());
31609
31610 if (0 == $zip->numFiles) {
31611 return false;
31612 }
31613
31614 $foundFileIndex = $this->locateFile($zip, 'composer.json');
31615 if (false === $foundFileIndex) {
31616 return false;
31617 }
31618
31619 $configurationFileName = $zip->getNameIndex($foundFileIndex);
31620
31621 $composerFile = "zip://{$file->getPathname()}#$configurationFileName";
31622 $json = file_get_contents($composerFile);
31623
31624 $package = JsonFile::parseJson($json, $composerFile);
31625 $package['dist'] = array(
31626 'type' => 'zip',
31627 'url' => strtr($file->getPathname(), '\\', '/'),
31628 'shasum' => sha1_file($file->getRealPath()),
31629 );
31630
31631 try {
31632 $package = $this->loader->load($package);
31633 } catch (\UnexpectedValueException $e) {
31634 throw new \UnexpectedValueException('Failed loading package in '.$file.': '.$e->getMessage(), 0, $e);
31635 }
31636
31637 return $package;
31638 }
31639 }
31640 <?php
31641
31642
31643
31644
31645
31646
31647
31648
31649
31650
31651
31652 namespace Composer\Repository;
31653
31654 use Composer\Package\RootPackageInterface;
31655 use Composer\Semver\Constraint\ConstraintInterface;
31656 use Composer\Semver\Constraint\Constraint;
31657 use Composer\Package\Link;
31658
31659
31660
31661
31662
31663
31664 abstract class BaseRepository implements RepositoryInterface
31665 {
31666
31667
31668
31669
31670
31671
31672
31673
31674
31675
31676
31677
31678
31679 public function getDependents($needle, $constraint = null, $invert = false, $recurse = true, $packagesFound = null)
31680 {
31681 $needles = (array) $needle;
31682 $results = array();
31683
31684
31685  if (null === $packagesFound) {
31686 $packagesFound = $needles;
31687 }
31688
31689
31690  $rootPackage = null;
31691 foreach ($this->getPackages() as $package) {
31692 if ($package instanceof RootPackageInterface) {
31693 $rootPackage = $package;
31694 break;
31695 }
31696 }
31697
31698
31699  foreach ($this->getPackages() as $package) {
31700 $links = $package->getRequires();
31701
31702
31703  
31704  $packagesInTree = $packagesFound;
31705
31706
31707  if (!$invert) {
31708 $links += $package->getReplaces();
31709 }
31710
31711
31712  if ($package instanceof RootPackageInterface) {
31713 $links += $package->getDevRequires();
31714 }
31715
31716
31717  foreach ($links as $link) {
31718 foreach ($needles as $needle) {
31719 if ($link->getTarget() === $needle) {
31720 if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
31721
31722  if (in_array($link->getSource(), $packagesInTree)) {
31723 $results[$link->getSource()] = array($package, $link, false);
31724 continue;
31725 }
31726 $packagesInTree[] = $link->getSource();
31727 $dependents = $recurse ? $this->getDependents($link->getSource(), null, false, true, $packagesInTree) : array();
31728 $results[$link->getSource()] = array($package, $link, $dependents);
31729 }
31730 }
31731 }
31732 }
31733
31734
31735  if ($invert && in_array($package->getName(), $needles)) {
31736 foreach ($package->getConflicts() as $link) {
31737 foreach ($this->findPackages($link->getTarget()) as $pkg) {
31738 $version = new Constraint('=', $pkg->getVersion());
31739 if ($link->getConstraint()->matches($version) === $invert) {
31740 $results[] = array($package, $link, false);
31741 }
31742 }
31743 }
31744 }
31745
31746
31747  if ($invert && $constraint && in_array($package->getName(), $needles) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
31748 foreach ($package->getRequires() as $link) {
31749 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
31750 if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
31751 continue;
31752 }
31753
31754 $platformPkg = $this->findPackage($link->getTarget(), '*');
31755 $description = $platformPkg ? 'but '.$platformPkg->getPrettyVersion().' is installed' : 'but it is missing';
31756 $results[] = array($package, new Link($package->getName(), $link->getTarget(), null, 'requires', $link->getPrettyConstraint().' '.$description), false);
31757
31758 continue;
31759 }
31760
31761 foreach ($this->getPackages() as $pkg) {
31762 if (!in_array($link->getTarget(), $pkg->getNames())) {
31763 continue;
31764 }
31765
31766 $version = new Constraint('=', $pkg->getVersion());
31767 if (!$link->getConstraint()->matches($version)) {
31768
31769  
31770  if ($rootPackage) {
31771 foreach (array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) {
31772 if (in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) {
31773 $results[] = array($package, $link, false);
31774 $results[] = array($rootPackage, $rootReq, false);
31775 continue 3;
31776 }
31777 }
31778 $results[] = array($package, $link, false);
31779 $results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), null, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
31780 } else {
31781
31782  $results[] = array($package, $link, false);
31783 }
31784 }
31785
31786 continue 2;
31787 }
31788 }
31789 }
31790 }
31791
31792 ksort($results);
31793
31794 return $results;
31795 }
31796 }
31797 <?php
31798
31799
31800
31801
31802
31803
31804
31805
31806
31807
31808
31809 namespace Composer\Repository;
31810
31811 use Composer\Package\Loader\ArrayLoader;
31812 use Composer\Package\PackageInterface;
31813 use Composer\Package\AliasPackage;
31814 use Composer\Package\Version\VersionParser;
31815 use Composer\DependencyResolver\Pool;
31816 use Composer\Json\JsonFile;
31817 use Composer\Cache;
31818 use Composer\Config;
31819 use Composer\Factory;
31820 use Composer\IO\IOInterface;
31821 use Composer\Util\RemoteFilesystem;
31822 use Composer\Plugin\PluginEvents;
31823 use Composer\Plugin\PreFileDownloadEvent;
31824 use Composer\EventDispatcher\EventDispatcher;
31825 use Composer\Downloader\TransportException;
31826 use Composer\Semver\Constraint\ConstraintInterface;
31827 use Composer\Semver\Constraint\Constraint;
31828
31829
31830
31831
31832 class ComposerRepository extends ArrayRepository implements ConfigurableRepositoryInterface
31833 {
31834 protected $config;
31835 protected $repoConfig;
31836 protected $options;
31837 protected $url;
31838 protected $baseUrl;
31839 protected $io;
31840 protected $rfs;
31841 protected $cache;
31842 protected $notifyUrl;
31843 protected $searchUrl;
31844 protected $hasProviders = false;
31845 protected $providersUrl;
31846 protected $lazyProvidersUrl;
31847 protected $providerListing;
31848 protected $providers = array();
31849 protected $providersByUid = array();
31850 protected $loader;
31851 protected $rootAliases;
31852 protected $allowSslDowngrade = false;
31853 protected $eventDispatcher;
31854 protected $sourceMirrors;
31855 protected $distMirrors;
31856 private $degradedMode = false;
31857 private $rootData;
31858 private $hasPartialPackages;
31859 private $partialPackagesByName;
31860
31861 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
31862 {
31863 parent::__construct();
31864 if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) {
31865
31866  $repoConfig['url'] = 'http://'.$repoConfig['url'];
31867 }
31868 $repoConfig['url'] = rtrim($repoConfig['url'], '/');
31869
31870 if ('https?' === substr($repoConfig['url'], 0, 6)) {
31871 $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
31872 }
31873
31874 $urlBits = parse_url($repoConfig['url']);
31875 if ($urlBits === false || empty($urlBits['scheme'])) {
31876 throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
31877 }
31878
31879 if (!isset($repoConfig['options'])) {
31880 $repoConfig['options'] = array();
31881 }
31882 if (isset($repoConfig['allow_ssl_downgrade']) && true === $repoConfig['allow_ssl_downgrade']) {
31883 $this->allowSslDowngrade = true;
31884 }
31885
31886 $this->config = $config;
31887 $this->options = $repoConfig['options'];
31888 $this->url = $repoConfig['url'];
31889 $this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
31890 $this->io = $io;
31891 $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
31892 $this->loader = new ArrayLoader();
31893 if ($rfs && $this->options) {
31894 $rfs = clone $rfs;
31895 $rfs->setOptions($this->options);
31896 }
31897 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $this->config, $this->options);
31898 $this->eventDispatcher = $eventDispatcher;
31899 $this->repoConfig = $repoConfig;
31900 }
31901
31902 public function getRepoConfig()
31903 {
31904 return $this->repoConfig;
31905 }
31906
31907 public function setRootAliases(array $rootAliases)
31908 {
31909 $this->rootAliases = $rootAliases;
31910 }
31911
31912
31913
31914
31915 public function findPackage($name, $constraint)
31916 {
31917 if (!$this->hasProviders()) {
31918 return parent::findPackage($name, $constraint);
31919 }
31920
31921 $name = strtolower($name);
31922 if (!$constraint instanceof ConstraintInterface) {
31923 $versionParser = new VersionParser();
31924 $constraint = $versionParser->parseConstraints($constraint);
31925 }
31926
31927 foreach ($this->getProviderNames() as $providerName) {
31928 if ($name === $providerName) {
31929 $packages = $this->whatProvides(new Pool('dev'), $providerName);
31930 foreach ($packages as $package) {
31931 if ($name === $package->getName()) {
31932 $pkgConstraint = new Constraint('==', $package->getVersion());
31933 if ($constraint->matches($pkgConstraint)) {
31934 return $package;
31935 }
31936 }
31937 }
31938 break;
31939 }
31940 }
31941 }
31942
31943
31944
31945
31946 public function findPackages($name, $constraint = null)
31947 {
31948 if (!$this->hasProviders()) {
31949 return parent::findPackages($name, $constraint);
31950 }
31951
31952  $name = strtolower($name);
31953
31954 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
31955 $versionParser = new VersionParser();
31956 $constraint = $versionParser->parseConstraints($constraint);
31957 }
31958
31959 $packages = array();
31960
31961 foreach ($this->getProviderNames() as $providerName) {
31962 if ($name === $providerName) {
31963 $candidates = $this->whatProvides(new Pool('dev'), $providerName);
31964 foreach ($candidates as $package) {
31965 if ($name === $package->getName()) {
31966 $pkgConstraint = new Constraint('==', $package->getVersion());
31967 if (null === $constraint || $constraint->matches($pkgConstraint)) {
31968 $packages[] = $package;
31969 }
31970 }
31971 }
31972 break;
31973 }
31974 }
31975
31976 return $packages;
31977 }
31978
31979 public function getPackages()
31980 {
31981 if ($this->hasProviders()) {
31982 throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.');
31983 }
31984
31985 return parent::getPackages();
31986 }
31987
31988
31989
31990
31991 public function search($query, $mode = 0, $type = null)
31992 {
31993 $this->loadRootServerFile();
31994
31995 if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
31996 $url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl);
31997
31998 $hostname = parse_url($url, PHP_URL_HOST) ?: $url;
31999 $json = $this->rfs->getContents($hostname, $url, false);
32000 $results = JsonFile::parseJson($json, $url);
32001
32002 return $results['results'];
32003 }
32004
32005 if ($this->hasProviders()) {
32006 $results = array();
32007 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
32008
32009 foreach ($this->getProviderNames() as $name) {
32010 if (preg_match($regex, $name)) {
32011 $results[] = array('name' => $name);
32012 }
32013 }
32014
32015 return $results;
32016 }
32017
32018 return parent::search($query, $mode);
32019 }
32020
32021 public function getProviderNames()
32022 {
32023 $this->loadRootServerFile();
32024
32025 if (null === $this->providerListing) {
32026 $this->loadProviderListings($this->loadRootServerFile());
32027 }
32028
32029 if ($this->lazyProvidersUrl) {
32030
32031  return array();
32032 }
32033
32034 if ($this->providersUrl) {
32035 return array_keys($this->providerListing);
32036 }
32037
32038 return array();
32039 }
32040
32041 protected function configurePackageTransportOptions(PackageInterface $package)
32042 {
32043 foreach ($package->getDistUrls() as $url) {
32044 if (strpos($url, $this->baseUrl) === 0) {
32045 $package->setTransportOptions($this->options);
32046
32047 return;
32048 }
32049 }
32050 }
32051
32052 public function hasProviders()
32053 {
32054 $this->loadRootServerFile();
32055
32056 return $this->hasProviders;
32057 }
32058
32059 public function resetPackageIds()
32060 {
32061 foreach ($this->providersByUid as $package) {
32062 if ($package instanceof AliasPackage) {
32063 $package->getAliasOf()->setId(-1);
32064 }
32065 $package->setId(-1);
32066 }
32067 }
32068
32069
32070
32071
32072
32073
32074
32075 public function whatProvides(Pool $pool, $name, $bypassFilters = false)
32076 {
32077 if (isset($this->providers[$name]) && !$bypassFilters) {
32078 return $this->providers[$name];
32079 }
32080
32081 if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
32082 $this->initializePartialPackages();
32083 }
32084
32085 if (!$this->hasPartialPackages || !isset($this->partialPackagesByName[$name])) {
32086
32087  if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) {
32088 return array();
32089 }
32090
32091 if (null === $this->providerListing) {
32092 $this->loadProviderListings($this->loadRootServerFile());
32093 }
32094
32095 $useLastModifiedCheck = false;
32096 if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
32097 $hash = null;
32098 $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
32099 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
32100 $useLastModifiedCheck = true;
32101 } elseif ($this->providersUrl) {
32102
32103  if (!isset($this->providerListing[$name])) {
32104 return array();
32105 }
32106
32107 $hash = $this->providerListing[$name]['sha256'];
32108 $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
32109 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
32110 } else {
32111 return array();
32112 }
32113
32114 $packages = null;
32115 if ($cacheKey) {
32116 if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) {
32117 $packages = json_decode($this->cache->read($cacheKey), true);
32118 } elseif ($useLastModifiedCheck) {
32119 if ($contents = $this->cache->read($cacheKey)) {
32120 $contents = json_decode($contents, true);
32121 if (isset($contents['last-modified'])) {
32122 $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']);
32123 if (true === $response) {
32124 $packages = $contents;
32125 } elseif ($response) {
32126 $packages = $response;
32127 }
32128 }
32129 }
32130 }
32131 }
32132
32133 if (!$packages) {
32134 try {
32135 $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck);
32136 } catch (TransportException $e) {
32137
32138  if ($e->getStatusCode() === 404 && $this->lazyProvidersUrl) {
32139 $packages = array('packages' => array());
32140 } else {
32141 throw $e;
32142 }
32143 }
32144 }
32145
32146 $loadingPartialPackage = false;
32147 } else {
32148 $packages = array('packages' => array('versions' => $this->partialPackagesByName[$name]));
32149 $loadingPartialPackage = true;
32150 }
32151
32152 $this->providers[$name] = array();
32153 foreach ($packages['packages'] as $versions) {
32154 foreach ($versions as $version) {
32155 if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
32156 continue;
32157 }
32158
32159
32160  if (isset($this->providersByUid[$version['uid']])) {
32161
32162  if (!isset($this->providers[$name][$version['uid']])) {
32163
32164  if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
32165 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
32166 $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
32167 } else {
32168 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
32169 }
32170
32171  if (isset($this->providersByUid[$version['uid'].'-root'])) {
32172 $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
32173 }
32174 }
32175 } else {
32176 if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
32177 continue;
32178 }
32179
32180
32181  $package = $this->createPackage($version, 'Composer\Package\CompletePackage');
32182 $package->setRepository($this);
32183
32184 if ($package instanceof AliasPackage) {
32185 $aliased = $package->getAliasOf();
32186 $aliased->setRepository($this);
32187
32188 $this->providers[$name][$version['uid']] = $aliased;
32189 $this->providers[$name][$version['uid'].'-alias'] = $package;
32190
32191
32192  $this->providersByUid[$version['uid']] = $package;
32193 } else {
32194 $this->providers[$name][$version['uid']] = $package;
32195 $this->providersByUid[$version['uid']] = $package;
32196 }
32197
32198
32199  unset($rootAliasData);
32200
32201 if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
32202 $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
32203 } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
32204 $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
32205 }
32206
32207 if (isset($rootAliasData)) {
32208 $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
32209 $alias->setRepository($this);
32210
32211 $this->providers[$name][$version['uid'].'-root'] = $alias;
32212 $this->providersByUid[$version['uid'].'-root'] = $alias;
32213 }
32214 }
32215 }
32216 }
32217
32218 $result = $this->providers[$name];
32219
32220
32221  
32222  if ($bypassFilters) {
32223 foreach ($this->providers[$name] as $uid => $provider) {
32224 unset($this->providersByUid[$uid]);
32225 }
32226 unset($this->providers[$name]);
32227 }
32228
32229 return $result;
32230 }
32231
32232
32233
32234
32235 protected function initialize()
32236 {
32237 parent::initialize();
32238
32239 $repoData = $this->loadDataFromServer();
32240
32241 foreach ($repoData as $package) {
32242 $this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
32243 }
32244 }
32245
32246
32247
32248
32249
32250
32251 public function addPackage(PackageInterface $package)
32252 {
32253 parent::addPackage($package);
32254 $this->configurePackageTransportOptions($package);
32255 }
32256
32257 protected function loadRootServerFile()
32258 {
32259 if (null !== $this->rootData) {
32260 return $this->rootData;
32261 }
32262
32263 if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
32264 throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
32265 }
32266
32267 $jsonUrlParts = parse_url($this->url);
32268
32269 if (isset($jsonUrlParts['path']) && false !== strpos($jsonUrlParts['path'], '.json')) {
32270 $jsonUrl = $this->url;
32271 } else {
32272 $jsonUrl = $this->url . '/packages.json';
32273 }
32274
32275 $data = $this->fetchFile($jsonUrl, 'packages.json');
32276
32277 if (!empty($data['notify-batch'])) {
32278 $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
32279 } elseif (!empty($data['notify'])) {
32280 $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
32281 }
32282
32283 if (!empty($data['search'])) {
32284 $this->searchUrl = $this->canonicalizeUrl($data['search']);
32285 }
32286
32287 if (!empty($data['mirrors'])) {
32288 foreach ($data['mirrors'] as $mirror) {
32289 if (!empty($mirror['git-url'])) {
32290 $this->sourceMirrors['git'][] = array('url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred']));
32291 }
32292 if (!empty($mirror['hg-url'])) {
32293 $this->sourceMirrors['hg'][] = array('url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred']));
32294 }
32295 if (!empty($mirror['dist-url'])) {
32296 $this->distMirrors[] = array(
32297 'url' => $this->canonicalizeUrl($mirror['dist-url']),
32298 'preferred' => !empty($mirror['preferred']),
32299 );
32300 }
32301 }
32302 }
32303
32304 if (!empty($data['providers-lazy-url'])) {
32305 $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
32306 $this->hasProviders = true;
32307
32308 $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
32309 }
32310
32311 if ($this->allowSslDowngrade) {
32312 $this->url = str_replace('https://', 'http://', $this->url);
32313 $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
32314 }
32315
32316 if (!empty($data['providers-url'])) {
32317 $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
32318 $this->hasProviders = true;
32319 }
32320
32321 if (!empty($data['providers']) || !empty($data['providers-includes'])) {
32322 $this->hasProviders = true;
32323 }
32324
32325
32326  if (preg_match('{^https?://packagist.org/?$}i', $this->url) && !empty($this->repoConfig['force-lazy-providers'])) {
32327 $this->url = 'https://packagist.org';
32328 $this->baseUrl = 'https://packagist.org';
32329 $this->lazyProvidersUrl = $this->canonicalizeUrl('https://packagist.org/p/%package%.json');
32330 $this->providersUrl = null;
32331 } elseif (!empty($this->repoConfig['force-lazy-providers'])) {
32332 $this->lazyProvidersUrl = $this->canonicalizeUrl('/p/%package%.json');
32333 $this->providersUrl = null;
32334 }
32335
32336 return $this->rootData = $data;
32337 }
32338
32339 protected function canonicalizeUrl($url)
32340 {
32341 if ('/' === $url[0]) {
32342 return preg_replace('{(https?://[^/]+).*}i', '$1' . $url, $this->url);
32343 }
32344
32345 return $url;
32346 }
32347
32348 protected function loadDataFromServer()
32349 {
32350 $data = $this->loadRootServerFile();
32351
32352 return $this->loadIncludes($data);
32353 }
32354
32355 protected function loadProviderListings($data)
32356 {
32357 if (isset($data['providers'])) {
32358 if (!is_array($this->providerListing)) {
32359 $this->providerListing = array();
32360 }
32361 $this->providerListing = array_merge($this->providerListing, $data['providers']);
32362 }
32363
32364 if ($this->providersUrl && isset($data['provider-includes'])) {
32365 $includes = $data['provider-includes'];
32366 foreach ($includes as $include => $metadata) {
32367 $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
32368 $cacheKey = str_replace(array('%hash%','$'), '', $include);
32369 if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
32370 $includedData = json_decode($this->cache->read($cacheKey), true);
32371 } else {
32372 $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
32373 }
32374
32375 $this->loadProviderListings($includedData);
32376 }
32377 }
32378 }
32379
32380 protected function loadIncludes($data)
32381 {
32382 $packages = array();
32383
32384
32385  if (!isset($data['packages']) && !isset($data['includes'])) {
32386 foreach ($data as $pkg) {
32387 foreach ($pkg['versions'] as $metadata) {
32388 $packages[] = $metadata;
32389 }
32390 }
32391
32392 return $packages;
32393 }
32394
32395 if (isset($data['packages'])) {
32396 foreach ($data['packages'] as $package => $versions) {
32397 foreach ($versions as $version => $metadata) {
32398 $packages[] = $metadata;
32399 }
32400 }
32401 }
32402
32403 if (isset($data['includes'])) {
32404 foreach ($data['includes'] as $include => $metadata) {
32405 if ($this->cache->sha1($include) === $metadata['sha1']) {
32406 $includedData = json_decode($this->cache->read($include), true);
32407 } else {
32408 $includedData = $this->fetchFile($include);
32409 }
32410 $packages = array_merge($packages, $this->loadIncludes($includedData));
32411 }
32412 }
32413
32414 return $packages;
32415 }
32416
32417 protected function createPackage(array $data, $class = 'Composer\Package\CompletePackage')
32418 {
32419 try {
32420 if (!isset($data['notification-url'])) {
32421 $data['notification-url'] = $this->notifyUrl;
32422 }
32423
32424 $package = $this->loader->load($data, $class);
32425 if (isset($this->sourceMirrors[$package->getSourceType()])) {
32426 $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
32427 }
32428 $package->setDistMirrors($this->distMirrors);
32429 $this->configurePackageTransportOptions($package);
32430
32431 return $package;
32432 } catch (\Exception $e) {
32433 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);
32434 }
32435 }
32436
32437 protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)
32438 {
32439 if (null === $cacheKey) {
32440 $cacheKey = $filename;
32441 $filename = $this->baseUrl.'/'.$filename;
32442 }
32443
32444
32445  if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) {
32446 $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
32447 }
32448
32449 $retries = 3;
32450 while ($retries--) {
32451 try {
32452 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
32453 if ($this->eventDispatcher) {
32454 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
32455 }
32456
32457 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
32458 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
32459
32460 $json = $rfs->getContents($hostname, $filename, false);
32461 if ($sha256 && $sha256 !== hash('sha256', $json)) {
32462
32463  if ($this->allowSslDowngrade) {
32464 $this->url = str_replace('http://', 'https://', $this->url);
32465 $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
32466 $filename = str_replace('http://', 'https://', $filename);
32467 }
32468
32469 if ($retries) {
32470 usleep(100000);
32471
32472 continue;
32473 }
32474
32475
32476  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.');
32477 }
32478
32479 $data = JsonFile::parseJson($json, $filename);
32480 if (!empty($data['warning'])) {
32481 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
32482 }
32483 if (!empty($data['info'])) {
32484 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
32485 }
32486
32487 if ($cacheKey) {
32488 if ($storeLastModifiedTime) {
32489 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
32490 if ($lastModifiedDate) {
32491 $data['last-modified'] = $lastModifiedDate;
32492 $json = json_encode($data);
32493 }
32494 }
32495 $this->cache->write($cacheKey, $json);
32496 }
32497
32498 break;
32499 } catch (\Exception $e) {
32500 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
32501 throw $e;
32502 }
32503
32504 if ($retries) {
32505 usleep(100000);
32506 continue;
32507 }
32508
32509 if ($e instanceof RepositorySecurityException) {
32510 throw $e;
32511 }
32512
32513 if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
32514 if (!$this->degradedMode) {
32515 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
32516 $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>');
32517 }
32518 $this->degradedMode = true;
32519 $data = JsonFile::parseJson($contents, $this->cache->getRoot().$cacheKey);
32520
32521 break;
32522 }
32523
32524 throw $e;
32525 }
32526 }
32527
32528 return $data;
32529 }
32530
32531 protected function fetchFileIfLastModified($filename, $cacheKey, $lastModifiedTime)
32532 {
32533 $retries = 3;
32534 while ($retries--) {
32535 try {
32536 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
32537 if ($this->eventDispatcher) {
32538 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
32539 }
32540
32541 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
32542 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
32543 $options = array('http' => array('header' => array('If-Modified-Since: '.$lastModifiedTime)));
32544 $json = $rfs->getContents($hostname, $filename, false, $options);
32545 if ($json === '' && $rfs->findStatusCode($rfs->getLastHeaders()) === 304) {
32546 return true;
32547 }
32548
32549 $data = JsonFile::parseJson($json, $filename);
32550 if (!empty($data['warning'])) {
32551 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
32552 }
32553 if (!empty($data['info'])) {
32554 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
32555 }
32556
32557 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
32558 if ($lastModifiedDate) {
32559 $data['last-modified'] = $lastModifiedDate;
32560 $json = json_encode($data);
32561 }
32562 $this->cache->write($cacheKey, $json);
32563
32564 return $data;
32565 } catch (\Exception $e) {
32566 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
32567 throw $e;
32568 }
32569
32570 if ($retries) {
32571 usleep(100000);
32572 continue;
32573 }
32574
32575 if (!$this->degradedMode) {
32576 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
32577 $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>');
32578 }
32579 $this->degradedMode = true;
32580
32581 return true;
32582 }
32583 }
32584 }
32585
32586
32587
32588
32589
32590
32591 private function initializePartialPackages()
32592 {
32593 $rootData = $this->loadRootServerFile();
32594
32595 $this->partialPackagesByName = array();
32596 foreach ($rootData['packages'] as $package => $versions) {
32597 $package = strtolower($package);
32598 foreach ($versions as $version) {
32599 $this->partialPackagesByName[$package][] = $version;
32600 if (!empty($version['provide']) && is_array($version['provide'])) {
32601 foreach ($version['provide'] as $provided => $providedVersion) {
32602 $this->partialPackagesByName[strtolower($provided)][] = $version;
32603 }
32604 }
32605 if (!empty($version['replace']) && is_array($version['replace'])) {
32606 foreach ($version['replace'] as $provided => $providedVersion) {
32607 $this->partialPackagesByName[strtolower($provided)][] = $version;
32608 }
32609 }
32610 }
32611 }
32612
32613
32614  $this->rootData = true;
32615 }
32616 }
32617 <?php
32618
32619
32620
32621
32622
32623
32624
32625
32626
32627
32628
32629 namespace Composer\Repository;
32630
32631 use Composer\Package\PackageInterface;
32632
32633
32634
32635
32636
32637
32638 class CompositeRepository extends BaseRepository
32639 {
32640
32641
32642
32643
32644 private $repositories;
32645
32646
32647
32648
32649
32650 public function __construct(array $repositories)
32651 {
32652 $this->repositories = array();
32653 foreach ($repositories as $repo) {
32654 $this->addRepository($repo);
32655 }
32656 }
32657
32658
32659
32660
32661
32662
32663 public function getRepositories()
32664 {
32665 return $this->repositories;
32666 }
32667
32668
32669
32670
32671 public function hasPackage(PackageInterface $package)
32672 {
32673 foreach ($this->repositories as $repository) {
32674
32675 if ($repository->hasPackage($package)) {
32676 return true;
32677 }
32678 }
32679
32680 return false;
32681 }
32682
32683
32684
32685
32686 public function findPackage($name, $constraint)
32687 {
32688 foreach ($this->repositories as $repository) {
32689
32690 $package = $repository->findPackage($name, $constraint);
32691 if (null !== $package) {
32692 return $package;
32693 }
32694 }
32695
32696 return null;
32697 }
32698
32699
32700
32701
32702 public function findPackages($name, $constraint = null)
32703 {
32704 $packages = array();
32705 foreach ($this->repositories as $repository) {
32706
32707 $packages[] = $repository->findPackages($name, $constraint);
32708 }
32709
32710 return $packages ? call_user_func_array('array_merge', $packages) : array();
32711 }
32712
32713
32714
32715
32716 public function search($query, $mode = 0, $type = null)
32717 {
32718 $matches = array();
32719 foreach ($this->repositories as $repository) {
32720
32721 $matches[] = $repository->search($query, $mode, $type);
32722 }
32723
32724 return $matches ? call_user_func_array('array_merge', $matches) : array();
32725 }
32726
32727
32728
32729
32730 public function getPackages()
32731 {
32732 $packages = array();
32733 foreach ($this->repositories as $repository) {
32734
32735 $packages[] = $repository->getPackages();
32736 }
32737
32738 return $packages ? call_user_func_array('array_merge', $packages) : array();
32739 }
32740
32741
32742
32743
32744 public function removePackage(PackageInterface $package)
32745 {
32746 foreach ($this->repositories as $repository) {
32747
32748 $repository->removePackage($package);
32749 }
32750 }
32751
32752
32753
32754
32755 public function count()
32756 {
32757 $total = 0;
32758 foreach ($this->repositories as $repository) {
32759
32760 $total += $repository->count();
32761 }
32762
32763 return $total;
32764 }
32765
32766
32767
32768
32769
32770 public function addRepository(RepositoryInterface $repository)
32771 {
32772 if ($repository instanceof self) {
32773 foreach ($repository->getRepositories() as $repo) {
32774 $this->addRepository($repo);
32775 }
32776 } else {
32777 $this->repositories[] = $repository;
32778 }
32779 }
32780 }
32781 <?php
32782
32783
32784
32785
32786
32787
32788
32789
32790
32791
32792
32793 namespace Composer\Repository;
32794
32795
32796
32797
32798
32799
32800 interface ConfigurableRepositoryInterface
32801 {
32802 public function getRepoConfig();
32803 }
32804 <?php
32805
32806
32807
32808
32809
32810
32811
32812
32813
32814
32815
32816 namespace Composer\Repository;
32817
32818 use Composer\Json\JsonFile;
32819 use Composer\Package\Loader\ArrayLoader;
32820 use Composer\Package\Dumper\ArrayDumper;
32821
32822
32823
32824
32825
32826
32827
32828 class FilesystemRepository extends WritableArrayRepository
32829 {
32830 private $file;
32831
32832
32833
32834
32835
32836
32837 public function __construct(JsonFile $repositoryFile)
32838 {
32839 parent::__construct();
32840 $this->file = $repositoryFile;
32841 }
32842
32843
32844
32845
32846 protected function initialize()
32847 {
32848 parent::initialize();
32849
32850 if (!$this->file->exists()) {
32851 return;
32852 }
32853
32854 try {
32855 $packages = $this->file->read();
32856
32857 if (!is_array($packages)) {
32858 throw new \UnexpectedValueException('Could not parse package list from the repository');
32859 }
32860 } catch (\Exception $e) {
32861 throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.get_class($e).'] '.$e->getMessage());
32862 }
32863
32864 $loader = new ArrayLoader(null, true);
32865 foreach ($packages as $packageData) {
32866 $package = $loader->load($packageData);
32867 $this->addPackage($package);
32868 }
32869 }
32870
32871 public function reload()
32872 {
32873 $this->packages = null;
32874 $this->initialize();
32875 }
32876
32877
32878
32879
32880 public function write()
32881 {
32882 $data = array();
32883 $dumper = new ArrayDumper();
32884
32885 foreach ($this->getCanonicalPackages() as $package) {
32886 $data[] = $dumper->dump($package);
32887 }
32888
32889 usort($data, function ($a, $b) {
32890 return strcmp($a['name'], $b['name']);
32891 });
32892
32893 $this->file->write($data);
32894 }
32895 }
32896 <?php
32897
32898
32899
32900
32901
32902
32903
32904
32905
32906
32907
32908 namespace Composer\Repository;
32909
32910
32911
32912
32913
32914
32915
32916
32917 class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
32918 {
32919 }
32920 <?php
32921
32922
32923
32924
32925
32926
32927
32928
32929
32930
32931
32932 namespace Composer\Repository;
32933
32934
32935
32936
32937
32938
32939 class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
32940 {
32941 }
32942 <?php
32943
32944
32945
32946
32947
32948
32949
32950
32951
32952
32953
32954 namespace Composer\Repository;
32955
32956
32957
32958
32959
32960
32961
32962
32963 interface InstalledRepositoryInterface extends WritableRepositoryInterface
32964 {
32965 }
32966 <?php
32967
32968
32969
32970
32971
32972
32973
32974
32975
32976
32977
32978 namespace Composer\Repository;
32979
32980
32981
32982
32983
32984
32985 class InvalidRepositoryException extends \Exception
32986 {
32987 }
32988 <?php
32989
32990
32991
32992
32993
32994
32995
32996
32997
32998
32999
33000 namespace Composer\Repository;
33001
33002 use Composer\Package\Loader\ArrayLoader;
33003 use Composer\Package\Loader\ValidatingArrayLoader;
33004
33005
33006
33007
33008
33009
33010 class PackageRepository extends ArrayRepository
33011 {
33012 private $config;
33013
33014
33015
33016
33017
33018
33019 public function __construct(array $config)
33020 {
33021 parent::__construct();
33022 $this->config = $config['package'];
33023
33024
33025  if (!is_numeric(key($this->config))) {
33026 $this->config = array($this->config);
33027 }
33028 }
33029
33030
33031
33032
33033 protected function initialize()
33034 {
33035 parent::initialize();
33036
33037 $loader = new ValidatingArrayLoader(new ArrayLoader(null, true), false);
33038 foreach ($this->config as $package) {
33039 try {
33040 $package = $loader->load($package);
33041 } catch (\Exception $e) {
33042 throw new InvalidRepositoryException('A repository of type "package" contains an invalid package definition: '.$e->getMessage()."\n\nInvalid package definition:\n".json_encode($package));
33043 }
33044
33045 $this->addPackage($package);
33046 }
33047 }
33048 }
33049 <?php
33050
33051
33052
33053
33054
33055
33056
33057
33058
33059
33060
33061 namespace Composer\Repository;
33062
33063 use Composer\Config;
33064 use Composer\IO\IOInterface;
33065 use Composer\Json\JsonFile;
33066 use Composer\Package\Loader\ArrayLoader;
33067 use Composer\Package\Version\VersionGuesser;
33068 use Composer\Package\Version\VersionParser;
33069 use Composer\Util\Platform;
33070 use Composer\Util\ProcessExecutor;
33071
33072
33073
33074
33075
33076
33077
33078
33079
33080
33081
33082
33083
33084
33085
33086
33087
33088
33089
33090
33091
33092
33093
33094
33095
33096
33097
33098
33099
33100
33101
33102
33103
33104
33105
33106
33107 class PathRepository extends ArrayRepository implements ConfigurableRepositoryInterface
33108 {
33109
33110
33111
33112 private $loader;
33113
33114
33115
33116
33117 private $versionGuesser;
33118
33119
33120
33121
33122 private $url;
33123
33124
33125
33126
33127 private $repoConfig;
33128
33129
33130
33131
33132 private $process;
33133
33134
33135
33136
33137 private $options;
33138
33139
33140
33141
33142
33143
33144
33145
33146 public function __construct(array $repoConfig, IOInterface $io, Config $config)
33147 {
33148 if (!isset($repoConfig['url'])) {
33149 throw new \RuntimeException('You must specify the `url` configuration for the path repository');
33150 }
33151
33152 $this->loader = new ArrayLoader(null, true);
33153 $this->url = Platform::expandPath($repoConfig['url']);
33154 $this->process = new ProcessExecutor($io);
33155 $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
33156 $this->repoConfig = $repoConfig;
33157 $this->options = isset($repoConfig['options']) ? $repoConfig['options'] : array();
33158
33159 parent::__construct();
33160 }
33161
33162 public function getRepoConfig()
33163 {
33164 return $this->repoConfig;
33165 }
33166
33167
33168
33169
33170
33171
33172 protected function initialize()
33173 {
33174 parent::initialize();
33175
33176 foreach ($this->getUrlMatches() as $url) {
33177 $path = realpath($url) . DIRECTORY_SEPARATOR;
33178 $composerFilePath = $path.'composer.json';
33179
33180 if (!file_exists($composerFilePath)) {
33181 continue;
33182 }
33183
33184 $json = file_get_contents($composerFilePath);
33185 $package = JsonFile::parseJson($json, $composerFilePath);
33186 $package['dist'] = array(
33187 'type' => 'path',
33188 'url' => $url,
33189 'reference' => sha1($json . serialize($this->options)),
33190 );
33191 $package['transport-options'] = $this->options;
33192
33193
33194  if (!isset($package['version']) && ($rootVersion = getenv('COMPOSER_ROOT_VERSION'))) {
33195 if (
33196 0 === $this->process->execute('git rev-parse HEAD', $ref1, $path)
33197 && 0 === $this->process->execute('git rev-parse HEAD', $ref2)
33198 && $ref1 === $ref2
33199 ) {
33200 $package['version'] = $rootVersion;
33201 }
33202 }
33203
33204 if (!isset($package['version'])) {
33205 $versionData = $this->versionGuesser->guessVersion($package, $path);
33206 $package['version'] = $versionData['version'] ?: 'dev-master';
33207 }
33208
33209 $output = '';
33210 if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
33211 $package['dist']['reference'] = trim($output);
33212 }
33213 $package = $this->loader->load($package);
33214 $this->addPackage($package);
33215 }
33216 }
33217
33218
33219
33220
33221
33222
33223 private function getUrlMatches()
33224 {
33225
33226  return array_map(function ($val) {
33227 return rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $val), '/');
33228 }, glob($this->url, GLOB_MARK | GLOB_ONLYDIR));
33229 }
33230 }
33231 <?php
33232
33233
33234
33235
33236
33237
33238
33239
33240
33241
33242
33243 namespace Composer\Repository\Pear;
33244
33245 use Composer\Util\RemoteFilesystem;
33246
33247
33248
33249
33250
33251
33252
33253
33254 abstract class BaseChannelReader
33255 {
33256
33257
33258
33259 const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
33260 const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
33261 const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
33262 const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
33263 const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
33264 const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
33265
33266
33267 private $rfs;
33268
33269 protected function __construct(RemoteFilesystem $rfs)
33270 {
33271 $this->rfs = $rfs;
33272 }
33273
33274
33275
33276
33277
33278
33279
33280
33281
33282 protected function requestContent($origin, $path)
33283 {
33284 $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
33285 $content = $this->rfs->getContents($origin, $url, false);
33286 if (!$content) {
33287 throw new \UnexpectedValueException('The PEAR channel at ' . $url . ' did not respond.');
33288 }
33289
33290 return str_replace('http://pear.php.net/rest/', 'https://pear.php.net/rest/', $content);
33291 }
33292
33293
33294
33295
33296
33297
33298
33299
33300
33301 protected function requestXml($origin, $path)
33302 {
33303
33304  $xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
33305
33306 if (false === $xml) {
33307 throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
33308 }
33309
33310 return $xml;
33311 }
33312 }
33313 <?php
33314
33315
33316
33317
33318
33319
33320
33321
33322
33323
33324
33325 namespace Composer\Repository\Pear;
33326
33327
33328
33329
33330
33331
33332 class ChannelInfo
33333 {
33334 private $name;
33335 private $alias;
33336 private $packages;
33337
33338
33339
33340
33341
33342
33343 public function __construct($name, $alias, array $packages)
33344 {
33345 $this->name = $name;
33346 $this->alias = $alias;
33347 $this->packages = $packages;
33348 }
33349
33350
33351
33352
33353
33354
33355 public function getName()
33356 {
33357 return $this->name;
33358 }
33359
33360
33361
33362
33363
33364
33365 public function getAlias()
33366 {
33367 return $this->alias;
33368 }
33369
33370
33371
33372
33373
33374
33375 public function getPackages()
33376 {
33377 return $this->packages;
33378 }
33379 }
33380 <?php
33381
33382
33383
33384
33385
33386
33387
33388
33389
33390
33391
33392 namespace Composer\Repository\Pear;
33393
33394 use Composer\Util\RemoteFilesystem;
33395
33396
33397
33398
33399
33400
33401
33402
33403 class ChannelReader extends BaseChannelReader
33404 {
33405
33406 private $readerMap;
33407
33408 public function __construct(RemoteFilesystem $rfs)
33409 {
33410 parent::__construct($rfs);
33411
33412 $rest10reader = new ChannelRest10Reader($rfs);
33413 $rest11reader = new ChannelRest11Reader($rfs);
33414
33415 $this->readerMap = array(
33416 'REST1.3' => $rest11reader,
33417 'REST1.2' => $rest11reader,
33418 'REST1.1' => $rest11reader,
33419 'REST1.0' => $rest10reader,
33420 );
33421 }
33422
33423
33424
33425
33426
33427
33428
33429
33430 public function read($url)
33431 {
33432 $xml = $this->requestXml($url, "/channel.xml");
33433
33434 $channelName = (string) $xml->name;
33435 $channelAlias = (string) $xml->suggestedalias;
33436
33437 $supportedVersions = array_keys($this->readerMap);
33438 $selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
33439 if (!$selectedRestVersion) {
33440 throw new \UnexpectedValueException(sprintf('PEAR repository %s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
33441 }
33442
33443 $reader = $this->readerMap[$selectedRestVersion['version']];
33444 $packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
33445
33446 return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
33447 }
33448
33449
33450
33451
33452
33453
33454
33455
33456 private function selectRestVersion($channelXml, $supportedVersions)
33457 {
33458 $channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
33459
33460 foreach ($supportedVersions as $version) {
33461 $xpathTest = "ns:servers/ns:*/ns:rest/ns:baseurl[@type='{$version}']";
33462 $testResult = $channelXml->xpath($xpathTest);
33463
33464 foreach ($testResult as $result) {
33465
33466  $result = (string) $result;
33467 if (preg_match('{^https://}i', $result)) {
33468 return array('version' => $version, 'baseUrl' => $result);
33469 }
33470 }
33471
33472
33473  if (count($testResult) > 0) {
33474 return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
33475 }
33476 }
33477
33478 return null;
33479 }
33480 }
33481 <?php
33482
33483
33484
33485
33486
33487
33488
33489
33490
33491
33492
33493 namespace Composer\Repository\Pear;
33494
33495 use Composer\Downloader\TransportException;
33496
33497
33498
33499
33500
33501
33502
33503
33504
33505
33506
33507
33508 class ChannelRest10Reader extends BaseChannelReader
33509 {
33510 private $dependencyReader;
33511
33512 public function __construct($rfs)
33513 {
33514 parent::__construct($rfs);
33515
33516 $this->dependencyReader = new PackageDependencyParser();
33517 }
33518
33519
33520
33521
33522
33523
33524
33525
33526 public function read($baseUrl)
33527 {
33528 return $this->readPackages($baseUrl);
33529 }
33530
33531
33532
33533
33534
33535
33536
33537
33538 private function readPackages($baseUrl)
33539 {
33540 $result = array();
33541
33542 $xmlPath = '/p/packages.xml';
33543 $xml = $this->requestXml($baseUrl, $xmlPath);
33544 $xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
33545 foreach ($xml->xpath('ns:p') as $node) {
33546 $packageName = (string) $node;
33547 $packageInfo = $this->readPackage($baseUrl, $packageName);
33548 $result[] = $packageInfo;
33549 }
33550
33551 return $result;
33552 }
33553
33554
33555
33556
33557
33558
33559
33560
33561
33562 private function readPackage($baseUrl, $packageName)
33563 {
33564 $xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
33565 $xml = $this->requestXml($baseUrl, $xmlPath);
33566 $xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
33567
33568 $channelName = (string) $xml->c;
33569 $packageName = (string) $xml->n;
33570 $license = (string) $xml->l;
33571 $shortDescription = (string) $xml->s;
33572 $description = (string) $xml->d;
33573
33574 return new PackageInfo(
33575 $channelName,
33576 $packageName,
33577 $license,
33578 $shortDescription,
33579 $description,
33580 $this->readPackageReleases($baseUrl, $packageName)
33581 );
33582 }
33583
33584
33585
33586
33587
33588
33589
33590
33591
33592
33593 private function readPackageReleases($baseUrl, $packageName)
33594 {
33595 $result = array();
33596
33597 try {
33598 $xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
33599 $xml = $this->requestXml($baseUrl, $xmlPath);
33600 $xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
33601 foreach ($xml->xpath('ns:r') as $node) {
33602 $releaseVersion = (string) $node->v;
33603 $releaseStability = (string) $node->s;
33604
33605 try {
33606 $result[$releaseVersion] = new ReleaseInfo(
33607 $releaseStability,
33608 $this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
33609 );
33610 } catch (TransportException $exception) {
33611 if ($exception->getCode() != 404) {
33612 throw $exception;
33613 }
33614 }
33615 }
33616 } catch (TransportException $exception) {
33617 if ($exception->getCode() != 404) {
33618 throw $exception;
33619 }
33620 }
33621
33622 return $result;
33623 }
33624
33625
33626
33627
33628
33629
33630
33631
33632
33633
33634 private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
33635 {
33636 $dependencyReader = new PackageDependencyParser();
33637
33638 $depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
33639 $content = $this->requestContent($baseUrl, $depthPath);
33640 $dependencyArray = unserialize($content);
33641
33642 return $dependencyReader->buildDependencyInfo($dependencyArray);
33643 }
33644 }
33645 <?php
33646
33647
33648
33649
33650
33651
33652
33653
33654
33655
33656
33657 namespace Composer\Repository\Pear;
33658
33659
33660
33661
33662
33663
33664
33665
33666
33667
33668 class ChannelRest11Reader extends BaseChannelReader
33669 {
33670 private $dependencyReader;
33671
33672 public function __construct($rfs)
33673 {
33674 parent::__construct($rfs);
33675
33676 $this->dependencyReader = new PackageDependencyParser();
33677 }
33678
33679
33680
33681
33682
33683
33684
33685
33686 public function read($baseUrl)
33687 {
33688 return $this->readChannelPackages($baseUrl);
33689 }
33690
33691
33692
33693
33694
33695
33696
33697
33698 private function readChannelPackages($baseUrl)
33699 {
33700 $result = array();
33701
33702 $xml = $this->requestXml($baseUrl, "/c/categories.xml");
33703 $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
33704 foreach ($xml->xpath('ns:c') as $node) {
33705 $categoryName = (string) $node;
33706 $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
33707 $result = array_merge($result, $categoryPackages);
33708 }
33709
33710 return $result;
33711 }
33712
33713
33714
33715
33716
33717
33718
33719
33720
33721 private function readCategoryPackages($baseUrl, $categoryName)
33722 {
33723 $result = array();
33724
33725 $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
33726 $xml = $this->requestXml($baseUrl, $categoryPath);
33727 $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
33728 foreach ($xml->xpath('ns:pi') as $node) {
33729 $packageInfo = $this->parsePackage($node);
33730 $result[] = $packageInfo;
33731 }
33732
33733 return $result;
33734 }
33735
33736
33737
33738
33739
33740
33741
33742 private function parsePackage($packageInfo)
33743 {
33744 $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
33745 $channelName = (string) $packageInfo->p->c;
33746 $packageName = (string) $packageInfo->p->n;
33747 $license = (string) $packageInfo->p->l;
33748 $shortDescription = (string) $packageInfo->p->s;
33749 $description = (string) $packageInfo->p->d;
33750
33751 $dependencies = array();
33752 foreach ($packageInfo->xpath('ns:deps') as $node) {
33753 $dependencyVersion = (string) $node->v;
33754 $dependencyArray = unserialize((string) $node->d);
33755
33756 $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
33757
33758 $dependencies[$dependencyVersion] = $dependencyInfo;
33759 }
33760
33761 $releases = array();
33762 $releasesInfo = $packageInfo->xpath('ns:a/ns:r');
33763 if ($releasesInfo) {
33764 foreach ($releasesInfo as $node) {
33765 $releaseVersion = (string) $node->v;
33766 $releaseStability = (string) $node->s;
33767 $releases[$releaseVersion] = new ReleaseInfo(
33768 $releaseStability,
33769 isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
33770 );
33771 }
33772 }
33773
33774 return new PackageInfo(
33775 $channelName,
33776 $packageName,
33777 $license,
33778 $shortDescription,
33779 $description,
33780 $releases
33781 );
33782 }
33783 }
33784 <?php
33785
33786
33787
33788
33789
33790
33791
33792
33793
33794
33795
33796 namespace Composer\Repository\Pear;
33797
33798
33799
33800
33801
33802
33803 class DependencyConstraint
33804 {
33805 private $type;
33806 private $constraint;
33807 private $channelName;
33808 private $packageName;
33809
33810
33811
33812
33813
33814
33815
33816 public function __construct($type, $constraint, $channelName, $packageName)
33817 {
33818 $this->type = $type;
33819 $this->constraint = $constraint;
33820 $this->channelName = $channelName;
33821 $this->packageName = $packageName;
33822 }
33823
33824 public function getChannelName()
33825 {
33826 return $this->channelName;
33827 }
33828
33829 public function getConstraint()
33830 {
33831 return $this->constraint;
33832 }
33833
33834 public function getPackageName()
33835 {
33836 return $this->packageName;
33837 }
33838
33839 public function getType()
33840 {
33841 return $this->type;
33842 }
33843 }
33844 <?php
33845
33846
33847
33848
33849
33850
33851
33852
33853
33854
33855
33856 namespace Composer\Repository\Pear;
33857
33858
33859
33860
33861
33862
33863 class DependencyInfo
33864 {
33865 private $requires;
33866 private $optionals;
33867
33868
33869
33870
33871
33872 public function __construct($requires, $optionals)
33873 {
33874 $this->requires = $requires;
33875 $this->optionals = $optionals;
33876 }
33877
33878
33879
33880
33881 public function getRequires()
33882 {
33883 return $this->requires;
33884 }
33885
33886
33887
33888
33889 public function getOptionals()
33890 {
33891 return $this->optionals;
33892 }
33893 }
33894 <?php
33895
33896
33897
33898
33899
33900
33901
33902
33903
33904
33905
33906 namespace Composer\Repository\Pear;
33907
33908
33909
33910
33911
33912
33913 class PackageDependencyParser
33914 {
33915
33916
33917
33918
33919
33920
33921 public function buildDependencyInfo($depArray)
33922 {
33923 if (!is_array($depArray)) {
33924 return new DependencyInfo(array(), array());
33925 }
33926 if (!$this->isHash($depArray)) {
33927 return new DependencyInfo($this->buildDependency10Info($depArray), array());
33928 }
33929
33930 return $this->buildDependency20Info($depArray);
33931 }
33932
33933
33934
33935
33936
33937
33938
33939
33940
33941
33942
33943
33944
33945 private function buildDependency10Info($depArray)
33946 {
33947 static $dep10toOperatorMap = array('has' => '==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
33948
33949 $result = array();
33950
33951 foreach ($depArray as $depItem) {
33952 if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
33953
33954  continue;
33955 }
33956
33957 $depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
33958 ? 'optional'
33959 : 'required';
33960 $depType = 'not' == $depItem['rel']
33961 ? 'conflicts'
33962 : $depType;
33963
33964 $depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
33965
33966
33967  $depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
33968 ? '*'
33969 : $dep10toOperatorMap[$depItem['rel']] . $depVersion;
33970
33971 switch ($depItem['type']) {
33972 case 'php':
33973 $depChannelName = 'php';
33974 $depPackageName = '';
33975 break;
33976 case 'pkg':
33977 $depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
33978 $depPackageName = $depItem['name'];
33979 break;
33980 case 'ext':
33981 $depChannelName = 'ext';
33982 $depPackageName = $depItem['name'];
33983 break;
33984 case 'os':
33985 case 'sapi':
33986 $depChannelName = '';
33987 $depPackageName = '';
33988 break;
33989 default:
33990 $depChannelName = '';
33991 $depPackageName = '';
33992 break;
33993 }
33994
33995 if ('' != $depChannelName) {
33996 $result[] = new DependencyConstraint(
33997 $depType,
33998 $depVersionConstraint,
33999 $depChannelName,
34000 $depPackageName
34001 );
34002 }
34003 }
34004
34005 return $result;
34006 }
34007
34008
34009
34010
34011
34012
34013
34014 private function buildDependency20Info($depArray)
34015 {
34016 $result = array();
34017 $optionals = array();
34018 $defaultOptionals = array();
34019 foreach ($depArray as $depType => $depTypeGroup) {
34020 if (!is_array($depTypeGroup)) {
34021 continue;
34022 }
34023 if ('required' == $depType || 'optional' == $depType) {
34024 foreach ($depTypeGroup as $depItemType => $depItem) {
34025 switch ($depItemType) {
34026 case 'php':
34027 $result[] = new DependencyConstraint(
34028 $depType,
34029 $this->parse20VersionConstraint($depItem),
34030 'php',
34031 ''
34032 );
34033 break;
34034 case 'package':
34035 $deps = $this->buildDepPackageConstraints($depItem, $depType);
34036 $result = array_merge($result, $deps);
34037 break;
34038 case 'extension':
34039 $deps = $this->buildDepExtensionConstraints($depItem, $depType);
34040 $result = array_merge($result, $deps);
34041 break;
34042 case 'subpackage':
34043 $deps = $this->buildDepPackageConstraints($depItem, 'replaces');
34044 $defaultOptionals += $deps;
34045 break;
34046 case 'os':
34047 case 'pearinstaller':
34048 break;
34049 default:
34050 break;
34051 }
34052 }
34053 } elseif ('group' == $depType) {
34054 if ($this->isHash($depTypeGroup)) {
34055 $depTypeGroup = array($depTypeGroup);
34056 }
34057
34058 foreach ($depTypeGroup as $depItem) {
34059 $groupName = $depItem['attribs']['name'];
34060 if (!isset($optionals[$groupName])) {
34061 $optionals[$groupName] = array();
34062 }
34063
34064 if (isset($depItem['subpackage'])) {
34065 $optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
34066 } else {
34067 $result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
34068 }
34069 }
34070 }
34071 }
34072
34073 if (count($defaultOptionals) > 0) {
34074 $optionals['*'] = $defaultOptionals;
34075 }
34076
34077 return new DependencyInfo($result, $optionals);
34078 }
34079
34080
34081
34082
34083
34084
34085
34086
34087 private function buildDepExtensionConstraints($depItem, $depType)
34088 {
34089 if ($this->isHash($depItem)) {
34090 $depItem = array($depItem);
34091 }
34092
34093 $result = array();
34094 foreach ($depItem as $subDepItem) {
34095 $depChannelName = 'ext';
34096 $depPackageName = $subDepItem['name'];
34097 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
34098
34099 $result[] = new DependencyConstraint(
34100 $depType,
34101 $depVersionConstraint,
34102 $depChannelName,
34103 $depPackageName
34104 );
34105 }
34106
34107 return $result;
34108 }
34109
34110
34111
34112
34113
34114
34115
34116
34117 private function buildDepPackageConstraints($depItem, $depType)
34118 {
34119 if ($this->isHash($depItem)) {
34120 $depItem = array($depItem);
34121 }
34122
34123 $result = array();
34124 foreach ($depItem as $subDepItem) {
34125 if (!array_key_exists('channel', $subDepItem)) {
34126 $subDepItem['channel'] = $subDepItem['uri'];
34127 }
34128 $depChannelName = $subDepItem['channel'];
34129 $depPackageName = $subDepItem['name'];
34130 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
34131 if (isset($subDepItem['conflicts'])) {
34132 $depType = 'conflicts';
34133 }
34134
34135 $result[] = new DependencyConstraint(
34136 $depType,
34137 $depVersionConstraint,
34138 $depChannelName,
34139 $depPackageName
34140 );
34141 }
34142
34143 return $result;
34144 }
34145
34146
34147
34148
34149
34150
34151
34152 private function parse20VersionConstraint(array $data)
34153 {
34154 static $dep20toOperatorMap = array('has' => '==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
34155
34156 $versions = array();
34157 $values = array_intersect_key($data, $dep20toOperatorMap);
34158 if (0 == count($values)) {
34159 return '*';
34160 }
34161 if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
34162 $versions[] = '>' . $this->parseVersion($values['min']);
34163 } elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
34164 $versions[] = '<' . $this->parseVersion($values['max']);
34165 } else {
34166 foreach ($values as $op => $version) {
34167 if ('exclude' == $op && is_array($version)) {
34168 foreach ($version as $versionPart) {
34169 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
34170 }
34171 } else {
34172 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
34173 }
34174 }
34175 }
34176
34177 return implode(',', $versions);
34178 }
34179
34180
34181
34182
34183
34184
34185
34186 private function parseVersion($version)
34187 {
34188 if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
34189 $version = $matches[1]
34190 .(!empty($matches[2]) ? $matches[2] : '.0')
34191 .(!empty($matches[3]) ? $matches[3] : '.0')
34192 .(!empty($matches[4]) ? $matches[4] : '.0');
34193
34194 return $version;
34195 }
34196
34197 return null;
34198 }
34199
34200
34201
34202
34203
34204
34205
34206 private function isHash(array $array)
34207 {
34208 return !array_key_exists(1, $array) && !array_key_exists(0, $array);
34209 }
34210 }
34211 <?php
34212
34213
34214
34215
34216
34217
34218
34219
34220
34221
34222
34223 namespace Composer\Repository\Pear;
34224
34225
34226
34227
34228
34229
34230 class PackageInfo
34231 {
34232 private $channelName;
34233 private $packageName;
34234 private $license;
34235 private $shortDescription;
34236 private $description;
34237 private $releases;
34238
34239
34240
34241
34242
34243
34244
34245
34246
34247 public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
34248 {
34249 $this->channelName = $channelName;
34250 $this->packageName = $packageName;
34251 $this->license = $license;
34252 $this->shortDescription = $shortDescription;
34253 $this->description = $description;
34254 $this->releases = $releases;
34255 }
34256
34257
34258
34259
34260 public function getChannelName()
34261 {
34262 return $this->channelName;
34263 }
34264
34265
34266
34267
34268 public function getPackageName()
34269 {
34270 return $this->packageName;
34271 }
34272
34273
34274
34275
34276 public function getDescription()
34277 {
34278 return $this->description;
34279 }
34280
34281
34282
34283
34284 public function getShortDescription()
34285 {
34286 return $this->shortDescription;
34287 }
34288
34289
34290
34291
34292 public function getLicense()
34293 {
34294 return $this->license;
34295 }
34296
34297
34298
34299
34300 public function getReleases()
34301 {
34302 return $this->releases;
34303 }
34304 }
34305 <?php
34306
34307
34308
34309
34310
34311
34312
34313
34314
34315
34316
34317 namespace Composer\Repository\Pear;
34318
34319
34320
34321
34322
34323
34324 class ReleaseInfo
34325 {
34326 private $stability;
34327 private $dependencyInfo;
34328
34329
34330
34331
34332
34333 public function __construct($stability, $dependencyInfo)
34334 {
34335 $this->stability = $stability;
34336 $this->dependencyInfo = $dependencyInfo;
34337 }
34338
34339
34340
34341
34342 public function getDependencyInfo()
34343 {
34344 return $this->dependencyInfo;
34345 }
34346
34347
34348
34349
34350 public function getStability()
34351 {
34352 return $this->stability;
34353 }
34354 }
34355 <?php
34356
34357
34358
34359
34360
34361
34362
34363
34364
34365
34366
34367 namespace Composer\Repository;
34368
34369 use Composer\IO\IOInterface;
34370 use Composer\Semver\VersionParser as SemverVersionParser;
34371 use Composer\Package\Version\VersionParser;
34372 use Composer\Repository\Pear\ChannelReader;
34373 use Composer\Package\CompletePackage;
34374 use Composer\Repository\Pear\ChannelInfo;
34375 use Composer\EventDispatcher\EventDispatcher;
34376 use Composer\Package\Link;
34377 use Composer\Semver\Constraint\Constraint;
34378 use Composer\Util\RemoteFilesystem;
34379 use Composer\Config;
34380 use Composer\Factory;
34381
34382
34383
34384
34385
34386
34387
34388
34389
34390
34391 class PearRepository extends ArrayRepository implements ConfigurableRepositoryInterface
34392 {
34393 private $url;
34394 private $io;
34395 private $rfs;
34396 private $versionParser;
34397 private $repoConfig;
34398
34399
34400
34401
34402 private $vendorAlias;
34403
34404 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null)
34405 {
34406 parent::__construct();
34407 if (!preg_match('{^https?://}', $repoConfig['url'])) {
34408 $repoConfig['url'] = 'http://'.$repoConfig['url'];
34409 }
34410
34411 $urlBits = parse_url($repoConfig['url']);
34412 if (empty($urlBits['scheme']) || empty($urlBits['host'])) {
34413 throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']);
34414 }
34415
34416 $this->url = rtrim($repoConfig['url'], '/');
34417 $this->io = $io;
34418 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
34419 $this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
34420 $this->versionParser = new VersionParser();
34421 $this->repoConfig = $repoConfig;
34422 }
34423
34424 public function getRepoConfig()
34425 {
34426 return $this->repoConfig;
34427 }
34428
34429 protected function initialize()
34430 {
34431 parent::initialize();
34432
34433 $this->io->writeError('Initializing PEAR repository '.$this->url);
34434
34435 $reader = new ChannelReader($this->rfs);
34436 try {
34437 $channelInfo = $reader->read($this->url);
34438 } catch (\Exception $e) {
34439 $this->io->writeError('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
34440
34441 return;
34442 }
34443 $packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
34444 foreach ($packages as $package) {
34445 $this->addPackage($package);
34446 }
34447 }
34448
34449
34450
34451
34452
34453
34454
34455
34456 private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
34457 {
34458 $result = array();
34459 foreach ($channelInfo->getPackages() as $packageDefinition) {
34460 foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
34461 try {
34462 $normalizedVersion = $versionParser->normalize($version);
34463 } catch (\UnexpectedValueException $e) {
34464 $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage(), true, IOInterface::VERBOSE);
34465 continue;
34466 }
34467
34468 $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
34469
34470
34471  
34472  $urlBits = parse_url($this->url);
34473 $scheme = (isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl')) ? 'https' : 'http';
34474 $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
34475
34476 $requires = array();
34477 $suggests = array();
34478 $conflicts = array();
34479 $replaces = array();
34480
34481
34482  
34483  if ($channelInfo->getName() == $packageDefinition->getChannelName()) {
34484 $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
34485 $aliasConstraint = new Constraint('==', $normalizedVersion);
34486 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
34487 }
34488
34489
34490  if (!empty($this->vendorAlias)
34491 && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())
34492 ) {
34493 $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
34494 $aliasConstraint = new Constraint('==', $normalizedVersion);
34495 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
34496 }
34497
34498 foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) {
34499 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
34500 $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
34501 $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
34502 switch ($dependencyConstraint->getType()) {
34503 case 'required':
34504 $requires[] = $link;
34505 break;
34506 case 'conflicts':
34507 $conflicts[] = $link;
34508 break;
34509 case 'replaces':
34510 $replaces[] = $link;
34511 break;
34512 }
34513 }
34514
34515 foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
34516 foreach ($dependencyConstraints as $dependencyConstraint) {
34517 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
34518 $suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
34519 }
34520 }
34521
34522 $package = new CompletePackage($composerPackageName, $normalizedVersion, $version);
34523 $package->setType('pear-library');
34524 $package->setDescription($packageDefinition->getDescription());
34525 $package->setLicense(array($packageDefinition->getLicense()));
34526 $package->setDistType('file');
34527 $package->setDistUrl($distUrl);
34528 $package->setAutoload(array('classmap' => array('')));
34529 $package->setIncludePaths(array('/'));
34530 $package->setRequires($requires);
34531 $package->setConflicts($conflicts);
34532 $package->setSuggests($suggests);
34533 $package->setReplaces($replaces);
34534 $result[] = $package;
34535 }
34536 }
34537
34538 return $result;
34539 }
34540
34541 private function buildComposerPackageName($channelName, $packageName)
34542 {
34543 if ('php' === $channelName) {
34544 return "php";
34545 }
34546 if ('ext' === $channelName) {
34547 return "ext-{$packageName}";
34548 }
34549
34550 return "pear-{$channelName}/{$packageName}";
34551 }
34552 }
34553 <?php
34554
34555
34556
34557
34558
34559
34560
34561
34562
34563
34564
34565 namespace Composer\Repository;
34566
34567 use Composer\XdebugHandler;
34568 use Composer\Package\CompletePackage;
34569 use Composer\Package\PackageInterface;
34570 use Composer\Package\Version\VersionParser;
34571 use Composer\Plugin\PluginInterface;
34572 use Composer\Util\Silencer;
34573
34574
34575
34576
34577 class PlatformRepository extends ArrayRepository
34578 {
34579 const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[^/ ]+)$}i';
34580
34581 private $versionParser;
34582
34583
34584
34585
34586
34587
34588
34589
34590 private $overrides = array();
34591
34592 public function __construct(array $packages = array(), array $overrides = array())
34593 {
34594 foreach ($overrides as $name => $version) {
34595 $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
34596 }
34597 parent::__construct($packages);
34598 }
34599
34600 protected function initialize()
34601 {
34602 parent::initialize();
34603
34604 $this->versionParser = new VersionParser();
34605
34606
34607  
34608  foreach ($this->overrides as $override) {
34609
34610  if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
34611 throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
34612 }
34613
34614 $this->addOverriddenPackage($override);
34615 }
34616
34617 $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
34618 $version = $this->versionParser->normalize($prettyVersion);
34619 $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
34620 $composerPluginApi->setDescription('The Composer Plugin API');
34621 $this->addPackage($composerPluginApi);
34622
34623 try {
34624 $prettyVersion = PHP_VERSION;
34625 $version = $this->versionParser->normalize($prettyVersion);
34626 } catch (\UnexpectedValueException $e) {
34627 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
34628 $version = $this->versionParser->normalize($prettyVersion);
34629 }
34630
34631 $php = new CompletePackage('php', $version, $prettyVersion);
34632 $php->setDescription('The PHP interpreter');
34633 $this->addPackage($php);
34634
34635 if (PHP_DEBUG) {
34636 $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion);
34637 $phpdebug->setDescription('The PHP interpreter, with debugging symbols');
34638 $this->addPackage($phpdebug);
34639 }
34640
34641 if (defined('PHP_ZTS') && PHP_ZTS) {
34642 $phpzts = new CompletePackage('php-zts', $version, $prettyVersion);
34643 $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety');
34644 $this->addPackage($phpzts);
34645 }
34646
34647 if (PHP_INT_SIZE === 8) {
34648 $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
34649 $php64->setDescription('The PHP interpreter, 64bit');
34650 $this->addPackage($php64);
34651 }
34652
34653
34654  
34655  if (defined('AF_INET6') || Silencer::call('inet_pton', '::') !== false) {
34656 $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion);
34657 $phpIpv6->setDescription('The PHP interpreter, with IPv6 support');
34658 $this->addPackage($phpIpv6);
34659 }
34660
34661 $loadedExtensions = get_loaded_extensions();
34662
34663
34664  foreach ($loadedExtensions as $name) {
34665 if (in_array($name, array('standard', 'Core'))) {
34666 continue;
34667 }
34668
34669 $reflExt = new \ReflectionExtension($name);
34670 $prettyVersion = $reflExt->getVersion();
34671 $this->addExtension($name, $prettyVersion);
34672 }
34673
34674
34675  if (!in_array('xdebug', $loadedExtensions, true) && ($prettyVersion = strval(getenv(XdebugHandler::ENV_VERSION)))) {
34676 $this->addExtension('xdebug', $prettyVersion);
34677 }
34678
34679
34680  
34681  
34682  foreach ($loadedExtensions as $name) {
34683 $prettyVersion = null;
34684 $description = 'The '.$name.' PHP library';
34685 switch ($name) {
34686 case 'curl':
34687 $curlVersion = curl_version();
34688 $prettyVersion = $curlVersion['version'];
34689 break;
34690
34691 case 'iconv':
34692 $prettyVersion = ICONV_VERSION;
34693 break;
34694
34695 case 'intl':
34696 $name = 'ICU';
34697 if (defined('INTL_ICU_VERSION')) {
34698 $prettyVersion = INTL_ICU_VERSION;
34699 } else {
34700 $reflector = new \ReflectionExtension('intl');
34701
34702 ob_start();
34703 $reflector->info();
34704 $output = ob_get_clean();
34705
34706 preg_match('/^ICU version => (.*)$/m', $output, $matches);
34707 $prettyVersion = $matches[1];
34708 }
34709
34710 break;
34711
34712 case 'libxml':
34713 $prettyVersion = LIBXML_DOTTED_VERSION;
34714 break;
34715
34716 case 'openssl':
34717 $prettyVersion = preg_replace_callback('{^(?:OpenSSL|LibreSSL)?\s*([0-9.]+)([a-z]*).*}i', function ($match) {
34718 if (empty($match[2])) {
34719 return $match[1];
34720 }
34721
34722
34723  
34724
34725 if (!preg_match('{^z*[a-z]$}', $match[2])) {
34726
34727  return 0;
34728 }
34729
34730 $len = strlen($match[2]);
34731 $patchVersion = ($len - 1) * 26; 
34732  $patchVersion += ord($match[2][$len - 1]) - 96;
34733
34734 return $match[1].'.'.$patchVersion;
34735 }, OPENSSL_VERSION_TEXT);
34736
34737 $description = OPENSSL_VERSION_TEXT;
34738 break;
34739
34740 case 'pcre':
34741 $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION);
34742 break;
34743
34744 case 'uuid':
34745 $prettyVersion = phpversion('uuid');
34746 break;
34747
34748 case 'xsl':
34749 $prettyVersion = LIBXSLT_DOTTED_VERSION;
34750 break;
34751
34752 default:
34753
34754  continue 2;
34755 }
34756
34757 try {
34758 $version = $this->versionParser->normalize($prettyVersion);
34759 } catch (\UnexpectedValueException $e) {
34760 continue;
34761 }
34762
34763 $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
34764 $lib->setDescription($description);
34765 $this->addPackage($lib);
34766 }
34767
34768 if (defined('HHVM_VERSION')) {
34769 try {
34770 $prettyVersion = HHVM_VERSION;
34771 $version = $this->versionParser->normalize($prettyVersion);
34772 } catch (\UnexpectedValueException $e) {
34773 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION);
34774 $version = $this->versionParser->normalize($prettyVersion);
34775 }
34776
34777 $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
34778 $hhvm->setDescription('The HHVM Runtime (64bit)');
34779 $this->addPackage($hhvm);
34780 }
34781 }
34782
34783
34784
34785
34786 public function addPackage(PackageInterface $package)
34787 {
34788
34789  if (isset($this->overrides[$package->getName()])) {
34790 $overrider = $this->findPackage($package->getName(), '*');
34791 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
34792
34793 return;
34794 }
34795
34796
34797  if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
34798 $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
34799 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
34800
34801 return;
34802 }
34803
34804 parent::addPackage($package);
34805 }
34806
34807 private function addOverriddenPackage(array $override, $name = null)
34808 {
34809 $version = $this->versionParser->normalize($override['version']);
34810 $package = new CompletePackage($name ?: $override['name'], $version, $override['version']);
34811 $package->setDescription('Package overridden via config.platform');
34812 $package->setExtra(array('config.platform' => true));
34813 parent::addPackage($package);
34814
34815 return $package;
34816 }
34817
34818
34819
34820
34821
34822
34823
34824 private function addExtension($name, $prettyVersion)
34825 {
34826 $extraDescription = null;
34827
34828 try {
34829 $version = $this->versionParser->normalize($prettyVersion);
34830 } catch (\UnexpectedValueException $e) {
34831 $extraDescription = ' (actual version: '.$prettyVersion.')';
34832 if (preg_match('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) {
34833 $prettyVersion = $match[1];
34834 } else {
34835 $prettyVersion = '0';
34836 }
34837 $version = $this->versionParser->normalize($prettyVersion);
34838 }
34839
34840 $packageName = $this->buildPackageName($name);
34841 $ext = new CompletePackage($packageName, $version, $prettyVersion);
34842 $ext->setDescription('The '.$name.' PHP extension'.$extraDescription);
34843 $this->addPackage($ext);
34844 }
34845
34846 private function buildPackageName($name)
34847 {
34848 return 'ext-' . str_replace(' ', '-', $name);
34849 }
34850 }
34851 <?php
34852
34853
34854
34855
34856
34857
34858
34859
34860
34861
34862
34863 namespace Composer\Repository;
34864
34865 use Composer\Factory;
34866 use Composer\IO\IOInterface;
34867 use Composer\Config;
34868 use Composer\EventDispatcher\EventDispatcher;
34869 use Composer\Util\RemoteFilesystem;
34870 use Composer\Json\JsonFile;
34871
34872
34873
34874
34875 class RepositoryFactory
34876 {
34877
34878
34879
34880
34881
34882
34883
34884 public static function configFromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
34885 {
34886 if (0 === strpos($repository, 'http')) {
34887 $repoConfig = array('type' => 'composer', 'url' => $repository);
34888 } elseif ("json" === pathinfo($repository, PATHINFO_EXTENSION)) {
34889 $json = new JsonFile($repository, Factory::createRemoteFilesystem($io, $config));
34890 $data = $json->read();
34891 if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
34892 $repoConfig = array('type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/'));
34893 } elseif ($allowFilesystem) {
34894 $repoConfig = array('type' => 'filesystem', 'json' => $json);
34895 } else {
34896 throw new \InvalidArgumentException("Invalid repository URL ($repository) given. This file does not contain a valid composer repository.");
34897 }
34898 } elseif ('{' === substr($repository, 0, 1)) {
34899
34900  $repoConfig = JsonFile::parseJson($repository);
34901 } else {
34902 throw new \InvalidArgumentException("Invalid repository url ($repository) given. Has to be a .json file, an http url or a JSON object.");
34903 }
34904
34905 return $repoConfig;
34906 }
34907
34908
34909
34910
34911
34912
34913
34914
34915 public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
34916 {
34917 $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
34918
34919 return static::createRepo($io, $config, $repoConfig);
34920 }
34921
34922
34923
34924
34925
34926
34927
34928 public static function createRepo(IOInterface $io, Config $config, array $repoConfig)
34929 {
34930 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
34931 $repos = static::createRepos($rm, array($repoConfig));
34932
34933 return reset($repos);
34934 }
34935
34936
34937
34938
34939
34940
34941
34942 public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
34943 {
34944 if (!$config) {
34945 $config = Factory::createConfig($io);
34946 }
34947 if (!$rm) {
34948 if (!$io) {
34949 throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
34950 }
34951 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
34952 }
34953
34954 return static::createRepos($rm, $config->getRepositories());
34955 }
34956
34957
34958
34959
34960
34961
34962
34963
34964 public static function manager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
34965 {
34966 $rm = new RepositoryManager($io, $config, $eventDispatcher, $rfs);
34967 $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
34968 $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
34969 $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
34970 $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
34971 $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
34972 $rm->setRepositoryClass('git-bitbucket', 'Composer\Repository\VcsRepository');
34973 $rm->setRepositoryClass('github', 'Composer\Repository\VcsRepository');
34974 $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
34975 $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
34976 $rm->setRepositoryClass('fossil', 'Composer\Repository\VcsRepository');
34977 $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
34978 $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
34979 $rm->setRepositoryClass('hg-bitbucket', 'Composer\Repository\VcsRepository');
34980 $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
34981 $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
34982
34983 return $rm;
34984 }
34985
34986
34987
34988
34989 private static function createRepos(RepositoryManager $rm, array $repoConfigs)
34990 {
34991 $repos = array();
34992
34993 foreach ($repoConfigs as $index => $repo) {
34994 if (is_string($repo)) {
34995 throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
34996 }
34997 if (!is_array($repo)) {
34998 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') should be an array, '.gettype($repo).' given');
34999 }
35000 if (!isset($repo['type'])) {
35001 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') must have a type defined');
35002 }
35003 $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
35004 while (isset($repos[$name])) {
35005 $name .= '2';
35006 }
35007 if ($repo['type'] === 'filesystem') {
35008 $repos[$name] = new FilesystemRepository($repo['json']);
35009 } else {
35010 $repos[$name] = $rm->createRepository($repo['type'], $repo, $index);
35011 }
35012 }
35013
35014 return $repos;
35015 }
35016 }
35017 <?php
35018
35019
35020
35021
35022
35023
35024
35025
35026
35027
35028
35029 namespace Composer\Repository;
35030
35031 use Composer\Package\PackageInterface;
35032
35033
35034
35035
35036
35037
35038
35039
35040 interface RepositoryInterface extends \Countable
35041 {
35042 const SEARCH_FULLTEXT = 0;
35043 const SEARCH_NAME = 1;
35044
35045
35046
35047
35048
35049
35050
35051
35052 public function hasPackage(PackageInterface $package);
35053
35054
35055
35056
35057
35058
35059
35060
35061
35062 public function findPackage($name, $constraint);
35063
35064
35065
35066
35067
35068
35069
35070
35071
35072 public function findPackages($name, $constraint = null);
35073
35074
35075
35076
35077
35078
35079 public function getPackages();
35080
35081
35082
35083
35084
35085
35086
35087
35088
35089 public function search($query, $mode = 0);
35090 }
35091 <?php
35092
35093
35094
35095
35096
35097
35098
35099
35100
35101
35102
35103 namespace Composer\Repository;
35104
35105 use Composer\IO\IOInterface;
35106 use Composer\Config;
35107 use Composer\EventDispatcher\EventDispatcher;
35108 use Composer\Package\PackageInterface;
35109 use Composer\Util\RemoteFilesystem;
35110
35111
35112
35113
35114
35115
35116
35117
35118 class RepositoryManager
35119 {
35120 private $localRepository;
35121 private $repositories = array();
35122 private $repositoryClasses = array();
35123 private $io;
35124 private $config;
35125 private $eventDispatcher;
35126 private $rfs;
35127
35128 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
35129 {
35130 $this->io = $io;
35131 $this->config = $config;
35132 $this->eventDispatcher = $eventDispatcher;
35133 $this->rfs = $rfs;
35134 }
35135
35136
35137
35138
35139
35140
35141
35142
35143
35144 public function findPackage($name, $constraint)
35145 {
35146 foreach ($this->repositories as $repository) {
35147 if ($package = $repository->findPackage($name, $constraint)) {
35148 return $package;
35149 }
35150 }
35151
35152 return null;
35153 }
35154
35155
35156
35157
35158
35159
35160
35161
35162
35163 public function findPackages($name, $constraint)
35164 {
35165 $packages = array();
35166
35167 foreach ($this->repositories as $repository) {
35168 $packages = array_merge($packages, $repository->findPackages($name, $constraint));
35169 }
35170
35171 return $packages;
35172 }
35173
35174
35175
35176
35177
35178
35179 public function addRepository(RepositoryInterface $repository)
35180 {
35181 $this->repositories[] = $repository;
35182 }
35183
35184
35185
35186
35187
35188
35189
35190
35191 public function prependRepository(RepositoryInterface $repository)
35192 {
35193 array_unshift($this->repositories, $repository);
35194 }
35195
35196
35197
35198
35199
35200
35201
35202
35203
35204
35205 public function createRepository($type, $config, $name = null)
35206 {
35207 if (!isset($this->repositoryClasses[$type])) {
35208 throw new \InvalidArgumentException('Repository type is not registered: '.$type);
35209 }
35210
35211 if (isset($config['packagist']) && false === $config['packagist']) {
35212 $this->io->writeError('<warning>Repository "'.$name.'" ('.json_encode($config).') has a packagist key which should be in its own repository definition</warning>');
35213 }
35214
35215 $class = $this->repositoryClasses[$type];
35216
35217 $reflMethod = new \ReflectionMethod($class, '__construct');
35218 $params = $reflMethod->getParameters();
35219 if (isset($params[4]) && $params[4]->getClass() && $params[4]->getClass()->getName() === 'Composer\Util\RemoteFilesystem') {
35220 return new $class($config, $this->io, $this->config, $this->eventDispatcher, $this->rfs);
35221 }
35222
35223 return new $class($config, $this->io, $this->config, $this->eventDispatcher);
35224 }
35225
35226
35227
35228
35229
35230
35231
35232 public function setRepositoryClass($type, $class)
35233 {
35234 $this->repositoryClasses[$type] = $class;
35235 }
35236
35237
35238
35239
35240
35241
35242 public function getRepositories()
35243 {
35244 return $this->repositories;
35245 }
35246
35247
35248
35249
35250
35251
35252 public function setLocalRepository(WritableRepositoryInterface $repository)
35253 {
35254 $this->localRepository = $repository;
35255 }
35256
35257
35258
35259
35260
35261
35262 public function getLocalRepository()
35263 {
35264 return $this->localRepository;
35265 }
35266 }
35267 <?php
35268
35269
35270
35271
35272
35273
35274
35275
35276
35277
35278
35279 namespace Composer\Repository;
35280
35281
35282
35283
35284
35285
35286 class RepositorySecurityException extends \Exception
35287 {
35288 }
35289 <?php
35290
35291
35292
35293
35294
35295
35296
35297
35298
35299
35300
35301 namespace Composer\Repository\Vcs;
35302
35303 use Composer\Cache;
35304 use Composer\Downloader\TransportException;
35305 use Composer\Json\JsonFile;
35306 use Composer\Util\Bitbucket;
35307
35308 abstract class BitbucketDriver extends VcsDriver
35309 {
35310
35311 protected $cache;
35312 protected $owner;
35313 protected $repository;
35314 protected $hasIssues;
35315 protected $rootIdentifier;
35316 protected $tags;
35317 protected $branches;
35318 protected $infoCache = array();
35319 protected $branchesUrl = '';
35320 protected $tagsUrl = '';
35321 protected $homeUrl = '';
35322 protected $website = '';
35323 protected $cloneHttpsUrl = '';
35324
35325
35326
35327
35328 protected $fallbackDriver;
35329
35330 protected $vcsType;
35331
35332
35333
35334
35335 public function initialize()
35336 {
35337 preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#', $this->url, $match);
35338 $this->owner = $match[1];
35339 $this->repository = $match[2];
35340 $this->originUrl = 'bitbucket.org';
35341 $this->cache = new Cache(
35342 $this->io,
35343 implode('/', array(
35344 $this->config->get('cache-repo-dir'),
35345 $this->originUrl,
35346 $this->owner,
35347 $this->repository,
35348 ))
35349 );
35350 }
35351
35352
35353
35354
35355 public function getUrl()
35356 {
35357 if ($this->fallbackDriver) {
35358 return $this->fallbackDriver->getUrl();
35359 }
35360
35361 return $this->cloneHttpsUrl;
35362 }
35363
35364
35365
35366
35367
35368
35369
35370 protected function getRepoData()
35371 {
35372 $resource = sprintf(
35373 'https://api.bitbucket.org/2.0/repositories/%s/%s?%s',
35374 $this->owner,
35375 $this->repository,
35376 http_build_query(
35377 array('fields' => '-project,-owner'),
35378 null,
35379 '&'
35380 )
35381 );
35382
35383 $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource);
35384 if ($this->fallbackDriver) {
35385 return false;
35386 }
35387 $this->parseCloneUrls($repoData['links']['clone']);
35388
35389 $this->hasIssues = !empty($repoData['has_issues']);
35390 $this->branchesUrl = $repoData['links']['branches']['href'];
35391 $this->tagsUrl = $repoData['links']['tags']['href'];
35392 $this->homeUrl = $repoData['links']['html']['href'];
35393 $this->website = $repoData['website'];
35394 $this->vcsType = $repoData['scm'];
35395
35396 return true;
35397 }
35398
35399
35400
35401
35402 public function getComposerInformation($identifier)
35403 {
35404 if ($this->fallbackDriver) {
35405 return $this->fallbackDriver->getComposerInformation($identifier);
35406 }
35407
35408 if (!isset($this->infoCache[$identifier])) {
35409 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
35410 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
35411 }
35412
35413 $composer = $this->getBaseComposerInformation($identifier);
35414
35415
35416  if (!isset($composer['support']['source'])) {
35417 $label = array_search(
35418 $identifier,
35419 $this->getTags()
35420 ) ?: array_search(
35421 $identifier,
35422 $this->getBranches()
35423 ) ?: $identifier;
35424
35425 if (array_key_exists($label, $tags = $this->getTags())) {
35426 $hash = $tags[$label];
35427 } elseif (array_key_exists($label, $branches = $this->getBranches())) {
35428 $hash = $branches[$label];
35429 }
35430
35431 if (! isset($hash)) {
35432 $composer['support']['source'] = sprintf(
35433 'https://%s/%s/%s/src',
35434 $this->originUrl,
35435 $this->owner,
35436 $this->repository
35437 );
35438 } else {
35439 $composer['support']['source'] = sprintf(
35440 'https://%s/%s/%s/src/%s/?at=%s',
35441 $this->originUrl,
35442 $this->owner,
35443 $this->repository,
35444 $hash,
35445 $label
35446 );
35447 }
35448 }
35449 if (!isset($composer['support']['issues']) && $this->hasIssues) {
35450 $composer['support']['issues'] = sprintf(
35451 'https://%s/%s/%s/issues',
35452 $this->originUrl,
35453 $this->owner,
35454 $this->repository
35455 );
35456 }
35457 if (!isset($composer['homepage'])) {
35458 $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
35459 }
35460
35461 $this->infoCache[$identifier] = $composer;
35462
35463 if ($this->shouldCache($identifier)) {
35464 $this->cache->write($identifier, json_encode($composer));
35465 }
35466 }
35467
35468 return $this->infoCache[$identifier];
35469 }
35470
35471
35472
35473
35474 public function getFileContent($file, $identifier)
35475 {
35476 if ($this->fallbackDriver) {
35477 return $this->fallbackDriver->getFileContent($file, $identifier);
35478 }
35479
35480 $resource = sprintf(
35481 'https://api.bitbucket.org/1.0/repositories/%s/%s/raw/%s/%s',
35482 $this->owner,
35483 $this->repository,
35484 $identifier,
35485 $file
35486 );
35487
35488 return $this->getContentsWithOAuthCredentials($resource);
35489 }
35490
35491
35492
35493
35494 public function getChangeDate($identifier)
35495 {
35496 if ($this->fallbackDriver) {
35497 return $this->fallbackDriver->getChangeDate($identifier);
35498 }
35499
35500 $resource = sprintf(
35501 'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
35502 $this->owner,
35503 $this->repository,
35504 $identifier
35505 );
35506 $commit = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35507
35508 return new \DateTime($commit['date']);
35509 }
35510
35511
35512
35513
35514 public function getSource($identifier)
35515 {
35516 if ($this->fallbackDriver) {
35517 return $this->fallbackDriver->getSource($identifier);
35518 }
35519
35520 return array('type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier);
35521 }
35522
35523
35524
35525
35526 public function getDist($identifier)
35527 {
35528 if ($this->fallbackDriver) {
35529 return $this->fallbackDriver->getDist($identifier);
35530 }
35531
35532 $url = sprintf(
35533 'https://bitbucket.org/%s/%s/get/%s.zip',
35534 $this->owner,
35535 $this->repository,
35536 $identifier
35537 );
35538
35539 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
35540 }
35541
35542
35543
35544
35545 public function getTags()
35546 {
35547 if ($this->fallbackDriver) {
35548 return $this->fallbackDriver->getTags();
35549 }
35550
35551 if (null === $this->tags) {
35552 $this->tags = array();
35553 $resource = sprintf(
35554 '%s?%s',
35555 $this->tagsUrl,
35556 http_build_query(
35557 array(
35558 'pagelen' => 100,
35559 'fields' => 'values.name,values.target.hash,next',
35560 'sort' => '-target.date',
35561 ),
35562 null,
35563 '&'
35564 )
35565 );
35566 $hasNext = true;
35567 while ($hasNext) {
35568 $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35569 foreach ($tagsData['values'] as $data) {
35570 $this->tags[$data['name']] = $data['target']['hash'];
35571 }
35572 if (empty($tagsData['next'])) {
35573 $hasNext = false;
35574 } else {
35575 $resource = $tagsData['next'];
35576 }
35577 }
35578 if ($this->vcsType === 'hg') {
35579 unset($this->tags['tip']);
35580 }
35581 }
35582
35583 return $this->tags;
35584 }
35585
35586
35587
35588
35589 public function getBranches()
35590 {
35591 if ($this->fallbackDriver) {
35592 return $this->fallbackDriver->getBranches();
35593 }
35594
35595 if (null === $this->branches) {
35596 $this->branches = array();
35597 $resource = sprintf(
35598 '%s?%s',
35599 $this->branchesUrl,
35600 http_build_query(
35601 array(
35602 'pagelen' => 100,
35603 'fields' => 'values.name,values.target.hash,values.heads,next',
35604 'sort' => '-target.date',
35605 ),
35606 null,
35607 '&'
35608 )
35609 );
35610 $hasNext = true;
35611 while ($hasNext) {
35612 $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35613 foreach ($branchData['values'] as $data) {
35614
35615  if ($this->vcsType === 'hg' && empty($data['heads'])) {
35616 continue;
35617 }
35618
35619 $this->branches[$data['name']] = $data['target']['hash'];
35620 }
35621 if (empty($branchData['next'])) {
35622 $hasNext = false;
35623 } else {
35624 $resource = $branchData['next'];
35625 }
35626 }
35627 }
35628
35629 return $this->branches;
35630 }
35631
35632
35633
35634
35635
35636
35637
35638
35639
35640 protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false)
35641 {
35642 try {
35643 return parent::getContents($url);
35644 } catch (TransportException $e) {
35645 $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem);
35646
35647 if (403 === $e->getCode() || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) {
35648 if (!$this->io->hasAuthentication($this->originUrl)
35649 && $bitbucketUtil->authorizeOAuth($this->originUrl)
35650 ) {
35651 return parent::getContents($url);
35652 }
35653
35654 if (!$this->io->isInteractive() && $fetchingRepoData) {
35655 return $this->attemptCloneFallback();
35656 }
35657 }
35658
35659 throw $e;
35660 }
35661 }
35662
35663
35664
35665
35666
35667
35668 abstract protected function generateSshUrl();
35669
35670 protected function attemptCloneFallback()
35671 {
35672 try {
35673 $this->setupFallbackDriver($this->generateSshUrl());
35674 } catch (\RuntimeException $e) {
35675 $this->fallbackDriver = null;
35676
35677 $this->io->writeError(
35678 '<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode'
35679 . ' so that you can enter your Bitbucket OAuth consumer credentials</error>'
35680 );
35681 throw $e;
35682 }
35683 }
35684
35685
35686
35687
35688
35689 abstract protected function setupFallbackDriver($url);
35690
35691
35692
35693
35694
35695 protected function parseCloneUrls(array $cloneLinks)
35696 {
35697 foreach ($cloneLinks as $cloneLink) {
35698 if ($cloneLink['name'] === 'https') {
35699
35700  
35701  $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']);
35702 }
35703 }
35704 }
35705
35706
35707
35708
35709 protected function getMainBranchData()
35710 {
35711 $resource = sprintf(
35712 'https://api.bitbucket.org/1.0/repositories/%s/%s/main-branch',
35713 $this->owner,
35714 $this->repository
35715 );
35716
35717 return JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35718 }
35719 }
35720 <?php
35721
35722
35723
35724
35725
35726
35727
35728
35729
35730
35731
35732 namespace Composer\Repository\Vcs;
35733
35734 use Composer\Config;
35735 use Composer\Util\ProcessExecutor;
35736 use Composer\Util\Filesystem;
35737 use Composer\IO\IOInterface;
35738
35739
35740
35741
35742 class FossilDriver extends VcsDriver
35743 {
35744 protected $tags;
35745 protected $branches;
35746 protected $rootIdentifier;
35747 protected $repoFile;
35748 protected $checkoutDir;
35749 protected $infoCache = array();
35750
35751
35752
35753
35754 public function initialize()
35755 {
35756
35757  $this->checkFossil();
35758
35759
35760  $this->config->prohibitUrlByConfig($this->url, $this->io);
35761
35762
35763  
35764  if (Filesystem::isLocalPath($this->url) && is_dir($this->url)) {
35765 $this->checkoutDir = $this->url;
35766 } else {
35767 $localName = preg_replace('{[^a-z0-9]}i', '-', $this->url);
35768 $this->repoFile = $this->config->get('cache-repo-dir') . '/' . $localName . '.fossil';
35769 $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . $localName . '/';
35770
35771 $this->updateLocalRepo();
35772 }
35773
35774 $this->getTags();
35775 $this->getBranches();
35776 }
35777
35778
35779
35780
35781 protected function checkFossil()
35782 {
35783 if (0 !== $this->process->execute('fossil version', $ignoredOutput)) {
35784 throw new \RuntimeException("fossil was not found, check that it is installed and in your PATH env.\n\n" . $this->process->getErrorOutput());
35785 }
35786 }
35787
35788
35789
35790
35791 protected function updateLocalRepo()
35792 {
35793 $fs = new Filesystem();
35794 $fs->ensureDirectoryExists($this->checkoutDir);
35795
35796 if (!is_writable(dirname($this->checkoutDir))) {
35797 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.');
35798 }
35799
35800
35801  if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) {
35802 if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) {
35803 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
35804 }
35805 } else {
35806
35807  $fs->removeDirectory($this->checkoutDir);
35808 $fs->remove($this->repoFile);
35809
35810 $fs->ensureDirectoryExists($this->checkoutDir);
35811
35812 if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
35813 $output = $this->process->getErrorOutput();
35814
35815 throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output);
35816 }
35817
35818 if (0 !== $this->process->execute(sprintf('fossil open %s', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
35819 $output = $this->process->getErrorOutput();
35820
35821 throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output);
35822 }
35823 }
35824 }
35825
35826
35827
35828
35829 public function getRootIdentifier()
35830 {
35831 if (null === $this->rootIdentifier) {
35832 $this->rootIdentifier = 'trunk';
35833 }
35834
35835 return $this->rootIdentifier;
35836 }
35837
35838
35839
35840
35841 public function getUrl()
35842 {
35843 return $this->url;
35844 }
35845
35846
35847
35848
35849 public function getSource($identifier)
35850 {
35851 return array('type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier);
35852 }
35853
35854
35855
35856
35857 public function getDist($identifier)
35858 {
35859 return null;
35860 }
35861
35862
35863
35864
35865 public function getFileContent($file, $identifier)
35866 {
35867 $command = sprintf('fossil cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
35868 $this->process->execute($command, $content, $this->checkoutDir);
35869
35870 if (!trim($content)) {
35871 return null;
35872 }
35873
35874 return $content;
35875 }
35876
35877
35878
35879
35880 public function getChangeDate($identifier)
35881 {
35882 $this->process->execute('fossil finfo -b -n 1 composer.json', $output, $this->checkoutDir);
35883 list($ckout, $date, $message) = explode(' ', trim($output), 3);
35884
35885 return new \DateTime($date, new \DateTimeZone('UTC'));
35886 }
35887
35888
35889
35890
35891 public function getTags()
35892 {
35893 if (null === $this->tags) {
35894 $tags = array();
35895
35896 $this->process->execute('fossil tag list', $output, $this->checkoutDir);
35897 foreach ($this->process->splitLines($output) as $tag) {
35898 $tags[$tag] = $tag;
35899 }
35900
35901 $this->tags = $tags;
35902 }
35903
35904 return $this->tags;
35905 }
35906
35907
35908
35909
35910 public function getBranches()
35911 {
35912 if (null === $this->branches) {
35913 $branches = array();
35914 $bookmarks = array();
35915
35916 $this->process->execute('fossil branch list', $output, $this->checkoutDir);
35917 foreach ($this->process->splitLines($output) as $branch) {
35918 $branch = trim(preg_replace('/^\*/', '', trim($branch)));
35919 $branches[$branch] = $branch;
35920 }
35921
35922 $this->branches = $branches;
35923 }
35924
35925 return $this->branches;
35926 }
35927
35928
35929
35930
35931 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35932 {
35933 if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) {
35934 return true;
35935 }
35936
35937 if (preg_match('!/fossil/|\.fossil!', $url)) {
35938 return true;
35939 }
35940
35941
35942  if (Filesystem::isLocalPath($url)) {
35943 $url = Filesystem::getPlatformPath($url);
35944 if (!is_dir($url)) {
35945 return false;
35946 }
35947
35948 $process = new ProcessExecutor();
35949
35950  if ($process->execute('fossil info', $output, $url) === 0) {
35951 return true;
35952 }
35953 }
35954
35955 return false;
35956 }
35957 }
35958 <?php
35959
35960
35961
35962
35963
35964
35965
35966
35967
35968
35969
35970 namespace Composer\Repository\Vcs;
35971
35972 use Composer\Config;
35973 use Composer\IO\IOInterface;
35974
35975
35976
35977
35978 class GitBitbucketDriver extends BitbucketDriver
35979 {
35980
35981
35982
35983 public function getRootIdentifier()
35984 {
35985 if ($this->fallbackDriver) {
35986 return $this->fallbackDriver->getRootIdentifier();
35987 }
35988
35989 if (null === $this->rootIdentifier) {
35990 if (! $this->getRepoData()) {
35991 return $this->fallbackDriver->getRootIdentifier();
35992 }
35993
35994 if ($this->vcsType !== 'git') {
35995 throw new \RuntimeException(
35996 $this->url.' does not appear to be a git repository, use '.
35997 $this->cloneHttpsUrl.' if this is a mercurial bitbucket repository'
35998 );
35999 }
36000
36001 $mainBranchData = $this->getMainBranchData();
36002 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'master';
36003 }
36004
36005 return $this->rootIdentifier;
36006 }
36007
36008
36009
36010
36011 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36012 {
36013 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url)) {
36014 return false;
36015 }
36016
36017 if (!extension_loaded('openssl')) {
36018 $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36019
36020 return false;
36021 }
36022
36023 return true;
36024 }
36025
36026
36027
36028
36029 protected function setupFallbackDriver($url)
36030 {
36031 $this->fallbackDriver = new GitDriver(
36032 array('url' => $url),
36033 $this->io,
36034 $this->config,
36035 $this->process,
36036 $this->remoteFilesystem
36037 );
36038 $this->fallbackDriver->initialize();
36039 }
36040
36041
36042
36043
36044 protected function generateSshUrl()
36045 {
36046 return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git';
36047 }
36048 }
36049 <?php
36050
36051
36052
36053
36054
36055
36056
36057
36058
36059
36060
36061 namespace Composer\Repository\Vcs;
36062
36063 use Composer\Util\ProcessExecutor;
36064 use Composer\Util\Filesystem;
36065 use Composer\Util\Git as GitUtil;
36066 use Composer\IO\IOInterface;
36067 use Composer\Cache;
36068 use Composer\Config;
36069
36070
36071
36072
36073 class GitDriver extends VcsDriver
36074 {
36075 protected $cache;
36076 protected $tags;
36077 protected $branches;
36078 protected $rootIdentifier;
36079 protected $repoDir;
36080 protected $infoCache = array();
36081
36082
36083
36084
36085 public function initialize()
36086 {
36087 if (Filesystem::isLocalPath($this->url)) {
36088 $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
36089 $this->repoDir = $this->url;
36090 $cacheUrl = realpath($this->url);
36091 } else {
36092 $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
36093
36094 GitUtil::cleanEnv();
36095
36096 $fs = new Filesystem();
36097 $fs->ensureDirectoryExists(dirname($this->repoDir));
36098
36099 if (!is_writable(dirname($this->repoDir))) {
36100 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
36101 }
36102
36103 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
36104 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.');
36105 }
36106
36107 $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
36108 if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
36109 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
36110 }
36111
36112 $cacheUrl = $this->url;
36113 }
36114
36115 $this->getTags();
36116 $this->getBranches();
36117
36118 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
36119 }
36120
36121
36122
36123
36124 public function getRootIdentifier()
36125 {
36126 if (null === $this->rootIdentifier) {
36127 $this->rootIdentifier = 'master';
36128
36129
36130  $this->process->execute('git branch --no-color', $output, $this->repoDir);
36131 $branches = $this->process->splitLines($output);
36132 if (!in_array('* master', $branches)) {
36133 foreach ($branches as $branch) {
36134 if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) {
36135 $this->rootIdentifier = $match[1];
36136 break;
36137 }
36138 }
36139 }
36140 }
36141
36142 return $this->rootIdentifier;
36143 }
36144
36145
36146
36147
36148 public function getUrl()
36149 {
36150 return $this->url;
36151 }
36152
36153
36154
36155
36156 public function getSource($identifier)
36157 {
36158 return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
36159 }
36160
36161
36162
36163
36164 public function getDist($identifier)
36165 {
36166 return null;
36167 }
36168
36169
36170
36171
36172 public function getFileContent($file, $identifier)
36173 {
36174 $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
36175 $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir);
36176
36177 if (!trim($content)) {
36178 return null;
36179 }
36180
36181 return $content;
36182 }
36183
36184
36185
36186
36187 public function getChangeDate($identifier)
36188 {
36189 $this->process->execute(sprintf(
36190 'git log -1 --format=%%at %s',
36191 ProcessExecutor::escape($identifier)
36192 ), $output, $this->repoDir);
36193
36194 return new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
36195 }
36196
36197
36198
36199
36200 public function getTags()
36201 {
36202 if (null === $this->tags) {
36203 $this->tags = array();
36204
36205 $this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir);
36206 foreach ($output = $this->process->splitLines($output) as $tag) {
36207 if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
36208 $this->tags[$match[2]] = $match[1];
36209 }
36210 }
36211 }
36212
36213 return $this->tags;
36214 }
36215
36216
36217
36218
36219 public function getBranches()
36220 {
36221 if (null === $this->branches) {
36222 $branches = array();
36223
36224 $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
36225 foreach ($this->process->splitLines($output) as $branch) {
36226 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
36227 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) {
36228 $branches[$match[1]] = $match[2];
36229 }
36230 }
36231 }
36232
36233 $this->branches = $branches;
36234 }
36235
36236 return $this->branches;
36237 }
36238
36239
36240
36241
36242 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36243 {
36244 if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
36245 return true;
36246 }
36247
36248
36249  if (Filesystem::isLocalPath($url)) {
36250 $url = Filesystem::getPlatformPath($url);
36251 if (!is_dir($url)) {
36252 return false;
36253 }
36254
36255 $process = new ProcessExecutor($io);
36256
36257  if ($process->execute('git tag', $output, $url) === 0) {
36258 return true;
36259 }
36260 }
36261
36262 if (!$deep) {
36263 return false;
36264 }
36265
36266 $process = new ProcessExecutor($io);
36267
36268 return $process->execute('git ls-remote --heads ' . ProcessExecutor::escape($url), $output) === 0;
36269 }
36270 }
36271 <?php
36272
36273
36274
36275
36276
36277
36278
36279
36280
36281
36282
36283 namespace Composer\Repository\Vcs;
36284
36285 use Composer\Config;
36286 use Composer\Downloader\TransportException;
36287 use Composer\Json\JsonFile;
36288 use Composer\Cache;
36289 use Composer\IO\IOInterface;
36290 use Composer\Util\GitHub;
36291
36292
36293
36294
36295 class GitHubDriver extends VcsDriver
36296 {
36297 protected $cache;
36298 protected $owner;
36299 protected $repository;
36300 protected $tags;
36301 protected $branches;
36302 protected $rootIdentifier;
36303 protected $repoData;
36304 protected $hasIssues;
36305 protected $infoCache = array();
36306 protected $isPrivate = false;
36307
36308
36309
36310
36311
36312
36313 protected $gitDriver;
36314
36315
36316
36317
36318 public function initialize()
36319 {
36320 preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
36321 $this->owner = $match[3];
36322 $this->repository = $match[4];
36323 $this->originUrl = !empty($match[1]) ? $match[1] : $match[2];
36324 if ($this->originUrl === 'www.github.com') {
36325 $this->originUrl = 'github.com';
36326 }
36327 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
36328
36329 if (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api']) {
36330 $this->setupGitDriver($this->url);
36331
36332 return;
36333 }
36334
36335 $this->fetchRootIdentifier();
36336 }
36337
36338 public function getRepositoryUrl()
36339 {
36340 return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
36341 }
36342
36343
36344
36345
36346 public function getRootIdentifier()
36347 {
36348 if ($this->gitDriver) {
36349 return $this->gitDriver->getRootIdentifier();
36350 }
36351
36352 return $this->rootIdentifier;
36353 }
36354
36355
36356
36357
36358 public function getUrl()
36359 {
36360 if ($this->gitDriver) {
36361 return $this->gitDriver->getUrl();
36362 }
36363
36364 return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
36365 }
36366
36367
36368
36369
36370 protected function getApiUrl()
36371 {
36372 if ('github.com' === $this->originUrl) {
36373 $apiUrl = 'api.github.com';
36374 } else {
36375 $apiUrl = $this->originUrl . '/api/v3';
36376 }
36377
36378 return 'https://' . $apiUrl;
36379 }
36380
36381
36382
36383
36384 public function getSource($identifier)
36385 {
36386 if ($this->gitDriver) {
36387 return $this->gitDriver->getSource($identifier);
36388 }
36389 if ($this->isPrivate) {
36390
36391  
36392  $url = $this->generateSshUrl();
36393 } else {
36394 $url = $this->getUrl();
36395 }
36396
36397 return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
36398 }
36399
36400
36401
36402
36403 public function getDist($identifier)
36404 {
36405 $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
36406
36407 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
36408 }
36409
36410
36411
36412
36413 public function getComposerInformation($identifier)
36414 {
36415 if ($this->gitDriver) {
36416 return $this->gitDriver->getComposerInformation($identifier);
36417 }
36418
36419 if (!isset($this->infoCache[$identifier])) {
36420 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
36421 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
36422 }
36423
36424 $composer = $this->getBaseComposerInformation($identifier);
36425 if ($composer) {
36426
36427
36428  if (!isset($composer['support']['source'])) {
36429 $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
36430 $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
36431 }
36432 if (!isset($composer['support']['issues']) && $this->hasIssues) {
36433 $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
36434 }
36435 }
36436
36437 if ($this->shouldCache($identifier)) {
36438 $this->cache->write($identifier, json_encode($composer));
36439 }
36440
36441 $this->infoCache[$identifier] = $composer;
36442 }
36443
36444 return $this->infoCache[$identifier];
36445 }
36446
36447
36448
36449
36450 public function getFileContent($file, $identifier)
36451 {
36452 if ($this->gitDriver) {
36453 return $this->gitDriver->getFileContent($file, $identifier);
36454 }
36455
36456 $notFoundRetries = 2;
36457 while ($notFoundRetries) {
36458 try {
36459 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
36460 $resource = JsonFile::parseJson($this->getContents($resource));
36461 if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
36462 throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
36463 }
36464
36465 return $content;
36466 } catch (TransportException $e) {
36467 if (404 !== $e->getCode()) {
36468 throw $e;
36469 }
36470
36471
36472  
36473  $notFoundRetries--;
36474
36475 return null;
36476 }
36477 }
36478
36479 return null;
36480 }
36481
36482
36483
36484
36485 public function getChangeDate($identifier)
36486 {
36487 if ($this->gitDriver) {
36488 return $this->gitDriver->getChangeDate($identifier);
36489 }
36490
36491 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
36492 $commit = JsonFile::parseJson($this->getContents($resource), $resource);
36493
36494 return new \DateTime($commit['commit']['committer']['date']);
36495 }
36496
36497
36498
36499
36500 public function getTags()
36501 {
36502 if ($this->gitDriver) {
36503 return $this->gitDriver->getTags();
36504 }
36505 if (null === $this->tags) {
36506 $this->tags = array();
36507 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
36508
36509 do {
36510 $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
36511 foreach ($tagsData as $tag) {
36512 $this->tags[$tag['name']] = $tag['commit']['sha'];
36513 }
36514
36515 $resource = $this->getNextPage();
36516 } while ($resource);
36517 }
36518
36519 return $this->tags;
36520 }
36521
36522
36523
36524
36525 public function getBranches()
36526 {
36527 if ($this->gitDriver) {
36528 return $this->gitDriver->getBranches();
36529 }
36530 if (null === $this->branches) {
36531 $this->branches = array();
36532 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
36533
36534 $branchBlacklist = array('gh-pages');
36535
36536 do {
36537 $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
36538 foreach ($branchData as $branch) {
36539 $name = substr($branch['ref'], 11);
36540 if (!in_array($name, $branchBlacklist)) {
36541 $this->branches[$name] = $branch['object']['sha'];
36542 }
36543 }
36544
36545 $resource = $this->getNextPage();
36546 } while ($resource);
36547 }
36548
36549 return $this->branches;
36550 }
36551
36552
36553
36554
36555 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36556 {
36557 if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
36558 return false;
36559 }
36560
36561 $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
36562 if (!in_array(preg_replace('{^www\.}i', '', $originUrl), $config->get('github-domains'))) {
36563 return false;
36564 }
36565
36566 if (!extension_loaded('openssl')) {
36567 $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36568
36569 return false;
36570 }
36571
36572 return true;
36573 }
36574
36575
36576
36577
36578
36579
36580 public function getRepoData()
36581 {
36582 $this->fetchRootIdentifier();
36583
36584 return $this->repoData;
36585 }
36586
36587
36588
36589
36590
36591
36592 protected function generateSshUrl()
36593 {
36594 return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
36595 }
36596
36597
36598
36599
36600 protected function getContents($url, $fetchingRepoData = false)
36601 {
36602 try {
36603 return parent::getContents($url);
36604 } catch (TransportException $e) {
36605 $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
36606
36607 switch ($e->getCode()) {
36608 case 401:
36609 case 404:
36610
36611  if (!$fetchingRepoData) {
36612 throw $e;
36613 }
36614
36615 if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
36616 return parent::getContents($url);
36617 }
36618
36619 if (!$this->io->isInteractive()) {
36620 return $this->attemptCloneFallback();
36621 }
36622
36623 $scopesIssued = array();
36624 $scopesNeeded = array();
36625 if ($headers = $e->getHeaders()) {
36626 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-OAuth-Scopes')) {
36627 $scopesIssued = explode(' ', $scopes);
36628 }
36629 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
36630 $scopesNeeded = explode(' ', $scopes);
36631 }
36632 }
36633 $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
36634
36635  
36636  if (!$headers || !count($scopesNeeded) || count($scopesFailed)) {
36637 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
36638 }
36639
36640 return parent::getContents($url);
36641
36642 case 403:
36643 if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
36644 return parent::getContents($url);
36645 }
36646
36647 if (!$this->io->isInteractive() && $fetchingRepoData) {
36648 return $this->attemptCloneFallback();
36649 }
36650
36651 $rateLimited = false;
36652 foreach ($e->getHeaders() as $header) {
36653 if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
36654 $rateLimited = true;
36655 }
36656 }
36657
36658 if (!$this->io->hasAuthentication($this->originUrl)) {
36659 if (!$this->io->isInteractive()) {
36660 $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>');
36661 throw $e;
36662 }
36663
36664 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>'.$this->url.'</info>)');
36665
36666 return parent::getContents($url);
36667 }
36668
36669 if ($rateLimited) {
36670 $rateLimit = $this->getRateLimit($e->getHeaders());
36671 $this->io->writeError(sprintf(
36672 '<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>',
36673 $rateLimit['limit'],
36674 $rateLimit['reset']
36675 ));
36676 }
36677
36678 throw $e;
36679
36680 default:
36681 throw $e;
36682 }
36683 }
36684 }
36685
36686
36687
36688
36689
36690
36691
36692
36693 protected function getRateLimit(array $headers)
36694 {
36695 $rateLimit = array(
36696 'limit' => '?',
36697 'reset' => '?',
36698 );
36699
36700 foreach ($headers as $header) {
36701 $header = trim($header);
36702 if (false === strpos($header, 'X-RateLimit-')) {
36703 continue;
36704 }
36705 list($type, $value) = explode(':', $header, 2);
36706 switch ($type) {
36707 case 'X-RateLimit-Limit':
36708 $rateLimit['limit'] = (int) trim($value);
36709 break;
36710 case 'X-RateLimit-Reset':
36711 $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
36712 break;
36713 }
36714 }
36715
36716 return $rateLimit;
36717 }
36718
36719
36720
36721
36722
36723
36724 protected function fetchRootIdentifier()
36725 {
36726 if ($this->repoData) {
36727 return;
36728 }
36729
36730 $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
36731
36732 $this->repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
36733 if (null === $this->repoData && null !== $this->gitDriver) {
36734 return;
36735 }
36736
36737 $this->owner = $this->repoData['owner']['login'];
36738 $this->repository = $this->repoData['name'];
36739
36740 $this->isPrivate = !empty($this->repoData['private']);
36741 if (isset($this->repoData['default_branch'])) {
36742 $this->rootIdentifier = $this->repoData['default_branch'];
36743 } elseif (isset($this->repoData['master_branch'])) {
36744 $this->rootIdentifier = $this->repoData['master_branch'];
36745 } else {
36746 $this->rootIdentifier = 'master';
36747 }
36748 $this->hasIssues = !empty($this->repoData['has_issues']);
36749 }
36750
36751 protected function attemptCloneFallback()
36752 {
36753 $this->isPrivate = true;
36754
36755 try {
36756
36757  
36758  
36759  
36760  $this->setupGitDriver($this->generateSshUrl());
36761
36762 return;
36763 } catch (\RuntimeException $e) {
36764 $this->gitDriver = null;
36765
36766 $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>');
36767 throw $e;
36768 }
36769 }
36770
36771 protected function setupGitDriver($url)
36772 {
36773 $this->gitDriver = new GitDriver(
36774 array('url' => $url),
36775 $this->io,
36776 $this->config,
36777 $this->process,
36778 $this->remoteFilesystem
36779 );
36780 $this->gitDriver->initialize();
36781 }
36782
36783 protected function getNextPage()
36784 {
36785 $headers = $this->remoteFilesystem->getLastHeaders();
36786 foreach ($headers as $header) {
36787 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
36788 $links = explode(',', $match[1]);
36789 foreach ($links as $link) {
36790 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
36791 return $match[1];
36792 }
36793 }
36794 }
36795 }
36796 }
36797 }
36798 <?php
36799
36800
36801
36802
36803
36804
36805
36806
36807
36808
36809
36810 namespace Composer\Repository\Vcs;
36811
36812 use Composer\Config;
36813 use Composer\Cache;
36814 use Composer\IO\IOInterface;
36815 use Composer\Json\JsonFile;
36816 use Composer\Downloader\TransportException;
36817 use Composer\Util\RemoteFilesystem;
36818 use Composer\Util\GitLab;
36819
36820
36821
36822
36823
36824
36825
36826 class GitLabDriver extends VcsDriver
36827 {
36828 private $scheme;
36829 private $namespace;
36830 private $repository;
36831
36832
36833
36834
36835 private $project;
36836
36837
36838
36839
36840 private $commits = array();
36841
36842
36843
36844
36845 private $tags;
36846
36847
36848
36849
36850 private $branches;
36851
36852
36853
36854
36855
36856
36857 protected $gitDriver;
36858
36859
36860
36861
36862
36863
36864 private $isPrivate = true;
36865
36866
36867
36868
36869 protected $portNumber;
36870
36871 const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)(?::(?P<port>[0-9]+))?/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
36872
36873
36874
36875
36876
36877
36878
36879
36880 public function initialize()
36881 {
36882 if (!preg_match(self::URL_REGEX, $this->url, $match)) {
36883 throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
36884 }
36885
36886 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
36887 $configuredDomains = $this->config->get('gitlab-domains');
36888 $urlParts = explode('/', $match['parts']);
36889
36890 $this->scheme = !empty($match['scheme'])
36891 ? $match['scheme']
36892 : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https')
36893 ;
36894 $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts);
36895
36896 if (!empty($match['port']) && true === is_numeric($match['port'])) {
36897
36898  $this->portNumber = (int) $match['port'];
36899 }
36900
36901 $this->namespace = implode('/', $urlParts);
36902 $this->repository = preg_replace('#(\.git)$#', '', $match['repo']);
36903
36904 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository);
36905
36906 $this->fetchProject();
36907 }
36908
36909
36910
36911
36912
36913
36914
36915 public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
36916 {
36917 $this->remoteFilesystem = $remoteFilesystem;
36918 }
36919
36920
36921
36922
36923 public function getFileContent($file, $identifier)
36924 {
36925 if ($this->gitDriver) {
36926 return $this->gitDriver->getFileContent($file, $identifier);
36927 }
36928
36929
36930  if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
36931 $branches = $this->getBranches();
36932 if (isset($branches[$identifier])) {
36933 $identifier = $branches[$identifier];
36934 }
36935 }
36936
36937 $resource = $this->getApiUrl().'/repository/files/'.$this->urlEncodeAll($file).'/raw?ref='.$identifier;
36938
36939 try {
36940 $content = $this->getContents($resource);
36941 } catch (TransportException $e) {
36942 if ($e->getCode() !== 404) {
36943 throw $e;
36944 }
36945
36946 return null;
36947 }
36948
36949 return $content;
36950 }
36951
36952
36953
36954
36955 public function getChangeDate($identifier)
36956 {
36957 if ($this->gitDriver) {
36958 return $this->gitDriver->getChangeDate($identifier);
36959 }
36960
36961 if (isset($this->commits[$identifier])) {
36962 return new \DateTime($this->commits[$identifier]['committed_date']);
36963 }
36964
36965 return new \DateTime();
36966 }
36967
36968
36969
36970
36971 public function getRepositoryUrl()
36972 {
36973 return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
36974 }
36975
36976
36977
36978
36979 public function getUrl()
36980 {
36981 if ($this->gitDriver) {
36982 return $this->gitDriver->getUrl();
36983 }
36984
36985 return $this->project['web_url'];
36986 }
36987
36988
36989
36990
36991 public function getDist($identifier)
36992 {
36993 $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
36994
36995 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
36996 }
36997
36998
36999
37000
37001 public function getSource($identifier)
37002 {
37003 if ($this->gitDriver) {
37004 return $this->gitDriver->getSource($identifier);
37005 }
37006
37007 return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
37008 }
37009
37010
37011
37012
37013 public function getRootIdentifier()
37014 {
37015 if ($this->gitDriver) {
37016 return $this->gitDriver->getRootIdentifier();
37017 }
37018
37019 return $this->project['default_branch'];
37020 }
37021
37022
37023
37024
37025 public function getBranches()
37026 {
37027 if ($this->gitDriver) {
37028 return $this->gitDriver->getBranches();
37029 }
37030
37031 if (!$this->branches) {
37032 $this->branches = $this->getReferences('branches');
37033 }
37034
37035 return $this->branches;
37036 }
37037
37038
37039
37040
37041 public function getTags()
37042 {
37043 if ($this->gitDriver) {
37044 return $this->gitDriver->getTags();
37045 }
37046
37047 if (!$this->tags) {
37048 $this->tags = $this->getReferences('tags');
37049 }
37050
37051 return $this->tags;
37052 }
37053
37054
37055
37056
37057 public function getApiUrl()
37058 {
37059 $domainName = $this->originUrl;
37060 $portNumber = (true === is_numeric($this->portNumber)) ? sprintf(':%s', $this->portNumber) : '';
37061
37062 return $this->scheme.'://'.$domainName.$portNumber.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository);
37063 }
37064
37065
37066
37067
37068
37069
37070
37071 private function urlEncodeAll($string)
37072 {
37073 $encoded = '';
37074 for ($i = 0; isset($string[$i]); $i++) {
37075 $character = $string[$i];
37076 if (!ctype_alnum($character) && !in_array($character, array('-', '_'), true)) {
37077 $character = '%' . sprintf('%02X', ord($character));
37078 }
37079 $encoded .= $character;
37080 }
37081
37082 return $encoded;
37083 }
37084
37085
37086
37087
37088
37089
37090 protected function getReferences($type)
37091 {
37092 $perPage = 100;
37093 $resource = $this->getApiUrl().'/repository/'.$type.'?per_page='.$perPage;
37094
37095 $references = array();
37096 do {
37097 $data = JsonFile::parseJson($this->getContents($resource), $resource);
37098
37099 foreach ($data as $datum) {
37100 $references[$datum['name']] = $datum['commit']['id'];
37101
37102
37103  
37104  $this->commits[$datum['commit']['id']] = $datum['commit'];
37105 }
37106
37107 if (count($data) >= $perPage) {
37108 $resource = $this->getNextPage();
37109 } else {
37110 $resource = false;
37111 }
37112 } while ($resource);
37113
37114 return $references;
37115 }
37116
37117 protected function fetchProject()
37118 {
37119
37120  $resource = $this->getApiUrl();
37121 $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
37122 if (isset($this->project['visibility'])) {
37123 $this->isPrivate = $this->project['visibility'] !== 'public';
37124 } else {
37125
37126  $this->isPrivate = false;
37127 }
37128 }
37129
37130 protected function attemptCloneFallback()
37131 {
37132 try {
37133 if ($this->isPrivate === false) {
37134 $url = $this->generatePublicUrl();
37135 } else {
37136 $url = $this->generateSshUrl();
37137 }
37138
37139
37140  
37141  
37142  $this->setupGitDriver($url);
37143
37144 return;
37145 } catch (\RuntimeException $e) {
37146 $this->gitDriver = null;
37147
37148 $this->io->writeError('<error>Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials</error>');
37149 throw $e;
37150 }
37151 }
37152
37153
37154
37155
37156
37157
37158 protected function generateSshUrl()
37159 {
37160 return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git';
37161 }
37162
37163 protected function generatePublicUrl()
37164 {
37165 return $this->scheme . '://' . $this->originUrl . '/'.$this->namespace.'/'.$this->repository.'.git';
37166 }
37167
37168 protected function setupGitDriver($url)
37169 {
37170 $this->gitDriver = new GitDriver(
37171 array('url' => $url),
37172 $this->io,
37173 $this->config,
37174 $this->process,
37175 $this->remoteFilesystem
37176 );
37177 $this->gitDriver->initialize();
37178 }
37179
37180
37181
37182
37183 protected function getContents($url, $fetchingRepoData = false)
37184 {
37185 try {
37186 $res = parent::getContents($url);
37187
37188 if ($fetchingRepoData) {
37189 $json = JsonFile::parseJson($res, $url);
37190
37191
37192  if (!isset($json['default_branch'])) {
37193 if (!empty($json['id'])) {
37194 $this->isPrivate = false;
37195 }
37196
37197 throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
37198 }
37199 }
37200
37201 return $res;
37202 } catch (TransportException $e) {
37203 $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);
37204
37205 switch ($e->getCode()) {
37206 case 401:
37207 case 404:
37208
37209  if (!$fetchingRepoData) {
37210 throw $e;
37211 }
37212
37213 if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
37214 return parent::getContents($url);
37215 }
37216
37217 if (!$this->io->isInteractive()) {
37218 return $this->attemptCloneFallback();
37219 }
37220 $this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
37221 $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
37222
37223 return parent::getContents($url);
37224
37225 case 403:
37226 if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
37227 return parent::getContents($url);
37228 }
37229
37230 if (!$this->io->isInteractive() && $fetchingRepoData) {
37231 return $this->attemptCloneFallback();
37232 }
37233
37234 throw $e;
37235
37236 default:
37237 throw $e;
37238 }
37239 }
37240 }
37241
37242
37243
37244
37245
37246
37247
37248 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37249 {
37250 if (!preg_match(self::URL_REGEX, $url, $match)) {
37251 return false;
37252 }
37253
37254 $scheme = !empty($match['scheme']) ? $match['scheme'] : null;
37255 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
37256 $urlParts = explode('/', $match['parts']);
37257
37258 if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts)) {
37259 return false;
37260 }
37261
37262 if ('https' === $scheme && !extension_loaded('openssl')) {
37263 $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
37264
37265 return false;
37266 }
37267
37268 return true;
37269 }
37270
37271 private function getNextPage()
37272 {
37273 $headers = $this->remoteFilesystem->getLastHeaders();
37274 foreach ($headers as $header) {
37275 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
37276 $links = explode(',', $match[1]);
37277 foreach ($links as $link) {
37278 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
37279 return $match[1];
37280 }
37281 }
37282 }
37283 }
37284 }
37285
37286
37287
37288
37289
37290
37291
37292 private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts)
37293 {
37294 if (in_array($guessedDomain, $configuredDomains)) {
37295 return $guessedDomain;
37296 }
37297
37298 while (null !== ($part = array_shift($urlParts))) {
37299 $guessedDomain .= '/' . $part;
37300
37301 if (in_array($guessedDomain, $configuredDomains)) {
37302 return $guessedDomain;
37303 }
37304 }
37305
37306 return false;
37307 }
37308 }
37309 <?php
37310
37311
37312
37313
37314
37315
37316
37317
37318
37319
37320
37321 namespace Composer\Repository\Vcs;
37322
37323 use Composer\Config;
37324 use Composer\IO\IOInterface;
37325
37326
37327
37328
37329 class HgBitbucketDriver extends BitbucketDriver
37330 {
37331
37332
37333
37334 public function getRootIdentifier()
37335 {
37336 if ($this->fallbackDriver) {
37337 return $this->fallbackDriver->getRootIdentifier();
37338 }
37339
37340 if (null === $this->rootIdentifier) {
37341 if (! $this->getRepoData()) {
37342 return $this->fallbackDriver->getRootIdentifier();
37343 }
37344
37345 if ($this->vcsType !== 'hg') {
37346 throw new \RuntimeException(
37347 $this->url.' does not appear to be a mercurial repository, use '.
37348 $this->cloneHttpsUrl.' if this is a git bitbucket repository'
37349 );
37350 }
37351
37352 $mainBranchData = $this->getMainBranchData();
37353 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'default';
37354 }
37355
37356 return $this->rootIdentifier;
37357 }
37358
37359
37360
37361
37362 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37363 {
37364 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url)) {
37365 return false;
37366 }
37367
37368 if (!extension_loaded('openssl')) {
37369 $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
37370
37371 return false;
37372 }
37373
37374 return true;
37375 }
37376
37377
37378
37379
37380 protected function setupFallbackDriver($url)
37381 {
37382 $this->fallbackDriver = new HgDriver(
37383 array('url' => $url),
37384 $this->io,
37385 $this->config,
37386 $this->process,
37387 $this->remoteFilesystem
37388 );
37389 $this->fallbackDriver->initialize();
37390 }
37391
37392
37393
37394
37395 protected function generateSshUrl()
37396 {
37397 return 'ssh://hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository;
37398 }
37399 }
37400 <?php
37401
37402
37403
37404
37405
37406
37407
37408
37409
37410
37411
37412 namespace Composer\Repository\Vcs;
37413
37414 use Composer\Config;
37415 use Composer\Util\ProcessExecutor;
37416 use Composer\Util\Filesystem;
37417 use Composer\IO\IOInterface;
37418
37419
37420
37421
37422 class HgDriver extends VcsDriver
37423 {
37424 protected $tags;
37425 protected $branches;
37426 protected $rootIdentifier;
37427 protected $repoDir;
37428 protected $infoCache = array();
37429
37430
37431
37432
37433 public function initialize()
37434 {
37435 if (Filesystem::isLocalPath($this->url)) {
37436 $this->repoDir = $this->url;
37437 } else {
37438 $cacheDir = $this->config->get('cache-vcs-dir');
37439 $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
37440
37441 $fs = new Filesystem();
37442 $fs->ensureDirectoryExists($cacheDir);
37443
37444 if (!is_writable(dirname($this->repoDir))) {
37445 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.');
37446 }
37447
37448
37449  $this->config->prohibitUrlByConfig($this->url, $this->io);
37450
37451
37452  if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) {
37453 if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) {
37454 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
37455 }
37456 } else {
37457
37458  $fs->removeDirectory($this->repoDir);
37459
37460 if (0 !== $this->process->execute(sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoDir)), $output, $cacheDir)) {
37461 $output = $this->process->getErrorOutput();
37462
37463 if (0 !== $this->process->execute('hg --version', $ignoredOutput)) {
37464 throw new \RuntimeException('Failed to clone '.$this->url.', hg was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput());
37465 }
37466
37467 throw new \RuntimeException('Failed to clone '.$this->url.', could not read packages from it' . "\n\n" .$output);
37468 }
37469 }
37470 }
37471
37472 $this->getTags();
37473 $this->getBranches();
37474 }
37475
37476
37477
37478
37479 public function getRootIdentifier()
37480 {
37481 if (null === $this->rootIdentifier) {
37482 $this->process->execute(sprintf('hg tip --template "{node}"'), $output, $this->repoDir);
37483 $output = $this->process->splitLines($output);
37484 $this->rootIdentifier = $output[0];
37485 }
37486
37487 return $this->rootIdentifier;
37488 }
37489
37490
37491
37492
37493 public function getUrl()
37494 {
37495 return $this->url;
37496 }
37497
37498
37499
37500
37501 public function getSource($identifier)
37502 {
37503 return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
37504 }
37505
37506
37507
37508
37509 public function getDist($identifier)
37510 {
37511 return null;
37512 }
37513
37514
37515
37516
37517 public function getFileContent($file, $identifier)
37518 {
37519 $resource = sprintf('hg cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
37520 $this->process->execute($resource, $content, $this->repoDir);
37521
37522 if (!trim($content)) {
37523 return;
37524 }
37525
37526 return $content;
37527 }
37528
37529
37530
37531
37532 public function getChangeDate($identifier)
37533 {
37534 $this->process->execute(
37535 sprintf(
37536 'hg log --template "{date|rfc3339date}" -r %s',
37537 ProcessExecutor::escape($identifier)
37538 ),
37539 $output,
37540 $this->repoDir
37541 );
37542
37543 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
37544 }
37545
37546
37547
37548
37549 public function getTags()
37550 {
37551 if (null === $this->tags) {
37552 $tags = array();
37553
37554 $this->process->execute('hg tags', $output, $this->repoDir);
37555 foreach ($this->process->splitLines($output) as $tag) {
37556 if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
37557 $tags[$match[1]] = $match[2];
37558 }
37559 }
37560 unset($tags['tip']);
37561
37562 $this->tags = $tags;
37563 }
37564
37565 return $this->tags;
37566 }
37567
37568
37569
37570
37571 public function getBranches()
37572 {
37573 if (null === $this->branches) {
37574 $branches = array();
37575 $bookmarks = array();
37576
37577 $this->process->execute('hg branches', $output, $this->repoDir);
37578 foreach ($this->process->splitLines($output) as $branch) {
37579 if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) {
37580 $branches[$match[1]] = $match[2];
37581 }
37582 }
37583
37584 $this->process->execute('hg bookmarks', $output, $this->repoDir);
37585 foreach ($this->process->splitLines($output) as $branch) {
37586 if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) {
37587 $bookmarks[$match[1]] = $match[2];
37588 }
37589 }
37590
37591
37592  $this->branches = array_merge($bookmarks, $branches);
37593 }
37594
37595 return $this->branches;
37596 }
37597
37598
37599
37600
37601 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37602 {
37603 if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
37604 return true;
37605 }
37606
37607
37608  if (Filesystem::isLocalPath($url)) {
37609 $url = Filesystem::getPlatformPath($url);
37610 if (!is_dir($url)) {
37611 return false;
37612 }
37613
37614 $process = new ProcessExecutor();
37615
37616  if ($process->execute('hg summary', $output, $url) === 0) {
37617 return true;
37618 }
37619 }
37620
37621 if (!$deep) {
37622 return false;
37623 }
37624
37625 $processExecutor = new ProcessExecutor();
37626 $exit = $processExecutor->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);
37627
37628 return $exit === 0;
37629 }
37630 }
37631 <?php
37632
37633
37634
37635
37636
37637
37638
37639
37640
37641
37642
37643 namespace Composer\Repository\Vcs;
37644
37645 use Composer\Config;
37646 use Composer\IO\IOInterface;
37647 use Composer\Util\ProcessExecutor;
37648 use Composer\Util\Perforce;
37649
37650
37651
37652
37653 class PerforceDriver extends VcsDriver
37654 {
37655 protected $depot;
37656 protected $branch;
37657
37658 protected $perforce;
37659
37660
37661
37662
37663 public function initialize()
37664 {
37665 $this->depot = $this->repoConfig['depot'];
37666 $this->branch = '';
37667 if (!empty($this->repoConfig['branch'])) {
37668 $this->branch = $this->repoConfig['branch'];
37669 }
37670
37671 $this->initPerforce($this->repoConfig);
37672 $this->perforce->p4Login();
37673 $this->perforce->checkStream();
37674
37675 $this->perforce->writeP4ClientSpec();
37676 $this->perforce->connectClient();
37677
37678 return true;
37679 }
37680
37681 private function initPerforce($repoConfig)
37682 {
37683 if (!empty($this->perforce)) {
37684 return;
37685 }
37686
37687 $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
37688 $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
37689 }
37690
37691
37692
37693
37694 public function getFileContent($file, $identifier)
37695 {
37696 return $this->perforce->getFileContent($file, $identifier);
37697 }
37698
37699
37700
37701
37702 public function getChangeDate($identifier)
37703 {
37704 return null;
37705 }
37706
37707
37708
37709
37710 public function getRootIdentifier()
37711 {
37712 return $this->branch;
37713 }
37714
37715
37716
37717
37718 public function getBranches()
37719 {
37720 return $this->perforce->getBranches();
37721 }
37722
37723
37724
37725
37726 public function getTags()
37727 {
37728 return $this->perforce->getTags();
37729 }
37730
37731
37732
37733
37734 public function getDist($identifier)
37735 {
37736 return null;
37737 }
37738
37739
37740
37741
37742 public function getSource($identifier)
37743 {
37744 $source = array(
37745 'type' => 'perforce',
37746 'url' => $this->repoConfig['url'],
37747 'reference' => $identifier,
37748 'p4user' => $this->perforce->getUser(),
37749 );
37750
37751 return $source;
37752 }
37753
37754
37755
37756
37757 public function getUrl()
37758 {
37759 return $this->url;
37760 }
37761
37762
37763
37764
37765 public function hasComposerFile($identifier)
37766 {
37767 $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
37768 $composerInfoIdentifier = $identifier;
37769
37770 return !empty($composerInfo);
37771 }
37772
37773
37774
37775
37776 public function getContents($url)
37777 {
37778 return false;
37779 }
37780
37781
37782
37783
37784 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37785 {
37786 if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) {
37787 return Perforce::checkServerExists($url, new ProcessExecutor($io));
37788 }
37789
37790 return false;
37791 }
37792
37793
37794
37795
37796 public function cleanup()
37797 {
37798 $this->perforce->cleanupClientSpec();
37799 $this->perforce = null;
37800 }
37801
37802 public function getDepot()
37803 {
37804 return $this->depot;
37805 }
37806
37807 public function getBranch()
37808 {
37809 return $this->branch;
37810 }
37811 }
37812 <?php
37813
37814
37815
37816
37817
37818
37819
37820
37821
37822
37823
37824 namespace Composer\Repository\Vcs;
37825
37826 use Composer\Cache;
37827 use Composer\Config;
37828 use Composer\Json\JsonFile;
37829 use Composer\Util\ProcessExecutor;
37830 use Composer\Util\Filesystem;
37831 use Composer\Util\Svn as SvnUtil;
37832 use Composer\IO\IOInterface;
37833 use Composer\Downloader\TransportException;
37834
37835
37836
37837
37838
37839 class SvnDriver extends VcsDriver
37840 {
37841
37842
37843
37844 protected $cache;
37845 protected $baseUrl;
37846 protected $tags;
37847 protected $branches;
37848 protected $rootIdentifier;
37849 protected $infoCache = array();
37850
37851 protected $trunkPath = 'trunk';
37852 protected $branchesPath = 'branches';
37853 protected $tagsPath = 'tags';
37854 protected $packagePath = '';
37855 protected $cacheCredentials = true;
37856
37857
37858
37859
37860 private $util;
37861
37862
37863
37864
37865 public function initialize()
37866 {
37867 $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
37868
37869 SvnUtil::cleanEnv();
37870
37871 if (isset($this->repoConfig['trunk-path'])) {
37872 $this->trunkPath = $this->repoConfig['trunk-path'];
37873 }
37874 if (isset($this->repoConfig['branches-path'])) {
37875 $this->branchesPath = $this->repoConfig['branches-path'];
37876 }
37877 if (isset($this->repoConfig['tags-path'])) {
37878 $this->tagsPath = $this->repoConfig['tags-path'];
37879 }
37880 if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
37881 $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
37882 }
37883 if (isset($this->repoConfig['package-path'])) {
37884 $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
37885 }
37886
37887 if (false !== ($pos = strrpos($this->url, '/' . $this->trunkPath))) {
37888 $this->baseUrl = substr($this->url, 0, $pos);
37889 }
37890
37891 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl));
37892
37893 $this->getBranches();
37894 $this->getTags();
37895 }
37896
37897
37898
37899
37900 public function getRootIdentifier()
37901 {
37902 return $this->rootIdentifier ?: $this->trunkPath;
37903 }
37904
37905
37906
37907
37908 public function getUrl()
37909 {
37910 return $this->url;
37911 }
37912
37913
37914
37915
37916 public function getSource($identifier)
37917 {
37918 return array('type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier);
37919 }
37920
37921
37922
37923
37924 public function getDist($identifier)
37925 {
37926 return null;
37927 }
37928
37929
37930
37931
37932 public function getComposerInformation($identifier)
37933 {
37934 if (!isset($this->infoCache[$identifier])) {
37935 if ($res = $this->cache->read($identifier.'.json')) {
37936 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37937 }
37938
37939 $composer = $this->getBaseComposerInformation($identifier);
37940
37941 $this->cache->write($identifier.'.json', json_encode($composer));
37942
37943 $this->infoCache[$identifier] = $composer;
37944 }
37945
37946 return $this->infoCache[$identifier];
37947 }
37948
37949
37950
37951
37952
37953 public function getFileContent($file, $identifier)
37954 {
37955 $identifier = '/' . trim($identifier, '/') . '/';
37956
37957 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
37958 if (!empty($match[2])) {
37959 $path = $match[1];
37960 $rev = $match[2];
37961 } else {
37962 $path = $identifier;
37963 $rev = '';
37964 }
37965
37966 try {
37967 $resource = $path.$file;
37968 $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
37969 if (!trim($output)) {
37970 return null;
37971 }
37972 } catch (\RuntimeException $e) {
37973 throw new TransportException($e->getMessage());
37974 }
37975
37976 return $output;
37977 }
37978
37979
37980
37981
37982 public function getChangeDate($identifier)
37983 {
37984 $identifier = '/' . trim($identifier, '/') . '/';
37985
37986 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
37987 if (!empty($match[2])) {
37988 $path = $match[1];
37989 $rev = $match[2];
37990 } else {
37991 $path = $identifier;
37992 $rev = '';
37993 }
37994
37995 $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
37996 foreach ($this->process->splitLines($output) as $line) {
37997 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
37998 return new \DateTime($match[1], new \DateTimeZone('UTC'));
37999 }
38000 }
38001
38002 return null;
38003 }
38004
38005
38006
38007
38008 public function getTags()
38009 {
38010 if (null === $this->tags) {
38011 $this->tags = array();
38012
38013 if ($this->tagsPath !== false) {
38014 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
38015 if ($output) {
38016 foreach ($this->process->splitLines($output) as $line) {
38017 $line = trim($line);
38018 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
38019 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
38020 $this->tags[rtrim($match[2], '/')] = $this->buildIdentifier(
38021 '/' . $this->tagsPath . '/' . $match[2],
38022 $match[1]
38023 );
38024 }
38025 }
38026 }
38027 }
38028 }
38029 }
38030
38031 return $this->tags;
38032 }
38033
38034
38035
38036
38037 public function getBranches()
38038 {
38039 if (null === $this->branches) {
38040 $this->branches = array();
38041
38042 if (false === $this->trunkPath) {
38043 $trunkParent = $this->baseUrl . '/';
38044 } else {
38045 $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
38046 }
38047
38048 $output = $this->execute('svn ls --verbose', $trunkParent);
38049 if ($output) {
38050 foreach ($this->process->splitLines($output) as $line) {
38051 $line = trim($line);
38052 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
38053 if (isset($match[1]) && isset($match[2]) && $match[2] === './') {
38054 $this->branches['trunk'] = $this->buildIdentifier(
38055 '/' . $this->trunkPath,
38056 $match[1]
38057 );
38058 $this->rootIdentifier = $this->branches['trunk'];
38059 break;
38060 }
38061 }
38062 }
38063 }
38064 unset($output);
38065
38066 if ($this->branchesPath !== false) {
38067 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
38068 if ($output) {
38069 foreach ($this->process->splitLines(trim($output)) as $line) {
38070 $line = trim($line);
38071 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
38072 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
38073 $this->branches[rtrim($match[2], '/')] = $this->buildIdentifier(
38074 '/' . $this->branchesPath . '/' . $match[2],
38075 $match[1]
38076 );
38077 }
38078 }
38079 }
38080 }
38081 }
38082 }
38083
38084 return $this->branches;
38085 }
38086
38087
38088
38089
38090 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38091 {
38092 $url = self::normalizeUrl($url);
38093 if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
38094 return true;
38095 }
38096
38097
38098  if (!$deep && !Filesystem::isLocalPath($url)) {
38099 return false;
38100 }
38101
38102 $processExecutor = new ProcessExecutor();
38103
38104 $exit = $processExecutor->execute(
38105 "svn info --non-interactive {$url}",
38106 $ignoredOutput
38107 );
38108
38109 if ($exit === 0) {
38110
38111  return true;
38112 }
38113
38114
38115  if (false !== stripos($processExecutor->getErrorOutput(), 'authorization failed:')) {
38116
38117  
38118  return true;
38119 }
38120
38121
38122  if (false !== stripos($processExecutor->getErrorOutput(), 'Authentication failed')) {
38123
38124  
38125  return true;
38126 }
38127
38128 return false;
38129 }
38130
38131
38132
38133
38134
38135
38136
38137
38138 protected static function normalizeUrl($url)
38139 {
38140 $fs = new Filesystem();
38141 if ($fs->isAbsolutePath($url)) {
38142 return 'file://' . strtr($url, '\\', '/');
38143 }
38144
38145 return $url;
38146 }
38147
38148
38149
38150
38151
38152
38153
38154
38155
38156
38157 protected function execute($command, $url)
38158 {
38159 if (null === $this->util) {
38160 $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
38161 $this->util->setCacheCredentials($this->cacheCredentials);
38162 }
38163
38164 try {
38165 return $this->util->execute($command, $url);
38166 } catch (\RuntimeException $e) {
38167 if (0 !== $this->process->execute('svn --version', $ignoredOutput)) {
38168 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());
38169 }
38170
38171 throw new \RuntimeException(
38172 'Repository '.$this->url.' could not be processed, '.$e->getMessage()
38173 );
38174 }
38175 }
38176
38177
38178
38179
38180
38181
38182
38183
38184
38185 protected function buildIdentifier($baseDir, $revision)
38186 {
38187 return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
38188 }
38189 }
38190 <?php
38191
38192
38193
38194
38195
38196
38197
38198
38199
38200
38201
38202 namespace Composer\Repository\Vcs;
38203
38204 use Composer\Cache;
38205 use Composer\Downloader\TransportException;
38206 use Composer\Config;
38207 use Composer\Factory;
38208 use Composer\IO\IOInterface;
38209 use Composer\Json\JsonFile;
38210 use Composer\Util\ProcessExecutor;
38211 use Composer\Util\RemoteFilesystem;
38212 use Composer\Util\Filesystem;
38213
38214
38215
38216
38217
38218
38219 abstract class VcsDriver implements VcsDriverInterface
38220 {
38221
38222 protected $url;
38223
38224 protected $originUrl;
38225
38226 protected $repoConfig;
38227
38228 protected $io;
38229
38230 protected $config;
38231
38232 protected $process;
38233
38234 protected $remoteFilesystem;
38235
38236 protected $infoCache = array();
38237
38238 protected $cache;
38239
38240
38241
38242
38243
38244
38245
38246
38247
38248
38249 final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
38250 {
38251 if (Filesystem::isLocalPath($repoConfig['url'])) {
38252 $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
38253 }
38254
38255 $this->url = $repoConfig['url'];
38256 $this->originUrl = $repoConfig['url'];
38257 $this->repoConfig = $repoConfig;
38258 $this->io = $io;
38259 $this->config = $config;
38260 $this->process = $process ?: new ProcessExecutor($io);
38261 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
38262 }
38263
38264
38265
38266
38267
38268
38269
38270 protected function shouldCache($identifier)
38271 {
38272 return $this->cache && preg_match('{[a-f0-9]{40}}i', $identifier);
38273 }
38274
38275
38276
38277
38278 public function getComposerInformation($identifier)
38279 {
38280 if (!isset($this->infoCache[$identifier])) {
38281 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
38282 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
38283 }
38284
38285 $composer = $this->getBaseComposerInformation($identifier);
38286
38287 if ($this->shouldCache($identifier)) {
38288 $this->cache->write($identifier, json_encode($composer));
38289 }
38290
38291 $this->infoCache[$identifier] = $composer;
38292 }
38293
38294 return $this->infoCache[$identifier];
38295 }
38296
38297 protected function getBaseComposerInformation($identifier)
38298 {
38299 $composerFileContent = $this->getFileContent('composer.json', $identifier);
38300
38301 if (!$composerFileContent) {
38302 return null;
38303 }
38304
38305 $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json');
38306
38307 if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) {
38308 $composer['time'] = $changeDate->format(DATE_RFC3339);
38309 }
38310
38311 return $composer;
38312 }
38313
38314
38315
38316
38317 public function hasComposerFile($identifier)
38318 {
38319 try {
38320 return (bool) $this->getComposerInformation($identifier);
38321 } catch (TransportException $e) {
38322 }
38323
38324 return false;
38325 }
38326
38327
38328
38329
38330
38331
38332
38333
38334 protected function getScheme()
38335 {
38336 if (extension_loaded('openssl')) {
38337 return 'https';
38338 }
38339
38340 return 'http';
38341 }
38342
38343
38344
38345
38346
38347
38348
38349
38350 protected function getContents($url)
38351 {
38352 $options = isset($this->repoConfig['options']) ? $this->repoConfig['options'] : array();
38353
38354 return $this->remoteFilesystem->getContents($this->originUrl, $url, false, $options);
38355 }
38356
38357
38358
38359
38360 public function cleanup()
38361 {
38362 return;
38363 }
38364 }
38365 <?php
38366
38367
38368
38369
38370
38371
38372
38373
38374
38375
38376
38377 namespace Composer\Repository\Vcs;
38378
38379 use Composer\Config;
38380 use Composer\IO\IOInterface;
38381
38382
38383
38384
38385 interface VcsDriverInterface
38386 {
38387
38388
38389
38390 public function initialize();
38391
38392
38393
38394
38395
38396
38397
38398 public function getComposerInformation($identifier);
38399
38400
38401
38402
38403
38404
38405
38406
38407 public function getFileContent($file, $identifier);
38408
38409
38410
38411
38412
38413
38414
38415 public function getChangeDate($identifier);
38416
38417
38418
38419
38420
38421
38422 public function getRootIdentifier();
38423
38424
38425
38426
38427
38428
38429 public function getBranches();
38430
38431
38432
38433
38434
38435
38436 public function getTags();
38437
38438
38439
38440
38441
38442 public function getDist($identifier);
38443
38444
38445
38446
38447
38448 public function getSource($identifier);
38449
38450
38451
38452
38453
38454
38455 public function getUrl();
38456
38457
38458
38459
38460
38461
38462
38463
38464 public function hasComposerFile($identifier);
38465
38466
38467
38468
38469 public function cleanup();
38470
38471
38472
38473
38474
38475
38476
38477
38478
38479
38480 public static function supports(IOInterface $io, Config $config, $url, $deep = false);
38481 }
38482 <?php
38483
38484
38485
38486
38487
38488
38489
38490
38491
38492
38493
38494 namespace Composer\Repository;
38495
38496 use Composer\Downloader\TransportException;
38497 use Composer\Repository\Vcs\VcsDriverInterface;
38498 use Composer\Package\Version\VersionParser;
38499 use Composer\Package\Loader\ArrayLoader;
38500 use Composer\Package\Loader\ValidatingArrayLoader;
38501 use Composer\Package\Loader\InvalidPackageException;
38502 use Composer\Package\Loader\LoaderInterface;
38503 use Composer\EventDispatcher\EventDispatcher;
38504 use Composer\IO\IOInterface;
38505 use Composer\Config;
38506
38507
38508
38509
38510 class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInterface
38511 {
38512 protected $url;
38513 protected $packageName;
38514 protected $verbose;
38515 protected $io;
38516 protected $config;
38517 protected $versionParser;
38518 protected $type;
38519 protected $loader;
38520 protected $repoConfig;
38521 protected $branchErrorOccurred = false;
38522 private $drivers;
38523
38524 private $driver;
38525
38526 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null)
38527 {
38528 parent::__construct();
38529 $this->drivers = $drivers ?: array(
38530 'github' => 'Composer\Repository\Vcs\GitHubDriver',
38531 'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
38532 'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
38533 'git' => 'Composer\Repository\Vcs\GitDriver',
38534 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver',
38535 'hg' => 'Composer\Repository\Vcs\HgDriver',
38536 'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
38537 'fossil' => 'Composer\Repository\Vcs\FossilDriver',
38538
38539  'svn' => 'Composer\Repository\Vcs\SvnDriver',
38540 );
38541
38542 $this->url = $repoConfig['url'];
38543 $this->io = $io;
38544 $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
38545 $this->verbose = $io->isVeryVerbose();
38546 $this->config = $config;
38547 $this->repoConfig = $repoConfig;
38548 }
38549
38550 public function getRepoConfig()
38551 {
38552 return $this->repoConfig;
38553 }
38554
38555 public function setLoader(LoaderInterface $loader)
38556 {
38557 $this->loader = $loader;
38558 }
38559
38560 public function getDriver()
38561 {
38562 if ($this->driver) {
38563 return $this->driver;
38564 }
38565
38566 if (isset($this->drivers[$this->type])) {
38567 $class = $this->drivers[$this->type];
38568 $this->driver = new $class($this->repoConfig, $this->io, $this->config);
38569 $this->driver->initialize();
38570
38571 return $this->driver;
38572 }
38573
38574 foreach ($this->drivers as $driver) {
38575 if ($driver::supports($this->io, $this->config, $this->url)) {
38576 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
38577 $this->driver->initialize();
38578
38579 return $this->driver;
38580 }
38581 }
38582
38583 foreach ($this->drivers as $driver) {
38584 if ($driver::supports($this->io, $this->config, $this->url, true)) {
38585 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
38586 $this->driver->initialize();
38587
38588 return $this->driver;
38589 }
38590 }
38591 }
38592
38593 public function hadInvalidBranches()
38594 {
38595 return $this->branchErrorOccurred;
38596 }
38597
38598 protected function initialize()
38599 {
38600 parent::initialize();
38601
38602 $verbose = $this->verbose;
38603
38604 $driver = $this->getDriver();
38605 if (!$driver) {
38606 throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url);
38607 }
38608
38609 $this->versionParser = new VersionParser;
38610 if (!$this->loader) {
38611 $this->loader = new ArrayLoader($this->versionParser);
38612 }
38613
38614 try {
38615 if ($driver->hasComposerFile($driver->getRootIdentifier())) {
38616 $data = $driver->getComposerInformation($driver->getRootIdentifier());
38617 $this->packageName = !empty($data['name']) ? $data['name'] : null;
38618 }
38619 } catch (\Exception $e) {
38620 if ($verbose) {
38621 $this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
38622 }
38623 }
38624
38625 foreach ($driver->getTags() as $tag => $identifier) {
38626 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
38627 if ($verbose) {
38628 $this->io->writeError($msg);
38629 } else {
38630 $this->io->overwriteError($msg, false);
38631 }
38632
38633
38634  $tag = str_replace('release-', '', $tag);
38635
38636 if (!$parsedTag = $this->validateTag($tag)) {
38637 if ($verbose) {
38638 $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
38639 }
38640 continue;
38641 }
38642
38643 try {
38644 if (!$data = $driver->getComposerInformation($identifier)) {
38645 if ($verbose) {
38646 $this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
38647 }
38648 continue;
38649 }
38650
38651
38652  if (isset($data['version'])) {
38653 $data['version_normalized'] = $this->versionParser->normalize($data['version']);
38654 } else {
38655
38656  $data['version'] = $tag;
38657 $data['version_normalized'] = $parsedTag;
38658 }
38659
38660
38661  $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']);
38662 $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
38663
38664
38665  if ($data['version_normalized'] !== $parsedTag) {
38666 if ($verbose) {
38667 $this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
38668 }
38669 continue;
38670 }
38671
38672 if ($verbose) {
38673 $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
38674 }
38675
38676 $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
38677 } catch (\Exception $e) {
38678 if ($verbose) {
38679 $this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
38680 }
38681 continue;
38682 }
38683 }
38684
38685 if (!$verbose) {
38686 $this->io->overwriteError('', false);
38687 }
38688
38689 foreach ($driver->getBranches() as $branch => $identifier) {
38690 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
38691 if ($verbose) {
38692 $this->io->writeError($msg);
38693 } else {
38694 $this->io->overwriteError($msg, false);
38695 }
38696
38697 if (!$parsedBranch = $this->validateBranch($branch)) {
38698 if ($verbose) {
38699 $this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
38700 }
38701 continue;
38702 }
38703
38704 try {
38705 if (!$data = $driver->getComposerInformation($identifier)) {
38706 if ($verbose) {
38707 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
38708 }
38709 continue;
38710 }
38711
38712
38713  $data['version'] = $branch;
38714 $data['version_normalized'] = $parsedBranch;
38715
38716
38717  if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
38718 $data['version'] = 'dev-' . $data['version'];
38719 } else {
38720 $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
38721 $data['version'] = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
38722 }
38723
38724 if ($verbose) {
38725 $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
38726 }
38727
38728 $packageData = $this->preProcess($driver, $data, $identifier);
38729 $package = $this->loader->load($packageData);
38730 if ($this->loader instanceof ValidatingArrayLoader && $this->loader->getWarnings()) {
38731 throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
38732 }
38733 $this->addPackage($package);
38734 } catch (TransportException $e) {
38735 if ($verbose) {
38736 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
38737 }
38738 continue;
38739 } catch (\Exception $e) {
38740 if (!$verbose) {
38741 $this->io->writeError('');
38742 }
38743 $this->branchErrorOccurred = true;
38744 $this->io->writeError('<error>Skipped branch '.$branch.', '.$e->getMessage().'</error>');
38745 $this->io->writeError('');
38746 continue;
38747 }
38748 }
38749 $driver->cleanup();
38750
38751 if (!$verbose) {
38752 $this->io->overwriteError('', false);
38753 }
38754
38755 if (!$this->getPackages()) {
38756 throw new InvalidRepositoryException('No valid composer.json was found in any branch or tag of '.$this->url.', could not load a package from it.');
38757 }
38758 }
38759
38760 protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
38761 {
38762
38763  $data['name'] = $this->packageName ?: $data['name'];
38764
38765 if (!isset($data['dist'])) {
38766 $data['dist'] = $driver->getDist($identifier);
38767 }
38768 if (!isset($data['source'])) {
38769 $data['source'] = $driver->getSource($identifier);
38770 }
38771
38772 return $data;
38773 }
38774
38775 private function validateBranch($branch)
38776 {
38777 try {
38778 return $this->versionParser->normalizeBranch($branch);
38779 } catch (\Exception $e) {
38780 }
38781
38782 return false;
38783 }
38784
38785 private function validateTag($version)
38786 {
38787 try {
38788 return $this->versionParser->normalize($version);
38789 } catch (\Exception $e) {
38790 }
38791
38792 return false;
38793 }
38794 }
38795 <?php
38796
38797
38798
38799
38800
38801
38802
38803
38804
38805
38806
38807 namespace Composer\Repository;
38808
38809 use Composer\Package\AliasPackage;
38810
38811
38812
38813
38814
38815
38816 class WritableArrayRepository extends ArrayRepository implements WritableRepositoryInterface
38817 {
38818
38819
38820
38821 public function write()
38822 {
38823 }
38824
38825
38826
38827
38828 public function reload()
38829 {
38830 }
38831
38832
38833
38834
38835 public function getCanonicalPackages()
38836 {
38837 $packages = $this->getPackages();
38838
38839
38840  $packagesByName = array();
38841 foreach ($packages as $package) {
38842 if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
38843 $packagesByName[$package->getName()] = $package;
38844 }
38845 }
38846
38847 $canonicalPackages = array();
38848
38849
38850  foreach ($packagesByName as $package) {
38851 while ($package instanceof AliasPackage) {
38852 $package = $package->getAliasOf();
38853 }
38854
38855 $canonicalPackages[] = $package;
38856 }
38857
38858 return $canonicalPackages;
38859 }
38860 }
38861 <?php
38862
38863
38864
38865
38866
38867
38868
38869
38870
38871
38872
38873 namespace Composer\Repository;
38874
38875 use Composer\Package\PackageInterface;
38876
38877
38878
38879
38880
38881
38882 interface WritableRepositoryInterface extends RepositoryInterface
38883 {
38884
38885
38886
38887 public function write();
38888
38889
38890
38891
38892
38893
38894 public function addPackage(PackageInterface $package);
38895
38896
38897
38898
38899
38900
38901 public function removePackage(PackageInterface $package);
38902
38903
38904
38905
38906
38907
38908 public function getCanonicalPackages();
38909
38910
38911
38912
38913 public function reload();
38914 }
38915 <?php
38916
38917
38918
38919
38920
38921
38922
38923
38924
38925
38926
38927 namespace Composer\Script;
38928
38929
38930
38931
38932
38933
38934 class CommandEvent extends Event
38935 {
38936 }
38937 <?php
38938
38939
38940
38941
38942
38943
38944
38945
38946
38947
38948
38949 namespace Composer\Script;
38950
38951 use Composer\Composer;
38952 use Composer\IO\IOInterface;
38953 use Composer\EventDispatcher\Event as BaseEvent;
38954
38955
38956
38957
38958
38959
38960
38961 class Event extends BaseEvent
38962 {
38963
38964
38965
38966 private $composer;
38967
38968
38969
38970
38971 private $io;
38972
38973
38974
38975
38976 private $devMode;
38977
38978
38979
38980
38981
38982
38983
38984
38985
38986
38987
38988 public function __construct($name, Composer $composer, IOInterface $io, $devMode = false, array $args = array(), array $flags = array())
38989 {
38990 parent::__construct($name, $args, $flags);
38991 $this->composer = $composer;
38992 $this->io = $io;
38993 $this->devMode = $devMode;
38994 }
38995
38996
38997
38998
38999
39000
39001 public function getComposer()
39002 {
39003 return $this->composer;
39004 }
39005
39006
39007
39008
39009
39010
39011 public function getIO()
39012 {
39013 return $this->io;
39014 }
39015
39016
39017
39018
39019
39020
39021 public function isDevMode()
39022 {
39023 return $this->devMode;
39024 }
39025 }
39026 <?php
39027
39028
39029
39030
39031
39032
39033
39034
39035
39036
39037
39038 namespace Composer\Script;
39039
39040 use Composer\Installer\PackageEvent as BasePackageEvent;
39041
39042
39043
39044
39045
39046
39047 class PackageEvent extends BasePackageEvent
39048 {
39049 }
39050 <?php
39051
39052
39053
39054
39055
39056
39057
39058
39059
39060
39061
39062 namespace Composer\Script;
39063
39064
39065
39066
39067
39068
39069
39070 class ScriptEvents
39071 {
39072
39073
39074
39075
39076
39077
39078
39079 const PRE_INSTALL_CMD = 'pre-install-cmd';
39080
39081
39082
39083
39084
39085
39086
39087
39088 const POST_INSTALL_CMD = 'post-install-cmd';
39089
39090
39091
39092
39093
39094
39095
39096
39097 const PRE_UPDATE_CMD = 'pre-update-cmd';
39098
39099
39100
39101
39102
39103
39104
39105
39106 const POST_UPDATE_CMD = 'post-update-cmd';
39107
39108
39109
39110
39111
39112
39113
39114
39115 const PRE_STATUS_CMD = 'pre-status-cmd';
39116
39117
39118
39119
39120
39121
39122
39123
39124 const POST_STATUS_CMD = 'post-status-cmd';
39125
39126
39127
39128
39129
39130
39131
39132
39133 const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
39134
39135
39136
39137
39138
39139
39140
39141
39142 const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
39143
39144
39145
39146
39147
39148
39149
39150
39151 const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
39152
39153
39154
39155
39156
39157
39158
39159
39160
39161 const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
39162
39163
39164
39165
39166
39167
39168
39169
39170 const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
39171
39172
39173
39174
39175
39176
39177
39178
39179 const POST_ARCHIVE_CMD = 'post-archive-cmd';
39180
39181
39182
39183
39184
39185
39186
39187
39188
39189
39190
39191 const PRE_PACKAGE_INSTALL = 'pre-package-install';
39192
39193
39194
39195
39196
39197
39198
39199
39200
39201 const POST_PACKAGE_INSTALL = 'post-package-install';
39202
39203
39204
39205
39206
39207
39208
39209
39210
39211 const PRE_PACKAGE_UPDATE = 'pre-package-update';
39212
39213
39214
39215
39216
39217
39218
39219
39220
39221 const POST_PACKAGE_UPDATE = 'post-package-update';
39222
39223
39224
39225
39226
39227
39228
39229
39230
39231 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
39232
39233
39234
39235
39236
39237
39238
39239
39240
39241 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
39242 }
39243 <?php
39244
39245
39246
39247
39248
39249
39250
39251
39252
39253
39254
39255 namespace Composer\SelfUpdate;
39256
39257
39258
39259
39260 class Keys
39261 {
39262 public static function fingerprint($path)
39263 {
39264 $hash = strtoupper(hash('sha256', preg_replace('{\s}', '', file_get_contents($path))));
39265
39266 return implode(' ', array(
39267 substr($hash, 0, 8),
39268 substr($hash, 8, 8),
39269 substr($hash, 16, 8),
39270 substr($hash, 24, 8),
39271 '', 
39272  substr($hash, 32, 8),
39273 substr($hash, 40, 8),
39274 substr($hash, 48, 8),
39275 substr($hash, 56, 8),
39276 ));
39277 }
39278 }
39279 <?php
39280
39281
39282
39283
39284
39285
39286
39287
39288
39289
39290
39291 namespace Composer\SelfUpdate;
39292
39293 use Composer\Util\RemoteFilesystem;
39294 use Composer\Config;
39295 use Composer\Json\JsonFile;
39296
39297
39298
39299
39300 class Versions
39301 {
39302 private $rfs;
39303 private $config;
39304 private $channel;
39305
39306 public function __construct(Config $config, RemoteFilesystem $rfs)
39307 {
39308 $this->rfs = $rfs;
39309 $this->config = $config;
39310 }
39311
39312 public function getChannel()
39313 {
39314 if ($this->channel) {
39315 return $this->channel;
39316 }
39317
39318 $channelFile = $this->config->get('home').'/update-channel';
39319 if (file_exists($channelFile)) {
39320 $channel = trim(file_get_contents($channelFile));
39321 if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
39322 return $this->channel = $channel;
39323 }
39324 }
39325
39326 return $this->channel = 'stable';
39327 }
39328
39329 public function setChannel($channel)
39330 {
39331 if (!in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
39332 throw new \InvalidArgumentException('Invalid channel '.$channel.', must be one of: stable, preview, snapshot');
39333 }
39334
39335 $channelFile = $this->config->get('home').'/update-channel';
39336 $this->channel = $channel;
39337 file_put_contents($channelFile, $channel.PHP_EOL);
39338 }
39339
39340 public function getLatest()
39341 {
39342 $protocol = extension_loaded('openssl') ? 'https' : 'http';
39343 $versions = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false));
39344
39345 foreach ($versions[$this->getChannel()] as $version) {
39346 if ($version['min-php'] <= PHP_VERSION_ID) {
39347 return $version;
39348 }
39349 }
39350
39351 throw new \LogicException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')');
39352 }
39353 }
39354 <?php
39355
39356
39357
39358
39359
39360
39361
39362
39363
39364
39365
39366 namespace Composer\Util;
39367
39368 use Composer\Config;
39369 use Composer\IO\IOInterface;
39370
39371
39372
39373
39374 class AuthHelper
39375 {
39376 protected $io;
39377 protected $config;
39378
39379 public function __construct(IOInterface $io, Config $config)
39380 {
39381 $this->io = $io;
39382 $this->config = $config;
39383 }
39384
39385 public function storeAuth($originUrl, $storeAuth)
39386 {
39387 $store = false;
39388 $configSource = $this->config->getAuthConfigSource();
39389 if ($storeAuth === true) {
39390 $store = $configSource;
39391 } elseif ($storeAuth === 'prompt') {
39392 $answer = $this->io->askAndValidate(
39393 'Do you want to store credentials for '.$originUrl.' in '.$configSource->getName().' ? [Yn] ',
39394 function ($value) {
39395 $input = strtolower(substr(trim($value), 0, 1));
39396 if (in_array($input, array('y','n'))) {
39397 return $input;
39398 }
39399 throw new \RuntimeException('Please answer (y)es or (n)o');
39400 },
39401 null,
39402 'y'
39403 );
39404
39405 if ($answer === 'y') {
39406 $store = $configSource;
39407 }
39408 }
39409 if ($store) {
39410 $store->addConfigSetting(
39411 'http-basic.'.$originUrl,
39412 $this->io->getAuthentication($originUrl)
39413 );
39414 }
39415 }
39416 }
39417 <?php
39418
39419
39420
39421
39422
39423
39424
39425
39426
39427
39428
39429 namespace Composer\Util;
39430
39431 use Composer\Factory;
39432 use Composer\IO\IOInterface;
39433 use Composer\Config;
39434 use Composer\Downloader\TransportException;
39435
39436
39437
39438
39439 class Bitbucket
39440 {
39441 private $io;
39442 private $config;
39443 private $process;
39444 private $remoteFilesystem;
39445 private $token = array();
39446 private $time;
39447
39448 const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
39449
39450
39451
39452
39453
39454
39455
39456
39457
39458
39459 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null, $time = null)
39460 {
39461 $this->io = $io;
39462 $this->config = $config;
39463 $this->process = $process ?: new ProcessExecutor;
39464 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
39465 $this->time = $time;
39466 }
39467
39468
39469
39470
39471 public function getToken()
39472 {
39473 if (!isset($this->token['access_token'])) {
39474 return '';
39475 }
39476
39477 return $this->token['access_token'];
39478 }
39479
39480
39481
39482
39483
39484
39485
39486 public function authorizeOAuth($originUrl)
39487 {
39488 if ($originUrl !== 'bitbucket.org') {
39489 return false;
39490 }
39491
39492
39493  if (0 === $this->process->execute('git config bitbucket.accesstoken', $output)) {
39494 $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));
39495
39496 return true;
39497 }
39498
39499 return false;
39500 }
39501
39502
39503
39504
39505
39506 private function requestAccessToken($originUrl)
39507 {
39508 try {
39509 $json = $this->remoteFilesystem->getContents($originUrl, self::OAUTH2_ACCESS_TOKEN_URL, false, array(
39510 'retry-auth-failure' => false,
39511 'http' => array(
39512 'method' => 'POST',
39513 'content' => 'grant_type=client_credentials',
39514 ),
39515 ));
39516
39517 $this->token = json_decode($json, true);
39518 } catch (TransportException $e) {
39519 if ($e->getCode() === 400) {
39520 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
39521 $this->io->writeError('This can have two reasons:');
39522 $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
39523 $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
39524
39525 return false;
39526 } elseif (in_array($e->getCode(), array(403, 401))) {
39527 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
39528 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39529
39530 return false;
39531 }
39532
39533 throw $e;
39534 }
39535
39536 return true;
39537 }
39538
39539
39540
39541
39542
39543
39544
39545
39546
39547
39548 public function authorizeOAuthInteractively($originUrl, $message = null)
39549 {
39550 if ($message) {
39551 $this->io->writeError($message);
39552 }
39553
39554 $url = 'https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html';
39555 $this->io->writeError(sprintf('Follow the instructions on %s', $url));
39556 $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
39557 $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)');
39558
39559 $consumerKey = trim($this->io->askAndHideAnswer('Consumer Key (hidden): '));
39560
39561 if (!$consumerKey) {
39562 $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
39563 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39564
39565 return false;
39566 }
39567
39568 $consumerSecret = trim($this->io->askAndHideAnswer('Consumer Secret (hidden): '));
39569
39570 if (!$consumerSecret) {
39571 $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
39572 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39573
39574 return false;
39575 }
39576
39577 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
39578
39579 if (!$this->requestAccessToken($originUrl)) {
39580 return false;
39581 }
39582
39583
39584  $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
39585
39586
39587  $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
39588
39589 $this->io->writeError('<info>Consumer stored successfully.</info>');
39590
39591 return true;
39592 }
39593
39594
39595
39596
39597
39598
39599
39600
39601
39602 public function requestToken($originUrl, $consumerKey, $consumerSecret)
39603 {
39604 if (!empty($this->token) || $this->getTokenFromConfig($originUrl)) {
39605 return $this->token['access_token'];
39606 }
39607
39608 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
39609 if (!$this->requestAccessToken($originUrl)) {
39610 return '';
39611 }
39612
39613 $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
39614
39615 return $this->token['access_token'];
39616 }
39617
39618
39619
39620
39621
39622
39623
39624 private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret)
39625 {
39626 $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
39627
39628 $time = null === $this->time ? time() : $this->time;
39629 $consumer = array(
39630 "consumer-key" => $consumerKey,
39631 "consumer-secret" => $consumerSecret,
39632 "access-token" => $this->token['access_token'],
39633 "access-token-expiration" => $time + $this->token['expires_in'],
39634 );
39635
39636 $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.'.$originUrl, $consumer);
39637 }
39638
39639
39640
39641
39642
39643 private function getTokenFromConfig($originUrl)
39644 {
39645 $authConfig = $this->config->get('bitbucket-oauth');
39646
39647 if (
39648 !isset($authConfig[$originUrl]['access-token'])
39649 || !isset($authConfig[$originUrl]['access-token-expiration'])
39650 || time() > $authConfig[$originUrl]['access-token-expiration']
39651 ) {
39652 return false;
39653 }
39654
39655 $this->token = array(
39656 'access_token' => $authConfig[$originUrl]['access-token'],
39657 );
39658
39659 return true;
39660 }
39661 }
39662 <?php
39663
39664
39665
39666
39667
39668
39669
39670
39671
39672
39673
39674 namespace Composer\Util;
39675
39676
39677
39678
39679
39680
39681 class ComposerMirror
39682 {
39683 public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type)
39684 {
39685 if ($reference) {
39686 $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference);
39687 }
39688 $version = strpos($version, '/') === false ? $version : md5($version);
39689
39690 return str_replace(
39691 array('%package%', '%version%', '%reference%', '%type%'),
39692 array($packageName, $version, $reference, $type),
39693 $mirrorUrl
39694 );
39695 }
39696
39697 public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
39698 {
39699 if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
39700 $url = 'gh-'.$match[1].'/'.$match[2];
39701 } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
39702 $url = 'bb-'.$match[1].'/'.$match[2];
39703 } else {
39704 $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
39705 }
39706
39707 return str_replace(
39708 array('%package%', '%normalizedUrl%', '%type%'),
39709 array($packageName, $url, $type),
39710 $mirrorUrl
39711 );
39712 }
39713
39714 public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
39715 {
39716 return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
39717 }
39718 }
39719 <?php
39720
39721
39722
39723
39724
39725
39726
39727
39728
39729
39730
39731 namespace Composer\Util;
39732
39733 use Composer\Package\Loader\ArrayLoader;
39734 use Composer\Package\Loader\ValidatingArrayLoader;
39735 use Composer\Package\Loader\InvalidPackageException;
39736 use Composer\Json\JsonValidationException;
39737 use Composer\IO\IOInterface;
39738 use Composer\Json\JsonFile;
39739
39740
39741
39742
39743
39744
39745
39746 class ConfigValidator
39747 {
39748 private $io;
39749
39750 public function __construct(IOInterface $io)
39751 {
39752 $this->io = $io;
39753 }
39754
39755
39756
39757
39758
39759
39760
39761
39762
39763 public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL)
39764 {
39765 $errors = array();
39766 $publishErrors = array();
39767 $warnings = array();
39768
39769
39770  $laxValid = false;
39771 try {
39772 $json = new JsonFile($file, null, $this->io);
39773 $manifest = $json->read();
39774
39775 $json->validateSchema(JsonFile::LAX_SCHEMA);
39776 $laxValid = true;
39777 $json->validateSchema();
39778 } catch (JsonValidationException $e) {
39779 foreach ($e->getErrors() as $message) {
39780 if ($laxValid) {
39781 $publishErrors[] = $message;
39782 } else {
39783 $errors[] = $message;
39784 }
39785 }
39786 } catch (\Exception $e) {
39787 $errors[] = $e->getMessage();
39788
39789 return array($errors, $publishErrors, $warnings);
39790 }
39791
39792
39793  if (empty($manifest['license'])) {
39794 $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
39795 }
39796
39797 if (isset($manifest['version'])) {
39798 $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
39799 }
39800
39801 if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) {
39802 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']);
39803 $suggestName = strtolower($suggestName);
39804
39805 $publishErrors[] = sprintf(
39806 '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.',
39807 $manifest['name'],
39808 $suggestName
39809 );
39810 }
39811
39812 if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') {
39813 $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.";
39814 }
39815
39816
39817  if (isset($manifest['require']) && isset($manifest['require-dev'])) {
39818 $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
39819
39820 if (!empty($requireOverrides)) {
39821 $plural = (count($requireOverrides) > 1) ? 'are' : 'is';
39822 $warnings[] = implode(', ', array_keys($requireOverrides)). " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
39823 }
39824 }
39825
39826
39827  $require = isset($manifest['require']) ? $manifest['require'] : array();
39828 $requireDev = isset($manifest['require-dev']) ? $manifest['require-dev'] : array();
39829 $packages = array_merge($require, $requireDev);
39830 foreach ($packages as $package => $version) {
39831 if (preg_match('/#/', $version) === 1) {
39832 $warnings[] = sprintf(
39833 'The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.',
39834 $package
39835 );
39836 }
39837 }
39838
39839
39840  if (isset($manifest['autoload']['psr-0'][''])) {
39841 $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
39842 }
39843 if (isset($manifest['autoload']['psr-4'][''])) {
39844 $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
39845 }
39846
39847 try {
39848 $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags);
39849 if (!isset($manifest['version'])) {
39850 $manifest['version'] = '1.0.0';
39851 }
39852 if (!isset($manifest['name'])) {
39853 $manifest['name'] = 'dummy/dummy';
39854 }
39855 $loader->load($manifest);
39856 } catch (InvalidPackageException $e) {
39857 $errors = array_merge($errors, $e->getErrors());
39858 }
39859
39860 $warnings = array_merge($warnings, $loader->getWarnings());
39861
39862 return array($errors, $publishErrors, $warnings);
39863 }
39864 }
39865 <?php
39866
39867
39868
39869
39870
39871
39872
39873
39874
39875
39876
39877 namespace Composer\Util;
39878
39879 use Composer\IO\IOInterface;
39880
39881
39882
39883
39884
39885
39886 class ErrorHandler
39887 {
39888 private static $io;
39889
39890
39891
39892
39893
39894
39895
39896
39897
39898
39899
39900
39901 public static function handle($level, $message, $file, $line)
39902 {
39903
39904  if (!(error_reporting() & $level)) {
39905 return;
39906 }
39907
39908 if (ini_get('xdebug.scream')) {
39909 $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
39910 "\na legitimately suppressed error that you were not supposed to see.";
39911 }
39912
39913 if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
39914 throw new \ErrorException($message, 0, $level, $file, $line);
39915 }
39916
39917 if (self::$io) {
39918 self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
39919 if (self::$io->isVerbose()) {
39920 self::$io->writeError('<warning>Stack trace:</warning>');
39921 self::$io->writeError(array_filter(array_map(function ($a) {
39922 if (isset($a['line'], $a['file'])) {
39923 return '<warning> '.$a['file'].':'.$a['line'].'</warning>';
39924 }
39925
39926 return null;
39927 }, array_slice(debug_backtrace(), 2))));
39928 }
39929 }
39930 }
39931
39932
39933
39934
39935
39936
39937 public static function register(IOInterface $io = null)
39938 {
39939 set_error_handler(array(__CLASS__, 'handle'));
39940 error_reporting(E_ALL | E_STRICT);
39941 self::$io = $io;
39942 }
39943 }
39944 <?php
39945
39946
39947
39948
39949
39950
39951
39952
39953
39954
39955
39956 namespace Composer\Util;
39957
39958 use RecursiveDirectoryIterator;
39959 use RecursiveIteratorIterator;
39960 use Symfony\Component\Filesystem\Exception\IOException;
39961 use Symfony\Component\Finder\Finder;
39962
39963
39964
39965
39966
39967 class Filesystem
39968 {
39969 private $processExecutor;
39970
39971 public function __construct(ProcessExecutor $executor = null)
39972 {
39973 $this->processExecutor = $executor ?: new ProcessExecutor();
39974 }
39975
39976 public function remove($file)
39977 {
39978 if (is_dir($file)) {
39979 return $this->removeDirectory($file);
39980 }
39981
39982 if (file_exists($file)) {
39983 return $this->unlink($file);
39984 }
39985
39986 return false;
39987 }
39988
39989
39990
39991
39992
39993
39994
39995 public function isDirEmpty($dir)
39996 {
39997 $finder = Finder::create()
39998 ->ignoreVCS(false)
39999 ->ignoreDotFiles(false)
40000 ->depth(0)
40001 ->in($dir);
40002
40003 return count($finder) === 0;
40004 }
40005
40006 public function emptyDirectory($dir, $ensureDirectoryExists = true)
40007 {
40008 if (file_exists($dir) && is_link($dir)) {
40009 $this->unlink($dir);
40010 }
40011
40012 if ($ensureDirectoryExists) {
40013 $this->ensureDirectoryExists($dir);
40014 }
40015
40016 if (is_dir($dir)) {
40017 $finder = Finder::create()
40018 ->ignoreVCS(false)
40019 ->ignoreDotFiles(false)
40020 ->depth(0)
40021 ->in($dir);
40022
40023 foreach ($finder as $path) {
40024 $this->remove((string) $path);
40025 }
40026 }
40027 }
40028
40029
40030
40031
40032
40033
40034
40035
40036
40037
40038
40039 public function removeDirectory($directory)
40040 {
40041 if ($this->isSymlinkedDirectory($directory)) {
40042 return $this->unlinkSymlinkedDirectory($directory);
40043 }
40044
40045 if ($this->isJunction($directory)) {
40046 return $this->removeJunction($directory);
40047 }
40048
40049 if (!file_exists($directory) || !is_dir($directory)) {
40050 return true;
40051 }
40052
40053 if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
40054 throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.');
40055 }
40056
40057 if (!function_exists('proc_open')) {
40058 return $this->removeDirectoryPhp($directory);
40059 }
40060
40061 if (Platform::isWindows()) {
40062 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape(realpath($directory)));
40063 } else {
40064 $cmd = sprintf('rm -rf %s', ProcessExecutor::escape($directory));
40065 }
40066
40067 $result = $this->getProcess()->execute($cmd, $output) === 0;
40068
40069
40070  clearstatcache();
40071
40072 if ($result && !file_exists($directory)) {
40073 return true;
40074 }
40075
40076 return $this->removeDirectoryPhp($directory);
40077 }
40078
40079
40080
40081
40082
40083
40084
40085
40086
40087
40088
40089 public function removeDirectoryPhp($directory)
40090 {
40091 try {
40092 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
40093 } catch (\UnexpectedValueException $e) {
40094
40095  
40096  clearstatcache();
40097 usleep(100000);
40098 if (!is_dir($directory)) {
40099 return true;
40100 }
40101 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
40102 }
40103 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
40104
40105 foreach ($ri as $file) {
40106 if ($file->isDir()) {
40107 $this->rmdir($file->getPathname());
40108 } else {
40109 $this->unlink($file->getPathname());
40110 }
40111 }
40112
40113 return $this->rmdir($directory);
40114 }
40115
40116 public function ensureDirectoryExists($directory)
40117 {
40118 if (!is_dir($directory)) {
40119 if (file_exists($directory)) {
40120 throw new \RuntimeException(
40121 $directory.' exists and is not a directory.'
40122 );
40123 }
40124 if (!@mkdir($directory, 0777, true)) {
40125 throw new \RuntimeException(
40126 $directory.' does not exist and could not be created.'
40127 );
40128 }
40129 }
40130 }
40131
40132
40133
40134
40135
40136
40137
40138
40139 public function unlink($path)
40140 {
40141 if (!@$this->unlinkImplementation($path)) {
40142
40143  if (!Platform::isWindows() || (usleep(350000) && !@$this->unlinkImplementation($path))) {
40144 $error = error_get_last();
40145 $message = 'Could not delete '.$path.': ' . @$error['message'];
40146 if (Platform::isWindows()) {
40147 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
40148 }
40149
40150 throw new \RuntimeException($message);
40151 }
40152 }
40153
40154 return true;
40155 }
40156
40157
40158
40159
40160
40161
40162
40163
40164 public function rmdir($path)
40165 {
40166 if (!@rmdir($path)) {
40167
40168  if (!Platform::isWindows() || (usleep(350000) && !@rmdir($path))) {
40169 $error = error_get_last();
40170 $message = 'Could not delete '.$path.': ' . @$error['message'];
40171 if (Platform::isWindows()) {
40172 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
40173 }
40174
40175 throw new \RuntimeException($message);
40176 }
40177 }
40178
40179 return true;
40180 }
40181
40182
40183
40184
40185
40186
40187
40188
40189
40190
40191 public function copyThenRemove($source, $target)
40192 {
40193 $this->copy($source, $target);
40194 if (!is_dir($source)) {
40195 $this->unlink($source);
40196
40197 return;
40198 }
40199
40200 $this->removeDirectoryPhp($source);
40201 }
40202
40203
40204
40205
40206
40207
40208
40209
40210 public function copy($source, $target)
40211 {
40212 if (!is_dir($source)) {
40213 return copy($source, $target);
40214 }
40215
40216 $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
40217 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
40218 $this->ensureDirectoryExists($target);
40219
40220 $result = true;
40221 foreach ($ri as $file) {
40222 $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
40223 if ($file->isDir()) {
40224 $this->ensureDirectoryExists($targetPath);
40225 } else {
40226 $result = $result && copy($file->getPathname(), $targetPath);
40227 }
40228 }
40229
40230 return $result;
40231 }
40232
40233 public function rename($source, $target)
40234 {
40235 if (true === @rename($source, $target)) {
40236 return;
40237 }
40238
40239 if (!function_exists('proc_open')) {
40240 return $this->copyThenRemove($source, $target);
40241 }
40242
40243 if (Platform::isWindows()) {
40244
40245  $command = sprintf('xcopy %s %s /E /I /Q /Y', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
40246 $result = $this->processExecutor->execute($command, $output);
40247
40248
40249  clearstatcache();
40250
40251 if (0 === $result) {
40252 $this->remove($source);
40253
40254 return;
40255 }
40256 } else {
40257
40258  
40259  $command = sprintf('mv %s %s', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
40260 $result = $this->processExecutor->execute($command, $output);
40261
40262
40263  clearstatcache();
40264
40265 if (0 === $result) {
40266 return;
40267 }
40268 }
40269
40270 return $this->copyThenRemove($source, $target);
40271 }
40272
40273
40274
40275
40276
40277
40278
40279
40280
40281
40282 public function findShortestPath($from, $to, $directories = false)
40283 {
40284 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
40285 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
40286 }
40287
40288 $from = lcfirst($this->normalizePath($from));
40289 $to = lcfirst($this->normalizePath($to));
40290
40291 if ($directories) {
40292 $from = rtrim($from, '/') . '/dummy_file';
40293 }
40294
40295 if (dirname($from) === dirname($to)) {
40296 return './'.basename($to);
40297 }
40298
40299 $commonPath = $to;
40300 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) {
40301 $commonPath = strtr(dirname($commonPath), '\\', '/');
40302 }
40303
40304 if (0 !== strpos($from, $commonPath) || '/' === $commonPath) {
40305 return $to;
40306 }
40307
40308 $commonPath = rtrim($commonPath, '/') . '/';
40309 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/');
40310 $commonPathCode = str_repeat('../', $sourcePathDepth);
40311
40312 return ($commonPathCode . substr($to, strlen($commonPath))) ?: './';
40313 }
40314
40315
40316
40317
40318
40319
40320
40321
40322
40323
40324
40325 public function findShortestPathCode($from, $to, $directories = false, $staticCode = false)
40326 {
40327 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
40328 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
40329 }
40330
40331 $from = lcfirst($this->normalizePath($from));
40332 $to = lcfirst($this->normalizePath($to));
40333
40334 if ($from === $to) {
40335 return $directories ? '__DIR__' : '__FILE__';
40336 }
40337
40338 $commonPath = $to;
40339 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) {
40340 $commonPath = strtr(dirname($commonPath), '\\', '/');
40341 }
40342
40343 if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) {
40344 return var_export($to, true);
40345 }
40346
40347 $commonPath = rtrim($commonPath, '/') . '/';
40348 if (strpos($to, $from.'/') === 0) {
40349 return '__DIR__ . '.var_export(substr($to, strlen($from)), true);
40350 }
40351 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/') + $directories;
40352 if ($staticCode) {
40353 $commonPathCode = "__DIR__ . '".str_repeat('/..', $sourcePathDepth)."'";
40354 } else {
40355 $commonPathCode = str_repeat('dirname(', $sourcePathDepth).'__DIR__'.str_repeat(')', $sourcePathDepth);
40356 }
40357 $relTarget = substr($to, strlen($commonPath));
40358
40359 return $commonPathCode . (strlen($relTarget) ? '.' . var_export('/' . $relTarget, true) : '');
40360 }
40361
40362
40363
40364
40365
40366
40367
40368 public function isAbsolutePath($path)
40369 {
40370 return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':';
40371 }
40372
40373
40374
40375
40376
40377
40378
40379
40380
40381 public function size($path)
40382 {
40383 if (!file_exists($path)) {
40384 throw new \RuntimeException("$path does not exist.");
40385 }
40386 if (is_dir($path)) {
40387 return $this->directorySize($path);
40388 }
40389
40390 return filesize($path);
40391 }
40392
40393
40394
40395
40396
40397
40398
40399
40400 public function normalizePath($path)
40401 {
40402 $parts = array();
40403 $path = strtr($path, '\\', '/');
40404 $prefix = '';
40405 $absolute = false;
40406
40407
40408  if (preg_match('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
40409 $prefix = $match[1];
40410 $path = substr($path, strlen($prefix));
40411 }
40412
40413 if (substr($path, 0, 1) === '/') {
40414 $absolute = true;
40415 $path = substr($path, 1);
40416 }
40417
40418 $up = false;
40419 foreach (explode('/', $path) as $chunk) {
40420 if ('..' === $chunk && ($absolute || $up)) {
40421 array_pop($parts);
40422 $up = !(empty($parts) || '..' === end($parts));
40423 } elseif ('.' !== $chunk && '' !== $chunk) {
40424 $parts[] = $chunk;
40425 $up = '..' !== $chunk;
40426 }
40427 }
40428
40429 return $prefix.($absolute ? '/' : '').implode('/', $parts);
40430 }
40431
40432
40433
40434
40435
40436
40437
40438 public static function isLocalPath($path)
40439 {
40440 return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
40441 }
40442
40443 public static function getPlatformPath($path)
40444 {
40445 if (Platform::isWindows()) {
40446 $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
40447 }
40448
40449 return preg_replace('{^file://}i', '', $path);
40450 }
40451
40452 protected function directorySize($directory)
40453 {
40454 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
40455 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
40456
40457 $size = 0;
40458 foreach ($ri as $file) {
40459 if ($file->isFile()) {
40460 $size += $file->getSize();
40461 }
40462 }
40463
40464 return $size;
40465 }
40466
40467 protected function getProcess()
40468 {
40469 return new ProcessExecutor;
40470 }
40471
40472
40473
40474
40475
40476
40477
40478
40479
40480
40481 private function unlinkImplementation($path)
40482 {
40483 if (Platform::isWindows() && is_dir($path) && is_link($path)) {
40484 return rmdir($path);
40485 }
40486
40487 return unlink($path);
40488 }
40489
40490
40491
40492
40493
40494
40495
40496
40497 public function relativeSymlink($target, $link)
40498 {
40499 $cwd = getcwd();
40500
40501 $relativePath = $this->findShortestPath($link, $target);
40502 chdir(dirname($link));
40503 $result = @symlink($relativePath, $link);
40504
40505 chdir($cwd);
40506
40507 return (bool) $result;
40508 }
40509
40510
40511
40512
40513
40514
40515
40516
40517 public function isSymlinkedDirectory($directory)
40518 {
40519 if (!is_dir($directory)) {
40520 return false;
40521 }
40522
40523 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
40524
40525 return is_link($resolved);
40526 }
40527
40528
40529
40530
40531
40532
40533 private function unlinkSymlinkedDirectory($directory)
40534 {
40535 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
40536
40537 return $this->unlink($resolved);
40538 }
40539
40540
40541
40542
40543
40544
40545
40546
40547 private function resolveSymlinkedDirectorySymlink($pathname)
40548 {
40549 if (!is_dir($pathname)) {
40550 return $pathname;
40551 }
40552
40553 $resolved = rtrim($pathname, '/');
40554
40555 if (!strlen($resolved)) {
40556 return $pathname;
40557 }
40558
40559 return $resolved;
40560 }
40561
40562
40563
40564
40565
40566
40567
40568 public function junction($target, $junction)
40569 {
40570 if (!Platform::isWindows()) {
40571 throw new \LogicException(sprintf('Function %s is not available on non-Windows platform', __CLASS__));
40572 }
40573 if (!is_dir($target)) {
40574 throw new IOException(sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target);
40575 }
40576 $cmd = sprintf('mklink /J %s %s',
40577 ProcessExecutor::escape(str_replace('/', DIRECTORY_SEPARATOR, $junction)),
40578 ProcessExecutor::escape(realpath($target)));
40579 if ($this->getProcess()->execute($cmd, $output) !== 0) {
40580 throw new IOException(sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target);
40581 }
40582 clearstatcache(true, $junction);
40583 }
40584
40585
40586
40587
40588
40589
40590
40591 public function isJunction($junction)
40592 {
40593 if (!Platform::isWindows()) {
40594 return false;
40595 }
40596 if (!is_dir($junction) || is_link($junction)) {
40597 return false;
40598 }
40599
40600
40601
40602
40603
40604
40605
40606
40607
40608
40609
40610 clearstatcache(true, $junction);
40611 clearstatcache(false);
40612 $stat = lstat($junction);
40613
40614 return !($stat['mode'] & 0xC000);
40615 }
40616
40617
40618
40619
40620
40621
40622
40623 public function removeJunction($junction)
40624 {
40625 if (!Platform::isWindows()) {
40626 return false;
40627 }
40628 $junction = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $junction), DIRECTORY_SEPARATOR);
40629 if (!$this->isJunction($junction)) {
40630 throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
40631 }
40632 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape($junction));
40633 clearstatcache(true, $junction);
40634
40635 return ($this->getProcess()->execute($cmd, $output) === 0);
40636 }
40637 }
40638 <?php
40639
40640
40641
40642
40643
40644
40645
40646
40647
40648
40649
40650 namespace Composer\Util;
40651
40652 use Composer\Config;
40653 use Composer\IO\IOInterface;
40654
40655
40656
40657
40658 class Git
40659 {
40660 private static $version;
40661
40662
40663 protected $io;
40664
40665 protected $config;
40666
40667 protected $process;
40668
40669 protected $filesystem;
40670
40671 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process, Filesystem $fs)
40672 {
40673 $this->io = $io;
40674 $this->config = $config;
40675 $this->process = $process;
40676 $this->filesystem = $fs;
40677 }
40678
40679 public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
40680 {
40681
40682  $this->config->prohibitUrlByConfig($url, $this->io);
40683
40684 if ($initialClone) {
40685 $origCwd = $cwd;
40686 $cwd = null;
40687 }
40688
40689 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
40690 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.');
40691 }
40692
40693 if (!$initialClone) {
40694
40695  $this->process->execute('git remote -v', $output, $cwd);
40696 if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match)) {
40697 $this->io->setAuthentication($match[3], urldecode($match[1]), urldecode($match[2]));
40698 }
40699 }
40700
40701 $protocols = $this->config->get('github-protocols');
40702 if (!is_array($protocols)) {
40703 throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols));
40704 }
40705
40706  if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
40707 $messages = array();
40708 foreach ($protocols as $protocol) {
40709 if ('ssh' === $protocol) {
40710 $protoUrl = "git@" . $match[1] . ":" . $match[2];
40711 } else {
40712 $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
40713 }
40714
40715 if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) {
40716 return;
40717 }
40718 $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', '  ', $this->process->getErrorOutput());
40719 if ($initialClone) {
40720 $this->filesystem->removeDirectory($origCwd);
40721 }
40722 }
40723
40724
40725  $this->throwException('Failed to clone ' . $url . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
40726 }
40727
40728
40729  $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
40730
40731 $command = call_user_func($commandCallable, $url);
40732
40733 $auth = null;
40734 if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
40735
40736  if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)) {
40737 if (!$this->io->hasAuthentication($match[1])) {
40738 $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
40739 $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
40740
40741 if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
40742 $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
40743 }
40744 }
40745
40746 if ($this->io->hasAuthentication($match[1])) {
40747 $auth = $this->io->getAuthentication($match[1]);
40748 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
40749 $command = call_user_func($commandCallable, $authUrl);
40750 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40751 return;
40752 }
40753 }
40754 } elseif (preg_match('{^https://(bitbucket\.org)/(.*)(\.git)?$}U', $url, $match)) { 
40755  $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process);
40756
40757 if (!$this->io->hasAuthentication($match[1])) {
40758 $message = 'Enter your Bitbucket credentials to access private repos';
40759
40760 if (!$bitbucketUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
40761 $bitbucketUtil->authorizeOAuthInteractively($match[1], $message);
40762 $accessToken = $bitbucketUtil->getToken();
40763 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
40764 }
40765 } else { 
40766  $auth = $this->io->getAuthentication($match[1]);
40767
40768
40769  if ($auth['username'] !== 'x-token-auth') {
40770 $accessToken = $bitbucketUtil->requestToken($match[1], $auth['username'], $auth['password']);
40771 if (! empty($accessToken)) {
40772 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
40773 }
40774 }
40775 }
40776
40777 if ($this->io->hasAuthentication($match[1])) {
40778 $auth = $this->io->getAuthentication($match[1]);
40779 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
40780
40781 $command = call_user_func($commandCallable, $authUrl);
40782 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40783 return;
40784 }
40785 } else { 
40786  $sshUrl = 'git@bitbucket.org:' . $match[2] . '.git';
40787 $this->io->writeError('    No bitbucket authentication configured. Falling back to ssh.');
40788 $command = call_user_func($commandCallable, $sshUrl);
40789 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40790 return;
40791 }
40792 }
40793 } elseif ($this->isAuthenticationFailure($url, $match)) { 
40794  if (strpos($match[2], '@')) {
40795 list($authParts, $match[2]) = explode('@', $match[2], 2);
40796 }
40797
40798 $storeAuth = false;
40799 if ($this->io->hasAuthentication($match[2])) {
40800 $auth = $this->io->getAuthentication($match[2]);
40801 } elseif ($this->io->isInteractive()) {
40802 $defaultUsername = null;
40803 if (isset($authParts) && $authParts) {
40804 if (false !== strpos($authParts, ':')) {
40805 list($defaultUsername, ) = explode(':', $authParts, 2);
40806 } else {
40807 $defaultUsername = $authParts;
40808 }
40809 }
40810
40811 $this->io->writeError('    Authentication required (<info>' . parse_url($url, PHP_URL_HOST) . '</info>):');
40812 $auth = array(
40813 'username' => $this->io->ask('      Username: ', $defaultUsername),
40814 'password' => $this->io->askAndHideAnswer('      Password: '),
40815 );
40816 $storeAuth = $this->config->get('store-auths');
40817 }
40818
40819 if ($auth) {
40820 $authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
40821
40822 $command = call_user_func($commandCallable, $authUrl);
40823 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40824 $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
40825 $authHelper = new AuthHelper($this->io, $this->config);
40826 $authHelper->storeAuth($match[2], $storeAuth);
40827
40828 return;
40829 }
40830 }
40831 }
40832
40833 if ($initialClone) {
40834 $this->filesystem->removeDirectory($origCwd);
40835 }
40836 $this->throwException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput(), $url);
40837 }
40838 }
40839
40840 public function syncMirror($url, $dir)
40841 {
40842
40843  if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
40844 try {
40845 $commandCallable = function ($url) {
40846 return sprintf('git remote set-url origin %s && git remote update --prune origin', ProcessExecutor::escape($url));
40847 };
40848 $this->runCommand($commandCallable, $url, $dir);
40849 } catch (\Exception $e) {
40850 return false;
40851 }
40852
40853 return true;
40854 }
40855
40856
40857  $this->filesystem->removeDirectory($dir);
40858
40859 $commandCallable = function ($url) use ($dir) {
40860 return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
40861 };
40862
40863 $this->runCommand($commandCallable, $url, $dir, true);
40864
40865 return true;
40866 }
40867
40868 public function fetchRefOrSyncMirror($url, $dir, $ref)
40869 {
40870 if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
40871 $escapedRef = ProcessExecutor::escape($ref.'^{commit}');
40872 $exitCode = $this->process->execute(sprintf('git rev-parse --quiet --verify %s', $escapedRef), $output, $dir);
40873 if ($exitCode === 0) {
40874 return true;
40875 }
40876 }
40877
40878 $this->syncMirror($url, $dir);
40879
40880 return false;
40881 }
40882
40883 private function isAuthenticationFailure($url, &$match)
40884 {
40885 if (!preg_match('{(https?://)([^/]+)(.*)$}i', $url, $match)) {
40886 return false;
40887 }
40888
40889 $authFailures = array(
40890 'fatal: Authentication failed',
40891 'remote error: Invalid username or password.',
40892 'error: 401 Unauthorized',
40893 'fatal: unable to access',
40894 );
40895
40896 foreach ($authFailures as $authFailure) {
40897 if (strpos($this->process->getErrorOutput(), $authFailure) !== false) {
40898 return true;
40899 }
40900 }
40901
40902 return false;
40903 }
40904
40905 public static function cleanEnv()
40906 {
40907 if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
40908 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');
40909 }
40910
40911
40912  if (getenv('GIT_ASKPASS') !== 'echo') {
40913 putenv('GIT_ASKPASS=echo');
40914 unset($_SERVER['GIT_ASKPASS']);
40915 }
40916
40917
40918  if (getenv('GIT_DIR')) {
40919 putenv('GIT_DIR');
40920 unset($_SERVER['GIT_DIR']);
40921 }
40922 if (getenv('GIT_WORK_TREE')) {
40923 putenv('GIT_WORK_TREE');
40924 unset($_SERVER['GIT_WORK_TREE']);
40925 }
40926
40927
40928  if (getenv('LANGUAGE') !== 'C') {
40929 putenv('LANGUAGE=C');
40930 }
40931
40932
40933  putenv("DYLD_LIBRARY_PATH");
40934 unset($_SERVER['DYLD_LIBRARY_PATH']);
40935 }
40936
40937 public static function getGitHubDomainsRegex(Config $config)
40938 {
40939 return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
40940 }
40941
40942 public static function sanitizeUrl($message)
40943 {
40944 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
40945 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
40946 return '://***:***@';
40947 }
40948
40949 return '://' . $m[1] . ':***@';
40950 }, $message);
40951 }
40952
40953 private function throwException($message, $url)
40954 {
40955
40956  clearstatcache();
40957
40958 if (0 !== $this->process->execute('git --version', $ignoredOutput)) {
40959 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()));
40960 }
40961
40962 throw new \RuntimeException(self::sanitizeUrl($message));
40963 }
40964
40965
40966
40967
40968
40969
40970 public function getVersion()
40971 {
40972 if (isset(self::$version)) {
40973 return self::$version;
40974 }
40975 if (0 !== $this->process->execute('git --version', $output)) {
40976 return;
40977 }
40978 if (preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
40979 return self::$version = $matches[1];
40980 }
40981 }
40982 }
40983 <?php
40984
40985
40986
40987
40988
40989
40990
40991
40992
40993
40994
40995 namespace Composer\Util;
40996
40997 use Composer\Factory;
40998 use Composer\IO\IOInterface;
40999 use Composer\Config;
41000 use Composer\Downloader\TransportException;
41001
41002
41003
41004
41005 class GitHub
41006 {
41007 protected $io;
41008 protected $config;
41009 protected $process;
41010 protected $remoteFilesystem;
41011
41012
41013
41014
41015
41016
41017
41018
41019
41020 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
41021 {
41022 $this->io = $io;
41023 $this->config = $config;
41024 $this->process = $process ?: new ProcessExecutor;
41025 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
41026 }
41027
41028
41029
41030
41031
41032
41033
41034 public function authorizeOAuth($originUrl)
41035 {
41036 if (!in_array($originUrl, $this->config->get('github-domains'))) {
41037 return false;
41038 }
41039
41040
41041  if (0 === $this->process->execute('git config github.accesstoken', $output)) {
41042 $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
41043
41044 return true;
41045 }
41046
41047 return false;
41048 }
41049
41050
41051
41052
41053
41054
41055
41056
41057
41058
41059 public function authorizeOAuthInteractively($originUrl, $message = null)
41060 {
41061 if ($message) {
41062 $this->io->writeError($message);
41063 }
41064
41065 $note = 'Composer';
41066 if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
41067 $note .= ' on ' . trim($output);
41068 }
41069 $note .= ' ' . date('Y-m-d Hi');
41070
41071 $url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
41072 $this->io->writeError(sprintf('Head to %s', $url));
41073 $this->io->writeError(sprintf('to retrieve a token. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
41074
41075 $token = trim($this->io->askAndHideAnswer('Token (hidden): '));
41076
41077 if (!$token) {
41078 $this->io->writeError('<warning>No token given, aborting.</warning>');
41079 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
41080
41081 return false;
41082 }
41083
41084 $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
41085
41086 try {
41087 $apiUrl = ('github.com' === $originUrl) ? 'api.github.com/' : $originUrl . '/api/v3/';
41088
41089 $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl, false, array(
41090 'retry-auth-failure' => false,
41091 ));
41092 } catch (TransportException $e) {
41093 if (in_array($e->getCode(), array(403, 401))) {
41094 $this->io->writeError('<error>Invalid token provided.</error>');
41095 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
41096
41097 return false;
41098 }
41099
41100 throw $e;
41101 }
41102
41103
41104  $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
41105 $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
41106
41107 $this->io->writeError('<info>Token stored successfully.</info>');
41108
41109 return true;
41110 }
41111 }
41112 <?php
41113
41114
41115
41116
41117
41118
41119
41120
41121
41122
41123
41124 namespace Composer\Util;
41125
41126 use Composer\IO\IOInterface;
41127 use Composer\Config;
41128 use Composer\Factory;
41129 use Composer\Downloader\TransportException;
41130 use Composer\Json\JsonFile;
41131
41132
41133
41134
41135 class GitLab
41136 {
41137 protected $io;
41138 protected $config;
41139 protected $process;
41140 protected $remoteFilesystem;
41141
41142
41143
41144
41145
41146
41147
41148
41149
41150 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
41151 {
41152 $this->io = $io;
41153 $this->config = $config;
41154 $this->process = $process ?: new ProcessExecutor();
41155 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
41156 }
41157
41158
41159
41160
41161
41162
41163
41164
41165 public function authorizeOAuth($originUrl)
41166 {
41167 if (!in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
41168 return false;
41169 }
41170
41171
41172  if (0 === $this->process->execute('git config gitlab.accesstoken', $output)) {
41173 $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
41174
41175 return true;
41176 }
41177
41178
41179  $authTokens = $this->config->get('gitlab-token');
41180
41181 if (isset($authTokens[$originUrl])) {
41182 $this->io->setAuthentication($originUrl, $authTokens[$originUrl], 'private-token');
41183
41184 return true;
41185 }
41186
41187 return false;
41188 }
41189
41190
41191
41192
41193
41194
41195
41196
41197
41198
41199
41200
41201
41202 public function authorizeOAuthInteractively($scheme, $originUrl, $message = null)
41203 {
41204 if ($message) {
41205 $this->io->writeError($message);
41206 }
41207
41208 $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
41209 $this->io->writeError('To revoke access to this token you can visit '.$originUrl.'/profile/applications');
41210
41211 $attemptCounter = 0;
41212
41213 while ($attemptCounter++ < 5) {
41214 try {
41215 $response = $this->createToken($scheme, $originUrl);
41216 } catch (TransportException $e) {
41217
41218  
41219  if (in_array($e->getCode(), array(403, 401))) {
41220 if (401 === $e->getCode()) {
41221 $this->io->writeError('Bad credentials.');
41222 } else {
41223 $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
41224 }
41225
41226 $this->io->writeError('You can also manually create a personal token at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
41227 $this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
41228
41229 continue;
41230 }
41231
41232 throw $e;
41233 }
41234
41235 $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
41236
41237
41238  $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
41239
41240 return true;
41241 }
41242
41243 throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
41244 }
41245
41246 private function createToken($scheme, $originUrl)
41247 {
41248 $username = $this->io->ask('Username: ');
41249 $password = $this->io->askAndHideAnswer('Password: ');
41250
41251 $headers = array('Content-Type: application/x-www-form-urlencoded');
41252
41253 $apiUrl = $originUrl;
41254 $data = http_build_query(array(
41255 'username' => $username,
41256 'password' => $password,
41257 'grant_type' => 'password',
41258 ), null, '&');
41259 $options = array(
41260 'retry-auth-failure' => false,
41261 'http' => array(
41262 'method' => 'POST',
41263 'header' => $headers,
41264 'content' => $data,
41265 ),
41266 );
41267
41268 $json = $this->remoteFilesystem->getContents($originUrl, $scheme.'://'.$apiUrl.'/oauth/token', false, $options);
41269
41270 $this->io->writeError('Token successfully created');
41271
41272 return JsonFile::parseJson($json);
41273 }
41274 }
41275 <?php
41276
41277
41278
41279
41280
41281
41282
41283
41284
41285
41286
41287 namespace Composer\Util;
41288
41289
41290
41291
41292
41293
41294
41295
41296 class IniHelper
41297 {
41298 const ENV_ORIGINAL = 'COMPOSER_ORIGINAL_INIS';
41299
41300
41301
41302
41303
41304
41305
41306
41307
41308 public static function getAll()
41309 {
41310 $env = getenv(self::ENV_ORIGINAL);
41311
41312 if (false !== $env) {
41313 return explode(PATH_SEPARATOR, $env);
41314 }
41315
41316 $paths = array(strval(php_ini_loaded_file()));
41317
41318 if ($scanned = php_ini_scanned_files()) {
41319 $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
41320 }
41321
41322 return $paths;
41323 }
41324
41325
41326
41327
41328
41329
41330 public static function getMessage()
41331 {
41332 $paths = self::getAll();
41333
41334 if (empty($paths[0])) {
41335 array_shift($paths);
41336 }
41337
41338 $ini = array_shift($paths);
41339
41340 if (empty($ini)) {
41341 return 'A php.ini file does not exist. You will have to create one.';
41342 }
41343
41344 if (!empty($paths)) {
41345 return 'Your command-line PHP is using multiple ini files. Run `php --ini` to show them.';
41346 }
41347
41348 return 'The php.ini used by your command-line PHP is: '.$ini;
41349 }
41350 }
41351 <?php
41352
41353
41354
41355
41356
41357
41358
41359
41360
41361
41362
41363 namespace Composer\Util;
41364
41365
41366
41367
41368 class NoProxyPattern
41369 {
41370
41371
41372
41373 protected $rules = array();
41374
41375
41376
41377
41378 public function __construct($pattern)
41379 {
41380 $this->rules = preg_split("/[\s,]+/", $pattern);
41381 }
41382
41383
41384
41385
41386
41387
41388
41389
41390 public function test($url)
41391 {
41392 $host = parse_url($url, PHP_URL_HOST);
41393 $port = parse_url($url, PHP_URL_PORT);
41394
41395 if (empty($port)) {
41396 switch (parse_url($url, PHP_URL_SCHEME)) {
41397 case 'http':
41398 $port = 80;
41399 break;
41400 case 'https':
41401 $port = 443;
41402 break;
41403 }
41404 }
41405
41406 foreach ($this->rules as $rule) {
41407 if ($rule == '*') {
41408 return true;
41409 }
41410
41411 $match = false;
41412
41413 list($ruleHost) = explode(':', $rule);
41414 list($base) = explode('/', $ruleHost);
41415
41416 if (filter_var($base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
41417
41418
41419 if (!isset($ip)) {
41420 $ip = gethostbyname($host);
41421 }
41422
41423 if (strpos($ruleHost, '/') === false) {
41424 $match = $ip === $ruleHost;
41425 } else {
41426
41427  
41428  if ($ip === $host) {
41429 $match = false;
41430 } else {
41431
41432  $match = self::inCIDRBlock($ruleHost, $ip);
41433 }
41434 }
41435 } else {
41436
41437
41438 $haystack = '.' . trim($host, '.') . '.';
41439 $needle = '.'. trim($ruleHost, '.') .'.';
41440 $match = stripos(strrev($haystack), strrev($needle)) === 0;
41441 }
41442
41443
41444  if ($match && strpos($rule, ':') !== false) {
41445 list(, $rulePort) = explode(':', $rule);
41446 if (!empty($rulePort) && $port != $rulePort) {
41447 $match = false;
41448 }
41449 }
41450
41451 if ($match) {
41452 return true;
41453 }
41454 }
41455
41456 return false;
41457 }
41458
41459
41460
41461
41462
41463
41464
41465
41466
41467
41468
41469 private static function inCIDRBlock($cidr, $ip)
41470 {
41471
41472  list($base, $bits) = explode('/', $cidr);
41473
41474
41475  list($a, $b, $c, $d) = explode('.', $base);
41476
41477
41478  $i = ($a << 24) + ($b << 16) + ($c << 8) + $d;
41479 $mask = $bits == 0 ? 0 : (~0 << (32 - $bits));
41480
41481
41482  $low = $i & $mask;
41483
41484
41485  $high = $i | (~$mask & 0xFFFFFFFF);
41486
41487
41488  list($a, $b, $c, $d) = explode('.', $ip);
41489
41490
41491  $check = ($a << 24) + ($b << 16) + ($c << 8) + $d;
41492
41493
41494  
41495  return $check >= $low && $check <= $high;
41496 }
41497 }
41498 <?php
41499
41500
41501
41502
41503
41504
41505
41506
41507
41508
41509
41510 namespace Composer\Util;
41511
41512 use Composer\IO\IOInterface;
41513 use Symfony\Component\Process\Process;
41514
41515
41516
41517
41518 class Perforce
41519 {
41520 protected $path;
41521 protected $p4Depot;
41522 protected $p4Client;
41523 protected $p4User;
41524 protected $p4Password;
41525 protected $p4Port;
41526 protected $p4Stream;
41527 protected $p4ClientSpec;
41528 protected $p4DepotType;
41529 protected $p4Branch;
41530 protected $process;
41531 protected $uniquePerforceClientName;
41532 protected $windowsFlag;
41533 protected $commandResult;
41534
41535 protected $io;
41536
41537 protected $filesystem;
41538
41539 public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
41540 {
41541 $this->windowsFlag = $isWindows;
41542 $this->p4Port = $port;
41543 $this->initializePath($path);
41544 $this->process = $process;
41545 $this->initialize($repoConfig);
41546 $this->io = $io;
41547 }
41548
41549 public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
41550 {
41551 return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io);
41552 }
41553
41554 public static function checkServerExists($url, ProcessExecutor $processExecutor)
41555 {
41556 $output = null;
41557
41558 return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s', $output);
41559 }
41560
41561 public function initialize($repoConfig)
41562 {
41563 $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
41564 if (!$repoConfig) {
41565 return;
41566 }
41567 if (isset($repoConfig['unique_perforce_client_name'])) {
41568 $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
41569 }
41570
41571 if (isset($repoConfig['depot'])) {
41572 $this->p4Depot = $repoConfig['depot'];
41573 }
41574 if (isset($repoConfig['branch'])) {
41575 $this->p4Branch = $repoConfig['branch'];
41576 }
41577 if (isset($repoConfig['p4user'])) {
41578 $this->p4User = $repoConfig['p4user'];
41579 } else {
41580 $this->p4User = $this->getP4variable('P4USER');
41581 }
41582 if (isset($repoConfig['p4password'])) {
41583 $this->p4Password = $repoConfig['p4password'];
41584 }
41585 }
41586
41587 public function initializeDepotAndBranch($depot, $branch)
41588 {
41589 if (isset($depot)) {
41590 $this->p4Depot = $depot;
41591 }
41592 if (isset($branch)) {
41593 $this->p4Branch = $branch;
41594 }
41595 }
41596
41597 public function generateUniquePerforceClientName()
41598 {
41599 return gethostname() . "_" . time();
41600 }
41601
41602 public function cleanupClientSpec()
41603 {
41604 $client = $this->getClient();
41605 $task = 'client -d ' . $client;
41606 $useP4Client = false;
41607 $command = $this->generateP4Command($task, $useP4Client);
41608 $this->executeCommand($command);
41609 $clientSpec = $this->getP4ClientSpec();
41610 $fileSystem = $this->getFilesystem();
41611 $fileSystem->remove($clientSpec);
41612 }
41613
41614 protected function executeCommand($command)
41615 {
41616 $this->commandResult = '';
41617
41618 return $this->process->execute($command, $this->commandResult);
41619 }
41620
41621 public function getClient()
41622 {
41623 if (!isset($this->p4Client)) {
41624 $cleanStreamName = str_replace(array('//', '/', '@'), array('', '_', ''), $this->getStream());
41625 $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
41626 }
41627
41628 return $this->p4Client;
41629 }
41630
41631 protected function getPath()
41632 {
41633 return $this->path;
41634 }
41635
41636 public function initializePath($path)
41637 {
41638 $this->path = $path;
41639 $fs = $this->getFilesystem();
41640 $fs->ensureDirectoryExists($path);
41641 }
41642
41643 protected function getPort()
41644 {
41645 return $this->p4Port;
41646 }
41647
41648 public function setStream($stream)
41649 {
41650 $this->p4Stream = $stream;
41651 $index = strrpos($stream, '/');
41652
41653  if ($index > 2) {
41654 $this->p4DepotType = 'stream';
41655 }
41656 }
41657
41658 public function isStream()
41659 {
41660 return (strcmp($this->p4DepotType, 'stream') === 0);
41661 }
41662
41663 public function getStream()
41664 {
41665 if (!isset($this->p4Stream)) {
41666 if ($this->isStream()) {
41667 $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
41668 } else {
41669 $this->p4Stream = '//' . $this->p4Depot;
41670 }
41671 }
41672
41673 return $this->p4Stream;
41674 }
41675
41676 public function getStreamWithoutLabel($stream)
41677 {
41678 $index = strpos($stream, '@');
41679 if ($index === false) {
41680 return $stream;
41681 }
41682
41683 return substr($stream, 0, $index);
41684 }
41685
41686 public function getP4ClientSpec()
41687 {
41688 return $this->path . '/' . $this->getClient() . '.p4.spec';
41689 }
41690
41691 public function getUser()
41692 {
41693 return $this->p4User;
41694 }
41695
41696 public function setUser($user)
41697 {
41698 $this->p4User = $user;
41699 }
41700
41701 public function queryP4User()
41702 {
41703 $this->getUser();
41704 if (strlen($this->p4User) > 0) {
41705 return;
41706 }
41707 $this->p4User = $this->getP4variable('P4USER');
41708 if (strlen($this->p4User) > 0) {
41709 return;
41710 }
41711 $this->p4User = $this->io->ask('Enter P4 User:');
41712 if ($this->windowsFlag) {
41713 $command = 'p4 set P4USER=' . $this->p4User;
41714 } else {
41715 $command = 'export P4USER=' . $this->p4User;
41716 }
41717 $this->executeCommand($command);
41718 }
41719
41720 protected function getP4variable($name)
41721 {
41722 if ($this->windowsFlag) {
41723 $command = 'p4 set';
41724 $this->executeCommand($command);
41725 $result = trim($this->commandResult);
41726 $resArray = explode(PHP_EOL, $result);
41727 foreach ($resArray as $line) {
41728 $fields = explode('=', $line);
41729 if (strcmp($name, $fields[0]) == 0) {
41730 $index = strpos($fields[1], ' ');
41731 if ($index === false) {
41732 $value = $fields[1];
41733 } else {
41734 $value = substr($fields[1], 0, $index);
41735 }
41736 $value = trim($value);
41737
41738 return $value;
41739 }
41740 }
41741
41742 return null;
41743 }
41744
41745 $command = 'echo $' . $name;
41746 $this->executeCommand($command);
41747 $result = trim($this->commandResult);
41748
41749 return $result;
41750 }
41751
41752 public function queryP4Password()
41753 {
41754 if (isset($this->p4Password)) {
41755 return $this->p4Password;
41756 }
41757 $password = $this->getP4variable('P4PASSWD');
41758 if (strlen($password) <= 0) {
41759 $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
41760 }
41761 $this->p4Password = $password;
41762
41763 return $password;
41764 }
41765
41766 public function generateP4Command($command, $useClient = true)
41767 {
41768 $p4Command = 'p4 ';
41769 $p4Command = $p4Command . '-u ' . $this->getUser() . ' ';
41770 if ($useClient) {
41771 $p4Command = $p4Command . '-c ' . $this->getClient() . ' ';
41772 }
41773 $p4Command = $p4Command . '-p ' . $this->getPort() . ' ' . $command;
41774
41775 return $p4Command;
41776 }
41777
41778 public function isLoggedIn()
41779 {
41780 $command = $this->generateP4Command('login -s', false);
41781 $exitCode = $this->executeCommand($command);
41782 if ($exitCode) {
41783 $errorOutput = $this->process->getErrorOutput();
41784 $index = strpos($errorOutput, $this->getUser());
41785 if ($index === false) {
41786 $index = strpos($errorOutput, 'p4');
41787 if ($index === false) {
41788 return false;
41789 }
41790 throw new \Exception('p4 command not found in path: ' . $errorOutput);
41791 }
41792 throw new \Exception('Invalid user name: ' . $this->getUser());
41793 }
41794
41795 return true;
41796 }
41797
41798 public function connectClient()
41799 {
41800 $p4CreateClientCommand = $this->generateP4Command(
41801 'client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())
41802 );
41803 $this->executeCommand($p4CreateClientCommand);
41804 }
41805
41806 public function syncCodeBase($sourceReference)
41807 {
41808 $prevDir = getcwd();
41809 chdir($this->path);
41810 $p4SyncCommand = $this->generateP4Command('sync -f ');
41811 if (null !== $sourceReference) {
41812 $p4SyncCommand = $p4SyncCommand . '@' . $sourceReference;
41813 }
41814 $this->executeCommand($p4SyncCommand);
41815 chdir($prevDir);
41816 }
41817
41818 public function writeClientSpecToFile($spec)
41819 {
41820 fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
41821 fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL);
41822 fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL);
41823 fwrite($spec, 'Owner:  ' . $this->getUser() . PHP_EOL . PHP_EOL);
41824 fwrite($spec, 'Description:' . PHP_EOL);
41825 fwrite($spec, '  Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL);
41826 fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL);
41827 fwrite($spec, 'Options:  noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL);
41828 fwrite($spec, 'SubmitOptions:  revertunchanged' . PHP_EOL . PHP_EOL);
41829 fwrite($spec, 'LineEnd:  local' . PHP_EOL . PHP_EOL);
41830 if ($this->isStream()) {
41831 fwrite($spec, 'Stream:' . PHP_EOL);
41832 fwrite($spec, '  ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL);
41833 } else {
41834 fwrite(
41835 $spec,
41836 'View:  ' . $this->getStream() . '/...  //' . $this->getClient() . '/... ' . PHP_EOL
41837 );
41838 }
41839 }
41840
41841 public function writeP4ClientSpec()
41842 {
41843 $clientSpec = $this->getP4ClientSpec();
41844 $spec = fopen($clientSpec, 'w');
41845 try {
41846 $this->writeClientSpecToFile($spec);
41847 } catch (\Exception $e) {
41848 fclose($spec);
41849 throw $e;
41850 }
41851 fclose($spec);
41852 }
41853
41854 protected function read($pipe, $name)
41855 {
41856 if (feof($pipe)) {
41857 return;
41858 }
41859 $line = fgets($pipe);
41860 while ($line !== false) {
41861 $line = fgets($pipe);
41862 }
41863
41864 return;
41865 }
41866
41867 public function windowsLogin($password)
41868 {
41869 $command = $this->generateP4Command(' login -a');
41870 $process = new Process($command, null, null, $password);
41871
41872 return $process->run();
41873 }
41874
41875 public function p4Login()
41876 {
41877 $this->queryP4User();
41878 if (!$this->isLoggedIn()) {
41879 $password = $this->queryP4Password();
41880 if ($this->windowsFlag) {
41881 $this->windowsLogin($password);
41882 } else {
41883 $command = 'echo ' . $password . ' | ' . $this->generateP4Command(' login -a', false);
41884 $exitCode = $this->executeCommand($command);
41885 $result = trim($this->commandResult);
41886 if ($exitCode) {
41887 throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
41888 }
41889 }
41890 }
41891 }
41892
41893 public function getComposerInformation($identifier)
41894 {
41895 $composerFileContent = $this->getFileContent('composer.json', $identifier);
41896
41897 if (!$composerFileContent) {
41898 return;
41899 }
41900
41901 return json_decode($composerFileContent, true);
41902 }
41903
41904 public function getFileContent($file, $identifier)
41905 {
41906 $path = $this->getFilePath($file, $identifier);
41907
41908 $command = $this->generateP4Command(' print ' . $path);
41909 $this->executeCommand($command);
41910 $result = $this->commandResult;
41911
41912 if (!trim($result)) {
41913 return null;
41914 }
41915
41916 return $result;
41917 }
41918
41919 public function getFilePath($file, $identifier)
41920 {
41921 $index = strpos($identifier, '@');
41922 if ($index === false) {
41923 $path = $identifier. '/' . $file;
41924
41925 return $path;
41926 }
41927
41928 $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index);
41929 $command = $this->generateP4Command(' files ' . $path, false);
41930 $this->executeCommand($command);
41931 $result = $this->commandResult;
41932 $index2 = strpos($result, 'no such file(s).');
41933 if ($index2 === false) {
41934 $index3 = strpos($result, 'change');
41935 if ($index3 !== false) {
41936 $phrase = trim(substr($result, $index3));
41937 $fields = explode(' ', $phrase);
41938
41939 return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1];
41940 }
41941 }
41942
41943 return null;
41944 }
41945
41946 public function getBranches()
41947 {
41948 $possibleBranches = array();
41949 if (!$this->isStream()) {
41950 $possibleBranches[$this->p4Branch] = $this->getStream();
41951 } else {
41952 $command = $this->generateP4Command('streams //' . $this->p4Depot . '/...');
41953 $this->executeCommand($command);
41954 $result = $this->commandResult;
41955 $resArray = explode(PHP_EOL, $result);
41956 foreach ($resArray as $line) {
41957 $resBits = explode(' ', $line);
41958 if (count($resBits) > 4) {
41959 $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
41960 $possibleBranches[$branch] = $resBits[1];
41961 }
41962 }
41963 }
41964 $command = $this->generateP4Command('changes '. $this->getStream() . '/...', false);
41965 $this->executeCommand($command);
41966 $result = $this->commandResult;
41967 $resArray = explode(PHP_EOL, $result);
41968 $lastCommit = $resArray[0];
41969 $lastCommitArr = explode(' ', $lastCommit);
41970 $lastCommitNum = $lastCommitArr[1];
41971
41972 $branches = array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
41973
41974 return $branches;
41975 }
41976
41977 public function getTags()
41978 {
41979 $command = $this->generateP4Command('labels');
41980 $this->executeCommand($command);
41981 $result = $this->commandResult;
41982 $resArray = explode(PHP_EOL, $result);
41983 $tags = array();
41984 foreach ($resArray as $line) {
41985 $index = strpos($line, 'Label');
41986 if (!($index === false)) {
41987 $fields = explode(' ', $line);
41988 $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
41989 }
41990 }
41991
41992 return $tags;
41993 }
41994
41995 public function checkStream()
41996 {
41997 $command = $this->generateP4Command('depots', false);
41998 $this->executeCommand($command);
41999 $result = $this->commandResult;
42000 $resArray = explode(PHP_EOL, $result);
42001 foreach ($resArray as $line) {
42002 $index = strpos($line, 'Depot');
42003 if (!($index === false)) {
42004 $fields = explode(' ', $line);
42005 if (strcmp($this->p4Depot, $fields[1]) === 0) {
42006 $this->p4DepotType = $fields[3];
42007
42008 return $this->isStream();
42009 }
42010 }
42011 }
42012
42013 return false;
42014 }
42015
42016
42017
42018
42019
42020 protected function getChangeList($reference)
42021 {
42022 $index = strpos($reference, '@');
42023 if ($index === false) {
42024 return null;
42025 }
42026 $label = substr($reference, $index);
42027 $command = $this->generateP4Command(' changes -m1 ' . $label);
42028 $this->executeCommand($command);
42029 $changes = $this->commandResult;
42030 if (strpos($changes, 'Change') !== 0) {
42031 return null;
42032 }
42033 $fields = explode(' ', $changes);
42034
42035 return $fields[1];
42036 }
42037
42038
42039
42040
42041
42042
42043 public function getCommitLogs($fromReference, $toReference)
42044 {
42045 $fromChangeList = $this->getChangeList($fromReference);
42046 if ($fromChangeList === null) {
42047 return null;
42048 }
42049 $toChangeList = $this->getChangeList($toReference);
42050 if ($toChangeList === null) {
42051 return null;
42052 }
42053 $index = strpos($fromReference, '@');
42054 $main = substr($fromReference, 0, $index) . '/...';
42055 $command = $this->generateP4Command('filelog ' . $main . '@' . $fromChangeList. ',' . $toChangeList);
42056 $this->executeCommand($command);
42057
42058 return $this->commandResult;
42059 }
42060
42061 public function getFilesystem()
42062 {
42063 if (empty($this->filesystem)) {
42064 $this->filesystem = new Filesystem($this->process);
42065 }
42066
42067 return $this->filesystem;
42068 }
42069
42070 public function setFilesystem(Filesystem $fs)
42071 {
42072 $this->filesystem = $fs;
42073 }
42074 }
42075 <?php
42076
42077
42078
42079
42080
42081
42082
42083
42084
42085
42086
42087 namespace Composer\Util;
42088
42089
42090
42091
42092
42093
42094 class Platform
42095 {
42096
42097
42098
42099
42100
42101
42102 public static function expandPath($path)
42103 {
42104 if (preg_match('#^~[\\/]#', $path)) {
42105 return self::getUserDirectory() . substr($path, 1);
42106 }
42107
42108 return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
42109
42110  if (Platform::isWindows() && $matches['var'] == 'HOME') {
42111 return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches['path'];
42112 }
42113
42114 return getenv($matches['var']) . $matches['path'];
42115 }, $path);
42116 }
42117
42118
42119
42120
42121
42122 public static function getUserDirectory()
42123 {
42124 if (false !== ($home = getenv('HOME'))) {
42125 return $home;
42126 }
42127
42128 if (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) {
42129 return $home;
42130 }
42131
42132 if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
42133 $info = posix_getpwuid(posix_getuid());
42134
42135 return $info['dir'];
42136 }
42137
42138 throw new \RuntimeException('Could not determine user directory');
42139 }
42140
42141
42142
42143
42144 public static function isWindows()
42145 {
42146 return defined('PHP_WINDOWS_VERSION_BUILD');
42147 }
42148
42149
42150
42151
42152
42153 public static function strlen($str)
42154 {
42155 static $useMbString = null;
42156 if (null === $useMbString) {
42157 $useMbString = function_exists('mb_strlen') && ini_get('mbstring.func_overload');
42158 }
42159
42160 if ($useMbString) {
42161 return mb_strlen($str, '8bit');
42162 }
42163
42164 return strlen($str);
42165 }
42166 }
42167 <?php
42168
42169
42170
42171
42172
42173
42174
42175
42176
42177
42178
42179 namespace Composer\Util;
42180
42181 use Composer\IO\IOInterface;
42182 use Symfony\Component\Process\Process;
42183 use Symfony\Component\Process\ProcessUtils;
42184
42185
42186
42187
42188 class ProcessExecutor
42189 {
42190 protected static $timeout = 300;
42191
42192 protected $captureOutput;
42193 protected $errorOutput;
42194 protected $io;
42195
42196 public function __construct(IOInterface $io = null)
42197 {
42198 $this->io = $io;
42199 }
42200
42201
42202
42203
42204
42205
42206
42207
42208
42209
42210 public function execute($command, &$output = null, $cwd = null)
42211 {
42212 if ($this->io && $this->io->isDebug()) {
42213 $safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
42214 if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) {
42215 return '://***:***@';
42216 }
42217
42218 return '://'.$m['user'].':***@';
42219 }, $command);
42220 $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
42221 }
42222
42223
42224  
42225  if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) {
42226 $cwd = realpath(getcwd());
42227 }
42228
42229 $this->captureOutput = count(func_get_args()) > 1;
42230 $this->errorOutput = null;
42231 $process = new Process($command, $cwd, null, null, static::getTimeout());
42232
42233 $callback = is_callable($output) ? $output : array($this, 'outputHandler');
42234 $process->run($callback);
42235
42236 if ($this->captureOutput && !is_callable($output)) {
42237 $output = $process->getOutput();
42238 }
42239
42240 $this->errorOutput = $process->getErrorOutput();
42241
42242 return $process->getExitCode();
42243 }
42244
42245 public function splitLines($output)
42246 {
42247 $output = trim($output);
42248
42249 return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output);
42250 }
42251
42252
42253
42254
42255
42256
42257 public function getErrorOutput()
42258 {
42259 return $this->errorOutput;
42260 }
42261
42262 public function outputHandler($type, $buffer)
42263 {
42264 if ($this->captureOutput) {
42265 return;
42266 }
42267
42268 if (null === $this->io) {
42269 echo $buffer;
42270
42271 return;
42272 }
42273
42274 if (Process::ERR === $type) {
42275 $this->io->writeError($buffer, false);
42276 } else {
42277 $this->io->write($buffer, false);
42278 }
42279 }
42280
42281 public static function getTimeout()
42282 {
42283 return static::$timeout;
42284 }
42285
42286 public static function setTimeout($timeout)
42287 {
42288 static::$timeout = $timeout;
42289 }
42290
42291
42292
42293
42294
42295
42296
42297
42298 public static function escape($argument)
42299 {
42300 if (method_exists('Symfony\Component\Process\ProcessUtils', 'escapeArgument')) {
42301 return ProcessUtils::escapeArgument($argument);
42302 }
42303
42304 return self::escapeArgument($argument);
42305 }
42306
42307
42308
42309
42310
42311
42312
42313
42314 private static function escapeArgument($argument)
42315 {
42316
42317  
42318  
42319  
42320  if ('\\' === DIRECTORY_SEPARATOR) {
42321 if ('' === $argument) {
42322 return escapeshellarg($argument);
42323 }
42324
42325 $escapedArgument = '';
42326 $quote = false;
42327 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
42328 if ('"' === $part) {
42329 $escapedArgument .= '\\"';
42330 } elseif (self::isSurroundedBy($part, '%')) {
42331
42332  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
42333 } else {
42334
42335  if ('\\' === substr($part, -1)) {
42336 $part .= '\\';
42337 }
42338 $quote = true;
42339 $escapedArgument .= $part;
42340 }
42341 }
42342 if ($quote) {
42343 $escapedArgument = '"'.$escapedArgument.'"';
42344 }
42345
42346 return $escapedArgument;
42347 }
42348
42349 return "'".str_replace("'", "'\\''", $argument)."'";
42350 }
42351
42352 private static function isSurroundedBy($arg, $char)
42353 {
42354 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
42355 }
42356 }
42357 <?php
42358
42359
42360
42361
42362
42363
42364
42365
42366
42367
42368
42369 namespace Composer\Util;
42370
42371 use Composer\Config;
42372 use Composer\IO\IOInterface;
42373 use Composer\Downloader\TransportException;
42374 use Composer\CaBundle\CaBundle;
42375 use Psr\Log\LoggerInterface;
42376
42377
42378
42379
42380
42381
42382 class RemoteFilesystem
42383 {
42384 private $io;
42385 private $config;
42386 private $scheme;
42387 private $bytesMax;
42388 private $originUrl;
42389 private $fileUrl;
42390 private $fileName;
42391 private $retry;
42392 private $progress;
42393 private $lastProgress;
42394 private $options = array();
42395 private $peerCertificateMap = array();
42396 private $disableTls = false;
42397 private $retryAuthFailure;
42398 private $lastHeaders;
42399 private $storeAuth;
42400 private $degradedMode = false;
42401 private $redirects;
42402 private $maxRedirects = 20;
42403
42404
42405
42406
42407
42408
42409
42410
42411
42412 public function __construct(IOInterface $io, Config $config = null, array $options = array(), $disableTls = false)
42413 {
42414 $this->io = $io;
42415
42416
42417  
42418  if ($disableTls === false) {
42419 $this->options = $this->getTlsDefaults($options);
42420 } else {
42421 $this->disableTls = true;
42422 }
42423
42424
42425  $this->options = array_replace_recursive($this->options, $options);
42426 $this->config = $config;
42427 }
42428
42429
42430
42431
42432
42433
42434
42435
42436
42437
42438
42439
42440 public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array())
42441 {
42442 return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
42443 }
42444
42445
42446
42447
42448
42449
42450
42451
42452
42453
42454
42455 public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
42456 {
42457 return $this->get($originUrl, $fileUrl, $options, null, $progress);
42458 }
42459
42460
42461
42462
42463
42464
42465 public function getOptions()
42466 {
42467 return $this->options;
42468 }
42469
42470
42471
42472
42473
42474
42475 public function setOptions(array $options)
42476 {
42477 $this->options = array_replace_recursive($this->options, $options);
42478 }
42479
42480 public function isTlsDisabled()
42481 {
42482 return $this->disableTls === true;
42483 }
42484
42485
42486
42487
42488
42489
42490 public function getLastHeaders()
42491 {
42492 return $this->lastHeaders;
42493 }
42494
42495
42496
42497
42498
42499
42500 public function findHeaderValue(array $headers, $name)
42501 {
42502 $value = null;
42503 foreach ($headers as $header) {
42504 if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
42505 $value = $match[1];
42506 } elseif (preg_match('{^HTTP/}i', $header)) {
42507
42508  
42509  $value = null;
42510 }
42511 }
42512
42513 return $value;
42514 }
42515
42516
42517
42518
42519
42520 public function findStatusCode(array $headers)
42521 {
42522 $value = null;
42523 foreach ($headers as $header) {
42524 if (preg_match('{^HTTP/\S+ (\d+)}i', $header, $match)) {
42525
42526  
42527  $value = (int) $match[1];
42528 }
42529 }
42530
42531 return $value;
42532 }
42533
42534
42535
42536
42537
42538
42539
42540
42541
42542
42543
42544
42545
42546
42547
42548 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
42549 {
42550 if (strpos($originUrl, '.github.com') === (strlen($originUrl) - 11)) {
42551 $originUrl = 'github.com';
42552 }
42553
42554
42555  
42556  if (
42557 $this->config
42558 && is_array($this->config->get('gitlab-domains'))
42559 && false === strpos($originUrl, '/')
42560 && !in_array($originUrl, $this->config->get('gitlab-domains'))
42561 ) {
42562 foreach ($this->config->get('gitlab-domains') as $gitlabDomain) {
42563 if (0 === strpos($gitlabDomain, $originUrl)) {
42564 $originUrl = $gitlabDomain;
42565 break;
42566 }
42567 }
42568 unset($gitlabDomain);
42569 }
42570
42571 $this->scheme = parse_url($fileUrl, PHP_URL_SCHEME);
42572 $this->bytesMax = 0;
42573 $this->originUrl = $originUrl;
42574 $this->fileUrl = $fileUrl;
42575 $this->fileName = $fileName;
42576 $this->progress = $progress;
42577 $this->lastProgress = null;
42578 $this->retryAuthFailure = true;
42579 $this->lastHeaders = array();
42580 $this->redirects = 1; 
42581
42582
42583  if (preg_match('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $fileUrl, $match)) {
42584 $this->io->setAuthentication($originUrl, urldecode($match[1]), urldecode($match[2]));
42585 }
42586
42587 $tempAdditionalOptions = $additionalOptions;
42588 if (isset($tempAdditionalOptions['retry-auth-failure'])) {
42589 $this->retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure'];
42590
42591 unset($tempAdditionalOptions['retry-auth-failure']);
42592 }
42593
42594 $isRedirect = false;
42595 if (isset($tempAdditionalOptions['redirects'])) {
42596 $this->redirects = $tempAdditionalOptions['redirects'];
42597 $isRedirect = true;
42598
42599 unset($tempAdditionalOptions['redirects']);
42600 }
42601
42602 $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions);
42603 unset($tempAdditionalOptions);
42604
42605 $origFileUrl = $fileUrl;
42606
42607 if (isset($options['github-token'])) {
42608
42609  if (preg_match('{^https?://([a-z0-9-]+\.)*github\.com/}', $fileUrl)) {
42610 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['github-token'];
42611 }
42612 unset($options['github-token']);
42613 }
42614
42615 if (isset($options['gitlab-token'])) {
42616 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['gitlab-token'];
42617 unset($options['gitlab-token']);
42618 }
42619
42620 if (isset($options['http'])) {
42621 $options['http']['ignore_errors'] = true;
42622 }
42623
42624 if ($this->degradedMode && substr($fileUrl, 0, 21) === 'http://packagist.org/') {
42625
42626  $fileUrl = 'http://' . gethostbyname('packagist.org') . substr($fileUrl, 20);
42627 $degradedPackagist = true;
42628 }
42629
42630 $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
42631
42632 $actualContextOptions = stream_context_get_options($ctx);
42633 $usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : '';
42634 $this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $origFileUrl . $usingProxy, true, IOInterface::DEBUG);
42635 unset($origFileUrl, $actualContextOptions);
42636
42637
42638  if ((substr($fileUrl, 0, 23) !== 'http://packagist.org/p/' || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist) && $this->config) {
42639 $this->config->prohibitUrlByConfig($fileUrl, $this->io);
42640 }
42641
42642 if ($this->progress && !$isRedirect) {
42643 $this->io->writeError("Downloading (<comment>connecting...</comment>)", false);
42644 }
42645
42646 $errorMessage = '';
42647 $errorCode = 0;
42648 $result = false;
42649 set_error_handler(function ($code, $msg) use (&$errorMessage) {
42650 if ($errorMessage) {
42651 $errorMessage .= "\n";
42652 }
42653 $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg);
42654 });
42655 try {
42656 $result = file_get_contents($fileUrl, false, $ctx);
42657
42658 $contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
42659 if ($contentLength && Platform::strlen($result) < $contentLength) {
42660
42661  $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength);
42662 $e->setHeaders($http_response_header);
42663 $e->setStatusCode($this->findStatusCode($http_response_header));
42664 $e->setResponse($result);
42665 $this->io->writeError('Content-Length mismatch, received '.Platform::strlen($result).' out of '.$contentLength.' bytes: (' . base64_encode($result).')', true, IOInterface::DEBUG);
42666
42667 throw $e;
42668 }
42669
42670 if (PHP_VERSION_ID < 50600 && !empty($options['ssl']['peer_fingerprint'])) {
42671
42672  $params = stream_context_get_params($ctx);
42673 $expectedPeerFingerprint = $options['ssl']['peer_fingerprint'];
42674 $peerFingerprint = TlsHelper::getCertificateFingerprint($params['options']['ssl']['peer_certificate']);
42675
42676
42677  if ($expectedPeerFingerprint !== $peerFingerprint) {
42678 throw new TransportException('Peer fingerprint did not match');
42679 }
42680 }
42681 } catch (\Exception $e) {
42682 if ($e instanceof TransportException && !empty($http_response_header[0])) {
42683 $e->setHeaders($http_response_header);
42684 $e->setStatusCode($this->findStatusCode($http_response_header));
42685 }
42686 if ($e instanceof TransportException && $result !== false) {
42687 $e->setResponse($result);
42688 }
42689 $result = false;
42690 }
42691 if ($errorMessage && !ini_get('allow_url_fopen')) {
42692 $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
42693 }
42694 restore_error_handler();
42695 if (isset($e) && !$this->retry) {
42696 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
42697 $this->degradedMode = true;
42698 $this->io->writeError('');
42699 $this->io->writeError(array(
42700 '<error>'.$e->getMessage().'</error>',
42701 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42702 ));
42703
42704 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42705 }
42706
42707 throw $e;
42708 }
42709
42710 $statusCode = null;
42711 $contentType = null;
42712 if (!empty($http_response_header[0])) {
42713 $statusCode = $this->findStatusCode($http_response_header);
42714 $contentType = $this->findHeaderValue($http_response_header, 'content-type');
42715 }
42716
42717
42718  if ($originUrl === 'bitbucket.org'
42719 && !$this->isPublicBitBucketDownload($fileUrl)
42720 && substr($fileUrl, -4) === '.zip'
42721 && $contentType && preg_match('{^text/html\b}i', $contentType)
42722 ) {
42723 $result = false;
42724 if ($this->retryAuthFailure) {
42725 $this->promptAuthAndRetry(401);
42726 }
42727 }
42728
42729
42730  if ($statusCode === 404
42731 && $this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)
42732 && false !== strpos($fileUrl, 'archive.zip')
42733 ) {
42734 $result = false;
42735 if ($this->retryAuthFailure) {
42736 $this->promptAuthAndRetry(401);
42737 }
42738 }
42739
42740
42741  $hasFollowedRedirect = false;
42742 if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
42743 $hasFollowedRedirect = true;
42744 $result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
42745 }
42746
42747
42748  if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
42749 if (!$this->retry) {
42750 if ($this->progress && !$this->retry && !$isRedirect) {
42751 $this->io->overwriteError("Downloading (<error>failed</error>)", false);
42752 }
42753
42754 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $statusCode);
42755 $e->setHeaders($http_response_header);
42756 $e->setResponse($result);
42757 $e->setStatusCode($statusCode);
42758 throw $e;
42759 }
42760 $result = false;
42761 }
42762
42763 if ($this->progress && !$this->retry && !$isRedirect) {
42764 $this->io->overwriteError("Downloading (".($result === false ? '<error>failed</error>' : '<comment>100%</comment>').")", false);
42765 }
42766
42767
42768  if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) {
42769 $contentEncoding = $this->findHeaderValue($http_response_header, 'content-encoding');
42770 $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
42771
42772 if ($decode) {
42773 try {
42774 if (PHP_VERSION_ID >= 50400) {
42775 $result = zlib_decode($result);
42776 } else {
42777
42778  $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
42779 }
42780
42781 if (!$result) {
42782 throw new TransportException('Failed to decode zlib stream');
42783 }
42784 } catch (\Exception $e) {
42785 if ($this->degradedMode) {
42786 throw $e;
42787 }
42788
42789 $this->degradedMode = true;
42790 $this->io->writeError(array(
42791 '',
42792 '<error>Failed to decode response: '.$e->getMessage().'</error>',
42793 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42794 ));
42795
42796 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42797 }
42798 }
42799 }
42800
42801
42802  if (false !== $result && null !== $fileName && !$isRedirect) {
42803 if ('' === $result) {
42804 throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
42805 }
42806
42807 $errorMessage = '';
42808 set_error_handler(function ($code, $msg) use (&$errorMessage) {
42809 if ($errorMessage) {
42810 $errorMessage .= "\n";
42811 }
42812 $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg);
42813 });
42814 $result = (bool) file_put_contents($fileName, $result);
42815 restore_error_handler();
42816 if (false === $result) {
42817 throw new TransportException('The "'.$this->fileUrl.'" file could not be written to '.$fileName.': '.$errorMessage);
42818 }
42819 }
42820
42821
42822  if (false === $result && false !== strpos($errorMessage, 'Peer certificate') && PHP_VERSION_ID < 50600) {
42823
42824  
42825  
42826  
42827  
42828  
42829  
42830  
42831  
42832  
42833  
42834  
42835  
42836  
42837  
42838  
42839  if (CaBundle::isOpensslParseSafe()) {
42840 $certDetails = $this->getCertificateCnAndFp($this->fileUrl, $options);
42841
42842 if ($certDetails) {
42843 $this->peerCertificateMap[$this->getUrlAuthority($this->fileUrl)] = $certDetails;
42844
42845 $this->retry = true;
42846 }
42847 } else {
42848 $this->io->writeError('');
42849 $this->io->writeError(sprintf(
42850 '<error>Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.</error>',
42851 PHP_VERSION
42852 ));
42853 }
42854 }
42855
42856 if ($this->retry) {
42857 $this->retry = false;
42858
42859 $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42860
42861 if ($this->storeAuth && $this->config) {
42862 $authHelper = new AuthHelper($this->io, $this->config);
42863 $authHelper->storeAuth($this->originUrl, $this->storeAuth);
42864 $this->storeAuth = false;
42865 }
42866
42867 return $result;
42868 }
42869
42870 if (false === $result) {
42871 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded: '.$errorMessage, $errorCode);
42872 if (!empty($http_response_header[0])) {
42873 $e->setHeaders($http_response_header);
42874 }
42875
42876 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
42877 $this->degradedMode = true;
42878 $this->io->writeError('');
42879 $this->io->writeError(array(
42880 '<error>'.$e->getMessage().'</error>',
42881 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42882 ));
42883
42884 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42885 }
42886
42887 throw $e;
42888 }
42889
42890 if (!empty($http_response_header[0])) {
42891 $this->lastHeaders = $http_response_header;
42892 }
42893
42894 return $result;
42895 }
42896
42897
42898
42899
42900
42901
42902
42903
42904
42905
42906
42907
42908 protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
42909 {
42910 switch ($notificationCode) {
42911 case STREAM_NOTIFY_FAILURE:
42912 if (400 === $messageCode) {
42913
42914  
42915  throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
42916 }
42917
42918  
42919
42920 case STREAM_NOTIFY_AUTH_REQUIRED:
42921 if (401 === $messageCode) {
42922
42923  if (!$this->retryAuthFailure) {
42924 break;
42925 }
42926
42927 $this->promptAuthAndRetry($messageCode);
42928 }
42929 break;
42930
42931 case STREAM_NOTIFY_AUTH_RESULT:
42932 if (403 === $messageCode) {
42933
42934  if (!$this->retryAuthFailure) {
42935 break;
42936 }
42937
42938 $this->promptAuthAndRetry($messageCode, $message);
42939 }
42940 break;
42941
42942 case STREAM_NOTIFY_FILE_SIZE_IS:
42943 $this->bytesMax = $bytesMax;
42944 break;
42945
42946 case STREAM_NOTIFY_PROGRESS:
42947 if ($this->bytesMax > 0 && $this->progress) {
42948 $progression = min(100, round($bytesTransferred / $this->bytesMax * 100));
42949
42950 if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) {
42951 $this->lastProgress = $progression;
42952 $this->io->overwriteError("Downloading (<comment>$progression%</comment>)", false);
42953 }
42954 }
42955 break;
42956
42957 default:
42958 break;
42959 }
42960 }
42961
42962 protected function promptAuthAndRetry($httpStatus, $reason = null)
42963 {
42964 if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
42965 $message = "\n".'Could not fetch '.$this->fileUrl.', please create a GitHub OAuth token '.($httpStatus === 404 ? 'to access private repos' : 'to go over the API rate limit');
42966 $gitHubUtil = new GitHub($this->io, $this->config, null);
42967 if (!$gitHubUtil->authorizeOAuth($this->originUrl)
42968 && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($this->originUrl, $message))
42969 ) {
42970 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
42971 }
42972 } elseif ($this->config && in_array($this->originUrl, $this->config->get('gitlab-domains'), true)) {
42973 $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');
42974 $gitLabUtil = new GitLab($this->io, $this->config, null);
42975
42976 if ($this->io->hasAuthentication($this->originUrl) && ($auth = $this->io->getAuthentication($this->originUrl)) && $auth['password'] === 'private-token') {
42977 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
42978 }
42979
42980 if (!$gitLabUtil->authorizeOAuth($this->originUrl)
42981 && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, $message))
42982 ) {
42983 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
42984 }
42985 } elseif ($this->config && $this->originUrl === 'bitbucket.org') {
42986 $askForOAuthToken = true;
42987 if ($this->io->hasAuthentication($this->originUrl)) {
42988 $auth = $this->io->getAuthentication($this->originUrl);
42989 if ($auth['username'] !== 'x-token-auth') {
42990 $bitbucketUtil = new Bitbucket($this->io, $this->config);
42991 $accessToken = $bitbucketUtil->requestToken($this->originUrl, $auth['username'], $auth['password']);
42992 if (!empty($accessToken)) {
42993 $this->io->setAuthentication($this->originUrl, 'x-token-auth', $accessToken);
42994 $askForOAuthToken = false;
42995 }
42996 } else {
42997 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
42998 }
42999 }
43000
43001 if ($askForOAuthToken) {
43002 $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');
43003 $bitBucketUtil = new Bitbucket($this->io, $this->config);
43004 if (! $bitBucketUtil->authorizeOAuth($this->originUrl)
43005 && (! $this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($this->originUrl, $message))
43006 ) {
43007 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
43008 }
43009 }
43010 } else {
43011
43012  if ($httpStatus === 404) {
43013 return;
43014 }
43015
43016
43017  if (!$this->io->isInteractive()) {
43018 if ($httpStatus === 401) {
43019 $message = "The '" . $this->fileUrl . "' URL required authentication.\nYou must be using the interactive console to authenticate";
43020 }
43021 if ($httpStatus === 403) {
43022 $message = "The '" . $this->fileUrl . "' URL could not be accessed: " . $reason;
43023 }
43024
43025 throw new TransportException($message, $httpStatus);
43026 }
43027
43028  if ($this->io->hasAuthentication($this->originUrl)) {
43029 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
43030 }
43031
43032 $this->io->overwriteError('');
43033 $this->io->writeError('    Authentication required (<info>'.parse_url($this->fileUrl, PHP_URL_HOST).'</info>):');
43034 $username = $this->io->ask('      Username: ');
43035 $password = $this->io->askAndHideAnswer('      Password: ');
43036 $this->io->setAuthentication($this->originUrl, $username, $password);
43037 $this->storeAuth = $this->config->get('store-auths');
43038 }
43039
43040 $this->retry = true;
43041 throw new TransportException('RETRY');
43042 }
43043
43044 protected function getOptionsForUrl($originUrl, $additionalOptions)
43045 {
43046 $tlsOptions = array();
43047
43048
43049  if ($this->disableTls === false && PHP_VERSION_ID < 50600 && !stream_is_local($this->fileUrl)) {
43050 $host = parse_url($this->fileUrl, PHP_URL_HOST);
43051
43052 if (PHP_VERSION_ID < 50304) {
43053
43054  
43055  
43056  
43057
43058 if ($host === 'github.com' || $host === 'api.github.com') {
43059 $host = '*.github.com';
43060 }
43061 }
43062
43063 $tlsOptions['ssl']['CN_match'] = $host;
43064 $tlsOptions['ssl']['SNI_server_name'] = $host;
43065
43066 $urlAuthority = $this->getUrlAuthority($this->fileUrl);
43067
43068 if (isset($this->peerCertificateMap[$urlAuthority])) {
43069
43070  $certMap = $this->peerCertificateMap[$urlAuthority];
43071
43072 $this->io->writeError('', true, IOInterface::DEBUG);
43073 $this->io->writeError(sprintf(
43074 'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
43075 $certMap['cn'],
43076 $urlAuthority
43077 ), true, IOInterface::DEBUG);
43078
43079 $tlsOptions['ssl']['CN_match'] = $certMap['cn'];
43080 $tlsOptions['ssl']['peer_fingerprint'] = $certMap['fp'];
43081 }
43082 }
43083
43084 $headers = array();
43085
43086 if (extension_loaded('zlib')) {
43087 $headers[] = 'Accept-Encoding: gzip';
43088 }
43089
43090 $options = array_replace_recursive($this->options, $tlsOptions, $additionalOptions);
43091 if (!$this->degradedMode) {
43092
43093  
43094  $options['http']['protocol_version'] = 1.1;
43095 $headers[] = 'Connection: close';
43096 }
43097
43098 if ($this->io->hasAuthentication($originUrl)) {
43099 $auth = $this->io->getAuthentication($originUrl);
43100 if ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
43101 $options['github-token'] = $auth['username'];
43102 } elseif ($this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
43103 if ($auth['password'] === 'oauth2') {
43104 $headers[] = 'Authorization: Bearer '.$auth['username'];
43105 } elseif ($auth['password'] === 'private-token') {
43106 $headers[] = 'PRIVATE-TOKEN: '.$auth['username'];
43107 }
43108 } elseif ('bitbucket.org' === $originUrl
43109 && $this->fileUrl !== Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']
43110 ) {
43111 if (!$this->isPublicBitBucketDownload($this->fileUrl)) {
43112 $headers[] = 'Authorization: Bearer ' . $auth['password'];
43113 }
43114 } else {
43115 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
43116 $headers[] = 'Authorization: Basic '.$authStr;
43117 }
43118 }
43119
43120 $options['http']['follow_location'] = 0;
43121
43122 if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
43123 $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
43124 }
43125 foreach ($headers as $header) {
43126 $options['http']['header'][] = $header;
43127 }
43128
43129 return $options;
43130 }
43131
43132 private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
43133 {
43134 if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
43135 if (parse_url($locationHeader, PHP_URL_SCHEME)) {
43136
43137  $targetUrl = $locationHeader;
43138 } elseif (parse_url($locationHeader, PHP_URL_HOST)) {
43139
43140  $targetUrl = $this->scheme.':'.$locationHeader;
43141 } elseif ('/' === $locationHeader[0]) {
43142
43143  $urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
43144
43145
43146  $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
43147 } else {
43148
43149  
43150  $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
43151 }
43152 }
43153
43154 if (!empty($targetUrl)) {
43155 $this->redirects++;
43156
43157 $this->io->writeError('', true, IOInterface::DEBUG);
43158 $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $targetUrl), true, IOInterface::DEBUG);
43159
43160 $additionalOptions['redirects'] = $this->redirects;
43161
43162 return $this->get(parse_url($targetUrl, PHP_URL_HOST), $targetUrl, $additionalOptions, $this->fileName, $this->progress);
43163 }
43164
43165 if (!$this->retry) {
43166 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
43167 $e->setHeaders($http_response_header);
43168 $e->setResponse($result);
43169
43170 throw $e;
43171 }
43172
43173 return false;
43174 }
43175
43176
43177
43178
43179
43180
43181 private function getTlsDefaults(array $options)
43182 {
43183 $ciphers = implode(':', array(
43184 'ECDHE-RSA-AES128-GCM-SHA256',
43185 'ECDHE-ECDSA-AES128-GCM-SHA256',
43186 'ECDHE-RSA-AES256-GCM-SHA384',
43187 'ECDHE-ECDSA-AES256-GCM-SHA384',
43188 'DHE-RSA-AES128-GCM-SHA256',
43189 'DHE-DSS-AES128-GCM-SHA256',
43190 'kEDH+AESGCM',
43191 'ECDHE-RSA-AES128-SHA256',
43192 'ECDHE-ECDSA-AES128-SHA256',
43193 'ECDHE-RSA-AES128-SHA',
43194 'ECDHE-ECDSA-AES128-SHA',
43195 'ECDHE-RSA-AES256-SHA384',
43196 'ECDHE-ECDSA-AES256-SHA384',
43197 'ECDHE-RSA-AES256-SHA',
43198 'ECDHE-ECDSA-AES256-SHA',
43199 'DHE-RSA-AES128-SHA256',
43200 'DHE-RSA-AES128-SHA',
43201 'DHE-DSS-AES128-SHA256',
43202 'DHE-RSA-AES256-SHA256',
43203 'DHE-DSS-AES256-SHA',
43204 'DHE-RSA-AES256-SHA',
43205 'AES128-GCM-SHA256',
43206 'AES256-GCM-SHA384',
43207 'AES128-SHA256',
43208 'AES256-SHA256',
43209 'AES128-SHA',
43210 'AES256-SHA',
43211 'AES',
43212 'CAMELLIA',
43213 'DES-CBC3-SHA',
43214 '!aNULL',
43215 '!eNULL',
43216 '!EXPORT',
43217 '!DES',
43218 '!RC4',
43219 '!MD5',
43220 '!PSK',
43221 '!aECDH',
43222 '!EDH-DSS-DES-CBC3-SHA',
43223 '!EDH-RSA-DES-CBC3-SHA',
43224 '!KRB5-DES-CBC3-SHA',
43225 ));
43226
43227
43228
43229
43230
43231
43232
43233 $defaults = array(
43234 'ssl' => array(
43235 'ciphers' => $ciphers,
43236 'verify_peer' => true,
43237 'verify_depth' => 7,
43238 'SNI_enabled' => true,
43239 'capture_peer_cert' => true,
43240 ),
43241 );
43242
43243 if (isset($options['ssl'])) {
43244 $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
43245 }
43246
43247 $caBundleLogger = $this->io instanceof LoggerInterface ? $this->io : null;
43248
43249
43250
43251
43252
43253 if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
43254 $result = CaBundle::getSystemCaRootBundlePath($caBundleLogger);
43255
43256 if (is_dir($result)) {
43257 $defaults['ssl']['capath'] = $result;
43258 } else {
43259 $defaults['ssl']['cafile'] = $result;
43260 }
43261 }
43262
43263 if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $caBundleLogger))) {
43264 throw new TransportException('The configured cafile was not valid or could not be read.');
43265 }
43266
43267 if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !is_readable($defaults['ssl']['capath']))) {
43268 throw new TransportException('The configured capath was not valid or could not be read.');
43269 }
43270
43271
43272
43273
43274 if (PHP_VERSION_ID >= 50413) {
43275 $defaults['ssl']['disable_compression'] = true;
43276 }
43277
43278 return $defaults;
43279 }
43280
43281
43282
43283
43284
43285
43286 private function getCertificateCnAndFp($url, $options)
43287 {
43288 if (PHP_VERSION_ID >= 50600) {
43289 throw new \BadMethodCallException(sprintf(
43290 '%s must not be used on PHP >= 5.6',
43291 __METHOD__
43292 ));
43293 }
43294
43295 $context = StreamContextFactory::getContext($url, $options, array('options' => array(
43296 'ssl' => array(
43297 'capture_peer_cert' => true,
43298 'verify_peer' => false, 
43299  ), ),
43300 ));
43301
43302
43303  
43304  if (false === $handle = @fopen($url, 'rb', false, $context)) {
43305 return;
43306 }
43307
43308
43309  fclose($handle);
43310 $handle = null;
43311
43312 $params = stream_context_get_params($context);
43313
43314 if (!empty($params['options']['ssl']['peer_certificate'])) {
43315 $peerCertificate = $params['options']['ssl']['peer_certificate'];
43316
43317 if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) {
43318 return array(
43319 'cn' => $commonName,
43320 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate),
43321 );
43322 }
43323 }
43324 }
43325
43326 private function getUrlAuthority($url)
43327 {
43328 $defaultPorts = array(
43329 'ftp' => 21,
43330 'http' => 80,
43331 'https' => 443,
43332 'ssh2.sftp' => 22,
43333 'ssh2.scp' => 22,
43334 );
43335
43336 $scheme = parse_url($url, PHP_URL_SCHEME);
43337
43338 if (!isset($defaultPorts[$scheme])) {
43339 throw new \InvalidArgumentException(sprintf(
43340 'Could not get default port for unknown scheme: %s',
43341 $scheme
43342 ));
43343 }
43344
43345 $defaultPort = $defaultPorts[$scheme];
43346 $port = parse_url($url, PHP_URL_PORT) ?: $defaultPort;
43347
43348 return parse_url($url, PHP_URL_HOST).':'.$port;
43349 }
43350
43351
43352
43353
43354
43355
43356
43357
43358 private function isPublicBitBucketDownload($urlToBitBucketFile)
43359 {
43360 $domain = parse_url($urlToBitBucketFile, PHP_URL_HOST);
43361 if (strpos($domain, 'bitbucket.org') === false) {
43362
43363  
43364  return true;
43365 }
43366
43367 $path = parse_url($urlToBitBucketFile, PHP_URL_PATH);
43368
43369
43370  
43371  $pathParts = explode('/', $path);
43372
43373 return count($pathParts) >= 4 && $pathParts[3] == 'downloads';
43374 }
43375 }
43376 <?php
43377
43378
43379
43380
43381
43382
43383
43384
43385
43386
43387
43388 namespace Composer\Util;
43389
43390
43391
43392
43393
43394
43395 class Silencer
43396 {
43397
43398
43399
43400 private static $stack = array();
43401
43402
43403
43404
43405
43406
43407
43408 public static function suppress($mask = null)
43409 {
43410 if (!isset($mask)) {
43411 $mask = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT;
43412 }
43413 $old = error_reporting();
43414 self::$stack[] = $old;
43415 error_reporting($old & ~$mask);
43416
43417 return $old;
43418 }
43419
43420
43421
43422
43423 public static function restore()
43424 {
43425 if (!empty(self::$stack)) {
43426 error_reporting(array_pop(self::$stack));
43427 }
43428 }
43429
43430
43431
43432
43433
43434
43435
43436
43437
43438
43439 public static function call($callable )
43440 {
43441 try {
43442 self::suppress();
43443 $result = call_user_func_array($callable, array_slice(func_get_args(), 1));
43444 self::restore();
43445
43446 return $result;
43447 } catch (\Exception $e) {
43448
43449  self::restore();
43450 throw $e;
43451 }
43452 }
43453 }
43454 <?php
43455
43456
43457
43458
43459
43460
43461
43462
43463
43464
43465
43466 namespace Composer\Util;
43467
43468 use Composer\Spdx\SpdxLicenses;
43469
43470 trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED);
43471
43472
43473
43474
43475 class SpdxLicense extends SpdxLicenses
43476 {
43477 }
43478 <?php
43479
43480
43481
43482
43483
43484
43485
43486
43487
43488
43489
43490 namespace Composer\Util;
43491
43492 use Composer\Composer;
43493
43494
43495
43496
43497
43498
43499
43500 final class StreamContextFactory
43501 {
43502
43503
43504
43505
43506
43507
43508
43509
43510
43511 public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
43512 {
43513 $options = array('http' => array(
43514
43515  'follow_location' => 1,
43516 'max_redirects' => 20,
43517 ));
43518
43519
43520  if (PHP_SAPI === 'cli' && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) {
43521 $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
43522 }
43523
43524
43525  if (!empty($_SERVER['CGI_HTTP_PROXY'])) {
43526 $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']);
43527 }
43528
43529
43530  if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
43531 $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
43532 }
43533
43534
43535  if (!empty($_SERVER['NO_PROXY']) || !empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
43536 $pattern = new NoProxyPattern(!empty($_SERVER['no_proxy']) ? $_SERVER['no_proxy'] : $_SERVER['NO_PROXY']);
43537 if ($pattern->test($url)) {
43538 unset($proxy);
43539 }
43540 }
43541
43542 if (!empty($proxy)) {
43543 $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
43544 $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
43545
43546 if (isset($proxy['port'])) {
43547 $proxyURL .= ":" . $proxy['port'];
43548 } elseif ('http://' == substr($proxyURL, 0, 7)) {
43549 $proxyURL .= ":80";
43550 } elseif ('https://' == substr($proxyURL, 0, 8)) {
43551 $proxyURL .= ":443";
43552 }
43553
43554
43555  $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
43556
43557 if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) {
43558 throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
43559 }
43560
43561 $options['http']['proxy'] = $proxyURL;
43562
43563
43564  switch (parse_url($url, PHP_URL_SCHEME)) {
43565 case 'http': 
43566  $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
43567 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
43568 $options['http']['request_fulluri'] = true;
43569 }
43570 break;
43571 case 'https': 
43572  $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
43573 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
43574 $options['http']['request_fulluri'] = true;
43575 }
43576 break;
43577 }
43578
43579
43580  if ('https' === parse_url($url, PHP_URL_SCHEME)) {
43581 $options['ssl']['SNI_enabled'] = true;
43582 if (PHP_VERSION_ID < 50600) {
43583 $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST);
43584 }
43585 }
43586
43587
43588  if (isset($proxy['user'])) {
43589 $auth = urldecode($proxy['user']);
43590 if (isset($proxy['pass'])) {
43591 $auth .= ':' . urldecode($proxy['pass']);
43592 }
43593 $auth = base64_encode($auth);
43594
43595
43596  if (isset($defaultOptions['http']['header'])) {
43597 if (is_string($defaultOptions['http']['header'])) {
43598 $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
43599 }
43600 $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
43601 } else {
43602 $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
43603 }
43604 }
43605 }
43606
43607 $options = array_replace_recursive($options, $defaultOptions);
43608
43609 if (isset($options['http']['header'])) {
43610 $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
43611 }
43612
43613 if (defined('HHVM_VERSION')) {
43614 $phpVersion = 'HHVM ' . HHVM_VERSION;
43615 } else {
43616 $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
43617 }
43618
43619 if (!isset($options['http']['header']) || false === stripos(implode('', $options['http']['header']), 'user-agent')) {
43620 $options['http']['header'][] = sprintf(
43621 'User-Agent: Composer/%s (%s; %s; %s%s)',
43622 Composer::VERSION === '@package_version@' ? 'source' : Composer::VERSION,
43623 function_exists('php_uname') ? php_uname('s') : 'Unknown',
43624 function_exists('php_uname') ? php_uname('r') : 'Unknown',
43625 $phpVersion,
43626 getenv('CI') ? '; CI' : ''
43627 );
43628 }
43629
43630 return stream_context_create($options, $defaultParams);
43631 }
43632
43633
43634
43635
43636
43637
43638
43639
43640
43641
43642
43643 private static function fixHttpHeaderField($header)
43644 {
43645 if (!is_array($header)) {
43646 $header = explode("\r\n", $header);
43647 }
43648 uasort($header, function ($el) {
43649 return preg_match('{^content-type}i', $el) ? 1 : -1;
43650 });
43651
43652 return $header;
43653 }
43654 }
43655 <?php
43656
43657
43658
43659
43660
43661
43662
43663
43664
43665
43666
43667 namespace Composer\Util;
43668
43669 use Composer\Config;
43670 use Composer\IO\IOInterface;
43671
43672
43673
43674
43675
43676 class Svn
43677 {
43678 const MAX_QTY_AUTH_TRIES = 5;
43679
43680
43681
43682
43683 protected $credentials;
43684
43685
43686
43687
43688 protected $hasAuth;
43689
43690
43691
43692
43693 protected $io;
43694
43695
43696
43697
43698 protected $url;
43699
43700
43701
43702
43703 protected $cacheCredentials = true;
43704
43705
43706
43707
43708 protected $process;
43709
43710
43711
43712
43713 protected $qtyAuthTries = 0;
43714
43715
43716
43717
43718 protected $config;
43719
43720
43721
43722
43723
43724
43725
43726 public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null)
43727 {
43728 $this->url = $url;
43729 $this->io = $io;
43730 $this->config = $config;
43731 $this->process = $process ?: new ProcessExecutor;
43732 }
43733
43734 public static function cleanEnv()
43735 {
43736
43737  putenv("DYLD_LIBRARY_PATH");
43738 unset($_SERVER['DYLD_LIBRARY_PATH']);
43739 }
43740
43741
43742
43743
43744
43745
43746
43747
43748
43749
43750
43751
43752
43753
43754 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
43755 {
43756
43757  $this->config->prohibitUrlByConfig($url, $this->io);
43758
43759 $svnCommand = $this->getCommand($command, $url, $path);
43760
43761 return $this->executeWithAuthRetry($svnCommand, $cwd, $path, $verbose);
43762 }
43763
43764
43765
43766
43767
43768
43769
43770
43771
43772
43773
43774
43775
43776 public function executeLocal($command, $path, $cwd = null, $verbose = false)
43777 {
43778 $svnCommand = sprintf('%s %s%s %s',
43779 $command,
43780 '--non-interactive ',
43781 $this->getCredentialString(),
43782 ProcessExecutor::escape($path)
43783 );
43784
43785 return $this->executeWithAuthRetry($svnCommand, $cwd, $path, $verbose);
43786 }
43787
43788 private function executeWithAuthRetry($command, $cwd, $path, $verbose)
43789 {
43790 $output = null;
43791 $io = $this->io;
43792 $handler = function ($type, $buffer) use (&$output, $io, $verbose) {
43793 if ($type !== 'out') {
43794 return;
43795 }
43796 if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
43797 return;
43798 }
43799 $output .= $buffer;
43800 if ($verbose) {
43801 $io->writeError($buffer, false);
43802 }
43803 };
43804 $status = $this->process->execute($command, $handler, $cwd);
43805 if (0 === $status) {
43806 return $output;
43807 }
43808
43809 $errorOutput = $this->process->getErrorOutput();
43810 $fullOutput = implode("\n", array($output, $errorOutput));
43811
43812
43813  if (false === stripos($fullOutput, 'Could not authenticate to server:')
43814 && false === stripos($fullOutput, 'authorization failed')
43815 && false === stripos($fullOutput, 'svn: E170001:')
43816 && false === stripos($fullOutput, 'svn: E215004:')) {
43817 throw new \RuntimeException($fullOutput);
43818 }
43819
43820 if (!$this->hasAuth()) {
43821 $this->doAuthDance();
43822 }
43823
43824
43825  if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
43826
43827  return $this->executeWithAuthRetry($command, $cwd, $path, $verbose);
43828 }
43829
43830 throw new \RuntimeException(
43831 'wrong credentials provided ('.$fullOutput.')'
43832 );
43833 }
43834
43835
43836
43837
43838 public function setCacheCredentials($cacheCredentials)
43839 {
43840 $this->cacheCredentials = $cacheCredentials;
43841 }
43842
43843
43844
43845
43846
43847
43848
43849 protected function doAuthDance()
43850 {
43851
43852  if (!$this->io->isInteractive()) {
43853 throw new \RuntimeException(
43854 'can not ask for authentication in non interactive mode'
43855 );
43856 }
43857
43858 $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
43859
43860 $this->hasAuth = true;
43861 $this->credentials['username'] = $this->io->ask("Username: ");
43862 $this->credentials['password'] = $this->io->askAndHideAnswer("Password: ");
43863
43864 $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ", true);
43865
43866 return $this;
43867 }
43868
43869
43870
43871
43872
43873
43874
43875
43876
43877
43878 protected function getCommand($cmd, $url, $path = null)
43879 {
43880 $cmd = sprintf('%s %s%s %s',
43881 $cmd,
43882 '--non-interactive ',
43883 $this->getCredentialString(),
43884 ProcessExecutor::escape($url)
43885 );
43886
43887 if ($path) {
43888 $cmd .= ' ' . ProcessExecutor::escape($path);
43889 }
43890
43891 return $cmd;
43892 }
43893
43894
43895
43896
43897
43898
43899
43900
43901 protected function getCredentialString()
43902 {
43903 if (!$this->hasAuth()) {
43904 return '';
43905 }
43906
43907 return sprintf(
43908 ' %s--username %s --password %s ',
43909 $this->getAuthCache(),
43910 ProcessExecutor::escape($this->getUsername()),
43911 ProcessExecutor::escape($this->getPassword())
43912 );
43913 }
43914
43915
43916
43917
43918
43919
43920
43921 protected function getPassword()
43922 {
43923 if ($this->credentials === null) {
43924 throw new \LogicException("No svn auth detected.");
43925 }
43926
43927 return isset($this->credentials['password']) ? $this->credentials['password'] : '';
43928 }
43929
43930
43931
43932
43933
43934
43935
43936 protected function getUsername()
43937 {
43938 if ($this->credentials === null) {
43939 throw new \LogicException("No svn auth detected.");
43940 }
43941
43942 return $this->credentials['username'];
43943 }
43944
43945
43946
43947
43948
43949
43950 protected function hasAuth()
43951 {
43952 if (null !== $this->hasAuth) {
43953 return $this->hasAuth;
43954 }
43955
43956 if (false === $this->createAuthFromConfig()) {
43957 $this->createAuthFromUrl();
43958 }
43959
43960 return $this->hasAuth;
43961 }
43962
43963
43964
43965
43966
43967
43968 protected function getAuthCache()
43969 {
43970 return $this->cacheCredentials ? '' : '--no-auth-cache ';
43971 }
43972
43973
43974
43975
43976
43977
43978 private function createAuthFromConfig()
43979 {
43980 if (!$this->config->has('http-basic')) {
43981 return $this->hasAuth = false;
43982 }
43983
43984 $authConfig = $this->config->get('http-basic');
43985
43986 $host = parse_url($this->url, PHP_URL_HOST);
43987 if (isset($authConfig[$host])) {
43988 $this->credentials['username'] = $authConfig[$host]['username'];
43989 $this->credentials['password'] = $authConfig[$host]['password'];
43990
43991 return $this->hasAuth = true;
43992 }
43993
43994 return $this->hasAuth = false;
43995 }
43996
43997
43998
43999
44000
44001
44002 private function createAuthFromUrl()
44003 {
44004 $uri = parse_url($this->url);
44005 if (empty($uri['user'])) {
44006 return $this->hasAuth = false;
44007 }
44008
44009 $this->credentials['username'] = $uri['user'];
44010 if (!empty($uri['pass'])) {
44011 $this->credentials['password'] = $uri['pass'];
44012 }
44013
44014 return $this->hasAuth = true;
44015 }
44016 }
44017 <?php
44018
44019
44020
44021
44022
44023
44024
44025
44026
44027
44028
44029 namespace Composer\Util;
44030
44031 use Composer\CaBundle\CaBundle;
44032
44033
44034
44035
44036 final class TlsHelper
44037 {
44038 private static $useOpensslParse;
44039
44040
44041
44042
44043
44044
44045
44046
44047
44048
44049 public static function checkCertificateHost($certificate, $hostname, &$cn = null)
44050 {
44051 $names = self::getCertificateNames($certificate);
44052
44053 if (empty($names)) {
44054 return false;
44055 }
44056
44057 $combinedNames = array_merge($names['san'], array($names['cn']));
44058 $hostname = strtolower($hostname);
44059
44060 foreach ($combinedNames as $certName) {
44061 $matcher = self::certNameMatcher($certName);
44062
44063 if ($matcher && $matcher($hostname)) {
44064 $cn = $names['cn'];
44065
44066 return true;
44067 }
44068 }
44069
44070 return false;
44071 }
44072
44073
44074
44075
44076
44077
44078
44079
44080 public static function getCertificateNames($certificate)
44081 {
44082 if (is_array($certificate)) {
44083 $info = $certificate;
44084 } elseif (CaBundle::isOpensslParseSafe()) {
44085 $info = openssl_x509_parse($certificate, false);
44086 }
44087
44088 if (!isset($info['subject']['commonName'])) {
44089 return null;
44090 }
44091
44092 $commonName = strtolower($info['subject']['commonName']);
44093 $subjectAltNames = array();
44094
44095 if (isset($info['extensions']['subjectAltName'])) {
44096 $subjectAltNames = preg_split('{\s*,\s*}', $info['extensions']['subjectAltName']);
44097 $subjectAltNames = array_filter(array_map(function ($name) {
44098 if (0 === strpos($name, 'DNS:')) {
44099 return strtolower(ltrim(substr($name, 4)));
44100 }
44101
44102 return null;
44103 }, $subjectAltNames));
44104 $subjectAltNames = array_values($subjectAltNames);
44105 }
44106
44107 return array(
44108 'cn' => $commonName,
44109 'san' => $subjectAltNames,
44110 );
44111 }
44112
44113
44114
44115
44116
44117
44118
44119
44120
44121
44122
44123
44124
44125
44126
44127
44128
44129
44130
44131
44132
44133
44134
44135
44136
44137
44138
44139
44140
44141
44142
44143
44144
44145
44146
44147
44148
44149
44150
44151
44152 public static function getCertificateFingerprint($certificate)
44153 {
44154 $pubkeydetails = openssl_pkey_get_details(openssl_get_publickey($certificate));
44155 $pubkeypem = $pubkeydetails['key'];
44156
44157  $start = '-----BEGIN PUBLIC KEY-----';
44158 $end = '-----END PUBLIC KEY-----';
44159 $pemtrim = substr($pubkeypem, (strpos($pubkeypem, $start) + strlen($start)), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
44160 $der = base64_decode($pemtrim);
44161
44162 return sha1($der);
44163 }
44164
44165
44166
44167
44168
44169
44170
44171
44172
44173 public static function isOpensslParseSafe()
44174 {
44175 return CaBundle::isOpensslParseSafe();
44176 }
44177
44178
44179
44180
44181
44182
44183
44184
44185 private static function certNameMatcher($certName)
44186 {
44187 $wildcards = substr_count($certName, '*');
44188
44189 if (0 === $wildcards) {
44190
44191  return function ($hostname) use ($certName) {
44192 return $hostname === $certName;
44193 };
44194 }
44195
44196 if (1 === $wildcards) {
44197 $components = explode('.', $certName);
44198
44199 if (3 > count($components)) {
44200
44201  return;
44202 }
44203
44204 $firstComponent = $components[0];
44205
44206
44207  if ('*' !== $firstComponent[strlen($firstComponent) - 1]) {
44208 return;
44209 }
44210
44211 $wildcardRegex = preg_quote($certName);
44212 $wildcardRegex = str_replace('\\*', '[a-z0-9-]+', $wildcardRegex);
44213 $wildcardRegex = "{^{$wildcardRegex}$}";
44214
44215 return function ($hostname) use ($wildcardRegex) {
44216 return 1 === preg_match($wildcardRegex, $hostname);
44217 };
44218 }
44219 }
44220 }
44221 <?php
44222
44223
44224
44225
44226
44227
44228
44229
44230
44231
44232
44233 namespace Composer\Util;
44234
44235 use Composer\Config;
44236 use Composer\IO\IOInterface;
44237
44238
44239
44240
44241 class Url
44242 {
44243 public static function updateDistReference(Config $config, $url, $ref)
44244 {
44245 $host = parse_url($url, PHP_URL_HOST);
44246
44247 if ($host === 'api.github.com' || $host === 'github.com' || $host === 'www.github.com') {
44248 if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
44249
44250  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
44251 } elseif (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
44252
44253  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
44254 } elseif (preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
44255
44256  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
44257 }
44258 } elseif ($host === 'bitbucket.org' || $host === 'www.bitbucket.org') {
44259 if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
44260
44261  $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $ref . '.' . $match[4];
44262 }
44263 } elseif ($host === 'gitlab.com' || $host === 'www.gitlab.com') {
44264 if (preg_match('{^https?://(?:www\.)?gitlab\.com/api/v[34]/projects/([^/]+)/repository/archive\.(zip|tar\.gz|tar\.bz2|tar)\?sha=.+$}i', $url, $match)) {
44265
44266  $url = 'https://gitlab.com/api/v4/projects/' . $match[1] . '/repository/archive.' . $match[2] . '?sha=' . $ref;
44267 }
44268 } elseif (in_array($host, $config->get('github-domains'), true)) {
44269 $url = preg_replace('{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i', '$1/'.$ref, $url);
44270 } elseif (in_array($host, $config->get('gitlab-domains'), true)) {
44271 $url = preg_replace('{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i', '${1}'.$ref, $url);
44272 }
44273
44274 return $url;
44275 }
44276 }
44277 <?php
44278
44279
44280
44281
44282
44283
44284
44285
44286
44287
44288
44289 namespace Composer;
44290
44291 use Composer\Util\IniHelper;
44292 use Symfony\Component\Console\Output\OutputInterface;
44293
44294
44295
44296
44297 class XdebugHandler
44298 {
44299 const ENV_ALLOW = 'COMPOSER_ALLOW_XDEBUG';
44300 const ENV_VERSION = 'COMPOSER_XDEBUG_VERSION';
44301 const RESTART_ID = 'internal';
44302
44303 private $output;
44304 private $loaded;
44305 private $envScanDir;
44306 private $version;
44307 private $tmpIni;
44308
44309
44310
44311
44312 public function __construct(OutputInterface $output)
44313 {
44314 $this->output = $output;
44315 $this->loaded = extension_loaded('xdebug');
44316 $this->envScanDir = getenv('PHP_INI_SCAN_DIR');
44317
44318 if ($this->loaded) {
44319 $ext = new \ReflectionExtension('xdebug');
44320 $this->version = strval($ext->getVersion());
44321 }
44322 }
44323
44324
44325
44326
44327
44328
44329
44330
44331
44332
44333
44334
44335
44336
44337 public function check()
44338 {
44339 $args = explode('|', strval(getenv(self::ENV_ALLOW)), 2);
44340
44341 if ($this->needsRestart($args[0])) {
44342 if ($this->prepareRestart()) {
44343 $command = $this->getCommand();
44344 $this->restart($command);
44345 }
44346
44347 return;
44348 }
44349
44350
44351  if (self::RESTART_ID === $args[0]) {
44352 putenv(self::ENV_ALLOW);
44353
44354 if (false !== $this->envScanDir) {
44355
44356  if (isset($args[1])) {
44357 putenv('PHP_INI_SCAN_DIR='.$args[1]);
44358 } else {
44359 putenv('PHP_INI_SCAN_DIR');
44360 }
44361 }
44362
44363
44364  if ($this->loaded) {
44365 putenv(self::ENV_VERSION);
44366 }
44367 }
44368 }
44369
44370
44371
44372
44373
44374
44375 protected function restart($command)
44376 {
44377 passthru($command, $exitCode);
44378
44379 if (!empty($this->tmpIni)) {
44380 @unlink($this->tmpIni);
44381 }
44382
44383 exit($exitCode);
44384 }
44385
44386
44387
44388
44389
44390
44391
44392
44393 private function needsRestart($allow)
44394 {
44395 if (PHP_SAPI !== 'cli' || !defined('PHP_BINARY')) {
44396 return false;
44397 }
44398
44399 return empty($allow) && $this->loaded;
44400 }
44401
44402
44403
44404
44405
44406
44407
44408
44409
44410
44411
44412 private function prepareRestart()
44413 {
44414 $this->tmpIni = '';
44415 $iniPaths = IniHelper::getAll();
44416 $additional = count($iniPaths) > 1;
44417
44418 if ($this->writeTmpIni($iniPaths)) {
44419 return $this->setEnvironment($additional, $iniPaths);
44420 }
44421
44422 return false;
44423 }
44424
44425
44426
44427
44428
44429
44430
44431
44432
44433
44434 private function writeTmpIni(array $iniPaths)
44435 {
44436 if (!$this->tmpIni = tempnam(sys_get_temp_dir(), '')) {
44437 return false;
44438 }
44439
44440
44441  if (empty($iniPaths[0])) {
44442 array_shift($iniPaths);
44443 }
44444
44445 $content = '';
44446 $regex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
44447
44448 foreach ($iniPaths as $file) {
44449 $data = preg_replace($regex, ';$1', file_get_contents($file));
44450 $content .= $data.PHP_EOL;
44451 }
44452
44453 $content .= 'allow_url_fopen='.ini_get('allow_url_fopen').PHP_EOL;
44454 $content .= 'disable_functions="'.ini_get('disable_functions').'"'.PHP_EOL;
44455 $content .= 'memory_limit='.ini_get('memory_limit').PHP_EOL;
44456
44457 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
44458
44459  $content .= 'opcache.enable_cli=0'.PHP_EOL;
44460 }
44461
44462 return @file_put_contents($this->tmpIni, $content);
44463 }
44464
44465
44466
44467
44468
44469
44470 private function getCommand()
44471 {
44472 $phpArgs = array(PHP_BINARY, '-c', $this->tmpIni);
44473 $params = array_merge($phpArgs, $this->getScriptArgs($_SERVER['argv']));
44474
44475 return implode(' ', array_map(array($this, 'escape'), $params));
44476 }
44477
44478
44479
44480
44481
44482
44483
44484
44485
44486 private function setEnvironment($additional, array $iniPaths)
44487 {
44488
44489  if ($additional && !putenv('PHP_INI_SCAN_DIR=')) {
44490 return false;
44491 }
44492
44493
44494  if (!putenv(IniHelper::ENV_ORIGINAL.'='.implode(PATH_SEPARATOR, $iniPaths))) {
44495 return false;
44496 }
44497
44498
44499  if (!putenv(self::ENV_VERSION.'='.$this->version)) {
44500 return false;
44501 }
44502
44503
44504  $args = array(self::RESTART_ID);
44505
44506 if (false !== $this->envScanDir) {
44507
44508  $args[] = $this->envScanDir;
44509 }
44510
44511 return putenv(self::ENV_ALLOW.'='.implode('|', $args));
44512 }
44513
44514
44515
44516
44517
44518
44519
44520
44521
44522
44523
44524 private function getScriptArgs(array $args)
44525 {
44526 if (in_array('--no-ansi', $args) || in_array('--ansi', $args)) {
44527 return $args;
44528 }
44529
44530 if ($this->output->isDecorated()) {
44531 $offset = count($args) > 1 ? 2 : 1;
44532 array_splice($args, $offset, 0, '--ansi');
44533 }
44534
44535 return $args;
44536 }
44537
44538
44539
44540
44541
44542
44543
44544
44545
44546
44547
44548
44549 private function escape($arg, $meta = true)
44550 {
44551 if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
44552 return escapeshellarg($arg);
44553 }
44554
44555 $quote = strpbrk($arg, " \t") !== false || $arg === '';
44556 $arg = preg_replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes);
44557
44558 if ($meta) {
44559 $meta = $dquotes || preg_match('/%[^%]+%/', $arg);
44560
44561 if (!$meta && !$quote) {
44562 $quote = strpbrk($arg, '^&|<>()') !== false;
44563 }
44564 }
44565
44566 if ($quote) {
44567 $arg = preg_replace('/(\\\\*)$/', '$1$1', $arg);
44568 $arg = '"'.$arg.'"';
44569 }
44570
44571 if ($meta) {
44572 $arg = preg_replace('/(["^&|<>()%])/', '^$1', $arg);
44573 }
44574
44575 return $arg;
44576 }
44577 }
44578 <?php
44579
44580
44581
44582
44583
44584
44585
44586
44587
44588
44589
44590 function includeIfExists($file)
44591 {
44592 return file_exists($file) ? include $file : false;
44593 }
44594
44595 if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
44596 echo 'You must set up the project dependencies using `composer install`'.PHP_EOL.
44597 'See https://getcomposer.org/download/ for instructions on installing Composer'.PHP_EOL;
44598 exit(1);
44599 }
44600
44601 return $loader;
44602 <?php
44603
44604 /*
44605  * This file is part of Composer.
44606  *
44607  * (c) Nils Adermann <naderman@naderman.de>
44608  *     Jordi Boggiano <j.boggiano@seld.be>
44609  *
44610  * For the full copyright and license information, please view the LICENSE
44611  * file that was distributed with this source code.
44612  */
44613
44614 namespace Composer\Autoload;
44615
44616 /**
44617  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
44618  *
44619  *     $loader = new \Composer\Autoload\ClassLoader();
44620  *
44621  *     // register classes with namespaces
44622  *     $loader->add('Symfony\Component', __DIR__.'/component');
44623  *     $loader->add('Symfony',           __DIR__.'/framework');
44624  *
44625  *     // activate the autoloader
44626  *     $loader->register();
44627  *
44628  *     // to enable searching the include path (eg. for PEAR packages)
44629  *     $loader->setUseIncludePath(true);
44630  *
44631  * In this example, if you try to use a class in the Symfony\Component
44632  * namespace or one of its children (Symfony\Component\Console for instance),
44633  * the autoloader will first look for the class under the component/
44634  * directory, and it will then fallback to the framework/ directory if not
44635  * found before giving up.
44636  *
44637  * This class is loosely based on the Symfony UniversalClassLoader.
44638  *
44639  * @author Fabien Potencier <fabien@symfony.com>
44640  * @author Jordi Boggiano <j.boggiano@seld.be>
44641  * @see    http://www.php-fig.org/psr/psr-0/
44642  * @see    http://www.php-fig.org/psr/psr-4/
44643  */
44644 class ClassLoader
44645 {
44646     // PSR-4
44647     private $prefixLengthsPsr4 = array();
44648     private $prefixDirsPsr4 = array();
44649     private $fallbackDirsPsr4 = array();
44650
44651     // PSR-0
44652     private $prefixesPsr0 = array();
44653     private $fallbackDirsPsr0 = array();
44654
44655     private $useIncludePath = false;
44656     private $classMap = array();
44657     private $classMapAuthoritative = false;
44658     private $missingClasses = array();
44659     private $apcuPrefix;
44660
44661     public function getPrefixes()
44662     {
44663         if (!empty($this->prefixesPsr0)) {
44664             return call_user_func_array('array_merge', $this->prefixesPsr0);
44665         }
44666
44667         return array();
44668     }
44669
44670     public function getPrefixesPsr4()
44671     {
44672         return $this->prefixDirsPsr4;
44673     }
44674
44675     public function getFallbackDirs()
44676     {
44677         return $this->fallbackDirsPsr0;
44678     }
44679
44680     public function getFallbackDirsPsr4()
44681     {
44682         return $this->fallbackDirsPsr4;
44683     }
44684
44685     public function getClassMap()
44686     {
44687         return $this->classMap;
44688     }
44689
44690     /**
44691      * @param array $classMap Class to filename map
44692      */
44693     public function addClassMap(array $classMap)
44694     {
44695         if ($this->classMap) {
44696             $this->classMap = array_merge($this->classMap, $classMap);
44697         } else {
44698             $this->classMap = $classMap;
44699         }
44700     }
44701
44702     /**
44703      * Registers a set of PSR-0 directories for a given prefix, either
44704      * appending or prepending to the ones previously set for this prefix.
44705      *
44706      * @param string       $prefix  The prefix
44707      * @param array|string $paths   The PSR-0 root directories
44708      * @param bool         $prepend Whether to prepend the directories
44709      */
44710     public function add($prefix, $paths, $prepend = false)
44711     {
44712         if (!$prefix) {
44713             if ($prepend) {
44714                 $this->fallbackDirsPsr0 = array_merge(
44715                     (array) $paths,
44716                     $this->fallbackDirsPsr0
44717                 );
44718             } else {
44719                 $this->fallbackDirsPsr0 = array_merge(
44720                     $this->fallbackDirsPsr0,
44721                     (array) $paths
44722                 );
44723             }
44724
44725             return;
44726         }
44727
44728         $first = $prefix[0];
44729         if (!isset($this->prefixesPsr0[$first][$prefix])) {
44730             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
44731
44732             return;
44733         }
44734         if ($prepend) {
44735             $this->prefixesPsr0[$first][$prefix] = array_merge(
44736                 (array) $paths,
44737                 $this->prefixesPsr0[$first][$prefix]
44738             );
44739         } else {
44740             $this->prefixesPsr0[$first][$prefix] = array_merge(
44741                 $this->prefixesPsr0[$first][$prefix],
44742                 (array) $paths
44743             );
44744         }
44745     }
44746
44747     /**
44748      * Registers a set of PSR-4 directories for a given namespace, either
44749      * appending or prepending to the ones previously set for this namespace.
44750      *
44751      * @param string       $prefix  The prefix/namespace, with trailing '\\'
44752      * @param array|string $paths   The PSR-4 base directories
44753      * @param bool         $prepend Whether to prepend the directories
44754      *
44755      * @throws \InvalidArgumentException
44756      */
44757     public function addPsr4($prefix, $paths, $prepend = false)
44758     {
44759         if (!$prefix) {
44760             // Register directories for the root namespace.
44761             if ($prepend) {
44762                 $this->fallbackDirsPsr4 = array_merge(
44763                     (array) $paths,
44764                     $this->fallbackDirsPsr4
44765                 );
44766             } else {
44767                 $this->fallbackDirsPsr4 = array_merge(
44768                     $this->fallbackDirsPsr4,
44769                     (array) $paths
44770                 );
44771             }
44772         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
44773             // Register directories for a new namespace.
44774             $length = strlen($prefix);
44775             if ('\\' !== $prefix[$length - 1]) {
44776                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
44777             }
44778             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
44779             $this->prefixDirsPsr4[$prefix] = (array) $paths;
44780         } elseif ($prepend) {
44781             // Prepend directories for an already registered namespace.
44782             $this->prefixDirsPsr4[$prefix] = array_merge(
44783                 (array) $paths,
44784                 $this->prefixDirsPsr4[$prefix]
44785             );
44786         } else {
44787             // Append directories for an already registered namespace.
44788             $this->prefixDirsPsr4[$prefix] = array_merge(
44789                 $this->prefixDirsPsr4[$prefix],
44790                 (array) $paths
44791             );
44792         }
44793     }
44794
44795     /**
44796      * Registers a set of PSR-0 directories for a given prefix,
44797      * replacing any others previously set for this prefix.
44798      *
44799      * @param string       $prefix The prefix
44800      * @param array|string $paths  The PSR-0 base directories
44801      */
44802     public function set($prefix, $paths)
44803     {
44804         if (!$prefix) {
44805             $this->fallbackDirsPsr0 = (array) $paths;
44806         } else {
44807             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
44808         }
44809     }
44810
44811     /**
44812      * Registers a set of PSR-4 directories for a given namespace,
44813      * replacing any others previously set for this namespace.
44814      *
44815      * @param string       $prefix The prefix/namespace, with trailing '\\'
44816      * @param array|string $paths  The PSR-4 base directories
44817      *
44818      * @throws \InvalidArgumentException
44819      */
44820     public function setPsr4($prefix, $paths)
44821     {
44822         if (!$prefix) {
44823             $this->fallbackDirsPsr4 = (array) $paths;
44824         } else {
44825             $length = strlen($prefix);
44826             if ('\\' !== $prefix[$length - 1]) {
44827                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
44828             }
44829             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
44830             $this->prefixDirsPsr4[$prefix] = (array) $paths;
44831         }
44832     }
44833
44834     /**
44835      * Turns on searching the include path for class files.
44836      *
44837      * @param bool $useIncludePath
44838      */
44839     public function setUseIncludePath($useIncludePath)
44840     {
44841         $this->useIncludePath = $useIncludePath;
44842     }
44843
44844     /**
44845      * Can be used to check if the autoloader uses the include path to check
44846      * for classes.
44847      *
44848      * @return bool
44849      */
44850     public function getUseIncludePath()
44851     {
44852         return $this->useIncludePath;
44853     }
44854
44855     /**
44856      * Turns off searching the prefix and fallback directories for classes
44857      * that have not been registered with the class map.
44858      *
44859      * @param bool $classMapAuthoritative
44860      */
44861     public function setClassMapAuthoritative($classMapAuthoritative)
44862     {
44863         $this->classMapAuthoritative = $classMapAuthoritative;
44864     }
44865
44866     /**
44867      * Should class lookup fail if not found in the current class map?
44868      *
44869      * @return bool
44870      */
44871     public function isClassMapAuthoritative()
44872     {
44873         return $this->classMapAuthoritative;
44874     }
44875
44876     /**
44877      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
44878      *
44879      * @param string|null $apcuPrefix
44880      */
44881     public function setApcuPrefix($apcuPrefix)
44882     {
44883         $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
44884     }
44885
44886     /**
44887      * The APCu prefix in use, or null if APCu caching is not enabled.
44888      *
44889      * @return string|null
44890      */
44891     public function getApcuPrefix()
44892     {
44893         return $this->apcuPrefix;
44894     }
44895
44896     /**
44897      * Registers this instance as an autoloader.
44898      *
44899      * @param bool $prepend Whether to prepend the autoloader or not
44900      */
44901     public function register($prepend = false)
44902     {
44903         spl_autoload_register(array($this, 'loadClass'), true, $prepend);
44904     }
44905
44906     /**
44907      * Unregisters this instance as an autoloader.
44908      */
44909     public function unregister()
44910     {
44911         spl_autoload_unregister(array($this, 'loadClass'));
44912     }
44913
44914     /**
44915      * Loads the given class or interface.
44916      *
44917      * @param  string    $class The name of the class
44918      * @return bool|null True if loaded, null otherwise
44919      */
44920     public function loadClass($class)
44921     {
44922         if ($file = $this->findFile($class)) {
44923             includeFile($file);
44924
44925             return true;
44926         }
44927     }
44928
44929     /**
44930      * Finds the path to the file where the class is defined.
44931      *
44932      * @param string $class The name of the class
44933      *
44934      * @return string|false The path if found, false otherwise
44935      */
44936     public function findFile($class)
44937     {
44938         // class map lookup
44939         if (isset($this->classMap[$class])) {
44940             return $this->classMap[$class];
44941         }
44942         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
44943             return false;
44944         }
44945         if (null !== $this->apcuPrefix) {
44946             $file = apcu_fetch($this->apcuPrefix.$class, $hit);
44947             if ($hit) {
44948                 return $file;
44949             }
44950         }
44951
44952         $file = $this->findFileWithExtension($class, '.php');
44953
44954         // Search for Hack files if we are running on HHVM
44955         if (false === $file && defined('HHVM_VERSION')) {
44956             $file = $this->findFileWithExtension($class, '.hh');
44957         }
44958
44959         if (null !== $this->apcuPrefix) {
44960             apcu_add($this->apcuPrefix.$class, $file);
44961         }
44962
44963         if (false === $file) {
44964             // Remember that this class does not exist.
44965             $this->missingClasses[$class] = true;
44966         }
44967
44968         return $file;
44969     }
44970
44971     private function findFileWithExtension($class, $ext)
44972     {
44973         // PSR-4 lookup
44974         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
44975
44976         $first = $class[0];
44977         if (isset($this->prefixLengthsPsr4[$first])) {
44978             $subPath = $class;
44979             while (false !== $lastPos = strrpos($subPath, '\\')) {
44980                 $subPath = substr($subPath, 0, $lastPos);
44981                 $search = $subPath.'\\';
44982                 if (isset($this->prefixDirsPsr4[$search])) {
44983                     $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
44984                     foreach ($this->prefixDirsPsr4[$search] as $dir) {
44985                         if (file_exists($file = $dir . $pathEnd)) {
44986                             return $file;
44987                         }
44988                     }
44989                 }
44990             }
44991         }
44992
44993         // PSR-4 fallback dirs
44994         foreach ($this->fallbackDirsPsr4 as $dir) {
44995             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
44996                 return $file;
44997             }
44998         }
44999
45000         // PSR-0 lookup
45001         if (false !== $pos = strrpos($class, '\\')) {
45002             // namespaced class name
45003             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
45004                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
45005         } else {
45006             // PEAR-like class name
45007             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
45008         }
45009
45010         if (isset($this->prefixesPsr0[$first])) {
45011             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
45012                 if (0 === strpos($class, $prefix)) {
45013                     foreach ($dirs as $dir) {
45014                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
45015                             return $file;
45016                         }
45017                     }
45018                 }
45019             }
45020         }
45021
45022         // PSR-0 fallback dirs
45023         foreach ($this->fallbackDirsPsr0 as $dir) {
45024             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
45025                 return $file;
45026             }
45027         }
45028
45029         // PSR-0 include paths.
45030         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
45031             return $file;
45032         }
45033
45034         return false;
45035     }
45036 }
45037
45038 /**
45039  * Scope isolated include.
45040  *
45041  * Prevents access to $this/self from included files.
45042  */
45043 function includeFile($file)
45044 {
45045     include $file;
45046 }
45047 {
45048     "$schema": "http://json-schema.org/draft-04/schema#",
45049     "description": "A representation of packages metadata.",
45050     "type": "object",
45051     "oneOf": [
45052         { "required": [ "packages" ] },
45053         { "required": [ "providers" ] },
45054         { "required": [ "provider-includes", "providers-url" ] }
45055     ],
45056     "properties": {
45057         "packages": {
45058             "type": ["object", "array"],
45059             "description": "A hashmap of package names in the form of <vendor>/<name>.",
45060             "additionalProperties": { "$ref": "#/definitions/versions" }
45061         },
45062         "providers-url": {
45063             "type": "string",
45064             "description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
45065         },
45066         "provider-includes": {
45067             "type": "object",
45068             "description": "A hashmap of provider listings.",
45069             "additionalProperties": { "$ref": "#/definitions/provider" }
45070         },
45071         "providers": {
45072             "type": "object",
45073             "description": "A hashmap of package names in the form of <vendor>/<name>.",
45074             "additionalProperties": { "$ref": "#/definitions/provider" }
45075         },
45076         "notify-batch": {
45077             "type": "string",
45078             "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
45079         },
45080         "search": {
45081             "type": "string",
45082             "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
45083         },
45084         "warning": {
45085             "type": "string",
45086             "description": "A message that will be output by Composer as a warning when this source is consulted."
45087         }
45088     },
45089     "definitions": {
45090         "versions": {
45091             "type": "object",
45092             "description": "A hashmap of versions and their metadata.",
45093             "additionalProperties": { "$ref": "#/definitions/version" }
45094         },
45095         "version": {
45096             "type": "object",
45097             "oneOf": [
45098                 { "$ref": "#/definitions/package" },
45099                 { "$ref": "#/definitions/metapackage" }
45100             ]
45101         },
45102         "package-base": {
45103             "properties": {
45104                 "name": { "type": "string" },
45105                 "type": { "type": "string" },
45106                 "version": { "type": "string" },
45107                 "version_normalized": {
45108                     "type": "string",
45109                     "description": "Normalized version, optional but can save computational time on client side."
45110                 },
45111                 "autoload": { "type": "object" },
45112                 "require": { "type": "object" },
45113                 "replace": { "type": "object" },
45114                 "conflict": { "type": "object" },
45115                 "provide": { "type": "object" },
45116                 "time": { "type": "string" }
45117             },
45118             "additionalProperties": true
45119         },
45120         "package": {
45121             "allOf": [
45122                 { "$ref": "#/definitions/package-base" },
45123                 {
45124                     "properties": {
45125                         "dist": { "type": "object" },
45126                         "source": { "type": "object" }
45127                     }
45128                 },
45129                 { "oneOf": [
45130                     { "required": [ "name", "version", "source" ] },
45131                     { "required": [ "name", "version", "dist" ] }
45132                 ] }
45133             ]
45134         },
45135         "metapackage": {
45136             "allOf": [
45137                 { "$ref": "#/definitions/package-base" },
45138                 {
45139                     "properties": {
45140                         "type": { "type": "string", "enum": [ "metapackage" ] }
45141                     },
45142                     "required": [ "name", "version", "type" ]
45143                 }
45144             ]
45145         },
45146         "provider": {
45147             "type": "object",
45148             "properties": {
45149                 "sha256": {
45150                     "type": "string",
45151                     "description": "Hash value that can be used to validate the resource."
45152                 }
45153             }
45154         }
45155     }
45156 }
45157 {
45158     "$schema": "http://json-schema.org/draft-04/schema#",
45159     "name": "Package",
45160     "type": "object",
45161     "additionalProperties": false,
45162     "required": [ "name", "description" ],
45163     "properties": {
45164         "name": {
45165             "type": "string",
45166             "description": "Package name, including 'vendor-name/' prefix."
45167         },
45168         "type": {
45169             "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.",
45170             "type": "string"
45171         },
45172         "target-dir": {
45173             "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.",
45174             "type": "string"
45175         },
45176         "description": {
45177             "type": "string",
45178             "description": "Short package description."
45179         },
45180         "keywords": {
45181             "type": "array",
45182             "items": {
45183                 "type": "string",
45184                 "description": "A tag/keyword that this package relates to."
45185             }
45186         },
45187         "homepage": {
45188             "type": "string",
45189             "description": "Homepage URL for the project.",
45190             "format": "uri"
45191         },
45192         "version": {
45193             "type": "string",
45194             "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes."
45195         },
45196         "time": {
45197             "type": "string",
45198             "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
45199         },
45200         "license": {
45201             "type": ["string", "array"],
45202             "description": "License name. Or an array of license names."
45203         },
45204         "authors": {
45205             "$ref": "#/definitions/authors"
45206         },
45207         "require": {
45208             "type": "object",
45209             "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
45210             "additionalProperties": {
45211                 "type": "string"
45212             }
45213         },
45214         "replace": {
45215             "type": "object",
45216             "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
45217             "additionalProperties": {
45218                 "type": "string"
45219             }
45220         },
45221         "conflict": {
45222             "type": "object",
45223             "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
45224             "additionalProperties": {
45225                 "type": "string"
45226             }
45227         },
45228         "provide": {
45229             "type": "object",
45230             "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
45231             "additionalProperties": {
45232                 "type": "string"
45233             }
45234         },
45235         "require-dev": {
45236             "type": "object",
45237             "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
45238             "additionalProperties": {
45239                 "type": "string"
45240             }
45241         },
45242         "suggest": {
45243             "type": "object",
45244             "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).",
45245             "additionalProperties": {
45246                 "type": "string"
45247             }
45248         },
45249         "config": {
45250             "type": "object",
45251             "description": "Composer options.",
45252             "properties": {
45253                 "process-timeout": {
45254                     "type": "integer",
45255                     "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
45256                 },
45257                 "use-include-path": {
45258                     "type": "boolean",
45259                     "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
45260                 },
45261                 "preferred-install": {
45262                     "type": ["string", "object"],
45263                     "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\"}."
45264                 },
45265                 "notify-on-install": {
45266                     "type": "boolean",
45267                     "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."
45268                 },
45269                 "github-protocols": {
45270                     "type": "array",
45271                     "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].",
45272                     "items": {
45273                         "type": "string"
45274                     }
45275                 },
45276                 "github-oauth": {
45277                     "type": "object",
45278                     "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
45279                     "additionalProperties": {
45280                         "type": "string"
45281                     }
45282                 },
45283                 "gitlab-oauth": {
45284                     "type": "object",
45285                     "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"<token>\"}.",
45286                     "additionalProperties": {
45287                         "type": "string"
45288                     }
45289                 },
45290                 "gitlab-token": {
45291                     "type": "object",
45292                     "description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}.",
45293                     "additionalProperties": true
45294                 },
45295                 "disable-tls": {
45296                     "type": "boolean",
45297                     "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."
45298                 },
45299                 "secure-http": {
45300                     "type": "boolean",
45301                     "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."
45302                 },
45303                 "cafile": {
45304                     "type": "string",
45305                     "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."
45306                 },
45307                 "capath": {
45308                     "type": "string",
45309                     "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."
45310                 },
45311                 "http-basic": {
45312                     "type": "object",
45313                     "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
45314                     "additionalProperties": {
45315                         "type": "object",
45316                         "required": ["username", "password"],
45317                         "properties": {
45318                             "username": {
45319                                 "type": "string",
45320                                 "description": "The username used for HTTP Basic authentication"
45321                             },
45322                             "password": {
45323                                 "type": "string",
45324                                 "description": "The password used for HTTP Basic authentication"
45325                             }
45326                         }
45327                     }
45328                 },
45329                 "store-auths": {
45330                     "type": ["string", "boolean"],
45331                     "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
45332                 },
45333                 "platform": {
45334                     "type": "object",
45335                     "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
45336                     "additionalProperties": {
45337                         "type": "string"
45338                     }
45339                 },
45340                 "vendor-dir": {
45341                     "type": "string",
45342                     "description": "The location where all packages are installed, defaults to \"vendor\"."
45343                 },
45344                 "bin-dir": {
45345                     "type": "string",
45346                     "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
45347                 },
45348                 "data-dir": {
45349                     "type": "string",
45350                     "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes."
45351                 },
45352                 "cache-dir": {
45353                     "type": "string",
45354                     "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
45355                 },
45356                 "cache-files-dir": {
45357                     "type": "string",
45358                     "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
45359                 },
45360                 "cache-repo-dir": {
45361                     "type": "string",
45362                     "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
45363                 },
45364                 "cache-vcs-dir": {
45365                     "type": "string",
45366                     "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
45367                 },
45368                 "cache-ttl": {
45369                     "type": "integer",
45370                     "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
45371                 },
45372                 "cache-files-ttl": {
45373                     "type": "integer",
45374                     "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
45375                 },
45376                 "cache-files-maxsize": {
45377                     "type": ["string", "integer"],
45378                     "description": "The cache max size for the files cache, defaults to \"300MiB\"."
45379                 },
45380                 "bin-compat": {
45381                     "enum": ["auto", "full"],
45382                     "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)."
45383                 },
45384                 "discard-changes": {
45385                     "type": ["string", "boolean"],
45386                     "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
45387                 },
45388                 "autoloader-suffix": {
45389                     "type": "string",
45390                     "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
45391                 },
45392                 "optimize-autoloader": {
45393                     "type": "boolean",
45394                     "description": "Always optimize when dumping the autoloader."
45395                 },
45396                 "prepend-autoloader": {
45397                     "type": "boolean",
45398                     "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
45399                 },
45400                 "classmap-authoritative": {
45401                     "type": "boolean",
45402                     "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
45403                 },
45404                 "apcu-autoloader": {
45405                     "type": "boolean",
45406                     "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."
45407                 },
45408                 "github-domains": {
45409                     "type": "array",
45410                     "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
45411                     "items": {
45412                         "type": "string"
45413                     }
45414                 },
45415                 "github-expose-hostname": {
45416                     "type": "boolean",
45417                     "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."
45418                 },
45419                 "gitlab-domains": {
45420                     "type": "array",
45421                     "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].",
45422                     "items": {
45423                         "type": "string"
45424                     }
45425                 },
45426                 "archive-format": {
45427                     "type": "string",
45428                     "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
45429                 },
45430                 "archive-dir": {
45431                     "type": "string",
45432                     "description": "The default archive path when not provided on cli, defaults to \".\"."
45433                 },
45434                 "htaccess-protect": {
45435                     "type": "boolean",
45436                     "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
45437                 },
45438                 "sort-packages": {
45439                     "type": "boolean",
45440                     "description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency."
45441                 }
45442             }
45443         },
45444         "extra": {
45445             "type": ["object", "array"],
45446             "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.",
45447             "additionalProperties": true
45448         },
45449         "autoload": {
45450             "$ref": "#/definitions/autoload"
45451         },
45452         "autoload-dev": {
45453             "type": "object",
45454             "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
45455             "properties": {
45456                 "psr-0": {
45457                     "type": "object",
45458                     "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.",
45459                     "additionalProperties": {
45460                         "type": ["string", "array"],
45461                         "items": {
45462                             "type": "string"
45463                         }
45464                     }
45465                 },
45466                 "psr-4": {
45467                     "type": "object",
45468                     "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.",
45469                     "additionalProperties": {
45470                         "type": ["string", "array"],
45471                         "items": {
45472                             "type": "string"
45473                         }
45474                     }
45475                 },
45476                 "classmap": {
45477                     "type": "array",
45478                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
45479                 },
45480                 "files": {
45481                     "type": "array",
45482                     "description": "This is an array of files that are always required on every request."
45483                 }
45484             }
45485         },
45486         "archive": {
45487             "type": ["object"],
45488             "description": "Options for creating package archives for distribution.",
45489             "properties": {
45490                 "exclude": {
45491                     "type": "array",
45492                     "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
45493                 }
45494             }
45495         },
45496         "repositories": {
45497             "type": ["object", "array"],
45498             "description": "A set of additional repositories where packages can be found.",
45499             "additionalProperties": {
45500                 "oneOf": [
45501                     { "$ref": "#/definitions/repository" },
45502                     { "type": "boolean", "enum": [false] }
45503                 ]
45504             },
45505             "items": {
45506                 "oneOf": [
45507                     { "$ref": "#/definitions/repository" },
45508                     {
45509                         "type": "object",
45510                         "additionalProperties": { "type": "boolean", "enum": [false] },
45511                         "minProperties": 1,
45512                         "maxProperties": 1
45513                     }
45514                 ]
45515             }
45516         },
45517         "minimum-stability": {
45518             "type": ["string"],
45519             "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
45520             "pattern": "^dev|alpha|beta|rc|RC|stable$"
45521         },
45522         "prefer-stable": {
45523             "type": ["boolean"],
45524             "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages."
45525         },
45526         "bin": {
45527             "type": ["string", "array"],
45528             "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
45529             "items": {
45530                 "type": "string"
45531             }
45532         },
45533         "include-path": {
45534             "type": ["array"],
45535             "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.",
45536             "items": {
45537                 "type": "string"
45538             }
45539         },
45540         "scripts": {
45541             "type": ["object"],
45542             "description": "Script listeners that will be executed before/after some events.",
45543             "properties": {
45544                 "pre-install-cmd": {
45545                     "type": ["array", "string"],
45546                     "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
45547                 },
45548                 "post-install-cmd": {
45549                     "type": ["array", "string"],
45550                     "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
45551                 },
45552                 "pre-update-cmd": {
45553                     "type": ["array", "string"],
45554                     "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
45555                 },
45556                 "post-update-cmd": {
45557                     "type": ["array", "string"],
45558                     "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
45559                 },
45560                 "pre-status-cmd": {
45561                     "type": ["array", "string"],
45562                     "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
45563                 },
45564                 "post-status-cmd": {
45565                     "type": ["array", "string"],
45566                     "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
45567                 },
45568                 "pre-package-install": {
45569                     "type": ["array", "string"],
45570                     "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
45571                 },
45572                 "post-package-install": {
45573                     "type": ["array", "string"],
45574                     "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
45575                 },
45576                 "pre-package-update": {
45577                     "type": ["array", "string"],
45578                     "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
45579                 },
45580                 "post-package-update": {
45581                     "type": ["array", "string"],
45582                     "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
45583                 },
45584                 "pre-package-uninstall": {
45585                     "type": ["array", "string"],
45586                     "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
45587                 },
45588                 "post-package-uninstall": {
45589                     "type": ["array", "string"],
45590                     "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
45591                 },
45592                 "pre-autoload-dump": {
45593                     "type": ["array", "string"],
45594                     "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
45595                 },
45596                 "post-autoload-dump": {
45597                     "type": ["array", "string"],
45598                     "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
45599                 },
45600                 "post-root-package-install": {
45601                     "type": ["array", "string"],
45602                     "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
45603                 },
45604                 "post-create-project-cmd": {
45605                     "type": ["array", "string"],
45606                     "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
45607                 }
45608             }
45609         },
45610         "scripts-descriptions": {
45611             "type": ["object"],
45612             "description": "Descriptions for custom commands, shown in console help.",
45613             "additionalProperties": {
45614                 "type": "string"
45615             }
45616         },
45617         "support": {
45618             "type": "object",
45619             "properties": {
45620                 "email": {
45621                     "type": "string",
45622                     "description": "Email address for support.",
45623                     "format": "email"
45624                 },
45625                 "issues": {
45626                     "type": "string",
45627                     "description": "URL to the issue tracker.",
45628                     "format": "uri"
45629                 },
45630                 "forum": {
45631                     "type": "string",
45632                     "description": "URL to the forum.",
45633                     "format": "uri"
45634                 },
45635                 "wiki": {
45636                     "type": "string",
45637                     "description": "URL to the wiki.",
45638                     "format": "uri"
45639                 },
45640                 "irc": {
45641                     "type": "string",
45642                     "description": "IRC channel for support, as irc://server/channel.",
45643                     "format": "uri"
45644                 },
45645                 "source": {
45646                     "type": "string",
45647                     "description": "URL to browse or download the sources.",
45648                     "format": "uri"
45649                 },
45650                 "docs": {
45651                     "type": "string",
45652                     "description": "URL to the documentation.",
45653                     "format": "uri"
45654                 },
45655                 "rss": {
45656                     "type": "string",
45657                     "description": "URL to the RSS feed.",
45658                     "format": "uri"
45659                 }
45660             }
45661         },
45662         "non-feature-branches": {
45663             "type": ["array"],
45664             "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
45665             "items": {
45666                 "type": "string"
45667             }
45668         },
45669         "abandoned": {
45670             "type": ["boolean", "string"],
45671             "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."
45672         },
45673         "_comment": {
45674             "type": ["array", "string"],
45675             "description": "A key to store comments in"
45676         }
45677     },
45678     "definitions": {
45679         "authors": {
45680             "type": "array",
45681             "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
45682             "items": {
45683                 "type": "object",
45684                 "additionalProperties": false,
45685                 "required": [ "name"],
45686                 "properties": {
45687                     "name": {
45688                         "type": "string",
45689                         "description": "Full name of the author."
45690                     },
45691                     "email": {
45692                         "type": "string",
45693                         "description": "Email address of the author.",
45694                         "format": "email"
45695                     },
45696                     "homepage": {
45697                         "type": "string",
45698                         "description": "Homepage URL for the author.",
45699                         "format": "uri"
45700                     },
45701                     "role": {
45702                         "type": "string",
45703                         "description": "Author's role in the project."
45704                     }
45705                 }
45706             }
45707         },
45708         "autoload": {
45709             "type": "object",
45710             "description": "Description of how the package can be autoloaded.",
45711             "properties": {
45712                 "psr-0": {
45713                     "type": "object",
45714                     "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.",
45715                     "additionalProperties": {
45716                         "type": ["string", "array"],
45717                         "items": {
45718                             "type": "string"
45719                         }
45720                     }
45721                 },
45722                 "psr-4": {
45723                     "type": "object",
45724                     "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.",
45725                     "additionalProperties": {
45726                         "type": ["string", "array"],
45727                         "items": {
45728                             "type": "string"
45729                         }
45730                     }
45731                 },
45732                 "classmap": {
45733                     "type": "array",
45734                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
45735                 },
45736                 "files": {
45737                     "type": "array",
45738                     "description": "This is an array of files that are always required on every request."
45739                 },
45740                 "exclude-from-classmap": {
45741                     "type": "array",
45742                     "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
45743                 }
45744             }
45745         },
45746         "repository": {
45747             "type": "object",
45748             "oneOf": [
45749                 { "$ref": "#/definitions/composer-repository" },
45750                 { "$ref": "#/definitions/vcs-repository" },
45751                 { "$ref": "#/definitions/path-repository" },
45752                 { "$ref": "#/definitions/artifact-repository" },
45753                 { "$ref": "#/definitions/pear-repository" },
45754                 { "$ref": "#/definitions/package-repository" }
45755             ]
45756         },
45757         "composer-repository": {
45758             "type": "object",
45759             "required": ["type", "url"],
45760             "properties": {
45761                 "type": { "type": "string", "enum": ["composer"] },
45762                 "url": { "type": "string" },
45763                 "options": {
45764                     "type": "object",
45765                     "additionalProperties": true
45766                 },
45767                 "allow_ssl_downgrade": { "type": "boolean" },
45768                 "force-lazy-providers": { "type": "boolean" }
45769             }
45770         },
45771         "vcs-repository": {
45772             "type": "object",
45773             "required": ["type", "url"],
45774             "properties": {
45775                 "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] },
45776                 "url": { "type": "string" },
45777                 "no-api": { "type": "boolean" },
45778                 "secure-http": { "type": "boolean" },
45779                 "svn-cache-credentials": { "type": "boolean" },
45780                 "trunk-path": { "type": ["string", "boolean"] },
45781                 "branches-path": { "type": ["string", "boolean"] },
45782                 "tags-path": { "type": ["string", "boolean"] },
45783                 "package-path": { "type": "string" },
45784                 "depot": { "type": "string" },
45785                 "branch": { "type": "string" },
45786                 "unique_perforce_client_name": { "type": "string" },
45787                 "p4user": { "type": "string" },
45788                 "p4password": { "type": "string" }
45789             }
45790         },
45791         "path-repository": {
45792             "type": "object",
45793             "required": ["type", "url"],
45794             "properties": {
45795                 "type": { "type": "string", "enum": ["path"] },
45796                 "url": { "type": "string" },
45797                 "options": {
45798                     "type": "object",
45799                     "properties": {
45800                         "symlink": { "type": ["boolean", "null"] }
45801                     },
45802                     "additionalProperties": true
45803                 }
45804             }
45805         },
45806         "artifact-repository": {
45807             "type": "object",
45808             "required": ["type", "url"],
45809             "properties": {
45810                 "type": { "type": "string", "enum": ["artifact"] },
45811                 "url": { "type": "string" }
45812             }
45813         },
45814         "pear-repository": {
45815             "type": "object",
45816             "required": ["type", "url"],
45817             "properties": {
45818                 "type": { "type": "string", "enum": ["pear"] },
45819                 "url": { "type": "string" },
45820                 "vendor-alias": { "type": "string" }
45821             }
45822         },
45823         "package-repository": {
45824             "type": "object",
45825             "required": ["type", "package"],
45826             "properties": {
45827                 "type": { "type": "string", "enum": ["package"] },
45828                 "package": {
45829                     "oneOf": [
45830                         { "$ref": "#/definitions/inline-package" },
45831                         {
45832                             "type": "array",
45833                             "items": {
45834                                 "type": { "$ref": "#/definitions/inline-package" }
45835                             }
45836                         }
45837                     ]
45838                 }
45839             }
45840         },
45841         "inline-package": {
45842             "required": ["name", "version"],
45843             "properties": {
45844                 "name": {
45845                     "type": "string",
45846                     "description": "Package name, including 'vendor-name/' prefix."
45847                 },
45848                 "type": {
45849                     "type": "string"
45850                 },
45851                 "target-dir": {
45852                     "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.",
45853                     "type": "string"
45854                 },
45855                 "description": {
45856                     "type": "string"
45857                 },
45858                 "keywords": {
45859                     "type": "array",
45860                     "items": {
45861                         "type": "string"
45862                     }
45863                 },
45864                 "homepage": {
45865                     "type": "string",
45866                     "format": "uri"
45867                 },
45868                 "version": {
45869                     "type": "string"
45870                 },
45871                 "time": {
45872                     "type": "string"
45873                 },
45874                 "license": {
45875                     "type": [
45876                         "string",
45877                         "array"
45878                     ]
45879                 },
45880                 "authors": {
45881                     "$ref": "#/definitions/authors"
45882                 },
45883                 "require": {
45884                     "type": "object",
45885                     "additionalProperties": {
45886                         "type": "string"
45887                     }
45888                 },
45889                 "replace": {
45890                     "type": "object",
45891                     "additionalProperties": {
45892                         "type": "string"
45893                     }
45894                 },
45895                 "conflict": {
45896                     "type": "object",
45897                     "additionalProperties": {
45898                         "type": "string"
45899                     }
45900                 },
45901                 "provide": {
45902                     "type": "object",
45903                     "additionalProperties": {
45904                         "type": "string"
45905                     }
45906                 },
45907                 "require-dev": {
45908                     "type": "object",
45909                     "additionalProperties": {
45910                         "type": "string"
45911                     }
45912                 },
45913                 "suggest": {
45914                     "type": "object",
45915                     "additionalProperties": {
45916                         "type": "string"
45917                     }
45918                 },
45919                 "extra": {
45920                     "type": ["object", "array"],
45921                     "additionalProperties": true
45922                 },
45923                 "autoload": {
45924                     "$ref": "#/definitions/autoload"
45925                 },
45926                 "archive": {
45927                     "type": ["object"],
45928                     "properties": {
45929                         "exclude": {
45930                             "type": "array"
45931                         }
45932                     }
45933                 },
45934                 "bin": {
45935                     "type": ["string", "array"],
45936                     "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
45937                     "items": {
45938                         "type": "string"
45939                     }
45940                 },
45941                 "include-path": {
45942                     "type": ["array"],
45943                     "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.",
45944                     "items": {
45945                         "type": "string"
45946                     }
45947                 },
45948                 "source": {
45949                     "type": "object",
45950                     "required": ["type", "url", "reference"],
45951                     "properties": {
45952                         "type": {
45953                             "type": "string"
45954                         },
45955                         "url": {
45956                             "type": "string"
45957                         },
45958                         "reference": {
45959                             "type": "string"
45960                         },
45961                         "mirrors": {
45962                             "type": "array"
45963                         }
45964                     }
45965                 },
45966                 "dist": {
45967                     "type": "object",
45968                     "required": ["type", "url"],
45969                     "properties": {
45970                         "type": {
45971                             "type": "string"
45972                         },
45973                         "url": {
45974                             "type": "string"
45975                         },
45976                         "reference": {
45977                             "type": "string"
45978                         },
45979                         "shasum": {
45980                             "type": "string"
45981                         },
45982                         "mirrors": {
45983                             "type": "array"
45984                         }
45985                     }
45986                 }
45987             },
45988             "additionalProperties": true
45989         }
45990     }
45991 }
45992 {
45993     "389-exception": [
45994         "389 Directory Server Exception"
45995     ],
45996     "Autoconf-exception-2.0": [
45997         "Autoconf exception 2.0"
45998     ],
45999     "Autoconf-exception-3.0": [
46000         "Autoconf exception 3.0"
46001     ],
46002     "Bison-exception-2.2": [
46003         "Bison exception 2.2"
46004     ],
46005     "Bootloader-exception": [
46006         "Bootloader Distribution Exception"
46007     ],
46008     "Classpath-exception-2.0": [
46009         "Classpath exception 2.0"
46010     ],
46011     "CLISP-exception-2.0": [
46012         "CLISP exception 2.0"
46013     ],
46014     "DigiRule-FOSS-exception": [
46015         "DigiRule FOSS License Exception"
46016     ],
46017     "eCos-exception-2.0": [
46018         "eCos exception 2.0"
46019     ],
46020     "Fawkes-Runtime-exception": [
46021         "Fawkes Runtime Exception"
46022     ],
46023     "FLTK-exception": [
46024         "FLTK exception"
46025     ],
46026     "Font-exception-2.0": [
46027         "Font exception 2.0"
46028     ],
46029     "freertos-exception-2.0": [
46030         "FreeRTOS Exception 2.0"
46031     ],
46032     "GCC-exception-2.0": [
46033         "GCC Runtime Library exception 2.0"
46034     ],
46035     "GCC-exception-3.1": [
46036         "GCC Runtime Library exception 3.1"
46037     ],
46038     "gnu-javamail-exception": [
46039         "GNU JavaMail exception"
46040     ],
46041     "i2p-gpl-java-exception": [
46042         "i2p GPL+Java Exception"
46043     ],
46044     "Libtool-exception": [
46045         "Libtool Exception"
46046     ],
46047     "Linux-syscall-note": [
46048         "Linux Syscall Note"
46049     ],
46050     "LZMA-exception": [
46051         "LZMA exception"
46052     ],
46053     "mif-exception": [
46054         "Macros and Inline Functions Exception"
46055     ],
46056     "Nokia-Qt-exception-1.1": [
46057         "Nokia Qt LGPL exception 1.1"
46058     ],
46059     "OCCT-exception-1.0": [
46060         "Open CASCADE Exception 1.0"
46061     ],
46062     "openvpn-openssl-exception": [
46063         "OpenVPN OpenSSL Exception"
46064     ],
46065     "Qwt-exception-1.0": [
46066         "Qwt exception 1.0"
46067     ],
46068     "u-boot-exception-2.0": [
46069         "U-Boot exception 2.0"
46070     ],
46071     "WxWindows-exception-3.1": [
46072         "WxWindows Library Exception 3.1"
46073     ]
46074 }{
46075     "0BSD": [
46076         "BSD Zero Clause License",
46077         false,
46078         false
46079     ],
46080     "AAL": [
46081         "Attribution Assurance License",
46082         true,
46083         false
46084     ],
46085     "Abstyles": [
46086         "Abstyles License",
46087         false,
46088         false
46089     ],
46090     "Adobe-2006": [
46091         "Adobe Systems Incorporated Source Code License Agreement",
46092         false,
46093         false
46094     ],
46095     "Adobe-Glyph": [
46096         "Adobe Glyph List License",
46097         false,
46098         false
46099     ],
46100     "ADSL": [
46101         "Amazon Digital Services License",
46102         false,
46103         false
46104     ],
46105     "AFL-1.1": [
46106         "Academic Free License v1.1",
46107         true,
46108         false
46109     ],
46110     "AFL-1.2": [
46111         "Academic Free License v1.2",
46112         true,
46113         false
46114     ],
46115     "AFL-2.0": [
46116         "Academic Free License v2.0",
46117         true,
46118         false
46119     ],
46120     "AFL-2.1": [
46121         "Academic Free License v2.1",
46122         true,
46123         false
46124     ],
46125     "AFL-3.0": [
46126         "Academic Free License v3.0",
46127         true,
46128         false
46129     ],
46130     "Afmparse": [
46131         "Afmparse License",
46132         false,
46133         false
46134     ],
46135     "AGPL-1.0": [
46136         "Affero General Public License v1.0",
46137         false,
46138         false
46139     ],
46140     "AGPL-3.0": [
46141         "GNU Affero General Public License v3.0",
46142         true,
46143         true
46144     ],
46145     "AGPL-3.0-only": [
46146         "GNU Affero General Public License v3.0 only",
46147         true,
46148         false
46149     ],
46150     "AGPL-3.0-or-later": [
46151         "GNU Affero General Public License v3.0 or later",
46152         true,
46153         false
46154     ],
46155     "Aladdin": [
46156         "Aladdin Free Public License",
46157         false,
46158         false
46159     ],
46160     "AMDPLPA": [
46161         "AMD's plpa_map.c License",
46162         false,
46163         false
46164     ],
46165     "AML": [
46166         "Apple MIT License",
46167         false,
46168         false
46169     ],
46170     "AMPAS": [
46171         "Academy of Motion Picture Arts and Sciences BSD",
46172         false,
46173         false
46174     ],
46175     "ANTLR-PD": [
46176         "ANTLR Software Rights Notice",
46177         false,
46178         false
46179     ],
46180     "Apache-1.0": [
46181         "Apache License 1.0",
46182         false,
46183         false
46184     ],
46185     "Apache-1.1": [
46186         "Apache License 1.1",
46187         true,
46188         false
46189     ],
46190     "Apache-2.0": [
46191         "Apache License 2.0",
46192         true,
46193         false
46194     ],
46195     "APAFML": [
46196         "Adobe Postscript AFM License",
46197         false,
46198         false
46199     ],
46200     "APL-1.0": [
46201         "Adaptive Public License 1.0",
46202         true,
46203         false
46204     ],
46205     "APSL-1.0": [
46206         "Apple Public Source License 1.0",
46207         true,
46208         false
46209     ],
46210     "APSL-1.1": [
46211         "Apple Public Source License 1.1",
46212         true,
46213         false
46214     ],
46215     "APSL-1.2": [
46216         "Apple Public Source License 1.2",
46217         true,
46218         false
46219     ],
46220     "APSL-2.0": [
46221         "Apple Public Source License 2.0",
46222         true,
46223         false
46224     ],
46225     "Artistic-1.0": [
46226         "Artistic License 1.0",
46227         true,
46228         false
46229     ],
46230     "Artistic-1.0-cl8": [
46231         "Artistic License 1.0 w/clause 8",
46232         true,
46233         false
46234     ],
46235     "Artistic-1.0-Perl": [
46236         "Artistic License 1.0 (Perl)",
46237         true,
46238         false
46239     ],
46240     "Artistic-2.0": [
46241         "Artistic License 2.0",
46242         true,
46243         false
46244     ],
46245     "Bahyph": [
46246         "Bahyph License",
46247         false,
46248         false
46249     ],
46250     "Barr": [
46251         "Barr License",
46252         false,
46253         false
46254     ],
46255     "Beerware": [
46256         "Beerware License",
46257         false,
46258         false
46259     ],
46260     "BitTorrent-1.0": [
46261         "BitTorrent Open Source License v1.0",
46262         false,
46263         false
46264     ],
46265     "BitTorrent-1.1": [
46266         "BitTorrent Open Source License v1.1",
46267         false,
46268         false
46269     ],
46270     "Borceux": [
46271         "Borceux license",
46272         false,
46273         false
46274     ],
46275     "BSD-1-Clause": [
46276         "BSD 1-Clause License",
46277         false,
46278         false
46279     ],
46280     "BSD-2-Clause": [
46281         "BSD 2-Clause \"Simplified\" License",
46282         true,
46283         false
46284     ],
46285     "BSD-2-Clause-FreeBSD": [
46286         "BSD 2-Clause FreeBSD License",
46287         false,
46288         false
46289     ],
46290     "BSD-2-Clause-NetBSD": [
46291         "BSD 2-Clause NetBSD License",
46292         false,
46293         false
46294     ],
46295     "BSD-2-Clause-Patent": [
46296         "BSD-2-Clause Plus Patent License",
46297         true,
46298         false
46299     ],
46300     "BSD-3-Clause": [
46301         "BSD 3-Clause \"New\" or \"Revised\" License",
46302         true,
46303         false
46304     ],
46305     "BSD-3-Clause-Attribution": [
46306         "BSD with attribution",
46307         false,
46308         false
46309     ],
46310     "BSD-3-Clause-Clear": [
46311         "BSD 3-Clause Clear License",
46312         false,
46313         false
46314     ],
46315     "BSD-3-Clause-LBNL": [
46316         "Lawrence Berkeley National Labs BSD variant license",
46317         false,
46318         false
46319     ],
46320     "BSD-3-Clause-No-Nuclear-License": [
46321         "BSD 3-Clause No Nuclear License",
46322         false,
46323         false
46324     ],
46325     "BSD-3-Clause-No-Nuclear-License-2014": [
46326         "BSD 3-Clause No Nuclear License 2014",
46327         false,
46328         false
46329     ],
46330     "BSD-3-Clause-No-Nuclear-Warranty": [
46331         "BSD 3-Clause No Nuclear Warranty",
46332         false,
46333         false
46334     ],
46335     "BSD-4-Clause": [
46336         "BSD 4-Clause \"Original\" or \"Old\" License",
46337         false,
46338         false
46339     ],
46340     "BSD-4-Clause-UC": [
46341         "BSD-4-Clause (University of California-Specific)",
46342         false,
46343         false
46344     ],
46345     "BSD-Protection": [
46346         "BSD Protection License",
46347         false,
46348         false
46349     ],
46350     "BSD-Source-Code": [
46351         "BSD Source Code Attribution",
46352         false,
46353         false
46354     ],
46355     "BSL-1.0": [
46356         "Boost Software License 1.0",
46357         true,
46358         false
46359     ],
46360     "bzip2-1.0.5": [
46361         "bzip2 and libbzip2 License v1.0.5",
46362         false,
46363         false
46364     ],
46365     "bzip2-1.0.6": [
46366         "bzip2 and libbzip2 License v1.0.6",
46367         false,
46368         false
46369     ],
46370     "Caldera": [
46371         "Caldera License",
46372         false,
46373         false
46374     ],
46375     "CATOSL-1.1": [
46376         "Computer Associates Trusted Open Source License 1.1",
46377         true,
46378         false
46379     ],
46380     "CC-BY-1.0": [
46381         "Creative Commons Attribution 1.0",
46382         false,
46383         false
46384     ],
46385     "CC-BY-2.0": [
46386         "Creative Commons Attribution 2.0",
46387         false,
46388         false
46389     ],
46390     "CC-BY-2.5": [
46391         "Creative Commons Attribution 2.5",
46392         false,
46393         false
46394     ],
46395     "CC-BY-3.0": [
46396         "Creative Commons Attribution 3.0",
46397         false,
46398         false
46399     ],
46400     "CC-BY-4.0": [
46401         "Creative Commons Attribution 4.0",
46402         false,
46403         false
46404     ],
46405     "CC-BY-NC-1.0": [
46406         "Creative Commons Attribution Non Commercial 1.0",
46407         false,
46408         false
46409     ],
46410     "CC-BY-NC-2.0": [
46411         "Creative Commons Attribution Non Commercial 2.0",
46412         false,
46413         false
46414     ],
46415     "CC-BY-NC-2.5": [
46416         "Creative Commons Attribution Non Commercial 2.5",
46417         false,
46418         false
46419     ],
46420     "CC-BY-NC-3.0": [
46421         "Creative Commons Attribution Non Commercial 3.0",
46422         false,
46423         false
46424     ],
46425     "CC-BY-NC-4.0": [
46426         "Creative Commons Attribution Non Commercial 4.0",
46427         false,
46428         false
46429     ],
46430     "CC-BY-NC-ND-1.0": [
46431         "Creative Commons Attribution Non Commercial No Derivatives 1.0",
46432         false,
46433         false
46434     ],
46435     "CC-BY-NC-ND-2.0": [
46436         "Creative Commons Attribution Non Commercial No Derivatives 2.0",
46437         false,
46438         false
46439     ],
46440     "CC-BY-NC-ND-2.5": [
46441         "Creative Commons Attribution Non Commercial No Derivatives 2.5",
46442         false,
46443         false
46444     ],
46445     "CC-BY-NC-ND-3.0": [
46446         "Creative Commons Attribution Non Commercial No Derivatives 3.0",
46447         false,
46448         false
46449     ],
46450     "CC-BY-NC-ND-4.0": [
46451         "Creative Commons Attribution Non Commercial No Derivatives 4.0",
46452         false,
46453         false
46454     ],
46455     "CC-BY-NC-SA-1.0": [
46456         "Creative Commons Attribution Non Commercial Share Alike 1.0",
46457         false,
46458         false
46459     ],
46460     "CC-BY-NC-SA-2.0": [
46461         "Creative Commons Attribution Non Commercial Share Alike 2.0",
46462         false,
46463         false
46464     ],
46465     "CC-BY-NC-SA-2.5": [
46466         "Creative Commons Attribution Non Commercial Share Alike 2.5",
46467         false,
46468         false
46469     ],
46470     "CC-BY-NC-SA-3.0": [
46471         "Creative Commons Attribution Non Commercial Share Alike 3.0",
46472         false,
46473         false
46474     ],
46475     "CC-BY-NC-SA-4.0": [
46476         "Creative Commons Attribution Non Commercial Share Alike 4.0",
46477         false,
46478         false
46479     ],
46480     "CC-BY-ND-1.0": [
46481         "Creative Commons Attribution No Derivatives 1.0",
46482         false,
46483         false
46484     ],
46485     "CC-BY-ND-2.0": [
46486         "Creative Commons Attribution No Derivatives 2.0",
46487         false,
46488         false
46489     ],
46490     "CC-BY-ND-2.5": [
46491         "Creative Commons Attribution No Derivatives 2.5",
46492         false,
46493         false
46494     ],
46495     "CC-BY-ND-3.0": [
46496         "Creative Commons Attribution No Derivatives 3.0",
46497         false,
46498         false
46499     ],
46500     "CC-BY-ND-4.0": [
46501         "Creative Commons Attribution No Derivatives 4.0",
46502         false,
46503         false
46504     ],
46505     "CC-BY-SA-1.0": [
46506         "Creative Commons Attribution Share Alike 1.0",
46507         false,
46508         false
46509     ],
46510     "CC-BY-SA-2.0": [
46511         "Creative Commons Attribution Share Alike 2.0",
46512         false,
46513         false
46514     ],
46515     "CC-BY-SA-2.5": [
46516         "Creative Commons Attribution Share Alike 2.5",
46517         false,
46518         false
46519     ],
46520     "CC-BY-SA-3.0": [
46521         "Creative Commons Attribution Share Alike 3.0",
46522         false,
46523         false
46524     ],
46525     "CC-BY-SA-4.0": [
46526         "Creative Commons Attribution Share Alike 4.0",
46527         false,
46528         false
46529     ],
46530     "CC0-1.0": [
46531         "Creative Commons Zero v1.0 Universal",
46532         false,
46533         false
46534     ],
46535     "CDDL-1.0": [
46536         "Common Development and Distribution License 1.0",
46537         true,
46538         false
46539     ],
46540     "CDDL-1.1": [
46541         "Common Development and Distribution License 1.1",
46542         false,
46543         false
46544     ],
46545     "CDLA-Permissive-1.0": [
46546         "Community Data License Agreement Permissive 1.0",
46547         false,
46548         false
46549     ],
46550     "CDLA-Sharing-1.0": [
46551         "Community Data License Agreement Sharing 1.0",
46552         false,
46553         false
46554     ],
46555     "CECILL-1.0": [
46556         "CeCILL Free Software License Agreement v1.0",
46557         false,
46558         false
46559     ],
46560     "CECILL-1.1": [
46561         "CeCILL Free Software License Agreement v1.1",
46562         false,
46563         false
46564     ],
46565     "CECILL-2.0": [
46566         "CeCILL Free Software License Agreement v2.0",
46567         false,
46568         false
46569     ],
46570     "CECILL-2.1": [
46571         "CeCILL Free Software License Agreement v2.1",
46572         true,
46573         false
46574     ],
46575     "CECILL-B": [
46576         "CeCILL-B Free Software License Agreement",
46577         false,
46578         false
46579     ],
46580     "CECILL-C": [
46581         "CeCILL-C Free Software License Agreement",
46582         false,
46583         false
46584     ],
46585     "ClArtistic": [
46586         "Clarified Artistic License",
46587         false,
46588         false
46589     ],
46590     "CNRI-Jython": [
46591         "CNRI Jython License",
46592         false,
46593         false
46594     ],
46595     "CNRI-Python": [
46596         "CNRI Python License",
46597         true,
46598         false
46599     ],
46600     "CNRI-Python-GPL-Compatible": [
46601         "CNRI Python Open Source GPL Compatible License Agreement",
46602         false,
46603         false
46604     ],
46605     "Condor-1.1": [
46606         "Condor Public License v1.1",
46607         false,
46608         false
46609     ],
46610     "CPAL-1.0": [
46611         "Common Public Attribution License 1.0",
46612         true,
46613         false
46614     ],
46615     "CPL-1.0": [
46616         "Common Public License 1.0",
46617         true,
46618         false
46619     ],
46620     "CPOL-1.02": [
46621         "Code Project Open License 1.02",
46622         false,
46623         false
46624     ],
46625     "Crossword": [
46626         "Crossword License",
46627         false,
46628         false
46629     ],
46630     "CrystalStacker": [
46631         "CrystalStacker License",
46632         false,
46633         false
46634     ],
46635     "CUA-OPL-1.0": [
46636         "CUA Office Public License v1.0",
46637         true,
46638         false
46639     ],
46640     "Cube": [
46641         "Cube License",
46642         false,
46643         false
46644     ],
46645     "curl": [
46646         "curl License",
46647         false,
46648         false
46649     ],
46650     "D-FSL-1.0": [
46651         "Deutsche Freie Software Lizenz",
46652         false,
46653         false
46654     ],
46655     "diffmark": [
46656         "diffmark license",
46657         false,
46658         false
46659     ],
46660     "DOC": [
46661         "DOC License",
46662         false,
46663         false
46664     ],
46665     "Dotseqn": [
46666         "Dotseqn License",
46667         false,
46668         false
46669     ],
46670     "DSDP": [
46671         "DSDP License",
46672         false,
46673         false
46674     ],
46675     "dvipdfm": [
46676         "dvipdfm License",
46677         false,
46678         false
46679     ],
46680     "ECL-1.0": [
46681         "Educational Community License v1.0",
46682         true,
46683         false
46684     ],
46685     "ECL-2.0": [
46686         "Educational Community License v2.0",
46687         true,
46688         false
46689     ],
46690     "eCos-2.0": [
46691         "eCos license version 2.0",
46692         false,
46693         true
46694     ],
46695     "EFL-1.0": [
46696         "Eiffel Forum License v1.0",
46697         true,
46698         false
46699     ],
46700     "EFL-2.0": [
46701         "Eiffel Forum License v2.0",
46702         true,
46703         false
46704     ],
46705     "eGenix": [
46706         "eGenix.com Public License 1.1.0",
46707         false,
46708         false
46709     ],
46710     "Entessa": [
46711         "Entessa Public License v1.0",
46712         true,
46713         false
46714     ],
46715     "EPL-1.0": [
46716         "Eclipse Public License 1.0",
46717         true,
46718         false
46719     ],
46720     "EPL-2.0": [
46721         "Eclipse Public License 2.0",
46722         true,
46723         false
46724     ],
46725     "ErlPL-1.1": [
46726         "Erlang Public License v1.1",
46727         false,
46728         false
46729     ],
46730     "EUDatagrid": [
46731         "EU DataGrid Software License",
46732         true,
46733         false
46734     ],
46735     "EUPL-1.0": [
46736         "European Union Public License 1.0",
46737         false,
46738         false
46739     ],
46740     "EUPL-1.1": [
46741         "European Union Public License 1.1",
46742         true,
46743         false
46744     ],
46745     "EUPL-1.2": [
46746         "European Union Public License 1.2",
46747         true,
46748         false
46749     ],
46750     "Eurosym": [
46751         "Eurosym License",
46752         false,
46753         false
46754     ],
46755     "Fair": [
46756         "Fair License",
46757         true,
46758         false
46759     ],
46760     "Frameworx-1.0": [
46761         "Frameworx Open License 1.0",
46762         true,
46763         false
46764     ],
46765     "FreeImage": [
46766         "FreeImage Public License v1.0",
46767         false,
46768         false
46769     ],
46770     "FSFAP": [
46771         "FSF All Permissive License",
46772         false,
46773         false
46774     ],
46775     "FSFUL": [
46776         "FSF Unlimited License",
46777         false,
46778         false
46779     ],
46780     "FSFULLR": [
46781         "FSF Unlimited License (with License Retention)",
46782         false,
46783         false
46784     ],
46785     "FTL": [
46786         "Freetype Project License",
46787         false,
46788         false
46789     ],
46790     "GFDL-1.1": [
46791         "GNU Free Documentation License v1.1",
46792         false,
46793         true
46794     ],
46795     "GFDL-1.1-only": [
46796         "GNU Free Documentation License v1.1 only",
46797         false,
46798         false
46799     ],
46800     "GFDL-1.1-or-later": [
46801         "GNU Free Documentation License v1.1 or later",
46802         false,
46803         false
46804     ],
46805     "GFDL-1.2": [
46806         "GNU Free Documentation License v1.2",
46807         false,
46808         true
46809     ],
46810     "GFDL-1.2-only": [
46811         "GNU Free Documentation License v1.2 only",
46812         false,
46813         false
46814     ],
46815     "GFDL-1.2-or-later": [
46816         "GNU Free Documentation License v1.2 or later",
46817         false,
46818         false
46819     ],
46820     "GFDL-1.3": [
46821         "GNU Free Documentation License v1.3",
46822         false,
46823         true
46824     ],
46825     "GFDL-1.3-only": [
46826         "GNU Free Documentation License v1.3 only",
46827         false,
46828         false
46829     ],
46830     "GFDL-1.3-or-later": [
46831         "GNU Free Documentation License v1.3 or later",
46832         false,
46833         false
46834     ],
46835     "Giftware": [
46836         "Giftware License",
46837         false,
46838         false
46839     ],
46840     "GL2PS": [
46841         "GL2PS License",
46842         false,
46843         false
46844     ],
46845     "Glide": [
46846         "3dfx Glide License",
46847         false,
46848         false
46849     ],
46850     "Glulxe": [
46851         "Glulxe License",
46852         false,
46853         false
46854     ],
46855     "gnuplot": [
46856         "gnuplot License",
46857         false,
46858         false
46859     ],
46860     "GPL-1.0": [
46861         "GNU General Public License v1.0 only",
46862         false,
46863         true
46864     ],
46865     "GPL-1.0+": [
46866         "GNU General Public License v1.0 or later",
46867         false,
46868         true
46869     ],
46870     "GPL-1.0-only": [
46871         "GNU General Public License v1.0 only",
46872         false,
46873         false
46874     ],
46875     "GPL-1.0-or-later": [
46876         "GNU General Public License v1.0 or later",
46877         false,
46878         false
46879     ],
46880     "GPL-2.0": [
46881         "GNU General Public License v2.0 only",
46882         true,
46883         true
46884     ],
46885     "GPL-2.0+": [
46886         "GNU General Public License v2.0 or later",
46887         true,
46888         true
46889     ],
46890     "GPL-2.0-only": [
46891         "GNU General Public License v2.0 only",
46892         true,
46893         false
46894     ],
46895     "GPL-2.0-or-later": [
46896         "GNU General Public License v2.0 or later",
46897         true,
46898         false
46899     ],
46900     "GPL-2.0-with-autoconf-exception": [
46901         "GNU General Public License v2.0 w/Autoconf exception",
46902         false,
46903         true
46904     ],
46905     "GPL-2.0-with-bison-exception": [
46906         "GNU General Public License v2.0 w/Bison exception",
46907         false,
46908         true
46909     ],
46910     "GPL-2.0-with-classpath-exception": [
46911         "GNU General Public License v2.0 w/Classpath exception",
46912         false,
46913         true
46914     ],
46915     "GPL-2.0-with-font-exception": [
46916         "GNU General Public License v2.0 w/Font exception",
46917         false,
46918         true
46919     ],
46920     "GPL-2.0-with-GCC-exception": [
46921         "GNU General Public License v2.0 w/GCC Runtime Library exception",
46922         false,
46923         true
46924     ],
46925     "GPL-3.0": [
46926         "GNU General Public License v3.0 only",
46927         true,
46928         true
46929     ],
46930     "GPL-3.0+": [
46931         "GNU General Public License v3.0 or later",
46932         true,
46933         true
46934     ],
46935     "GPL-3.0-only": [
46936         "GNU General Public License v3.0 only",
46937         true,
46938         false
46939     ],
46940     "GPL-3.0-or-later": [
46941         "GNU General Public License v3.0 or later",
46942         true,
46943         false
46944     ],
46945     "GPL-3.0-with-autoconf-exception": [
46946         "GNU General Public License v3.0 w/Autoconf exception",
46947         false,
46948         true
46949     ],
46950     "GPL-3.0-with-GCC-exception": [
46951         "GNU General Public License v3.0 w/GCC Runtime Library exception",
46952         true,
46953         true
46954     ],
46955     "gSOAP-1.3b": [
46956         "gSOAP Public License v1.3b",
46957         false,
46958         false
46959     ],
46960     "HaskellReport": [
46961         "Haskell Language Report License",
46962         false,
46963         false
46964     ],
46965     "HPND": [
46966         "Historical Permission Notice and Disclaimer",
46967         true,
46968         false
46969     ],
46970     "IBM-pibs": [
46971         "IBM PowerPC Initialization and Boot Software",
46972         false,
46973         false
46974     ],
46975     "ICU": [
46976         "ICU License",
46977         false,
46978         false
46979     ],
46980     "IJG": [
46981         "Independent JPEG Group License",
46982         false,
46983         false
46984     ],
46985     "ImageMagick": [
46986         "ImageMagick License",
46987         false,
46988         false
46989     ],
46990     "iMatix": [
46991         "iMatix Standard Function Library Agreement",
46992         false,
46993         false
46994     ],
46995     "Imlib2": [
46996         "Imlib2 License",
46997         false,
46998         false
46999     ],
47000     "Info-ZIP": [
47001         "Info-ZIP License",
47002         false,
47003         false
47004     ],
47005     "Intel": [
47006         "Intel Open Source License",
47007         true,
47008         false
47009     ],
47010     "Intel-ACPI": [
47011         "Intel ACPI Software License Agreement",
47012         false,
47013         false
47014     ],
47015     "Interbase-1.0": [
47016         "Interbase Public License v1.0",
47017         false,
47018         false
47019     ],
47020     "IPA": [
47021         "IPA Font License",
47022         true,
47023         false
47024     ],
47025     "IPL-1.0": [
47026         "IBM Public License v1.0",
47027         true,
47028         false
47029     ],
47030     "ISC": [
47031         "ISC License",
47032         true,
47033         false
47034     ],
47035     "JasPer-2.0": [
47036         "JasPer License",
47037         false,
47038         false
47039     ],
47040     "JSON": [
47041         "JSON License",
47042         false,
47043         false
47044     ],
47045     "LAL-1.2": [
47046         "Licence Art Libre 1.2",
47047         false,
47048         false
47049     ],
47050     "LAL-1.3": [
47051         "Licence Art Libre 1.3",
47052         false,
47053         false
47054     ],
47055     "Latex2e": [
47056         "Latex2e License",
47057         false,
47058         false
47059     ],
47060     "Leptonica": [
47061         "Leptonica License",
47062         false,
47063         false
47064     ],
47065     "LGPL-2.0": [
47066         "GNU Library General Public License v2 only",
47067         true,
47068         true
47069     ],
47070     "LGPL-2.0+": [
47071         "GNU Library General Public License v2 or later",
47072         true,
47073         true
47074     ],
47075     "LGPL-2.0-only": [
47076         "GNU Library General Public License v2 only",
47077         true,
47078         false
47079     ],
47080     "LGPL-2.0-or-later": [
47081         "GNU Library General Public License v2 or later",
47082         true,
47083         false
47084     ],
47085     "LGPL-2.1": [
47086         "GNU Lesser General Public License v2.1 only",
47087         true,
47088         true
47089     ],
47090     "LGPL-2.1+": [
47091         "GNU Library General Public License v2 or later",
47092         true,
47093         true
47094     ],
47095     "LGPL-2.1-only": [
47096         "GNU Lesser General Public License v2.1 only",
47097         true,
47098         false
47099     ],
47100     "LGPL-2.1-or-later": [
47101         "GNU Lesser General Public License v2.1 or later",
47102         true,
47103         false
47104     ],
47105     "LGPL-3.0": [
47106         "GNU Lesser General Public License v3.0 only",
47107         true,
47108         true
47109     ],
47110     "LGPL-3.0+": [
47111         "GNU Lesser General Public License v3.0 or later",
47112         true,
47113         true
47114     ],
47115     "LGPL-3.0-only": [
47116         "GNU Lesser General Public License v3.0 only",
47117         true,
47118         false
47119     ],
47120     "LGPL-3.0-or-later": [
47121         "GNU Lesser General Public License v3.0 or later",
47122         true,
47123         false
47124     ],
47125     "LGPLLR": [
47126         "Lesser General Public License For Linguistic Resources",
47127         false,
47128         false
47129     ],
47130     "Libpng": [
47131         "libpng License",
47132         false,
47133         false
47134     ],
47135     "libtiff": [
47136         "libtiff License",
47137         false,
47138         false
47139     ],
47140     "LiLiQ-P-1.1": [
47141         "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1",
47142         true,
47143         false
47144     ],
47145     "LiLiQ-R-1.1": [
47146         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1",
47147         true,
47148         false
47149     ],
47150     "LiLiQ-Rplus-1.1": [
47151         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1",
47152         true,
47153         false
47154     ],
47155     "LPL-1.0": [
47156         "Lucent Public License Version 1.0",
47157         true,
47158         false
47159     ],
47160     "LPL-1.02": [
47161         "Lucent Public License v1.02",
47162         true,
47163         false
47164     ],
47165     "LPPL-1.0": [
47166         "LaTeX Project Public License v1.0",
47167         false,
47168         false
47169     ],
47170     "LPPL-1.1": [
47171         "LaTeX Project Public License v1.1",
47172         false,
47173         false
47174     ],
47175     "LPPL-1.2": [
47176         "LaTeX Project Public License v1.2",
47177         false,
47178         false
47179     ],
47180     "LPPL-1.3a": [
47181         "LaTeX Project Public License v1.3a",
47182         false,
47183         false
47184     ],
47185     "LPPL-1.3c": [
47186         "LaTeX Project Public License v1.3c",
47187         true,
47188         false
47189     ],
47190     "MakeIndex": [
47191         "MakeIndex License",
47192         false,
47193         false
47194     ],
47195     "MirOS": [
47196         "MirOS License",
47197         true,
47198         false
47199     ],
47200     "MIT": [
47201         "MIT License",
47202         true,
47203         false
47204     ],
47205     "MIT-advertising": [
47206         "Enlightenment License (e16)",
47207         false,
47208         false
47209     ],
47210     "MIT-CMU": [
47211         "CMU License",
47212         false,
47213         false
47214     ],
47215     "MIT-enna": [
47216         "enna License",
47217         false,
47218         false
47219     ],
47220     "MIT-feh": [
47221         "feh License",
47222         false,
47223         false
47224     ],
47225     "MITNFA": [
47226         "MIT +no-false-attribs license",
47227         false,
47228         false
47229     ],
47230     "Motosoto": [
47231         "Motosoto License",
47232         true,
47233         false
47234     ],
47235     "mpich2": [
47236         "mpich2 License",
47237         false,
47238         false
47239     ],
47240     "MPL-1.0": [
47241         "Mozilla Public License 1.0",
47242         true,
47243         false
47244     ],
47245     "MPL-1.1": [
47246         "Mozilla Public License 1.1",
47247         true,
47248         false
47249     ],
47250     "MPL-2.0": [
47251         "Mozilla Public License 2.0",
47252         true,
47253         false
47254     ],
47255     "MPL-2.0-no-copyleft-exception": [
47256         "Mozilla Public License 2.0 (no copyleft exception)",
47257         true,
47258         false
47259     ],
47260     "MS-PL": [
47261         "Microsoft Public License",
47262         true,
47263         false
47264     ],
47265     "MS-RL": [
47266         "Microsoft Reciprocal License",
47267         true,
47268         false
47269     ],
47270     "MTLL": [
47271         "Matrix Template Library License",
47272         false,
47273         false
47274     ],
47275     "Multics": [
47276         "Multics License",
47277         true,
47278         false
47279     ],
47280     "Mup": [
47281         "Mup License",
47282         false,
47283         false
47284     ],
47285     "NASA-1.3": [
47286         "NASA Open Source Agreement 1.3",
47287         true,
47288         false
47289     ],
47290     "Naumen": [
47291         "Naumen Public License",
47292         true,
47293         false
47294     ],
47295     "NBPL-1.0": [
47296         "Net Boolean Public License v1",
47297         false,
47298         false
47299     ],
47300     "NCSA": [
47301         "University of Illinois/NCSA Open Source License",
47302         true,
47303         false
47304     ],
47305     "Net-SNMP": [
47306         "Net-SNMP License",
47307         false,
47308         false
47309     ],
47310     "NetCDF": [
47311         "NetCDF license",
47312         false,
47313         false
47314     ],
47315     "Newsletr": [
47316         "Newsletr License",
47317         false,
47318         false
47319     ],
47320     "NGPL": [
47321         "Nethack General Public License",
47322         true,
47323         false
47324     ],
47325     "NLOD-1.0": [
47326         "Norwegian Licence for Open Government Data",
47327         false,
47328         false
47329     ],
47330     "NLPL": [
47331         "No Limit Public License",
47332         false,
47333         false
47334     ],
47335     "Nokia": [
47336         "Nokia Open Source License",
47337         true,
47338         false
47339     ],
47340     "NOSL": [
47341         "Netizen Open Source License",
47342         false,
47343         false
47344     ],
47345     "Noweb": [
47346         "Noweb License",
47347         false,
47348         false
47349     ],
47350     "NPL-1.0": [
47351         "Netscape Public License v1.0",
47352         false,
47353         false
47354     ],
47355     "NPL-1.1": [
47356         "Netscape Public License v1.1",
47357         false,
47358         false
47359     ],
47360     "NPOSL-3.0": [
47361         "Non-Profit Open Software License 3.0",
47362         true,
47363         false
47364     ],
47365     "NRL": [
47366         "NRL License",
47367         false,
47368         false
47369     ],
47370     "NTP": [
47371         "NTP License",
47372         true,
47373         false
47374     ],
47375     "Nunit": [
47376         "Nunit License",
47377         false,
47378         true
47379     ],
47380     "OCCT-PL": [
47381         "Open CASCADE Technology Public License",
47382         false,
47383         false
47384     ],
47385     "OCLC-2.0": [
47386         "OCLC Research Public License 2.0",
47387         true,
47388         false
47389     ],
47390     "ODbL-1.0": [
47391         "ODC Open Database License v1.0",
47392         false,
47393         false
47394     ],
47395     "OFL-1.0": [
47396         "SIL Open Font License 1.0",
47397         false,
47398         false
47399     ],
47400     "OFL-1.1": [
47401         "SIL Open Font License 1.1",
47402         true,
47403         false
47404     ],
47405     "OGTSL": [
47406         "Open Group Test Suite License",
47407         true,
47408         false
47409     ],
47410     "OLDAP-1.1": [
47411         "Open LDAP Public License v1.1",
47412         false,
47413         false
47414     ],
47415     "OLDAP-1.2": [
47416         "Open LDAP Public License v1.2",
47417         false,
47418         false
47419     ],
47420     "OLDAP-1.3": [
47421         "Open LDAP Public License v1.3",
47422         false,
47423         false
47424     ],
47425     "OLDAP-1.4": [
47426         "Open LDAP Public License v1.4",
47427         false,
47428         false
47429     ],
47430     "OLDAP-2.0": [
47431         "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
47432         false,
47433         false
47434     ],
47435     "OLDAP-2.0.1": [
47436         "Open LDAP Public License v2.0.1",
47437         false,
47438         false
47439     ],
47440     "OLDAP-2.1": [
47441         "Open LDAP Public License v2.1",
47442         false,
47443         false
47444     ],
47445     "OLDAP-2.2": [
47446         "Open LDAP Public License v2.2",
47447         false,
47448         false
47449     ],
47450     "OLDAP-2.2.1": [
47451         "Open LDAP Public License v2.2.1",
47452         false,
47453         false
47454     ],
47455     "OLDAP-2.2.2": [
47456         "Open LDAP Public License 2.2.2",
47457         false,
47458         false
47459     ],
47460     "OLDAP-2.3": [
47461         "Open LDAP Public License v2.3",
47462         false,
47463         false
47464     ],
47465     "OLDAP-2.4": [
47466         "Open LDAP Public License v2.4",
47467         false,
47468         false
47469     ],
47470     "OLDAP-2.5": [
47471         "Open LDAP Public License v2.5",
47472         false,
47473         false
47474     ],
47475     "OLDAP-2.6": [
47476         "Open LDAP Public License v2.6",
47477         false,
47478         false
47479     ],
47480     "OLDAP-2.7": [
47481         "Open LDAP Public License v2.7",
47482         false,
47483         false
47484     ],
47485     "OLDAP-2.8": [
47486         "Open LDAP Public License v2.8",
47487         false,
47488         false
47489     ],
47490     "OML": [
47491         "Open Market License",
47492         false,
47493         false
47494     ],
47495     "OpenSSL": [
47496         "OpenSSL License",
47497         false,
47498         false
47499     ],
47500     "OPL-1.0": [
47501         "Open Public License v1.0",
47502         false,
47503         false
47504     ],
47505     "OSET-PL-2.1": [
47506         "OSET Public License version 2.1",
47507         true,
47508         false
47509     ],
47510     "OSL-1.0": [
47511         "Open Software License 1.0",
47512         true,
47513         false
47514     ],
47515     "OSL-1.1": [
47516         "Open Software License 1.1",
47517         false,
47518         false
47519     ],
47520     "OSL-2.0": [
47521         "Open Software License 2.0",
47522         true,
47523         false
47524     ],
47525     "OSL-2.1": [
47526         "Open Software License 2.1",
47527         true,
47528         false
47529     ],
47530     "OSL-3.0": [
47531         "Open Software License 3.0",
47532         true,
47533         false
47534     ],
47535     "PDDL-1.0": [
47536         "ODC Public Domain Dedication & License 1.0",
47537         false,
47538         false
47539     ],
47540     "PHP-3.0": [
47541         "PHP License v3.0",
47542         true,
47543         false
47544     ],
47545     "PHP-3.01": [
47546         "PHP License v3.01",
47547         false,
47548         false
47549     ],
47550     "Plexus": [
47551         "Plexus Classworlds License",
47552         false,
47553         false
47554     ],
47555     "PostgreSQL": [
47556         "PostgreSQL License",
47557         true,
47558         false
47559     ],
47560     "psfrag": [
47561         "psfrag License",
47562         false,
47563         false
47564     ],
47565     "psutils": [
47566         "psutils License",
47567         false,
47568         false
47569     ],
47570     "Python-2.0": [
47571         "Python License 2.0",
47572         true,
47573         false
47574     ],
47575     "Qhull": [
47576         "Qhull License",
47577         false,
47578         false
47579     ],
47580     "QPL-1.0": [
47581         "Q Public License 1.0",
47582         true,
47583         false
47584     ],
47585     "Rdisc": [
47586         "Rdisc License",
47587         false,
47588         false
47589     ],
47590     "RHeCos-1.1": [
47591         "Red Hat eCos Public License v1.1",
47592         false,
47593         false
47594     ],
47595     "RPL-1.1": [
47596         "Reciprocal Public License 1.1",
47597         true,
47598         false
47599     ],
47600     "RPL-1.5": [
47601         "Reciprocal Public License 1.5",
47602         true,
47603         false
47604     ],
47605     "RPSL-1.0": [
47606         "RealNetworks Public Source License v1.0",
47607         true,
47608         false
47609     ],
47610     "RSA-MD": [
47611         "RSA Message-Digest License",
47612         false,
47613         false
47614     ],
47615     "RSCPL": [
47616         "Ricoh Source Code Public License",
47617         true,
47618         false
47619     ],
47620     "Ruby": [
47621         "Ruby License",
47622         false,
47623         false
47624     ],
47625     "SAX-PD": [
47626         "Sax Public Domain Notice",
47627         false,
47628         false
47629     ],
47630     "Saxpath": [
47631         "Saxpath License",
47632         false,
47633         false
47634     ],
47635     "SCEA": [
47636         "SCEA Shared Source License",
47637         false,
47638         false
47639     ],
47640     "Sendmail": [
47641         "Sendmail License",
47642         false,
47643         false
47644     ],
47645     "SGI-B-1.0": [
47646         "SGI Free Software License B v1.0",
47647         false,
47648         false
47649     ],
47650     "SGI-B-1.1": [
47651         "SGI Free Software License B v1.1",
47652         false,
47653         false
47654     ],
47655     "SGI-B-2.0": [
47656         "SGI Free Software License B v2.0",
47657         false,
47658         false
47659     ],
47660     "SimPL-2.0": [
47661         "Simple Public License 2.0",
47662         true,
47663         false
47664     ],
47665     "SISSL": [
47666         "Sun Industry Standards Source License v1.1",
47667         true,
47668         false
47669     ],
47670     "SISSL-1.2": [
47671         "Sun Industry Standards Source License v1.2",
47672         false,
47673         false
47674     ],
47675     "Sleepycat": [
47676         "Sleepycat License",
47677         true,
47678         false
47679     ],
47680     "SMLNJ": [
47681         "Standard ML of New Jersey License",
47682         false,
47683         false
47684     ],
47685     "SMPPL": [
47686         "Secure Messaging Protocol Public License",
47687         false,
47688         false
47689     ],
47690     "SNIA": [
47691         "SNIA Public License 1.1",
47692         false,
47693         false
47694     ],
47695     "Spencer-86": [
47696         "Spencer License 86",
47697         false,
47698         false
47699     ],
47700     "Spencer-94": [
47701         "Spencer License 94",
47702         false,
47703         false
47704     ],
47705     "Spencer-99": [
47706         "Spencer License 99",
47707         false,
47708         false
47709     ],
47710     "SPL-1.0": [
47711         "Sun Public License v1.0",
47712         true,
47713         false
47714     ],
47715     "StandardML-NJ": [
47716         "Standard ML of New Jersey License",
47717         false,
47718         true
47719     ],
47720     "SugarCRM-1.1.3": [
47721         "SugarCRM Public License v1.1.3",
47722         false,
47723         false
47724     ],
47725     "SWL": [
47726         "Scheme Widget Library (SWL) Software License Agreement",
47727         false,
47728         false
47729     ],
47730     "TCL": [
47731         "TCL/TK License",
47732         false,
47733         false
47734     ],
47735     "TCP-wrappers": [
47736         "TCP Wrappers License",
47737         false,
47738         false
47739     ],
47740     "TMate": [
47741         "TMate Open Source License",
47742         false,
47743         false
47744     ],
47745     "TORQUE-1.1": [
47746         "TORQUE v2.5+ Software License v1.1",
47747         false,
47748         false
47749     ],
47750     "TOSL": [
47751         "Trusster Open Source License",
47752         false,
47753         false
47754     ],
47755     "Unicode-DFS-2015": [
47756         "Unicode License Agreement - Data Files and Software (2015)",
47757         false,
47758         false
47759     ],
47760     "Unicode-DFS-2016": [
47761         "Unicode License Agreement - Data Files and Software (2016)",
47762         false,
47763         false
47764     ],
47765     "Unicode-TOU": [
47766         "Unicode Terms of Use",
47767         false,
47768         false
47769     ],
47770     "Unlicense": [
47771         "The Unlicense",
47772         false,
47773         false
47774     ],
47775     "UPL-1.0": [
47776         "Universal Permissive License v1.0",
47777         true,
47778         false
47779     ],
47780     "Vim": [
47781         "Vim License",
47782         false,
47783         false
47784     ],
47785     "VOSTROM": [
47786         "VOSTROM Public License for Open Source",
47787         false,
47788         false
47789     ],
47790     "VSL-1.0": [
47791         "Vovida Software License v1.0",
47792         true,
47793         false
47794     ],
47795     "W3C": [
47796         "W3C Software Notice and License (2002-12-31)",
47797         true,
47798         false
47799     ],
47800     "W3C-19980720": [
47801         "W3C Software Notice and License (1998-07-20)",
47802         false,
47803         false
47804     ],
47805     "W3C-20150513": [
47806         "W3C Software Notice and Document License (2015-05-13)",
47807         false,
47808         false
47809     ],
47810     "Watcom-1.0": [
47811         "Sybase Open Watcom Public License 1.0",
47812         true,
47813         false
47814     ],
47815     "Wsuipa": [
47816         "Wsuipa License",
47817         false,
47818         false
47819     ],
47820     "WTFPL": [
47821         "Do What The F*ck You Want To Public License",
47822         false,
47823         false
47824     ],
47825     "wxWindows": [
47826         "wxWindows Library License",
47827         false,
47828         true
47829     ],
47830     "X11": [
47831         "X11 License",
47832         false,
47833         false
47834     ],
47835     "Xerox": [
47836         "Xerox License",
47837         false,
47838         false
47839     ],
47840     "XFree86-1.1": [
47841         "XFree86 License 1.1",
47842         false,
47843         false
47844     ],
47845     "xinetd": [
47846         "xinetd License",
47847         false,
47848         false
47849     ],
47850     "Xnet": [
47851         "X.Net License",
47852         true,
47853         false
47854     ],
47855     "xpp": [
47856         "XPP License",
47857         false,
47858         false
47859     ],
47860     "XSkat": [
47861         "XSkat License",
47862         false,
47863         false
47864     ],
47865     "YPL-1.0": [
47866         "Yahoo! Public License v1.0",
47867         false,
47868         false
47869     ],
47870     "YPL-1.1": [
47871         "Yahoo! Public License v1.1",
47872         false,
47873         false
47874     ],
47875     "Zed": [
47876         "Zed License",
47877         false,
47878         false
47879     ],
47880     "Zend-2.0": [
47881         "Zend License v2.0",
47882         false,
47883         false
47884     ],
47885     "Zimbra-1.3": [
47886         "Zimbra Public License v1.3",
47887         false,
47888         false
47889     ],
47890     "Zimbra-1.4": [
47891         "Zimbra Public License v1.4",
47892         false,
47893         false
47894     ],
47895     "Zlib": [
47896         "zlib License",
47897         true,
47898         false
47899     ],
47900     "zlib-acknowledgement": [
47901         "zlib/libpng License with Acknowledgement",
47902         false,
47903         false
47904     ],
47905     "ZPL-1.1": [
47906         "Zope Public License 1.1",
47907         false,
47908         false
47909     ],
47910     "ZPL-2.0": [
47911         "Zope Public License 2.0",
47912         true,
47913         false
47914     ],
47915     "ZPL-2.1": [
47916         "Zope Public License 2.1",
47917         false,
47918         false
47919     ]
47920 }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
47921 $\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
47922 \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
47923 \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
47924 \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
47925 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
47926 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
47927 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
47928   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">\r
47929     <security>\r
47930       <requestedPrivileges>\r
47931         <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>\r
47932       </requestedPrivileges>\r
47933     </security>\r
47934   </trustInfo>\r
47935   <dependency>\r
47936     <dependentAssembly>\r
47937       <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>\r
47938     </dependentAssembly>\r
47939   </dependency>\r
47940 </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
47941
47942
47943
47944
47945
47946
47947
47948
47949
47950
47951 namespace Symfony\Component\Console;
47952
47953 use Symfony\Component\Console\Descriptor\TextDescriptor;
47954 use Symfony\Component\Console\Descriptor\XmlDescriptor;
47955 use Symfony\Component\Console\Exception\ExceptionInterface;
47956 use Symfony\Component\Console\Formatter\OutputFormatter;
47957 use Symfony\Component\Console\Helper\DebugFormatterHelper;
47958 use Symfony\Component\Console\Helper\Helper;
47959 use Symfony\Component\Console\Helper\ProcessHelper;
47960 use Symfony\Component\Console\Helper\QuestionHelper;
47961 use Symfony\Component\Console\Input\InputInterface;
47962 use Symfony\Component\Console\Input\ArgvInput;
47963 use Symfony\Component\Console\Input\ArrayInput;
47964 use Symfony\Component\Console\Input\InputDefinition;
47965 use Symfony\Component\Console\Input\InputOption;
47966 use Symfony\Component\Console\Input\InputArgument;
47967 use Symfony\Component\Console\Input\InputAwareInterface;
47968 use Symfony\Component\Console\Output\BufferedOutput;
47969 use Symfony\Component\Console\Output\OutputInterface;
47970 use Symfony\Component\Console\Output\ConsoleOutput;
47971 use Symfony\Component\Console\Output\ConsoleOutputInterface;
47972 use Symfony\Component\Console\Command\Command;
47973 use Symfony\Component\Console\Command\HelpCommand;
47974 use Symfony\Component\Console\Command\ListCommand;
47975 use Symfony\Component\Console\Helper\HelperSet;
47976 use Symfony\Component\Console\Helper\FormatterHelper;
47977 use Symfony\Component\Console\Helper\DialogHelper;
47978 use Symfony\Component\Console\Helper\ProgressHelper;
47979 use Symfony\Component\Console\Helper\TableHelper;
47980 use Symfony\Component\Console\Event\ConsoleCommandEvent;
47981 use Symfony\Component\Console\Event\ConsoleExceptionEvent;
47982 use Symfony\Component\Console\Event\ConsoleTerminateEvent;
47983 use Symfony\Component\Console\Exception\CommandNotFoundException;
47984 use Symfony\Component\Console\Exception\LogicException;
47985 use Symfony\Component\Debug\Exception\FatalThrowableError;
47986 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
47987
47988
47989
47990
47991
47992
47993
47994
47995
47996
47997
47998
47999
48000
48001
48002
48003 class Application
48004 {
48005 private $commands = array();
48006 private $wantHelps = false;
48007 private $runningCommand;
48008 private $name;
48009 private $version;
48010 private $catchExceptions = true;
48011 private $autoExit = true;
48012 private $definition;
48013 private $helperSet;
48014 private $dispatcher;
48015 private $terminalDimensions;
48016 private $defaultCommand;
48017 private $initialized;
48018
48019
48020
48021
48022
48023 public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
48024 {
48025 $this->name = $name;
48026 $this->version = $version;
48027 $this->defaultCommand = 'list';
48028 }
48029
48030 public function setDispatcher(EventDispatcherInterface $dispatcher)
48031 {
48032 $this->dispatcher = $dispatcher;
48033 }
48034
48035
48036
48037
48038
48039
48040
48041
48042 public function run(InputInterface $input = null, OutputInterface $output = null)
48043 {
48044 if (null === $input) {
48045 $input = new ArgvInput();
48046 }
48047
48048 if (null === $output) {
48049 $output = new ConsoleOutput();
48050 }
48051
48052 $this->configureIO($input, $output);
48053
48054 try {
48055 $e = null;
48056 $exitCode = $this->doRun($input, $output);
48057 } catch (\Exception $e) {
48058 }
48059
48060 if (null !== $e) {
48061 if (!$this->catchExceptions) {
48062 throw $e;
48063 }
48064
48065 if ($output instanceof ConsoleOutputInterface) {
48066 $this->renderException($e, $output->getErrorOutput());
48067 } else {
48068 $this->renderException($e, $output);
48069 }
48070
48071 $exitCode = $e->getCode();
48072 if (is_numeric($exitCode)) {
48073 $exitCode = (int) $exitCode;
48074 if (0 === $exitCode) {
48075 $exitCode = 1;
48076 }
48077 } else {
48078 $exitCode = 1;
48079 }
48080 }
48081
48082 if ($this->autoExit) {
48083 if ($exitCode > 255) {
48084 $exitCode = 255;
48085 }
48086
48087 exit($exitCode);
48088 }
48089
48090 return $exitCode;
48091 }
48092
48093
48094
48095
48096
48097
48098 public function doRun(InputInterface $input, OutputInterface $output)
48099 {
48100 if (true === $input->hasParameterOption(array('--version', '-V'))) {
48101 $output->writeln($this->getLongVersion());
48102
48103 return 0;
48104 }
48105
48106 $name = $this->getCommandName($input);
48107 if (true === $input->hasParameterOption(array('--help', '-h'))) {
48108 if (!$name) {
48109 $name = 'help';
48110 $input = new ArrayInput(array('command' => 'help'));
48111 } else {
48112 $this->wantHelps = true;
48113 }
48114 }
48115
48116 if (!$name) {
48117 $name = $this->defaultCommand;
48118 $definition = $this->getDefinition();
48119 $definition->setArguments(array_merge(
48120 $definition->getArguments(),
48121 array(
48122 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
48123 )
48124 ));
48125 }
48126
48127 $this->runningCommand = null;
48128
48129  $command = $this->find($name);
48130
48131 $this->runningCommand = $command;
48132 $exitCode = $this->doRunCommand($command, $input, $output);
48133 $this->runningCommand = null;
48134
48135 return $exitCode;
48136 }
48137
48138 public function setHelperSet(HelperSet $helperSet)
48139 {
48140 $this->helperSet = $helperSet;
48141 }
48142
48143
48144
48145
48146
48147
48148 public function getHelperSet()
48149 {
48150 if (!$this->helperSet) {
48151 $this->helperSet = $this->getDefaultHelperSet();
48152 }
48153
48154 return $this->helperSet;
48155 }
48156
48157 public function setDefinition(InputDefinition $definition)
48158 {
48159 $this->definition = $definition;
48160 }
48161
48162
48163
48164
48165
48166
48167 public function getDefinition()
48168 {
48169 if (!$this->definition) {
48170 $this->definition = $this->getDefaultInputDefinition();
48171 }
48172
48173 return $this->definition;
48174 }
48175
48176
48177
48178
48179
48180
48181 public function getHelp()
48182 {
48183 return $this->getLongVersion();
48184 }
48185
48186
48187
48188
48189
48190
48191 public function setCatchExceptions($boolean)
48192 {
48193 $this->catchExceptions = (bool) $boolean;
48194 }
48195
48196
48197
48198
48199
48200
48201 public function setAutoExit($boolean)
48202 {
48203 $this->autoExit = (bool) $boolean;
48204 }
48205
48206
48207
48208
48209
48210
48211 public function getName()
48212 {
48213 return $this->name;
48214 }
48215
48216
48217
48218
48219
48220
48221 public function setName($name)
48222 {
48223 $this->name = $name;
48224 }
48225
48226
48227
48228
48229
48230
48231 public function getVersion()
48232 {
48233 return $this->version;
48234 }
48235
48236
48237
48238
48239
48240
48241 public function setVersion($version)
48242 {
48243 $this->version = $version;
48244 }
48245
48246
48247
48248
48249
48250
48251 public function getLongVersion()
48252 {
48253 if ('UNKNOWN' !== $this->getName()) {
48254 if ('UNKNOWN' !== $this->getVersion()) {
48255 return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
48256 }
48257
48258 return sprintf('<info>%s</info>', $this->getName());
48259 }
48260
48261 return '<info>Console Tool</info>';
48262 }
48263
48264
48265
48266
48267
48268
48269
48270
48271 public function register($name)
48272 {
48273 return $this->add(new Command($name));
48274 }
48275
48276
48277
48278
48279
48280
48281
48282
48283 public function addCommands(array $commands)
48284 {
48285 foreach ($commands as $command) {
48286 $this->add($command);
48287 }
48288 }
48289
48290
48291
48292
48293
48294
48295
48296
48297
48298 public function add(Command $command)
48299 {
48300 $this->init();
48301
48302 $command->setApplication($this);
48303
48304 if (!$command->isEnabled()) {
48305 $command->setApplication(null);
48306
48307 return;
48308 }
48309
48310 if (null === $command->getDefinition()) {
48311 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
48312 }
48313
48314 $this->commands[$command->getName()] = $command;
48315
48316 foreach ($command->getAliases() as $alias) {
48317 $this->commands[$alias] = $command;
48318 }
48319
48320 return $command;
48321 }
48322
48323
48324
48325
48326
48327
48328
48329
48330
48331
48332 public function get($name)
48333 {
48334 $this->init();
48335
48336 if (!isset($this->commands[$name])) {
48337 throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
48338 }
48339
48340 $command = $this->commands[$name];
48341
48342 if ($this->wantHelps) {
48343 $this->wantHelps = false;
48344
48345 $helpCommand = $this->get('help');
48346 $helpCommand->setCommand($command);
48347
48348 return $helpCommand;
48349 }
48350
48351 return $command;
48352 }
48353
48354
48355
48356
48357
48358
48359
48360
48361 public function has($name)
48362 {
48363 $this->init();
48364
48365 return isset($this->commands[$name]);
48366 }
48367
48368
48369
48370
48371
48372
48373
48374
48375 public function getNamespaces()
48376 {
48377 $namespaces = array();
48378 foreach ($this->all() as $command) {
48379 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
48380
48381 foreach ($command->getAliases() as $alias) {
48382 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
48383 }
48384 }
48385
48386 return array_values(array_unique(array_filter($namespaces)));
48387 }
48388
48389
48390
48391
48392
48393
48394
48395
48396
48397
48398 public function findNamespace($namespace)
48399 {
48400 $allNamespaces = $this->getNamespaces();
48401 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
48402 $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
48403
48404 if (empty($namespaces)) {
48405 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
48406
48407 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
48408 if (1 == count($alternatives)) {
48409 $message .= "\n\nDid you mean this?\n    ";
48410 } else {
48411 $message .= "\n\nDid you mean one of these?\n    ";
48412 }
48413
48414 $message .= implode("\n    ", $alternatives);
48415 }
48416
48417 throw new CommandNotFoundException($message, $alternatives);
48418 }
48419
48420 $exact = in_array($namespace, $namespaces, true);
48421 if (count($namespaces) > 1 && !$exact) {
48422 throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
48423 }
48424
48425 return $exact ? $namespace : reset($namespaces);
48426 }
48427
48428
48429
48430
48431
48432
48433
48434
48435
48436
48437
48438
48439
48440 public function find($name)
48441 {
48442 $this->init();
48443
48444 $allCommands = array_keys($this->commands);
48445 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
48446 $commands = preg_grep('{^'.$expr.'}', $allCommands);
48447
48448 if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
48449 if (false !== $pos = strrpos($name, ':')) {
48450
48451  $this->findNamespace(substr($name, 0, $pos));
48452 }
48453
48454 $message = sprintf('Command "%s" is not defined.', $name);
48455
48456 if ($alternatives = $this->findAlternatives($name, $allCommands)) {
48457 if (1 == count($alternatives)) {
48458 $message .= "\n\nDid you mean this?\n    ";
48459 } else {
48460 $message .= "\n\nDid you mean one of these?\n    ";
48461 }
48462 $message .= implode("\n    ", $alternatives);
48463 }
48464
48465 throw new CommandNotFoundException($message, $alternatives);
48466 }
48467
48468
48469  if (count($commands) > 1) {
48470 $commandList = $this->commands;
48471 $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
48472 $commandName = $commandList[$nameOrAlias]->getName();
48473
48474 return $commandName === $nameOrAlias || !in_array($commandName, $commands);
48475 });
48476 }
48477
48478 $exact = in_array($name, $commands, true);
48479 if (count($commands) > 1 && !$exact) {
48480 $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
48481
48482 throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
48483 }
48484
48485 return $this->get($exact ? $name : reset($commands));
48486 }
48487
48488
48489
48490
48491
48492
48493
48494
48495
48496
48497 public function all($namespace = null)
48498 {
48499 $this->init();
48500
48501 if (null === $namespace) {
48502 return $this->commands;
48503 }
48504
48505 $commands = array();
48506 foreach ($this->commands as $name => $command) {
48507 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
48508 $commands[$name] = $command;
48509 }
48510 }
48511
48512 return $commands;
48513 }
48514
48515
48516
48517
48518
48519
48520
48521
48522 public static function getAbbreviations($names)
48523 {
48524 $abbrevs = array();
48525 foreach ($names as $name) {
48526 for ($len = strlen($name); $len > 0; --$len) {
48527 $abbrev = substr($name, 0, $len);
48528 $abbrevs[$abbrev][] = $name;
48529 }
48530 }
48531
48532 return $abbrevs;
48533 }
48534
48535
48536
48537
48538
48539
48540
48541
48542
48543
48544
48545 public function asText($namespace = null, $raw = false)
48546 {
48547 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
48548
48549 $descriptor = new TextDescriptor();
48550 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
48551 $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
48552
48553 return $output->fetch();
48554 }
48555
48556
48557
48558
48559
48560
48561
48562
48563
48564
48565
48566 public function asXml($namespace = null, $asDom = false)
48567 {
48568 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
48569
48570 $descriptor = new XmlDescriptor();
48571
48572 if ($asDom) {
48573 return $descriptor->getApplicationDocument($this, $namespace);
48574 }
48575
48576 $output = new BufferedOutput();
48577 $descriptor->describe($output, $this, array('namespace' => $namespace));
48578
48579 return $output->fetch();
48580 }
48581
48582
48583
48584
48585 public function renderException($e, $output)
48586 {
48587 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
48588
48589 do {
48590 $title = sprintf('  [%s]  ', get_class($e));
48591
48592 $len = Helper::strlen($title);
48593
48594 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
48595
48596  if (defined('HHVM_VERSION') && $width > 1 << 31) {
48597 $width = 1 << 31;
48598 }
48599 $lines = array();
48600 foreach (preg_split('/\r?\n/', trim($e->getMessage())) as $line) {
48601 foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
48602
48603  $lineLength = Helper::strlen($line) + 4;
48604 $lines[] = array($line, $lineLength);
48605
48606 $len = max($lineLength, $len);
48607 }
48608 }
48609
48610 $messages = array();
48611 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
48612 $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
48613 foreach ($lines as $line) {
48614 $messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
48615 }
48616 $messages[] = $emptyLine;
48617 $messages[] = '';
48618
48619 $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
48620
48621 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
48622 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
48623
48624
48625  $trace = $e->getTrace();
48626 array_unshift($trace, array(
48627 'function' => '',
48628 'file' => null !== $e->getFile() ? $e->getFile() : 'n/a',
48629 'line' => null !== $e->getLine() ? $e->getLine() : 'n/a',
48630 'args' => array(),
48631 ));
48632
48633 for ($i = 0, $count = count($trace); $i < $count; ++$i) {
48634 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
48635 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
48636 $function = $trace[$i]['function'];
48637 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
48638 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
48639
48640 $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
48641 }
48642
48643 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
48644 }
48645 } while ($e = $e->getPrevious());
48646
48647 if (null !== $this->runningCommand) {
48648 $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
48649 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
48650 }
48651 }
48652
48653
48654
48655
48656
48657
48658 protected function getTerminalWidth()
48659 {
48660 $dimensions = $this->getTerminalDimensions();
48661
48662 return $dimensions[0];
48663 }
48664
48665
48666
48667
48668
48669
48670 protected function getTerminalHeight()
48671 {
48672 $dimensions = $this->getTerminalDimensions();
48673
48674 return $dimensions[1];
48675 }
48676
48677
48678
48679
48680
48681
48682 public function getTerminalDimensions()
48683 {
48684 if ($this->terminalDimensions) {
48685 return $this->terminalDimensions;
48686 }
48687
48688 if ('\\' === DIRECTORY_SEPARATOR) {
48689
48690  if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
48691 return array((int) $matches[1], (int) $matches[2]);
48692 }
48693
48694  if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
48695 return array((int) $matches[1], (int) $matches[2]);
48696 }
48697 }
48698
48699 if ($sttyString = $this->getSttyColumns()) {
48700
48701  if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
48702 return array((int) $matches[2], (int) $matches[1]);
48703 }
48704
48705  if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
48706 return array((int) $matches[2], (int) $matches[1]);
48707 }
48708 }
48709
48710 return array(null, null);
48711 }
48712
48713
48714
48715
48716
48717
48718
48719
48720
48721
48722
48723 public function setTerminalDimensions($width, $height)
48724 {
48725 $this->terminalDimensions = array($width, $height);
48726
48727 return $this;
48728 }
48729
48730
48731
48732
48733 protected function configureIO(InputInterface $input, OutputInterface $output)
48734 {
48735 if (true === $input->hasParameterOption(array('--ansi'))) {
48736 $output->setDecorated(true);
48737 } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
48738 $output->setDecorated(false);
48739 }
48740
48741 if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
48742 $input->setInteractive(false);
48743 } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
48744 $inputStream = $this->getHelperSet()->get('question')->getInputStream();
48745 if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
48746 $input->setInteractive(false);
48747 }
48748 }
48749
48750 if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
48751 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
48752 $input->setInteractive(false);
48753 } else {
48754 if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || 3 === $input->getParameterOption('--verbose')) {
48755 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
48756 } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || 2 === $input->getParameterOption('--verbose')) {
48757 $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
48758 } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
48759 $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
48760 }
48761 }
48762 }
48763
48764
48765
48766
48767
48768
48769
48770
48771
48772 protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
48773 {
48774 foreach ($command->getHelperSet() as $helper) {
48775 if ($helper instanceof InputAwareInterface) {
48776 $helper->setInput($input);
48777 }
48778 }
48779
48780 if (null === $this->dispatcher) {
48781 return $command->run($input, $output);
48782 }
48783
48784
48785  try {
48786 $command->mergeApplicationDefinition();
48787 $input->bind($command->getDefinition());
48788 } catch (ExceptionInterface $e) {
48789
48790  }
48791
48792 $event = new ConsoleCommandEvent($command, $input, $output);
48793 $e = null;
48794
48795 try {
48796 $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
48797
48798 if ($event->commandShouldRun()) {
48799 $exitCode = $command->run($input, $output);
48800 } else {
48801 $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
48802 }
48803 } catch (\Exception $e) {
48804 } catch (\Throwable $e) {
48805 }
48806 if (null !== $e) {
48807 $x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
48808 $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
48809 $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
48810
48811 if ($x !== $event->getException()) {
48812 $e = $event->getException();
48813 }
48814 $exitCode = $e->getCode();
48815 }
48816
48817 $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
48818 $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
48819
48820 if (null !== $e) {
48821 throw $e;
48822 }
48823
48824 return $event->getExitCode();
48825 }
48826
48827
48828
48829
48830
48831
48832 protected function getCommandName(InputInterface $input)
48833 {
48834 return $input->getFirstArgument();
48835 }
48836
48837
48838
48839
48840
48841
48842 protected function getDefaultInputDefinition()
48843 {
48844 return new InputDefinition(array(
48845 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
48846
48847 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
48848 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
48849 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'),
48850 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
48851 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
48852 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
48853 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
48854 ));
48855 }
48856
48857
48858
48859
48860
48861
48862 protected function getDefaultCommands()
48863 {
48864 return array(new HelpCommand(), new ListCommand());
48865 }
48866
48867
48868
48869
48870
48871
48872 protected function getDefaultHelperSet()
48873 {
48874 return new HelperSet(array(
48875 new FormatterHelper(),
48876 new DialogHelper(false),
48877 new ProgressHelper(false),
48878 new TableHelper(false),
48879 new DebugFormatterHelper(),
48880 new ProcessHelper(),
48881 new QuestionHelper(),
48882 ));
48883 }
48884
48885
48886
48887
48888
48889
48890 private function getSttyColumns()
48891 {
48892 if (!function_exists('proc_open')) {
48893 return;
48894 }
48895
48896 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
48897 $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
48898 if (is_resource($process)) {
48899 $info = stream_get_contents($pipes[1]);
48900 fclose($pipes[1]);
48901 fclose($pipes[2]);
48902 proc_close($process);
48903
48904 return $info;
48905 }
48906 }
48907
48908
48909
48910
48911
48912
48913 private function getConsoleMode()
48914 {
48915 if (!function_exists('proc_open')) {
48916 return;
48917 }
48918
48919 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
48920 $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
48921 if (is_resource($process)) {
48922 $info = stream_get_contents($pipes[1]);
48923 fclose($pipes[1]);
48924 fclose($pipes[2]);
48925 proc_close($process);
48926
48927 if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
48928 return $matches[2].'x'.$matches[1];
48929 }
48930 }
48931 }
48932
48933
48934
48935
48936
48937
48938
48939
48940 private function getAbbreviationSuggestions($abbrevs)
48941 {
48942 return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
48943 }
48944
48945
48946
48947
48948
48949
48950
48951
48952
48953
48954
48955 public function extractNamespace($name, $limit = null)
48956 {
48957 $parts = explode(':', $name);
48958 array_pop($parts);
48959
48960 return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
48961 }
48962
48963
48964
48965
48966
48967
48968
48969
48970
48971
48972 private function findAlternatives($name, $collection)
48973 {
48974 $threshold = 1e3;
48975 $alternatives = array();
48976
48977 $collectionParts = array();
48978 foreach ($collection as $item) {
48979 $collectionParts[$item] = explode(':', $item);
48980 }
48981
48982 foreach (explode(':', $name) as $i => $subname) {
48983 foreach ($collectionParts as $collectionName => $parts) {
48984 $exists = isset($alternatives[$collectionName]);
48985 if (!isset($parts[$i]) && $exists) {
48986 $alternatives[$collectionName] += $threshold;
48987 continue;
48988 } elseif (!isset($parts[$i])) {
48989 continue;
48990 }
48991
48992 $lev = levenshtein($subname, $parts[$i]);
48993 if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
48994 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
48995 } elseif ($exists) {
48996 $alternatives[$collectionName] += $threshold;
48997 }
48998 }
48999 }
49000
49001 foreach ($collection as $item) {
49002 $lev = levenshtein($name, $item);
49003 if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
49004 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
49005 }
49006 }
49007
49008 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
49009 asort($alternatives);
49010
49011 return array_keys($alternatives);
49012 }
49013
49014
49015
49016
49017
49018
49019 public function setDefaultCommand($commandName)
49020 {
49021 $this->defaultCommand = $commandName;
49022 }
49023
49024 private function splitStringByWidth($string, $width)
49025 {
49026
49027  
49028  
49029  if (false === $encoding = mb_detect_encoding($string, null, true)) {
49030 return str_split($string, $width);
49031 }
49032
49033 $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
49034 $lines = array();
49035 $line = '';
49036 foreach (preg_split('//u', $utf8String) as $char) {
49037
49038  if (mb_strwidth($line.$char, 'utf8') <= $width) {
49039 $line .= $char;
49040 continue;
49041 }
49042
49043  $lines[] = str_pad($line, $width);
49044 $line = $char;
49045 }
49046
49047 $lines[] = count($lines) ? str_pad($line, $width) : $line;
49048
49049 mb_convert_variables($encoding, 'utf8', $lines);
49050
49051 return $lines;
49052 }
49053
49054
49055
49056
49057
49058
49059
49060
49061 private function extractAllNamespaces($name)
49062 {
49063
49064  $parts = explode(':', $name, -1);
49065 $namespaces = array();
49066
49067 foreach ($parts as $part) {
49068 if (count($namespaces)) {
49069 $namespaces[] = end($namespaces).':'.$part;
49070 } else {
49071 $namespaces[] = $part;
49072 }
49073 }
49074
49075 return $namespaces;
49076 }
49077
49078 private function init()
49079 {
49080 if ($this->initialized) {
49081 return;
49082 }
49083 $this->initialized = true;
49084
49085 foreach ($this->getDefaultCommands() as $command) {
49086 $this->add($command);
49087 }
49088 }
49089 }
49090 <?php
49091
49092
49093
49094
49095
49096
49097
49098
49099
49100
49101 namespace Symfony\Component\Console\Command;
49102
49103 use Symfony\Component\Console\Descriptor\TextDescriptor;
49104 use Symfony\Component\Console\Descriptor\XmlDescriptor;
49105 use Symfony\Component\Console\Exception\ExceptionInterface;
49106 use Symfony\Component\Console\Input\InputDefinition;
49107 use Symfony\Component\Console\Input\InputOption;
49108 use Symfony\Component\Console\Input\InputArgument;
49109 use Symfony\Component\Console\Input\InputInterface;
49110 use Symfony\Component\Console\Output\BufferedOutput;
49111 use Symfony\Component\Console\Output\OutputInterface;
49112 use Symfony\Component\Console\Application;
49113 use Symfony\Component\Console\Helper\HelperSet;
49114 use Symfony\Component\Console\Exception\InvalidArgumentException;
49115 use Symfony\Component\Console\Exception\LogicException;
49116
49117
49118
49119
49120
49121
49122 class Command
49123 {
49124 private $application;
49125 private $name;
49126 private $processTitle;
49127 private $aliases = array();
49128 private $definition;
49129 private $help;
49130 private $description;
49131 private $ignoreValidationErrors = false;
49132 private $applicationDefinitionMerged = false;
49133 private $applicationDefinitionMergedWithArgs = false;
49134 private $code;
49135 private $synopsis = array();
49136 private $usages = array();
49137 private $helperSet;
49138
49139
49140
49141
49142
49143
49144 public function __construct($name = null)
49145 {
49146 $this->definition = new InputDefinition();
49147
49148 if (null !== $name) {
49149 $this->setName($name);
49150 }
49151
49152 $this->configure();
49153
49154 if (!$this->name) {
49155 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
49156 }
49157 }
49158
49159
49160
49161
49162
49163
49164 public function ignoreValidationErrors()
49165 {
49166 $this->ignoreValidationErrors = true;
49167 }
49168
49169 public function setApplication(Application $application = null)
49170 {
49171 $this->application = $application;
49172 if ($application) {
49173 $this->setHelperSet($application->getHelperSet());
49174 } else {
49175 $this->helperSet = null;
49176 }
49177 }
49178
49179 public function setHelperSet(HelperSet $helperSet)
49180 {
49181 $this->helperSet = $helperSet;
49182 }
49183
49184
49185
49186
49187
49188
49189 public function getHelperSet()
49190 {
49191 return $this->helperSet;
49192 }
49193
49194
49195
49196
49197
49198
49199 public function getApplication()
49200 {
49201 return $this->application;
49202 }
49203
49204
49205
49206
49207
49208
49209
49210
49211
49212 public function isEnabled()
49213 {
49214 return true;
49215 }
49216
49217
49218
49219
49220 protected function configure()
49221 {
49222 }
49223
49224
49225
49226
49227
49228
49229
49230
49231
49232
49233
49234
49235
49236
49237
49238 protected function execute(InputInterface $input, OutputInterface $output)
49239 {
49240 throw new LogicException('You must override the execute() method in the concrete command class.');
49241 }
49242
49243
49244
49245
49246
49247
49248
49249
49250 protected function interact(InputInterface $input, OutputInterface $output)
49251 {
49252 }
49253
49254
49255
49256
49257
49258
49259
49260 protected function initialize(InputInterface $input, OutputInterface $output)
49261 {
49262 }
49263
49264
49265
49266
49267
49268
49269
49270
49271
49272
49273
49274
49275
49276
49277
49278 public function run(InputInterface $input, OutputInterface $output)
49279 {
49280
49281  $this->getSynopsis(true);
49282 $this->getSynopsis(false);
49283
49284
49285  $this->mergeApplicationDefinition();
49286
49287
49288  try {
49289 $input->bind($this->definition);
49290 } catch (ExceptionInterface $e) {
49291 if (!$this->ignoreValidationErrors) {
49292 throw $e;
49293 }
49294 }
49295
49296 $this->initialize($input, $output);
49297
49298 if (null !== $this->processTitle) {
49299 if (function_exists('cli_set_process_title')) {
49300 if (false === @cli_set_process_title($this->processTitle)) {
49301 if ('Darwin' === PHP_OS) {
49302 $output->writeln('<comment>Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.</comment>');
49303 } else {
49304 $error = error_get_last();
49305 trigger_error($error['message'], E_USER_WARNING);
49306 }
49307 }
49308 } elseif (function_exists('setproctitle')) {
49309 setproctitle($this->processTitle);
49310 } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
49311 $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
49312 }
49313 }
49314
49315 if ($input->isInteractive()) {
49316 $this->interact($input, $output);
49317 }
49318
49319
49320  
49321  
49322  if ($input->hasArgument('command') && null === $input->getArgument('command')) {
49323 $input->setArgument('command', $this->getName());
49324 }
49325
49326 $input->validate();
49327
49328 if ($this->code) {
49329 $statusCode = call_user_func($this->code, $input, $output);
49330 } else {
49331 $statusCode = $this->execute($input, $output);
49332 }
49333
49334 return is_numeric($statusCode) ? (int) $statusCode : 0;
49335 }
49336
49337
49338
49339
49340
49341
49342
49343
49344
49345
49346
49347
49348
49349
49350
49351 public function setCode($code)
49352 {
49353 if (!is_callable($code)) {
49354 throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
49355 }
49356
49357 if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
49358 $r = new \ReflectionFunction($code);
49359 if (null === $r->getClosureThis()) {
49360 if (PHP_VERSION_ID < 70000) {
49361
49362  
49363  
49364  
49365  $code = @\Closure::bind($code, $this);
49366 } else {
49367 $code = \Closure::bind($code, $this);
49368 }
49369 }
49370 }
49371
49372 $this->code = $code;
49373
49374 return $this;
49375 }
49376
49377
49378
49379
49380
49381
49382
49383
49384 public function mergeApplicationDefinition($mergeArgs = true)
49385 {
49386 if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
49387 return;
49388 }
49389
49390 $this->definition->addOptions($this->application->getDefinition()->getOptions());
49391
49392 if ($mergeArgs) {
49393 $currentArguments = $this->definition->getArguments();
49394 $this->definition->setArguments($this->application->getDefinition()->getArguments());
49395 $this->definition->addArguments($currentArguments);
49396 }
49397
49398 $this->applicationDefinitionMerged = true;
49399 if ($mergeArgs) {
49400 $this->applicationDefinitionMergedWithArgs = true;
49401 }
49402 }
49403
49404
49405
49406
49407
49408
49409
49410
49411 public function setDefinition($definition)
49412 {
49413 if ($definition instanceof InputDefinition) {
49414 $this->definition = $definition;
49415 } else {
49416 $this->definition->setDefinition($definition);
49417 }
49418
49419 $this->applicationDefinitionMerged = false;
49420
49421 return $this;
49422 }
49423
49424
49425
49426
49427
49428
49429 public function getDefinition()
49430 {
49431 return $this->definition;
49432 }
49433
49434
49435
49436
49437
49438
49439
49440
49441
49442
49443
49444 public function getNativeDefinition()
49445 {
49446 return $this->getDefinition();
49447 }
49448
49449
49450
49451
49452
49453
49454
49455
49456
49457
49458
49459 public function addArgument($name, $mode = null, $description = '', $default = null)
49460 {
49461 $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
49462
49463 return $this;
49464 }
49465
49466
49467
49468
49469
49470
49471
49472
49473
49474
49475
49476
49477 public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
49478 {
49479 $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
49480
49481 return $this;
49482 }
49483
49484
49485
49486
49487
49488
49489
49490
49491
49492
49493
49494
49495
49496
49497
49498 public function setName($name)
49499 {
49500 $this->validateName($name);
49501
49502 $this->name = $name;
49503
49504 return $this;
49505 }
49506
49507
49508
49509
49510
49511
49512
49513
49514
49515
49516
49517
49518
49519 public function setProcessTitle($title)
49520 {
49521 $this->processTitle = $title;
49522
49523 return $this;
49524 }
49525
49526
49527
49528
49529
49530
49531 public function getName()
49532 {
49533 return $this->name;
49534 }
49535
49536
49537
49538
49539
49540
49541
49542
49543 public function setDescription($description)
49544 {
49545 $this->description = $description;
49546
49547 return $this;
49548 }
49549
49550
49551
49552
49553
49554
49555 public function getDescription()
49556 {
49557 return $this->description;
49558 }
49559
49560
49561
49562
49563
49564
49565
49566
49567 public function setHelp($help)
49568 {
49569 $this->help = $help;
49570
49571 return $this;
49572 }
49573
49574
49575
49576
49577
49578
49579 public function getHelp()
49580 {
49581 return $this->help;
49582 }
49583
49584
49585
49586
49587
49588
49589
49590 public function getProcessedHelp()
49591 {
49592 $name = $this->name;
49593
49594 $placeholders = array(
49595 '%command.name%',
49596 '%command.full_name%',
49597 );
49598 $replacements = array(
49599 $name,
49600 $_SERVER['PHP_SELF'].' '.$name,
49601 );
49602
49603 return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
49604 }
49605
49606
49607
49608
49609
49610
49611
49612
49613
49614
49615 public function setAliases($aliases)
49616 {
49617 if (!is_array($aliases) && !$aliases instanceof \Traversable) {
49618 throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
49619 }
49620
49621 foreach ($aliases as $alias) {
49622 $this->validateName($alias);
49623 }
49624
49625 $this->aliases = $aliases;
49626
49627 return $this;
49628 }
49629
49630
49631
49632
49633
49634
49635 public function getAliases()
49636 {
49637 return $this->aliases;
49638 }
49639
49640
49641
49642
49643
49644
49645
49646
49647 public function getSynopsis($short = false)
49648 {
49649 $key = $short ? 'short' : 'long';
49650
49651 if (!isset($this->synopsis[$key])) {
49652 $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
49653 }
49654
49655 return $this->synopsis[$key];
49656 }
49657
49658
49659
49660
49661
49662
49663
49664
49665 public function addUsage($usage)
49666 {
49667 if (0 !== strpos($usage, $this->name)) {
49668 $usage = sprintf('%s %s', $this->name, $usage);
49669 }
49670
49671 $this->usages[] = $usage;
49672
49673 return $this;
49674 }
49675
49676
49677
49678
49679
49680
49681 public function getUsages()
49682 {
49683 return $this->usages;
49684 }
49685
49686
49687
49688
49689
49690
49691
49692
49693
49694
49695
49696 public function getHelper($name)
49697 {
49698 if (null === $this->helperSet) {
49699 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));
49700 }
49701
49702 return $this->helperSet->get($name);
49703 }
49704
49705
49706
49707
49708
49709
49710
49711
49712 public function asText()
49713 {
49714 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
49715
49716 $descriptor = new TextDescriptor();
49717 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
49718 $descriptor->describe($output, $this, array('raw_output' => true));
49719
49720 return $output->fetch();
49721 }
49722
49723
49724
49725
49726
49727
49728
49729
49730
49731
49732 public function asXml($asDom = false)
49733 {
49734 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
49735
49736 $descriptor = new XmlDescriptor();
49737
49738 if ($asDom) {
49739 return $descriptor->getCommandDocument($this);
49740 }
49741
49742 $output = new BufferedOutput();
49743 $descriptor->describe($output, $this);
49744
49745 return $output->fetch();
49746 }
49747
49748
49749
49750
49751
49752
49753
49754
49755
49756
49757 private function validateName($name)
49758 {
49759 if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
49760 throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
49761 }
49762 }
49763 }
49764 <?php
49765
49766
49767
49768
49769
49770
49771
49772
49773
49774
49775 namespace Symfony\Component\Console\Command;
49776
49777 use Symfony\Component\Console\Helper\DescriptorHelper;
49778 use Symfony\Component\Console\Input\InputArgument;
49779 use Symfony\Component\Console\Input\InputOption;
49780 use Symfony\Component\Console\Input\InputInterface;
49781 use Symfony\Component\Console\Output\OutputInterface;
49782
49783
49784
49785
49786
49787
49788 class HelpCommand extends Command
49789 {
49790 private $command;
49791
49792
49793
49794
49795 protected function configure()
49796 {
49797 $this->ignoreValidationErrors();
49798
49799 $this
49800 ->setName('help')
49801 ->setDefinition(array(
49802 new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
49803 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
49804 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
49805 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
49806 ))
49807 ->setDescription('Displays help for a command')
49808 ->setHelp(<<<'EOF'
49809 The <info>%command.name%</info> command displays help for a given command:
49810
49811   <info>php %command.full_name% list</info>
49812
49813 You can also output the help in other formats by using the <comment>--format</comment> option:
49814
49815   <info>php %command.full_name% --format=xml list</info>
49816
49817 To display the list of available commands, please use the <info>list</info> command.
49818 EOF
49819 )
49820 ;
49821 }
49822
49823 public function setCommand(Command $command)
49824 {
49825 $this->command = $command;
49826 }
49827
49828
49829
49830
49831 protected function execute(InputInterface $input, OutputInterface $output)
49832 {
49833 if (null === $this->command) {
49834 $this->command = $this->getApplication()->find($input->getArgument('command_name'));
49835 }
49836
49837 if ($input->getOption('xml')) {
49838 @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);
49839
49840 $input->setOption('format', 'xml');
49841 }
49842
49843 $helper = new DescriptorHelper();
49844 $helper->describe($output, $this->command, array(
49845 'format' => $input->getOption('format'),
49846 'raw_text' => $input->getOption('raw'),
49847 ));
49848
49849 $this->command = null;
49850 }
49851 }
49852 <?php
49853
49854
49855
49856
49857
49858
49859
49860
49861
49862
49863 namespace Symfony\Component\Console\Command;
49864
49865 use Symfony\Component\Console\Helper\DescriptorHelper;
49866 use Symfony\Component\Console\Input\InputArgument;
49867 use Symfony\Component\Console\Input\InputOption;
49868 use Symfony\Component\Console\Input\InputInterface;
49869 use Symfony\Component\Console\Output\OutputInterface;
49870 use Symfony\Component\Console\Input\InputDefinition;
49871
49872
49873
49874
49875
49876
49877 class ListCommand extends Command
49878 {
49879
49880
49881
49882 protected function configure()
49883 {
49884 $this
49885 ->setName('list')
49886 ->setDefinition($this->createDefinition())
49887 ->setDescription('Lists commands')
49888 ->setHelp(<<<'EOF'
49889 The <info>%command.name%</info> command lists all commands:
49890
49891   <info>php %command.full_name%</info>
49892
49893 You can also display the commands for a specific namespace:
49894
49895   <info>php %command.full_name% test</info>
49896
49897 You can also output the information in other formats by using the <comment>--format</comment> option:
49898
49899   <info>php %command.full_name% --format=xml</info>
49900
49901 It's also possible to get raw list of commands (useful for embedding command runner):
49902
49903   <info>php %command.full_name% --raw</info>
49904 EOF
49905 )
49906 ;
49907 }
49908
49909
49910
49911
49912 public function getNativeDefinition()
49913 {
49914 return $this->createDefinition();
49915 }
49916
49917
49918
49919
49920 protected function execute(InputInterface $input, OutputInterface $output)
49921 {
49922 if ($input->getOption('xml')) {
49923 @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);
49924
49925 $input->setOption('format', 'xml');
49926 }
49927
49928 $helper = new DescriptorHelper();
49929 $helper->describe($output, $this->getApplication(), array(
49930 'format' => $input->getOption('format'),
49931 'raw_text' => $input->getOption('raw'),
49932 'namespace' => $input->getArgument('namespace'),
49933 ));
49934 }
49935
49936
49937
49938
49939 private function createDefinition()
49940 {
49941 return new InputDefinition(array(
49942 new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
49943 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
49944 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
49945 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
49946 ));
49947 }
49948 }
49949 <?php
49950
49951
49952
49953
49954
49955
49956
49957
49958
49959
49960 namespace Symfony\Component\Console;
49961
49962
49963
49964
49965
49966
49967 final class ConsoleEvents
49968 {
49969
49970
49971
49972
49973
49974
49975
49976
49977
49978
49979 const COMMAND = 'console.command';
49980
49981
49982
49983
49984
49985
49986
49987
49988
49989
49990 const TERMINATE = 'console.terminate';
49991
49992
49993
49994
49995
49996
49997
49998
49999
50000
50001
50002 const EXCEPTION = 'console.exception';
50003 }
50004 <?php
50005
50006
50007
50008
50009
50010
50011
50012
50013
50014
50015 namespace Symfony\Component\Console\Descriptor;
50016
50017 use Symfony\Component\Console\Application;
50018 use Symfony\Component\Console\Command\Command;
50019 use Symfony\Component\Console\Exception\CommandNotFoundException;
50020
50021
50022
50023
50024
50025
50026 class ApplicationDescription
50027 {
50028 const GLOBAL_NAMESPACE = '_global';
50029
50030 private $application;
50031 private $namespace;
50032
50033
50034
50035
50036 private $namespaces;
50037
50038
50039
50040
50041 private $commands;
50042
50043
50044
50045
50046 private $aliases;
50047
50048 public function __construct(Application $application, $namespace = null)
50049 {
50050 $this->application = $application;
50051 $this->namespace = $namespace;
50052 }
50053
50054
50055
50056
50057 public function getNamespaces()
50058 {
50059 if (null === $this->namespaces) {
50060 $this->inspectApplication();
50061 }
50062
50063 return $this->namespaces;
50064 }
50065
50066
50067
50068
50069 public function getCommands()
50070 {
50071 if (null === $this->commands) {
50072 $this->inspectApplication();
50073 }
50074
50075 return $this->commands;
50076 }
50077
50078
50079
50080
50081
50082
50083
50084
50085 public function getCommand($name)
50086 {
50087 if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
50088 throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
50089 }
50090
50091 return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
50092 }
50093
50094 private function inspectApplication()
50095 {
50096 $this->commands = array();
50097 $this->namespaces = array();
50098
50099 $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
50100 foreach ($this->sortCommands($all) as $namespace => $commands) {
50101 $names = array();
50102
50103
50104 foreach ($commands as $name => $command) {
50105 if (!$command->getName()) {
50106 continue;
50107 }
50108
50109 if ($command->getName() === $name) {
50110 $this->commands[$name] = $command;
50111 } else {
50112 $this->aliases[$name] = $command;
50113 }
50114
50115 $names[] = $name;
50116 }
50117
50118 $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
50119 }
50120 }
50121
50122
50123
50124
50125 private function sortCommands(array $commands)
50126 {
50127 $namespacedCommands = array();
50128 $globalCommands = array();
50129 foreach ($commands as $name => $command) {
50130 $key = $this->application->extractNamespace($name, 1);
50131 if (!$key) {
50132 $globalCommands['_global'][$name] = $command;
50133 } else {
50134 $namespacedCommands[$key][$name] = $command;
50135 }
50136 }
50137 ksort($namespacedCommands);
50138 $namespacedCommands = array_merge($globalCommands, $namespacedCommands);
50139
50140 foreach ($namespacedCommands as &$commandsSet) {
50141 ksort($commandsSet);
50142 }
50143
50144  unset($commandsSet);
50145
50146 return $namespacedCommands;
50147 }
50148 }
50149 <?php
50150
50151
50152
50153
50154
50155
50156
50157
50158
50159
50160 namespace Symfony\Component\Console\Descriptor;
50161
50162 use Symfony\Component\Console\Application;
50163 use Symfony\Component\Console\Command\Command;
50164 use Symfony\Component\Console\Input\InputArgument;
50165 use Symfony\Component\Console\Input\InputDefinition;
50166 use Symfony\Component\Console\Input\InputOption;
50167 use Symfony\Component\Console\Output\OutputInterface;
50168 use Symfony\Component\Console\Exception\InvalidArgumentException;
50169
50170
50171
50172
50173
50174
50175 abstract class Descriptor implements DescriptorInterface
50176 {
50177
50178
50179
50180 private $output;
50181
50182
50183
50184
50185 public function describe(OutputInterface $output, $object, array $options = array())
50186 {
50187 $this->output = $output;
50188
50189 switch (true) {
50190 case $object instanceof InputArgument:
50191 $this->describeInputArgument($object, $options);
50192 break;
50193 case $object instanceof InputOption:
50194 $this->describeInputOption($object, $options);
50195 break;
50196 case $object instanceof InputDefinition:
50197 $this->describeInputDefinition($object, $options);
50198 break;
50199 case $object instanceof Command:
50200 $this->describeCommand($object, $options);
50201 break;
50202 case $object instanceof Application:
50203 $this->describeApplication($object, $options);
50204 break;
50205 default:
50206 throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
50207 }
50208 }
50209
50210
50211
50212
50213
50214
50215
50216 protected function write($content, $decorated = false)
50217 {
50218 $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
50219 }
50220
50221
50222
50223
50224
50225
50226 abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
50227
50228
50229
50230
50231
50232
50233 abstract protected function describeInputOption(InputOption $option, array $options = array());
50234
50235
50236
50237
50238
50239
50240 abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
50241
50242
50243
50244
50245
50246
50247 abstract protected function describeCommand(Command $command, array $options = array());
50248
50249
50250
50251
50252
50253
50254 abstract protected function describeApplication(Application $application, array $options = array());
50255 }
50256 <?php
50257
50258
50259
50260
50261
50262
50263
50264
50265
50266
50267 namespace Symfony\Component\Console\Descriptor;
50268
50269 use Symfony\Component\Console\Output\OutputInterface;
50270
50271
50272
50273
50274
50275
50276 interface DescriptorInterface
50277 {
50278
50279
50280
50281
50282
50283
50284
50285 public function describe(OutputInterface $output, $object, array $options = array());
50286 }
50287 <?php
50288
50289
50290
50291
50292
50293
50294
50295
50296
50297
50298 namespace Symfony\Component\Console\Descriptor;
50299
50300 use Symfony\Component\Console\Application;
50301 use Symfony\Component\Console\Command\Command;
50302 use Symfony\Component\Console\Input\InputArgument;
50303 use Symfony\Component\Console\Input\InputDefinition;
50304 use Symfony\Component\Console\Input\InputOption;
50305
50306
50307
50308
50309
50310
50311
50312
50313 class JsonDescriptor extends Descriptor
50314 {
50315
50316
50317
50318 protected function describeInputArgument(InputArgument $argument, array $options = array())
50319 {
50320 $this->writeData($this->getInputArgumentData($argument), $options);
50321 }
50322
50323
50324
50325
50326 protected function describeInputOption(InputOption $option, array $options = array())
50327 {
50328 $this->writeData($this->getInputOptionData($option), $options);
50329 }
50330
50331
50332
50333
50334 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
50335 {
50336 $this->writeData($this->getInputDefinitionData($definition), $options);
50337 }
50338
50339
50340
50341
50342 protected function describeCommand(Command $command, array $options = array())
50343 {
50344 $this->writeData($this->getCommandData($command), $options);
50345 }
50346
50347
50348
50349
50350 protected function describeApplication(Application $application, array $options = array())
50351 {
50352 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
50353 $description = new ApplicationDescription($application, $describedNamespace);
50354 $commands = array();
50355
50356 foreach ($description->getCommands() as $command) {
50357 $commands[] = $this->getCommandData($command);
50358 }
50359
50360 $data = $describedNamespace
50361 ? array('commands' => $commands, 'namespace' => $describedNamespace)
50362 : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
50363
50364 $this->writeData($data, $options);
50365 }
50366
50367
50368
50369
50370
50371
50372 private function writeData(array $data, array $options)
50373 {
50374 $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
50375 }
50376
50377
50378
50379
50380 private function getInputArgumentData(InputArgument $argument)
50381 {
50382 return array(
50383 'name' => $argument->getName(),
50384 'is_required' => $argument->isRequired(),
50385 'is_array' => $argument->isArray(),
50386 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
50387 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
50388 );
50389 }
50390
50391
50392
50393
50394 private function getInputOptionData(InputOption $option)
50395 {
50396 return array(
50397 'name' => '--'.$option->getName(),
50398 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
50399 'accept_value' => $option->acceptValue(),
50400 'is_value_required' => $option->isValueRequired(),
50401 'is_multiple' => $option->isArray(),
50402 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
50403 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
50404 );
50405 }
50406
50407
50408
50409
50410 private function getInputDefinitionData(InputDefinition $definition)
50411 {
50412 $inputArguments = array();
50413 foreach ($definition->getArguments() as $name => $argument) {
50414 $inputArguments[$name] = $this->getInputArgumentData($argument);
50415 }
50416
50417 $inputOptions = array();
50418 foreach ($definition->getOptions() as $name => $option) {
50419 $inputOptions[$name] = $this->getInputOptionData($option);
50420 }
50421
50422 return array('arguments' => $inputArguments, 'options' => $inputOptions);
50423 }
50424
50425
50426
50427
50428 private function getCommandData(Command $command)
50429 {
50430 $command->getSynopsis();
50431 $command->mergeApplicationDefinition(false);
50432
50433 return array(
50434 'name' => $command->getName(),
50435 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
50436 'description' => $command->getDescription(),
50437 'help' => $command->getProcessedHelp(),
50438 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
50439 );
50440 }
50441 }
50442 <?php
50443
50444
50445
50446
50447
50448
50449
50450
50451
50452
50453 namespace Symfony\Component\Console\Descriptor;
50454
50455 use Symfony\Component\Console\Application;
50456 use Symfony\Component\Console\Command\Command;
50457 use Symfony\Component\Console\Helper\Helper;
50458 use Symfony\Component\Console\Input\InputArgument;
50459 use Symfony\Component\Console\Input\InputDefinition;
50460 use Symfony\Component\Console\Input\InputOption;
50461
50462
50463
50464
50465
50466
50467
50468
50469 class MarkdownDescriptor extends Descriptor
50470 {
50471
50472
50473
50474 protected function describeInputArgument(InputArgument $argument, array $options = array())
50475 {
50476 $this->write(
50477 '**'.$argument->getName().':**'."\n\n"
50478 .'* Name: '.($argument->getName() ?: '<none>')."\n"
50479 .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
50480 .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
50481 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $argument->getDescription() ?: '<none>')."\n"
50482 .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
50483 );
50484 }
50485
50486
50487
50488
50489 protected function describeInputOption(InputOption $option, array $options = array())
50490 {
50491 $this->write(
50492 '**'.$option->getName().':**'."\n\n"
50493 .'* Name: `--'.$option->getName().'`'."\n"
50494 .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '<none>')."\n"
50495 .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
50496 .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
50497 .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
50498 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $option->getDescription() ?: '<none>')."\n"
50499 .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
50500 );
50501 }
50502
50503
50504
50505
50506 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
50507 {
50508 if ($showArguments = count($definition->getArguments()) > 0) {
50509 $this->write('### Arguments:');
50510 foreach ($definition->getArguments() as $argument) {
50511 $this->write("\n\n");
50512 $this->write($this->describeInputArgument($argument));
50513 }
50514 }
50515
50516 if (count($definition->getOptions()) > 0) {
50517 if ($showArguments) {
50518 $this->write("\n\n");
50519 }
50520
50521 $this->write('### Options:');
50522 foreach ($definition->getOptions() as $option) {
50523 $this->write("\n\n");
50524 $this->write($this->describeInputOption($option));
50525 }
50526 }
50527 }
50528
50529
50530
50531
50532 protected function describeCommand(Command $command, array $options = array())
50533 {
50534 $command->getSynopsis();
50535 $command->mergeApplicationDefinition(false);
50536
50537 $this->write(
50538 $command->getName()."\n"
50539 .str_repeat('-', Helper::strlen($command->getName()))."\n\n"
50540 .'* Description: '.($command->getDescription() ?: '<none>')."\n"
50541 .'* Usage:'."\n\n"
50542 .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
50543 return $carry.'  * `'.$usage.'`'."\n";
50544 })
50545 );
50546
50547 if ($help = $command->getProcessedHelp()) {
50548 $this->write("\n");
50549 $this->write($help);
50550 }
50551
50552 if ($command->getNativeDefinition()) {
50553 $this->write("\n\n");
50554 $this->describeInputDefinition($command->getNativeDefinition());
50555 }
50556 }
50557
50558
50559
50560
50561 protected function describeApplication(Application $application, array $options = array())
50562 {
50563 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
50564 $description = new ApplicationDescription($application, $describedNamespace);
50565
50566 $this->write($application->getName()."\n".str_repeat('=', Helper::strlen($application->getName())));
50567
50568 foreach ($description->getNamespaces() as $namespace) {
50569 if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
50570 $this->write("\n\n");
50571 $this->write('**'.$namespace['id'].':**');
50572 }
50573
50574 $this->write("\n\n");
50575 $this->write(implode("\n", array_map(function ($commandName) {
50576 return '* '.$commandName;
50577 }, $namespace['commands'])));
50578 }
50579
50580 foreach ($description->getCommands() as $command) {
50581 $this->write("\n\n");
50582 $this->write($this->describeCommand($command));
50583 }
50584 }
50585 }
50586 <?php
50587
50588
50589
50590
50591
50592
50593
50594
50595
50596
50597 namespace Symfony\Component\Console\Descriptor;
50598
50599 use Symfony\Component\Console\Application;
50600 use Symfony\Component\Console\Command\Command;
50601 use Symfony\Component\Console\Formatter\OutputFormatter;
50602 use Symfony\Component\Console\Helper\Helper;
50603 use Symfony\Component\Console\Input\InputArgument;
50604 use Symfony\Component\Console\Input\InputDefinition;
50605 use Symfony\Component\Console\Input\InputOption;
50606
50607
50608
50609
50610
50611
50612
50613
50614 class TextDescriptor extends Descriptor
50615 {
50616
50617
50618
50619 protected function describeInputArgument(InputArgument $argument, array $options = array())
50620 {
50621 if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
50622 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
50623 } else {
50624 $default = '';
50625 }
50626
50627 $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
50628 $spacingWidth = $totalWidth - strlen($argument->getName());
50629
50630 $this->writeText(sprintf('  <info>%s</info>  %s%s%s',
50631 $argument->getName(),
50632 str_repeat(' ', $spacingWidth),
50633
50634  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
50635 $default
50636 ), $options);
50637 }
50638
50639
50640
50641
50642 protected function describeInputOption(InputOption $option, array $options = array())
50643 {
50644 if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
50645 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
50646 } else {
50647 $default = '';
50648 }
50649
50650 $value = '';
50651 if ($option->acceptValue()) {
50652 $value = '='.strtoupper($option->getName());
50653
50654 if ($option->isValueOptional()) {
50655 $value = '['.$value.']';
50656 }
50657 }
50658
50659 $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
50660 $synopsis = sprintf('%s%s',
50661 $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
50662 sprintf('--%s%s', $option->getName(), $value)
50663 );
50664
50665 $spacingWidth = $totalWidth - Helper::strlen($synopsis);
50666
50667 $this->writeText(sprintf('  <info>%s</info>  %s%s%s%s',
50668 $synopsis,
50669 str_repeat(' ', $spacingWidth),
50670
50671  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
50672 $default,
50673 $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
50674 ), $options);
50675 }
50676
50677
50678
50679
50680 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
50681 {
50682 $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
50683 foreach ($definition->getArguments() as $argument) {
50684 $totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
50685 }
50686
50687 if ($definition->getArguments()) {
50688 $this->writeText('<comment>Arguments:</comment>', $options);
50689 $this->writeText("\n");
50690 foreach ($definition->getArguments() as $argument) {
50691 $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
50692 $this->writeText("\n");
50693 }
50694 }
50695
50696 if ($definition->getArguments() && $definition->getOptions()) {
50697 $this->writeText("\n");
50698 }
50699
50700 if ($definition->getOptions()) {
50701 $laterOptions = array();
50702
50703 $this->writeText('<comment>Options:</comment>', $options);
50704 foreach ($definition->getOptions() as $option) {
50705 if (strlen($option->getShortcut()) > 1) {
50706 $laterOptions[] = $option;
50707 continue;
50708 }
50709 $this->writeText("\n");
50710 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
50711 }
50712 foreach ($laterOptions as $option) {
50713 $this->writeText("\n");
50714 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
50715 }
50716 }
50717 }
50718
50719
50720
50721
50722 protected function describeCommand(Command $command, array $options = array())
50723 {
50724 $command->getSynopsis(true);
50725 $command->getSynopsis(false);
50726 $command->mergeApplicationDefinition(false);
50727
50728 $this->writeText('<comment>Usage:</comment>', $options);
50729 foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
50730 $this->writeText("\n");
50731 $this->writeText('  '.OutputFormatter::escape($usage), $options);
50732 }
50733 $this->writeText("\n");
50734
50735 $definition = $command->getNativeDefinition();
50736 if ($definition->getOptions() || $definition->getArguments()) {
50737 $this->writeText("\n");
50738 $this->describeInputDefinition($definition, $options);
50739 $this->writeText("\n");
50740 }
50741
50742 if ($help = $command->getProcessedHelp()) {
50743 $this->writeText("\n");
50744 $this->writeText('<comment>Help:</comment>', $options);
50745 $this->writeText("\n");
50746 $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
50747 $this->writeText("\n");
50748 }
50749 }
50750
50751
50752
50753
50754 protected function describeApplication(Application $application, array $options = array())
50755 {
50756 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
50757 $description = new ApplicationDescription($application, $describedNamespace);
50758
50759 if (isset($options['raw_text']) && $options['raw_text']) {
50760 $width = $this->getColumnWidth($description->getCommands());
50761
50762 foreach ($description->getCommands() as $command) {
50763 $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
50764 $this->writeText("\n");
50765 }
50766 } else {
50767 if ('' != $help = $application->getHelp()) {
50768 $this->writeText("$help\n\n", $options);
50769 }
50770
50771 $this->writeText("<comment>Usage:</comment>\n", $options);
50772 $this->writeText("  command [options] [arguments]\n\n", $options);
50773
50774 $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
50775
50776 $this->writeText("\n");
50777 $this->writeText("\n");
50778
50779 $width = $this->getColumnWidth($description->getCommands());
50780
50781 if ($describedNamespace) {
50782 $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
50783 } else {
50784 $this->writeText('<comment>Available commands:</comment>', $options);
50785 }
50786
50787
50788  foreach ($description->getNamespaces() as $namespace) {
50789 if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
50790 $this->writeText("\n");
50791 $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
50792 }
50793
50794 foreach ($namespace['commands'] as $name) {
50795 $this->writeText("\n");
50796 $spacingWidth = $width - Helper::strlen($name);
50797 $this->writeText(sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
50798 }
50799 }
50800
50801 $this->writeText("\n");
50802 }
50803 }
50804
50805
50806
50807
50808 private function writeText($content, array $options = array())
50809 {
50810 $this->write(
50811 isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
50812 isset($options['raw_output']) ? !$options['raw_output'] : true
50813 );
50814 }
50815
50816
50817
50818
50819
50820
50821
50822
50823 private function formatDefaultValue($default)
50824 {
50825 if (INF === $default) {
50826 return 'INF';
50827 }
50828
50829 if (is_string($default)) {
50830 $default = OutputFormatter::escape($default);
50831 } elseif (is_array($default)) {
50832 foreach ($default as $key => $value) {
50833 if (is_string($value)) {
50834 $default[$key] = OutputFormatter::escape($value);
50835 }
50836 }
50837 }
50838
50839 if (\PHP_VERSION_ID < 50400) {
50840 return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
50841 }
50842
50843 return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
50844 }
50845
50846
50847
50848
50849
50850
50851 private function getColumnWidth(array $commands)
50852 {
50853 $widths = array();
50854
50855 foreach ($commands as $command) {
50856 $widths[] = Helper::strlen($command->getName());
50857 foreach ($command->getAliases() as $alias) {
50858 $widths[] = Helper::strlen($alias);
50859 }
50860 }
50861
50862 return max($widths) + 2;
50863 }
50864
50865
50866
50867
50868
50869
50870 private function calculateTotalWidthForOptions(array $options)
50871 {
50872 $totalWidth = 0;
50873 foreach ($options as $option) {
50874
50875  $nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
50876
50877 if ($option->acceptValue()) {
50878 $valueLength = 1 + Helper::strlen($option->getName()); 
50879  $valueLength += $option->isValueOptional() ? 2 : 0; 
50880
50881 $nameLength += $valueLength;
50882 }
50883 $totalWidth = max($totalWidth, $nameLength);
50884 }
50885
50886 return $totalWidth;
50887 }
50888 }
50889 <?php
50890
50891
50892
50893
50894
50895
50896
50897
50898
50899
50900 namespace Symfony\Component\Console\Descriptor;
50901
50902 use Symfony\Component\Console\Application;
50903 use Symfony\Component\Console\Command\Command;
50904 use Symfony\Component\Console\Input\InputArgument;
50905 use Symfony\Component\Console\Input\InputDefinition;
50906 use Symfony\Component\Console\Input\InputOption;
50907
50908
50909
50910
50911
50912
50913
50914
50915 class XmlDescriptor extends Descriptor
50916 {
50917
50918
50919
50920 public function getInputDefinitionDocument(InputDefinition $definition)
50921 {
50922 $dom = new \DOMDocument('1.0', 'UTF-8');
50923 $dom->appendChild($definitionXML = $dom->createElement('definition'));
50924
50925 $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
50926 foreach ($definition->getArguments() as $argument) {
50927 $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
50928 }
50929
50930 $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
50931 foreach ($definition->getOptions() as $option) {
50932 $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
50933 }
50934
50935 return $dom;
50936 }
50937
50938
50939
50940
50941 public function getCommandDocument(Command $command)
50942 {
50943 $dom = new \DOMDocument('1.0', 'UTF-8');
50944 $dom->appendChild($commandXML = $dom->createElement('command'));
50945
50946 $command->getSynopsis();
50947 $command->mergeApplicationDefinition(false);
50948
50949 $commandXML->setAttribute('id', $command->getName());
50950 $commandXML->setAttribute('name', $command->getName());
50951
50952 $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
50953
50954 foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
50955 $usagesXML->appendChild($dom->createElement('usage', $usage));
50956 }
50957
50958 $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
50959 $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
50960
50961 $commandXML->appendChild($helpXML = $dom->createElement('help'));
50962 $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
50963
50964 $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
50965 $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
50966
50967 return $dom;
50968 }
50969
50970
50971
50972
50973
50974
50975
50976 public function getApplicationDocument(Application $application, $namespace = null)
50977 {
50978 $dom = new \DOMDocument('1.0', 'UTF-8');
50979 $dom->appendChild($rootXml = $dom->createElement('symfony'));
50980
50981 if ('UNKNOWN' !== $application->getName()) {
50982 $rootXml->setAttribute('name', $application->getName());
50983 if ('UNKNOWN' !== $application->getVersion()) {
50984 $rootXml->setAttribute('version', $application->getVersion());
50985 }
50986 }
50987
50988 $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
50989
50990 $description = new ApplicationDescription($application, $namespace);
50991
50992 if ($namespace) {
50993 $commandsXML->setAttribute('namespace', $namespace);
50994 }
50995
50996 foreach ($description->getCommands() as $command) {
50997 $this->appendDocument($commandsXML, $this->getCommandDocument($command));
50998 }
50999
51000 if (!$namespace) {
51001 $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
51002
51003 foreach ($description->getNamespaces() as $namespaceDescription) {
51004 $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
51005 $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
51006
51007 foreach ($namespaceDescription['commands'] as $name) {
51008 $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
51009 $commandXML->appendChild($dom->createTextNode($name));
51010 }
51011 }
51012 }
51013
51014 return $dom;
51015 }
51016
51017
51018
51019
51020 protected function describeInputArgument(InputArgument $argument, array $options = array())
51021 {
51022 $this->writeDocument($this->getInputArgumentDocument($argument));
51023 }
51024
51025
51026
51027
51028 protected function describeInputOption(InputOption $option, array $options = array())
51029 {
51030 $this->writeDocument($this->getInputOptionDocument($option));
51031 }
51032
51033
51034
51035
51036 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
51037 {
51038 $this->writeDocument($this->getInputDefinitionDocument($definition));
51039 }
51040
51041
51042
51043
51044 protected function describeCommand(Command $command, array $options = array())
51045 {
51046 $this->writeDocument($this->getCommandDocument($command));
51047 }
51048
51049
51050
51051
51052 protected function describeApplication(Application $application, array $options = array())
51053 {
51054 $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
51055 }
51056
51057
51058
51059
51060 private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
51061 {
51062 foreach ($importedParent->childNodes as $childNode) {
51063 $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
51064 }
51065 }
51066
51067
51068
51069
51070
51071
51072 private function writeDocument(\DOMDocument $dom)
51073 {
51074 $dom->formatOutput = true;
51075 $this->write($dom->saveXML());
51076 }
51077
51078
51079
51080
51081 private function getInputArgumentDocument(InputArgument $argument)
51082 {
51083 $dom = new \DOMDocument('1.0', 'UTF-8');
51084
51085 $dom->appendChild($objectXML = $dom->createElement('argument'));
51086 $objectXML->setAttribute('name', $argument->getName());
51087 $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
51088 $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
51089 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
51090 $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
51091
51092 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
51093 $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
51094 foreach ($defaults as $default) {
51095 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
51096 $defaultXML->appendChild($dom->createTextNode($default));
51097 }
51098
51099 return $dom;
51100 }
51101
51102
51103
51104
51105 private function getInputOptionDocument(InputOption $option)
51106 {
51107 $dom = new \DOMDocument('1.0', 'UTF-8');
51108
51109 $dom->appendChild($objectXML = $dom->createElement('option'));
51110 $objectXML->setAttribute('name', '--'.$option->getName());
51111 $pos = strpos($option->getShortcut(), '|');
51112 if (false !== $pos) {
51113 $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
51114 $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
51115 } else {
51116 $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
51117 }
51118 $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
51119 $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
51120 $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
51121 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
51122 $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
51123
51124 if ($option->acceptValue()) {
51125 $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
51126 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
51127
51128 if (!empty($defaults)) {
51129 foreach ($defaults as $default) {
51130 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
51131 $defaultXML->appendChild($dom->createTextNode($default));
51132 }
51133 }
51134 }
51135
51136 return $dom;
51137 }
51138 }
51139 <?php
51140
51141
51142
51143
51144
51145
51146
51147
51148
51149
51150 namespace Symfony\Component\Console\Event;
51151
51152
51153
51154
51155
51156
51157 class ConsoleCommandEvent extends ConsoleEvent
51158 {
51159
51160
51161
51162 const RETURN_CODE_DISABLED = 113;
51163
51164
51165
51166
51167 private $commandShouldRun = true;
51168
51169
51170
51171
51172
51173
51174 public function disableCommand()
51175 {
51176 return $this->commandShouldRun = false;
51177 }
51178
51179
51180
51181
51182
51183
51184 public function enableCommand()
51185 {
51186 return $this->commandShouldRun = true;
51187 }
51188
51189
51190
51191
51192
51193
51194 public function commandShouldRun()
51195 {
51196 return $this->commandShouldRun;
51197 }
51198 }
51199 <?php
51200
51201
51202
51203
51204
51205
51206
51207
51208
51209
51210 namespace Symfony\Component\Console\Event;
51211
51212 use Symfony\Component\Console\Command\Command;
51213 use Symfony\Component\Console\Input\InputInterface;
51214 use Symfony\Component\Console\Output\OutputInterface;
51215 use Symfony\Component\EventDispatcher\Event;
51216
51217
51218
51219
51220
51221
51222 class ConsoleEvent extends Event
51223 {
51224 protected $command;
51225
51226 private $input;
51227 private $output;
51228
51229 public function __construct(Command $command, InputInterface $input, OutputInterface $output)
51230 {
51231 $this->command = $command;
51232 $this->input = $input;
51233 $this->output = $output;
51234 }
51235
51236
51237
51238
51239
51240
51241 public function getCommand()
51242 {
51243 return $this->command;
51244 }
51245
51246
51247
51248
51249
51250
51251 public function getInput()
51252 {
51253 return $this->input;
51254 }
51255
51256
51257
51258
51259
51260
51261 public function getOutput()
51262 {
51263 return $this->output;
51264 }
51265 }
51266 <?php
51267
51268
51269
51270
51271
51272
51273
51274
51275
51276
51277 namespace Symfony\Component\Console\Event;
51278
51279 use Symfony\Component\Console\Command\Command;
51280 use Symfony\Component\Console\Input\InputInterface;
51281 use Symfony\Component\Console\Output\OutputInterface;
51282
51283
51284
51285
51286
51287
51288 class ConsoleExceptionEvent extends ConsoleEvent
51289 {
51290 private $exception;
51291 private $exitCode;
51292
51293 public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
51294 {
51295 parent::__construct($command, $input, $output);
51296
51297 $this->setException($exception);
51298 $this->exitCode = (int) $exitCode;
51299 }
51300
51301
51302
51303
51304
51305
51306 public function getException()
51307 {
51308 return $this->exception;
51309 }
51310
51311
51312
51313
51314
51315
51316
51317
51318 public function setException(\Exception $exception)
51319 {
51320 $this->exception = $exception;
51321 }
51322
51323
51324
51325
51326
51327
51328 public function getExitCode()
51329 {
51330 return $this->exitCode;
51331 }
51332 }
51333 <?php
51334
51335
51336
51337
51338
51339
51340
51341
51342
51343
51344 namespace Symfony\Component\Console\Event;
51345
51346 use Symfony\Component\Console\Command\Command;
51347 use Symfony\Component\Console\Input\InputInterface;
51348 use Symfony\Component\Console\Output\OutputInterface;
51349
51350
51351
51352
51353
51354
51355 class ConsoleTerminateEvent extends ConsoleEvent
51356 {
51357
51358
51359
51360
51361
51362 private $exitCode;
51363
51364 public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
51365 {
51366 parent::__construct($command, $input, $output);
51367
51368 $this->setExitCode($exitCode);
51369 }
51370
51371
51372
51373
51374
51375
51376 public function setExitCode($exitCode)
51377 {
51378 $this->exitCode = (int) $exitCode;
51379 }
51380
51381
51382
51383
51384
51385
51386 public function getExitCode()
51387 {
51388 return $this->exitCode;
51389 }
51390 }
51391 <?php
51392
51393
51394
51395
51396
51397
51398
51399
51400
51401
51402 namespace Symfony\Component\Console\Exception;
51403
51404
51405
51406
51407
51408
51409 class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
51410 {
51411 private $alternatives;
51412
51413
51414
51415
51416
51417
51418
51419 public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
51420 {
51421 parent::__construct($message, $code, $previous);
51422
51423 $this->alternatives = $alternatives;
51424 }
51425
51426
51427
51428
51429 public function getAlternatives()
51430 {
51431 return $this->alternatives;
51432 }
51433 }
51434 <?php
51435
51436
51437
51438
51439
51440
51441
51442
51443
51444
51445 namespace Symfony\Component\Console\Exception;
51446
51447
51448
51449
51450
51451
51452 interface ExceptionInterface
51453 {
51454 }
51455 <?php
51456
51457
51458
51459
51460
51461
51462
51463
51464
51465
51466 namespace Symfony\Component\Console\Exception;
51467
51468
51469
51470
51471 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
51472 {
51473 }
51474 <?php
51475
51476
51477
51478
51479
51480
51481
51482
51483
51484
51485 namespace Symfony\Component\Console\Exception;
51486
51487
51488
51489
51490
51491
51492 class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
51493 {
51494 }
51495 <?php
51496
51497
51498
51499
51500
51501
51502
51503
51504
51505
51506 namespace Symfony\Component\Console\Exception;
51507
51508
51509
51510
51511 class LogicException extends \LogicException implements ExceptionInterface
51512 {
51513 }
51514 <?php
51515
51516
51517
51518
51519
51520
51521
51522
51523
51524
51525 namespace Symfony\Component\Console\Exception;
51526
51527
51528
51529
51530 class RuntimeException extends \RuntimeException implements ExceptionInterface
51531 {
51532 }
51533 <?php
51534
51535
51536
51537
51538
51539
51540
51541
51542
51543
51544 namespace Symfony\Component\Console\Formatter;
51545
51546 use Symfony\Component\Console\Exception\InvalidArgumentException;
51547
51548
51549
51550
51551
51552
51553 class OutputFormatter implements OutputFormatterInterface
51554 {
51555 private $decorated;
51556 private $styles = array();
51557 private $styleStack;
51558
51559
51560
51561
51562
51563
51564
51565
51566 public static function escape($text)
51567 {
51568 $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
51569
51570 return self::escapeTrailingBackslash($text);
51571 }
51572
51573
51574
51575
51576
51577
51578
51579
51580
51581
51582 public static function escapeTrailingBackslash($text)
51583 {
51584 if ('\\' === substr($text, -1)) {
51585 $len = strlen($text);
51586 $text = rtrim($text, '\\');
51587 $text = str_replace("\0", '', $text);
51588 $text .= str_repeat("\0", $len - strlen($text));
51589 }
51590
51591 return $text;
51592 }
51593
51594
51595
51596
51597
51598
51599
51600 public function __construct($decorated = false, array $styles = array())
51601 {
51602 $this->decorated = (bool) $decorated;
51603
51604 $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
51605 $this->setStyle('info', new OutputFormatterStyle('green'));
51606 $this->setStyle('comment', new OutputFormatterStyle('yellow'));
51607 $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
51608
51609 foreach ($styles as $name => $style) {
51610 $this->setStyle($name, $style);
51611 }
51612
51613 $this->styleStack = new OutputFormatterStyleStack();
51614 }
51615
51616
51617
51618
51619 public function setDecorated($decorated)
51620 {
51621 $this->decorated = (bool) $decorated;
51622 }
51623
51624
51625
51626
51627 public function isDecorated()
51628 {
51629 return $this->decorated;
51630 }
51631
51632
51633
51634
51635 public function setStyle($name, OutputFormatterStyleInterface $style)
51636 {
51637 $this->styles[strtolower($name)] = $style;
51638 }
51639
51640
51641
51642
51643 public function hasStyle($name)
51644 {
51645 return isset($this->styles[strtolower($name)]);
51646 }
51647
51648
51649
51650
51651 public function getStyle($name)
51652 {
51653 if (!$this->hasStyle($name)) {
51654 throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
51655 }
51656
51657 return $this->styles[strtolower($name)];
51658 }
51659
51660
51661
51662
51663 public function format($message)
51664 {
51665 $message = (string) $message;
51666 $offset = 0;
51667 $output = '';
51668 $tagRegex = '[a-z][a-z0-9_=;-]*+';
51669 preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
51670 foreach ($matches[0] as $i => $match) {
51671 $pos = $match[1];
51672 $text = $match[0];
51673
51674 if (0 != $pos && '\\' == $message[$pos - 1]) {
51675 continue;
51676 }
51677
51678
51679  $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
51680 $offset = $pos + strlen($text);
51681
51682
51683  if ($open = '/' != $text[1]) {
51684 $tag = $matches[1][$i][0];
51685 } else {
51686 $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
51687 }
51688
51689 if (!$open && !$tag) {
51690
51691  $this->styleStack->pop();
51692 } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
51693 $output .= $this->applyCurrentStyle($text);
51694 } elseif ($open) {
51695 $this->styleStack->push($style);
51696 } else {
51697 $this->styleStack->pop($style);
51698 }
51699 }
51700
51701 $output .= $this->applyCurrentStyle(substr($message, $offset));
51702
51703 if (false !== strpos($output, "\0")) {
51704 return strtr($output, array("\0" => '\\', '\\<' => '<'));
51705 }
51706
51707 return str_replace('\\<', '<', $output);
51708 }
51709
51710
51711
51712
51713 public function getStyleStack()
51714 {
51715 return $this->styleStack;
51716 }
51717
51718
51719
51720
51721
51722
51723
51724
51725 private function createStyleFromString($string)
51726 {
51727 if (isset($this->styles[$string])) {
51728 return $this->styles[$string];
51729 }
51730
51731 if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
51732 return false;
51733 }
51734
51735 $style = new OutputFormatterStyle();
51736 foreach ($matches as $match) {
51737 array_shift($match);
51738
51739 if ('fg' == $match[0]) {
51740 $style->setForeground($match[1]);
51741 } elseif ('bg' == $match[0]) {
51742 $style->setBackground($match[1]);
51743 } else {
51744 try {
51745 $style->setOption($match[1]);
51746 } catch (\InvalidArgumentException $e) {
51747 return false;
51748 }
51749 }
51750 }
51751
51752 return $style;
51753 }
51754
51755
51756
51757
51758
51759
51760
51761
51762 private function applyCurrentStyle($text)
51763 {
51764 return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
51765 }
51766 }
51767 <?php
51768
51769
51770
51771
51772
51773
51774
51775
51776
51777
51778 namespace Symfony\Component\Console\Formatter;
51779
51780
51781
51782
51783
51784
51785 interface OutputFormatterInterface
51786 {
51787
51788
51789
51790
51791
51792 public function setDecorated($decorated);
51793
51794
51795
51796
51797
51798
51799 public function isDecorated();
51800
51801
51802
51803
51804
51805
51806
51807 public function setStyle($name, OutputFormatterStyleInterface $style);
51808
51809
51810
51811
51812
51813
51814
51815
51816 public function hasStyle($name);
51817
51818
51819
51820
51821
51822
51823
51824
51825
51826
51827 public function getStyle($name);
51828
51829
51830
51831
51832
51833
51834
51835
51836 public function format($message);
51837 }
51838 <?php
51839
51840
51841
51842
51843
51844
51845
51846
51847
51848
51849 namespace Symfony\Component\Console\Formatter;
51850
51851 use Symfony\Component\Console\Exception\InvalidArgumentException;
51852
51853
51854
51855
51856
51857
51858 class OutputFormatterStyle implements OutputFormatterStyleInterface
51859 {
51860 private static $availableForegroundColors = array(
51861 'black' => array('set' => 30, 'unset' => 39),
51862 'red' => array('set' => 31, 'unset' => 39),
51863 'green' => array('set' => 32, 'unset' => 39),
51864 'yellow' => array('set' => 33, 'unset' => 39),
51865 'blue' => array('set' => 34, 'unset' => 39),
51866 'magenta' => array('set' => 35, 'unset' => 39),
51867 'cyan' => array('set' => 36, 'unset' => 39),
51868 'white' => array('set' => 37, 'unset' => 39),
51869 'default' => array('set' => 39, 'unset' => 39),
51870 );
51871 private static $availableBackgroundColors = array(
51872 'black' => array('set' => 40, 'unset' => 49),
51873 'red' => array('set' => 41, 'unset' => 49),
51874 'green' => array('set' => 42, 'unset' => 49),
51875 'yellow' => array('set' => 43, 'unset' => 49),
51876 'blue' => array('set' => 44, 'unset' => 49),
51877 'magenta' => array('set' => 45, 'unset' => 49),
51878 'cyan' => array('set' => 46, 'unset' => 49),
51879 'white' => array('set' => 47, 'unset' => 49),
51880 'default' => array('set' => 49, 'unset' => 49),
51881 );
51882 private static $availableOptions = array(
51883 'bold' => array('set' => 1, 'unset' => 22),
51884 'underscore' => array('set' => 4, 'unset' => 24),
51885 'blink' => array('set' => 5, 'unset' => 25),
51886 'reverse' => array('set' => 7, 'unset' => 27),
51887 'conceal' => array('set' => 8, 'unset' => 28),
51888 );
51889
51890 private $foreground;
51891 private $background;
51892 private $options = array();
51893
51894
51895
51896
51897
51898
51899
51900
51901 public function __construct($foreground = null, $background = null, array $options = array())
51902 {
51903 if (null !== $foreground) {
51904 $this->setForeground($foreground);
51905 }
51906 if (null !== $background) {
51907 $this->setBackground($background);
51908 }
51909 if (count($options)) {
51910 $this->setOptions($options);
51911 }
51912 }
51913
51914
51915
51916
51917
51918
51919
51920
51921 public function setForeground($color = null)
51922 {
51923 if (null === $color) {
51924 $this->foreground = null;
51925
51926 return;
51927 }
51928
51929 if (!isset(static::$availableForegroundColors[$color])) {
51930 throw new InvalidArgumentException(sprintf(
51931 'Invalid foreground color specified: "%s". Expected one of (%s)',
51932 $color,
51933 implode(', ', array_keys(static::$availableForegroundColors))
51934 ));
51935 }
51936
51937 $this->foreground = static::$availableForegroundColors[$color];
51938 }
51939
51940
51941
51942
51943
51944
51945
51946
51947 public function setBackground($color = null)
51948 {
51949 if (null === $color) {
51950 $this->background = null;
51951
51952 return;
51953 }
51954
51955 if (!isset(static::$availableBackgroundColors[$color])) {
51956 throw new InvalidArgumentException(sprintf(
51957 'Invalid background color specified: "%s". Expected one of (%s)',
51958 $color,
51959 implode(', ', array_keys(static::$availableBackgroundColors))
51960 ));
51961 }
51962
51963 $this->background = static::$availableBackgroundColors[$color];
51964 }
51965
51966
51967
51968
51969
51970
51971
51972
51973 public function setOption($option)
51974 {
51975 if (!isset(static::$availableOptions[$option])) {
51976 throw new InvalidArgumentException(sprintf(
51977 'Invalid option specified: "%s". Expected one of (%s)',
51978 $option,
51979 implode(', ', array_keys(static::$availableOptions))
51980 ));
51981 }
51982
51983 if (!in_array(static::$availableOptions[$option], $this->options)) {
51984 $this->options[] = static::$availableOptions[$option];
51985 }
51986 }
51987
51988
51989
51990
51991
51992
51993
51994
51995 public function unsetOption($option)
51996 {
51997 if (!isset(static::$availableOptions[$option])) {
51998 throw new InvalidArgumentException(sprintf(
51999 'Invalid option specified: "%s". Expected one of (%s)',
52000 $option,
52001 implode(', ', array_keys(static::$availableOptions))
52002 ));
52003 }
52004
52005 $pos = array_search(static::$availableOptions[$option], $this->options);
52006 if (false !== $pos) {
52007 unset($this->options[$pos]);
52008 }
52009 }
52010
52011
52012
52013
52014 public function setOptions(array $options)
52015 {
52016 $this->options = array();
52017
52018 foreach ($options as $option) {
52019 $this->setOption($option);
52020 }
52021 }
52022
52023
52024
52025
52026
52027
52028
52029
52030 public function apply($text)
52031 {
52032 $setCodes = array();
52033 $unsetCodes = array();
52034
52035 if (null !== $this->foreground) {
52036 $setCodes[] = $this->foreground['set'];
52037 $unsetCodes[] = $this->foreground['unset'];
52038 }
52039 if (null !== $this->background) {
52040 $setCodes[] = $this->background['set'];
52041 $unsetCodes[] = $this->background['unset'];
52042 }
52043 if (count($this->options)) {
52044 foreach ($this->options as $option) {
52045 $setCodes[] = $option['set'];
52046 $unsetCodes[] = $option['unset'];
52047 }
52048 }
52049
52050 if (0 === count($setCodes)) {
52051 return $text;
52052 }
52053
52054 return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
52055 }
52056 }
52057 <?php
52058
52059
52060
52061
52062
52063
52064
52065
52066
52067
52068 namespace Symfony\Component\Console\Formatter;
52069
52070
52071
52072
52073
52074
52075 interface OutputFormatterStyleInterface
52076 {
52077
52078
52079
52080
52081
52082 public function setForeground($color = null);
52083
52084
52085
52086
52087
52088
52089 public function setBackground($color = null);
52090
52091
52092
52093
52094
52095
52096 public function setOption($option);
52097
52098
52099
52100
52101
52102
52103 public function unsetOption($option);
52104
52105
52106
52107
52108 public function setOptions(array $options);
52109
52110
52111
52112
52113
52114
52115
52116
52117 public function apply($text);
52118 }
52119 <?php
52120
52121
52122
52123
52124
52125
52126
52127
52128
52129
52130 namespace Symfony\Component\Console\Formatter;
52131
52132 use Symfony\Component\Console\Exception\InvalidArgumentException;
52133
52134
52135
52136
52137 class OutputFormatterStyleStack
52138 {
52139
52140
52141
52142 private $styles;
52143
52144 private $emptyStyle;
52145
52146 public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
52147 {
52148 $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
52149 $this->reset();
52150 }
52151
52152
52153
52154
52155 public function reset()
52156 {
52157 $this->styles = array();
52158 }
52159
52160
52161
52162
52163 public function push(OutputFormatterStyleInterface $style)
52164 {
52165 $this->styles[] = $style;
52166 }
52167
52168
52169
52170
52171
52172
52173
52174
52175 public function pop(OutputFormatterStyleInterface $style = null)
52176 {
52177 if (empty($this->styles)) {
52178 return $this->emptyStyle;
52179 }
52180
52181 if (null === $style) {
52182 return array_pop($this->styles);
52183 }
52184
52185 foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
52186 if ($style->apply('') === $stackedStyle->apply('')) {
52187 $this->styles = array_slice($this->styles, 0, $index);
52188
52189 return $stackedStyle;
52190 }
52191 }
52192
52193 throw new InvalidArgumentException('Incorrectly nested style tag found.');
52194 }
52195
52196
52197
52198
52199
52200
52201 public function getCurrent()
52202 {
52203 if (empty($this->styles)) {
52204 return $this->emptyStyle;
52205 }
52206
52207 return $this->styles[count($this->styles) - 1];
52208 }
52209
52210
52211
52212
52213 public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
52214 {
52215 $this->emptyStyle = $emptyStyle;
52216
52217 return $this;
52218 }
52219
52220
52221
52222
52223 public function getEmptyStyle()
52224 {
52225 return $this->emptyStyle;
52226 }
52227 }
52228 <?php
52229
52230
52231
52232
52233
52234
52235
52236
52237
52238
52239 namespace Symfony\Component\Console\Helper;
52240
52241
52242
52243
52244
52245
52246
52247
52248 class DebugFormatterHelper extends Helper
52249 {
52250 private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
52251 private $started = array();
52252 private $count = -1;
52253
52254
52255
52256
52257
52258
52259
52260
52261
52262
52263 public function start($id, $message, $prefix = 'RUN')
52264 {
52265 $this->started[$id] = array('border' => ++$this->count % count($this->colors));
52266
52267 return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
52268 }
52269
52270
52271
52272
52273
52274
52275
52276
52277
52278
52279
52280
52281 public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
52282 {
52283 $message = '';
52284
52285 if ($error) {
52286 if (isset($this->started[$id]['out'])) {
52287 $message .= "\n";
52288 unset($this->started[$id]['out']);
52289 }
52290 if (!isset($this->started[$id]['err'])) {
52291 $message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
52292 $this->started[$id]['err'] = true;
52293 }
52294
52295 $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
52296 } else {
52297 if (isset($this->started[$id]['err'])) {
52298 $message .= "\n";
52299 unset($this->started[$id]['err']);
52300 }
52301 if (!isset($this->started[$id]['out'])) {
52302 $message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
52303 $this->started[$id]['out'] = true;
52304 }
52305
52306 $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
52307 }
52308
52309 return $message;
52310 }
52311
52312
52313
52314
52315
52316
52317
52318
52319
52320
52321
52322 public function stop($id, $message, $successful, $prefix = 'RES')
52323 {
52324 $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
52325
52326 if ($successful) {
52327 return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
52328 }
52329
52330 $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
52331
52332 unset($this->started[$id]['out'], $this->started[$id]['err']);
52333
52334 return $message;
52335 }
52336
52337
52338
52339
52340
52341
52342 private function getBorder($id)
52343 {
52344 return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
52345 }
52346
52347
52348
52349
52350 public function getName()
52351 {
52352 return 'debug_formatter';
52353 }
52354 }
52355 <?php
52356
52357
52358
52359
52360
52361
52362
52363
52364
52365
52366 namespace Symfony\Component\Console\Helper;
52367
52368 use Symfony\Component\Console\Descriptor\DescriptorInterface;
52369 use Symfony\Component\Console\Descriptor\JsonDescriptor;
52370 use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
52371 use Symfony\Component\Console\Descriptor\TextDescriptor;
52372 use Symfony\Component\Console\Descriptor\XmlDescriptor;
52373 use Symfony\Component\Console\Output\OutputInterface;
52374 use Symfony\Component\Console\Exception\InvalidArgumentException;
52375
52376
52377
52378
52379
52380
52381 class DescriptorHelper extends Helper
52382 {
52383
52384
52385
52386 private $descriptors = array();
52387
52388 public function __construct()
52389 {
52390 $this
52391 ->register('txt', new TextDescriptor())
52392 ->register('xml', new XmlDescriptor())
52393 ->register('json', new JsonDescriptor())
52394 ->register('md', new MarkdownDescriptor())
52395 ;
52396 }
52397
52398
52399
52400
52401
52402
52403
52404
52405
52406
52407
52408
52409
52410
52411 public function describe(OutputInterface $output, $object, array $options = array())
52412 {
52413 $options = array_merge(array(
52414 'raw_text' => false,
52415 'format' => 'txt',
52416 ), $options);
52417
52418 if (!isset($this->descriptors[$options['format']])) {
52419 throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
52420 }
52421
52422 $descriptor = $this->descriptors[$options['format']];
52423 $descriptor->describe($output, $object, $options);
52424 }
52425
52426
52427
52428
52429
52430
52431
52432
52433
52434 public function register($format, DescriptorInterface $descriptor)
52435 {
52436 $this->descriptors[$format] = $descriptor;
52437
52438 return $this;
52439 }
52440
52441
52442
52443
52444 public function getName()
52445 {
52446 return 'descriptor';
52447 }
52448 }
52449 <?php
52450
52451
52452
52453
52454
52455
52456
52457
52458
52459
52460 namespace Symfony\Component\Console\Helper;
52461
52462 use Symfony\Component\Console\Exception\InvalidArgumentException;
52463 use Symfony\Component\Console\Exception\RuntimeException;
52464 use Symfony\Component\Console\Output\ConsoleOutputInterface;
52465 use Symfony\Component\Console\Output\OutputInterface;
52466 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
52467
52468
52469
52470
52471
52472
52473
52474
52475
52476 class DialogHelper extends InputAwareHelper
52477 {
52478 private $inputStream;
52479 private static $shell;
52480 private static $stty;
52481
52482 public function __construct($triggerDeprecationError = true)
52483 {
52484 if ($triggerDeprecationError) {
52485 @trigger_error('"Symfony\Component\Console\Helper\DialogHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\QuestionHelper" instead.', E_USER_DEPRECATED);
52486 }
52487 }
52488
52489
52490
52491
52492
52493
52494
52495
52496
52497
52498
52499
52500
52501
52502
52503
52504 public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
52505 {
52506 if ($output instanceof ConsoleOutputInterface) {
52507 $output = $output->getErrorOutput();
52508 }
52509
52510 $width = max(array_map('strlen', array_keys($choices)));
52511
52512 $messages = (array) $question;
52513 foreach ($choices as $key => $value) {
52514 $messages[] = sprintf("  [<info>%-{$width}s</info>] %s", $key, $value);
52515 }
52516
52517 $output->writeln($messages);
52518
52519 $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
52520
52521  $selectedChoices = str_replace(' ', '', $picked);
52522
52523 if ($multiselect) {
52524
52525  if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
52526 throw new InvalidArgumentException(sprintf($errorMessage, $picked));
52527 }
52528 $selectedChoices = explode(',', $selectedChoices);
52529 } else {
52530 $selectedChoices = array($picked);
52531 }
52532
52533 $multiselectChoices = array();
52534
52535 foreach ($selectedChoices as $value) {
52536 if (empty($choices[$value])) {
52537 throw new InvalidArgumentException(sprintf($errorMessage, $value));
52538 }
52539 $multiselectChoices[] = $value;
52540 }
52541
52542 if ($multiselect) {
52543 return $multiselectChoices;
52544 }
52545
52546 return $picked;
52547 }, $attempts, $default);
52548
52549 return $result;
52550 }
52551
52552
52553
52554
52555
52556
52557
52558
52559
52560
52561
52562
52563
52564 public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
52565 {
52566 if ($this->input && !$this->input->isInteractive()) {
52567 return $default;
52568 }
52569
52570 if ($output instanceof ConsoleOutputInterface) {
52571 $output = $output->getErrorOutput();
52572 }
52573
52574 $output->write($question);
52575
52576 $inputStream = $this->inputStream ?: STDIN;
52577
52578 if (null === $autocomplete || !$this->hasSttyAvailable()) {
52579 $ret = fgets($inputStream, 4096);
52580 if (false === $ret) {
52581 throw new RuntimeException('Aborted');
52582 }
52583 $ret = trim($ret);
52584 } else {
52585 $ret = '';
52586
52587 $i = 0;
52588 $ofs = -1;
52589 $matches = $autocomplete;
52590 $numMatches = count($matches);
52591
52592 $sttyMode = shell_exec('stty -g');
52593
52594
52595  shell_exec('stty -icanon -echo');
52596
52597
52598  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
52599
52600
52601  while (!feof($inputStream)) {
52602 $c = fread($inputStream, 1);
52603
52604
52605  if ("\177" === $c) {
52606 if (0 === $numMatches && 0 !== $i) {
52607 --$i;
52608
52609  $output->write("\033[1D");
52610 }
52611
52612 if (0 === $i) {
52613 $ofs = -1;
52614 $matches = $autocomplete;
52615 $numMatches = count($matches);
52616 } else {
52617 $numMatches = 0;
52618 }
52619
52620
52621  $ret = substr($ret, 0, $i);
52622 } elseif ("\033" === $c) {
52623
52624  $c .= fread($inputStream, 2);
52625
52626
52627  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
52628 if ('A' === $c[2] && -1 === $ofs) {
52629 $ofs = 0;
52630 }
52631
52632 if (0 === $numMatches) {
52633 continue;
52634 }
52635
52636 $ofs += ('A' === $c[2]) ? -1 : 1;
52637 $ofs = ($numMatches + $ofs) % $numMatches;
52638 }
52639 } elseif (ord($c) < 32) {
52640 if ("\t" === $c || "\n" === $c) {
52641 if ($numMatches > 0 && -1 !== $ofs) {
52642 $ret = $matches[$ofs];
52643
52644  $output->write(substr($ret, $i));
52645 $i = strlen($ret);
52646 }
52647
52648 if ("\n" === $c) {
52649 $output->write($c);
52650 break;
52651 }
52652
52653 $numMatches = 0;
52654 }
52655
52656 continue;
52657 } else {
52658 $output->write($c);
52659 $ret .= $c;
52660 ++$i;
52661
52662 $numMatches = 0;
52663 $ofs = 0;
52664
52665 foreach ($autocomplete as $value) {
52666
52667  if (0 === strpos($value, $ret) && $i !== strlen($value)) {
52668 $matches[$numMatches++] = $value;
52669 }
52670 }
52671 }
52672
52673
52674  $output->write("\033[K");
52675
52676 if ($numMatches > 0 && -1 !== $ofs) {
52677
52678  $output->write("\0337");
52679
52680  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
52681
52682  $output->write("\0338");
52683 }
52684 }
52685
52686
52687  shell_exec(sprintf('stty %s', $sttyMode));
52688 }
52689
52690 return strlen($ret) > 0 ? $ret : $default;
52691 }
52692
52693
52694
52695
52696
52697
52698
52699
52700
52701
52702
52703
52704 public function askConfirmation(OutputInterface $output, $question, $default = true)
52705 {
52706 $answer = 'z';
52707 while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
52708 $answer = $this->ask($output, $question);
52709 }
52710
52711 if (false === $default) {
52712 return $answer && 'y' == strtolower($answer[0]);
52713 }
52714
52715 return !$answer || 'y' == strtolower($answer[0]);
52716 }
52717
52718
52719
52720
52721
52722
52723
52724
52725
52726
52727
52728
52729 public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
52730 {
52731 if ($output instanceof ConsoleOutputInterface) {
52732 $output = $output->getErrorOutput();
52733 }
52734
52735 if ('\\' === DIRECTORY_SEPARATOR) {
52736 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
52737
52738
52739  if ('phar:' === substr(__FILE__, 0, 5)) {
52740 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
52741 copy($exe, $tmpExe);
52742 $exe = $tmpExe;
52743 }
52744
52745 $output->write($question);
52746 $value = rtrim(shell_exec($exe));
52747 $output->writeln('');
52748
52749 if (isset($tmpExe)) {
52750 unlink($tmpExe);
52751 }
52752
52753 return $value;
52754 }
52755
52756 if ($this->hasSttyAvailable()) {
52757 $output->write($question);
52758
52759 $sttyMode = shell_exec('stty -g');
52760
52761 shell_exec('stty -echo');
52762 $value = fgets($this->inputStream ?: STDIN, 4096);
52763 shell_exec(sprintf('stty %s', $sttyMode));
52764
52765 if (false === $value) {
52766 throw new RuntimeException('Aborted');
52767 }
52768
52769 $value = trim($value);
52770 $output->writeln('');
52771
52772 return $value;
52773 }
52774
52775 if (false !== $shell = $this->getShell()) {
52776 $output->write($question);
52777 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
52778 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
52779 $value = rtrim(shell_exec($command));
52780 $output->writeln('');
52781
52782 return $value;
52783 }
52784
52785 if ($fallback) {
52786 return $this->ask($output, $question);
52787 }
52788
52789 throw new RuntimeException('Unable to hide the response');
52790 }
52791
52792
52793
52794
52795
52796
52797
52798
52799
52800
52801
52802
52803
52804
52805
52806
52807
52808
52809
52810 public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
52811 {
52812 $that = $this;
52813
52814 $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
52815 return $that->ask($output, $question, $default, $autocomplete);
52816 };
52817
52818 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
52819 }
52820
52821
52822
52823
52824
52825
52826
52827
52828
52829
52830
52831
52832
52833
52834
52835
52836
52837
52838
52839 public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
52840 {
52841 $that = $this;
52842
52843 $interviewer = function () use ($output, $question, $fallback, $that) {
52844 return $that->askHiddenResponse($output, $question, $fallback);
52845 };
52846
52847 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
52848 }
52849
52850
52851
52852
52853
52854
52855
52856
52857 public function setInputStream($stream)
52858 {
52859 $this->inputStream = $stream;
52860 }
52861
52862
52863
52864
52865
52866
52867 public function getInputStream()
52868 {
52869 return $this->inputStream;
52870 }
52871
52872
52873
52874
52875 public function getName()
52876 {
52877 return 'dialog';
52878 }
52879
52880
52881
52882
52883
52884
52885 private function getShell()
52886 {
52887 if (null !== self::$shell) {
52888 return self::$shell;
52889 }
52890
52891 self::$shell = false;
52892
52893 if (file_exists('/usr/bin/env')) {
52894
52895  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
52896 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
52897 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
52898 self::$shell = $sh;
52899 break;
52900 }
52901 }
52902 }
52903
52904 return self::$shell;
52905 }
52906
52907 private function hasSttyAvailable()
52908 {
52909 if (null !== self::$stty) {
52910 return self::$stty;
52911 }
52912
52913 exec('stty 2>&1', $output, $exitcode);
52914
52915 return self::$stty = 0 === $exitcode;
52916 }
52917
52918
52919
52920
52921
52922
52923
52924
52925
52926
52927
52928
52929
52930 private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
52931 {
52932 if ($output instanceof ConsoleOutputInterface) {
52933 $output = $output->getErrorOutput();
52934 }
52935
52936 $e = null;
52937 while (false === $attempts || $attempts--) {
52938 if (null !== $e) {
52939 $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
52940 }
52941
52942 try {
52943 return call_user_func($validator, $interviewer());
52944 } catch (\Exception $e) {
52945 }
52946 }
52947
52948 throw $e;
52949 }
52950 }
52951 <?php
52952
52953
52954
52955
52956
52957
52958
52959
52960
52961
52962 namespace Symfony\Component\Console\Helper;
52963
52964 use Symfony\Component\Console\Formatter\OutputFormatter;
52965
52966
52967
52968
52969
52970
52971 class FormatterHelper extends Helper
52972 {
52973
52974
52975
52976
52977
52978
52979
52980
52981
52982 public function formatSection($section, $message, $style = 'info')
52983 {
52984 return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
52985 }
52986
52987
52988
52989
52990
52991
52992
52993
52994
52995
52996 public function formatBlock($messages, $style, $large = false)
52997 {
52998 if (!is_array($messages)) {
52999 $messages = array($messages);
53000 }
53001
53002 $len = 0;
53003 $lines = array();
53004 foreach ($messages as $message) {
53005 $message = OutputFormatter::escape($message);
53006 $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
53007 $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
53008 }
53009
53010 $messages = $large ? array(str_repeat(' ', $len)) : array();
53011 for ($i = 0; isset($lines[$i]); ++$i) {
53012 $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
53013 }
53014 if ($large) {
53015 $messages[] = str_repeat(' ', $len);
53016 }
53017
53018 for ($i = 0; isset($messages[$i]); ++$i) {
53019 $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
53020 }
53021
53022 return implode("\n", $messages);
53023 }
53024
53025
53026
53027
53028 public function getName()
53029 {
53030 return 'formatter';
53031 }
53032 }
53033 <?php
53034
53035
53036
53037
53038
53039
53040
53041
53042
53043
53044 namespace Symfony\Component\Console\Helper;
53045
53046 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
53047
53048
53049
53050
53051
53052
53053 abstract class Helper implements HelperInterface
53054 {
53055 protected $helperSet = null;
53056
53057
53058
53059
53060 public function setHelperSet(HelperSet $helperSet = null)
53061 {
53062 $this->helperSet = $helperSet;
53063 }
53064
53065
53066
53067
53068 public function getHelperSet()
53069 {
53070 return $this->helperSet;
53071 }
53072
53073
53074
53075
53076
53077
53078
53079
53080 public static function strlen($string)
53081 {
53082 if (false === $encoding = mb_detect_encoding($string, null, true)) {
53083 return strlen($string);
53084 }
53085
53086 return mb_strwidth($string, $encoding);
53087 }
53088
53089 public static function formatTime($secs)
53090 {
53091 static $timeFormats = array(
53092 array(0, '< 1 sec'),
53093 array(1, '1 sec'),
53094 array(2, 'secs', 1),
53095 array(60, '1 min'),
53096 array(120, 'mins', 60),
53097 array(3600, '1 hr'),
53098 array(7200, 'hrs', 3600),
53099 array(86400, '1 day'),
53100 array(172800, 'days', 86400),
53101 );
53102
53103 foreach ($timeFormats as $index => $format) {
53104 if ($secs >= $format[0]) {
53105 if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
53106 || $index == count($timeFormats) - 1
53107 ) {
53108 if (2 == count($format)) {
53109 return $format[1];
53110 }
53111
53112 return floor($secs / $format[2]).' '.$format[1];
53113 }
53114 }
53115 }
53116 }
53117
53118 public static function formatMemory($memory)
53119 {
53120 if ($memory >= 1024 * 1024 * 1024) {
53121 return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
53122 }
53123
53124 if ($memory >= 1024 * 1024) {
53125 return sprintf('%.1f MiB', $memory / 1024 / 1024);
53126 }
53127
53128 if ($memory >= 1024) {
53129 return sprintf('%d KiB', $memory / 1024);
53130 }
53131
53132 return sprintf('%d B', $memory);
53133 }
53134
53135 public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
53136 {
53137 return self::strlen(self::removeDecoration($formatter, $string));
53138 }
53139
53140 public static function removeDecoration(OutputFormatterInterface $formatter, $string)
53141 {
53142 $isDecorated = $formatter->isDecorated();
53143 $formatter->setDecorated(false);
53144
53145  $string = $formatter->format($string);
53146
53147  $string = preg_replace("/\033\[[^m]*m/", '', $string);
53148 $formatter->setDecorated($isDecorated);
53149
53150 return $string;
53151 }
53152 }
53153 <?php
53154
53155
53156
53157
53158
53159
53160
53161
53162
53163
53164 namespace Symfony\Component\Console\Helper;
53165
53166
53167
53168
53169
53170
53171 interface HelperInterface
53172 {
53173
53174
53175
53176 public function setHelperSet(HelperSet $helperSet = null);
53177
53178
53179
53180
53181
53182
53183 public function getHelperSet();
53184
53185
53186
53187
53188
53189
53190 public function getName();
53191 }
53192 <?php
53193
53194
53195
53196
53197
53198
53199
53200
53201
53202
53203 namespace Symfony\Component\Console\Helper;
53204
53205 use Symfony\Component\Console\Command\Command;
53206 use Symfony\Component\Console\Exception\InvalidArgumentException;
53207
53208
53209
53210
53211
53212
53213 class HelperSet implements \IteratorAggregate
53214 {
53215
53216
53217
53218 private $helpers = array();
53219 private $command;
53220
53221
53222
53223
53224 public function __construct(array $helpers = array())
53225 {
53226 foreach ($helpers as $alias => $helper) {
53227 $this->set($helper, is_int($alias) ? null : $alias);
53228 }
53229 }
53230
53231
53232
53233
53234
53235
53236
53237 public function set(HelperInterface $helper, $alias = null)
53238 {
53239 $this->helpers[$helper->getName()] = $helper;
53240 if (null !== $alias) {
53241 $this->helpers[$alias] = $helper;
53242 }
53243
53244 $helper->setHelperSet($this);
53245 }
53246
53247
53248
53249
53250
53251
53252
53253
53254 public function has($name)
53255 {
53256 return isset($this->helpers[$name]);
53257 }
53258
53259
53260
53261
53262
53263
53264
53265
53266
53267
53268 public function get($name)
53269 {
53270 if (!$this->has($name)) {
53271 throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
53272 }
53273
53274 if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) {
53275 @trigger_error('"Symfony\Component\Console\Helper\DialogHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\QuestionHelper" instead.', E_USER_DEPRECATED);
53276 } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) {
53277 @trigger_error('"Symfony\Component\Console\Helper\ProgressHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\ProgressBar" instead.', E_USER_DEPRECATED);
53278 } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) {
53279 @trigger_error('"Symfony\Component\Console\Helper\TableHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\Table" instead.', E_USER_DEPRECATED);
53280 }
53281
53282 return $this->helpers[$name];
53283 }
53284
53285 public function setCommand(Command $command = null)
53286 {
53287 $this->command = $command;
53288 }
53289
53290
53291
53292
53293
53294
53295 public function getCommand()
53296 {
53297 return $this->command;
53298 }
53299
53300
53301
53302
53303 public function getIterator()
53304 {
53305 return new \ArrayIterator($this->helpers);
53306 }
53307 }
53308 <?php
53309
53310
53311
53312
53313
53314
53315
53316
53317
53318
53319 namespace Symfony\Component\Console\Helper;
53320
53321 use Symfony\Component\Console\Input\InputInterface;
53322 use Symfony\Component\Console\Input\InputAwareInterface;
53323
53324
53325
53326
53327
53328
53329 abstract class InputAwareHelper extends Helper implements InputAwareInterface
53330 {
53331 protected $input;
53332
53333
53334
53335
53336 public function setInput(InputInterface $input)
53337 {
53338 $this->input = $input;
53339 }
53340 }
53341 <?php
53342
53343
53344
53345
53346
53347
53348
53349
53350
53351
53352 namespace Symfony\Component\Console\Helper;
53353
53354 use Symfony\Component\Console\Output\ConsoleOutputInterface;
53355 use Symfony\Component\Console\Output\OutputInterface;
53356 use Symfony\Component\Process\Exception\ProcessFailedException;
53357 use Symfony\Component\Process\Process;
53358 use Symfony\Component\Process\ProcessBuilder;
53359
53360
53361
53362
53363
53364
53365 class ProcessHelper extends Helper
53366 {
53367
53368
53369
53370
53371
53372
53373
53374
53375
53376
53377
53378
53379 public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
53380 {
53381 if ($output instanceof ConsoleOutputInterface) {
53382 $output = $output->getErrorOutput();
53383 }
53384
53385 $formatter = $this->getHelperSet()->get('debug_formatter');
53386
53387 if (is_array($cmd)) {
53388 $process = ProcessBuilder::create($cmd)->getProcess();
53389 } elseif ($cmd instanceof Process) {
53390 $process = $cmd;
53391 } else {
53392 $process = new Process($cmd);
53393 }
53394
53395 if ($verbosity <= $output->getVerbosity()) {
53396 $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
53397 }
53398
53399 if ($output->isDebug()) {
53400 $callback = $this->wrapCallback($output, $process, $callback);
53401 }
53402
53403 $process->run($callback);
53404
53405 if ($verbosity <= $output->getVerbosity()) {
53406 $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
53407 $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
53408 }
53409
53410 if (!$process->isSuccessful() && null !== $error) {
53411 $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
53412 }
53413
53414 return $process;
53415 }
53416
53417
53418
53419
53420
53421
53422
53423
53424
53425
53426
53427
53428
53429
53430
53431
53432
53433
53434
53435 public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
53436 {
53437 $process = $this->run($output, $cmd, $error, $callback);
53438
53439 if (!$process->isSuccessful()) {
53440 throw new ProcessFailedException($process);
53441 }
53442
53443 return $process;
53444 }
53445
53446
53447
53448
53449
53450
53451
53452
53453
53454
53455 public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
53456 {
53457 if ($output instanceof ConsoleOutputInterface) {
53458 $output = $output->getErrorOutput();
53459 }
53460
53461 $formatter = $this->getHelperSet()->get('debug_formatter');
53462
53463 $that = $this;
53464
53465 return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
53466 $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
53467
53468 if (null !== $callback) {
53469 call_user_func($callback, $type, $buffer);
53470 }
53471 };
53472 }
53473
53474
53475
53476
53477
53478
53479 public function escapeString($str)
53480 {
53481 return str_replace('<', '\\<', $str);
53482 }
53483
53484
53485
53486
53487 public function getName()
53488 {
53489 return 'process';
53490 }
53491 }
53492 <?php
53493
53494
53495
53496
53497
53498
53499
53500
53501
53502
53503 namespace Symfony\Component\Console\Helper;
53504
53505 use Symfony\Component\Console\Output\ConsoleOutputInterface;
53506 use Symfony\Component\Console\Output\OutputInterface;
53507 use Symfony\Component\Console\Exception\LogicException;
53508
53509
53510
53511
53512
53513
53514
53515 class ProgressBar
53516 {
53517 private $barWidth = 28;
53518 private $barChar;
53519 private $emptyBarChar = '-';
53520 private $progressChar = '>';
53521 private $format;
53522 private $internalFormat;
53523 private $redrawFreq = 1;
53524 private $output;
53525 private $step = 0;
53526 private $max;
53527 private $startTime;
53528 private $stepWidth;
53529 private $percent = 0.0;
53530 private $formatLineCount;
53531 private $messages = array();
53532 private $overwrite = true;
53533 private $firstRun = true;
53534
53535 private static $formatters;
53536 private static $formats;
53537
53538
53539
53540
53541
53542 public function __construct(OutputInterface $output, $max = 0)
53543 {
53544 if ($output instanceof ConsoleOutputInterface) {
53545 $output = $output->getErrorOutput();
53546 }
53547
53548 $this->output = $output;
53549 $this->setMaxSteps($max);
53550
53551 if (!$this->output->isDecorated()) {
53552
53553  $this->overwrite = false;
53554
53555
53556  $this->setRedrawFrequency($max / 10);
53557 }
53558
53559 $this->startTime = time();
53560 }
53561
53562
53563
53564
53565
53566
53567
53568
53569
53570 public static function setPlaceholderFormatterDefinition($name, $callable)
53571 {
53572 if (!self::$formatters) {
53573 self::$formatters = self::initPlaceholderFormatters();
53574 }
53575
53576 self::$formatters[$name] = $callable;
53577 }
53578
53579
53580
53581
53582
53583
53584
53585
53586 public static function getPlaceholderFormatterDefinition($name)
53587 {
53588 if (!self::$formatters) {
53589 self::$formatters = self::initPlaceholderFormatters();
53590 }
53591
53592 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
53593 }
53594
53595
53596
53597
53598
53599
53600
53601
53602
53603 public static function setFormatDefinition($name, $format)
53604 {
53605 if (!self::$formats) {
53606 self::$formats = self::initFormats();
53607 }
53608
53609 self::$formats[$name] = $format;
53610 }
53611
53612
53613
53614
53615
53616
53617
53618
53619 public static function getFormatDefinition($name)
53620 {
53621 if (!self::$formats) {
53622 self::$formats = self::initFormats();
53623 }
53624
53625 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
53626 }
53627
53628
53629
53630
53631
53632
53633
53634
53635
53636
53637
53638 public function setMessage($message, $name = 'message')
53639 {
53640 $this->messages[$name] = $message;
53641 }
53642
53643 public function getMessage($name = 'message')
53644 {
53645 return $this->messages[$name];
53646 }
53647
53648
53649
53650
53651
53652
53653 public function getStartTime()
53654 {
53655 return $this->startTime;
53656 }
53657
53658
53659
53660
53661
53662
53663 public function getMaxSteps()
53664 {
53665 return $this->max;
53666 }
53667
53668
53669
53670
53671
53672
53673
53674
53675 public function getStep()
53676 {
53677 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the getProgress() method instead.', E_USER_DEPRECATED);
53678
53679 return $this->getProgress();
53680 }
53681
53682
53683
53684
53685
53686
53687 public function getProgress()
53688 {
53689 return $this->step;
53690 }
53691
53692
53693
53694
53695
53696
53697
53698
53699 public function getStepWidth()
53700 {
53701 return $this->stepWidth;
53702 }
53703
53704
53705
53706
53707
53708
53709 public function getProgressPercent()
53710 {
53711 return $this->percent;
53712 }
53713
53714
53715
53716
53717
53718
53719 public function setBarWidth($size)
53720 {
53721 $this->barWidth = (int) $size;
53722 }
53723
53724
53725
53726
53727
53728
53729 public function getBarWidth()
53730 {
53731 return $this->barWidth;
53732 }
53733
53734
53735
53736
53737
53738
53739 public function setBarCharacter($char)
53740 {
53741 $this->barChar = $char;
53742 }
53743
53744
53745
53746
53747
53748
53749 public function getBarCharacter()
53750 {
53751 if (null === $this->barChar) {
53752 return $this->max ? '=' : $this->emptyBarChar;
53753 }
53754
53755 return $this->barChar;
53756 }
53757
53758
53759
53760
53761
53762
53763 public function setEmptyBarCharacter($char)
53764 {
53765 $this->emptyBarChar = $char;
53766 }
53767
53768
53769
53770
53771
53772
53773 public function getEmptyBarCharacter()
53774 {
53775 return $this->emptyBarChar;
53776 }
53777
53778
53779
53780
53781
53782
53783 public function setProgressCharacter($char)
53784 {
53785 $this->progressChar = $char;
53786 }
53787
53788
53789
53790
53791
53792
53793 public function getProgressCharacter()
53794 {
53795 return $this->progressChar;
53796 }
53797
53798
53799
53800
53801
53802
53803 public function setFormat($format)
53804 {
53805 $this->format = null;
53806 $this->internalFormat = $format;
53807 }
53808
53809
53810
53811
53812
53813
53814 public function setRedrawFrequency($freq)
53815 {
53816 $this->redrawFreq = max((int) $freq, 1);
53817 }
53818
53819
53820
53821
53822
53823
53824 public function start($max = null)
53825 {
53826 $this->startTime = time();
53827 $this->step = 0;
53828 $this->percent = 0.0;
53829
53830 if (null !== $max) {
53831 $this->setMaxSteps($max);
53832 }
53833
53834 $this->display();
53835 }
53836
53837
53838
53839
53840
53841
53842
53843
53844 public function advance($step = 1)
53845 {
53846 $this->setProgress($this->step + $step);
53847 }
53848
53849
53850
53851
53852
53853
53854
53855
53856
53857
53858 public function setCurrent($step)
53859 {
53860 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the setProgress() method instead.', E_USER_DEPRECATED);
53861
53862 $this->setProgress($step);
53863 }
53864
53865
53866
53867
53868
53869
53870 public function setOverwrite($overwrite)
53871 {
53872 $this->overwrite = (bool) $overwrite;
53873 }
53874
53875
53876
53877
53878
53879
53880
53881
53882 public function setProgress($step)
53883 {
53884 $step = (int) $step;
53885 if ($step < $this->step) {
53886 throw new LogicException('You can\'t regress the progress bar.');
53887 }
53888
53889 if ($this->max && $step > $this->max) {
53890 $this->max = $step;
53891 }
53892
53893 $prevPeriod = (int) ($this->step / $this->redrawFreq);
53894 $currPeriod = (int) ($step / $this->redrawFreq);
53895 $this->step = $step;
53896 $this->percent = $this->max ? (float) $this->step / $this->max : 0;
53897 if ($prevPeriod !== $currPeriod || $this->max === $step) {
53898 $this->display();
53899 }
53900 }
53901
53902
53903
53904
53905 public function finish()
53906 {
53907 if (!$this->max) {
53908 $this->max = $this->step;
53909 }
53910
53911 if ($this->step === $this->max && !$this->overwrite) {
53912
53913  return;
53914 }
53915
53916 $this->setProgress($this->max);
53917 }
53918
53919
53920
53921
53922 public function display()
53923 {
53924 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
53925 return;
53926 }
53927
53928 if (null === $this->format) {
53929 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
53930 }
53931
53932
53933  $self = $this;
53934 $output = $this->output;
53935 $messages = $this->messages;
53936 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
53937 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
53938 $text = call_user_func($formatter, $self, $output);
53939 } elseif (isset($messages[$matches[1]])) {
53940 $text = $messages[$matches[1]];
53941 } else {
53942 return $matches[0];
53943 }
53944
53945 if (isset($matches[2])) {
53946 $text = sprintf('%'.$matches[2], $text);
53947 }
53948
53949 return $text;
53950 }, $this->format));
53951 }
53952
53953
53954
53955
53956
53957
53958
53959
53960 public function clear()
53961 {
53962 if (!$this->overwrite) {
53963 return;
53964 }
53965
53966 if (null === $this->format) {
53967 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
53968 }
53969
53970 $this->overwrite('');
53971 }
53972
53973
53974
53975
53976
53977
53978 private function setRealFormat($format)
53979 {
53980
53981  if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
53982 $this->format = self::getFormatDefinition($format.'_nomax');
53983 } elseif (null !== self::getFormatDefinition($format)) {
53984 $this->format = self::getFormatDefinition($format);
53985 } else {
53986 $this->format = $format;
53987 }
53988
53989 $this->formatLineCount = substr_count($this->format, "\n");
53990 }
53991
53992
53993
53994
53995
53996
53997 private function setMaxSteps($max)
53998 {
53999 $this->max = max(0, (int) $max);
54000 $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
54001 }
54002
54003
54004
54005
54006
54007
54008 private function overwrite($message)
54009 {
54010 if ($this->overwrite) {
54011 if (!$this->firstRun) {
54012
54013  $this->output->write("\x0D");
54014
54015
54016  $this->output->write("\x1B[2K");
54017
54018
54019  if ($this->formatLineCount > 0) {
54020 $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
54021 }
54022 }
54023 } elseif ($this->step > 0) {
54024 $this->output->writeln('');
54025 }
54026
54027 $this->firstRun = false;
54028
54029 $this->output->write($message);
54030 }
54031
54032 private function determineBestFormat()
54033 {
54034 switch ($this->output->getVerbosity()) {
54035
54036  case OutputInterface::VERBOSITY_VERBOSE:
54037 return $this->max ? 'verbose' : 'verbose_nomax';
54038 case OutputInterface::VERBOSITY_VERY_VERBOSE:
54039 return $this->max ? 'very_verbose' : 'very_verbose_nomax';
54040 case OutputInterface::VERBOSITY_DEBUG:
54041 return $this->max ? 'debug' : 'debug_nomax';
54042 default:
54043 return $this->max ? 'normal' : 'normal_nomax';
54044 }
54045 }
54046
54047 private static function initPlaceholderFormatters()
54048 {
54049 return array(
54050 'bar' => function (ProgressBar $bar, OutputInterface $output) {
54051 $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
54052 $display = str_repeat($bar->getBarCharacter(), $completeBars);
54053 if ($completeBars < $bar->getBarWidth()) {
54054 $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
54055 $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
54056 }
54057
54058 return $display;
54059 },
54060 'elapsed' => function (ProgressBar $bar) {
54061 return Helper::formatTime(time() - $bar->getStartTime());
54062 },
54063 'remaining' => function (ProgressBar $bar) {
54064 if (!$bar->getMaxSteps()) {
54065 throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
54066 }
54067
54068 if (!$bar->getProgress()) {
54069 $remaining = 0;
54070 } else {
54071 $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
54072 }
54073
54074 return Helper::formatTime($remaining);
54075 },
54076 'estimated' => function (ProgressBar $bar) {
54077 if (!$bar->getMaxSteps()) {
54078 throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
54079 }
54080
54081 if (!$bar->getProgress()) {
54082 $estimated = 0;
54083 } else {
54084 $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
54085 }
54086
54087 return Helper::formatTime($estimated);
54088 },
54089 'memory' => function (ProgressBar $bar) {
54090 return Helper::formatMemory(memory_get_usage(true));
54091 },
54092 'current' => function (ProgressBar $bar) {
54093 return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
54094 },
54095 'max' => function (ProgressBar $bar) {
54096 return $bar->getMaxSteps();
54097 },
54098 'percent' => function (ProgressBar $bar) {
54099 return floor($bar->getProgressPercent() * 100);
54100 },
54101 );
54102 }
54103
54104 private static function initFormats()
54105 {
54106 return array(
54107 'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
54108 'normal_nomax' => ' %current% [%bar%]',
54109
54110 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
54111 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
54112
54113 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
54114 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
54115
54116 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
54117 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
54118 );
54119 }
54120 }
54121 <?php
54122
54123
54124
54125
54126
54127
54128
54129
54130
54131
54132 namespace Symfony\Component\Console\Helper;
54133
54134 use Symfony\Component\Console\Output\NullOutput;
54135 use Symfony\Component\Console\Output\ConsoleOutputInterface;
54136 use Symfony\Component\Console\Output\OutputInterface;
54137 use Symfony\Component\Console\Exception\LogicException;
54138
54139
54140
54141
54142
54143
54144
54145
54146
54147
54148 class ProgressHelper extends Helper
54149 {
54150 const FORMAT_QUIET = ' %percent%%';
54151 const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
54152 const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
54153 const FORMAT_QUIET_NOMAX = ' %current%';
54154 const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
54155 const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
54156
54157
54158  private $barWidth = 28;
54159 private $barChar = '=';
54160 private $emptyBarChar = '-';
54161 private $progressChar = '>';
54162 private $format = null;
54163 private $redrawFreq = 1;
54164
54165 private $lastMessagesLength;
54166 private $barCharOriginal;
54167
54168
54169
54170
54171 private $output;
54172
54173
54174
54175
54176
54177
54178 private $current;
54179
54180
54181
54182
54183
54184
54185 private $max;
54186
54187
54188
54189
54190
54191
54192 private $startTime;
54193
54194
54195
54196
54197
54198
54199 private $defaultFormatVars = array(
54200 'current',
54201 'max',
54202 'bar',
54203 'percent',
54204 'elapsed',
54205 );
54206
54207
54208
54209
54210
54211
54212 private $formatVars;
54213
54214
54215
54216
54217
54218
54219 private $widths = array(
54220 'current' => 4,
54221 'max' => 4,
54222 'percent' => 3,
54223 'elapsed' => 6,
54224 );
54225
54226
54227
54228
54229
54230
54231 private $timeFormats = array(
54232 array(0, '???'),
54233 array(2, '1 sec'),
54234 array(59, 'secs', 1),
54235 array(60, '1 min'),
54236 array(3600, 'mins', 60),
54237 array(5400, '1 hr'),
54238 array(86400, 'hrs', 3600),
54239 array(129600, '1 day'),
54240 array(604800, 'days', 86400),
54241 );
54242
54243 public function __construct($triggerDeprecationError = true)
54244 {
54245 if ($triggerDeprecationError) {
54246 @trigger_error('The '.__CLASS__.' class is deprecated since version 2.5 and will be removed in 3.0. Use the Symfony\Component\Console\Helper\ProgressBar class instead.', E_USER_DEPRECATED);
54247 }
54248 }
54249
54250
54251
54252
54253
54254
54255 public function setBarWidth($size)
54256 {
54257 $this->barWidth = (int) $size;
54258 }
54259
54260
54261
54262
54263
54264
54265 public function setBarCharacter($char)
54266 {
54267 $this->barChar = $char;
54268 }
54269
54270
54271
54272
54273
54274
54275 public function setEmptyBarCharacter($char)
54276 {
54277 $this->emptyBarChar = $char;
54278 }
54279
54280
54281
54282
54283
54284
54285 public function setProgressCharacter($char)
54286 {
54287 $this->progressChar = $char;
54288 }
54289
54290
54291
54292
54293
54294
54295 public function setFormat($format)
54296 {
54297 $this->format = $format;
54298 }
54299
54300
54301
54302
54303
54304
54305 public function setRedrawFrequency($freq)
54306 {
54307 $this->redrawFreq = (int) $freq;
54308 }
54309
54310
54311
54312
54313
54314
54315
54316 public function start(OutputInterface $output, $max = null)
54317 {
54318 if ($output instanceof ConsoleOutputInterface) {
54319 $output = $output->getErrorOutput();
54320 }
54321
54322 $this->startTime = time();
54323 $this->current = 0;
54324 $this->max = (int) $max;
54325
54326
54327  $this->output = $output->isDecorated() ? $output : new NullOutput();
54328 $this->lastMessagesLength = 0;
54329 $this->barCharOriginal = '';
54330
54331 if (null === $this->format) {
54332 switch ($output->getVerbosity()) {
54333 case OutputInterface::VERBOSITY_QUIET:
54334 $this->format = self::FORMAT_QUIET_NOMAX;
54335 if ($this->max > 0) {
54336 $this->format = self::FORMAT_QUIET;
54337 }
54338 break;
54339 case OutputInterface::VERBOSITY_VERBOSE:
54340 case OutputInterface::VERBOSITY_VERY_VERBOSE:
54341 case OutputInterface::VERBOSITY_DEBUG:
54342 $this->format = self::FORMAT_VERBOSE_NOMAX;
54343 if ($this->max > 0) {
54344 $this->format = self::FORMAT_VERBOSE;
54345 }
54346 break;
54347 default:
54348 $this->format = self::FORMAT_NORMAL_NOMAX;
54349 if ($this->max > 0) {
54350 $this->format = self::FORMAT_NORMAL;
54351 }
54352 break;
54353 }
54354 }
54355
54356 $this->initialize();
54357 }
54358
54359
54360
54361
54362
54363
54364
54365
54366
54367 public function advance($step = 1, $redraw = false)
54368 {
54369 $this->setCurrent($this->current + $step, $redraw);
54370 }
54371
54372
54373
54374
54375
54376
54377
54378
54379
54380 public function setCurrent($current, $redraw = false)
54381 {
54382 if (null === $this->startTime) {
54383 throw new LogicException('You must start the progress bar before calling setCurrent().');
54384 }
54385
54386 $current = (int) $current;
54387
54388 if ($current < $this->current) {
54389 throw new LogicException('You can\'t regress the progress bar');
54390 }
54391
54392 if (0 === $this->current) {
54393 $redraw = true;
54394 }
54395
54396 $prevPeriod = (int) ($this->current / $this->redrawFreq);
54397
54398 $this->current = $current;
54399
54400 $currPeriod = (int) ($this->current / $this->redrawFreq);
54401 if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
54402 $this->display();
54403 }
54404 }
54405
54406
54407
54408
54409
54410
54411
54412
54413 public function display($finish = false)
54414 {
54415 if (null === $this->startTime) {
54416 throw new LogicException('You must start the progress bar before calling display().');
54417 }
54418
54419 $message = $this->format;
54420 foreach ($this->generate($finish) as $name => $value) {
54421 $message = str_replace("%{$name}%", $value, $message);
54422 }
54423 $this->overwrite($this->output, $message);
54424 }
54425
54426
54427
54428
54429
54430
54431
54432
54433 public function clear()
54434 {
54435 $this->overwrite($this->output, '');
54436 }
54437
54438
54439
54440
54441 public function finish()
54442 {
54443 if (null === $this->startTime) {
54444 throw new LogicException('You must start the progress bar before calling finish().');
54445 }
54446
54447 if (null !== $this->startTime) {
54448 if (!$this->max) {
54449 $this->barChar = $this->barCharOriginal;
54450 $this->display(true);
54451 }
54452 $this->startTime = null;
54453 $this->output->writeln('');
54454 $this->output = null;
54455 }
54456 }
54457
54458
54459
54460
54461 private function initialize()
54462 {
54463 $this->formatVars = array();
54464 foreach ($this->defaultFormatVars as $var) {
54465 if (false !== strpos($this->format, "%{$var}%")) {
54466 $this->formatVars[$var] = true;
54467 }
54468 }
54469
54470 if ($this->max > 0) {
54471 $this->widths['max'] = $this->strlen($this->max);
54472 $this->widths['current'] = $this->widths['max'];
54473 } else {
54474 $this->barCharOriginal = $this->barChar;
54475 $this->barChar = $this->emptyBarChar;
54476 }
54477 }
54478
54479
54480
54481
54482
54483
54484
54485
54486 private function generate($finish = false)
54487 {
54488 $vars = array();
54489 $percent = 0;
54490 if ($this->max > 0) {
54491 $percent = (float) $this->current / $this->max;
54492 }
54493
54494 if (isset($this->formatVars['bar'])) {
54495 if ($this->max > 0) {
54496 $completeBars = floor($percent * $this->barWidth);
54497 } else {
54498 if (!$finish) {
54499 $completeBars = floor($this->current % $this->barWidth);
54500 } else {
54501 $completeBars = $this->barWidth;
54502 }
54503 }
54504
54505 $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
54506 $bar = str_repeat($this->barChar, $completeBars);
54507 if ($completeBars < $this->barWidth) {
54508 $bar .= $this->progressChar;
54509 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
54510 }
54511
54512 $vars['bar'] = $bar;
54513 }
54514
54515 if (isset($this->formatVars['elapsed'])) {
54516 $elapsed = time() - $this->startTime;
54517 $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
54518 }
54519
54520 if (isset($this->formatVars['current'])) {
54521 $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
54522 }
54523
54524 if (isset($this->formatVars['max'])) {
54525 $vars['max'] = $this->max;
54526 }
54527
54528 if (isset($this->formatVars['percent'])) {
54529 $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
54530 }
54531
54532 return $vars;
54533 }
54534
54535
54536
54537
54538
54539
54540
54541
54542 private function humaneTime($secs)
54543 {
54544 $text = '';
54545 foreach ($this->timeFormats as $format) {
54546 if ($secs < $format[0]) {
54547 if (2 == count($format)) {
54548 $text = $format[1];
54549 break;
54550 } else {
54551 $text = ceil($secs / $format[2]).' '.$format[1];
54552 break;
54553 }
54554 }
54555 }
54556
54557 return $text;
54558 }
54559
54560
54561
54562
54563
54564
54565
54566 private function overwrite(OutputInterface $output, $message)
54567 {
54568 $length = $this->strlen($message);
54569
54570
54571  if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
54572 $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
54573 }
54574
54575
54576  $output->write("\x0D");
54577 $output->write($message);
54578
54579 $this->lastMessagesLength = $this->strlen($message);
54580 }
54581
54582
54583
54584
54585 public function getName()
54586 {
54587 return 'progress';
54588 }
54589 }
54590 <?php
54591
54592
54593
54594
54595
54596
54597
54598
54599
54600
54601 namespace Symfony\Component\Console\Helper;
54602
54603 use Symfony\Component\Console\Exception\InvalidArgumentException;
54604 use Symfony\Component\Console\Exception\LogicException;
54605 use Symfony\Component\Console\Output\OutputInterface;
54606
54607
54608
54609
54610 class ProgressIndicator
54611 {
54612 private $output;
54613 private $startTime;
54614 private $format;
54615 private $message;
54616 private $indicatorValues;
54617 private $indicatorCurrent;
54618 private $indicatorChangeInterval;
54619 private $indicatorUpdateTime;
54620 private $started = false;
54621
54622 private static $formatters;
54623 private static $formats;
54624
54625
54626
54627
54628
54629
54630
54631 public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
54632 {
54633 $this->output = $output;
54634
54635 if (null === $format) {
54636 $format = $this->determineBestFormat();
54637 }
54638
54639 if (null === $indicatorValues) {
54640 $indicatorValues = array('-', '\\', '|', '/');
54641 }
54642
54643 $indicatorValues = array_values($indicatorValues);
54644
54645 if (2 > count($indicatorValues)) {
54646 throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
54647 }
54648
54649 $this->format = self::getFormatDefinition($format);
54650 $this->indicatorChangeInterval = $indicatorChangeInterval;
54651 $this->indicatorValues = $indicatorValues;
54652 $this->startTime = time();
54653 }
54654
54655
54656
54657
54658
54659
54660 public function setMessage($message)
54661 {
54662 $this->message = $message;
54663
54664 $this->display();
54665 }
54666
54667
54668
54669
54670
54671
54672
54673
54674 public function getMessage()
54675 {
54676 return $this->message;
54677 }
54678
54679
54680
54681
54682
54683
54684
54685
54686 public function getStartTime()
54687 {
54688 return $this->startTime;
54689 }
54690
54691
54692
54693
54694
54695
54696
54697
54698 public function getCurrentValue()
54699 {
54700 return $this->indicatorValues[$this->indicatorCurrent % count($this->indicatorValues)];
54701 }
54702
54703
54704
54705
54706
54707
54708 public function start($message)
54709 {
54710 if ($this->started) {
54711 throw new LogicException('Progress indicator already started.');
54712 }
54713
54714 $this->message = $message;
54715 $this->started = true;
54716 $this->startTime = time();
54717 $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
54718 $this->indicatorCurrent = 0;
54719
54720 $this->display();
54721 }
54722
54723
54724
54725
54726 public function advance()
54727 {
54728 if (!$this->started) {
54729 throw new LogicException('Progress indicator has not yet been started.');
54730 }
54731
54732 if (!$this->output->isDecorated()) {
54733 return;
54734 }
54735
54736 $currentTime = $this->getCurrentTimeInMilliseconds();
54737
54738 if ($currentTime < $this->indicatorUpdateTime) {
54739 return;
54740 }
54741
54742 $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
54743 ++$this->indicatorCurrent;
54744
54745 $this->display();
54746 }
54747
54748
54749
54750
54751
54752
54753 public function finish($message)
54754 {
54755 if (!$this->started) {
54756 throw new LogicException('Progress indicator has not yet been started.');
54757 }
54758
54759 $this->message = $message;
54760 $this->display();
54761 $this->output->writeln('');
54762 $this->started = false;
54763 }
54764
54765
54766
54767
54768
54769
54770
54771
54772 public static function getFormatDefinition($name)
54773 {
54774 if (!self::$formats) {
54775 self::$formats = self::initFormats();
54776 }
54777
54778 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
54779 }
54780
54781
54782
54783
54784
54785
54786
54787
54788
54789 public static function setPlaceholderFormatterDefinition($name, $callable)
54790 {
54791 if (!self::$formatters) {
54792 self::$formatters = self::initPlaceholderFormatters();
54793 }
54794
54795 self::$formatters[$name] = $callable;
54796 }
54797
54798
54799
54800
54801
54802
54803
54804
54805 public static function getPlaceholderFormatterDefinition($name)
54806 {
54807 if (!self::$formatters) {
54808 self::$formatters = self::initPlaceholderFormatters();
54809 }
54810
54811 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
54812 }
54813
54814 private function display()
54815 {
54816 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
54817 return;
54818 }
54819
54820 $self = $this;
54821
54822 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
54823 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
54824 return call_user_func($formatter, $self);
54825 }
54826
54827 return $matches[0];
54828 }, $this->format));
54829 }
54830
54831 private function determineBestFormat()
54832 {
54833 switch ($this->output->getVerbosity()) {
54834
54835  case OutputInterface::VERBOSITY_VERBOSE:
54836 return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
54837 case OutputInterface::VERBOSITY_VERY_VERBOSE:
54838 case OutputInterface::VERBOSITY_DEBUG:
54839 return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
54840 default:
54841 return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
54842 }
54843 }
54844
54845
54846
54847
54848
54849
54850 private function overwrite($message)
54851 {
54852 if ($this->output->isDecorated()) {
54853 $this->output->write("\x0D\x1B[2K");
54854 $this->output->write($message);
54855 } else {
54856 $this->output->writeln($message);
54857 }
54858 }
54859
54860 private function getCurrentTimeInMilliseconds()
54861 {
54862 return round(microtime(true) * 1000);
54863 }
54864
54865 private static function initPlaceholderFormatters()
54866 {
54867 return array(
54868 'indicator' => function (ProgressIndicator $indicator) {
54869 return $indicator->getCurrentValue();
54870 },
54871 'message' => function (ProgressIndicator $indicator) {
54872 return $indicator->getMessage();
54873 },
54874 'elapsed' => function (ProgressIndicator $indicator) {
54875 return Helper::formatTime(time() - $indicator->getStartTime());
54876 },
54877 'memory' => function () {
54878 return Helper::formatMemory(memory_get_usage(true));
54879 },
54880 );
54881 }
54882
54883 private static function initFormats()
54884 {
54885 return array(
54886 'normal' => ' %indicator% %message%',
54887 'normal_no_ansi' => ' %message%',
54888
54889 'verbose' => ' %indicator% %message% (%elapsed:6s%)',
54890 'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
54891
54892 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
54893 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
54894 );
54895 }
54896 }
54897 <?php
54898
54899
54900
54901
54902
54903
54904
54905
54906
54907
54908 namespace Symfony\Component\Console\Helper;
54909
54910 use Symfony\Component\Console\Exception\InvalidArgumentException;
54911 use Symfony\Component\Console\Exception\RuntimeException;
54912 use Symfony\Component\Console\Formatter\OutputFormatter;
54913 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
54914 use Symfony\Component\Console\Input\InputInterface;
54915 use Symfony\Component\Console\Output\ConsoleOutputInterface;
54916 use Symfony\Component\Console\Output\OutputInterface;
54917 use Symfony\Component\Console\Question\Question;
54918 use Symfony\Component\Console\Question\ChoiceQuestion;
54919
54920
54921
54922
54923
54924
54925 class QuestionHelper extends Helper
54926 {
54927 private $inputStream;
54928 private static $shell;
54929 private static $stty;
54930
54931
54932
54933
54934
54935
54936
54937
54938 public function ask(InputInterface $input, OutputInterface $output, Question $question)
54939 {
54940 if ($output instanceof ConsoleOutputInterface) {
54941 $output = $output->getErrorOutput();
54942 }
54943
54944 if (!$input->isInteractive()) {
54945 return $question->getDefault();
54946 }
54947
54948 if (!$question->getValidator()) {
54949 return $this->doAsk($output, $question);
54950 }
54951
54952 $that = $this;
54953
54954 $interviewer = function () use ($output, $question, $that) {
54955 return $that->doAsk($output, $question);
54956 };
54957
54958 return $this->validateAttempts($interviewer, $output, $question);
54959 }
54960
54961
54962
54963
54964
54965
54966
54967
54968
54969
54970 public function setInputStream($stream)
54971 {
54972 if (!is_resource($stream)) {
54973 throw new InvalidArgumentException('Input stream must be a valid resource.');
54974 }
54975
54976 $this->inputStream = $stream;
54977 }
54978
54979
54980
54981
54982
54983
54984 public function getInputStream()
54985 {
54986 return $this->inputStream;
54987 }
54988
54989
54990
54991
54992 public function getName()
54993 {
54994 return 'question';
54995 }
54996
54997
54998
54999
55000
55001
55002
55003
55004
55005
55006 public function doAsk(OutputInterface $output, Question $question)
55007 {
55008 $this->writePrompt($output, $question);
55009
55010 $inputStream = $this->inputStream ?: STDIN;
55011 $autocomplete = $question->getAutocompleterValues();
55012
55013 if (null === $autocomplete || !$this->hasSttyAvailable()) {
55014 $ret = false;
55015 if ($question->isHidden()) {
55016 try {
55017 $ret = trim($this->getHiddenResponse($output, $inputStream));
55018 } catch (RuntimeException $e) {
55019 if (!$question->isHiddenFallback()) {
55020 throw $e;
55021 }
55022 }
55023 }
55024
55025 if (false === $ret) {
55026 $ret = fgets($inputStream, 4096);
55027 if (false === $ret) {
55028 throw new RuntimeException('Aborted');
55029 }
55030 $ret = trim($ret);
55031 }
55032 } else {
55033 $ret = trim($this->autocomplete($output, $question, $inputStream, is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
55034 }
55035
55036 $ret = strlen($ret) > 0 ? $ret : $question->getDefault();
55037
55038 if ($normalizer = $question->getNormalizer()) {
55039 return $normalizer($ret);
55040 }
55041
55042 return $ret;
55043 }
55044
55045
55046
55047
55048 protected function writePrompt(OutputInterface $output, Question $question)
55049 {
55050 $message = $question->getQuestion();
55051
55052 if ($question instanceof ChoiceQuestion) {
55053 $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
55054
55055 $messages = (array) $question->getQuestion();
55056 foreach ($question->getChoices() as $key => $value) {
55057 $width = $maxWidth - $this->strlen($key);
55058 $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
55059 }
55060
55061 $output->writeln($messages);
55062
55063 $message = $question->getPrompt();
55064 }
55065
55066 $output->write($message);
55067 }
55068
55069
55070
55071
55072 protected function writeError(OutputInterface $output, \Exception $error)
55073 {
55074 if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
55075 $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
55076 } else {
55077 $message = '<error>'.$error->getMessage().'</error>';
55078 }
55079
55080 $output->writeln($message);
55081 }
55082
55083
55084
55085
55086
55087
55088
55089
55090
55091
55092
55093 private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete)
55094 {
55095 $ret = '';
55096
55097 $i = 0;
55098 $ofs = -1;
55099 $matches = $autocomplete;
55100 $numMatches = count($matches);
55101
55102 $sttyMode = shell_exec('stty -g');
55103
55104
55105  shell_exec('stty -icanon -echo');
55106
55107
55108  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
55109
55110
55111  while (!feof($inputStream)) {
55112 $c = fread($inputStream, 1);
55113
55114
55115  if ("\177" === $c) {
55116 if (0 === $numMatches && 0 !== $i) {
55117 --$i;
55118
55119  $output->write("\033[1D");
55120 }
55121
55122 if (0 === $i) {
55123 $ofs = -1;
55124 $matches = $autocomplete;
55125 $numMatches = count($matches);
55126 } else {
55127 $numMatches = 0;
55128 }
55129
55130
55131  $ret = substr($ret, 0, $i);
55132 } elseif ("\033" === $c) {
55133
55134  $c .= fread($inputStream, 2);
55135
55136
55137  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
55138 if ('A' === $c[2] && -1 === $ofs) {
55139 $ofs = 0;
55140 }
55141
55142 if (0 === $numMatches) {
55143 continue;
55144 }
55145
55146 $ofs += ('A' === $c[2]) ? -1 : 1;
55147 $ofs = ($numMatches + $ofs) % $numMatches;
55148 }
55149 } elseif (ord($c) < 32) {
55150 if ("\t" === $c || "\n" === $c) {
55151 if ($numMatches > 0 && -1 !== $ofs) {
55152 $ret = $matches[$ofs];
55153
55154  $output->write(substr($ret, $i));
55155 $i = strlen($ret);
55156 }
55157
55158 if ("\n" === $c) {
55159 $output->write($c);
55160 break;
55161 }
55162
55163 $numMatches = 0;
55164 }
55165
55166 continue;
55167 } else {
55168 $output->write($c);
55169 $ret .= $c;
55170 ++$i;
55171
55172 $numMatches = 0;
55173 $ofs = 0;
55174
55175 foreach ($autocomplete as $value) {
55176
55177  if (0 === strpos($value, $ret) && $i !== strlen($value)) {
55178 $matches[$numMatches++] = $value;
55179 }
55180 }
55181 }
55182
55183
55184  $output->write("\033[K");
55185
55186 if ($numMatches > 0 && -1 !== $ofs) {
55187
55188  $output->write("\0337");
55189
55190  $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>');
55191
55192  $output->write("\0338");
55193 }
55194 }
55195
55196
55197  shell_exec(sprintf('stty %s', $sttyMode));
55198
55199 return $ret;
55200 }
55201
55202
55203
55204
55205
55206
55207
55208
55209
55210
55211
55212 private function getHiddenResponse(OutputInterface $output, $inputStream)
55213 {
55214 if ('\\' === DIRECTORY_SEPARATOR) {
55215 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
55216
55217
55218  if ('phar:' === substr(__FILE__, 0, 5)) {
55219 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
55220 copy($exe, $tmpExe);
55221 $exe = $tmpExe;
55222 }
55223
55224 $value = rtrim(shell_exec($exe));
55225 $output->writeln('');
55226
55227 if (isset($tmpExe)) {
55228 unlink($tmpExe);
55229 }
55230
55231 return $value;
55232 }
55233
55234 if ($this->hasSttyAvailable()) {
55235 $sttyMode = shell_exec('stty -g');
55236
55237 shell_exec('stty -echo');
55238 $value = fgets($inputStream, 4096);
55239 shell_exec(sprintf('stty %s', $sttyMode));
55240
55241 if (false === $value) {
55242 throw new RuntimeException('Aborted');
55243 }
55244
55245 $value = trim($value);
55246 $output->writeln('');
55247
55248 return $value;
55249 }
55250
55251 if (false !== $shell = $this->getShell()) {
55252 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
55253 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
55254 $value = rtrim(shell_exec($command));
55255 $output->writeln('');
55256
55257 return $value;
55258 }
55259
55260 throw new RuntimeException('Unable to hide the response.');
55261 }
55262
55263
55264
55265
55266
55267
55268
55269
55270
55271
55272
55273
55274 private function validateAttempts($interviewer, OutputInterface $output, Question $question)
55275 {
55276 $error = null;
55277 $attempts = $question->getMaxAttempts();
55278 while (null === $attempts || $attempts--) {
55279 if (null !== $error) {
55280 $this->writeError($output, $error);
55281 }
55282
55283 try {
55284 return call_user_func($question->getValidator(), $interviewer());
55285 } catch (RuntimeException $e) {
55286 throw $e;
55287 } catch (\Exception $error) {
55288 }
55289 }
55290
55291 throw $error;
55292 }
55293
55294
55295
55296
55297
55298
55299 private function getShell()
55300 {
55301 if (null !== self::$shell) {
55302 return self::$shell;
55303 }
55304
55305 self::$shell = false;
55306
55307 if (file_exists('/usr/bin/env')) {
55308
55309  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
55310 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
55311 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
55312 self::$shell = $sh;
55313 break;
55314 }
55315 }
55316 }
55317
55318 return self::$shell;
55319 }
55320
55321
55322
55323
55324
55325
55326 private function hasSttyAvailable()
55327 {
55328 if (null !== self::$stty) {
55329 return self::$stty;
55330 }
55331
55332 exec('stty 2>&1', $output, $exitcode);
55333
55334 return self::$stty = 0 === $exitcode;
55335 }
55336 }
55337 <?php
55338
55339
55340
55341
55342
55343
55344
55345
55346
55347
55348 namespace Symfony\Component\Console\Helper;
55349
55350 use Symfony\Component\Console\Exception\LogicException;
55351 use Symfony\Component\Console\Input\InputInterface;
55352 use Symfony\Component\Console\Output\OutputInterface;
55353 use Symfony\Component\Console\Question\ChoiceQuestion;
55354 use Symfony\Component\Console\Question\ConfirmationQuestion;
55355 use Symfony\Component\Console\Question\Question;
55356 use Symfony\Component\Console\Style\SymfonyStyle;
55357 use Symfony\Component\Console\Formatter\OutputFormatter;
55358
55359
55360
55361
55362
55363
55364 class SymfonyQuestionHelper extends QuestionHelper
55365 {
55366
55367
55368
55369 public function ask(InputInterface $input, OutputInterface $output, Question $question)
55370 {
55371 $validator = $question->getValidator();
55372 $question->setValidator(function ($value) use ($validator) {
55373 if (null !== $validator) {
55374 $value = $validator($value);
55375 } else {
55376
55377  if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
55378 throw new LogicException('A value is required.');
55379 }
55380 }
55381
55382 return $value;
55383 });
55384
55385 return parent::ask($input, $output, $question);
55386 }
55387
55388
55389
55390
55391 protected function writePrompt(OutputInterface $output, Question $question)
55392 {
55393 $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
55394 $default = $question->getDefault();
55395
55396 switch (true) {
55397 case null === $default:
55398 $text = sprintf(' <info>%s</info>:', $text);
55399
55400 break;
55401
55402 case $question instanceof ConfirmationQuestion:
55403 $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
55404
55405 break;
55406
55407 case $question instanceof ChoiceQuestion && $question->isMultiselect():
55408 $choices = $question->getChoices();
55409 $default = explode(',', $default);
55410
55411 foreach ($default as $key => $value) {
55412 $default[$key] = $choices[trim($value)];
55413 }
55414
55415 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
55416
55417 break;
55418
55419 case $question instanceof ChoiceQuestion:
55420 $choices = $question->getChoices();
55421 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default]));
55422
55423 break;
55424
55425 default:
55426 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
55427 }
55428
55429 $output->writeln($text);
55430
55431 if ($question instanceof ChoiceQuestion) {
55432 $width = max(array_map('strlen', array_keys($question->getChoices())));
55433
55434 foreach ($question->getChoices() as $key => $value) {
55435 $output->writeln(sprintf("  [<comment>%-${width}s</comment>] %s", $key, $value));
55436 }
55437 }
55438
55439 $output->write(' > ');
55440 }
55441
55442
55443
55444
55445 protected function writeError(OutputInterface $output, \Exception $error)
55446 {
55447 if ($output instanceof SymfonyStyle) {
55448 $output->newLine();
55449 $output->error($error->getMessage());
55450
55451 return;
55452 }
55453
55454 parent::writeError($output, $error);
55455 }
55456 }
55457 <?php
55458
55459
55460
55461
55462
55463
55464
55465
55466
55467
55468 namespace Symfony\Component\Console\Helper;
55469
55470 use Symfony\Component\Console\Output\OutputInterface;
55471 use Symfony\Component\Console\Exception\InvalidArgumentException;
55472
55473
55474
55475
55476
55477
55478
55479
55480
55481 class Table
55482 {
55483
55484
55485
55486 private $headers = array();
55487
55488
55489
55490
55491 private $rows = array();
55492
55493
55494
55495
55496 private $columnWidths = array();
55497
55498
55499
55500
55501
55502
55503 private $numberOfColumns;
55504
55505
55506
55507
55508 private $output;
55509
55510
55511
55512
55513 private $style;
55514
55515
55516
55517
55518 private $columnStyles = array();
55519
55520 private static $styles;
55521
55522 public function __construct(OutputInterface $output)
55523 {
55524 $this->output = $output;
55525
55526 if (!self::$styles) {
55527 self::$styles = self::initStyles();
55528 }
55529
55530 $this->setStyle('default');
55531 }
55532
55533
55534
55535
55536
55537
55538
55539 public static function setStyleDefinition($name, TableStyle $style)
55540 {
55541 if (!self::$styles) {
55542 self::$styles = self::initStyles();
55543 }
55544
55545 self::$styles[$name] = $style;
55546 }
55547
55548
55549
55550
55551
55552
55553
55554
55555 public static function getStyleDefinition($name)
55556 {
55557 if (!self::$styles) {
55558 self::$styles = self::initStyles();
55559 }
55560
55561 if (isset(self::$styles[$name])) {
55562 return self::$styles[$name];
55563 }
55564
55565 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
55566 }
55567
55568
55569
55570
55571
55572
55573
55574
55575 public function setStyle($name)
55576 {
55577 $this->style = $this->resolveStyle($name);
55578
55579 return $this;
55580 }
55581
55582
55583
55584
55585
55586
55587 public function getStyle()
55588 {
55589 return $this->style;
55590 }
55591
55592
55593
55594
55595
55596
55597
55598
55599
55600 public function setColumnStyle($columnIndex, $name)
55601 {
55602 $columnIndex = (int) $columnIndex;
55603
55604 $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
55605
55606 return $this;
55607 }
55608
55609
55610
55611
55612
55613
55614
55615
55616
55617
55618 public function getColumnStyle($columnIndex)
55619 {
55620 if (isset($this->columnStyles[$columnIndex])) {
55621 return $this->columnStyles[$columnIndex];
55622 }
55623
55624 return $this->getStyle();
55625 }
55626
55627 public function setHeaders(array $headers)
55628 {
55629 $headers = array_values($headers);
55630 if (!empty($headers) && !is_array($headers[0])) {
55631 $headers = array($headers);
55632 }
55633
55634 $this->headers = $headers;
55635
55636 return $this;
55637 }
55638
55639 public function setRows(array $rows)
55640 {
55641 $this->rows = array();
55642
55643 return $this->addRows($rows);
55644 }
55645
55646 public function addRows(array $rows)
55647 {
55648 foreach ($rows as $row) {
55649 $this->addRow($row);
55650 }
55651
55652 return $this;
55653 }
55654
55655 public function addRow($row)
55656 {
55657 if ($row instanceof TableSeparator) {
55658 $this->rows[] = $row;
55659
55660 return $this;
55661 }
55662
55663 if (!is_array($row)) {
55664 throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
55665 }
55666
55667 $this->rows[] = array_values($row);
55668
55669 return $this;
55670 }
55671
55672 public function setRow($column, array $row)
55673 {
55674 $this->rows[$column] = $row;
55675
55676 return $this;
55677 }
55678
55679
55680
55681
55682
55683
55684
55685
55686
55687
55688
55689
55690
55691 public function render()
55692 {
55693 $this->calculateNumberOfColumns();
55694 $rows = $this->buildTableRows($this->rows);
55695 $headers = $this->buildTableRows($this->headers);
55696
55697 $this->calculateColumnsWidth(array_merge($headers, $rows));
55698
55699 $this->renderRowSeparator();
55700 if (!empty($headers)) {
55701 foreach ($headers as $header) {
55702 $this->renderRow($header, $this->style->getCellHeaderFormat());
55703 $this->renderRowSeparator();
55704 }
55705 }
55706 foreach ($rows as $row) {
55707 if ($row instanceof TableSeparator) {
55708 $this->renderRowSeparator();
55709 } else {
55710 $this->renderRow($row, $this->style->getCellRowFormat());
55711 }
55712 }
55713 if (!empty($rows)) {
55714 $this->renderRowSeparator();
55715 }
55716
55717 $this->cleanup();
55718 }
55719
55720
55721
55722
55723
55724
55725 private function renderRowSeparator()
55726 {
55727 if (0 === $count = $this->numberOfColumns) {
55728 return;
55729 }
55730
55731 if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
55732 return;
55733 }
55734
55735 $markup = $this->style->getCrossingChar();
55736 for ($column = 0; $column < $count; ++$column) {
55737 $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
55738 }
55739
55740 $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
55741 }
55742
55743
55744
55745
55746 private function renderColumnSeparator()
55747 {
55748 return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
55749 }
55750
55751
55752
55753
55754
55755
55756
55757
55758
55759 private function renderRow(array $row, $cellFormat)
55760 {
55761 if (empty($row)) {
55762 return;
55763 }
55764
55765 $rowContent = $this->renderColumnSeparator();
55766 foreach ($this->getRowColumns($row) as $column) {
55767 $rowContent .= $this->renderCell($row, $column, $cellFormat);
55768 $rowContent .= $this->renderColumnSeparator();
55769 }
55770 $this->output->writeln($rowContent);
55771 }
55772
55773
55774
55775
55776
55777
55778
55779
55780 private function renderCell(array $row, $column, $cellFormat)
55781 {
55782 $cell = isset($row[$column]) ? $row[$column] : '';
55783 $width = $this->columnWidths[$column];
55784 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
55785
55786  foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
55787 $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
55788 }
55789 }
55790
55791
55792  if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
55793 $width += strlen($cell) - mb_strwidth($cell, $encoding);
55794 }
55795
55796 $style = $this->getColumnStyle($column);
55797
55798 if ($cell instanceof TableSeparator) {
55799 return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
55800 }
55801
55802 $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
55803 $content = sprintf($style->getCellRowContentFormat(), $cell);
55804
55805 return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
55806 }
55807
55808
55809
55810
55811 private function calculateNumberOfColumns()
55812 {
55813 if (null !== $this->numberOfColumns) {
55814 return;
55815 }
55816
55817 $columns = array(0);
55818 foreach (array_merge($this->headers, $this->rows) as $row) {
55819 if ($row instanceof TableSeparator) {
55820 continue;
55821 }
55822
55823 $columns[] = $this->getNumberOfColumns($row);
55824 }
55825
55826 $this->numberOfColumns = max($columns);
55827 }
55828
55829 private function buildTableRows($rows)
55830 {
55831 $unmergedRows = array();
55832 for ($rowKey = 0; $rowKey < count($rows); ++$rowKey) {
55833 $rows = $this->fillNextRows($rows, $rowKey);
55834
55835
55836  foreach ($rows[$rowKey] as $column => $cell) {
55837 if (!strstr($cell, "\n")) {
55838 continue;
55839 }
55840 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
55841 foreach ($lines as $lineKey => $line) {
55842 if ($cell instanceof TableCell) {
55843 $line = new TableCell($line, array('colspan' => $cell->getColspan()));
55844 }
55845 if (0 === $lineKey) {
55846 $rows[$rowKey][$column] = $line;
55847 } else {
55848 $unmergedRows[$rowKey][$lineKey][$column] = $line;
55849 }
55850 }
55851 }
55852 }
55853
55854 $tableRows = array();
55855 foreach ($rows as $rowKey => $row) {
55856 $tableRows[] = $this->fillCells($row);
55857 if (isset($unmergedRows[$rowKey])) {
55858 $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
55859 }
55860 }
55861
55862 return $tableRows;
55863 }
55864
55865
55866
55867
55868
55869
55870
55871
55872
55873 private function fillNextRows(array $rows, $line)
55874 {
55875 $unmergedRows = array();
55876 foreach ($rows[$line] as $column => $cell) {
55877 if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
55878 $nbLines = $cell->getRowspan() - 1;
55879 $lines = array($cell);
55880 if (strstr($cell, "\n")) {
55881 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
55882 $nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
55883
55884 $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
55885 unset($lines[0]);
55886 }
55887
55888
55889  $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
55890 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
55891 $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
55892 $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
55893 if ($nbLines === $unmergedRowKey - $line) {
55894 break;
55895 }
55896 }
55897 }
55898 }
55899
55900 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
55901
55902  if (isset($rows[$unmergedRowKey]) && is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
55903 foreach ($unmergedRow as $cellKey => $cell) {
55904
55905  array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
55906 }
55907 } else {
55908 $row = $this->copyRow($rows, $unmergedRowKey - 1);
55909 foreach ($unmergedRow as $column => $cell) {
55910 if (!empty($cell)) {
55911 $row[$column] = $unmergedRow[$column];
55912 }
55913 }
55914 array_splice($rows, $unmergedRowKey, 0, array($row));
55915 }
55916 }
55917
55918 return $rows;
55919 }
55920
55921
55922
55923
55924
55925
55926 private function fillCells($row)
55927 {
55928 $newRow = array();
55929 foreach ($row as $column => $cell) {
55930 $newRow[] = $cell;
55931 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
55932 foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
55933
55934  $newRow[] = '';
55935 }
55936 }
55937 }
55938
55939 return $newRow ?: $row;
55940 }
55941
55942
55943
55944
55945
55946
55947
55948 private function copyRow(array $rows, $line)
55949 {
55950 $row = $rows[$line];
55951 foreach ($row as $cellKey => $cellValue) {
55952 $row[$cellKey] = '';
55953 if ($cellValue instanceof TableCell) {
55954 $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
55955 }
55956 }
55957
55958 return $row;
55959 }
55960
55961
55962
55963
55964
55965
55966 private function getNumberOfColumns(array $row)
55967 {
55968 $columns = count($row);
55969 foreach ($row as $column) {
55970 $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
55971 }
55972
55973 return $columns;
55974 }
55975
55976
55977
55978
55979
55980
55981 private function getRowColumns(array $row)
55982 {
55983 $columns = range(0, $this->numberOfColumns - 1);
55984 foreach ($row as $cellKey => $cell) {
55985 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
55986
55987  $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
55988 }
55989 }
55990
55991 return $columns;
55992 }
55993
55994
55995
55996
55997
55998
55999 private function calculateColumnsWidth($rows)
56000 {
56001 for ($column = 0; $column < $this->numberOfColumns; ++$column) {
56002 $lengths = array();
56003 foreach ($rows as $row) {
56004 if ($row instanceof TableSeparator) {
56005 continue;
56006 }
56007
56008 foreach ($row as $i => $cell) {
56009 if ($cell instanceof TableCell) {
56010 $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
56011 $textLength = Helper::strlen($textContent);
56012 if ($textLength > 0) {
56013 $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
56014 foreach ($contentColumns as $position => $content) {
56015 $row[$i + $position] = $content;
56016 }
56017 }
56018 }
56019 }
56020
56021 $lengths[] = $this->getCellWidth($row, $column);
56022 }
56023
56024 $this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
56025 }
56026 }
56027
56028
56029
56030
56031
56032
56033 private function getColumnSeparatorWidth()
56034 {
56035 return strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
56036 }
56037
56038
56039
56040
56041
56042
56043
56044
56045
56046 private function getCellWidth(array $row, $column)
56047 {
56048 if (isset($row[$column])) {
56049 $cell = $row[$column];
56050 $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
56051
56052 return $cellWidth;
56053 }
56054
56055 return 0;
56056 }
56057
56058
56059
56060
56061 private function cleanup()
56062 {
56063 $this->columnWidths = array();
56064 $this->numberOfColumns = null;
56065 }
56066
56067 private static function initStyles()
56068 {
56069 $borderless = new TableStyle();
56070 $borderless
56071 ->setHorizontalBorderChar('=')
56072 ->setVerticalBorderChar(' ')
56073 ->setCrossingChar(' ')
56074 ;
56075
56076 $compact = new TableStyle();
56077 $compact
56078 ->setHorizontalBorderChar('')
56079 ->setVerticalBorderChar(' ')
56080 ->setCrossingChar('')
56081 ->setCellRowContentFormat('%s')
56082 ;
56083
56084 $styleGuide = new TableStyle();
56085 $styleGuide
56086 ->setHorizontalBorderChar('-')
56087 ->setVerticalBorderChar(' ')
56088 ->setCrossingChar(' ')
56089 ->setCellHeaderFormat('%s')
56090 ;
56091
56092 return array(
56093 'default' => new TableStyle(),
56094 'borderless' => $borderless,
56095 'compact' => $compact,
56096 'symfony-style-guide' => $styleGuide,
56097 );
56098 }
56099
56100 private function resolveStyle($name)
56101 {
56102 if ($name instanceof TableStyle) {
56103 return $name;
56104 }
56105
56106 if (isset(self::$styles[$name])) {
56107 return self::$styles[$name];
56108 }
56109
56110 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
56111 }
56112 }
56113 <?php
56114
56115
56116
56117
56118
56119
56120
56121
56122
56123
56124 namespace Symfony\Component\Console\Helper;
56125
56126 use Symfony\Component\Console\Exception\InvalidArgumentException;
56127
56128
56129
56130
56131 class TableCell
56132 {
56133 private $value;
56134 private $options = array(
56135 'rowspan' => 1,
56136 'colspan' => 1,
56137 );
56138
56139
56140
56141
56142
56143 public function __construct($value = '', array $options = array())
56144 {
56145 if (is_numeric($value) && !is_string($value)) {
56146 $value = (string) $value;
56147 }
56148
56149 $this->value = $value;
56150
56151
56152  if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
56153 throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
56154 }
56155
56156 $this->options = array_merge($this->options, $options);
56157 }
56158
56159
56160
56161
56162
56163
56164 public function __toString()
56165 {
56166 return $this->value;
56167 }
56168
56169
56170
56171
56172
56173
56174 public function getColspan()
56175 {
56176 return (int) $this->options['colspan'];
56177 }
56178
56179
56180
56181
56182
56183
56184 public function getRowspan()
56185 {
56186 return (int) $this->options['rowspan'];
56187 }
56188 }
56189 <?php
56190
56191
56192
56193
56194
56195
56196
56197
56198
56199
56200 namespace Symfony\Component\Console\Helper;
56201
56202 use Symfony\Component\Console\Output\OutputInterface;
56203 use Symfony\Component\Console\Output\NullOutput;
56204 use Symfony\Component\Console\Exception\InvalidArgumentException;
56205
56206
56207
56208
56209
56210
56211
56212
56213
56214
56215 class TableHelper extends Helper
56216 {
56217 const LAYOUT_DEFAULT = 0;
56218 const LAYOUT_BORDERLESS = 1;
56219 const LAYOUT_COMPACT = 2;
56220
56221 private $table;
56222
56223 public function __construct($triggerDeprecationError = true)
56224 {
56225 if ($triggerDeprecationError) {
56226 @trigger_error('The '.__CLASS__.' class is deprecated since version 2.5 and will be removed in 3.0. Use the Symfony\Component\Console\Helper\Table class instead.', E_USER_DEPRECATED);
56227 }
56228
56229 $this->table = new Table(new NullOutput());
56230 }
56231
56232
56233
56234
56235
56236
56237
56238
56239
56240
56241 public function setLayout($layout)
56242 {
56243 switch ($layout) {
56244 case self::LAYOUT_BORDERLESS:
56245 $this->table->setStyle('borderless');
56246 break;
56247
56248 case self::LAYOUT_COMPACT:
56249 $this->table->setStyle('compact');
56250 break;
56251
56252 case self::LAYOUT_DEFAULT:
56253 $this->table->setStyle('default');
56254 break;
56255
56256 default:
56257 throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
56258 }
56259
56260 return $this;
56261 }
56262
56263 public function setHeaders(array $headers)
56264 {
56265 $this->table->setHeaders($headers);
56266
56267 return $this;
56268 }
56269
56270 public function setRows(array $rows)
56271 {
56272 $this->table->setRows($rows);
56273
56274 return $this;
56275 }
56276
56277 public function addRows(array $rows)
56278 {
56279 $this->table->addRows($rows);
56280
56281 return $this;
56282 }
56283
56284 public function addRow(array $row)
56285 {
56286 $this->table->addRow($row);
56287
56288 return $this;
56289 }
56290
56291 public function setRow($column, array $row)
56292 {
56293 $this->table->setRow($column, $row);
56294
56295 return $this;
56296 }
56297
56298
56299
56300
56301
56302
56303
56304
56305 public function setPaddingChar($paddingChar)
56306 {
56307 $this->table->getStyle()->setPaddingChar($paddingChar);
56308
56309 return $this;
56310 }
56311
56312
56313
56314
56315
56316
56317
56318
56319 public function setHorizontalBorderChar($horizontalBorderChar)
56320 {
56321 $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
56322
56323 return $this;
56324 }
56325
56326
56327
56328
56329
56330
56331
56332
56333 public function setVerticalBorderChar($verticalBorderChar)
56334 {
56335 $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
56336
56337 return $this;
56338 }
56339
56340
56341
56342
56343
56344
56345
56346
56347 public function setCrossingChar($crossingChar)
56348 {
56349 $this->table->getStyle()->setCrossingChar($crossingChar);
56350
56351 return $this;
56352 }
56353
56354
56355
56356
56357
56358
56359
56360
56361 public function setCellHeaderFormat($cellHeaderFormat)
56362 {
56363 $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
56364
56365 return $this;
56366 }
56367
56368
56369
56370
56371
56372
56373
56374
56375 public function setCellRowFormat($cellRowFormat)
56376 {
56377 $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
56378
56379 return $this;
56380 }
56381
56382
56383
56384
56385
56386
56387
56388
56389 public function setCellRowContentFormat($cellRowContentFormat)
56390 {
56391 $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
56392
56393 return $this;
56394 }
56395
56396
56397
56398
56399
56400
56401
56402
56403 public function setBorderFormat($borderFormat)
56404 {
56405 $this->table->getStyle()->setBorderFormat($borderFormat);
56406
56407 return $this;
56408 }
56409
56410
56411
56412
56413
56414
56415
56416
56417 public function setPadType($padType)
56418 {
56419 $this->table->getStyle()->setPadType($padType);
56420
56421 return $this;
56422 }
56423
56424
56425
56426
56427
56428
56429
56430
56431
56432
56433
56434
56435
56436 public function render(OutputInterface $output)
56437 {
56438 $p = new \ReflectionProperty($this->table, 'output');
56439 $p->setAccessible(true);
56440 $p->setValue($this->table, $output);
56441
56442 $this->table->render();
56443 }
56444
56445
56446
56447
56448 public function getName()
56449 {
56450 return 'table';
56451 }
56452 }
56453 <?php
56454
56455
56456
56457
56458
56459
56460
56461
56462
56463
56464 namespace Symfony\Component\Console\Helper;
56465
56466
56467
56468
56469
56470
56471 class TableSeparator extends TableCell
56472 {
56473 public function __construct(array $options = array())
56474 {
56475 parent::__construct('', $options);
56476 }
56477 }
56478 <?php
56479
56480
56481
56482
56483
56484
56485
56486
56487
56488
56489 namespace Symfony\Component\Console\Helper;
56490
56491 use Symfony\Component\Console\Exception\InvalidArgumentException;
56492 use Symfony\Component\Console\Exception\LogicException;
56493
56494
56495
56496
56497
56498
56499
56500 class TableStyle
56501 {
56502 private $paddingChar = ' ';
56503 private $horizontalBorderChar = '-';
56504 private $verticalBorderChar = '|';
56505 private $crossingChar = '+';
56506 private $cellHeaderFormat = '<info>%s</info>';
56507 private $cellRowFormat = '%s';
56508 private $cellRowContentFormat = ' %s ';
56509 private $borderFormat = '%s';
56510 private $padType = STR_PAD_RIGHT;
56511
56512
56513
56514
56515
56516
56517
56518
56519 public function setPaddingChar($paddingChar)
56520 {
56521 if (!$paddingChar) {
56522 throw new LogicException('The padding char must not be empty');
56523 }
56524
56525 $this->paddingChar = $paddingChar;
56526
56527 return $this;
56528 }
56529
56530
56531
56532
56533
56534
56535 public function getPaddingChar()
56536 {
56537 return $this->paddingChar;
56538 }
56539
56540
56541
56542
56543
56544
56545
56546
56547 public function setHorizontalBorderChar($horizontalBorderChar)
56548 {
56549 $this->horizontalBorderChar = $horizontalBorderChar;
56550
56551 return $this;
56552 }
56553
56554
56555
56556
56557
56558
56559 public function getHorizontalBorderChar()
56560 {
56561 return $this->horizontalBorderChar;
56562 }
56563
56564
56565
56566
56567
56568
56569
56570
56571 public function setVerticalBorderChar($verticalBorderChar)
56572 {
56573 $this->verticalBorderChar = $verticalBorderChar;
56574
56575 return $this;
56576 }
56577
56578
56579
56580
56581
56582
56583 public function getVerticalBorderChar()
56584 {
56585 return $this->verticalBorderChar;
56586 }
56587
56588
56589
56590
56591
56592
56593
56594
56595 public function setCrossingChar($crossingChar)
56596 {
56597 $this->crossingChar = $crossingChar;
56598
56599 return $this;
56600 }
56601
56602
56603
56604
56605
56606
56607 public function getCrossingChar()
56608 {
56609 return $this->crossingChar;
56610 }
56611
56612
56613
56614
56615
56616
56617
56618
56619 public function setCellHeaderFormat($cellHeaderFormat)
56620 {
56621 $this->cellHeaderFormat = $cellHeaderFormat;
56622
56623 return $this;
56624 }
56625
56626
56627
56628
56629
56630
56631 public function getCellHeaderFormat()
56632 {
56633 return $this->cellHeaderFormat;
56634 }
56635
56636
56637
56638
56639
56640
56641
56642
56643 public function setCellRowFormat($cellRowFormat)
56644 {
56645 $this->cellRowFormat = $cellRowFormat;
56646
56647 return $this;
56648 }
56649
56650
56651
56652
56653
56654
56655 public function getCellRowFormat()
56656 {
56657 return $this->cellRowFormat;
56658 }
56659
56660
56661
56662
56663
56664
56665
56666
56667 public function setCellRowContentFormat($cellRowContentFormat)
56668 {
56669 $this->cellRowContentFormat = $cellRowContentFormat;
56670
56671 return $this;
56672 }
56673
56674
56675
56676
56677
56678
56679 public function getCellRowContentFormat()
56680 {
56681 return $this->cellRowContentFormat;
56682 }
56683
56684
56685
56686
56687
56688
56689
56690
56691 public function setBorderFormat($borderFormat)
56692 {
56693 $this->borderFormat = $borderFormat;
56694
56695 return $this;
56696 }
56697
56698
56699
56700
56701
56702
56703 public function getBorderFormat()
56704 {
56705 return $this->borderFormat;
56706 }
56707
56708
56709
56710
56711
56712
56713
56714
56715 public function setPadType($padType)
56716 {
56717 if (!in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
56718 throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
56719 }
56720
56721 $this->padType = $padType;
56722
56723 return $this;
56724 }
56725
56726
56727
56728
56729
56730
56731 public function getPadType()
56732 {
56733 return $this->padType;
56734 }
56735 }
56736 <?php
56737
56738
56739
56740
56741
56742
56743
56744
56745
56746
56747 namespace Symfony\Component\Console\Input;
56748
56749 use Symfony\Component\Console\Exception\RuntimeException;
56750
56751
56752
56753
56754
56755
56756
56757
56758
56759
56760
56761
56762
56763
56764
56765
56766
56767
56768
56769
56770
56771
56772
56773
56774
56775
56776 class ArgvInput extends Input
56777 {
56778 private $tokens;
56779 private $parsed;
56780
56781
56782
56783
56784
56785 public function __construct(array $argv = null, InputDefinition $definition = null)
56786 {
56787 if (null === $argv) {
56788 $argv = $_SERVER['argv'];
56789 }
56790
56791
56792  array_shift($argv);
56793
56794 $this->tokens = $argv;
56795
56796 parent::__construct($definition);
56797 }
56798
56799 protected function setTokens(array $tokens)
56800 {
56801 $this->tokens = $tokens;
56802 }
56803
56804
56805
56806
56807 protected function parse()
56808 {
56809 $parseOptions = true;
56810 $this->parsed = $this->tokens;
56811 while (null !== $token = array_shift($this->parsed)) {
56812 if ($parseOptions && '' == $token) {
56813 $this->parseArgument($token);
56814 } elseif ($parseOptions && '--' == $token) {
56815 $parseOptions = false;
56816 } elseif ($parseOptions && 0 === strpos($token, '--')) {
56817 $this->parseLongOption($token);
56818 } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
56819 $this->parseShortOption($token);
56820 } else {
56821 $this->parseArgument($token);
56822 }
56823 }
56824 }
56825
56826
56827
56828
56829
56830
56831 private function parseShortOption($token)
56832 {
56833 $name = substr($token, 1);
56834
56835 if (strlen($name) > 1) {
56836 if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
56837
56838  $this->addShortOption($name[0], substr($name, 1));
56839 } else {
56840 $this->parseShortOptionSet($name);
56841 }
56842 } else {
56843 $this->addShortOption($name, null);
56844 }
56845 }
56846
56847
56848
56849
56850
56851
56852
56853
56854 private function parseShortOptionSet($name)
56855 {
56856 $len = strlen($name);
56857 for ($i = 0; $i < $len; ++$i) {
56858 if (!$this->definition->hasShortcut($name[$i])) {
56859 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
56860 }
56861
56862 $option = $this->definition->getOptionForShortcut($name[$i]);
56863 if ($option->acceptValue()) {
56864 $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
56865
56866 break;
56867 } else {
56868 $this->addLongOption($option->getName(), null);
56869 }
56870 }
56871 }
56872
56873
56874
56875
56876
56877
56878 private function parseLongOption($token)
56879 {
56880 $name = substr($token, 2);
56881
56882 if (false !== $pos = strpos($name, '=')) {
56883 if (0 === strlen($value = substr($name, $pos + 1))) {
56884 array_unshift($this->parsed, null);
56885 }
56886 $this->addLongOption(substr($name, 0, $pos), $value);
56887 } else {
56888 $this->addLongOption($name, null);
56889 }
56890 }
56891
56892
56893
56894
56895
56896
56897
56898
56899 private function parseArgument($token)
56900 {
56901 $c = count($this->arguments);
56902
56903
56904  if ($this->definition->hasArgument($c)) {
56905 $arg = $this->definition->getArgument($c);
56906 $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
56907
56908
56909  } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
56910 $arg = $this->definition->getArgument($c - 1);
56911 $this->arguments[$arg->getName()][] = $token;
56912
56913
56914  } else {
56915 $all = $this->definition->getArguments();
56916 if (count($all)) {
56917 throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
56918 }
56919
56920 throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
56921 }
56922 }
56923
56924
56925
56926
56927
56928
56929
56930
56931
56932 private function addShortOption($shortcut, $value)
56933 {
56934 if (!$this->definition->hasShortcut($shortcut)) {
56935 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
56936 }
56937
56938 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
56939 }
56940
56941
56942
56943
56944
56945
56946
56947
56948
56949 private function addLongOption($name, $value)
56950 {
56951 if (!$this->definition->hasOption($name)) {
56952 throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
56953 }
56954
56955 $option = $this->definition->getOption($name);
56956
56957
56958  if (!isset($value[0])) {
56959 $value = null;
56960 }
56961
56962 if (null !== $value && !$option->acceptValue()) {
56963 throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
56964 }
56965
56966 if (null === $value && $option->acceptValue() && count($this->parsed)) {
56967
56968  
56969  $next = array_shift($this->parsed);
56970 if (isset($next[0]) && '-' !== $next[0]) {
56971 $value = $next;
56972 } elseif (empty($next)) {
56973 $value = null;
56974 } else {
56975 array_unshift($this->parsed, $next);
56976 }
56977 }
56978
56979 if (null === $value) {
56980 if ($option->isValueRequired()) {
56981 throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
56982 }
56983
56984 if (!$option->isArray()) {
56985 $value = $option->isValueOptional() ? $option->getDefault() : true;
56986 }
56987 }
56988
56989 if ($option->isArray()) {
56990 $this->options[$name][] = $value;
56991 } else {
56992 $this->options[$name] = $value;
56993 }
56994 }
56995
56996
56997
56998
56999 public function getFirstArgument()
57000 {
57001 foreach ($this->tokens as $token) {
57002 if ($token && '-' === $token[0]) {
57003 continue;
57004 }
57005
57006 return $token;
57007 }
57008 }
57009
57010
57011
57012
57013 public function hasParameterOption($values)
57014 {
57015 $values = (array) $values;
57016
57017 foreach ($this->tokens as $token) {
57018 foreach ($values as $value) {
57019 if ($token === $value || 0 === strpos($token, $value.'=')) {
57020 return true;
57021 }
57022
57023 if (0 === strpos($token, '-') && 0 !== strpos($token, '--')) {
57024 $searchableToken = str_replace('-', '', $token);
57025 $searchableValue = str_replace('-', '', $value);
57026 if ('' !== $searchableToken && '' !== $searchableValue && false !== strpos($searchableToken, $searchableValue)) {
57027 return true;
57028 }
57029 }
57030 }
57031 }
57032
57033 return false;
57034 }
57035
57036
57037
57038
57039 public function getParameterOption($values, $default = false)
57040 {
57041 $values = (array) $values;
57042 $tokens = $this->tokens;
57043
57044 while (0 < count($tokens)) {
57045 $token = array_shift($tokens);
57046
57047 foreach ($values as $value) {
57048 if ($token === $value || 0 === strpos($token, $value.'=')) {
57049 if (false !== $pos = strpos($token, '=')) {
57050 return substr($token, $pos + 1);
57051 }
57052
57053 return array_shift($tokens);
57054 }
57055 }
57056 }
57057
57058 return $default;
57059 }
57060
57061
57062
57063
57064
57065
57066 public function __toString()
57067 {
57068 $self = $this;
57069 $tokens = array_map(function ($token) use ($self) {
57070 if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
57071 return $match[1].$self->escapeToken($match[2]);
57072 }
57073
57074 if ($token && '-' !== $token[0]) {
57075 return $self->escapeToken($token);
57076 }
57077
57078 return $token;
57079 }, $this->tokens);
57080
57081 return implode(' ', $tokens);
57082 }
57083 }
57084 <?php
57085
57086
57087
57088
57089
57090
57091
57092
57093
57094
57095 namespace Symfony\Component\Console\Input;
57096
57097 use Symfony\Component\Console\Exception\InvalidArgumentException;
57098 use Symfony\Component\Console\Exception\InvalidOptionException;
57099
57100
57101
57102
57103
57104
57105
57106
57107
57108
57109 class ArrayInput extends Input
57110 {
57111 private $parameters;
57112
57113 public function __construct(array $parameters, InputDefinition $definition = null)
57114 {
57115 $this->parameters = $parameters;
57116
57117 parent::__construct($definition);
57118 }
57119
57120
57121
57122
57123 public function getFirstArgument()
57124 {
57125 foreach ($this->parameters as $key => $value) {
57126 if ($key && '-' === $key[0]) {
57127 continue;
57128 }
57129
57130 return $value;
57131 }
57132 }
57133
57134
57135
57136
57137 public function hasParameterOption($values)
57138 {
57139 $values = (array) $values;
57140
57141 foreach ($this->parameters as $k => $v) {
57142 if (!is_int($k)) {
57143 $v = $k;
57144 }
57145
57146 if (in_array($v, $values)) {
57147 return true;
57148 }
57149 }
57150
57151 return false;
57152 }
57153
57154
57155
57156
57157 public function getParameterOption($values, $default = false)
57158 {
57159 $values = (array) $values;
57160
57161 foreach ($this->parameters as $k => $v) {
57162 if (is_int($k)) {
57163 if (in_array($v, $values)) {
57164 return true;
57165 }
57166 } elseif (in_array($k, $values)) {
57167 return $v;
57168 }
57169 }
57170
57171 return $default;
57172 }
57173
57174
57175
57176
57177
57178
57179 public function __toString()
57180 {
57181 $params = array();
57182 foreach ($this->parameters as $param => $val) {
57183 if ($param && '-' === $param[0]) {
57184 if (is_array($val)) {
57185 foreach ($val as $v) {
57186 $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : '');
57187 }
57188 } else {
57189 $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
57190 }
57191 } else {
57192 $params[] = is_array($val) ? array_map(array($this, 'escapeToken'), $val) : $this->escapeToken($val);
57193 }
57194 }
57195
57196 return implode(' ', $params);
57197 }
57198
57199
57200
57201
57202 protected function parse()
57203 {
57204 foreach ($this->parameters as $key => $value) {
57205 if (0 === strpos($key, '--')) {
57206 $this->addLongOption(substr($key, 2), $value);
57207 } elseif ('-' === $key[0]) {
57208 $this->addShortOption(substr($key, 1), $value);
57209 } else {
57210 $this->addArgument($key, $value);
57211 }
57212 }
57213 }
57214
57215
57216
57217
57218
57219
57220
57221
57222
57223 private function addShortOption($shortcut, $value)
57224 {
57225 if (!$this->definition->hasShortcut($shortcut)) {
57226 throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
57227 }
57228
57229 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
57230 }
57231
57232
57233
57234
57235
57236
57237
57238
57239
57240
57241 private function addLongOption($name, $value)
57242 {
57243 if (!$this->definition->hasOption($name)) {
57244 throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
57245 }
57246
57247 $option = $this->definition->getOption($name);
57248
57249 if (null === $value) {
57250 if ($option->isValueRequired()) {
57251 throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
57252 }
57253
57254 $value = $option->isValueOptional() ? $option->getDefault() : true;
57255 }
57256
57257 $this->options[$name] = $value;
57258 }
57259
57260
57261
57262
57263
57264
57265
57266
57267
57268 private function addArgument($name, $value)
57269 {
57270 if (!$this->definition->hasArgument($name)) {
57271 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
57272 }
57273
57274 $this->arguments[$name] = $value;
57275 }
57276 }
57277 <?php
57278
57279
57280
57281
57282
57283
57284
57285
57286
57287
57288 namespace Symfony\Component\Console\Input;
57289
57290 use Symfony\Component\Console\Exception\InvalidArgumentException;
57291 use Symfony\Component\Console\Exception\RuntimeException;
57292
57293
57294
57295
57296
57297
57298
57299
57300
57301
57302
57303
57304 abstract class Input implements InputInterface
57305 {
57306 protected $definition;
57307 protected $options = array();
57308 protected $arguments = array();
57309 protected $interactive = true;
57310
57311 public function __construct(InputDefinition $definition = null)
57312 {
57313 if (null === $definition) {
57314 $this->definition = new InputDefinition();
57315 } else {
57316 $this->bind($definition);
57317 $this->validate();
57318 }
57319 }
57320
57321
57322
57323
57324 public function bind(InputDefinition $definition)
57325 {
57326 $this->arguments = array();
57327 $this->options = array();
57328 $this->definition = $definition;
57329
57330 $this->parse();
57331 }
57332
57333
57334
57335
57336 abstract protected function parse();
57337
57338
57339
57340
57341 public function validate()
57342 {
57343 $definition = $this->definition;
57344 $givenArguments = $this->arguments;
57345
57346 $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
57347 return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
57348 });
57349
57350 if (count($missingArguments) > 0) {
57351 throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
57352 }
57353 }
57354
57355
57356
57357
57358 public function isInteractive()
57359 {
57360 return $this->interactive;
57361 }
57362
57363
57364
57365
57366 public function setInteractive($interactive)
57367 {
57368 $this->interactive = (bool) $interactive;
57369 }
57370
57371
57372
57373
57374 public function getArguments()
57375 {
57376 return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
57377 }
57378
57379
57380
57381
57382 public function getArgument($name)
57383 {
57384 if (!$this->definition->hasArgument($name)) {
57385 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
57386 }
57387
57388 return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
57389 }
57390
57391
57392
57393
57394 public function setArgument($name, $value)
57395 {
57396 if (!$this->definition->hasArgument($name)) {
57397 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
57398 }
57399
57400 $this->arguments[$name] = $value;
57401 }
57402
57403
57404
57405
57406 public function hasArgument($name)
57407 {
57408 return $this->definition->hasArgument($name);
57409 }
57410
57411
57412
57413
57414 public function getOptions()
57415 {
57416 return array_merge($this->definition->getOptionDefaults(), $this->options);
57417 }
57418
57419
57420
57421
57422 public function getOption($name)
57423 {
57424 if (!$this->definition->hasOption($name)) {
57425 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
57426 }
57427
57428 return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
57429 }
57430
57431
57432
57433
57434 public function setOption($name, $value)
57435 {
57436 if (!$this->definition->hasOption($name)) {
57437 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
57438 }
57439
57440 $this->options[$name] = $value;
57441 }
57442
57443
57444
57445
57446 public function hasOption($name)
57447 {
57448 return $this->definition->hasOption($name);
57449 }
57450
57451
57452
57453
57454
57455
57456
57457
57458 public function escapeToken($token)
57459 {
57460 return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
57461 }
57462 }
57463 <?php
57464
57465
57466
57467
57468
57469
57470
57471
57472
57473
57474 namespace Symfony\Component\Console\Input;
57475
57476 use Symfony\Component\Console\Exception\InvalidArgumentException;
57477 use Symfony\Component\Console\Exception\LogicException;
57478
57479
57480
57481
57482
57483
57484 class InputArgument
57485 {
57486 const REQUIRED = 1;
57487 const OPTIONAL = 2;
57488 const IS_ARRAY = 4;
57489
57490 private $name;
57491 private $mode;
57492 private $default;
57493 private $description;
57494
57495
57496
57497
57498
57499
57500
57501
57502
57503 public function __construct($name, $mode = null, $description = '', $default = null)
57504 {
57505 if (null === $mode) {
57506 $mode = self::OPTIONAL;
57507 } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
57508 throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
57509 }
57510
57511 $this->name = $name;
57512 $this->mode = $mode;
57513 $this->description = $description;
57514
57515 $this->setDefault($default);
57516 }
57517
57518
57519
57520
57521
57522
57523 public function getName()
57524 {
57525 return $this->name;
57526 }
57527
57528
57529
57530
57531
57532
57533 public function isRequired()
57534 {
57535 return self::REQUIRED === (self::REQUIRED & $this->mode);
57536 }
57537
57538
57539
57540
57541
57542
57543 public function isArray()
57544 {
57545 return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
57546 }
57547
57548
57549
57550
57551
57552
57553
57554
57555 public function setDefault($default = null)
57556 {
57557 if (self::REQUIRED === $this->mode && null !== $default) {
57558 throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
57559 }
57560
57561 if ($this->isArray()) {
57562 if (null === $default) {
57563 $default = array();
57564 } elseif (!is_array($default)) {
57565 throw new LogicException('A default value for an array argument must be an array.');
57566 }
57567 }
57568
57569 $this->default = $default;
57570 }
57571
57572
57573
57574
57575
57576
57577 public function getDefault()
57578 {
57579 return $this->default;
57580 }
57581
57582
57583
57584
57585
57586
57587 public function getDescription()
57588 {
57589 return $this->description;
57590 }
57591 }
57592 <?php
57593
57594
57595
57596
57597
57598
57599
57600
57601
57602
57603 namespace Symfony\Component\Console\Input;
57604
57605
57606
57607
57608
57609
57610
57611 interface InputAwareInterface
57612 {
57613
57614
57615
57616
57617
57618 public function setInput(InputInterface $input);
57619 }
57620 <?php
57621
57622
57623
57624
57625
57626
57627
57628
57629
57630
57631 namespace Symfony\Component\Console\Input;
57632
57633 use Symfony\Component\Console\Descriptor\TextDescriptor;
57634 use Symfony\Component\Console\Descriptor\XmlDescriptor;
57635 use Symfony\Component\Console\Output\BufferedOutput;
57636 use Symfony\Component\Console\Exception\InvalidArgumentException;
57637 use Symfony\Component\Console\Exception\LogicException;
57638
57639
57640
57641
57642
57643
57644
57645
57646
57647
57648
57649
57650
57651 class InputDefinition
57652 {
57653 private $arguments;
57654 private $requiredCount;
57655 private $hasAnArrayArgument = false;
57656 private $hasOptional;
57657 private $options;
57658 private $shortcuts;
57659
57660
57661
57662
57663 public function __construct(array $definition = array())
57664 {
57665 $this->setDefinition($definition);
57666 }
57667
57668
57669
57670
57671 public function setDefinition(array $definition)
57672 {
57673 $arguments = array();
57674 $options = array();
57675 foreach ($definition as $item) {
57676 if ($item instanceof InputOption) {
57677 $options[] = $item;
57678 } else {
57679 $arguments[] = $item;
57680 }
57681 }
57682
57683 $this->setArguments($arguments);
57684 $this->setOptions($options);
57685 }
57686
57687
57688
57689
57690
57691
57692 public function setArguments($arguments = array())
57693 {
57694 $this->arguments = array();
57695 $this->requiredCount = 0;
57696 $this->hasOptional = false;
57697 $this->hasAnArrayArgument = false;
57698 $this->addArguments($arguments);
57699 }
57700
57701
57702
57703
57704
57705
57706 public function addArguments($arguments = array())
57707 {
57708 if (null !== $arguments) {
57709 foreach ($arguments as $argument) {
57710 $this->addArgument($argument);
57711 }
57712 }
57713 }
57714
57715
57716
57717
57718 public function addArgument(InputArgument $argument)
57719 {
57720 if (isset($this->arguments[$argument->getName()])) {
57721 throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
57722 }
57723
57724 if ($this->hasAnArrayArgument) {
57725 throw new LogicException('Cannot add an argument after an array argument.');
57726 }
57727
57728 if ($argument->isRequired() && $this->hasOptional) {
57729 throw new LogicException('Cannot add a required argument after an optional one.');
57730 }
57731
57732 if ($argument->isArray()) {
57733 $this->hasAnArrayArgument = true;
57734 }
57735
57736 if ($argument->isRequired()) {
57737 ++$this->requiredCount;
57738 } else {
57739 $this->hasOptional = true;
57740 }
57741
57742 $this->arguments[$argument->getName()] = $argument;
57743 }
57744
57745
57746
57747
57748
57749
57750
57751
57752
57753
57754 public function getArgument($name)
57755 {
57756 if (!$this->hasArgument($name)) {
57757 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
57758 }
57759
57760 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
57761
57762 return $arguments[$name];
57763 }
57764
57765
57766
57767
57768
57769
57770
57771
57772 public function hasArgument($name)
57773 {
57774 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
57775
57776 return isset($arguments[$name]);
57777 }
57778
57779
57780
57781
57782
57783
57784 public function getArguments()
57785 {
57786 return $this->arguments;
57787 }
57788
57789
57790
57791
57792
57793
57794 public function getArgumentCount()
57795 {
57796 return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
57797 }
57798
57799
57800
57801
57802
57803
57804 public function getArgumentRequiredCount()
57805 {
57806 return $this->requiredCount;
57807 }
57808
57809
57810
57811
57812
57813
57814 public function getArgumentDefaults()
57815 {
57816 $values = array();
57817 foreach ($this->arguments as $argument) {
57818 $values[$argument->getName()] = $argument->getDefault();
57819 }
57820
57821 return $values;
57822 }
57823
57824
57825
57826
57827
57828
57829 public function setOptions($options = array())
57830 {
57831 $this->options = array();
57832 $this->shortcuts = array();
57833 $this->addOptions($options);
57834 }
57835
57836
57837
57838
57839
57840
57841 public function addOptions($options = array())
57842 {
57843 foreach ($options as $option) {
57844 $this->addOption($option);
57845 }
57846 }
57847
57848
57849
57850
57851 public function addOption(InputOption $option)
57852 {
57853 if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
57854 throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
57855 }
57856
57857 if ($option->getShortcut()) {
57858 foreach (explode('|', $option->getShortcut()) as $shortcut) {
57859 if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
57860 throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
57861 }
57862 }
57863 }
57864
57865 $this->options[$option->getName()] = $option;
57866 if ($option->getShortcut()) {
57867 foreach (explode('|', $option->getShortcut()) as $shortcut) {
57868 $this->shortcuts[$shortcut] = $option->getName();
57869 }
57870 }
57871 }
57872
57873
57874
57875
57876
57877
57878
57879
57880
57881
57882 public function getOption($name)
57883 {
57884 if (!$this->hasOption($name)) {
57885 throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
57886 }
57887
57888 return $this->options[$name];
57889 }
57890
57891
57892
57893
57894
57895
57896
57897
57898
57899
57900
57901 public function hasOption($name)
57902 {
57903 return isset($this->options[$name]);
57904 }
57905
57906
57907
57908
57909
57910
57911 public function getOptions()
57912 {
57913 return $this->options;
57914 }
57915
57916
57917
57918
57919
57920
57921
57922
57923 public function hasShortcut($name)
57924 {
57925 return isset($this->shortcuts[$name]);
57926 }
57927
57928
57929
57930
57931
57932
57933
57934
57935 public function getOptionForShortcut($shortcut)
57936 {
57937 return $this->getOption($this->shortcutToName($shortcut));
57938 }
57939
57940
57941
57942
57943
57944
57945 public function getOptionDefaults()
57946 {
57947 $values = array();
57948 foreach ($this->options as $option) {
57949 $values[$option->getName()] = $option->getDefault();
57950 }
57951
57952 return $values;
57953 }
57954
57955
57956
57957
57958
57959
57960
57961
57962
57963
57964 private function shortcutToName($shortcut)
57965 {
57966 if (!isset($this->shortcuts[$shortcut])) {
57967 throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
57968 }
57969
57970 return $this->shortcuts[$shortcut];
57971 }
57972
57973
57974
57975
57976
57977
57978
57979
57980 public function getSynopsis($short = false)
57981 {
57982 $elements = array();
57983
57984 if ($short && $this->getOptions()) {
57985 $elements[] = '[options]';
57986 } elseif (!$short) {
57987 foreach ($this->getOptions() as $option) {
57988 $value = '';
57989 if ($option->acceptValue()) {
57990 $value = sprintf(
57991 ' %s%s%s',
57992 $option->isValueOptional() ? '[' : '',
57993 strtoupper($option->getName()),
57994 $option->isValueOptional() ? ']' : ''
57995 );
57996 }
57997
57998 $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
57999 $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
58000 }
58001 }
58002
58003 if (count($elements) && $this->getArguments()) {
58004 $elements[] = '[--]';
58005 }
58006
58007 foreach ($this->getArguments() as $argument) {
58008 $element = '<'.$argument->getName().'>';
58009 if (!$argument->isRequired()) {
58010 $element = '['.$element.']';
58011 } elseif ($argument->isArray()) {
58012 $element = $element.' ('.$element.')';
58013 }
58014
58015 if ($argument->isArray()) {
58016 $element .= '...';
58017 }
58018
58019 $elements[] = $element;
58020 }
58021
58022 return implode(' ', $elements);
58023 }
58024
58025
58026
58027
58028
58029
58030
58031
58032 public function asText()
58033 {
58034 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
58035
58036 $descriptor = new TextDescriptor();
58037 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
58038 $descriptor->describe($output, $this, array('raw_output' => true));
58039
58040 return $output->fetch();
58041 }
58042
58043
58044
58045
58046
58047
58048
58049
58050
58051
58052 public function asXml($asDom = false)
58053 {
58054 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
58055
58056 $descriptor = new XmlDescriptor();
58057
58058 if ($asDom) {
58059 return $descriptor->getInputDefinitionDocument($this);
58060 }
58061
58062 $output = new BufferedOutput();
58063 $descriptor->describe($output, $this);
58064
58065 return $output->fetch();
58066 }
58067 }
58068 <?php
58069
58070
58071
58072
58073
58074
58075
58076
58077
58078
58079 namespace Symfony\Component\Console\Input;
58080
58081 use Symfony\Component\Console\Exception\InvalidArgumentException;
58082 use Symfony\Component\Console\Exception\RuntimeException;
58083
58084
58085
58086
58087
58088
58089 interface InputInterface
58090 {
58091
58092
58093
58094
58095
58096 public function getFirstArgument();
58097
58098
58099
58100
58101
58102
58103
58104
58105
58106
58107
58108 public function hasParameterOption($values);
58109
58110
58111
58112
58113
58114
58115
58116
58117
58118
58119
58120
58121 public function getParameterOption($values, $default = false);
58122
58123
58124
58125
58126 public function bind(InputDefinition $definition);
58127
58128
58129
58130
58131
58132
58133 public function validate();
58134
58135
58136
58137
58138
58139
58140 public function getArguments();
58141
58142
58143
58144
58145
58146
58147
58148
58149
58150
58151 public function getArgument($name);
58152
58153
58154
58155
58156
58157
58158
58159
58160
58161 public function setArgument($name, $value);
58162
58163
58164
58165
58166
58167
58168
58169
58170 public function hasArgument($name);
58171
58172
58173
58174
58175
58176
58177 public function getOptions();
58178
58179
58180
58181
58182
58183
58184
58185
58186
58187
58188 public function getOption($name);
58189
58190
58191
58192
58193
58194
58195
58196
58197
58198 public function setOption($name, $value);
58199
58200
58201
58202
58203
58204
58205
58206
58207 public function hasOption($name);
58208
58209
58210
58211
58212
58213
58214 public function isInteractive();
58215
58216
58217
58218
58219
58220
58221 public function setInteractive($interactive);
58222 }
58223 <?php
58224
58225
58226
58227
58228
58229
58230
58231
58232
58233
58234 namespace Symfony\Component\Console\Input;
58235
58236 use Symfony\Component\Console\Exception\InvalidArgumentException;
58237 use Symfony\Component\Console\Exception\LogicException;
58238
58239
58240
58241
58242
58243
58244 class InputOption
58245 {
58246 const VALUE_NONE = 1;
58247 const VALUE_REQUIRED = 2;
58248 const VALUE_OPTIONAL = 4;
58249 const VALUE_IS_ARRAY = 8;
58250
58251 private $name;
58252 private $shortcut;
58253 private $mode;
58254 private $default;
58255 private $description;
58256
58257
58258
58259
58260
58261
58262
58263
58264
58265
58266 public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
58267 {
58268 if (0 === strpos($name, '--')) {
58269 $name = substr($name, 2);
58270 }
58271
58272 if (empty($name)) {
58273 throw new InvalidArgumentException('An option name cannot be empty.');
58274 }
58275
58276 if (empty($shortcut)) {
58277 $shortcut = null;
58278 }
58279
58280 if (null !== $shortcut) {
58281 if (is_array($shortcut)) {
58282 $shortcut = implode('|', $shortcut);
58283 }
58284 $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
58285 $shortcuts = array_filter($shortcuts);
58286 $shortcut = implode('|', $shortcuts);
58287
58288 if (empty($shortcut)) {
58289 throw new InvalidArgumentException('An option shortcut cannot be empty.');
58290 }
58291 }
58292
58293 if (null === $mode) {
58294 $mode = self::VALUE_NONE;
58295 } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
58296 throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
58297 }
58298
58299 $this->name = $name;
58300 $this->shortcut = $shortcut;
58301 $this->mode = $mode;
58302 $this->description = $description;
58303
58304 if ($this->isArray() && !$this->acceptValue()) {
58305 throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
58306 }
58307
58308 $this->setDefault($default);
58309 }
58310
58311
58312
58313
58314
58315
58316 public function getShortcut()
58317 {
58318 return $this->shortcut;
58319 }
58320
58321
58322
58323
58324
58325
58326 public function getName()
58327 {
58328 return $this->name;
58329 }
58330
58331
58332
58333
58334
58335
58336 public function acceptValue()
58337 {
58338 return $this->isValueRequired() || $this->isValueOptional();
58339 }
58340
58341
58342
58343
58344
58345
58346 public function isValueRequired()
58347 {
58348 return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
58349 }
58350
58351
58352
58353
58354
58355
58356 public function isValueOptional()
58357 {
58358 return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
58359 }
58360
58361
58362
58363
58364
58365
58366 public function isArray()
58367 {
58368 return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
58369 }
58370
58371
58372
58373
58374
58375
58376
58377
58378 public function setDefault($default = null)
58379 {
58380 if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
58381 throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
58382 }
58383
58384 if ($this->isArray()) {
58385 if (null === $default) {
58386 $default = array();
58387 } elseif (!is_array($default)) {
58388 throw new LogicException('A default value for an array option must be an array.');
58389 }
58390 }
58391
58392 $this->default = $this->acceptValue() ? $default : false;
58393 }
58394
58395
58396
58397
58398
58399
58400 public function getDefault()
58401 {
58402 return $this->default;
58403 }
58404
58405
58406
58407
58408
58409
58410 public function getDescription()
58411 {
58412 return $this->description;
58413 }
58414
58415
58416
58417
58418
58419
58420 public function equals(InputOption $option)
58421 {
58422 return $option->getName() === $this->getName()
58423 && $option->getShortcut() === $this->getShortcut()
58424 && $option->getDefault() === $this->getDefault()
58425 && $option->isArray() === $this->isArray()
58426 && $option->isValueRequired() === $this->isValueRequired()
58427 && $option->isValueOptional() === $this->isValueOptional()
58428 ;
58429 }
58430 }
58431 <?php
58432
58433
58434
58435
58436
58437
58438
58439
58440
58441
58442 namespace Symfony\Component\Console\Input;
58443
58444 use Symfony\Component\Console\Exception\InvalidArgumentException;
58445
58446
58447
58448
58449
58450
58451
58452
58453
58454
58455 class StringInput extends ArgvInput
58456 {
58457 const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
58458 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
58459
58460
58461
58462
58463
58464
58465
58466 public function __construct($input, InputDefinition $definition = null)
58467 {
58468 if ($definition) {
58469 @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);
58470 }
58471
58472 parent::__construct(array(), null);
58473
58474 $this->setTokens($this->tokenize($input));
58475
58476 if (null !== $definition) {
58477 $this->bind($definition);
58478 }
58479 }
58480
58481
58482
58483
58484
58485
58486
58487
58488
58489
58490 private function tokenize($input)
58491 {
58492 $tokens = array();
58493 $length = strlen($input);
58494 $cursor = 0;
58495 while ($cursor < $length) {
58496 if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
58497 } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
58498 $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
58499 } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
58500 $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
58501 } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
58502 $tokens[] = stripcslashes($match[1]);
58503 } else {
58504
58505  throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
58506 }
58507
58508 $cursor += strlen($match[0]);
58509 }
58510
58511 return $tokens;
58512 }
58513 }
58514 Copyright (c) 2004-2017 Fabien Potencier
58515
58516 Permission is hereby granted, free of charge, to any person obtaining a copy
58517 of this software and associated documentation files (the "Software"), to deal
58518 in the Software without restriction, including without limitation the rights
58519 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
58520 copies of the Software, and to permit persons to whom the Software is furnished
58521 to do so, subject to the following conditions:
58522
58523 The above copyright notice and this permission notice shall be included in all
58524 copies or substantial portions of the Software.
58525
58526 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
58527 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
58528 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58529 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
58530 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
58531 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
58532 THE SOFTWARE.
58533 <?php
58534
58535
58536
58537
58538
58539
58540
58541
58542
58543
58544 namespace Symfony\Component\Console\Logger;
58545
58546 use Psr\Log\AbstractLogger;
58547 use Psr\Log\InvalidArgumentException;
58548 use Psr\Log\LogLevel;
58549 use Symfony\Component\Console\Output\OutputInterface;
58550 use Symfony\Component\Console\Output\ConsoleOutputInterface;
58551
58552
58553
58554
58555
58556
58557
58558
58559 class ConsoleLogger extends AbstractLogger
58560 {
58561 const INFO = 'info';
58562 const ERROR = 'error';
58563
58564 private $output;
58565 private $verbosityLevelMap = array(
58566 LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
58567 LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
58568 LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
58569 LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
58570 LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
58571 LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
58572 LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
58573 LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
58574 );
58575 private $formatLevelMap = array(
58576 LogLevel::EMERGENCY => self::ERROR,
58577 LogLevel::ALERT => self::ERROR,
58578 LogLevel::CRITICAL => self::ERROR,
58579 LogLevel::ERROR => self::ERROR,
58580 LogLevel::WARNING => self::INFO,
58581 LogLevel::NOTICE => self::INFO,
58582 LogLevel::INFO => self::INFO,
58583 LogLevel::DEBUG => self::INFO,
58584 );
58585
58586 public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
58587 {
58588 $this->output = $output;
58589 $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
58590 $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
58591 }
58592
58593
58594
58595
58596 public function log($level, $message, array $context = array())
58597 {
58598 if (!isset($this->verbosityLevelMap[$level])) {
58599 throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
58600 }
58601
58602
58603  if (self::ERROR === $this->formatLevelMap[$level] && $this->output instanceof ConsoleOutputInterface) {
58604 $output = $this->output->getErrorOutput();
58605 } else {
58606 $output = $this->output;
58607 }
58608
58609 if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
58610 $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
58611 }
58612 }
58613
58614
58615
58616
58617
58618
58619
58620
58621
58622
58623
58624 private function interpolate($message, array $context)
58625 {
58626
58627  $replace = array();
58628 foreach ($context as $key => $val) {
58629 if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
58630 $replace[sprintf('{%s}', $key)] = $val;
58631 }
58632 }
58633
58634
58635  return strtr($message, $replace);
58636 }
58637 }
58638 <?php
58639
58640
58641
58642
58643
58644
58645
58646
58647
58648
58649 namespace Symfony\Component\Console\Output;
58650
58651
58652
58653
58654 class BufferedOutput extends Output
58655 {
58656 private $buffer = '';
58657
58658
58659
58660
58661
58662
58663 public function fetch()
58664 {
58665 $content = $this->buffer;
58666 $this->buffer = '';
58667
58668 return $content;
58669 }
58670
58671
58672
58673
58674 protected function doWrite($message, $newline)
58675 {
58676 $this->buffer .= $message;
58677
58678 if ($newline) {
58679 $this->buffer .= PHP_EOL;
58680 }
58681 }
58682 }
58683 <?php
58684
58685
58686
58687
58688
58689
58690
58691
58692
58693
58694 namespace Symfony\Component\Console\Output;
58695
58696 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58697
58698
58699
58700
58701
58702
58703
58704
58705
58706
58707
58708
58709
58710
58711 class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
58712 {
58713 private $stderr;
58714
58715
58716
58717
58718
58719
58720 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
58721 {
58722 parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
58723
58724 $actualDecorated = $this->isDecorated();
58725 $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
58726
58727 if (null === $decorated) {
58728 $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
58729 }
58730 }
58731
58732
58733
58734
58735 public function setDecorated($decorated)
58736 {
58737 parent::setDecorated($decorated);
58738 $this->stderr->setDecorated($decorated);
58739 }
58740
58741
58742
58743
58744 public function setFormatter(OutputFormatterInterface $formatter)
58745 {
58746 parent::setFormatter($formatter);
58747 $this->stderr->setFormatter($formatter);
58748 }
58749
58750
58751
58752
58753 public function setVerbosity($level)
58754 {
58755 parent::setVerbosity($level);
58756 $this->stderr->setVerbosity($level);
58757 }
58758
58759
58760
58761
58762 public function getErrorOutput()
58763 {
58764 return $this->stderr;
58765 }
58766
58767
58768
58769
58770 public function setErrorOutput(OutputInterface $error)
58771 {
58772 $this->stderr = $error;
58773 }
58774
58775
58776
58777
58778
58779
58780
58781 protected function hasStdoutSupport()
58782 {
58783 return false === $this->isRunningOS400();
58784 }
58785
58786
58787
58788
58789
58790
58791
58792 protected function hasStderrSupport()
58793 {
58794 return false === $this->isRunningOS400();
58795 }
58796
58797
58798
58799
58800
58801
58802
58803 private function isRunningOS400()
58804 {
58805 $checks = array(
58806 function_exists('php_uname') ? php_uname('s') : '',
58807 getenv('OSTYPE'),
58808 PHP_OS,
58809 );
58810
58811 return false !== stripos(implode(';', $checks), 'OS400');
58812 }
58813
58814
58815
58816
58817 private function openOutputStream()
58818 {
58819 $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output';
58820
58821 return @fopen($outputStream, 'w') ?: fopen('php://output', 'w');
58822 }
58823
58824
58825
58826
58827 private function openErrorStream()
58828 {
58829 $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output';
58830
58831 return fopen($errorStream, 'w');
58832 }
58833 }
58834 <?php
58835
58836
58837
58838
58839
58840
58841
58842
58843
58844
58845 namespace Symfony\Component\Console\Output;
58846
58847
58848
58849
58850
58851
58852
58853 interface ConsoleOutputInterface extends OutputInterface
58854 {
58855
58856
58857
58858
58859
58860 public function getErrorOutput();
58861
58862 public function setErrorOutput(OutputInterface $error);
58863 }
58864 <?php
58865
58866
58867
58868
58869
58870
58871
58872
58873
58874
58875 namespace Symfony\Component\Console\Output;
58876
58877 use Symfony\Component\Console\Formatter\OutputFormatter;
58878 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58879
58880
58881
58882
58883
58884
58885
58886
58887
58888 class NullOutput implements OutputInterface
58889 {
58890
58891
58892
58893 public function setFormatter(OutputFormatterInterface $formatter)
58894 {
58895
58896  }
58897
58898
58899
58900
58901 public function getFormatter()
58902 {
58903
58904  return new OutputFormatter();
58905 }
58906
58907
58908
58909
58910 public function setDecorated($decorated)
58911 {
58912
58913  }
58914
58915
58916
58917
58918 public function isDecorated()
58919 {
58920 return false;
58921 }
58922
58923
58924
58925
58926 public function setVerbosity($level)
58927 {
58928
58929  }
58930
58931
58932
58933
58934 public function getVerbosity()
58935 {
58936 return self::VERBOSITY_QUIET;
58937 }
58938
58939
58940
58941
58942 public function isQuiet()
58943 {
58944 return true;
58945 }
58946
58947
58948
58949
58950 public function isVerbose()
58951 {
58952 return false;
58953 }
58954
58955
58956
58957
58958 public function isVeryVerbose()
58959 {
58960 return false;
58961 }
58962
58963
58964
58965
58966 public function isDebug()
58967 {
58968 return false;
58969 }
58970
58971
58972
58973
58974 public function writeln($messages, $options = self::OUTPUT_NORMAL)
58975 {
58976
58977  }
58978
58979
58980
58981
58982 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
58983 {
58984
58985  }
58986 }
58987 <?php
58988
58989
58990
58991
58992
58993
58994
58995
58996
58997
58998 namespace Symfony\Component\Console\Output;
58999
59000 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59001 use Symfony\Component\Console\Formatter\OutputFormatter;
59002
59003
59004
59005
59006
59007
59008
59009
59010
59011
59012
59013
59014
59015
59016 abstract class Output implements OutputInterface
59017 {
59018 private $verbosity;
59019 private $formatter;
59020
59021
59022
59023
59024
59025
59026 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
59027 {
59028 $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
59029 $this->formatter = $formatter ?: new OutputFormatter();
59030 $this->formatter->setDecorated($decorated);
59031 }
59032
59033
59034
59035
59036 public function setFormatter(OutputFormatterInterface $formatter)
59037 {
59038 $this->formatter = $formatter;
59039 }
59040
59041
59042
59043
59044 public function getFormatter()
59045 {
59046 return $this->formatter;
59047 }
59048
59049
59050
59051
59052 public function setDecorated($decorated)
59053 {
59054 $this->formatter->setDecorated($decorated);
59055 }
59056
59057
59058
59059
59060 public function isDecorated()
59061 {
59062 return $this->formatter->isDecorated();
59063 }
59064
59065
59066
59067
59068 public function setVerbosity($level)
59069 {
59070 $this->verbosity = (int) $level;
59071 }
59072
59073
59074
59075
59076 public function getVerbosity()
59077 {
59078 return $this->verbosity;
59079 }
59080
59081
59082
59083
59084 public function isQuiet()
59085 {
59086 return self::VERBOSITY_QUIET === $this->verbosity;
59087 }
59088
59089
59090
59091
59092 public function isVerbose()
59093 {
59094 return self::VERBOSITY_VERBOSE <= $this->verbosity;
59095 }
59096
59097
59098
59099
59100 public function isVeryVerbose()
59101 {
59102 return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
59103 }
59104
59105
59106
59107
59108 public function isDebug()
59109 {
59110 return self::VERBOSITY_DEBUG <= $this->verbosity;
59111 }
59112
59113
59114
59115
59116 public function writeln($messages, $options = self::OUTPUT_NORMAL)
59117 {
59118 $this->write($messages, true, $options);
59119 }
59120
59121
59122
59123
59124 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
59125 {
59126 $messages = (array) $messages;
59127
59128 $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
59129 $type = $types & $options ?: self::OUTPUT_NORMAL;
59130
59131 $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
59132 $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
59133
59134 if ($verbosity > $this->getVerbosity()) {
59135 return;
59136 }
59137
59138 foreach ($messages as $message) {
59139 switch ($type) {
59140 case OutputInterface::OUTPUT_NORMAL:
59141 $message = $this->formatter->format($message);
59142 break;
59143 case OutputInterface::OUTPUT_RAW:
59144 break;
59145 case OutputInterface::OUTPUT_PLAIN:
59146 $message = strip_tags($this->formatter->format($message));
59147 break;
59148 }
59149
59150 $this->doWrite($message, $newline);
59151 }
59152 }
59153
59154
59155
59156
59157
59158
59159
59160 abstract protected function doWrite($message, $newline);
59161 }
59162 <?php
59163
59164
59165
59166
59167
59168
59169
59170
59171
59172
59173 namespace Symfony\Component\Console\Output;
59174
59175 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59176
59177
59178
59179
59180
59181
59182 interface OutputInterface
59183 {
59184 const VERBOSITY_QUIET = 16;
59185 const VERBOSITY_NORMAL = 32;
59186 const VERBOSITY_VERBOSE = 64;
59187 const VERBOSITY_VERY_VERBOSE = 128;
59188 const VERBOSITY_DEBUG = 256;
59189
59190 const OUTPUT_NORMAL = 1;
59191 const OUTPUT_RAW = 2;
59192 const OUTPUT_PLAIN = 4;
59193
59194
59195
59196
59197
59198
59199
59200
59201 public function write($messages, $newline = false, $options = 0);
59202
59203
59204
59205
59206
59207
59208
59209 public function writeln($messages, $options = 0);
59210
59211
59212
59213
59214
59215
59216 public function setVerbosity($level);
59217
59218
59219
59220
59221
59222
59223 public function getVerbosity();
59224
59225
59226
59227
59228
59229
59230 public function setDecorated($decorated);
59231
59232
59233
59234
59235
59236
59237 public function isDecorated();
59238
59239 public function setFormatter(OutputFormatterInterface $formatter);
59240
59241
59242
59243
59244
59245
59246 public function getFormatter();
59247 }
59248 <?php
59249
59250
59251
59252
59253
59254
59255
59256
59257
59258
59259 namespace Symfony\Component\Console\Output;
59260
59261 use Symfony\Component\Console\Exception\InvalidArgumentException;
59262 use Symfony\Component\Console\Exception\RuntimeException;
59263 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59264
59265
59266
59267
59268
59269
59270
59271
59272
59273
59274
59275
59276
59277
59278 class StreamOutput extends Output
59279 {
59280 private $stream;
59281
59282
59283
59284
59285
59286
59287
59288
59289
59290 public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
59291 {
59292 if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
59293 throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
59294 }
59295
59296 $this->stream = $stream;
59297
59298 if (null === $decorated) {
59299 $decorated = $this->hasColorSupport();
59300 }
59301
59302 parent::__construct($verbosity, $decorated, $formatter);
59303 }
59304
59305
59306
59307
59308
59309
59310 public function getStream()
59311 {
59312 return $this->stream;
59313 }
59314
59315
59316
59317
59318 protected function doWrite($message, $newline)
59319 {
59320 if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
59321
59322  throw new RuntimeException('Unable to write output.');
59323 }
59324
59325 fflush($this->stream);
59326 }
59327
59328
59329
59330
59331
59332
59333
59334
59335
59336
59337
59338 protected function hasColorSupport()
59339 {
59340 if (DIRECTORY_SEPARATOR === '\\') {
59341 return
59342 '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
59343 || false !== getenv('ANSICON')
59344 || 'ON' === getenv('ConEmuANSI')
59345 || 'xterm' === getenv('TERM');
59346 }
59347
59348 return function_exists('posix_isatty') && @posix_isatty($this->stream);
59349 }
59350 }
59351 <?php
59352
59353
59354
59355
59356
59357
59358
59359
59360
59361
59362 namespace Symfony\Component\Console\Question;
59363
59364 use Symfony\Component\Console\Exception\InvalidArgumentException;
59365
59366
59367
59368
59369
59370
59371 class ChoiceQuestion extends Question
59372 {
59373 private $choices;
59374 private $multiselect = false;
59375 private $prompt = ' > ';
59376 private $errorMessage = 'Value "%s" is invalid';
59377
59378
59379
59380
59381
59382
59383 public function __construct($question, array $choices, $default = null)
59384 {
59385 if (!$choices) {
59386 throw new \LogicException('Choice question must have at least 1 choice available.');
59387 }
59388
59389 parent::__construct($question, $default);
59390
59391 $this->choices = $choices;
59392 $this->setValidator($this->getDefaultValidator());
59393 $this->setAutocompleterValues($choices);
59394 }
59395
59396
59397
59398
59399
59400
59401 public function getChoices()
59402 {
59403 return $this->choices;
59404 }
59405
59406
59407
59408
59409
59410
59411
59412
59413
59414
59415 public function setMultiselect($multiselect)
59416 {
59417 $this->multiselect = $multiselect;
59418 $this->setValidator($this->getDefaultValidator());
59419
59420 return $this;
59421 }
59422
59423
59424
59425
59426
59427
59428 public function isMultiselect()
59429 {
59430 return $this->multiselect;
59431 }
59432
59433
59434
59435
59436
59437
59438 public function getPrompt()
59439 {
59440 return $this->prompt;
59441 }
59442
59443
59444
59445
59446
59447
59448
59449
59450 public function setPrompt($prompt)
59451 {
59452 $this->prompt = $prompt;
59453
59454 return $this;
59455 }
59456
59457
59458
59459
59460
59461
59462
59463
59464
59465
59466 public function setErrorMessage($errorMessage)
59467 {
59468 $this->errorMessage = $errorMessage;
59469 $this->setValidator($this->getDefaultValidator());
59470
59471 return $this;
59472 }
59473
59474
59475
59476
59477
59478
59479 private function getDefaultValidator()
59480 {
59481 $choices = $this->choices;
59482 $errorMessage = $this->errorMessage;
59483 $multiselect = $this->multiselect;
59484 $isAssoc = $this->isAssoc($choices);
59485
59486 return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
59487
59488  $selectedChoices = str_replace(' ', '', $selected);
59489
59490 if ($multiselect) {
59491
59492  if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
59493 throw new InvalidArgumentException(sprintf($errorMessage, $selected));
59494 }
59495 $selectedChoices = explode(',', $selectedChoices);
59496 } else {
59497 $selectedChoices = array($selected);
59498 }
59499
59500 $multiselectChoices = array();
59501 foreach ($selectedChoices as $value) {
59502 $results = array();
59503 foreach ($choices as $key => $choice) {
59504 if ($choice === $value) {
59505 $results[] = $key;
59506 }
59507 }
59508
59509 if (count($results) > 1) {
59510 throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
59511 }
59512
59513 $result = array_search($value, $choices);
59514
59515 if (!$isAssoc) {
59516 if (false !== $result) {
59517 $result = $choices[$result];
59518 } elseif (isset($choices[$value])) {
59519 $result = $choices[$value];
59520 }
59521 } elseif (false === $result && isset($choices[$value])) {
59522 $result = $value;
59523 }
59524
59525 if (false === $result) {
59526 throw new InvalidArgumentException(sprintf($errorMessage, $value));
59527 }
59528
59529 $multiselectChoices[] = (string) $result;
59530 }
59531
59532 if ($multiselect) {
59533 return $multiselectChoices;
59534 }
59535
59536 return current($multiselectChoices);
59537 };
59538 }
59539 }
59540 <?php
59541
59542
59543
59544
59545
59546
59547
59548
59549
59550
59551 namespace Symfony\Component\Console\Question;
59552
59553
59554
59555
59556
59557
59558 class ConfirmationQuestion extends Question
59559 {
59560 private $trueAnswerRegex;
59561
59562
59563
59564
59565
59566
59567 public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
59568 {
59569 parent::__construct($question, (bool) $default);
59570
59571 $this->trueAnswerRegex = $trueAnswerRegex;
59572 $this->setNormalizer($this->getDefaultNormalizer());
59573 }
59574
59575
59576
59577
59578
59579
59580 private function getDefaultNormalizer()
59581 {
59582 $default = $this->getDefault();
59583 $regex = $this->trueAnswerRegex;
59584
59585 return function ($answer) use ($default, $regex) {
59586 if (is_bool($answer)) {
59587 return $answer;
59588 }
59589
59590 $answerIsTrue = (bool) preg_match($regex, $answer);
59591 if (false === $default) {
59592 return $answer && $answerIsTrue;
59593 }
59594
59595 return !$answer || $answerIsTrue;
59596 };
59597 }
59598 }
59599 <?php
59600
59601
59602
59603
59604
59605
59606
59607
59608
59609
59610 namespace Symfony\Component\Console\Question;
59611
59612 use Symfony\Component\Console\Exception\InvalidArgumentException;
59613 use Symfony\Component\Console\Exception\LogicException;
59614
59615
59616
59617
59618
59619
59620 class Question
59621 {
59622 private $question;
59623 private $attempts;
59624 private $hidden = false;
59625 private $hiddenFallback = true;
59626 private $autocompleterValues;
59627 private $validator;
59628 private $default;
59629 private $normalizer;
59630
59631
59632
59633
59634
59635 public function __construct($question, $default = null)
59636 {
59637 $this->question = $question;
59638 $this->default = $default;
59639 }
59640
59641
59642
59643
59644
59645
59646 public function getQuestion()
59647 {
59648 return $this->question;
59649 }
59650
59651
59652
59653
59654
59655
59656 public function getDefault()
59657 {
59658 return $this->default;
59659 }
59660
59661
59662
59663
59664
59665
59666 public function isHidden()
59667 {
59668 return $this->hidden;
59669 }
59670
59671
59672
59673
59674
59675
59676
59677
59678
59679
59680 public function setHidden($hidden)
59681 {
59682 if ($this->autocompleterValues) {
59683 throw new LogicException('A hidden question cannot use the autocompleter.');
59684 }
59685
59686 $this->hidden = (bool) $hidden;
59687
59688 return $this;
59689 }
59690
59691
59692
59693
59694
59695
59696 public function isHiddenFallback()
59697 {
59698 return $this->hiddenFallback;
59699 }
59700
59701
59702
59703
59704
59705
59706
59707
59708 public function setHiddenFallback($fallback)
59709 {
59710 $this->hiddenFallback = (bool) $fallback;
59711
59712 return $this;
59713 }
59714
59715
59716
59717
59718
59719
59720 public function getAutocompleterValues()
59721 {
59722 return $this->autocompleterValues;
59723 }
59724
59725
59726
59727
59728
59729
59730
59731
59732
59733
59734
59735 public function setAutocompleterValues($values)
59736 {
59737 if (is_array($values)) {
59738 $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
59739 }
59740
59741 if (null !== $values && !is_array($values) && !$values instanceof \Traversable) {
59742 throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.');
59743 }
59744
59745 if ($this->hidden) {
59746 throw new LogicException('A hidden question cannot use the autocompleter.');
59747 }
59748
59749 $this->autocompleterValues = $values;
59750
59751 return $this;
59752 }
59753
59754
59755
59756
59757
59758
59759
59760
59761 public function setValidator($validator)
59762 {
59763 $this->validator = $validator;
59764
59765 return $this;
59766 }
59767
59768
59769
59770
59771
59772
59773 public function getValidator()
59774 {
59775 return $this->validator;
59776 }
59777
59778
59779
59780
59781
59782
59783
59784
59785
59786
59787
59788
59789 public function setMaxAttempts($attempts)
59790 {
59791 if (null !== $attempts && $attempts < 1) {
59792 throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
59793 }
59794
59795 $this->attempts = $attempts;
59796
59797 return $this;
59798 }
59799
59800
59801
59802
59803
59804
59805
59806
59807 public function getMaxAttempts()
59808 {
59809 return $this->attempts;
59810 }
59811
59812
59813
59814
59815
59816
59817
59818
59819
59820
59821 public function setNormalizer($normalizer)
59822 {
59823 $this->normalizer = $normalizer;
59824
59825 return $this;
59826 }
59827
59828
59829
59830
59831
59832
59833
59834
59835 public function getNormalizer()
59836 {
59837 return $this->normalizer;
59838 }
59839
59840 protected function isAssoc($array)
59841 {
59842 return (bool) count(array_filter(array_keys($array), 'is_string'));
59843 }
59844 }
59845 <?php
59846
59847
59848
59849
59850
59851
59852
59853
59854
59855
59856 namespace Symfony\Component\Console;
59857
59858 use Symfony\Component\Console\Exception\RuntimeException;
59859 use Symfony\Component\Console\Input\StringInput;
59860 use Symfony\Component\Console\Output\ConsoleOutput;
59861 use Symfony\Component\Process\ProcessBuilder;
59862 use Symfony\Component\Process\PhpExecutableFinder;
59863
59864
59865
59866
59867
59868
59869
59870
59871
59872
59873
59874
59875 class Shell
59876 {
59877 private $application;
59878 private $history;
59879 private $output;
59880 private $hasReadline;
59881 private $processIsolation = false;
59882
59883
59884
59885
59886
59887 public function __construct(Application $application)
59888 {
59889 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
59890
59891 $this->hasReadline = function_exists('readline');
59892 $this->application = $application;
59893 $this->history = getenv('HOME').'/.history_'.$application->getName();
59894 $this->output = new ConsoleOutput();
59895 }
59896
59897
59898
59899
59900 public function run()
59901 {
59902 $this->application->setAutoExit(false);
59903 $this->application->setCatchExceptions(true);
59904
59905 if ($this->hasReadline) {
59906 readline_read_history($this->history);
59907 readline_completion_function(array($this, 'autocompleter'));
59908 }
59909
59910 $this->output->writeln($this->getHeader());
59911 $php = null;
59912 if ($this->processIsolation) {
59913 $finder = new PhpExecutableFinder();
59914 $php = $finder->find();
59915 $this->output->writeln(<<<'EOF'
59916 <info>Running with process isolation, you should consider this:</info>
59917   * each command is executed as separate process,
59918   * commands don't support interactivity, all params must be passed explicitly,
59919   * commands output is not colorized.
59920
59921 EOF
59922 );
59923 }
59924
59925 while (true) {
59926 $command = $this->readline();
59927
59928 if (false === $command) {
59929 $this->output->writeln("\n");
59930
59931 break;
59932 }
59933
59934 if ($this->hasReadline) {
59935 readline_add_history($command);
59936 readline_write_history($this->history);
59937 }
59938
59939 if ($this->processIsolation) {
59940 $pb = new ProcessBuilder();
59941
59942 $process = $pb
59943 ->add($php)
59944 ->add($_SERVER['argv'][0])
59945 ->add($command)
59946 ->inheritEnvironmentVariables(true)
59947 ->getProcess()
59948 ;
59949
59950 $output = $this->output;
59951 $process->run(function ($type, $data) use ($output) {
59952 $output->writeln($data);
59953 });
59954
59955 $ret = $process->getExitCode();
59956 } else {
59957 $ret = $this->application->run(new StringInput($command), $this->output);
59958 }
59959
59960 if (0 !== $ret) {
59961 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
59962 }
59963 }
59964 }
59965
59966
59967
59968
59969
59970
59971 protected function getHeader()
59972 {
59973 return <<<EOF
59974
59975 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
59976
59977 At the prompt, type <comment>help</comment> for some help,
59978 or <comment>list</comment> to get a list of available commands.
59979
59980 To exit the shell, type <comment>^D</comment>.
59981
59982 EOF;
59983 }
59984
59985
59986
59987
59988
59989
59990 protected function getPrompt()
59991 {
59992
59993  return $this->output->getFormatter()->format($this->application->getName().' > ');
59994 }
59995
59996 protected function getOutput()
59997 {
59998 return $this->output;
59999 }
60000
60001 protected function getApplication()
60002 {
60003 return $this->application;
60004 }
60005
60006
60007
60008
60009
60010
60011
60012
60013 private function autocompleter($text)
60014 {
60015 $info = readline_info();
60016 $text = substr($info['line_buffer'], 0, $info['end']);
60017
60018 if ($info['point'] !== $info['end']) {
60019 return true;
60020 }
60021
60022
60023  if (false === strpos($text, ' ') || !$text) {
60024 return array_keys($this->application->all());
60025 }
60026
60027
60028  try {
60029 $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
60030 } catch (\Exception $e) {
60031 return true;
60032 }
60033
60034 $list = array('--help');
60035 foreach ($command->getDefinition()->getOptions() as $option) {
60036 $list[] = '--'.$option->getName();
60037 }
60038
60039 return $list;
60040 }
60041
60042
60043
60044
60045
60046
60047 private function readline()
60048 {
60049 if ($this->hasReadline) {
60050 $line = readline($this->getPrompt());
60051 } else {
60052 $this->output->write($this->getPrompt());
60053 $line = fgets(STDIN, 1024);
60054 $line = (false === $line || '' === $line) ? false : rtrim($line);
60055 }
60056
60057 return $line;
60058 }
60059
60060 public function getProcessIsolation()
60061 {
60062 return $this->processIsolation;
60063 }
60064
60065 public function setProcessIsolation($processIsolation)
60066 {
60067 $this->processIsolation = (bool) $processIsolation;
60068
60069 if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
60070 throw new RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
60071 }
60072 }
60073 }
60074 <?php
60075
60076
60077
60078
60079
60080
60081
60082
60083
60084
60085 namespace Symfony\Component\Console\Style;
60086
60087 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
60088 use Symfony\Component\Console\Helper\ProgressBar;
60089 use Symfony\Component\Console\Output\OutputInterface;
60090
60091
60092
60093
60094
60095
60096 abstract class OutputStyle implements OutputInterface, StyleInterface
60097 {
60098 private $output;
60099
60100 public function __construct(OutputInterface $output)
60101 {
60102 $this->output = $output;
60103 }
60104
60105
60106
60107
60108 public function newLine($count = 1)
60109 {
60110 $this->output->write(str_repeat(PHP_EOL, $count));
60111 }
60112
60113
60114
60115
60116
60117
60118 public function createProgressBar($max = 0)
60119 {
60120 return new ProgressBar($this->output, $max);
60121 }
60122
60123
60124
60125
60126 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
60127 {
60128 $this->output->write($messages, $newline, $type);
60129 }
60130
60131
60132
60133
60134 public function writeln($messages, $type = self::OUTPUT_NORMAL)
60135 {
60136 $this->output->writeln($messages, $type);
60137 }
60138
60139
60140
60141
60142 public function setVerbosity($level)
60143 {
60144 $this->output->setVerbosity($level);
60145 }
60146
60147
60148
60149
60150 public function getVerbosity()
60151 {
60152 return $this->output->getVerbosity();
60153 }
60154
60155
60156
60157
60158 public function setDecorated($decorated)
60159 {
60160 $this->output->setDecorated($decorated);
60161 }
60162
60163
60164
60165
60166 public function isDecorated()
60167 {
60168 return $this->output->isDecorated();
60169 }
60170
60171
60172
60173
60174 public function setFormatter(OutputFormatterInterface $formatter)
60175 {
60176 $this->output->setFormatter($formatter);
60177 }
60178
60179
60180
60181
60182 public function getFormatter()
60183 {
60184 return $this->output->getFormatter();
60185 }
60186 }
60187 <?php
60188
60189
60190
60191
60192
60193
60194
60195
60196
60197
60198 namespace Symfony\Component\Console\Style;
60199
60200
60201
60202
60203
60204
60205 interface StyleInterface
60206 {
60207
60208
60209
60210
60211
60212 public function title($message);
60213
60214
60215
60216
60217
60218
60219 public function section($message);
60220
60221
60222
60223
60224 public function listing(array $elements);
60225
60226
60227
60228
60229
60230
60231 public function text($message);
60232
60233
60234
60235
60236
60237
60238 public function success($message);
60239
60240
60241
60242
60243
60244
60245 public function error($message);
60246
60247
60248
60249
60250
60251
60252 public function warning($message);
60253
60254
60255
60256
60257
60258
60259 public function note($message);
60260
60261
60262
60263
60264
60265
60266 public function caution($message);
60267
60268
60269
60270
60271 public function table(array $headers, array $rows);
60272
60273
60274
60275
60276
60277
60278
60279
60280
60281
60282 public function ask($question, $default = null, $validator = null);
60283
60284
60285
60286
60287
60288
60289
60290
60291
60292 public function askHidden($question, $validator = null);
60293
60294
60295
60296
60297
60298
60299
60300
60301
60302 public function confirm($question, $default = true);
60303
60304
60305
60306
60307
60308
60309
60310
60311
60312
60313 public function choice($question, array $choices, $default = null);
60314
60315
60316
60317
60318
60319
60320 public function newLine($count = 1);
60321
60322
60323
60324
60325
60326
60327 public function progressStart($max = 0);
60328
60329
60330
60331
60332
60333
60334 public function progressAdvance($step = 1);
60335
60336
60337
60338
60339 public function progressFinish();
60340 }
60341 <?php
60342
60343
60344
60345
60346
60347
60348
60349
60350
60351
60352 namespace Symfony\Component\Console\Style;
60353
60354 use Symfony\Component\Console\Application;
60355 use Symfony\Component\Console\Exception\RuntimeException;
60356 use Symfony\Component\Console\Formatter\OutputFormatter;
60357 use Symfony\Component\Console\Helper\Helper;
60358 use Symfony\Component\Console\Helper\ProgressBar;
60359 use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
60360 use Symfony\Component\Console\Helper\Table;
60361 use Symfony\Component\Console\Input\InputInterface;
60362 use Symfony\Component\Console\Output\BufferedOutput;
60363 use Symfony\Component\Console\Output\OutputInterface;
60364 use Symfony\Component\Console\Question\ChoiceQuestion;
60365 use Symfony\Component\Console\Question\ConfirmationQuestion;
60366 use Symfony\Component\Console\Question\Question;
60367
60368
60369
60370
60371
60372
60373 class SymfonyStyle extends OutputStyle
60374 {
60375 const MAX_LINE_LENGTH = 120;
60376
60377 private $input;
60378 private $questionHelper;
60379 private $progressBar;
60380 private $lineLength;
60381 private $bufferedOutput;
60382
60383 public function __construct(InputInterface $input, OutputInterface $output)
60384 {
60385 $this->input = $input;
60386 $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
60387
60388  $this->lineLength = min($this->getTerminalWidth() - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
60389
60390 parent::__construct($output);
60391 }
60392
60393
60394
60395
60396
60397
60398
60399
60400
60401
60402 public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
60403 {
60404 $messages = is_array($messages) ? array_values($messages) : array($messages);
60405
60406 $this->autoPrependBlock();
60407 $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, true));
60408 $this->newLine();
60409 }
60410
60411
60412
60413
60414 public function title($message)
60415 {
60416 $this->autoPrependBlock();
60417 $this->writeln(array(
60418 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
60419 sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
60420 ));
60421 $this->newLine();
60422 }
60423
60424
60425
60426
60427 public function section($message)
60428 {
60429 $this->autoPrependBlock();
60430 $this->writeln(array(
60431 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
60432 sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
60433 ));
60434 $this->newLine();
60435 }
60436
60437
60438
60439
60440 public function listing(array $elements)
60441 {
60442 $this->autoPrependText();
60443 $elements = array_map(function ($element) {
60444 return sprintf(' * %s', $element);
60445 }, $elements);
60446
60447 $this->writeln($elements);
60448 $this->newLine();
60449 }
60450
60451
60452
60453
60454 public function text($message)
60455 {
60456 $this->autoPrependText();
60457
60458 $messages = is_array($message) ? array_values($message) : array($message);
60459 foreach ($messages as $message) {
60460 $this->writeln(sprintf(' %s', $message));
60461 }
60462 }
60463
60464
60465
60466
60467
60468
60469 public function comment($message)
60470 {
60471 $messages = is_array($message) ? array_values($message) : array($message);
60472
60473 $this->autoPrependBlock();
60474 $this->writeln($this->createBlock($messages, null, null, '<fg=default;bg=default> // </>'));
60475 $this->newLine();
60476 }
60477
60478
60479
60480
60481 public function success($message)
60482 {
60483 $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
60484 }
60485
60486
60487
60488
60489 public function error($message)
60490 {
60491 $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
60492 }
60493
60494
60495
60496
60497 public function warning($message)
60498 {
60499 $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
60500 }
60501
60502
60503
60504
60505 public function note($message)
60506 {
60507 $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
60508 }
60509
60510
60511
60512
60513 public function caution($message)
60514 {
60515 $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
60516 }
60517
60518
60519
60520
60521 public function table(array $headers, array $rows)
60522 {
60523 $style = clone Table::getStyleDefinition('symfony-style-guide');
60524 $style->setCellHeaderFormat('<info>%s</info>');
60525
60526 $table = new Table($this);
60527 $table->setHeaders($headers);
60528 $table->setRows($rows);
60529 $table->setStyle($style);
60530
60531 $table->render();
60532 $this->newLine();
60533 }
60534
60535
60536
60537
60538 public function ask($question, $default = null, $validator = null)
60539 {
60540 $question = new Question($question, $default);
60541 $question->setValidator($validator);
60542
60543 return $this->askQuestion($question);
60544 }
60545
60546
60547
60548
60549 public function askHidden($question, $validator = null)
60550 {
60551 $question = new Question($question);
60552
60553 $question->setHidden(true);
60554 $question->setValidator($validator);
60555
60556 return $this->askQuestion($question);
60557 }
60558
60559
60560
60561
60562 public function confirm($question, $default = true)
60563 {
60564 return $this->askQuestion(new ConfirmationQuestion($question, $default));
60565 }
60566
60567
60568
60569
60570 public function choice($question, array $choices, $default = null)
60571 {
60572 if (null !== $default) {
60573 $values = array_flip($choices);
60574 $default = $values[$default];
60575 }
60576
60577 return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
60578 }
60579
60580
60581
60582
60583 public function progressStart($max = 0)
60584 {
60585 $this->progressBar = $this->createProgressBar($max);
60586 $this->progressBar->start();
60587 }
60588
60589
60590
60591
60592 public function progressAdvance($step = 1)
60593 {
60594 $this->getProgressBar()->advance($step);
60595 }
60596
60597
60598
60599
60600 public function progressFinish()
60601 {
60602 $this->getProgressBar()->finish();
60603 $this->newLine(2);
60604 $this->progressBar = null;
60605 }
60606
60607
60608
60609
60610 public function createProgressBar($max = 0)
60611 {
60612 $progressBar = parent::createProgressBar($max);
60613
60614 if ('\\' !== DIRECTORY_SEPARATOR) {
60615 $progressBar->setEmptyBarCharacter('░'); 
60616  $progressBar->setProgressCharacter('');
60617 $progressBar->setBarCharacter('▓'); 
60618  }
60619
60620 return $progressBar;
60621 }
60622
60623
60624
60625
60626 public function askQuestion(Question $question)
60627 {
60628 if ($this->input->isInteractive()) {
60629 $this->autoPrependBlock();
60630 }
60631
60632 if (!$this->questionHelper) {
60633 $this->questionHelper = new SymfonyQuestionHelper();
60634 }
60635
60636 $answer = $this->questionHelper->ask($this->input, $this, $question);
60637
60638 if ($this->input->isInteractive()) {
60639 $this->newLine();
60640 $this->bufferedOutput->write("\n");
60641 }
60642
60643 return $answer;
60644 }
60645
60646
60647
60648
60649 public function writeln($messages, $type = self::OUTPUT_NORMAL)
60650 {
60651 parent::writeln($messages, $type);
60652 $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
60653 }
60654
60655
60656
60657
60658 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
60659 {
60660 parent::write($messages, $newline, $type);
60661 $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
60662 }
60663
60664
60665
60666
60667 public function newLine($count = 1)
60668 {
60669 parent::newLine($count);
60670 $this->bufferedOutput->write(str_repeat("\n", $count));
60671 }
60672
60673
60674
60675
60676 private function getProgressBar()
60677 {
60678 if (!$this->progressBar) {
60679 throw new RuntimeException('The ProgressBar is not started.');
60680 }
60681
60682 return $this->progressBar;
60683 }
60684
60685 private function getTerminalWidth()
60686 {
60687 $application = new Application();
60688 $dimensions = $application->getTerminalDimensions();
60689
60690 return $dimensions[0] ?: self::MAX_LINE_LENGTH;
60691 }
60692
60693 private function autoPrependBlock()
60694 {
60695 $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
60696
60697 if (!isset($chars[0])) {
60698 return $this->newLine(); 
60699  }
60700
60701  $this->newLine(2 - substr_count($chars, "\n"));
60702 }
60703
60704 private function autoPrependText()
60705 {
60706 $fetched = $this->bufferedOutput->fetch();
60707
60708  if ("\n" !== substr($fetched, -1)) {
60709 $this->newLine();
60710 }
60711 }
60712
60713 private function reduceBuffer($messages)
60714 {
60715
60716  
60717  return array_map(function ($value) {
60718 return substr($value, -4);
60719 }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
60720 }
60721
60722 private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
60723 {
60724 $indentLength = 0;
60725 $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
60726 $lines = array();
60727
60728 if (null !== $type) {
60729 $type = sprintf('[%s] ', $type);
60730 $indentLength = strlen($type);
60731 $lineIndentation = str_repeat(' ', $indentLength);
60732 }
60733
60734
60735  foreach ($messages as $key => $message) {
60736 if ($escape) {
60737 $message = OutputFormatter::escape($message);
60738 }
60739
60740 $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
60741
60742 if (count($messages) > 1 && $key < count($messages) - 1) {
60743 $lines[] = '';
60744 }
60745 }
60746
60747 $firstLineIndex = 0;
60748 if ($padding && $this->isDecorated()) {
60749 $firstLineIndex = 1;
60750 array_unshift($lines, '');
60751 $lines[] = '';
60752 }
60753
60754 foreach ($lines as $i => &$line) {
60755 if (null !== $type) {
60756 $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
60757 }
60758
60759 $line = $prefix.$line;
60760 $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
60761
60762 if ($style) {
60763 $line = sprintf('<%s>%s</>', $style, $line);
60764 }
60765 }
60766
60767 return $lines;
60768 }
60769 }
60770 <?php
60771
60772
60773
60774
60775
60776
60777
60778
60779
60780
60781 namespace Symfony\Component\Console\Tester;
60782
60783 use Symfony\Component\Console\Application;
60784 use Symfony\Component\Console\Input\ArrayInput;
60785 use Symfony\Component\Console\Input\InputInterface;
60786 use Symfony\Component\Console\Output\OutputInterface;
60787 use Symfony\Component\Console\Output\StreamOutput;
60788
60789
60790
60791
60792
60793
60794
60795
60796
60797
60798
60799 class ApplicationTester
60800 {
60801 private $application;
60802 private $input;
60803 private $output;
60804 private $statusCode;
60805
60806 public function __construct(Application $application)
60807 {
60808 $this->application = $application;
60809 }
60810
60811
60812
60813
60814
60815
60816
60817
60818
60819
60820
60821
60822
60823
60824
60825 public function run(array $input, $options = array())
60826 {
60827 $this->input = new ArrayInput($input);
60828 if (isset($options['interactive'])) {
60829 $this->input->setInteractive($options['interactive']);
60830 }
60831
60832 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
60833 if (isset($options['decorated'])) {
60834 $this->output->setDecorated($options['decorated']);
60835 }
60836 if (isset($options['verbosity'])) {
60837 $this->output->setVerbosity($options['verbosity']);
60838 }
60839
60840 return $this->statusCode = $this->application->run($this->input, $this->output);
60841 }
60842
60843
60844
60845
60846
60847
60848
60849
60850 public function getDisplay($normalize = false)
60851 {
60852 rewind($this->output->getStream());
60853
60854 $display = stream_get_contents($this->output->getStream());
60855
60856 if ($normalize) {
60857 $display = str_replace(PHP_EOL, "\n", $display);
60858 }
60859
60860 return $display;
60861 }
60862
60863
60864
60865
60866
60867
60868 public function getInput()
60869 {
60870 return $this->input;
60871 }
60872
60873
60874
60875
60876
60877
60878 public function getOutput()
60879 {
60880 return $this->output;
60881 }
60882
60883
60884
60885
60886
60887
60888 public function getStatusCode()
60889 {
60890 return $this->statusCode;
60891 }
60892 }
60893 <?php
60894
60895
60896
60897
60898
60899
60900
60901
60902
60903
60904 namespace Symfony\Component\Console\Tester;
60905
60906 use Symfony\Component\Console\Command\Command;
60907 use Symfony\Component\Console\Input\ArrayInput;
60908 use Symfony\Component\Console\Output\StreamOutput;
60909 use Symfony\Component\Console\Input\InputInterface;
60910 use Symfony\Component\Console\Output\OutputInterface;
60911
60912
60913
60914
60915
60916
60917 class CommandTester
60918 {
60919 private $command;
60920 private $input;
60921 private $output;
60922 private $statusCode;
60923
60924 public function __construct(Command $command)
60925 {
60926 $this->command = $command;
60927 }
60928
60929
60930
60931
60932
60933
60934
60935
60936
60937
60938
60939
60940
60941
60942
60943 public function execute(array $input, array $options = array())
60944 {
60945
60946  
60947  if (!isset($input['command'])
60948 && (null !== $application = $this->command->getApplication())
60949 && $application->getDefinition()->hasArgument('command')
60950 ) {
60951 $input = array_merge(array('command' => $this->command->getName()), $input);
60952 }
60953
60954 $this->input = new ArrayInput($input);
60955 if (isset($options['interactive'])) {
60956 $this->input->setInteractive($options['interactive']);
60957 }
60958
60959 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
60960 $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
60961 if (isset($options['verbosity'])) {
60962 $this->output->setVerbosity($options['verbosity']);
60963 }
60964
60965 return $this->statusCode = $this->command->run($this->input, $this->output);
60966 }
60967
60968
60969
60970
60971
60972
60973
60974
60975 public function getDisplay($normalize = false)
60976 {
60977 rewind($this->output->getStream());
60978
60979 $display = stream_get_contents($this->output->getStream());
60980
60981 if ($normalize) {
60982 $display = str_replace(PHP_EOL, "\n", $display);
60983 }
60984
60985 return $display;
60986 }
60987
60988
60989
60990
60991
60992
60993 public function getInput()
60994 {
60995 return $this->input;
60996 }
60997
60998
60999
61000
61001
61002
61003 public function getOutput()
61004 {
61005 return $this->output;
61006 }
61007
61008
61009
61010
61011
61012
61013 public function getStatusCode()
61014 {
61015 return $this->statusCode;
61016 }
61017 }
61018 <?php
61019
61020
61021
61022
61023
61024
61025
61026
61027
61028
61029 namespace Symfony\Component\Debug;
61030
61031 use Psr\Log\AbstractLogger;
61032
61033
61034
61035
61036
61037
61038 class BufferingLogger extends AbstractLogger
61039 {
61040 private $logs = array();
61041
61042 public function log($level, $message, array $context = array())
61043 {
61044 $this->logs[] = array($level, $message, $context);
61045 }
61046
61047 public function cleanLogs()
61048 {
61049 $logs = $this->logs;
61050 $this->logs = array();
61051
61052 return $logs;
61053 }
61054 }
61055 <?php
61056
61057
61058
61059
61060
61061
61062
61063
61064
61065
61066 namespace Symfony\Component\Debug;
61067
61068
61069
61070
61071
61072
61073 class Debug
61074 {
61075 private static $enabled = false;
61076
61077
61078
61079
61080
61081
61082
61083
61084
61085
61086
61087
61088 public static function enable($errorReportingLevel = null, $displayErrors = true)
61089 {
61090 if (static::$enabled) {
61091 return;
61092 }
61093
61094 static::$enabled = true;
61095
61096 if (null !== $errorReportingLevel) {
61097 error_reporting($errorReportingLevel);
61098 } else {
61099 error_reporting(-1);
61100 }
61101
61102 if ('cli' !== PHP_SAPI) {
61103 ini_set('display_errors', 0);
61104 ExceptionHandler::register();
61105 } elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
61106
61107  ini_set('display_errors', 1);
61108 }
61109 if ($displayErrors) {
61110 ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
61111 } else {
61112 ErrorHandler::register()->throwAt(0, true);
61113 }
61114
61115 DebugClassLoader::enable();
61116 }
61117 }
61118 <?php
61119
61120
61121
61122
61123
61124
61125
61126
61127
61128
61129 namespace Symfony\Component\Debug;
61130
61131
61132
61133
61134
61135
61136
61137
61138
61139
61140
61141
61142 class DebugClassLoader
61143 {
61144 private $classLoader;
61145 private $isFinder;
61146 private $loaded = array();
61147 private $wasFinder;
61148 private static $caseCheck;
61149 private static $deprecated = array();
61150 private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
61151 private static $darwinCache = array('/' => array('/', array()));
61152
61153
61154
61155
61156 public function __construct($classLoader)
61157 {
61158 $this->wasFinder = is_object($classLoader) && method_exists($classLoader, 'findFile');
61159
61160 if ($this->wasFinder) {
61161 @trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
61162 $this->classLoader = array($classLoader, 'loadClass');
61163 $this->isFinder = true;
61164 } else {
61165 $this->classLoader = $classLoader;
61166 $this->isFinder = is_array($classLoader) && method_exists($classLoader[0], 'findFile');
61167 }
61168
61169 if (!isset(self::$caseCheck)) {
61170 $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR);
61171 $i = strrpos($file, DIRECTORY_SEPARATOR);
61172 $dir = substr($file, 0, 1 + $i);
61173 $file = substr($file, 1 + $i);
61174 $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
61175 $test = realpath($dir.$test);
61176
61177 if (false === $test || false === $i) {
61178
61179  self::$caseCheck = 0;
61180 } elseif (substr($test, -strlen($file)) === $file) {
61181
61182  self::$caseCheck = 1;
61183 } elseif (false !== stripos(PHP_OS, 'darwin')) {
61184
61185  self::$caseCheck = 2;
61186 } else {
61187
61188  self::$caseCheck = 0;
61189 }
61190 }
61191 }
61192
61193
61194
61195
61196
61197
61198 public function getClassLoader()
61199 {
61200 return $this->wasFinder ? $this->classLoader[0] : $this->classLoader;
61201 }
61202
61203
61204
61205
61206 public static function enable()
61207 {
61208
61209  class_exists('Symfony\Component\Debug\ErrorHandler');
61210 class_exists('Psr\Log\LogLevel');
61211
61212 if (!is_array($functions = spl_autoload_functions())) {
61213 return;
61214 }
61215
61216 foreach ($functions as $function) {
61217 spl_autoload_unregister($function);
61218 }
61219
61220 foreach ($functions as $function) {
61221 if (!is_array($function) || !$function[0] instanceof self) {
61222 $function = array(new static($function), 'loadClass');
61223 }
61224
61225 spl_autoload_register($function);
61226 }
61227 }
61228
61229
61230
61231
61232 public static function disable()
61233 {
61234 if (!is_array($functions = spl_autoload_functions())) {
61235 return;
61236 }
61237
61238 foreach ($functions as $function) {
61239 spl_autoload_unregister($function);
61240 }
61241
61242 foreach ($functions as $function) {
61243 if (is_array($function) && $function[0] instanceof self) {
61244 $function = $function[0]->getClassLoader();
61245 }
61246
61247 spl_autoload_register($function);
61248 }
61249 }
61250
61251
61252
61253
61254
61255
61256
61257
61258
61259
61260 public function findFile($class)
61261 {
61262 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
61263
61264 if ($this->wasFinder) {
61265 return $this->classLoader[0]->findFile($class);
61266 }
61267 }
61268
61269
61270
61271
61272
61273
61274
61275
61276
61277
61278 public function loadClass($class)
61279 {
61280 ErrorHandler::stackErrors();
61281
61282 try {
61283 if ($this->isFinder && !isset($this->loaded[$class])) {
61284 $this->loaded[$class] = true;
61285 if ($file = $this->classLoader[0]->findFile($class)) {
61286 require $file;
61287 }
61288 } else {
61289 call_user_func($this->classLoader, $class);
61290 $file = false;
61291 }
61292 } catch (\Exception $e) {
61293 ErrorHandler::unstackErrors();
61294
61295 throw $e;
61296 } catch (\Throwable $e) {
61297 ErrorHandler::unstackErrors();
61298
61299 throw $e;
61300 }
61301
61302 ErrorHandler::unstackErrors();
61303
61304 $exists = class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
61305
61306 if ($class && '\\' === $class[0]) {
61307 $class = substr($class, 1);
61308 }
61309
61310 if ($exists) {
61311 $refl = new \ReflectionClass($class);
61312 $name = $refl->getName();
61313
61314 if ($name !== $class && 0 === strcasecmp($name, $class)) {
61315 throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name));
61316 }
61317
61318 if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
61319 @trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
61320 } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
61321 self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
61322 } else {
61323 if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
61324 $len = 0;
61325 $ns = '';
61326 } else {
61327 $ns = substr($name, 0, $len);
61328 }
61329 $parent = get_parent_class($class);
61330
61331 if (!$parent || strncmp($ns, $parent, $len)) {
61332 if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
61333 @trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
61334 }
61335
61336 $parentInterfaces = array();
61337 $deprecatedInterfaces = array();
61338 if ($parent) {
61339 foreach (class_implements($parent) as $interface) {
61340 $parentInterfaces[$interface] = 1;
61341 }
61342 }
61343
61344 foreach ($refl->getInterfaceNames() as $interface) {
61345 if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
61346 $deprecatedInterfaces[] = $interface;
61347 }
61348 foreach (class_implements($interface) as $interface) {
61349 $parentInterfaces[$interface] = 1;
61350 }
61351 }
61352
61353 foreach ($deprecatedInterfaces as $interface) {
61354 if (!isset($parentInterfaces[$interface])) {
61355 @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);
61356 }
61357 }
61358 }
61359 }
61360 }
61361
61362 if ($file) {
61363 if (!$exists) {
61364 if (false !== strpos($class, '/')) {
61365 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));
61366 }
61367
61368 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));
61369 }
61370 if (self::$caseCheck) {
61371 $real = explode('\\', $class.strrchr($file, '.'));
61372 $tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file));
61373
61374 $i = count($tail) - 1;
61375 $j = count($real) - 1;
61376
61377 while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
61378 --$i;
61379 --$j;
61380 }
61381
61382 array_splice($tail, 0, $i + 1);
61383 }
61384 if (self::$caseCheck && $tail) {
61385 $tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail);
61386 $tailLen = strlen($tail);
61387 $real = $refl->getFileName();
61388
61389 if (2 === self::$caseCheck) {
61390
61391
61392 $i = 1 + strrpos($real, '/');
61393 $file = substr($real, $i);
61394 $real = substr($real, 0, $i);
61395
61396 if (isset(self::$darwinCache[$real])) {
61397 $kDir = $real;
61398 } else {
61399 $kDir = strtolower($real);
61400
61401 if (isset(self::$darwinCache[$kDir])) {
61402 $real = self::$darwinCache[$kDir][0];
61403 } else {
61404 $dir = getcwd();
61405 chdir($real);
61406 $real = getcwd().'/';
61407 chdir($dir);
61408
61409 $dir = $real;
61410 $k = $kDir;
61411 $i = strlen($dir) - 1;
61412 while (!isset(self::$darwinCache[$k])) {
61413 self::$darwinCache[$k] = array($dir, array());
61414 self::$darwinCache[$dir] = &self::$darwinCache[$k];
61415
61416 while ('/' !== $dir[--$i]) {
61417 }
61418 $k = substr($k, 0, ++$i);
61419 $dir = substr($dir, 0, $i--);
61420 }
61421 }
61422 }
61423
61424 $dirFiles = self::$darwinCache[$kDir][1];
61425
61426 if (isset($dirFiles[$file])) {
61427 $kFile = $file;
61428 } else {
61429 $kFile = strtolower($file);
61430
61431 if (!isset($dirFiles[$kFile])) {
61432 foreach (scandir($real, 2) as $f) {
61433 if ('.' !== $f[0]) {
61434 $dirFiles[$f] = $f;
61435 if ($f === $file) {
61436 $kFile = $k = $file;
61437 } elseif ($f !== $k = strtolower($f)) {
61438 $dirFiles[$k] = $f;
61439 }
61440 }
61441 }
61442 self::$darwinCache[$kDir][1] = $dirFiles;
61443 }
61444 }
61445
61446 $real .= $dirFiles[$kFile];
61447 }
61448
61449 if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
61450 && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
61451 ) {
61452 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)));
61453 }
61454 }
61455
61456 return true;
61457 }
61458 }
61459 }
61460 <?php
61461
61462
61463
61464
61465
61466
61467
61468
61469
61470
61471 namespace Symfony\Component\Debug;
61472
61473 use Psr\Log\LogLevel;
61474 use Psr\Log\LoggerInterface;
61475 use Symfony\Component\Debug\Exception\ContextErrorException;
61476 use Symfony\Component\Debug\Exception\FatalErrorException;
61477 use Symfony\Component\Debug\Exception\FatalThrowableError;
61478 use Symfony\Component\Debug\Exception\OutOfMemoryException;
61479 use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
61480 use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
61481 use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
61482 use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
61483
61484
61485
61486
61487
61488
61489
61490
61491
61492
61493
61494
61495
61496
61497
61498
61499
61500
61501
61502
61503
61504
61505
61506 class ErrorHandler
61507 {
61508
61509
61510
61511 const TYPE_DEPRECATION = -100;
61512
61513 private $levels = array(
61514 E_DEPRECATED => 'Deprecated',
61515 E_USER_DEPRECATED => 'User Deprecated',
61516 E_NOTICE => 'Notice',
61517 E_USER_NOTICE => 'User Notice',
61518 E_STRICT => 'Runtime Notice',
61519 E_WARNING => 'Warning',
61520 E_USER_WARNING => 'User Warning',
61521 E_COMPILE_WARNING => 'Compile Warning',
61522 E_CORE_WARNING => 'Core Warning',
61523 E_USER_ERROR => 'User Error',
61524 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
61525 E_COMPILE_ERROR => 'Compile Error',
61526 E_PARSE => 'Parse Error',
61527 E_ERROR => 'Error',
61528 E_CORE_ERROR => 'Core Error',
61529 );
61530
61531 private $loggers = array(
61532 E_DEPRECATED => array(null, LogLevel::INFO),
61533 E_USER_DEPRECATED => array(null, LogLevel::INFO),
61534 E_NOTICE => array(null, LogLevel::WARNING),
61535 E_USER_NOTICE => array(null, LogLevel::WARNING),
61536 E_STRICT => array(null, LogLevel::WARNING),
61537 E_WARNING => array(null, LogLevel::WARNING),
61538 E_USER_WARNING => array(null, LogLevel::WARNING),
61539 E_COMPILE_WARNING => array(null, LogLevel::WARNING),
61540 E_CORE_WARNING => array(null, LogLevel::WARNING),
61541 E_USER_ERROR => array(null, LogLevel::CRITICAL),
61542 E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
61543 E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
61544 E_PARSE => array(null, LogLevel::CRITICAL),
61545 E_ERROR => array(null, LogLevel::CRITICAL),
61546 E_CORE_ERROR => array(null, LogLevel::CRITICAL),
61547 );
61548
61549 private $thrownErrors = 0x1FFF; 
61550  private $scopedErrors = 0x1FFF; 
61551  private $tracedErrors = 0x77FB; 
61552  private $screamedErrors = 0x55; 
61553  private $loggedErrors = 0;
61554
61555 private $loggedTraces = array();
61556 private $isRecursive = 0;
61557 private $isRoot = false;
61558 private $exceptionHandler;
61559 private $bootstrappingLogger;
61560
61561 private static $reservedMemory;
61562 private static $stackedErrors = array();
61563 private static $stackedErrorLevels = array();
61564 private static $toStringException = null;
61565 private static $exitCode = 0;
61566
61567
61568
61569
61570
61571
61572 private $displayErrors = 0x1FFF;
61573
61574
61575
61576
61577
61578
61579
61580
61581
61582 public static function register($handler = null, $replace = true)
61583 {
61584 if (null === self::$reservedMemory) {
61585 self::$reservedMemory = str_repeat('x', 10240);
61586 register_shutdown_function(__CLASS__.'::handleFatalError');
61587 }
61588
61589 $levels = -1;
61590
61591 if ($handlerIsNew = !$handler instanceof self) {
61592
61593  if (null !== $handler) {
61594 $levels = $replace ? $handler : 0;
61595 $replace = true;
61596 }
61597 $handler = new static();
61598 }
61599
61600 if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
61601 restore_error_handler();
61602
61603  set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
61604 $handler->isRoot = true;
61605 }
61606
61607 if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) {
61608 $handler = $prev[0];
61609 $replace = false;
61610 }
61611 if ($replace || !$prev) {
61612 $handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException')));
61613 } else {
61614 restore_error_handler();
61615 }
61616
61617 $handler->throwAt($levels & $handler->thrownErrors, true);
61618
61619 return $handler;
61620 }
61621
61622 public function __construct(BufferingLogger $bootstrappingLogger = null)
61623 {
61624 if ($bootstrappingLogger) {
61625 $this->bootstrappingLogger = $bootstrappingLogger;
61626 $this->setDefaultLogger($bootstrappingLogger);
61627 }
61628 }
61629
61630
61631
61632
61633
61634
61635
61636
61637 public function setDefaultLogger(LoggerInterface $logger, $levels = null, $replace = false)
61638 {
61639 $loggers = array();
61640
61641 if (is_array($levels)) {
61642 foreach ($levels as $type => $logLevel) {
61643 if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
61644 $loggers[$type] = array($logger, $logLevel);
61645 }
61646 }
61647 } else {
61648 if (null === $levels) {
61649 $levels = E_ALL | E_STRICT;
61650 }
61651 foreach ($this->loggers as $type => $log) {
61652 if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
61653 $log[0] = $logger;
61654 $loggers[$type] = $log;
61655 }
61656 }
61657 }
61658
61659 $this->setLoggers($loggers);
61660 }
61661
61662
61663
61664
61665
61666
61667
61668
61669
61670
61671 public function setLoggers(array $loggers)
61672 {
61673 $prevLogged = $this->loggedErrors;
61674 $prev = $this->loggers;
61675 $flush = array();
61676
61677 foreach ($loggers as $type => $log) {
61678 if (!isset($prev[$type])) {
61679 throw new \InvalidArgumentException('Unknown error type: '.$type);
61680 }
61681 if (!is_array($log)) {
61682 $log = array($log);
61683 } elseif (!array_key_exists(0, $log)) {
61684 throw new \InvalidArgumentException('No logger provided');
61685 }
61686 if (null === $log[0]) {
61687 $this->loggedErrors &= ~$type;
61688 } elseif ($log[0] instanceof LoggerInterface) {
61689 $this->loggedErrors |= $type;
61690 } else {
61691 throw new \InvalidArgumentException('Invalid logger provided');
61692 }
61693 $this->loggers[$type] = $log + $prev[$type];
61694
61695 if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
61696 $flush[$type] = $type;
61697 }
61698 }
61699 $this->reRegister($prevLogged | $this->thrownErrors);
61700
61701 if ($flush) {
61702 foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
61703 $type = $log[2]['type'];
61704 if (!isset($flush[$type])) {
61705 $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
61706 } elseif ($this->loggers[$type][0]) {
61707 $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
61708 }
61709 }
61710 }
61711
61712 return $prev;
61713 }
61714
61715
61716
61717
61718
61719
61720
61721
61722
61723
61724 public function setExceptionHandler($handler)
61725 {
61726 if (null !== $handler && !is_callable($handler)) {
61727 throw new \LogicException('The exception handler must be a valid PHP callable.');
61728 }
61729 $prev = $this->exceptionHandler;
61730 $this->exceptionHandler = $handler;
61731
61732 return $prev;
61733 }
61734
61735
61736
61737
61738
61739
61740
61741
61742
61743 public function throwAt($levels, $replace = false)
61744 {
61745 $prev = $this->thrownErrors;
61746 $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
61747 if (!$replace) {
61748 $this->thrownErrors |= $prev;
61749 }
61750 $this->reRegister($prev | $this->loggedErrors);
61751
61752
61753  $this->displayErrors = $this->thrownErrors;
61754
61755 return $prev;
61756 }
61757
61758
61759
61760
61761
61762
61763
61764
61765
61766 public function scopeAt($levels, $replace = false)
61767 {
61768 $prev = $this->scopedErrors;
61769 $this->scopedErrors = (int) $levels;
61770 if (!$replace) {
61771 $this->scopedErrors |= $prev;
61772 }
61773
61774 return $prev;
61775 }
61776
61777
61778
61779
61780
61781
61782
61783
61784
61785 public function traceAt($levels, $replace = false)
61786 {
61787 $prev = $this->tracedErrors;
61788 $this->tracedErrors = (int) $levels;
61789 if (!$replace) {
61790 $this->tracedErrors |= $prev;
61791 }
61792
61793 return $prev;
61794 }
61795
61796
61797
61798
61799
61800
61801
61802
61803
61804 public function screamAt($levels, $replace = false)
61805 {
61806 $prev = $this->screamedErrors;
61807 $this->screamedErrors = (int) $levels;
61808 if (!$replace) {
61809 $this->screamedErrors |= $prev;
61810 }
61811
61812 return $prev;
61813 }
61814
61815
61816
61817
61818 private function reRegister($prev)
61819 {
61820 if ($prev !== $this->thrownErrors | $this->loggedErrors) {
61821 $handler = set_error_handler('var_dump');
61822 $handler = is_array($handler) ? $handler[0] : null;
61823 restore_error_handler();
61824 if ($handler === $this) {
61825 restore_error_handler();
61826 if ($this->isRoot) {
61827 set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
61828 } else {
61829 set_error_handler(array($this, 'handleError'));
61830 }
61831 }
61832 }
61833 }
61834
61835
61836
61837
61838
61839
61840
61841
61842
61843
61844
61845
61846
61847
61848
61849 public function handleError($type, $message, $file, $line)
61850 {
61851 $level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
61852 $log = $this->loggedErrors & $type;
61853 $throw = $this->thrownErrors & $type & $level;
61854 $type &= $level | $this->screamedErrors;
61855
61856 if (!$type || (!$log && !$throw)) {
61857 return $type && $log;
61858 }
61859 $scope = $this->scopedErrors & $type;
61860
61861 if (4 < $numArgs = func_num_args()) {
61862 $context = $scope ? (func_get_arg(4) ?: array()) : array();
61863 $backtrace = 5 < $numArgs ? func_get_arg(5) : null; 
61864  } else {
61865 $context = array();
61866 $backtrace = null;
61867 }
61868
61869 if (isset($context['GLOBALS']) && $scope) {
61870 $e = $context; 
61871  unset($e['GLOBALS'], $context); 
61872  $context = $e;
61873 }
61874
61875 if (null !== $backtrace && $type & E_ERROR) {
61876
61877  
61878  
61879  $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
61880
61881 return true;
61882 }
61883
61884 if ($throw) {
61885 if (null !== self::$toStringException) {
61886 $throw = self::$toStringException;
61887 self::$toStringException = null;
61888 } elseif ($scope && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
61889
61890  $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
61891 } else {
61892 $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
61893 }
61894
61895 if (\PHP_VERSION_ID <= 50407 && (\PHP_VERSION_ID >= 50400 || \PHP_VERSION_ID <= 50317)) {
61896
61897  
61898  
61899
61900 $throw->errorHandlerCanary = new ErrorHandlerCanary();
61901 }
61902
61903 if (E_USER_ERROR & $type) {
61904 $backtrace = $backtrace ?: $throw->getTrace();
61905
61906 for ($i = 1; isset($backtrace[$i]); ++$i) {
61907 if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
61908 && '__toString' === $backtrace[$i]['function']
61909 && '->' === $backtrace[$i]['type']
61910 && !isset($backtrace[$i - 1]['class'])
61911 && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
61912 ) {
61913
61914  
61915  
61916  
61917  
61918  
61919
61920 foreach ($context as $e) {
61921 if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
61922 if (1 === $i) {
61923
61924  $throw = $e;
61925 break;
61926 }
61927 self::$toStringException = $e;
61928
61929 return true;
61930 }
61931 }
61932
61933 if (1 < $i) {
61934
61935  $this->handleException($throw);
61936
61937
61938  return false;
61939 }
61940 }
61941 }
61942 }
61943
61944 throw $throw;
61945 }
61946
61947
61948  $e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
61949 $trace = true;
61950
61951 if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
61952 $trace = false;
61953 } else {
61954 $this->loggedTraces[$e] = 1;
61955 }
61956
61957 $e = compact('type', 'file', 'line', 'level');
61958
61959 if ($type & $level) {
61960 if ($scope) {
61961 $e['scope_vars'] = $context;
61962 if ($trace) {
61963 $e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
61964 }
61965 } elseif ($trace) {
61966 if (null === $backtrace) {
61967 $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
61968 } else {
61969 foreach ($backtrace as &$frame) {
61970 unset($frame['args'], $frame);
61971 }
61972 $e['stack'] = $backtrace;
61973 }
61974 }
61975 }
61976
61977 if ($this->isRecursive) {
61978 $log = 0;
61979 } elseif (self::$stackedErrorLevels) {
61980 self::$stackedErrors[] = array($this->loggers[$type][0], ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
61981 } else {
61982 try {
61983 $this->isRecursive = true;
61984 $this->loggers[$type][0]->log(($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
61985 $this->isRecursive = false;
61986 } catch (\Exception $e) {
61987 $this->isRecursive = false;
61988
61989 throw $e;
61990 } catch (\Throwable $e) {
61991 $this->isRecursive = false;
61992
61993 throw $e;
61994 }
61995 }
61996
61997 return $type && $log;
61998 }
61999
62000
62001
62002
62003
62004
62005
62006
62007
62008 public function handleException($exception, array $error = null)
62009 {
62010 if (null === $error) {
62011 self::$exitCode = 255;
62012 }
62013 if (!$exception instanceof \Exception) {
62014 $exception = new FatalThrowableError($exception);
62015 }
62016 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
62017
62018 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
62019 $e = array(
62020 'type' => $type,
62021 'file' => $exception->getFile(),
62022 'line' => $exception->getLine(),
62023 'level' => error_reporting(),
62024 'stack' => $exception->getTrace(),
62025 );
62026 if ($exception instanceof FatalErrorException) {
62027 if ($exception instanceof FatalThrowableError) {
62028 $error = array(
62029 'type' => $type,
62030 'message' => $message = $exception->getMessage(),
62031 'file' => $e['file'],
62032 'line' => $e['line'],
62033 );
62034 } else {
62035 $message = 'Fatal '.$exception->getMessage();
62036 }
62037 } elseif ($exception instanceof \ErrorException) {
62038 $message = 'Uncaught '.$exception->getMessage();
62039 if ($exception instanceof ContextErrorException) {
62040 $e['context'] = $exception->getContext();
62041 }
62042 } else {
62043 $message = 'Uncaught Exception: '.$exception->getMessage();
62044 }
62045 }
62046 if ($this->loggedErrors & $type) {
62047 try {
62048 $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
62049 } catch (\Exception $handlerException) {
62050 } catch (\Throwable $handlerException) {
62051 }
62052 }
62053 if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
62054 foreach ($this->getFatalErrorHandlers() as $handler) {
62055 if ($e = $handler->handleError($error, $exception)) {
62056 $exception = $e;
62057 break;
62058 }
62059 }
62060 }
62061 if (empty($this->exceptionHandler)) {
62062 throw $exception; 
62063  }
62064 try {
62065 call_user_func($this->exceptionHandler, $exception);
62066 } catch (\Exception $handlerException) {
62067 } catch (\Throwable $handlerException) {
62068 }
62069 if (isset($handlerException)) {
62070 $this->exceptionHandler = null;
62071 $this->handleException($handlerException);
62072 }
62073 }
62074
62075
62076
62077
62078
62079
62080
62081
62082 public static function handleFatalError(array $error = null)
62083 {
62084 if (null === self::$reservedMemory) {
62085 return;
62086 }
62087
62088 self::$reservedMemory = null;
62089
62090 $handler = set_error_handler('var_dump');
62091 $handler = is_array($handler) ? $handler[0] : null;
62092 restore_error_handler();
62093
62094 if (!$handler instanceof self) {
62095 return;
62096 }
62097
62098 if ($exit = null === $error) {
62099 $error = error_get_last();
62100 }
62101
62102 try {
62103 while (self::$stackedErrorLevels) {
62104 static::unstackErrors();
62105 }
62106 } catch (\Exception $exception) {
62107
62108  } catch (\Throwable $exception) {
62109
62110  }
62111
62112 if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
62113
62114  $handler->throwAt(0, true);
62115 $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
62116
62117 if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
62118 $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
62119 } else {
62120 $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
62121 }
62122 }
62123
62124 try {
62125 if (isset($exception)) {
62126 self::$exitCode = 255;
62127 $handler->handleException($exception, $error);
62128 }
62129 } catch (FatalErrorException $e) {
62130
62131  }
62132
62133 if ($exit && self::$exitCode) {
62134 $exitCode = self::$exitCode;
62135 register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); });
62136 }
62137 }
62138
62139
62140
62141
62142
62143
62144
62145
62146
62147
62148
62149
62150 public static function stackErrors()
62151 {
62152 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
62153 }
62154
62155
62156
62157
62158 public static function unstackErrors()
62159 {
62160 $level = array_pop(self::$stackedErrorLevels);
62161
62162 if (null !== $level) {
62163 $e = error_reporting($level);
62164 if ($e !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
62165
62166  error_reporting($e);
62167 }
62168 }
62169
62170 if (empty(self::$stackedErrorLevels)) {
62171 $errors = self::$stackedErrors;
62172 self::$stackedErrors = array();
62173
62174 foreach ($errors as $e) {
62175 $e[0]->log($e[1], $e[2], $e[3]);
62176 }
62177 }
62178 }
62179
62180
62181
62182
62183
62184
62185
62186
62187 protected function getFatalErrorHandlers()
62188 {
62189 return array(
62190 new UndefinedFunctionFatalErrorHandler(),
62191 new UndefinedMethodFatalErrorHandler(),
62192 new ClassNotFoundFatalErrorHandler(),
62193 );
62194 }
62195
62196
62197
62198
62199
62200
62201
62202
62203 public function setLevel($level)
62204 {
62205 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the throwAt() method instead.', E_USER_DEPRECATED);
62206
62207 $level = null === $level ? error_reporting() : $level;
62208 $this->throwAt($level, true);
62209 }
62210
62211
62212
62213
62214
62215
62216
62217
62218 public function setDisplayErrors($displayErrors)
62219 {
62220 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the throwAt() method instead.', E_USER_DEPRECATED);
62221
62222 if ($displayErrors) {
62223 $this->throwAt($this->displayErrors, true);
62224 } else {
62225 $displayErrors = $this->displayErrors;
62226 $this->throwAt(0, true);
62227 $this->displayErrors = $displayErrors;
62228 }
62229 }
62230
62231
62232
62233
62234
62235
62236
62237
62238
62239 public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
62240 {
62241 @trigger_error('The '.__METHOD__.' static method is deprecated since version 2.6 and will be removed in 3.0. Use the setLoggers() or setDefaultLogger() methods instead.', E_USER_DEPRECATED);
62242
62243 $handler = set_error_handler('var_dump');
62244 $handler = is_array($handler) ? $handler[0] : null;
62245 restore_error_handler();
62246 if (!$handler instanceof self) {
62247 return;
62248 }
62249 if ('deprecation' === $channel) {
62250 $handler->setDefaultLogger($logger, E_DEPRECATED | E_USER_DEPRECATED, true);
62251 $handler->screamAt(E_DEPRECATED | E_USER_DEPRECATED);
62252 } elseif ('scream' === $channel) {
62253 $handler->setDefaultLogger($logger, E_ALL | E_STRICT, false);
62254 $handler->screamAt(E_ALL | E_STRICT);
62255 } elseif ('emergency' === $channel) {
62256 $handler->setDefaultLogger($logger, E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR, true);
62257 $handler->screamAt(E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
62258 }
62259 }
62260
62261
62262
62263
62264 public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
62265 {
62266 $this->handleError(E_USER_DEPRECATED, 'The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the handleError() method instead.', __FILE__, __LINE__, array());
62267
62268 return $this->handleError($level, $message, $file, $line, (array) $context);
62269 }
62270
62271
62272
62273
62274
62275
62276 public function handleFatal()
62277 {
62278 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the handleFatalError() method instead.', E_USER_DEPRECATED);
62279
62280 static::handleFatalError();
62281 }
62282 }
62283
62284
62285
62286
62287
62288
62289
62290
62291 class ErrorHandlerCanary
62292 {
62293 private static $displayErrors = null;
62294
62295 public function __construct()
62296 {
62297 if (null === self::$displayErrors) {
62298 self::$displayErrors = ini_set('display_errors', 1);
62299 }
62300 }
62301
62302 public function __destruct()
62303 {
62304 if (null !== self::$displayErrors) {
62305 ini_set('display_errors', self::$displayErrors);
62306 self::$displayErrors = null;
62307 }
62308 }
62309 }
62310 <?php
62311
62312
62313
62314
62315
62316
62317
62318
62319
62320
62321 namespace Symfony\Component\Debug\Exception;
62322
62323
62324
62325
62326
62327
62328 class ClassNotFoundException extends FatalErrorException
62329 {
62330 public function __construct($message, \ErrorException $previous)
62331 {
62332 parent::__construct(
62333 $message,
62334 $previous->getCode(),
62335 $previous->getSeverity(),
62336 $previous->getFile(),
62337 $previous->getLine(),
62338 $previous->getPrevious()
62339 );
62340 $this->setTrace($previous->getTrace());
62341 }
62342 }
62343 <?php
62344
62345
62346
62347
62348
62349
62350
62351
62352
62353
62354 namespace Symfony\Component\Debug\Exception;
62355
62356
62357
62358
62359
62360
62361 class ContextErrorException extends \ErrorException
62362 {
62363 private $context = array();
62364
62365 public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
62366 {
62367 parent::__construct($message, $code, $severity, $filename, $lineno);
62368 $this->context = $context;
62369 }
62370
62371
62372
62373
62374 public function getContext()
62375 {
62376 return $this->context;
62377 }
62378 }
62379 <?php
62380
62381
62382
62383
62384
62385
62386
62387
62388
62389
62390 namespace Symfony\Component\Debug\Exception;
62391
62392 @trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
62393
62394
62395
62396
62397
62398
62399 class DummyException extends \ErrorException
62400 {
62401 }
62402 <?php
62403
62404
62405
62406
62407
62408
62409
62410
62411
62412
62413 namespace Symfony\Component\HttpKernel\Exception;
62414
62415
62416
62417
62418
62419
62420
62421
62422
62423
62424 class FatalErrorException extends \ErrorException
62425 {
62426 }
62427
62428 namespace Symfony\Component\Debug\Exception;
62429
62430 use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
62431
62432
62433
62434
62435
62436
62437 class FatalErrorException extends LegacyFatalErrorException
62438 {
62439 public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null)
62440 {
62441 parent::__construct($message, $code, $severity, $filename, $lineno);
62442
62443 if (null !== $trace) {
62444 if (!$traceArgs) {
62445 foreach ($trace as &$frame) {
62446 unset($frame['args'], $frame['this'], $frame);
62447 }
62448 }
62449
62450 $this->setTrace($trace);
62451 } elseif (null !== $traceOffset) {
62452 if (function_exists('xdebug_get_function_stack')) {
62453 $trace = xdebug_get_function_stack();
62454 if (0 < $traceOffset) {
62455 array_splice($trace, -$traceOffset);
62456 }
62457
62458 foreach ($trace as &$frame) {
62459 if (!isset($frame['type'])) {
62460
62461  if (isset($frame['class'])) {
62462 $frame['type'] = '::';
62463 }
62464 } elseif ('dynamic' === $frame['type']) {
62465 $frame['type'] = '->';
62466 } elseif ('static' === $frame['type']) {
62467 $frame['type'] = '::';
62468 }
62469
62470
62471  if (!$traceArgs) {
62472 unset($frame['params'], $frame['args']);
62473 } elseif (isset($frame['params']) && !isset($frame['args'])) {
62474 $frame['args'] = $frame['params'];
62475 unset($frame['params']);
62476 }
62477 }
62478
62479 unset($frame);
62480 $trace = array_reverse($trace);
62481 } elseif (function_exists('symfony_debug_backtrace')) {
62482 $trace = symfony_debug_backtrace();
62483 if (0 < $traceOffset) {
62484 array_splice($trace, 0, $traceOffset);
62485 }
62486 } else {
62487 $trace = array();
62488 }
62489
62490 $this->setTrace($trace);
62491 }
62492 }
62493
62494 protected function setTrace($trace)
62495 {
62496 $traceReflector = new \ReflectionProperty('Exception', 'trace');
62497 $traceReflector->setAccessible(true);
62498 $traceReflector->setValue($this, $trace);
62499 }
62500 }
62501 <?php
62502
62503
62504
62505
62506
62507
62508
62509
62510
62511
62512 namespace Symfony\Component\Debug\Exception;
62513
62514
62515
62516
62517
62518
62519 class FatalThrowableError extends FatalErrorException
62520 {
62521 public function __construct(\Throwable $e)
62522 {
62523 if ($e instanceof \ParseError) {
62524 $message = 'Parse error: '.$e->getMessage();
62525 $severity = E_PARSE;
62526 } elseif ($e instanceof \TypeError) {
62527 $message = 'Type error: '.$e->getMessage();
62528 $severity = E_RECOVERABLE_ERROR;
62529 } else {
62530 $message = $e->getMessage();
62531 $severity = E_ERROR;
62532 }
62533
62534 \ErrorException::__construct(
62535 $message,
62536 $e->getCode(),
62537 $severity,
62538 $e->getFile(),
62539 $e->getLine()
62540 );
62541
62542 $this->setTrace($e->getTrace());
62543 }
62544 }
62545 <?php
62546
62547
62548
62549
62550
62551
62552
62553
62554
62555
62556 namespace Symfony\Component\HttpKernel\Exception;
62557
62558 use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;
62559
62560
62561
62562
62563
62564
62565
62566
62567
62568
62569 class FlattenException
62570 {
62571 private $handler;
62572
62573 public static function __callStatic($method, $args)
62574 {
62575 if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) {
62576 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_called_class(), $method));
62577 }
62578
62579 return call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
62580 }
62581
62582 public function __call($method, $args)
62583 {
62584 if (!isset($this->handler)) {
62585 $this->handler = new DebugFlattenException();
62586 }
62587
62588 if (!method_exists($this->handler, $method)) {
62589 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
62590 }
62591
62592 return call_user_func_array(array($this->handler, $method), $args);
62593 }
62594 }
62595
62596 namespace Symfony\Component\Debug\Exception;
62597
62598 use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
62599 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
62600
62601
62602
62603
62604
62605
62606
62607
62608 class FlattenException extends LegacyFlattenException
62609 {
62610 private $message;
62611 private $code;
62612 private $previous;
62613 private $trace;
62614 private $class;
62615 private $statusCode;
62616 private $headers;
62617 private $file;
62618 private $line;
62619
62620 public static function create(\Exception $exception, $statusCode = null, array $headers = array())
62621 {
62622 $e = new static();
62623 $e->setMessage($exception->getMessage());
62624 $e->setCode($exception->getCode());
62625
62626 if ($exception instanceof HttpExceptionInterface) {
62627 $statusCode = $exception->getStatusCode();
62628 $headers = array_merge($headers, $exception->getHeaders());
62629 }
62630
62631 if (null === $statusCode) {
62632 $statusCode = 500;
62633 }
62634
62635 $e->setStatusCode($statusCode);
62636 $e->setHeaders($headers);
62637 $e->setTraceFromException($exception);
62638 $e->setClass(get_class($exception));
62639 $e->setFile($exception->getFile());
62640 $e->setLine($exception->getLine());
62641
62642 $previous = $exception->getPrevious();
62643
62644 if ($previous instanceof \Exception) {
62645 $e->setPrevious(static::create($previous));
62646 } elseif ($previous instanceof \Throwable) {
62647 $e->setPrevious(static::create(new FatalThrowableError($previous)));
62648 }
62649
62650 return $e;
62651 }
62652
62653 public function toArray()
62654 {
62655 $exceptions = array();
62656 foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
62657 $exceptions[] = array(
62658 'message' => $exception->getMessage(),
62659 'class' => $exception->getClass(),
62660 'trace' => $exception->getTrace(),
62661 );
62662 }
62663
62664 return $exceptions;
62665 }
62666
62667 public function getStatusCode()
62668 {
62669 return $this->statusCode;
62670 }
62671
62672 public function setStatusCode($code)
62673 {
62674 $this->statusCode = $code;
62675 }
62676
62677 public function getHeaders()
62678 {
62679 return $this->headers;
62680 }
62681
62682 public function setHeaders(array $headers)
62683 {
62684 $this->headers = $headers;
62685 }
62686
62687 public function getClass()
62688 {
62689 return $this->class;
62690 }
62691
62692 public function setClass($class)
62693 {
62694 $this->class = $class;
62695 }
62696
62697 public function getFile()
62698 {
62699 return $this->file;
62700 }
62701
62702 public function setFile($file)
62703 {
62704 $this->file = $file;
62705 }
62706
62707 public function getLine()
62708 {
62709 return $this->line;
62710 }
62711
62712 public function setLine($line)
62713 {
62714 $this->line = $line;
62715 }
62716
62717 public function getMessage()
62718 {
62719 return $this->message;
62720 }
62721
62722 public function setMessage($message)
62723 {
62724 $this->message = $message;
62725 }
62726
62727 public function getCode()
62728 {
62729 return $this->code;
62730 }
62731
62732 public function setCode($code)
62733 {
62734 $this->code = $code;
62735 }
62736
62737 public function getPrevious()
62738 {
62739 return $this->previous;
62740 }
62741
62742 public function setPrevious(FlattenException $previous)
62743 {
62744 $this->previous = $previous;
62745 }
62746
62747 public function getAllPrevious()
62748 {
62749 $exceptions = array();
62750 $e = $this;
62751 while ($e = $e->getPrevious()) {
62752 $exceptions[] = $e;
62753 }
62754
62755 return $exceptions;
62756 }
62757
62758 public function getTrace()
62759 {
62760 return $this->trace;
62761 }
62762
62763 public function setTraceFromException(\Exception $exception)
62764 {
62765 $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
62766 }
62767
62768 public function setTrace($trace, $file, $line)
62769 {
62770 $this->trace = array();
62771 $this->trace[] = array(
62772 'namespace' => '',
62773 'short_class' => '',
62774 'class' => '',
62775 'type' => '',
62776 'function' => '',
62777 'file' => $file,
62778 'line' => $line,
62779 'args' => array(),
62780 );
62781 foreach ($trace as $entry) {
62782 $class = '';
62783 $namespace = '';
62784 if (isset($entry['class'])) {
62785 $parts = explode('\\', $entry['class']);
62786 $class = array_pop($parts);
62787 $namespace = implode('\\', $parts);
62788 }
62789
62790 $this->trace[] = array(
62791 'namespace' => $namespace,
62792 'short_class' => $class,
62793 'class' => isset($entry['class']) ? $entry['class'] : '',
62794 'type' => isset($entry['type']) ? $entry['type'] : '',
62795 'function' => isset($entry['function']) ? $entry['function'] : null,
62796 'file' => isset($entry['file']) ? $entry['file'] : null,
62797 'line' => isset($entry['line']) ? $entry['line'] : null,
62798 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
62799 );
62800 }
62801 }
62802
62803 private function flattenArgs($args, $level = 0, &$count = 0)
62804 {
62805 $result = array();
62806 foreach ($args as $key => $value) {
62807 if (++$count > 1e4) {
62808 return array('array', '*SKIPPED over 10000 entries*');
62809 }
62810 if ($value instanceof \__PHP_Incomplete_Class) {
62811
62812  $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
62813 } elseif (is_object($value)) {
62814 $result[$key] = array('object', get_class($value));
62815 } elseif (is_array($value)) {
62816 if ($level > 10) {
62817 $result[$key] = array('array', '*DEEP NESTED ARRAY*');
62818 } else {
62819 $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
62820 }
62821 } elseif (null === $value) {
62822 $result[$key] = array('null', null);
62823 } elseif (is_bool($value)) {
62824 $result[$key] = array('boolean', $value);
62825 } elseif (is_resource($value)) {
62826 $result[$key] = array('resource', get_resource_type($value));
62827 } else {
62828 $result[$key] = array('string', (string) $value);
62829 }
62830 }
62831
62832 return $result;
62833 }
62834
62835 private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
62836 {
62837 $array = new \ArrayObject($value);
62838
62839 return $array['__PHP_Incomplete_Class_Name'];
62840 }
62841 }
62842 <?php
62843
62844
62845
62846
62847
62848
62849
62850
62851
62852
62853 namespace Symfony\Component\Debug\Exception;
62854
62855
62856
62857
62858
62859
62860 class OutOfMemoryException extends FatalErrorException
62861 {
62862 }
62863 <?php
62864
62865
62866
62867
62868
62869
62870
62871
62872
62873
62874 namespace Symfony\Component\Debug\Exception;
62875
62876
62877
62878
62879
62880
62881 class UndefinedFunctionException extends FatalErrorException
62882 {
62883 public function __construct($message, \ErrorException $previous)
62884 {
62885 parent::__construct(
62886 $message,
62887 $previous->getCode(),
62888 $previous->getSeverity(),
62889 $previous->getFile(),
62890 $previous->getLine(),
62891 $previous->getPrevious()
62892 );
62893 $this->setTrace($previous->getTrace());
62894 }
62895 }
62896 <?php
62897
62898
62899
62900
62901
62902
62903
62904
62905
62906
62907 namespace Symfony\Component\Debug\Exception;
62908
62909
62910
62911
62912
62913
62914 class UndefinedMethodException extends FatalErrorException
62915 {
62916 public function __construct($message, \ErrorException $previous)
62917 {
62918 parent::__construct(
62919 $message,
62920 $previous->getCode(),
62921 $previous->getSeverity(),
62922 $previous->getFile(),
62923 $previous->getLine(),
62924 $previous->getPrevious()
62925 );
62926 $this->setTrace($previous->getTrace());
62927 }
62928 }
62929 <?php
62930
62931
62932
62933
62934
62935
62936
62937
62938
62939
62940 namespace Symfony\Component\Debug;
62941
62942 use Symfony\Component\HttpFoundation\Response;
62943 use Symfony\Component\Debug\Exception\FlattenException;
62944 use Symfony\Component\Debug\Exception\OutOfMemoryException;
62945
62946
62947
62948
62949
62950
62951
62952
62953
62954
62955
62956
62957
62958 class ExceptionHandler
62959 {
62960 private $debug;
62961 private $charset;
62962 private $handler;
62963 private $caughtBuffer;
62964 private $caughtLength;
62965 private $fileLinkFormat;
62966
62967 public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
62968 {
62969 if (false !== strpos($charset, '%')) {
62970 @trigger_error('Providing $fileLinkFormat as second argument to '.__METHOD__.' is deprecated since version 2.8 and will be unsupported in 3.0. Please provide it as third argument, after $charset.', E_USER_DEPRECATED);
62971
62972
62973  $pivot = $fileLinkFormat;
62974 $fileLinkFormat = $charset;
62975 $charset = $pivot;
62976 }
62977 $this->debug = $debug;
62978 $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
62979 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
62980 }
62981
62982
62983
62984
62985
62986
62987
62988
62989
62990
62991 public static function register($debug = true, $charset = null, $fileLinkFormat = null)
62992 {
62993 $handler = new static($debug, $charset, $fileLinkFormat);
62994
62995 $prev = set_exception_handler(array($handler, 'handle'));
62996 if (is_array($prev) && $prev[0] instanceof ErrorHandler) {
62997 restore_exception_handler();
62998 $prev[0]->setExceptionHandler(array($handler, 'handle'));
62999 }
63000
63001 return $handler;
63002 }
63003
63004
63005
63006
63007
63008
63009
63010
63011 public function setHandler($handler)
63012 {
63013 if (null !== $handler && !is_callable($handler)) {
63014 throw new \LogicException('The exception handler must be a valid PHP callable.');
63015 }
63016 $old = $this->handler;
63017 $this->handler = $handler;
63018
63019 return $old;
63020 }
63021
63022
63023
63024
63025
63026
63027
63028
63029 public function setFileLinkFormat($format)
63030 {
63031 $old = $this->fileLinkFormat;
63032 $this->fileLinkFormat = $format;
63033
63034 return $old;
63035 }
63036
63037
63038
63039
63040
63041
63042
63043
63044
63045 public function handle(\Exception $exception)
63046 {
63047 if (null === $this->handler || $exception instanceof OutOfMemoryException) {
63048 $this->failSafeHandle($exception);
63049
63050 return;
63051 }
63052
63053 $caughtLength = $this->caughtLength = 0;
63054
63055 ob_start(array($this, 'catchOutput'));
63056 $this->failSafeHandle($exception);
63057 while (null === $this->caughtBuffer && ob_end_flush()) {
63058
63059  }
63060 if (isset($this->caughtBuffer[0])) {
63061 ob_start(array($this, 'cleanOutput'));
63062 echo $this->caughtBuffer;
63063 $caughtLength = ob_get_length();
63064 }
63065 $this->caughtBuffer = null;
63066
63067 try {
63068 call_user_func($this->handler, $exception);
63069 $this->caughtLength = $caughtLength;
63070 } catch (\Exception $e) {
63071 if (!$caughtLength) {
63072
63073  throw $exception;
63074 }
63075 }
63076 }
63077
63078
63079
63080
63081
63082
63083
63084
63085 private function failSafeHandle(\Exception $exception)
63086 {
63087 if (class_exists('Symfony\Component\HttpFoundation\Response', false)
63088 && __CLASS__ !== get_class($this)
63089 && ($reflector = new \ReflectionMethod($this, 'createResponse'))
63090 && __CLASS__ !== $reflector->class
63091 ) {
63092 $response = $this->createResponse($exception);
63093 $response->sendHeaders();
63094 $response->sendContent();
63095 @trigger_error(sprintf("The %s::createResponse method is deprecated since 2.8 and won't be called anymore when handling an exception in 3.0.", $reflector->class), E_USER_DEPRECATED);
63096
63097 return;
63098 }
63099
63100 $this->sendPhpResponse($exception);
63101 }
63102
63103
63104
63105
63106
63107
63108
63109
63110
63111 public function sendPhpResponse($exception)
63112 {
63113 if (!$exception instanceof FlattenException) {
63114 $exception = FlattenException::create($exception);
63115 }
63116
63117 if (!headers_sent()) {
63118 header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
63119 foreach ($exception->getHeaders() as $name => $value) {
63120 header($name.': '.$value, false);
63121 }
63122 header('Content-Type: text/html; charset='.$this->charset);
63123 }
63124
63125 echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
63126 }
63127
63128
63129
63130
63131
63132
63133
63134
63135
63136
63137 public function createResponse($exception)
63138 {
63139 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
63140
63141 if (!$exception instanceof FlattenException) {
63142 $exception = FlattenException::create($exception);
63143 }
63144
63145 return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
63146 }
63147
63148
63149
63150
63151
63152
63153
63154
63155 public function getHtml($exception)
63156 {
63157 if (!$exception instanceof FlattenException) {
63158 $exception = FlattenException::create($exception);
63159 }
63160
63161 return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
63162 }
63163
63164
63165
63166
63167
63168
63169 public function getContent(FlattenException $exception)
63170 {
63171 switch ($exception->getStatusCode()) {
63172 case 404:
63173 $title = 'Sorry, the page you are looking for could not be found.';
63174 break;
63175 default:
63176 $title = 'Whoops, looks like something went wrong.';
63177 }
63178
63179 $content = '';
63180 if ($this->debug) {
63181 try {
63182 $count = count($exception->getAllPrevious());
63183 $total = $count + 1;
63184 foreach ($exception->toArray() as $position => $e) {
63185 $ind = $count - $position + 1;
63186 $class = $this->formatClass($e['class']);
63187 $message = nl2br($this->escapeHtml($e['message']));
63188 $content .= sprintf(<<<'EOF'
63189                         <h2 class="block_exception clear_fix">
63190                             <span class="exception_counter">%d/%d</span>
63191                             <span class="exception_title">%s%s:</span>
63192                             <span class="exception_message">%s</span>
63193                         </h2>
63194                         <div class="block">
63195                             <ol class="traces list_exception">
63196
63197 EOF
63198 , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
63199 foreach ($e['trace'] as $trace) {
63200 $content .= '       <li>';
63201 if ($trace['function']) {
63202 $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
63203 }
63204 if (isset($trace['file']) && isset($trace['line'])) {
63205 $content .= $this->formatPath($trace['file'], $trace['line']);
63206 }
63207 $content .= "</li>\n";
63208 }
63209
63210 $content .= "    </ol>\n</div>\n";
63211 }
63212 } catch (\Exception $e) {
63213
63214  if ($this->debug) {
63215 $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $this->escapeHtml($e->getMessage()));
63216 } else {
63217 $title = 'Whoops, looks like something went wrong.';
63218 }
63219 }
63220 }
63221
63222 return <<<EOF
63223             <div id="sf-resetcontent" class="sf-reset">
63224                 <h1>$title</h1>
63225                 $content
63226             </div>
63227 EOF;
63228 }
63229
63230
63231
63232
63233
63234
63235 public function getStylesheet(FlattenException $exception)
63236 {
63237 return <<<'EOF'
63238             .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
63239             .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
63240             .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
63241             .sf-reset .clear_fix { display:inline-block; }
63242             .sf-reset * html .clear_fix { height:1%; }
63243             .sf-reset .clear_fix { display:block; }
63244             .sf-reset, .sf-reset .block { margin: auto }
63245             .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
63246             .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
63247             .sf-reset strong { font-weight:bold; }
63248             .sf-reset a { color:#6c6159; cursor: default; }
63249             .sf-reset a img { border:none; }
63250             .sf-reset a:hover { text-decoration:underline; }
63251             .sf-reset em { font-style:italic; }
63252             .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
63253             .sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
63254             .sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
63255             .sf-reset .exception_message { margin-left: 3em; display: block; }
63256             .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
63257             .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
63258                 -webkit-border-bottom-right-radius: 16px;
63259                 -webkit-border-bottom-left-radius: 16px;
63260                 -moz-border-radius-bottomright: 16px;
63261                 -moz-border-radius-bottomleft: 16px;
63262                 border-bottom-right-radius: 16px;
63263                 border-bottom-left-radius: 16px;
63264                 border-bottom:1px solid #ccc;
63265                 border-right:1px solid #ccc;
63266                 border-left:1px solid #ccc;
63267                 word-wrap: break-word;
63268             }
63269             .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
63270                 -webkit-border-top-left-radius: 16px;
63271                 -webkit-border-top-right-radius: 16px;
63272                 -moz-border-radius-topleft: 16px;
63273                 -moz-border-radius-topright: 16px;
63274                 border-top-left-radius: 16px;
63275                 border-top-right-radius: 16px;
63276                 border-top:1px solid #ccc;
63277                 border-right:1px solid #ccc;
63278                 border-left:1px solid #ccc;
63279                 overflow: hidden;
63280                 word-wrap: break-word;
63281             }
63282             .sf-reset a { background:none; color:#868686; text-decoration:none; }
63283             .sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
63284             .sf-reset ol { padding: 10px 0; }
63285             .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
63286                 -webkit-border-radius: 10px;
63287                 -moz-border-radius: 10px;
63288                 border-radius: 10px;
63289                 border: 1px solid #ccc;
63290             }
63291 EOF;
63292 }
63293
63294 private function decorate($content, $css)
63295 {
63296 return <<<EOF
63297 <!DOCTYPE html>
63298 <html>
63299     <head>
63300         <meta charset="{$this->charset}" />
63301         <meta name="robots" content="noindex,nofollow" />
63302         <style>
63303             /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
63304             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;}
63305
63306             html { background: #eee; padding: 10px }
63307             img { border: 0; }
63308             #sf-resetcontent { width:970px; margin:0 auto; }
63309             $css
63310         </style>
63311     </head>
63312     <body>
63313         $content
63314     </body>
63315 </html>
63316 EOF;
63317 }
63318
63319 private function formatClass($class)
63320 {
63321 $parts = explode('\\', $class);
63322
63323 return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
63324 }
63325
63326 private function formatPath($path, $line)
63327 {
63328 $path = $this->escapeHtml($path);
63329 $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
63330
63331 if ($linkFormat = $this->fileLinkFormat) {
63332 $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
63333
63334 return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
63335 }
63336
63337 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);
63338 }
63339
63340
63341
63342
63343
63344
63345
63346
63347 private function formatArgs(array $args)
63348 {
63349 $result = array();
63350 foreach ($args as $key => $item) {
63351 if ('object' === $item[0]) {
63352 $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
63353 } elseif ('array' === $item[0]) {
63354 $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
63355 } elseif ('string' === $item[0]) {
63356 $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1]));
63357 } elseif ('null' === $item[0]) {
63358 $formattedValue = '<em>null</em>';
63359 } elseif ('boolean' === $item[0]) {
63360 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
63361 } elseif ('resource' === $item[0]) {
63362 $formattedValue = '<em>resource</em>';
63363 } else {
63364 $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true));
63365 }
63366
63367 $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
63368 }
63369
63370 return implode(', ', $result);
63371 }
63372
63373
63374
63375
63376
63377
63378 protected static function utf8Htmlize($str)
63379 {
63380 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
63381
63382 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
63383 }
63384
63385
63386
63387
63388 private function escapeHtml($str)
63389 {
63390 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset);
63391 }
63392
63393
63394
63395
63396 public function catchOutput($buffer)
63397 {
63398 $this->caughtBuffer = $buffer;
63399
63400 return '';
63401 }
63402
63403
63404
63405
63406 public function cleanOutput($buffer)
63407 {
63408 if ($this->caughtLength) {
63409
63410  $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
63411 if (isset($cleanBuffer[0])) {
63412 $buffer = $cleanBuffer;
63413 }
63414 }
63415
63416 return $buffer;
63417 }
63418 }
63419 <?php
63420
63421
63422
63423
63424
63425
63426
63427
63428
63429
63430 namespace Symfony\Component\Debug\FatalErrorHandler;
63431
63432 use Symfony\Component\Debug\Exception\ClassNotFoundException;
63433 use Symfony\Component\Debug\Exception\FatalErrorException;
63434 use Symfony\Component\Debug\DebugClassLoader;
63435 use Composer\Autoload\ClassLoader as ComposerClassLoader;
63436 use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
63437 use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
63438
63439
63440
63441
63442
63443
63444 class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
63445 {
63446
63447
63448
63449 public function handleError(array $error, FatalErrorException $exception)
63450 {
63451 $messageLen = strlen($error['message']);
63452 $notFoundSuffix = '\' not found';
63453 $notFoundSuffixLen = strlen($notFoundSuffix);
63454 if ($notFoundSuffixLen > $messageLen) {
63455 return;
63456 }
63457
63458 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
63459 return;
63460 }
63461
63462 foreach (array('class', 'interface', 'trait') as $typeName) {
63463 $prefix = ucfirst($typeName).' \'';
63464 $prefixLen = strlen($prefix);
63465 if (0 !== strpos($error['message'], $prefix)) {
63466 continue;
63467 }
63468
63469 $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
63470 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
63471 $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
63472 $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
63473 $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
63474 $tail = ' for another namespace?';
63475 } else {
63476 $className = $fullyQualifiedClassName;
63477 $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
63478 $tail = '?';
63479 }
63480
63481 if ($candidates = $this->getClassCandidates($className)) {
63482 $tail = array_pop($candidates).'"?';
63483 if ($candidates) {
63484 $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
63485 } else {
63486 $tail = ' for "'.$tail;
63487 }
63488 }
63489 $message .= "\nDid you forget a \"use\" statement".$tail;
63490
63491 return new ClassNotFoundException($message, $exception);
63492 }
63493 }
63494
63495
63496
63497
63498
63499
63500
63501
63502
63503
63504
63505 private function getClassCandidates($class)
63506 {
63507 if (!is_array($functions = spl_autoload_functions())) {
63508 return array();
63509 }
63510
63511
63512  $classes = array();
63513
63514 foreach ($functions as $function) {
63515 if (!is_array($function)) {
63516 continue;
63517 }
63518
63519  if ($function[0] instanceof DebugClassLoader) {
63520 $function = $function[0]->getClassLoader();
63521
63522
63523  if (is_object($function)) {
63524 $function = array($function);
63525 }
63526
63527 if (!is_array($function)) {
63528 continue;
63529 }
63530 }
63531
63532 if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader || $function[0] instanceof SymfonyUniversalClassLoader) {
63533 foreach ($function[0]->getPrefixes() as $prefix => $paths) {
63534 foreach ($paths as $path) {
63535 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
63536 }
63537 }
63538 }
63539 if ($function[0] instanceof ComposerClassLoader) {
63540 foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
63541 foreach ($paths as $path) {
63542 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
63543 }
63544 }
63545 }
63546 }
63547
63548 return array_unique($classes);
63549 }
63550
63551
63552
63553
63554
63555
63556
63557
63558 private function findClassInPath($path, $class, $prefix)
63559 {
63560 if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
63561 return array();
63562 }
63563
63564 $classes = array();
63565 $filename = $class.'.php';
63566 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
63567 if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
63568 $classes[] = $class;
63569 }
63570 }
63571
63572 return $classes;
63573 }
63574
63575
63576
63577
63578
63579
63580
63581
63582 private function convertFileToClass($path, $file, $prefix)
63583 {
63584 $candidates = array(
63585
63586  $namespacedClass = str_replace(array($path.DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
63587
63588  $prefix.$namespacedClass,
63589
63590  $prefix.'\\'.$namespacedClass,
63591
63592  str_replace('\\', '_', $namespacedClass),
63593
63594  str_replace('\\', '_', $prefix.$namespacedClass),
63595
63596  str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
63597 );
63598
63599 if ($prefix) {
63600 $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
63601 }
63602
63603
63604  
63605  
63606  foreach ($candidates as $candidate) {
63607 if ($this->classExists($candidate)) {
63608 return $candidate;
63609 }
63610 }
63611
63612 require_once $file;
63613
63614 foreach ($candidates as $candidate) {
63615 if ($this->classExists($candidate)) {
63616 return $candidate;
63617 }
63618 }
63619 }
63620
63621
63622
63623
63624
63625
63626 private function classExists($class)
63627 {
63628 return class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
63629 }
63630 }
63631 <?php
63632
63633
63634
63635
63636
63637
63638
63639
63640
63641
63642 namespace Symfony\Component\Debug\FatalErrorHandler;
63643
63644 use Symfony\Component\Debug\Exception\FatalErrorException;
63645
63646
63647
63648
63649
63650
63651 interface FatalErrorHandlerInterface
63652 {
63653
63654
63655
63656
63657
63658
63659
63660
63661 public function handleError(array $error, FatalErrorException $exception);
63662 }
63663 <?php
63664
63665
63666
63667
63668
63669
63670
63671
63672
63673
63674 namespace Symfony\Component\Debug\FatalErrorHandler;
63675
63676 use Symfony\Component\Debug\Exception\UndefinedFunctionException;
63677 use Symfony\Component\Debug\Exception\FatalErrorException;
63678
63679
63680
63681
63682
63683
63684 class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
63685 {
63686
63687
63688
63689 public function handleError(array $error, FatalErrorException $exception)
63690 {
63691 $messageLen = strlen($error['message']);
63692 $notFoundSuffix = '()';
63693 $notFoundSuffixLen = strlen($notFoundSuffix);
63694 if ($notFoundSuffixLen > $messageLen) {
63695 return;
63696 }
63697
63698 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
63699 return;
63700 }
63701
63702 $prefix = 'Call to undefined function ';
63703 $prefixLen = strlen($prefix);
63704 if (0 !== strpos($error['message'], $prefix)) {
63705 return;
63706 }
63707
63708 $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
63709 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
63710 $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
63711 $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
63712 $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
63713 } else {
63714 $functionName = $fullyQualifiedFunctionName;
63715 $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
63716 }
63717
63718 $candidates = array();
63719 foreach (get_defined_functions() as $type => $definedFunctionNames) {
63720 foreach ($definedFunctionNames as $definedFunctionName) {
63721 if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
63722 $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
63723 } else {
63724 $definedFunctionNameBasename = $definedFunctionName;
63725 }
63726
63727 if ($definedFunctionNameBasename === $functionName) {
63728 $candidates[] = '\\'.$definedFunctionName;
63729 }
63730 }
63731 }
63732
63733 if ($candidates) {
63734 sort($candidates);
63735 $last = array_pop($candidates).'"?';
63736 if ($candidates) {
63737 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
63738 } else {
63739 $candidates = '"'.$last;
63740 }
63741 $message .= "\nDid you mean to call ".$candidates;
63742 }
63743
63744 return new UndefinedFunctionException($message, $exception);
63745 }
63746 }
63747 <?php
63748
63749
63750
63751
63752
63753
63754
63755
63756
63757
63758 namespace Symfony\Component\Debug\FatalErrorHandler;
63759
63760 use Symfony\Component\Debug\Exception\FatalErrorException;
63761 use Symfony\Component\Debug\Exception\UndefinedMethodException;
63762
63763
63764
63765
63766
63767
63768 class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
63769 {
63770
63771
63772
63773 public function handleError(array $error, FatalErrorException $exception)
63774 {
63775 preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
63776 if (!$matches) {
63777 return;
63778 }
63779
63780 $className = $matches[1];
63781 $methodName = $matches[2];
63782
63783 $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
63784
63785 if (!class_exists($className) || null === $methods = get_class_methods($className)) {
63786
63787  return new UndefinedMethodException($message, $exception);
63788 }
63789
63790 $candidates = array();
63791 foreach ($methods as $definedMethodName) {
63792 $lev = levenshtein($methodName, $definedMethodName);
63793 if ($lev <= strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
63794 $candidates[] = $definedMethodName;
63795 }
63796 }
63797
63798 if ($candidates) {
63799 sort($candidates);
63800 $last = array_pop($candidates).'"?';
63801 if ($candidates) {
63802 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
63803 } else {
63804 $candidates = '"'.$last;
63805 }
63806
63807 $message .= "\nDid you mean to call ".$candidates;
63808 }
63809
63810 return new UndefinedMethodException($message, $exception);
63811 }
63812 }
63813 Copyright (c) 2004-2017 Fabien Potencier
63814
63815 Permission is hereby granted, free of charge, to any person obtaining a copy
63816 of this software and associated documentation files (the "Software"), to deal
63817 in the Software without restriction, including without limitation the rights
63818 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
63819 copies of the Software, and to permit persons to whom the Software is furnished
63820 to do so, subject to the following conditions:
63821
63822 The above copyright notice and this permission notice shall be included in all
63823 copies or substantial portions of the Software.
63824
63825 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63826 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63827 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63828 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63829 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63830 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
63831 THE SOFTWARE.
63832 <?php
63833
63834
63835
63836
63837
63838
63839
63840
63841
63842
63843 namespace Symfony\Component\Filesystem\Exception;
63844
63845
63846
63847
63848
63849
63850 interface ExceptionInterface
63851 {
63852 }
63853 <?php
63854
63855
63856
63857
63858
63859
63860
63861
63862
63863
63864 namespace Symfony\Component\Filesystem\Exception;
63865
63866
63867
63868
63869
63870
63871
63872 class FileNotFoundException extends IOException
63873 {
63874 public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
63875 {
63876 if (null === $message) {
63877 if (null === $path) {
63878 $message = 'File could not be found.';
63879 } else {
63880 $message = sprintf('File "%s" could not be found.', $path);
63881 }
63882 }
63883
63884 parent::__construct($message, $code, $previous, $path);
63885 }
63886 }
63887 <?php
63888
63889
63890
63891
63892
63893
63894
63895
63896
63897
63898 namespace Symfony\Component\Filesystem\Exception;
63899
63900
63901
63902
63903
63904
63905
63906
63907 class IOException extends \RuntimeException implements IOExceptionInterface
63908 {
63909 private $path;
63910
63911 public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
63912 {
63913 $this->path = $path;
63914
63915 parent::__construct($message, $code, $previous);
63916 }
63917
63918
63919
63920
63921 public function getPath()
63922 {
63923 return $this->path;
63924 }
63925 }
63926 <?php
63927
63928
63929
63930
63931
63932
63933
63934
63935
63936
63937 namespace Symfony\Component\Filesystem\Exception;
63938
63939
63940
63941
63942
63943
63944 interface IOExceptionInterface extends ExceptionInterface
63945 {
63946
63947
63948
63949
63950
63951 public function getPath();
63952 }
63953 <?php
63954
63955
63956
63957
63958
63959
63960
63961
63962
63963
63964 namespace Symfony\Component\Filesystem;
63965
63966 use Symfony\Component\Filesystem\Exception\IOException;
63967 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
63968
63969
63970
63971
63972
63973
63974 class Filesystem
63975 {
63976
63977
63978
63979
63980
63981
63982
63983
63984
63985
63986
63987
63988
63989
63990 public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
63991 {
63992 $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
63993 if ($originIsLocal && !is_file($originFile)) {
63994 throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
63995 }
63996
63997 $this->mkdir(dirname($targetFile));
63998
63999 $doCopy = true;
64000 if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
64001 $doCopy = filemtime($originFile) > filemtime($targetFile);
64002 }
64003
64004 if ($doCopy) {
64005
64006  if (false === $source = @fopen($originFile, 'r')) {
64007 throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
64008 }
64009
64010
64011  if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
64012 throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
64013 }
64014
64015 $bytesCopied = stream_copy_to_stream($source, $target);
64016 fclose($source);
64017 fclose($target);
64018 unset($source, $target);
64019
64020 if (!is_file($targetFile)) {
64021 throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
64022 }
64023
64024 if ($originIsLocal) {
64025
64026  @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
64027
64028 if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
64029 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);
64030 }
64031 }
64032 }
64033 }
64034
64035
64036
64037
64038
64039
64040
64041
64042
64043 public function mkdir($dirs, $mode = 0777)
64044 {
64045 foreach ($this->toIterator($dirs) as $dir) {
64046 if (is_dir($dir)) {
64047 continue;
64048 }
64049
64050 if (true !== @mkdir($dir, $mode, true)) {
64051 $error = error_get_last();
64052 if (!is_dir($dir)) {
64053
64054  if ($error) {
64055 throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']), 0, null, $dir);
64056 }
64057 throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
64058 }
64059 }
64060 }
64061 }
64062
64063
64064
64065
64066
64067
64068
64069
64070 public function exists($files)
64071 {
64072 $maxPathLength = PHP_MAXPATHLEN - 2;
64073
64074 foreach ($this->toIterator($files) as $file) {
64075 if (strlen($file) > $maxPathLength) {
64076 throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
64077 }
64078
64079 if (!file_exists($file)) {
64080 return false;
64081 }
64082 }
64083
64084 return true;
64085 }
64086
64087
64088
64089
64090
64091
64092
64093
64094
64095
64096 public function touch($files, $time = null, $atime = null)
64097 {
64098 foreach ($this->toIterator($files) as $file) {
64099 $touch = $time ? @touch($file, $time, $atime) : @touch($file);
64100 if (true !== $touch) {
64101 throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
64102 }
64103 }
64104 }
64105
64106
64107
64108
64109
64110
64111
64112
64113 public function remove($files)
64114 {
64115 if ($files instanceof \Traversable) {
64116 $files = iterator_to_array($files, false);
64117 } elseif (!is_array($files)) {
64118 $files = array($files);
64119 }
64120 $files = array_reverse($files);
64121 foreach ($files as $file) {
64122 if (is_link($file)) {
64123
64124  if (!@(unlink($file) || '\\' !== DIRECTORY_SEPARATOR || rmdir($file)) && file_exists($file)) {
64125 $error = error_get_last();
64126 throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, $error['message']));
64127 }
64128 } elseif (is_dir($file)) {
64129 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
64130
64131 if (!@rmdir($file) && file_exists($file)) {
64132 $error = error_get_last();
64133 throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, $error['message']));
64134 }
64135 } elseif (!@unlink($file) && file_exists($file)) {
64136 $error = error_get_last();
64137 throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, $error['message']));
64138 }
64139 }
64140 }
64141
64142
64143
64144
64145
64146
64147
64148
64149
64150
64151
64152 public function chmod($files, $mode, $umask = 0000, $recursive = false)
64153 {
64154 foreach ($this->toIterator($files) as $file) {
64155 if (true !== @chmod($file, $mode & ~$umask)) {
64156 throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
64157 }
64158 if ($recursive && is_dir($file) && !is_link($file)) {
64159 $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
64160 }
64161 }
64162 }
64163
64164
64165
64166
64167
64168
64169
64170
64171
64172
64173 public function chown($files, $user, $recursive = false)
64174 {
64175 foreach ($this->toIterator($files) as $file) {
64176 if ($recursive && is_dir($file) && !is_link($file)) {
64177 $this->chown(new \FilesystemIterator($file), $user, true);
64178 }
64179 if (is_link($file) && function_exists('lchown')) {
64180 if (true !== @lchown($file, $user)) {
64181 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
64182 }
64183 } else {
64184 if (true !== @chown($file, $user)) {
64185 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
64186 }
64187 }
64188 }
64189 }
64190
64191
64192
64193
64194
64195
64196
64197
64198
64199
64200 public function chgrp($files, $group, $recursive = false)
64201 {
64202 foreach ($this->toIterator($files) as $file) {
64203 if ($recursive && is_dir($file) && !is_link($file)) {
64204 $this->chgrp(new \FilesystemIterator($file), $group, true);
64205 }
64206 if (is_link($file) && function_exists('lchgrp')) {
64207 if (true !== @lchgrp($file, $group) || (defined('HHVM_VERSION') && !posix_getgrnam($group))) {
64208 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
64209 }
64210 } else {
64211 if (true !== @chgrp($file, $group)) {
64212 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
64213 }
64214 }
64215 }
64216 }
64217
64218
64219
64220
64221
64222
64223
64224
64225
64226
64227
64228 public function rename($origin, $target, $overwrite = false)
64229 {
64230
64231  if (!$overwrite && $this->isReadable($target)) {
64232 throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
64233 }
64234
64235 if (true !== @rename($origin, $target)) {
64236 if (is_dir($origin)) {
64237
64238  $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
64239 $this->remove($origin);
64240
64241 return;
64242 }
64243 throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
64244 }
64245 }
64246
64247
64248
64249
64250
64251
64252
64253
64254
64255
64256 private function isReadable($filename)
64257 {
64258 $maxPathLength = PHP_MAXPATHLEN - 2;
64259
64260 if (strlen($filename) > $maxPathLength) {
64261 throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename);
64262 }
64263
64264 return is_readable($filename);
64265 }
64266
64267
64268
64269
64270
64271
64272
64273
64274
64275
64276 public function symlink($originDir, $targetDir, $copyOnWindows = false)
64277 {
64278 if ('\\' === DIRECTORY_SEPARATOR) {
64279 $originDir = strtr($originDir, '/', '\\');
64280 $targetDir = strtr($targetDir, '/', '\\');
64281
64282 if ($copyOnWindows) {
64283 $this->mirror($originDir, $targetDir);
64284
64285 return;
64286 }
64287 }
64288
64289 $this->mkdir(dirname($targetDir));
64290
64291 $ok = false;
64292 if (is_link($targetDir)) {
64293 if (readlink($targetDir) != $originDir) {
64294 $this->remove($targetDir);
64295 } else {
64296 $ok = true;
64297 }
64298 }
64299
64300 if (!$ok && true !== @symlink($originDir, $targetDir)) {
64301 $report = error_get_last();
64302 if (is_array($report)) {
64303 if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
64304 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);
64305 }
64306 }
64307 throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
64308 }
64309 }
64310
64311
64312
64313
64314
64315
64316
64317
64318
64319 public function makePathRelative($endPath, $startPath)
64320 {
64321
64322  if ('\\' === DIRECTORY_SEPARATOR) {
64323 $endPath = str_replace('\\', '/', $endPath);
64324 $startPath = str_replace('\\', '/', $startPath);
64325 }
64326
64327 $stripDriveLetter = function ($path) {
64328 if (strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) {
64329 return substr($path, 2);
64330 }
64331
64332 return $path;
64333 };
64334
64335 $endPath = $stripDriveLetter($endPath);
64336 $startPath = $stripDriveLetter($startPath);
64337
64338
64339  $startPathArr = explode('/', trim($startPath, '/'));
64340 $endPathArr = explode('/', trim($endPath, '/'));
64341
64342 $normalizePathArray = function ($pathSegments, $absolute) {
64343 $result = array();
64344
64345 foreach ($pathSegments as $segment) {
64346 if ('..' === $segment && ($absolute || count($result))) {
64347 array_pop($result);
64348 } elseif ('.' !== $segment) {
64349 $result[] = $segment;
64350 }
64351 }
64352
64353 return $result;
64354 };
64355
64356 $startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath));
64357 $endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath));
64358
64359
64360  $index = 0;
64361 while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
64362 ++$index;
64363 }
64364
64365
64366  if (1 === count($startPathArr) && '' === $startPathArr[0]) {
64367 $depth = 0;
64368 } else {
64369 $depth = count($startPathArr) - $index;
64370 }
64371
64372
64373  $traverser = str_repeat('../', $depth);
64374
64375 $endPathRemainder = implode('/', array_slice($endPathArr, $index));
64376
64377
64378  $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
64379
64380 return '' === $relativePath ? './' : $relativePath;
64381 }
64382
64383
64384
64385
64386
64387
64388
64389
64390
64391
64392
64393
64394
64395
64396
64397 public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
64398 {
64399 $targetDir = rtrim($targetDir, '/\\');
64400 $originDir = rtrim($originDir, '/\\');
64401 $originDirLen = strlen($originDir);
64402
64403
64404  if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
64405 $deleteIterator = $iterator;
64406 if (null === $deleteIterator) {
64407 $flags = \FilesystemIterator::SKIP_DOTS;
64408 $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
64409 }
64410 $targetDirLen = strlen($targetDir);
64411 foreach ($deleteIterator as $file) {
64412 $origin = $originDir.substr($file->getPathname(), $targetDirLen);
64413 if (!$this->exists($origin)) {
64414 $this->remove($file);
64415 }
64416 }
64417 }
64418
64419 $copyOnWindows = false;
64420 if (isset($options['copy_on_windows'])) {
64421 $copyOnWindows = $options['copy_on_windows'];
64422 }
64423
64424 if (null === $iterator) {
64425 $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
64426 $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
64427 }
64428
64429 if ($this->exists($originDir)) {
64430 $this->mkdir($targetDir);
64431 }
64432
64433 foreach ($iterator as $file) {
64434 $target = $targetDir.substr($file->getPathname(), $originDirLen);
64435
64436 if ($copyOnWindows) {
64437 if (is_file($file)) {
64438 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
64439 } elseif (is_dir($file)) {
64440 $this->mkdir($target);
64441 } else {
64442 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
64443 }
64444 } else {
64445 if (is_link($file)) {
64446 $this->symlink($file->getLinkTarget(), $target);
64447 } elseif (is_dir($file)) {
64448 $this->mkdir($target);
64449 } elseif (is_file($file)) {
64450 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
64451 } else {
64452 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
64453 }
64454 }
64455 }
64456 }
64457
64458
64459
64460
64461
64462
64463
64464
64465 public function isAbsolutePath($file)
64466 {
64467 return strspn($file, '/\\', 0, 1)
64468 || (strlen($file) > 3 && ctype_alpha($file[0])
64469 && ':' === substr($file, 1, 1)
64470 && strspn($file, '/\\', 2, 1)
64471 )
64472 || null !== parse_url($file, PHP_URL_SCHEME)
64473 ;
64474 }
64475
64476
64477
64478
64479
64480
64481
64482
64483
64484
64485 public function tempnam($dir, $prefix)
64486 {
64487 list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
64488
64489
64490  if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) {
64491 $tmpFile = @tempnam($hierarchy, $prefix);
64492
64493
64494  if (false !== $tmpFile) {
64495 if (null !== $scheme && 'gs' !== $scheme) {
64496 return $scheme.'://'.$tmpFile;
64497 }
64498
64499 return $tmpFile;
64500 }
64501
64502 throw new IOException('A temporary file could not be created.');
64503 }
64504
64505
64506  for ($i = 0; $i < 10; ++$i) {
64507
64508  $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true);
64509
64510
64511  
64512  $handle = @fopen($tmpFile, 'x+');
64513
64514
64515  if (false === $handle) {
64516 continue;
64517 }
64518
64519
64520  @fclose($handle);
64521
64522 return $tmpFile;
64523 }
64524
64525 throw new IOException('A temporary file could not be created.');
64526 }
64527
64528
64529
64530
64531
64532
64533
64534
64535
64536
64537
64538 public function dumpFile($filename, $content, $mode = 0666)
64539 {
64540 $dir = dirname($filename);
64541
64542 if (!is_dir($dir)) {
64543 $this->mkdir($dir);
64544 }
64545
64546 if (!is_writable($dir)) {
64547 throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
64548 }
64549
64550 $tmpFile = $this->tempnam($dir, basename($filename));
64551
64552 if (false === @file_put_contents($tmpFile, $content)) {
64553 throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
64554 }
64555
64556 if (null !== $mode) {
64557 if (func_num_args() > 2) {
64558 @trigger_error('Support for modifying file permissions is deprecated since version 2.3.12 and will be removed in 3.0.', E_USER_DEPRECATED);
64559 }
64560
64561 $this->chmod($tmpFile, $mode);
64562 } elseif (file_exists($filename)) {
64563 @chmod($tmpFile, fileperms($filename));
64564 }
64565
64566 $this->rename($tmpFile, $filename, true);
64567 }
64568
64569
64570
64571
64572
64573
64574 private function toIterator($files)
64575 {
64576 if (!$files instanceof \Traversable) {
64577 $files = new \ArrayObject(is_array($files) ? $files : array($files));
64578 }
64579
64580 return $files;
64581 }
64582
64583
64584
64585
64586
64587
64588
64589
64590 private function getSchemeAndHierarchy($filename)
64591 {
64592 $components = explode('://', $filename, 2);
64593
64594 return 2 === count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
64595 }
64596 }
64597 Copyright (c) 2004-2017 Fabien Potencier
64598
64599 Permission is hereby granted, free of charge, to any person obtaining a copy
64600 of this software and associated documentation files (the "Software"), to deal
64601 in the Software without restriction, including without limitation the rights
64602 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
64603 copies of the Software, and to permit persons to whom the Software is furnished
64604 to do so, subject to the following conditions:
64605
64606 The above copyright notice and this permission notice shall be included in all
64607 copies or substantial portions of the Software.
64608
64609 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
64610 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64611 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
64612 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
64613 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
64614 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64615 THE SOFTWARE.
64616 <?php
64617
64618
64619
64620
64621
64622
64623
64624
64625
64626
64627 namespace Symfony\Component\Filesystem;
64628
64629 use Symfony\Component\Filesystem\Exception\IOException;
64630
64631
64632
64633
64634
64635
64636
64637
64638
64639
64640
64641
64642
64643
64644 class LockHandler
64645 {
64646 private $file;
64647 private $handle;
64648
64649
64650
64651
64652
64653
64654
64655 public function __construct($name, $lockPath = null)
64656 {
64657 $lockPath = $lockPath ?: sys_get_temp_dir();
64658
64659 if (!is_dir($lockPath)) {
64660 $fs = new Filesystem();
64661 $fs->mkdir($lockPath);
64662 }
64663
64664 if (!is_writable($lockPath)) {
64665 throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
64666 }
64667
64668 $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
64669 }
64670
64671
64672
64673
64674
64675
64676
64677
64678
64679
64680 public function lock($blocking = false)
64681 {
64682 if ($this->handle) {
64683 return true;
64684 }
64685
64686 $error = null;
64687
64688
64689  set_error_handler(function ($errno, $msg) use (&$error) {
64690 $error = $msg;
64691 });
64692
64693 if (!$this->handle = fopen($this->file, 'r')) {
64694 if ($this->handle = fopen($this->file, 'x')) {
64695 chmod($this->file, 0444);
64696 } elseif (!$this->handle = fopen($this->file, 'r')) {
64697 usleep(100); 
64698  $this->handle = fopen($this->file, 'r');
64699 }
64700 }
64701 restore_error_handler();
64702
64703 if (!$this->handle) {
64704 throw new IOException($error, 0, null, $this->file);
64705 }
64706
64707
64708  
64709  if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
64710 fclose($this->handle);
64711 $this->handle = null;
64712
64713 return false;
64714 }
64715
64716 return true;
64717 }
64718
64719
64720
64721
64722 public function release()
64723 {
64724 if ($this->handle) {
64725 flock($this->handle, LOCK_UN | LOCK_NB);
64726 fclose($this->handle);
64727 $this->handle = null;
64728 }
64729 }
64730 }
64731 <?php
64732
64733
64734
64735
64736
64737
64738
64739
64740
64741
64742 namespace Symfony\Component\Finder\Adapter;
64743
64744 @trigger_error('The '.__NAMESPACE__.'\AbstractAdapter class is deprecated since version 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
64745
64746
64747
64748
64749
64750
64751
64752
64753 abstract class AbstractAdapter implements AdapterInterface
64754 {
64755 protected $followLinks = false;
64756 protected $mode = 0;
64757 protected $minDepth = 0;
64758 protected $maxDepth = PHP_INT_MAX;
64759 protected $exclude = array();
64760 protected $names = array();
64761 protected $notNames = array();
64762 protected $contains = array();
64763 protected $notContains = array();
64764 protected $sizes = array();
64765 protected $dates = array();
64766 protected $filters = array();
64767 protected $sort = false;
64768 protected $paths = array();
64769 protected $notPaths = array();
64770 protected $ignoreUnreadableDirs = false;
64771
64772 private static $areSupported = array();
64773
64774
64775
64776
64777 public function isSupported()
64778 {
64779 $name = $this->getName();
64780
64781 if (!array_key_exists($name, self::$areSupported)) {
64782 self::$areSupported[$name] = $this->canBeUsed();
64783 }
64784
64785 return self::$areSupported[$name];
64786 }
64787
64788
64789
64790
64791 public function setFollowLinks($followLinks)
64792 {
64793 $this->followLinks = $followLinks;
64794
64795 return $this;
64796 }
64797
64798
64799
64800
64801 public function setMode($mode)
64802 {
64803 $this->mode = $mode;
64804
64805 return $this;
64806 }
64807
64808
64809
64810
64811 public function setDepths(array $depths)
64812 {
64813 $this->minDepth = 0;
64814 $this->maxDepth = PHP_INT_MAX;
64815
64816 foreach ($depths as $comparator) {
64817 switch ($comparator->getOperator()) {
64818 case '>':
64819 $this->minDepth = $comparator->getTarget() + 1;
64820 break;
64821 case '>=':
64822 $this->minDepth = $comparator->getTarget();
64823 break;
64824 case '<':
64825 $this->maxDepth = $comparator->getTarget() - 1;
64826 break;
64827 case '<=':
64828 $this->maxDepth = $comparator->getTarget();
64829 break;
64830 default:
64831 $this->minDepth = $this->maxDepth = $comparator->getTarget();
64832 }
64833 }
64834
64835 return $this;
64836 }
64837
64838
64839
64840
64841 public function setExclude(array $exclude)
64842 {
64843 $this->exclude = $exclude;
64844
64845 return $this;
64846 }
64847
64848
64849
64850
64851 public function setNames(array $names)
64852 {
64853 $this->names = $names;
64854
64855 return $this;
64856 }
64857
64858
64859
64860
64861 public function setNotNames(array $notNames)
64862 {
64863 $this->notNames = $notNames;
64864
64865 return $this;
64866 }
64867
64868
64869
64870
64871 public function setContains(array $contains)
64872 {
64873 $this->contains = $contains;
64874
64875 return $this;
64876 }
64877
64878
64879
64880
64881 public function setNotContains(array $notContains)
64882 {
64883 $this->notContains = $notContains;
64884
64885 return $this;
64886 }
64887
64888
64889
64890
64891 public function setSizes(array $sizes)
64892 {
64893 $this->sizes = $sizes;
64894
64895 return $this;
64896 }
64897
64898
64899
64900
64901 public function setDates(array $dates)
64902 {
64903 $this->dates = $dates;
64904
64905 return $this;
64906 }
64907
64908
64909
64910
64911 public function setFilters(array $filters)
64912 {
64913 $this->filters = $filters;
64914
64915 return $this;
64916 }
64917
64918
64919
64920
64921 public function setSort($sort)
64922 {
64923 $this->sort = $sort;
64924
64925 return $this;
64926 }
64927
64928
64929
64930
64931 public function setPath(array $paths)
64932 {
64933 $this->paths = $paths;
64934
64935 return $this;
64936 }
64937
64938
64939
64940
64941 public function setNotPath(array $notPaths)
64942 {
64943 $this->notPaths = $notPaths;
64944
64945 return $this;
64946 }
64947
64948
64949
64950
64951 public function ignoreUnreadableDirs($ignore = true)
64952 {
64953 $this->ignoreUnreadableDirs = (bool) $ignore;
64954
64955 return $this;
64956 }
64957
64958
64959
64960
64961
64962
64963
64964
64965
64966
64967
64968
64969 abstract protected function canBeUsed();
64970 }
64971 <?php
64972
64973
64974
64975
64976
64977
64978
64979
64980
64981
64982 namespace Symfony\Component\Finder\Adapter;
64983
64984 @trigger_error('The '.__NAMESPACE__.'\AbstractFindAdapter class is deprecated since version 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
64985
64986 use Symfony\Component\Finder\Exception\AccessDeniedException;
64987 use Symfony\Component\Finder\Iterator;
64988 use Symfony\Component\Finder\Shell\Shell;
64989 use Symfony\Component\Finder\Expression\Expression;
64990 use Symfony\Component\Finder\Shell\Command;
64991 use Symfony\Component\Finder\Comparator\NumberComparator;
64992 use Symfony\Component\Finder\Comparator\DateComparator;
64993
64994
64995
64996
64997
64998
64999
65000
65001 abstract class AbstractFindAdapter extends AbstractAdapter
65002 {
65003 protected $shell;
65004
65005 public function __construct()
65006 {
65007 $this->shell = new Shell();
65008 }
65009
65010
65011
65012
65013 public function searchInDirectory($dir)
65014 {
65015
65016  $dir = realpath($dir);
65017
65018
65019  if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
65020 return new Iterator\FilePathsIterator(array(), $dir);
65021 }
65022
65023 $command = Command::create();
65024 $find = $this->buildFindCommand($command, $dir);
65025
65026 if ($this->followLinks) {
65027 $find->add('-follow');
65028 }
65029
65030 $find->add('-mindepth')->add($this->minDepth + 1);
65031
65032 if (PHP_INT_MAX !== $this->maxDepth) {
65033 $find->add('-maxdepth')->add($this->maxDepth + 1);
65034 }
65035
65036 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
65037 $find->add('-type d');
65038 } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
65039 $find->add('-type f');
65040 }
65041
65042 $this->buildNamesFiltering($find, $this->names);
65043 $this->buildNamesFiltering($find, $this->notNames, true);
65044 $this->buildPathsFiltering($find, $dir, $this->paths);
65045 $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
65046 $this->buildSizesFiltering($find, $this->sizes);
65047 $this->buildDatesFiltering($find, $this->dates);
65048
65049 $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
65050 $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
65051
65052 if ($useGrep && ($this->contains || $this->notContains)) {
65053 $grep = $command->ins('grep');
65054 $this->buildContentFiltering($grep, $this->contains);
65055 $this->buildContentFiltering($grep, $this->notContains, true);
65056 }
65057
65058 if ($useSort) {
65059 $this->buildSorting($command, $this->sort);
65060 }
65061
65062 $command->setErrorHandler(
65063 $this->ignoreUnreadableDirs
65064
65065  ? function ($stderr) { }
65066 : function ($stderr) { throw new AccessDeniedException($stderr); }
65067 );
65068
65069 $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
65070 $iterator = new Iterator\FilePathsIterator($paths, $dir);
65071
65072 if ($this->exclude) {
65073 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
65074 }
65075
65076 if (!$useGrep && ($this->contains || $this->notContains)) {
65077 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
65078 }
65079
65080 if ($this->filters) {
65081 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
65082 }
65083
65084 if (!$useSort && $this->sort) {
65085 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
65086 $iterator = $iteratorAggregate->getIterator();
65087 }
65088
65089 return $iterator;
65090 }
65091
65092
65093
65094
65095 protected function canBeUsed()
65096 {
65097 return $this->shell->testCommand('find');
65098 }
65099
65100
65101
65102
65103
65104
65105
65106 protected function buildFindCommand(Command $command, $dir)
65107 {
65108 return $command
65109 ->ins('find')
65110 ->add('find ')
65111 ->arg($dir)
65112 ->add('-noleaf'); 
65113  }
65114
65115
65116
65117
65118
65119
65120 private function buildNamesFiltering(Command $command, array $names, $not = false)
65121 {
65122 if (0 === count($names)) {
65123 return;
65124 }
65125
65126 $command->add($not ? '-not' : null)->cmd('(');
65127
65128 foreach ($names as $i => $name) {
65129 $expr = Expression::create($name);
65130
65131
65132  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
65133 $expr = Expression::create($expr->getGlob()->toRegex(false));
65134 }
65135
65136
65137  
65138  
65139  if ($expr->isRegex()) {
65140 $regex = $expr->getRegex();
65141 $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
65142 ->setStartFlag(false)
65143 ->setStartJoker(true)
65144 ->replaceJokers('[^/]');
65145 if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
65146 $regex->setEndJoker(false)->append('[^/]*');
65147 }
65148 }
65149
65150 $command
65151 ->add($i > 0 ? '-or' : null)
65152 ->add($expr->isRegex()
65153 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
65154 : ($expr->isCaseSensitive() ? '-name' : '-iname')
65155 )
65156 ->arg($expr->renderPattern());
65157 }
65158
65159 $command->cmd(')');
65160 }
65161
65162
65163
65164
65165
65166
65167
65168 private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
65169 {
65170 if (0 === count($paths)) {
65171 return;
65172 }
65173
65174 $command->add($not ? '-not' : null)->cmd('(');
65175
65176 foreach ($paths as $i => $path) {
65177 $expr = Expression::create($path);
65178
65179
65180  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
65181 $expr = Expression::create($expr->getGlob()->toRegex(false));
65182 }
65183
65184
65185  if ($expr->isRegex()) {
65186 $regex = $expr->getRegex();
65187 $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
65188 } else {
65189 $expr->prepend('*')->append('*');
65190 }
65191
65192 $command
65193 ->add($i > 0 ? '-or' : null)
65194 ->add($expr->isRegex()
65195 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
65196 : ($expr->isCaseSensitive() ? '-path' : '-ipath')
65197 )
65198 ->arg($expr->renderPattern());
65199 }
65200
65201 $command->cmd(')');
65202 }
65203
65204
65205
65206
65207
65208 private function buildSizesFiltering(Command $command, array $sizes)
65209 {
65210 foreach ($sizes as $i => $size) {
65211 $command->add($i > 0 ? '-and' : null);
65212
65213 switch ($size->getOperator()) {
65214 case '<=':
65215 $command->add('-size -'.($size->getTarget() + 1).'c');
65216 break;
65217 case '>=':
65218 $command->add('-size +'.($size->getTarget() - 1).'c');
65219 break;
65220 case '>':
65221 $command->add('-size +'.$size->getTarget().'c');
65222 break;
65223 case '!=':
65224 $command->add('-size -'.$size->getTarget().'c');
65225 $command->add('-size +'.$size->getTarget().'c');
65226 break;
65227 case '<':
65228 default:
65229 $command->add('-size -'.$size->getTarget().'c');
65230 }
65231 }
65232 }
65233
65234
65235
65236
65237
65238 private function buildDatesFiltering(Command $command, array $dates)
65239 {
65240 foreach ($dates as $i => $date) {
65241 $command->add($i > 0 ? '-and' : null);
65242
65243 $mins = (int) round((time() - $date->getTarget()) / 60);
65244
65245 if (0 > $mins) {
65246
65247  $command->add(' -mmin -0');
65248
65249  return;
65250 }
65251
65252 switch ($date->getOperator()) {
65253 case '<=':
65254 $command->add('-mmin +'.($mins - 1));
65255 break;
65256 case '>=':
65257 $command->add('-mmin -'.($mins + 1));
65258 break;
65259 case '>':
65260 $command->add('-mmin -'.$mins);
65261 break;
65262 case '!=':
65263 $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
65264 break;
65265 case '<':
65266 default:
65267 $command->add('-mmin +'.$mins);
65268 }
65269 }
65270 }
65271
65272
65273
65274
65275
65276
65277
65278 private function buildSorting(Command $command, $sort)
65279 {
65280 $this->buildFormatSorting($command, $sort);
65281 }
65282
65283
65284
65285
65286
65287 abstract protected function buildFormatSorting(Command $command, $sort);
65288
65289
65290
65291
65292
65293
65294 abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
65295 }
65296 <?php
65297
65298
65299
65300
65301
65302
65303
65304
65305
65306
65307 namespace Symfony\Component\Finder\Adapter;
65308
65309
65310
65311
65312
65313
65314 interface AdapterInterface
65315 {
65316
65317
65318
65319
65320
65321 public function setFollowLinks($followLinks);
65322
65323
65324
65325
65326
65327
65328 public function setMode($mode);
65329
65330
65331
65332
65333 public function setExclude(array $exclude);
65334
65335
65336
65337
65338 public function setDepths(array $depths);
65339
65340
65341
65342
65343 public function setNames(array $names);
65344
65345
65346
65347
65348 public function setNotNames(array $notNames);
65349
65350
65351
65352
65353 public function setContains(array $contains);
65354
65355
65356
65357
65358 public function setNotContains(array $notContains);
65359
65360
65361
65362
65363 public function setSizes(array $sizes);
65364
65365
65366
65367
65368 public function setDates(array $dates);
65369
65370
65371
65372
65373 public function setFilters(array $filters);
65374
65375
65376
65377
65378
65379
65380 public function setSort($sort);
65381
65382
65383
65384
65385 public function setPath(array $paths);
65386
65387
65388
65389
65390 public function setNotPath(array $notPaths);
65391
65392
65393
65394
65395
65396
65397 public function ignoreUnreadableDirs($ignore = true);
65398
65399
65400
65401
65402
65403
65404 public function searchInDirectory($dir);
65405
65406
65407
65408
65409
65410
65411 public function isSupported();
65412
65413
65414
65415
65416
65417
65418 public function getName();
65419 }
65420 <?php
65421
65422
65423
65424
65425
65426
65427
65428
65429
65430
65431 namespace Symfony\Component\Finder\Adapter;
65432
65433 @trigger_error('The '.__NAMESPACE__.'\BsdFindAdapter class is deprecated since version 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
65434
65435 use Symfony\Component\Finder\Shell\Shell;
65436 use Symfony\Component\Finder\Shell\Command;
65437 use Symfony\Component\Finder\Iterator\SortableIterator;
65438 use Symfony\Component\Finder\Expression\Expression;
65439
65440
65441
65442
65443
65444
65445
65446
65447 class BsdFindAdapter extends AbstractFindAdapter
65448 {
65449
65450
65451
65452 public function getName()
65453 {
65454 return 'bsd_find';
65455 }
65456
65457
65458
65459
65460 protected function canBeUsed()
65461 {
65462 return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
65463 }
65464
65465
65466
65467
65468 protected function buildFormatSorting(Command $command, $sort)
65469 {
65470 switch ($sort) {
65471 case SortableIterator::SORT_BY_NAME:
65472 $command->ins('sort')->add('| sort');
65473
65474 return;
65475 case SortableIterator::SORT_BY_TYPE:
65476 $format = '%HT';
65477 break;
65478 case SortableIterator::SORT_BY_ACCESSED_TIME:
65479 $format = '%a';
65480 break;
65481 case SortableIterator::SORT_BY_CHANGED_TIME:
65482 $format = '%c';
65483 break;
65484 case SortableIterator::SORT_BY_MODIFIED_TIME:
65485 $format = '%m';
65486 break;
65487 default:
65488 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
65489 }
65490
65491 $command
65492 ->add('-print0 | xargs -0 stat -f')
65493 ->arg($format.'%t%N')
65494 ->add('| sort | cut -f 2');
65495 }
65496
65497
65498
65499
65500 protected function buildFindCommand(Command $command, $dir)
65501 {
65502 parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
65503
65504 return $command;
65505 }
65506
65507
65508
65509
65510 protected function buildContentFiltering(Command $command, array $contains, $not = false)
65511 {
65512 foreach ($contains as $contain) {
65513 $expr = Expression::create($contain);
65514
65515
65516  $command
65517 ->add('| grep -v \'^$\'')
65518 ->add('| xargs -I{} grep -I')
65519 ->add($expr->isCaseSensitive() ? null : '-i')
65520 ->add($not ? '-L' : '-l')
65521 ->add('-Ee')->arg($expr->renderPattern())
65522 ->add('{}')
65523 ;
65524 }
65525 }
65526 }
65527 <?php
65528
65529
65530
65531
65532
65533
65534
65535
65536
65537
65538 namespace Symfony\Component\Finder\Adapter;
65539
65540 @trigger_error('The '.__NAMESPACE__.'\GnuFindAdapter class is deprecated since version 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
65541
65542 use Symfony\Component\Finder\Shell\Shell;
65543 use Symfony\Component\Finder\Shell\Command;
65544 use Symfony\Component\Finder\Iterator\SortableIterator;
65545 use Symfony\Component\Finder\Expression\Expression;
65546
65547
65548
65549
65550
65551
65552
65553
65554 class GnuFindAdapter extends AbstractFindAdapter
65555 {
65556
65557
65558
65559 public function getName()
65560 {
65561 return 'gnu_find';
65562 }
65563
65564
65565
65566
65567 protected function buildFormatSorting(Command $command, $sort)
65568 {
65569 switch ($sort) {
65570 case SortableIterator::SORT_BY_NAME:
65571 $command->ins('sort')->add('| sort');
65572
65573 return;
65574 case SortableIterator::SORT_BY_TYPE:
65575 $format = '%y';
65576 break;
65577 case SortableIterator::SORT_BY_ACCESSED_TIME:
65578 $format = '%A@';
65579 break;
65580 case SortableIterator::SORT_BY_CHANGED_TIME:
65581 $format = '%C@';
65582 break;
65583 case SortableIterator::SORT_BY_MODIFIED_TIME:
65584 $format = '%T@';
65585 break;
65586 default:
65587 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
65588 }
65589
65590 $command
65591 ->get('find')
65592 ->add('-printf')
65593 ->arg($format.' %h/%f\\n')
65594 ->add('| sort | cut')
65595 ->arg('-d ')
65596 ->arg('-f2-')
65597 ;
65598 }
65599
65600
65601
65602
65603 protected function canBeUsed()
65604 {
65605 return Shell::TYPE_UNIX === $this->shell->getType() && parent::canBeUsed();
65606 }
65607
65608
65609
65610
65611 protected function buildFindCommand(Command $command, $dir)
65612 {
65613 return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
65614 }
65615
65616
65617
65618
65619 protected function buildContentFiltering(Command $command, array $contains, $not = false)
65620 {
65621 foreach ($contains as $contain) {
65622 $expr = Expression::create($contain);
65623
65624
65625  $command
65626 ->add('| xargs -I{} -r grep -I')
65627 ->add($expr->isCaseSensitive() ? null : '-i')
65628 ->add($not ? '-L' : '-l')
65629 ->add('-Ee')->arg($expr->renderPattern())
65630 ->add('{}')
65631 ;
65632 }
65633 }
65634 }
65635 <?php
65636
65637
65638
65639
65640
65641
65642
65643
65644
65645
65646 namespace Symfony\Component\Finder\Adapter;
65647
65648 @trigger_error('The '.__NAMESPACE__.'\PhpAdapter class is deprecated since version 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
65649
65650 use Symfony\Component\Finder\Iterator;
65651
65652
65653
65654
65655
65656
65657
65658
65659 class PhpAdapter extends AbstractAdapter
65660 {
65661
65662
65663
65664 public function searchInDirectory($dir)
65665 {
65666 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
65667
65668 if ($this->followLinks) {
65669 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
65670 }
65671
65672 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
65673
65674 if ($this->exclude) {
65675 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
65676 }
65677
65678 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
65679
65680 if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
65681 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
65682 }
65683
65684 if ($this->mode) {
65685 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
65686 }
65687
65688 if ($this->names || $this->notNames) {
65689 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
65690 }
65691
65692 if ($this->contains || $this->notContains) {
65693 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
65694 }
65695
65696 if ($this->sizes) {
65697 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
65698 }
65699
65700 if ($this->dates) {
65701 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
65702 }
65703
65704 if ($this->filters) {
65705 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
65706 }
65707
65708 if ($this->paths || $this->notPaths) {
65709 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
65710 }
65711
65712 if ($this->sort) {
65713 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
65714 $iterator = $iteratorAggregate->getIterator();
65715 }
65716
65717 return $iterator;
65718 }
65719
65720
65721
65722
65723 public function getName()
65724 {
65725 return 'php';
65726 }
65727
65728
65729
65730
65731 protected function canBeUsed()
65732 {
65733 return true;
65734 }
65735 }
65736 <?php
65737
65738
65739
65740
65741
65742
65743
65744
65745
65746
65747 namespace Symfony\Component\Finder\Comparator;
65748
65749
65750
65751
65752
65753
65754 class Comparator
65755 {
65756 private $target;
65757 private $operator = '==';
65758
65759
65760
65761
65762
65763
65764 public function getTarget()
65765 {
65766 return $this->target;
65767 }
65768
65769
65770
65771
65772
65773
65774 public function setTarget($target)
65775 {
65776 $this->target = $target;
65777 }
65778
65779
65780
65781
65782
65783
65784 public function getOperator()
65785 {
65786 return $this->operator;
65787 }
65788
65789
65790
65791
65792
65793
65794
65795
65796 public function setOperator($operator)
65797 {
65798 if (!$operator) {
65799 $operator = '==';
65800 }
65801
65802 if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
65803 throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
65804 }
65805
65806 $this->operator = $operator;
65807 }
65808
65809
65810
65811
65812
65813
65814
65815
65816 public function test($test)
65817 {
65818 switch ($this->operator) {
65819 case '>':
65820 return $test > $this->target;
65821 case '>=':
65822 return $test >= $this->target;
65823 case '<':
65824 return $test < $this->target;
65825 case '<=':
65826 return $test <= $this->target;
65827 case '!=':
65828 return $test != $this->target;
65829 }
65830
65831 return $test == $this->target;
65832 }
65833 }
65834 <?php
65835
65836
65837
65838
65839
65840
65841
65842
65843
65844
65845 namespace Symfony\Component\Finder\Comparator;
65846
65847
65848
65849
65850
65851
65852 class DateComparator extends Comparator
65853 {
65854
65855
65856
65857
65858
65859 public function __construct($test)
65860 {
65861 if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
65862 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
65863 }
65864
65865 try {
65866 $date = new \DateTime($matches[2]);
65867 $target = $date->format('U');
65868 } catch (\Exception $e) {
65869 throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
65870 }
65871
65872 $operator = isset($matches[1]) ? $matches[1] : '==';
65873 if ('since' === $operator || 'after' === $operator) {
65874 $operator = '>';
65875 }
65876
65877 if ('until' === $operator || 'before' === $operator) {
65878 $operator = '<';
65879 }
65880
65881 $this->setOperator($operator);
65882 $this->setTarget($target);
65883 }
65884 }
65885 <?php
65886
65887
65888
65889
65890
65891
65892
65893
65894
65895
65896 namespace Symfony\Component\Finder\Comparator;
65897
65898
65899
65900
65901
65902
65903
65904
65905
65906
65907
65908
65909
65910
65911
65912
65913
65914
65915
65916
65917
65918
65919 class NumberComparator extends Comparator
65920 {
65921
65922
65923
65924
65925
65926 public function __construct($test)
65927 {
65928 if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
65929 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
65930 }
65931
65932 $target = $matches[2];
65933 if (!is_numeric($target)) {
65934 throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
65935 }
65936 if (isset($matches[3])) {
65937
65938  switch (strtolower($matches[3])) {
65939 case 'k':
65940 $target *= 1000;
65941 break;
65942 case 'ki':
65943 $target *= 1024;
65944 break;
65945 case 'm':
65946 $target *= 1000000;
65947 break;
65948 case 'mi':
65949 $target *= 1024 * 1024;
65950 break;
65951 case 'g':
65952 $target *= 1000000000;
65953 break;
65954 case 'gi':
65955 $target *= 1024 * 1024 * 1024;
65956 break;
65957 }
65958 }
65959
65960 $this->setTarget($target);
65961 $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
65962 }
65963 }
65964 <?php
65965
65966
65967
65968
65969
65970
65971
65972
65973
65974
65975 namespace Symfony\Component\Finder\Exception;
65976
65977
65978
65979
65980 class AccessDeniedException extends \UnexpectedValueException
65981 {
65982 }
65983 <?php
65984
65985
65986
65987
65988
65989
65990
65991
65992
65993
65994 namespace Symfony\Component\Finder\Exception;
65995
65996 @trigger_error('The '.__NAMESPACE__.'\AdapterFailureException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65997
65998 use Symfony\Component\Finder\Adapter\AdapterInterface;
65999
66000
66001
66002
66003
66004
66005
66006
66007 class AdapterFailureException extends \RuntimeException implements ExceptionInterface
66008 {
66009 private $adapter;
66010
66011
66012
66013
66014
66015
66016 public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
66017 {
66018 $this->adapter = $adapter;
66019 parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
66020 }
66021
66022
66023
66024
66025 public function getAdapter()
66026 {
66027 return $this->adapter;
66028 }
66029 }
66030 <?php
66031
66032
66033
66034
66035
66036
66037
66038
66039
66040
66041 namespace Symfony\Component\Finder\Exception;
66042
66043
66044
66045
66046 interface ExceptionInterface
66047 {
66048
66049
66050
66051 public function getAdapter();
66052 }
66053 <?php
66054
66055
66056
66057
66058
66059
66060
66061
66062
66063
66064 namespace Symfony\Component\Finder\Exception;
66065
66066 @trigger_error('The '.__NAMESPACE__.'\OperationNotPermitedException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66067
66068
66069
66070
66071
66072
66073 class OperationNotPermitedException extends AdapterFailureException
66074 {
66075 }
66076 <?php
66077
66078
66079
66080
66081
66082
66083
66084
66085
66086
66087 namespace Symfony\Component\Finder\Exception;
66088
66089 @trigger_error('The '.__NAMESPACE__.'\ShellCommandFailureException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66090
66091 use Symfony\Component\Finder\Adapter\AdapterInterface;
66092 use Symfony\Component\Finder\Shell\Command;
66093
66094
66095
66096
66097
66098
66099 class ShellCommandFailureException extends AdapterFailureException
66100 {
66101 private $command;
66102
66103 public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
66104 {
66105 $this->command = $command;
66106 parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
66107 }
66108
66109
66110
66111
66112 public function getCommand()
66113 {
66114 return $this->command;
66115 }
66116 }
66117 <?php
66118
66119
66120
66121
66122
66123
66124
66125
66126
66127
66128 namespace Symfony\Component\Finder\Expression;
66129
66130 @trigger_error('The '.__NAMESPACE__.'\Expression class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66131
66132
66133
66134
66135 class Expression implements ValueInterface
66136 {
66137 const TYPE_REGEX = 1;
66138 const TYPE_GLOB = 2;
66139
66140
66141
66142
66143 private $value;
66144
66145
66146
66147
66148
66149
66150 public static function create($expr)
66151 {
66152 return new self($expr);
66153 }
66154
66155
66156
66157
66158 public function __construct($expr)
66159 {
66160 try {
66161 $this->value = Regex::create($expr);
66162 } catch (\InvalidArgumentException $e) {
66163 $this->value = new Glob($expr);
66164 }
66165 }
66166
66167
66168
66169
66170 public function __toString()
66171 {
66172 return $this->render();
66173 }
66174
66175
66176
66177
66178 public function render()
66179 {
66180 return $this->value->render();
66181 }
66182
66183
66184
66185
66186 public function renderPattern()
66187 {
66188 return $this->value->renderPattern();
66189 }
66190
66191
66192
66193
66194 public function isCaseSensitive()
66195 {
66196 return $this->value->isCaseSensitive();
66197 }
66198
66199
66200
66201
66202 public function getType()
66203 {
66204 return $this->value->getType();
66205 }
66206
66207
66208
66209
66210 public function prepend($expr)
66211 {
66212 $this->value->prepend($expr);
66213
66214 return $this;
66215 }
66216
66217
66218
66219
66220 public function append($expr)
66221 {
66222 $this->value->append($expr);
66223
66224 return $this;
66225 }
66226
66227
66228
66229
66230 public function isRegex()
66231 {
66232 return self::TYPE_REGEX === $this->value->getType();
66233 }
66234
66235
66236
66237
66238 public function isGlob()
66239 {
66240 return self::TYPE_GLOB === $this->value->getType();
66241 }
66242
66243
66244
66245
66246
66247
66248 public function getGlob()
66249 {
66250 if (self::TYPE_GLOB !== $this->value->getType()) {
66251 throw new \LogicException('Regex can\'t be transformed to glob.');
66252 }
66253
66254 return $this->value;
66255 }
66256
66257
66258
66259
66260 public function getRegex()
66261 {
66262 return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
66263 }
66264 }
66265 <?php
66266
66267
66268
66269
66270
66271
66272
66273
66274
66275
66276 namespace Symfony\Component\Finder\Expression;
66277
66278 @trigger_error('The '.__NAMESPACE__.'\Glob class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66279
66280 use Symfony\Component\Finder\Glob as FinderGlob;
66281
66282
66283
66284
66285 class Glob implements ValueInterface
66286 {
66287 private $pattern;
66288
66289
66290
66291
66292 public function __construct($pattern)
66293 {
66294 $this->pattern = $pattern;
66295 }
66296
66297
66298
66299
66300 public function render()
66301 {
66302 return $this->pattern;
66303 }
66304
66305
66306
66307
66308 public function renderPattern()
66309 {
66310 return $this->pattern;
66311 }
66312
66313
66314
66315
66316 public function getType()
66317 {
66318 return Expression::TYPE_GLOB;
66319 }
66320
66321
66322
66323
66324 public function isCaseSensitive()
66325 {
66326 return true;
66327 }
66328
66329
66330
66331
66332 public function prepend($expr)
66333 {
66334 $this->pattern = $expr.$this->pattern;
66335
66336 return $this;
66337 }
66338
66339
66340
66341
66342 public function append($expr)
66343 {
66344 $this->pattern .= $expr;
66345
66346 return $this;
66347 }
66348
66349
66350
66351
66352
66353
66354 public function isExpandable()
66355 {
66356 return false !== strpos($this->pattern, '{')
66357 && false !== strpos($this->pattern, '}');
66358 }
66359
66360
66361
66362
66363
66364
66365
66366 public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
66367 {
66368 $regex = FinderGlob::toRegex($this->pattern, $strictLeadingDot, $strictWildcardSlash, '');
66369
66370 return new Regex($regex);
66371 }
66372 }
66373 <?php
66374
66375
66376
66377
66378
66379
66380
66381
66382
66383
66384 namespace Symfony\Component\Finder\Expression;
66385
66386 @trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66387
66388
66389
66390
66391 class Regex implements ValueInterface
66392 {
66393 const START_FLAG = '^';
66394 const END_FLAG = '$';
66395 const BOUNDARY = '~';
66396 const JOKER = '.*';
66397 const ESCAPING = '\\';
66398
66399
66400
66401
66402 private $pattern;
66403
66404
66405
66406
66407 private $options;
66408
66409
66410
66411
66412 private $startFlag;
66413
66414
66415
66416
66417 private $endFlag;
66418
66419
66420
66421
66422 private $startJoker;
66423
66424
66425
66426
66427 private $endJoker;
66428
66429
66430
66431
66432
66433
66434
66435
66436 public static function create($expr)
66437 {
66438 if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
66439 $start = substr($m[1], 0, 1);
66440 $end = substr($m[1], -1);
66441
66442 if (
66443 ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
66444 || ('{' === $start && '}' === $end)
66445 || ('(' === $start && ')' === $end)
66446 ) {
66447 return new self(substr($m[1], 1, -1), $m[2], $end);
66448 }
66449 }
66450
66451 throw new \InvalidArgumentException('Given expression is not a regex.');
66452 }
66453
66454
66455
66456
66457
66458
66459 public function __construct($pattern, $options = '', $delimiter = null)
66460 {
66461 if (null !== $delimiter) {
66462
66463  $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
66464 }
66465
66466 $this->parsePattern($pattern);
66467 $this->options = $options;
66468 }
66469
66470
66471
66472
66473 public function __toString()
66474 {
66475 return $this->render();
66476 }
66477
66478
66479
66480
66481 public function render()
66482 {
66483 return self::BOUNDARY
66484 .$this->renderPattern()
66485 .self::BOUNDARY
66486 .$this->options;
66487 }
66488
66489
66490
66491
66492 public function renderPattern()
66493 {
66494 return ($this->startFlag ? self::START_FLAG : '')
66495 .($this->startJoker ? self::JOKER : '')
66496 .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
66497 .($this->endJoker ? self::JOKER : '')
66498 .($this->endFlag ? self::END_FLAG : '');
66499 }
66500
66501
66502
66503
66504 public function isCaseSensitive()
66505 {
66506 return !$this->hasOption('i');
66507 }
66508
66509
66510
66511
66512 public function getType()
66513 {
66514 return Expression::TYPE_REGEX;
66515 }
66516
66517
66518
66519
66520 public function prepend($expr)
66521 {
66522 $this->pattern = $expr.$this->pattern;
66523
66524 return $this;
66525 }
66526
66527
66528
66529
66530 public function append($expr)
66531 {
66532 $this->pattern .= $expr;
66533
66534 return $this;
66535 }
66536
66537
66538
66539
66540
66541
66542 public function hasOption($option)
66543 {
66544 return false !== strpos($this->options, $option);
66545 }
66546
66547
66548
66549
66550
66551
66552 public function addOption($option)
66553 {
66554 if (!$this->hasOption($option)) {
66555 $this->options .= $option;
66556 }
66557
66558 return $this;
66559 }
66560
66561
66562
66563
66564
66565
66566 public function removeOption($option)
66567 {
66568 $this->options = str_replace($option, '', $this->options);
66569
66570 return $this;
66571 }
66572
66573
66574
66575
66576
66577
66578 public function setStartFlag($startFlag)
66579 {
66580 $this->startFlag = $startFlag;
66581
66582 return $this;
66583 }
66584
66585
66586
66587
66588 public function hasStartFlag()
66589 {
66590 return $this->startFlag;
66591 }
66592
66593
66594
66595
66596
66597
66598 public function setEndFlag($endFlag)
66599 {
66600 $this->endFlag = (bool) $endFlag;
66601
66602 return $this;
66603 }
66604
66605
66606
66607
66608 public function hasEndFlag()
66609 {
66610 return $this->endFlag;
66611 }
66612
66613
66614
66615
66616
66617
66618 public function setStartJoker($startJoker)
66619 {
66620 $this->startJoker = $startJoker;
66621
66622 return $this;
66623 }
66624
66625
66626
66627
66628 public function hasStartJoker()
66629 {
66630 return $this->startJoker;
66631 }
66632
66633
66634
66635
66636
66637
66638 public function setEndJoker($endJoker)
66639 {
66640 $this->endJoker = (bool) $endJoker;
66641
66642 return $this;
66643 }
66644
66645
66646
66647
66648 public function hasEndJoker()
66649 {
66650 return $this->endJoker;
66651 }
66652
66653
66654
66655
66656 public function replaceJokers($replacement)
66657 {
66658 $replace = function ($subject) use ($replacement) {
66659 $subject = $subject[0];
66660 $replace = 0 === substr_count($subject, '\\') % 2;
66661
66662 return $replace ? str_replace('.', $replacement, $subject) : $subject;
66663 };
66664
66665 $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
66666
66667 return $this;
66668 }
66669
66670
66671
66672
66673 private function parsePattern($pattern)
66674 {
66675 if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
66676 $pattern = substr($pattern, 1);
66677 }
66678
66679 if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
66680 $pattern = substr($pattern, 2);
66681 }
66682
66683 if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
66684 $pattern = substr($pattern, 0, -1);
66685 }
66686
66687 if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
66688 $pattern = substr($pattern, 0, -2);
66689 }
66690
66691 $this->pattern = $pattern;
66692 }
66693 }
66694 <?php
66695
66696
66697
66698
66699
66700
66701
66702
66703
66704
66705 namespace Symfony\Component\Finder\Expression;
66706
66707 @trigger_error('The '.__NAMESPACE__.'\ValueInterface interface is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66708
66709
66710
66711
66712 interface ValueInterface
66713 {
66714
66715
66716
66717
66718
66719 public function render();
66720
66721
66722
66723
66724
66725
66726 public function renderPattern();
66727
66728
66729
66730
66731
66732
66733 public function isCaseSensitive();
66734
66735
66736
66737
66738
66739
66740 public function getType();
66741
66742
66743
66744
66745
66746
66747 public function prepend($expr);
66748
66749
66750
66751
66752
66753
66754 public function append($expr);
66755 }
66756 <?php
66757
66758
66759
66760
66761
66762
66763
66764
66765
66766
66767 namespace Symfony\Component\Finder;
66768
66769 use Symfony\Component\Finder\Adapter\AdapterInterface;
66770 use Symfony\Component\Finder\Adapter\GnuFindAdapter;
66771 use Symfony\Component\Finder\Adapter\BsdFindAdapter;
66772 use Symfony\Component\Finder\Adapter\PhpAdapter;
66773 use Symfony\Component\Finder\Comparator\DateComparator;
66774 use Symfony\Component\Finder\Comparator\NumberComparator;
66775 use Symfony\Component\Finder\Exception\ExceptionInterface;
66776 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
66777 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
66778 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
66779 use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
66780 use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
66781 use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
66782 use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
66783 use Symfony\Component\Finder\Iterator\SortableIterator;
66784
66785
66786
66787
66788
66789
66790
66791
66792
66793
66794
66795
66796
66797
66798 class Finder implements \IteratorAggregate, \Countable
66799 {
66800 const IGNORE_VCS_FILES = 1;
66801 const IGNORE_DOT_FILES = 2;
66802
66803 private $mode = 0;
66804 private $names = array();
66805 private $notNames = array();
66806 private $exclude = array();
66807 private $filters = array();
66808 private $depths = array();
66809 private $sizes = array();
66810 private $followLinks = false;
66811 private $sort = false;
66812 private $ignore = 0;
66813 private $dirs = array();
66814 private $dates = array();
66815 private $iterators = array();
66816 private $contains = array();
66817 private $notContains = array();
66818 private $adapters = null;
66819 private $paths = array();
66820 private $notPaths = array();
66821 private $ignoreUnreadableDirs = false;
66822
66823 private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
66824
66825 public function __construct()
66826 {
66827 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
66828 }
66829
66830
66831
66832
66833
66834
66835 public static function create()
66836 {
66837 return new static();
66838 }
66839
66840
66841
66842
66843
66844
66845
66846
66847
66848
66849
66850 public function addAdapter(AdapterInterface $adapter, $priority = 0)
66851 {
66852 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66853
66854 $this->initDefaultAdapters();
66855
66856 $this->adapters[$adapter->getName()] = array(
66857 'adapter' => $adapter,
66858 'priority' => $priority,
66859 'selected' => false,
66860 );
66861
66862 return $this->sortAdapters();
66863 }
66864
66865
66866
66867
66868
66869
66870
66871
66872 public function useBestAdapter()
66873 {
66874 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66875
66876 $this->initDefaultAdapters();
66877
66878 $this->resetAdapterSelection();
66879
66880 return $this->sortAdapters();
66881 }
66882
66883
66884
66885
66886
66887
66888
66889
66890
66891
66892
66893
66894 public function setAdapter($name)
66895 {
66896 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66897
66898 $this->initDefaultAdapters();
66899
66900 if (!isset($this->adapters[$name])) {
66901 throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
66902 }
66903
66904 $this->resetAdapterSelection();
66905 $this->adapters[$name]['selected'] = true;
66906
66907 return $this->sortAdapters();
66908 }
66909
66910
66911
66912
66913
66914
66915
66916
66917 public function removeAdapters()
66918 {
66919 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66920
66921 $this->adapters = array();
66922
66923 return $this;
66924 }
66925
66926
66927
66928
66929
66930
66931
66932
66933 public function getAdapters()
66934 {
66935 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66936
66937 $this->initDefaultAdapters();
66938
66939 return array_values(array_map(function (array $adapter) {
66940 return $adapter['adapter'];
66941 }, $this->adapters));
66942 }
66943
66944
66945
66946
66947
66948
66949 public function directories()
66950 {
66951 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
66952
66953 return $this;
66954 }
66955
66956
66957
66958
66959
66960
66961 public function files()
66962 {
66963 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
66964
66965 return $this;
66966 }
66967
66968
66969
66970
66971
66972
66973
66974
66975
66976
66977
66978
66979
66980
66981
66982
66983 public function depth($level)
66984 {
66985 $this->depths[] = new Comparator\NumberComparator($level);
66986
66987 return $this;
66988 }
66989
66990
66991
66992
66993
66994
66995
66996
66997
66998
66999
67000
67001
67002
67003
67004
67005
67006
67007
67008 public function date($date)
67009 {
67010 $this->dates[] = new Comparator\DateComparator($date);
67011
67012 return $this;
67013 }
67014
67015
67016
67017
67018
67019
67020
67021
67022
67023
67024
67025
67026
67027
67028
67029
67030 public function name($pattern)
67031 {
67032 $this->names[] = $pattern;
67033
67034 return $this;
67035 }
67036
67037
67038
67039
67040
67041
67042
67043
67044
67045
67046 public function notName($pattern)
67047 {
67048 $this->notNames[] = $pattern;
67049
67050 return $this;
67051 }
67052
67053
67054
67055
67056
67057
67058
67059
67060
67061
67062
67063
67064
67065
67066
67067 public function contains($pattern)
67068 {
67069 $this->contains[] = $pattern;
67070
67071 return $this;
67072 }
67073
67074
67075
67076
67077
67078
67079
67080
67081
67082
67083
67084
67085
67086
67087
67088 public function notContains($pattern)
67089 {
67090 $this->notContains[] = $pattern;
67091
67092 return $this;
67093 }
67094
67095
67096
67097
67098
67099
67100
67101
67102
67103
67104
67105
67106
67107
67108
67109
67110
67111 public function path($pattern)
67112 {
67113 $this->paths[] = $pattern;
67114
67115 return $this;
67116 }
67117
67118
67119
67120
67121
67122
67123
67124
67125
67126
67127
67128
67129
67130
67131
67132
67133
67134 public function notPath($pattern)
67135 {
67136 $this->notPaths[] = $pattern;
67137
67138 return $this;
67139 }
67140
67141
67142
67143
67144
67145
67146
67147
67148
67149
67150
67151
67152
67153
67154
67155 public function size($size)
67156 {
67157 $this->sizes[] = new Comparator\NumberComparator($size);
67158
67159 return $this;
67160 }
67161
67162
67163
67164
67165
67166
67167
67168
67169
67170
67171 public function exclude($dirs)
67172 {
67173 $this->exclude = array_merge($this->exclude, (array) $dirs);
67174
67175 return $this;
67176 }
67177
67178
67179
67180
67181
67182
67183
67184
67185
67186
67187 public function ignoreDotFiles($ignoreDotFiles)
67188 {
67189 if ($ignoreDotFiles) {
67190 $this->ignore |= static::IGNORE_DOT_FILES;
67191 } else {
67192 $this->ignore &= ~static::IGNORE_DOT_FILES;
67193 }
67194
67195 return $this;
67196 }
67197
67198
67199
67200
67201
67202
67203
67204
67205
67206
67207 public function ignoreVCS($ignoreVCS)
67208 {
67209 if ($ignoreVCS) {
67210 $this->ignore |= static::IGNORE_VCS_FILES;
67211 } else {
67212 $this->ignore &= ~static::IGNORE_VCS_FILES;
67213 }
67214
67215 return $this;
67216 }
67217
67218
67219
67220
67221
67222
67223
67224
67225 public static function addVCSPattern($pattern)
67226 {
67227 foreach ((array) $pattern as $p) {
67228 self::$vcsPatterns[] = $p;
67229 }
67230
67231 self::$vcsPatterns = array_unique(self::$vcsPatterns);
67232 }
67233
67234
67235
67236
67237
67238
67239
67240
67241
67242
67243
67244
67245 public function sort(\Closure $closure)
67246 {
67247 $this->sort = $closure;
67248
67249 return $this;
67250 }
67251
67252
67253
67254
67255
67256
67257
67258
67259
67260
67261 public function sortByName()
67262 {
67263 $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
67264
67265 return $this;
67266 }
67267
67268
67269
67270
67271
67272
67273
67274
67275
67276
67277 public function sortByType()
67278 {
67279 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
67280
67281 return $this;
67282 }
67283
67284
67285
67286
67287
67288
67289
67290
67291
67292
67293
67294
67295 public function sortByAccessedTime()
67296 {
67297 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
67298
67299 return $this;
67300 }
67301
67302
67303
67304
67305
67306
67307
67308
67309
67310
67311
67312
67313
67314
67315 public function sortByChangedTime()
67316 {
67317 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
67318
67319 return $this;
67320 }
67321
67322
67323
67324
67325
67326
67327
67328
67329
67330
67331
67332
67333 public function sortByModifiedTime()
67334 {
67335 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
67336
67337 return $this;
67338 }
67339
67340
67341
67342
67343
67344
67345
67346
67347
67348
67349
67350 public function filter(\Closure $closure)
67351 {
67352 $this->filters[] = $closure;
67353
67354 return $this;
67355 }
67356
67357
67358
67359
67360
67361
67362 public function followLinks()
67363 {
67364 $this->followLinks = true;
67365
67366 return $this;
67367 }
67368
67369
67370
67371
67372
67373
67374
67375
67376
67377
67378 public function ignoreUnreadableDirs($ignore = true)
67379 {
67380 $this->ignoreUnreadableDirs = (bool) $ignore;
67381
67382 return $this;
67383 }
67384
67385
67386
67387
67388
67389
67390
67391
67392
67393
67394 public function in($dirs)
67395 {
67396 $resolvedDirs = array();
67397
67398 foreach ((array) $dirs as $dir) {
67399 if (is_dir($dir)) {
67400 $resolvedDirs[] = $dir;
67401 } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
67402 $resolvedDirs = array_merge($resolvedDirs, $glob);
67403 } else {
67404 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
67405 }
67406 }
67407
67408 $this->dirs = array_merge($this->dirs, $resolvedDirs);
67409
67410 return $this;
67411 }
67412
67413
67414
67415
67416
67417
67418
67419
67420
67421
67422 public function getIterator()
67423 {
67424 if (0 === count($this->dirs) && 0 === count($this->iterators)) {
67425 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
67426 }
67427
67428 if (1 === count($this->dirs) && 0 === count($this->iterators)) {
67429 return $this->searchInDirectory($this->dirs[0]);
67430 }
67431
67432 $iterator = new \AppendIterator();
67433 foreach ($this->dirs as $dir) {
67434 $iterator->append($this->searchInDirectory($dir));
67435 }
67436
67437 foreach ($this->iterators as $it) {
67438 $iterator->append($it);
67439 }
67440
67441 return $iterator;
67442 }
67443
67444
67445
67446
67447
67448
67449
67450
67451
67452
67453
67454
67455 public function append($iterator)
67456 {
67457 if ($iterator instanceof \IteratorAggregate) {
67458 $this->iterators[] = $iterator->getIterator();
67459 } elseif ($iterator instanceof \Iterator) {
67460 $this->iterators[] = $iterator;
67461 } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
67462 $it = new \ArrayIterator();
67463 foreach ($iterator as $file) {
67464 $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
67465 }
67466 $this->iterators[] = $it;
67467 } else {
67468 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
67469 }
67470
67471 return $this;
67472 }
67473
67474
67475
67476
67477
67478
67479 public function count()
67480 {
67481 return iterator_count($this->getIterator());
67482 }
67483
67484
67485
67486
67487 private function sortAdapters()
67488 {
67489 uasort($this->adapters, function (array $a, array $b) {
67490 if ($a['selected'] || $b['selected']) {
67491 return $a['selected'] ? -1 : 1;
67492 }
67493
67494 return $a['priority'] > $b['priority'] ? -1 : 1;
67495 });
67496
67497 return $this;
67498 }
67499
67500
67501
67502
67503
67504
67505 private function searchInDirectory($dir)
67506 {
67507 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
67508 $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
67509 }
67510
67511 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
67512 $this->notPaths[] = '#(^|/)\..+(/|$)#';
67513 }
67514
67515 if ($this->adapters) {
67516 foreach ($this->adapters as $adapter) {
67517 if ($adapter['adapter']->isSupported()) {
67518 try {
67519 return $this
67520 ->buildAdapter($adapter['adapter'])
67521 ->searchInDirectory($dir);
67522 } catch (ExceptionInterface $e) {
67523 }
67524 }
67525 }
67526 }
67527
67528 $minDepth = 0;
67529 $maxDepth = PHP_INT_MAX;
67530
67531 foreach ($this->depths as $comparator) {
67532 switch ($comparator->getOperator()) {
67533 case '>':
67534 $minDepth = $comparator->getTarget() + 1;
67535 break;
67536 case '>=':
67537 $minDepth = $comparator->getTarget();
67538 break;
67539 case '<':
67540 $maxDepth = $comparator->getTarget() - 1;
67541 break;
67542 case '<=':
67543 $maxDepth = $comparator->getTarget();
67544 break;
67545 default:
67546 $minDepth = $maxDepth = $comparator->getTarget();
67547 }
67548 }
67549
67550 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
67551
67552 if ($this->followLinks) {
67553 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
67554 }
67555
67556 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
67557
67558 if ($this->exclude) {
67559 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
67560 }
67561
67562 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
67563
67564 if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
67565 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
67566 }
67567
67568 if ($this->mode) {
67569 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
67570 }
67571
67572 if ($this->names || $this->notNames) {
67573 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
67574 }
67575
67576 if ($this->contains || $this->notContains) {
67577 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
67578 }
67579
67580 if ($this->sizes) {
67581 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
67582 }
67583
67584 if ($this->dates) {
67585 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
67586 }
67587
67588 if ($this->filters) {
67589 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
67590 }
67591
67592 if ($this->paths || $this->notPaths) {
67593 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
67594 }
67595
67596 if ($this->sort) {
67597 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
67598 $iterator = $iteratorAggregate->getIterator();
67599 }
67600
67601 return $iterator;
67602 }
67603
67604
67605
67606
67607 private function buildAdapter(AdapterInterface $adapter)
67608 {
67609 return $adapter
67610 ->setFollowLinks($this->followLinks)
67611 ->setDepths($this->depths)
67612 ->setMode($this->mode)
67613 ->setExclude($this->exclude)
67614 ->setNames($this->names)
67615 ->setNotNames($this->notNames)
67616 ->setContains($this->contains)
67617 ->setNotContains($this->notContains)
67618 ->setSizes($this->sizes)
67619 ->setDates($this->dates)
67620 ->setFilters($this->filters)
67621 ->setSort($this->sort)
67622 ->setPath($this->paths)
67623 ->setNotPath($this->notPaths)
67624 ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
67625 }
67626
67627
67628
67629
67630 private function resetAdapterSelection()
67631 {
67632 $this->adapters = array_map(function (array $properties) {
67633 $properties['selected'] = false;
67634
67635 return $properties;
67636 }, $this->adapters);
67637 }
67638
67639 private function initDefaultAdapters()
67640 {
67641 if (null === $this->adapters) {
67642 $this->adapters = array();
67643 $this
67644 ->addAdapter(new GnuFindAdapter())
67645 ->addAdapter(new BsdFindAdapter())
67646 ->addAdapter(new PhpAdapter(), -50)
67647 ->setAdapter('php')
67648 ;
67649 }
67650 }
67651 }
67652 <?php
67653
67654
67655
67656
67657
67658
67659
67660
67661
67662
67663 namespace Symfony\Component\Finder;
67664
67665
67666
67667
67668
67669
67670
67671
67672
67673
67674
67675
67676
67677
67678
67679
67680
67681
67682
67683
67684
67685
67686
67687 class Glob
67688 {
67689
67690
67691
67692
67693
67694
67695
67696
67697
67698
67699 public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
67700 {
67701 $firstByte = true;
67702 $escaping = false;
67703 $inCurlies = 0;
67704 $regex = '';
67705 $sizeGlob = strlen($glob);
67706 for ($i = 0; $i < $sizeGlob; ++$i) {
67707 $car = $glob[$i];
67708 if ($firstByte) {
67709 if ($strictLeadingDot && '.' !== $car) {
67710 $regex .= '(?=[^\.])';
67711 }
67712
67713 $firstByte = false;
67714 }
67715
67716 if ('/' === $car) {
67717 $firstByte = true;
67718 }
67719
67720 if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
67721 $regex .= "\\$car";
67722 } elseif ('*' === $car) {
67723 $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
67724 } elseif ('?' === $car) {
67725 $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
67726 } elseif ('{' === $car) {
67727 $regex .= $escaping ? '\\{' : '(';
67728 if (!$escaping) {
67729 ++$inCurlies;
67730 }
67731 } elseif ('}' === $car && $inCurlies) {
67732 $regex .= $escaping ? '}' : ')';
67733 if (!$escaping) {
67734 --$inCurlies;
67735 }
67736 } elseif (',' === $car && $inCurlies) {
67737 $regex .= $escaping ? ',' : '|';
67738 } elseif ('\\' === $car) {
67739 if ($escaping) {
67740 $regex .= '\\\\';
67741 $escaping = false;
67742 } else {
67743 $escaping = true;
67744 }
67745
67746 continue;
67747 } else {
67748 $regex .= $car;
67749 }
67750 $escaping = false;
67751 }
67752
67753 return $delimiter.'^'.$regex.'$'.$delimiter;
67754 }
67755 }
67756 <?php
67757
67758
67759
67760
67761
67762
67763
67764
67765
67766
67767 namespace Symfony\Component\Finder\Iterator;
67768
67769
67770
67771
67772
67773
67774
67775
67776
67777 class CustomFilterIterator extends FilterIterator
67778 {
67779 private $filters = array();
67780
67781
67782
67783
67784
67785
67786
67787 public function __construct(\Iterator $iterator, array $filters)
67788 {
67789 foreach ($filters as $filter) {
67790 if (!is_callable($filter)) {
67791 throw new \InvalidArgumentException('Invalid PHP callback.');
67792 }
67793 }
67794 $this->filters = $filters;
67795
67796 parent::__construct($iterator);
67797 }
67798
67799
67800
67801
67802
67803
67804 public function accept()
67805 {
67806 $fileinfo = $this->current();
67807
67808 foreach ($this->filters as $filter) {
67809 if (false === call_user_func($filter, $fileinfo)) {
67810 return false;
67811 }
67812 }
67813
67814 return true;
67815 }
67816 }
67817 <?php
67818
67819
67820
67821
67822
67823
67824
67825
67826
67827
67828 namespace Symfony\Component\Finder\Iterator;
67829
67830 use Symfony\Component\Finder\Comparator\DateComparator;
67831
67832
67833
67834
67835
67836
67837 class DateRangeFilterIterator extends FilterIterator
67838 {
67839 private $comparators = array();
67840
67841
67842
67843
67844
67845 public function __construct(\Iterator $iterator, array $comparators)
67846 {
67847 $this->comparators = $comparators;
67848
67849 parent::__construct($iterator);
67850 }
67851
67852
67853
67854
67855
67856
67857 public function accept()
67858 {
67859 $fileinfo = $this->current();
67860
67861 if (!file_exists($fileinfo->getPathname())) {
67862 return false;
67863 }
67864
67865 $filedate = $fileinfo->getMTime();
67866 foreach ($this->comparators as $compare) {
67867 if (!$compare->test($filedate)) {
67868 return false;
67869 }
67870 }
67871
67872 return true;
67873 }
67874 }
67875 <?php
67876
67877
67878
67879
67880
67881
67882
67883
67884
67885
67886 namespace Symfony\Component\Finder\Iterator;
67887
67888
67889
67890
67891
67892
67893 class DepthRangeFilterIterator extends FilterIterator
67894 {
67895 private $minDepth = 0;
67896
67897
67898
67899
67900
67901
67902 public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
67903 {
67904 $this->minDepth = $minDepth;
67905 $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
67906
67907 parent::__construct($iterator);
67908 }
67909
67910
67911
67912
67913
67914
67915 public function accept()
67916 {
67917 return $this->getInnerIterator()->getDepth() >= $this->minDepth;
67918 }
67919 }
67920 <?php
67921
67922
67923
67924
67925
67926
67927
67928
67929
67930
67931 namespace Symfony\Component\Finder\Iterator;
67932
67933
67934
67935
67936
67937
67938 class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
67939 {
67940 private $iterator;
67941 private $isRecursive;
67942 private $excludedDirs = array();
67943 private $excludedPattern;
67944
67945
67946
67947
67948
67949 public function __construct(\Iterator $iterator, array $directories)
67950 {
67951 $this->iterator = $iterator;
67952 $this->isRecursive = $iterator instanceof \RecursiveIterator;
67953 $patterns = array();
67954 foreach ($directories as $directory) {
67955 $directory = rtrim($directory, '/');
67956 if (!$this->isRecursive || false !== strpos($directory, '/')) {
67957 $patterns[] = preg_quote($directory, '#');
67958 } else {
67959 $this->excludedDirs[$directory] = true;
67960 }
67961 }
67962 if ($patterns) {
67963 $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
67964 }
67965
67966 parent::__construct($iterator);
67967 }
67968
67969
67970
67971
67972
67973
67974 public function accept()
67975 {
67976 if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
67977 return false;
67978 }
67979
67980 if ($this->excludedPattern) {
67981 $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
67982 $path = str_replace('\\', '/', $path);
67983
67984 return !preg_match($this->excludedPattern, $path);
67985 }
67986
67987 return true;
67988 }
67989
67990 public function hasChildren()
67991 {
67992 return $this->isRecursive && $this->iterator->hasChildren();
67993 }
67994
67995 public function getChildren()
67996 {
67997 $children = new self($this->iterator->getChildren(), array());
67998 $children->excludedDirs = $this->excludedDirs;
67999 $children->excludedPattern = $this->excludedPattern;
68000
68001 return $children;
68002 }
68003 }
68004 <?php
68005
68006
68007
68008
68009
68010
68011
68012
68013
68014
68015 namespace Symfony\Component\Finder\Iterator;
68016
68017 @trigger_error('The '.__NAMESPACE__.'\FilePathsIterator class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68018
68019 use Symfony\Component\Finder\SplFileInfo;
68020
68021
68022
68023
68024
68025
68026
68027
68028 class FilePathsIterator extends \ArrayIterator
68029 {
68030
68031
68032
68033 private $baseDir;
68034
68035
68036
68037
68038 private $baseDirLength;
68039
68040
68041
68042
68043 private $subPath;
68044
68045
68046
68047
68048 private $subPathname;
68049
68050
68051
68052
68053 private $current;
68054
68055
68056
68057
68058
68059 public function __construct(array $paths, $baseDir)
68060 {
68061 $this->baseDir = $baseDir;
68062 $this->baseDirLength = strlen($baseDir);
68063
68064 parent::__construct($paths);
68065 }
68066
68067
68068
68069
68070
68071
68072
68073 public function __call($name, array $arguments)
68074 {
68075 return call_user_func_array(array($this->current(), $name), $arguments);
68076 }
68077
68078
68079
68080
68081
68082
68083 public function current()
68084 {
68085 return $this->current;
68086 }
68087
68088
68089
68090
68091 public function key()
68092 {
68093 return $this->current->getPathname();
68094 }
68095
68096 public function next()
68097 {
68098 parent::next();
68099 $this->buildProperties();
68100 }
68101
68102 public function rewind()
68103 {
68104 parent::rewind();
68105 $this->buildProperties();
68106 }
68107
68108
68109
68110
68111 public function getSubPath()
68112 {
68113 return $this->subPath;
68114 }
68115
68116
68117
68118
68119 public function getSubPathname()
68120 {
68121 return $this->subPathname;
68122 }
68123
68124 private function buildProperties()
68125 {
68126 $absolutePath = parent::current();
68127
68128 if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
68129 $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
68130 $dir = dirname($this->subPathname);
68131 $this->subPath = '.' === $dir ? '' : $dir;
68132 } else {
68133 $this->subPath = $this->subPathname = '';
68134 }
68135
68136 $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
68137 }
68138 }
68139 <?php
68140
68141
68142
68143
68144
68145
68146
68147
68148
68149
68150 namespace Symfony\Component\Finder\Iterator;
68151
68152
68153
68154
68155
68156
68157 class FileTypeFilterIterator extends FilterIterator
68158 {
68159 const ONLY_FILES = 1;
68160 const ONLY_DIRECTORIES = 2;
68161
68162 private $mode;
68163
68164
68165
68166
68167
68168 public function __construct(\Iterator $iterator, $mode)
68169 {
68170 $this->mode = $mode;
68171
68172 parent::__construct($iterator);
68173 }
68174
68175
68176
68177
68178
68179
68180 public function accept()
68181 {
68182 $fileinfo = $this->current();
68183 if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
68184 return false;
68185 } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
68186 return false;
68187 }
68188
68189 return true;
68190 }
68191 }
68192 <?php
68193
68194
68195
68196
68197
68198
68199
68200
68201
68202
68203 namespace Symfony\Component\Finder\Iterator;
68204
68205
68206
68207
68208
68209
68210
68211 class FilecontentFilterIterator extends MultiplePcreFilterIterator
68212 {
68213
68214
68215
68216
68217
68218 public function accept()
68219 {
68220 if (!$this->matchRegexps && !$this->noMatchRegexps) {
68221 return true;
68222 }
68223
68224 $fileinfo = $this->current();
68225
68226 if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
68227 return false;
68228 }
68229
68230 $content = $fileinfo->getContents();
68231 if (!$content) {
68232 return false;
68233 }
68234
68235 return $this->isAccepted($content);
68236 }
68237
68238
68239
68240
68241
68242
68243
68244
68245 protected function toRegex($str)
68246 {
68247 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
68248 }
68249 }
68250 <?php
68251
68252
68253
68254
68255
68256
68257
68258
68259
68260
68261 namespace Symfony\Component\Finder\Iterator;
68262
68263 use Symfony\Component\Finder\Glob;
68264
68265
68266
68267
68268
68269
68270 class FilenameFilterIterator extends MultiplePcreFilterIterator
68271 {
68272
68273
68274
68275
68276
68277 public function accept()
68278 {
68279 return $this->isAccepted($this->current()->getFilename());
68280 }
68281
68282
68283
68284
68285
68286
68287
68288
68289
68290
68291
68292 protected function toRegex($str)
68293 {
68294 return $this->isRegex($str) ? $str : Glob::toRegex($str);
68295 }
68296 }
68297 <?php
68298
68299
68300
68301
68302
68303
68304
68305
68306
68307
68308 namespace Symfony\Component\Finder\Iterator;
68309
68310
68311
68312
68313
68314
68315
68316
68317
68318 abstract class FilterIterator extends \FilterIterator
68319 {
68320
68321
68322
68323
68324
68325
68326 public function rewind()
68327 {
68328 if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
68329 parent::rewind();
68330
68331 return;
68332 }
68333
68334 $iterator = $this;
68335 while ($iterator instanceof \OuterIterator) {
68336 $innerIterator = $iterator->getInnerIterator();
68337
68338 if ($innerIterator instanceof RecursiveDirectoryIterator) {
68339
68340  if ($innerIterator->isRewindable()) {
68341 $innerIterator->next();
68342 $innerIterator->rewind();
68343 }
68344 } elseif ($innerIterator instanceof \FilesystemIterator) {
68345 $innerIterator->next();
68346 $innerIterator->rewind();
68347 }
68348
68349 $iterator = $innerIterator;
68350 }
68351
68352 parent::rewind();
68353 }
68354 }
68355 <?php
68356
68357
68358
68359
68360
68361
68362
68363
68364
68365
68366 namespace Symfony\Component\Finder\Iterator;
68367
68368
68369
68370
68371
68372
68373 abstract class MultiplePcreFilterIterator extends FilterIterator
68374 {
68375 protected $matchRegexps = array();
68376 protected $noMatchRegexps = array();
68377
68378
68379
68380
68381
68382
68383 public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
68384 {
68385 foreach ($matchPatterns as $pattern) {
68386 $this->matchRegexps[] = $this->toRegex($pattern);
68387 }
68388
68389 foreach ($noMatchPatterns as $pattern) {
68390 $this->noMatchRegexps[] = $this->toRegex($pattern);
68391 }
68392
68393 parent::__construct($iterator);
68394 }
68395
68396
68397
68398
68399
68400
68401
68402
68403
68404
68405
68406
68407 protected function isAccepted($string)
68408 {
68409
68410  foreach ($this->noMatchRegexps as $regex) {
68411 if (preg_match($regex, $string)) {
68412 return false;
68413 }
68414 }
68415
68416
68417  if ($this->matchRegexps) {
68418 foreach ($this->matchRegexps as $regex) {
68419 if (preg_match($regex, $string)) {
68420 return true;
68421 }
68422 }
68423
68424 return false;
68425 }
68426
68427
68428  return true;
68429 }
68430
68431
68432
68433
68434
68435
68436
68437
68438 protected function isRegex($str)
68439 {
68440 if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
68441 $start = substr($m[1], 0, 1);
68442 $end = substr($m[1], -1);
68443
68444 if ($start === $end) {
68445 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
68446 }
68447
68448 foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
68449 if ($start === $delimiters[0] && $end === $delimiters[1]) {
68450 return true;
68451 }
68452 }
68453 }
68454
68455 return false;
68456 }
68457
68458
68459
68460
68461
68462
68463
68464
68465 abstract protected function toRegex($str);
68466 }
68467 <?php
68468
68469
68470
68471
68472
68473
68474
68475
68476
68477
68478 namespace Symfony\Component\Finder\Iterator;
68479
68480
68481
68482
68483
68484
68485
68486 class PathFilterIterator extends MultiplePcreFilterIterator
68487 {
68488
68489
68490
68491
68492
68493 public function accept()
68494 {
68495 $filename = $this->current()->getRelativePathname();
68496
68497 if ('\\' === DIRECTORY_SEPARATOR) {
68498 $filename = str_replace('\\', '/', $filename);
68499 }
68500
68501 return $this->isAccepted($filename);
68502 }
68503
68504
68505
68506
68507
68508
68509
68510
68511
68512
68513
68514
68515
68516
68517
68518 protected function toRegex($str)
68519 {
68520 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
68521 }
68522 }
68523 <?php
68524
68525
68526
68527
68528
68529
68530
68531
68532
68533
68534 namespace Symfony\Component\Finder\Iterator;
68535
68536 use Symfony\Component\Finder\Exception\AccessDeniedException;
68537 use Symfony\Component\Finder\SplFileInfo;
68538
68539
68540
68541
68542
68543
68544 class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
68545 {
68546
68547
68548
68549 private $ignoreUnreadableDirs;
68550
68551
68552
68553
68554 private $rewindable;
68555
68556
68557  private $rootPath;
68558 private $subPath;
68559 private $directorySeparator = '/';
68560
68561
68562
68563
68564
68565
68566
68567
68568 public function __construct($path, $flags, $ignoreUnreadableDirs = false)
68569 {
68570 if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
68571 throw new \RuntimeException('This iterator only support returning current as fileinfo.');
68572 }
68573
68574 parent::__construct($path, $flags);
68575 $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
68576 $this->rootPath = (string) $path;
68577 if ('/' !== DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
68578 $this->directorySeparator = DIRECTORY_SEPARATOR;
68579 }
68580 }
68581
68582
68583
68584
68585
68586
68587 public function current()
68588 {
68589
68590
68591 if (null === $subPathname = $this->subPath) {
68592 $subPathname = $this->subPath = (string) $this->getSubPath();
68593 }
68594 if ('' !== $subPathname) {
68595 $subPathname .= $this->directorySeparator;
68596 }
68597 $subPathname .= $this->getFilename();
68598
68599 return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
68600 }
68601
68602
68603
68604
68605
68606
68607 public function getChildren()
68608 {
68609 try {
68610 $children = parent::getChildren();
68611
68612 if ($children instanceof self) {
68613
68614  $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
68615
68616
68617  $children->rewindable = &$this->rewindable;
68618 $children->rootPath = $this->rootPath;
68619 }
68620
68621 return $children;
68622 } catch (\UnexpectedValueException $e) {
68623 if ($this->ignoreUnreadableDirs) {
68624
68625  return new \RecursiveArrayIterator(array());
68626 } else {
68627 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
68628 }
68629 }
68630 }
68631
68632
68633
68634
68635 public function rewind()
68636 {
68637 if (false === $this->isRewindable()) {
68638 return;
68639 }
68640
68641
68642  if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
68643 parent::next();
68644 }
68645
68646 parent::rewind();
68647 }
68648
68649
68650
68651
68652
68653
68654 public function isRewindable()
68655 {
68656 if (null !== $this->rewindable) {
68657 return $this->rewindable;
68658 }
68659
68660
68661  if ('' === $this->getPath()) {
68662 return $this->rewindable = false;
68663 }
68664
68665 if (false !== $stream = @opendir($this->getPath())) {
68666 $infos = stream_get_meta_data($stream);
68667 closedir($stream);
68668
68669 if ($infos['seekable']) {
68670 return $this->rewindable = true;
68671 }
68672 }
68673
68674 return $this->rewindable = false;
68675 }
68676 }
68677 <?php
68678
68679
68680
68681
68682
68683
68684
68685
68686
68687
68688 namespace Symfony\Component\Finder\Iterator;
68689
68690 use Symfony\Component\Finder\Comparator\NumberComparator;
68691
68692
68693
68694
68695
68696
68697 class SizeRangeFilterIterator extends FilterIterator
68698 {
68699 private $comparators = array();
68700
68701
68702
68703
68704
68705 public function __construct(\Iterator $iterator, array $comparators)
68706 {
68707 $this->comparators = $comparators;
68708
68709 parent::__construct($iterator);
68710 }
68711
68712
68713
68714
68715
68716
68717 public function accept()
68718 {
68719 $fileinfo = $this->current();
68720 if (!$fileinfo->isFile()) {
68721 return true;
68722 }
68723
68724 $filesize = $fileinfo->getSize();
68725 foreach ($this->comparators as $compare) {
68726 if (!$compare->test($filesize)) {
68727 return false;
68728 }
68729 }
68730
68731 return true;
68732 }
68733 }
68734 <?php
68735
68736
68737
68738
68739
68740
68741
68742
68743
68744
68745 namespace Symfony\Component\Finder\Iterator;
68746
68747
68748
68749
68750
68751
68752 class SortableIterator implements \IteratorAggregate
68753 {
68754 const SORT_BY_NAME = 1;
68755 const SORT_BY_TYPE = 2;
68756 const SORT_BY_ACCESSED_TIME = 3;
68757 const SORT_BY_CHANGED_TIME = 4;
68758 const SORT_BY_MODIFIED_TIME = 5;
68759
68760 private $iterator;
68761 private $sort;
68762
68763
68764
68765
68766
68767
68768
68769 public function __construct(\Traversable $iterator, $sort)
68770 {
68771 $this->iterator = $iterator;
68772
68773 if (self::SORT_BY_NAME === $sort) {
68774 $this->sort = function ($a, $b) {
68775 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
68776 };
68777 } elseif (self::SORT_BY_TYPE === $sort) {
68778 $this->sort = function ($a, $b) {
68779 if ($a->isDir() && $b->isFile()) {
68780 return -1;
68781 } elseif ($a->isFile() && $b->isDir()) {
68782 return 1;
68783 }
68784
68785 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
68786 };
68787 } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
68788 $this->sort = function ($a, $b) {
68789 return $a->getATime() - $b->getATime();
68790 };
68791 } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
68792 $this->sort = function ($a, $b) {
68793 return $a->getCTime() - $b->getCTime();
68794 };
68795 } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
68796 $this->sort = function ($a, $b) {
68797 return $a->getMTime() - $b->getMTime();
68798 };
68799 } elseif (is_callable($sort)) {
68800 $this->sort = $sort;
68801 } else {
68802 throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
68803 }
68804 }
68805
68806 public function getIterator()
68807 {
68808 $array = iterator_to_array($this->iterator, true);
68809 uasort($array, $this->sort);
68810
68811 return new \ArrayIterator($array);
68812 }
68813 }
68814 Copyright (c) 2004-2017 Fabien Potencier
68815
68816 Permission is hereby granted, free of charge, to any person obtaining a copy
68817 of this software and associated documentation files (the "Software"), to deal
68818 in the Software without restriction, including without limitation the rights
68819 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
68820 copies of the Software, and to permit persons to whom the Software is furnished
68821 to do so, subject to the following conditions:
68822
68823 The above copyright notice and this permission notice shall be included in all
68824 copies or substantial portions of the Software.
68825
68826 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68827 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68828 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
68829 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
68830 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68831 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68832 THE SOFTWARE.
68833 <?php
68834
68835
68836
68837
68838
68839
68840
68841
68842
68843
68844 namespace Symfony\Component\Finder\Shell;
68845
68846 @trigger_error('The '.__NAMESPACE__.'\Command class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68847
68848
68849
68850
68851
68852
68853 class Command
68854 {
68855 private $parent;
68856 private $bits = array();
68857 private $labels = array();
68858
68859
68860
68861
68862 private $errorHandler;
68863
68864 public function __construct(Command $parent = null)
68865 {
68866 $this->parent = $parent;
68867 }
68868
68869
68870
68871
68872
68873
68874 public function __toString()
68875 {
68876 return $this->join();
68877 }
68878
68879
68880
68881
68882
68883
68884 public static function create(Command $parent = null)
68885 {
68886 return new self($parent);
68887 }
68888
68889
68890
68891
68892
68893
68894
68895
68896 public static function escape($input)
68897 {
68898 return escapeshellcmd($input);
68899 }
68900
68901
68902
68903
68904
68905
68906
68907
68908 public static function quote($input)
68909 {
68910 return escapeshellarg($input);
68911 }
68912
68913
68914
68915
68916
68917
68918
68919
68920 public function add($bit)
68921 {
68922 $this->bits[] = $bit;
68923
68924 return $this;
68925 }
68926
68927
68928
68929
68930
68931
68932
68933
68934 public function top($bit)
68935 {
68936 array_unshift($this->bits, $bit);
68937
68938 foreach ($this->labels as $label => $index) {
68939 $this->labels[$label] += 1;
68940 }
68941
68942 return $this;
68943 }
68944
68945
68946
68947
68948
68949
68950
68951
68952 public function arg($arg)
68953 {
68954 $this->bits[] = self::quote($arg);
68955
68956 return $this;
68957 }
68958
68959
68960
68961
68962
68963
68964
68965
68966 public function cmd($esc)
68967 {
68968 $this->bits[] = self::escape($esc);
68969
68970 return $this;
68971 }
68972
68973
68974
68975
68976
68977
68978
68979
68980
68981
68982 public function ins($label)
68983 {
68984 if (isset($this->labels[$label])) {
68985 throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
68986 }
68987
68988 $this->bits[] = self::create($this);
68989 $this->labels[$label] = count($this->bits) - 1;
68990
68991 return $this->bits[$this->labels[$label]];
68992 }
68993
68994
68995
68996
68997
68998
68999
69000
69001
69002
69003 public function get($label)
69004 {
69005 if (!isset($this->labels[$label])) {
69006 throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
69007 }
69008
69009 return $this->bits[$this->labels[$label]];
69010 }
69011
69012
69013
69014
69015
69016
69017
69018
69019 public function end()
69020 {
69021 if (null === $this->parent) {
69022 throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
69023 }
69024
69025 return $this->parent;
69026 }
69027
69028
69029
69030
69031
69032
69033 public function length()
69034 {
69035 return count($this->bits);
69036 }
69037
69038
69039
69040
69041 public function setErrorHandler(\Closure $errorHandler)
69042 {
69043 $this->errorHandler = $errorHandler;
69044
69045 return $this;
69046 }
69047
69048
69049
69050
69051 public function getErrorHandler()
69052 {
69053 return $this->errorHandler;
69054 }
69055
69056
69057
69058
69059
69060
69061
69062
69063 public function execute()
69064 {
69065 if (null === $errorHandler = $this->errorHandler) {
69066 exec($this->join(), $output);
69067 } else {
69068 $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
69069 $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
69070
69071 if ($error = stream_get_contents($pipes[2])) {
69072 $errorHandler($error);
69073 }
69074
69075 proc_close($process);
69076 }
69077
69078 return $output ?: array();
69079 }
69080
69081
69082
69083
69084
69085
69086 public function join()
69087 {
69088 return implode(' ', array_filter(
69089 array_map(function ($bit) {
69090 return $bit instanceof Command ? $bit->join() : ($bit ?: null);
69091 }, $this->bits),
69092 function ($bit) { return null !== $bit; }
69093 ));
69094 }
69095
69096
69097
69098
69099
69100
69101
69102
69103
69104 public function addAtIndex($bit, $index)
69105 {
69106 array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit);
69107
69108 return $this;
69109 }
69110 }
69111 <?php
69112
69113
69114
69115
69116
69117
69118
69119
69120
69121
69122 namespace Symfony\Component\Finder\Shell;
69123
69124 @trigger_error('The '.__NAMESPACE__.'\Shell class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69125
69126
69127
69128
69129
69130
69131 class Shell
69132 {
69133 const TYPE_UNIX = 1;
69134 const TYPE_DARWIN = 2;
69135 const TYPE_CYGWIN = 3;
69136 const TYPE_WINDOWS = 4;
69137 const TYPE_BSD = 5;
69138
69139
69140
69141
69142 private $type;
69143
69144
69145
69146
69147
69148
69149 public function getType()
69150 {
69151 if (null === $this->type) {
69152 $this->type = $this->guessType();
69153 }
69154
69155 return $this->type;
69156 }
69157
69158
69159
69160
69161
69162
69163
69164
69165 public function testCommand($command)
69166 {
69167 if (!function_exists('exec')) {
69168 return false;
69169 }
69170
69171
69172  $testCommand = 'which ';
69173 if (self::TYPE_WINDOWS === $this->type) {
69174 $testCommand = 'where ';
69175 }
69176
69177 $command = escapeshellcmd($command);
69178
69179 exec($testCommand.$command, $output, $code);
69180
69181 return 0 === $code && count($output) > 0;
69182 }
69183
69184
69185
69186
69187
69188
69189 private function guessType()
69190 {
69191 $os = strtolower(PHP_OS);
69192
69193 if (false !== strpos($os, 'cygwin')) {
69194 return self::TYPE_CYGWIN;
69195 }
69196
69197 if (false !== strpos($os, 'darwin')) {
69198 return self::TYPE_DARWIN;
69199 }
69200
69201 if (false !== strpos($os, 'bsd')) {
69202 return self::TYPE_BSD;
69203 }
69204
69205 if (0 === strpos($os, 'win')) {
69206 return self::TYPE_WINDOWS;
69207 }
69208
69209 return self::TYPE_UNIX;
69210 }
69211 }
69212 <?php
69213
69214
69215
69216
69217
69218
69219
69220
69221
69222
69223 namespace Symfony\Component\Finder;
69224
69225
69226
69227
69228
69229
69230 class SplFileInfo extends \SplFileInfo
69231 {
69232 private $relativePath;
69233 private $relativePathname;
69234
69235
69236
69237
69238
69239
69240 public function __construct($file, $relativePath, $relativePathname)
69241 {
69242 parent::__construct($file);
69243 $this->relativePath = $relativePath;
69244 $this->relativePathname = $relativePathname;
69245 }
69246
69247
69248
69249
69250
69251
69252
69253
69254 public function getRelativePath()
69255 {
69256 return $this->relativePath;
69257 }
69258
69259
69260
69261
69262
69263
69264
69265
69266 public function getRelativePathname()
69267 {
69268 return $this->relativePathname;
69269 }
69270
69271
69272
69273
69274
69275
69276
69277
69278 public function getContents()
69279 {
69280 $level = error_reporting(0);
69281 $content = file_get_contents($this->getPathname());
69282 error_reporting($level);
69283 if (false === $content) {
69284 $error = error_get_last();
69285 throw new \RuntimeException($error['message']);
69286 }
69287
69288 return $content;
69289 }
69290 }
69291 Copyright (c) 2014-2016 Fabien Potencier
69292
69293 Permission is hereby granted, free of charge, to any person obtaining a copy
69294 of this software and associated documentation files (the "Software"), to deal
69295 in the Software without restriction, including without limitation the rights
69296 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
69297 copies of the Software, and to permit persons to whom the Software is furnished
69298 to do so, subject to the following conditions:
69299
69300 The above copyright notice and this permission notice shall be included in all
69301 copies or substantial portions of the Software.
69302
69303 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
69304 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69305 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
69306 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
69307 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
69308 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
69309 THE SOFTWARE.
69310 <?php
69311
69312
69313
69314
69315
69316
69317
69318
69319
69320
69321 namespace Symfony\Polyfill\Mbstring;
69322
69323
69324
69325
69326
69327
69328
69329
69330
69331
69332
69333
69334
69335
69336
69337
69338
69339
69340
69341
69342
69343
69344
69345
69346
69347
69348
69349
69350
69351
69352
69353
69354
69355
69356
69357
69358
69359
69360
69361
69362
69363
69364
69365
69366
69367
69368
69369
69370
69371
69372
69373
69374
69375 final class Mbstring
69376 {
69377 const MB_CASE_FOLD = PHP_INT_MAX;
69378
69379 private static $encodingList = array('ASCII', 'UTF-8');
69380 private static $language = 'neutral';
69381 private static $internalEncoding = 'UTF-8';
69382 private static $caseFold = array(
69383 array('µ','ſ',"\xCD\x85",'ς',"\xCF\x90","\xCF\x91","\xCF\x95","\xCF\x96","\xCF\xB0","\xCF\xB1","\xCF\xB5","\xE1\xBA\x9B","\xE1\xBE\xBE"),
69384 array('μ','s','ι', 'σ','β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1",'ι'),
69385 );
69386
69387 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
69388 {
69389 if (is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
69390 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
69391 } else {
69392 $fromEncoding = self::getEncoding($fromEncoding);
69393 }
69394
69395 $toEncoding = self::getEncoding($toEncoding);
69396
69397 if ('BASE64' === $fromEncoding) {
69398 $s = base64_decode($s);
69399 $fromEncoding = $toEncoding;
69400 }
69401
69402 if ('BASE64' === $toEncoding) {
69403 return base64_encode($s);
69404 }
69405
69406 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
69407 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
69408 $fromEncoding = 'Windows-1252';
69409 }
69410 if ('UTF-8' !== $fromEncoding) {
69411 $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
69412 }
69413
69414 return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
69415 }
69416
69417 if ('HTML-ENTITIES' === $fromEncoding) {
69418 $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
69419 $fromEncoding = 'UTF-8';
69420 }
69421
69422 return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
69423 }
69424
69425 public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
69426 {
69427 $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
69428
69429 $ok = true;
69430 array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
69431 if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
69432 $ok = false;
69433 }
69434 });
69435
69436 return $ok ? $fromEncoding : false;
69437 }
69438
69439 public static function mb_decode_mimeheader($s)
69440 {
69441 return iconv_mime_decode($s, 2, self::$internalEncoding);
69442 }
69443
69444 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
69445 {
69446 trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
69447 }
69448
69449 public static function mb_convert_case($s, $mode, $encoding = null)
69450 {
69451 if ('' === $s .= '') {
69452 return '';
69453 }
69454
69455 $encoding = self::getEncoding($encoding);
69456
69457 if ('UTF-8' === $encoding) {
69458 $encoding = null;
69459 if (!preg_match('//u', $s)) {
69460 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
69461 }
69462 } else {
69463 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
69464 }
69465
69466 if (MB_CASE_TITLE == $mode) {
69467 $s = preg_replace_callback('/\b\p{Ll}/u', array(__CLASS__, 'title_case_upper'), $s);
69468 $s = preg_replace_callback('/\B[\p{Lu}\p{Lt}]+/u', array(__CLASS__, 'title_case_lower'), $s);
69469 } else {
69470 if (MB_CASE_UPPER == $mode) {
69471 static $upper = null;
69472 if (null === $upper) {
69473 $upper = self::getData('upperCase');
69474 }
69475 $map = $upper;
69476 } else {
69477 if (self::MB_CASE_FOLD === $mode) {
69478 $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
69479 }
69480
69481 static $lower = null;
69482 if (null === $lower) {
69483 $lower = self::getData('lowerCase');
69484 }
69485 $map = $lower;
69486 }
69487
69488 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
69489
69490 $i = 0;
69491 $len = strlen($s);
69492
69493 while ($i < $len) {
69494 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
69495 $uchr = substr($s, $i, $ulen);
69496 $i += $ulen;
69497
69498 if (isset($map[$uchr])) {
69499 $uchr = $map[$uchr];
69500 $nlen = strlen($uchr);
69501
69502 if ($nlen == $ulen) {
69503 $nlen = $i;
69504 do {
69505 $s[--$nlen] = $uchr[--$ulen];
69506 } while ($ulen);
69507 } else {
69508 $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
69509 $len += $nlen - $ulen;
69510 $i += $nlen - $ulen;
69511 }
69512 }
69513 }
69514 }
69515
69516 if (null === $encoding) {
69517 return $s;
69518 }
69519
69520 return iconv('UTF-8', $encoding.'//IGNORE', $s);
69521 }
69522
69523 public static function mb_internal_encoding($encoding = null)
69524 {
69525 if (null === $encoding) {
69526 return self::$internalEncoding;
69527 }
69528
69529 $encoding = self::getEncoding($encoding);
69530
69531 if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
69532 self::$internalEncoding = $encoding;
69533
69534 return true;
69535 }
69536
69537 return false;
69538 }
69539
69540 public static function mb_language($lang = null)
69541 {
69542 if (null === $lang) {
69543 return self::$language;
69544 }
69545
69546 switch ($lang = strtolower($lang)) {
69547 case 'uni':
69548 case 'neutral':
69549 self::$language = $lang;
69550
69551 return true;
69552 }
69553
69554 return false;
69555 }
69556
69557 public static function mb_list_encodings()
69558 {
69559 return array('UTF-8');
69560 }
69561
69562 public static function mb_encoding_aliases($encoding)
69563 {
69564 switch (strtoupper($encoding)) {
69565 case 'UTF8':
69566 case 'UTF-8':
69567 return array('utf8');
69568 }
69569
69570 return false;
69571 }
69572
69573 public static function mb_check_encoding($var = null, $encoding = null)
69574 {
69575 if (null === $encoding) {
69576 if (null === $var) {
69577 return false;
69578 }
69579 $encoding = self::$internalEncoding;
69580 }
69581
69582 return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
69583 }
69584
69585 public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
69586 {
69587 if (null === $encodingList) {
69588 $encodingList = self::$encodingList;
69589 } else {
69590 if (!is_array($encodingList)) {
69591 $encodingList = array_map('trim', explode(',', $encodingList));
69592 }
69593 $encodingList = array_map('strtoupper', $encodingList);
69594 }
69595
69596 foreach ($encodingList as $enc) {
69597 switch ($enc) {
69598 case 'ASCII':
69599 if (!preg_match('/[\x80-\xFF]/', $str)) {
69600 return $enc;
69601 }
69602 break;
69603
69604 case 'UTF8':
69605 case 'UTF-8':
69606 if (preg_match('//u', $str)) {
69607 return 'UTF-8';
69608 }
69609 break;
69610
69611 default:
69612 if (0 === strncmp($enc, 'ISO-8859-', 9)) {
69613 return $enc;
69614 }
69615 }
69616 }
69617
69618 return false;
69619 }
69620
69621 public static function mb_detect_order($encodingList = null)
69622 {
69623 if (null === $encodingList) {
69624 return self::$encodingList;
69625 }
69626
69627 if (!is_array($encodingList)) {
69628 $encodingList = array_map('trim', explode(',', $encodingList));
69629 }
69630 $encodingList = array_map('strtoupper', $encodingList);
69631
69632 foreach ($encodingList as $enc) {
69633 switch ($enc) {
69634 default:
69635 if (strncmp($enc, 'ISO-8859-', 9)) {
69636 return false;
69637 }
69638 case 'ASCII':
69639 case 'UTF8':
69640 case 'UTF-8':
69641 }
69642 }
69643
69644 self::$encodingList = $encodingList;
69645
69646 return true;
69647 }
69648
69649 public static function mb_strlen($s, $encoding = null)
69650 {
69651 $encoding = self::getEncoding($encoding);
69652 if ('CP850' === $encoding || 'ASCII' === $encoding) {
69653 return strlen($s);
69654 }
69655
69656 return @iconv_strlen($s, $encoding);
69657 }
69658
69659 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
69660 {
69661 $encoding = self::getEncoding($encoding);
69662 if ('CP850' === $encoding || 'ASCII' === $encoding) {
69663 return strpos($haystack, $needle, $offset);
69664 }
69665
69666 if ('' === $needle .= '') {
69667 trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
69668
69669 return false;
69670 }
69671
69672 return iconv_strpos($haystack, $needle, $offset, $encoding);
69673 }
69674
69675 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
69676 {
69677 $encoding = self::getEncoding($encoding);
69678 if ('CP850' === $encoding || 'ASCII' === $encoding) {
69679 return strrpos($haystack, $needle, $offset);
69680 }
69681
69682 if ($offset != (int) $offset) {
69683 $offset = 0;
69684 } elseif ($offset = (int) $offset) {
69685 if ($offset < 0) {
69686 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
69687 $offset = 0;
69688 } else {
69689 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
69690 }
69691 }
69692
69693 $pos = iconv_strrpos($haystack, $needle, $encoding);
69694
69695 return false !== $pos ? $offset + $pos : false;
69696 }
69697
69698 public static function mb_strtolower($s, $encoding = null)
69699 {
69700 return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
69701 }
69702
69703 public static function mb_strtoupper($s, $encoding = null)
69704 {
69705 return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
69706 }
69707
69708 public static function mb_substitute_character($c = null)
69709 {
69710 if (0 === strcasecmp($c, 'none')) {
69711 return true;
69712 }
69713
69714 return null !== $c ? false : 'none';
69715 }
69716
69717 public static function mb_substr($s, $start, $length = null, $encoding = null)
69718 {
69719 $encoding = self::getEncoding($encoding);
69720 if ('CP850' === $encoding || 'ASCII' === $encoding) {
69721 return substr($s, $start, null === $length ? 2147483647 : $length);
69722 }
69723
69724 if ($start < 0) {
69725 $start = iconv_strlen($s, $encoding) + $start;
69726 if ($start < 0) {
69727 $start = 0;
69728 }
69729 }
69730
69731 if (null === $length) {
69732 $length = 2147483647;
69733 } elseif ($length < 0) {
69734 $length = iconv_strlen($s, $encoding) + $length - $start;
69735 if ($length < 0) {
69736 return '';
69737 }
69738 }
69739
69740 return iconv_substr($s, $start, $length, $encoding).'';
69741 }
69742
69743 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
69744 {
69745 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
69746 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
69747
69748 return self::mb_strpos($haystack, $needle, $offset, $encoding);
69749 }
69750
69751 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
69752 {
69753 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
69754
69755 return self::getSubpart($pos, $part, $haystack, $encoding);
69756 }
69757
69758 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
69759 {
69760 $encoding = self::getEncoding($encoding);
69761 if ('CP850' === $encoding || 'ASCII' === $encoding) {
69762 return strrchr($haystack, $needle, $part);
69763 }
69764 $needle = self::mb_substr($needle, 0, 1, $encoding);
69765 $pos = iconv_strrpos($haystack, $needle, $encoding);
69766
69767 return self::getSubpart($pos, $part, $haystack, $encoding);
69768 }
69769
69770 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
69771 {
69772 $needle = self::mb_substr($needle, 0, 1, $encoding);
69773 $pos = self::mb_strripos($haystack, $needle, $encoding);
69774
69775 return self::getSubpart($pos, $part, $haystack, $encoding);
69776 }
69777
69778 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
69779 {
69780 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
69781 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
69782
69783 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
69784 }
69785
69786 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
69787 {
69788 $pos = strpos($haystack, $needle);
69789 if (false === $pos) {
69790 return false;
69791 }
69792 if ($part) {
69793 return substr($haystack, 0, $pos);
69794 }
69795
69796 return substr($haystack, $pos);
69797 }
69798
69799 public static function mb_get_info($type = 'all')
69800 {
69801 $info = array(
69802 'internal_encoding' => self::$internalEncoding,
69803 'http_output' => 'pass',
69804 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
69805 'func_overload' => 0,
69806 'func_overload_list' => 'no overload',
69807 'mail_charset' => 'UTF-8',
69808 'mail_header_encoding' => 'BASE64',
69809 'mail_body_encoding' => 'BASE64',
69810 'illegal_chars' => 0,
69811 'encoding_translation' => 'Off',
69812 'language' => self::$language,
69813 'detect_order' => self::$encodingList,
69814 'substitute_character' => 'none',
69815 'strict_detection' => 'Off',
69816 );
69817
69818 if ('all' === $type) {
69819 return $info;
69820 }
69821 if (isset($info[$type])) {
69822 return $info[$type];
69823 }
69824
69825 return false;
69826 }
69827
69828 public static function mb_http_input($type = '')
69829 {
69830 return false;
69831 }
69832
69833 public static function mb_http_output($encoding = null)
69834 {
69835 return null !== $encoding ? 'pass' === $encoding : 'pass';
69836 }
69837
69838 public static function mb_strwidth($s, $encoding = null)
69839 {
69840 $encoding = self::getEncoding($encoding);
69841
69842 if ('UTF-8' !== $encoding) {
69843 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
69844 }
69845
69846 $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);
69847
69848 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
69849 }
69850
69851 public static function mb_substr_count($haystack, $needle, $encoding = null)
69852 {
69853 return substr_count($haystack, $needle);
69854 }
69855
69856 public static function mb_output_handler($contents, $status)
69857 {
69858 return $contents;
69859 }
69860
69861 public static function mb_chr($code, $encoding = null)
69862 {
69863 if (0x80 > $code %= 0x200000) {
69864 $s = chr($code);
69865 } elseif (0x800 > $code) {
69866 $s = chr(0xC0 | $code >> 6).chr(0x80 | $code & 0x3F);
69867 } elseif (0x10000 > $code) {
69868 $s = chr(0xE0 | $code >> 12).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
69869 } else {
69870 $s = chr(0xF0 | $code >> 18).chr(0x80 | $code >> 12 & 0x3F).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
69871 }
69872
69873 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
69874 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
69875 }
69876
69877 return $s;
69878 }
69879
69880 public static function mb_ord($s, $encoding = null)
69881 {
69882 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
69883 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
69884 }
69885
69886 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
69887 if (0xF0 <= $code) {
69888 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
69889 }
69890 if (0xE0 <= $code) {
69891 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
69892 }
69893 if (0xC0 <= $code) {
69894 return (($code - 0xC0) << 6) + $s[2] - 0x80;
69895 }
69896
69897 return $code;
69898 }
69899
69900 private static function getSubpart($pos, $part, $haystack, $encoding)
69901 {
69902 if (false === $pos) {
69903 return false;
69904 }
69905 if ($part) {
69906 return self::mb_substr($haystack, 0, $pos, $encoding);
69907 }
69908
69909 return self::mb_substr($haystack, $pos, null, $encoding);
69910 }
69911
69912 private static function html_encoding_callback($m)
69913 {
69914 $i = 1;
69915 $entities = '';
69916 $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
69917
69918 while (isset($m[$i])) {
69919 if (0x80 > $m[$i]) {
69920 $entities .= chr($m[$i++]);
69921 continue;
69922 }
69923 if (0xF0 <= $m[$i]) {
69924 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
69925 } elseif (0xE0 <= $m[$i]) {
69926 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
69927 } else {
69928 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
69929 }
69930
69931 $entities .= '&#'.$c.';';
69932 }
69933
69934 return $entities;
69935 }
69936
69937 private static function title_case_lower($s)
69938 {
69939 return self::mb_convert_case($s[0], MB_CASE_LOWER, 'UTF-8');
69940 }
69941
69942 private static function title_case_upper($s)
69943 {
69944 return self::mb_convert_case($s[0], MB_CASE_UPPER, 'UTF-8');
69945 }
69946
69947 private static function getData($file)
69948 {
69949 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
69950 return require $file;
69951 }
69952
69953 return false;
69954 }
69955
69956 private static function getEncoding($encoding)
69957 {
69958 if (null === $encoding) {
69959 return self::$internalEncoding;
69960 }
69961
69962 $encoding = strtoupper($encoding);
69963
69964 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
69965 return 'CP850';
69966 }
69967 if ('UTF8' === $encoding) {
69968 return 'UTF-8';
69969 }
69970
69971 return $encoding;
69972 }
69973 }
69974 <?php
69975
69976 static $data = array (
69977 'A' => 'a',
69978 'B' => 'b',
69979 'C' => 'c',
69980 'D' => 'd',
69981 'E' => 'e',
69982 'F' => 'f',
69983 'G' => 'g',
69984 'H' => 'h',
69985 'I' => 'i',
69986 'J' => 'j',
69987 'K' => 'k',
69988 'L' => 'l',
69989 'M' => 'm',
69990 'N' => 'n',
69991 'O' => 'o',
69992 'P' => 'p',
69993 'Q' => 'q',
69994 'R' => 'r',
69995 'S' => 's',
69996 'T' => 't',
69997 'U' => 'u',
69998 'V' => 'v',
69999 'W' => 'w',
70000 'X' => 'x',
70001 'Y' => 'y',
70002 'Z' => 'z',
70003 'À' => 'à',
70004 'Á' => 'á',
70005 'Â' => 'â',
70006 'Ã' => 'ã',
70007 'Ä' => 'ä',
70008 'Å' => 'å',
70009 'Æ' => 'æ',
70010 'Ç' => 'ç',
70011 'È' => 'è',
70012 'É' => 'é',
70013 'Ê' => 'ê',
70014 'Ë' => 'ë',
70015 'Ì' => 'ì',
70016 'Í' => 'í',
70017 'Î' => 'î',
70018 'Ï' => 'ï',
70019 'Ð' => 'ð',
70020 'Ñ' => 'ñ',
70021 'Ò' => 'ò',
70022 'Ó' => 'ó',
70023 'Ô' => 'ô',
70024 'Õ' => 'õ',
70025 'Ö' => 'ö',
70026 'Ø' => 'ø',
70027 'Ù' => 'ù',
70028 'Ú' => 'ú',
70029 'Û' => 'û',
70030 'Ü' => 'ü',
70031 'Ý' => 'ý',
70032 'Þ' => 'þ',
70033 'Ā' => 'ā',
70034 'Ă' => 'ă',
70035 'Ą' => 'ą',
70036 'Ć' => 'ć',
70037 'Ĉ' => 'ĉ',
70038 'Ċ' => 'ċ',
70039 'Č' => 'č',
70040 'Ď' => 'ď',
70041 'Đ' => 'đ',
70042 'Ē' => 'ē',
70043 'Ĕ' => 'ĕ',
70044 'Ė' => 'ė',
70045 'Ę' => 'ę',
70046 'Ě' => 'ě',
70047 'Ĝ' => 'ĝ',
70048 'Ğ' => 'ğ',
70049 'Ġ' => 'ġ',
70050 'Ģ' => 'ģ',
70051 'Ĥ' => 'ĥ',
70052 'Ħ' => 'ħ',
70053 'Ĩ' => 'ĩ',
70054 'Ī' => 'ī',
70055 'Ĭ' => 'ĭ',
70056 'Į' => 'į',
70057 'İ' => 'i',
70058 'IJ' => 'ij',
70059 'Ĵ' => 'ĵ',
70060 'Ķ' => 'ķ',
70061 'Ĺ' => 'ĺ',
70062 'Ļ' => 'ļ',
70063 'Ľ' => 'ľ',
70064 'Ŀ' => 'ŀ',
70065 'Ł' => 'ł',
70066 'Ń' => 'ń',
70067 'Ņ' => 'ņ',
70068 'Ň' => 'ň',
70069 'Ŋ' => 'ŋ',
70070 'Ō' => 'ō',
70071 'Ŏ' => 'ŏ',
70072 'Ő' => 'ő',
70073 'Œ' => 'œ',
70074 'Ŕ' => 'ŕ',
70075 'Ŗ' => 'ŗ',
70076 'Ř' => 'ř',
70077 'Ś' => 'ś',
70078 'Ŝ' => 'ŝ',
70079 'Ş' => 'ş',
70080 'Š' => 'š',
70081 'Ţ' => 'ţ',
70082 'Ť' => 'ť',
70083 'Ŧ' => 'ŧ',
70084 'Ũ' => 'ũ',
70085 'Ū' => 'ū',
70086 'Ŭ' => 'ŭ',
70087 'Ů' => 'ů',
70088 'Ű' => 'ű',
70089 'Ų' => 'ų',
70090 'Ŵ' => 'ŵ',
70091 'Ŷ' => 'ŷ',
70092 'Ÿ' => 'ÿ',
70093 'Ź' => 'ź',
70094 'Ż' => 'ż',
70095 'Ž' => 'ž',
70096 'Ɓ' => 'ɓ',
70097 'Ƃ' => 'ƃ',
70098 'Ƅ' => 'ƅ',
70099 'Ɔ' => 'ɔ',
70100 'Ƈ' => 'ƈ',
70101 'Ɖ' => 'ɖ',
70102 'Ɗ' => 'ɗ',
70103 'Ƌ' => 'ƌ',
70104 'Ǝ' => 'ǝ',
70105 'Ə' => 'ə',
70106 'Ɛ' => 'ɛ',
70107 'Ƒ' => 'ƒ',
70108 'Ɠ' => 'ɠ',
70109 'Ɣ' => 'ɣ',
70110 'Ɩ' => 'ɩ',
70111 'Ɨ' => 'ɨ',
70112 'Ƙ' => 'ƙ',
70113 'Ɯ' => 'ɯ',
70114 'Ɲ' => 'ɲ',
70115 'Ɵ' => 'ɵ',
70116 'Ơ' => 'ơ',
70117 'Ƣ' => 'ƣ',
70118 'Ƥ' => 'ƥ',
70119 'Ʀ' => 'ʀ',
70120 'Ƨ' => 'ƨ',
70121 'Ʃ' => 'ʃ',
70122 'Ƭ' => 'ƭ',
70123 'Ʈ' => 'ʈ',
70124 'Ư' => 'ư',
70125 'Ʊ' => 'ʊ',
70126 'Ʋ' => 'ʋ',
70127 'Ƴ' => 'ƴ',
70128 'Ƶ' => 'ƶ',
70129 'Ʒ' => 'ʒ',
70130 'Ƹ' => 'ƹ',
70131 'Ƽ' => 'ƽ',
70132 'DŽ' => 'dž',
70133 'Dž' => 'dž',
70134 'LJ' => 'lj',
70135 'Lj' => 'lj',
70136 'NJ' => 'nj',
70137 'Nj' => 'nj',
70138 'Ǎ' => 'ǎ',
70139 'Ǐ' => 'ǐ',
70140 'Ǒ' => 'ǒ',
70141 'Ǔ' => 'ǔ',
70142 'Ǖ' => 'ǖ',
70143 'Ǘ' => 'ǘ',
70144 'Ǚ' => 'ǚ',
70145 'Ǜ' => 'ǜ',
70146 'Ǟ' => 'ǟ',
70147 'Ǡ' => 'ǡ',
70148 'Ǣ' => 'ǣ',
70149 'Ǥ' => 'ǥ',
70150 'Ǧ' => 'ǧ',
70151 'Ǩ' => 'ǩ',
70152 'Ǫ' => 'ǫ',
70153 'Ǭ' => 'ǭ',
70154 'Ǯ' => 'ǯ',
70155 'DZ' => 'dz',
70156 'Dz' => 'dz',
70157 'Ǵ' => 'ǵ',
70158 'Ƕ' => 'ƕ',
70159 'Ƿ' => 'ƿ',
70160 'Ǹ' => 'ǹ',
70161 'Ǻ' => 'ǻ',
70162 'Ǽ' => 'ǽ',
70163 'Ǿ' => 'ǿ',
70164 'Ȁ' => 'ȁ',
70165 'Ȃ' => 'ȃ',
70166 'Ȅ' => 'ȅ',
70167 'Ȇ' => 'ȇ',
70168 'Ȉ' => 'ȉ',
70169 'Ȋ' => 'ȋ',
70170 'Ȍ' => 'ȍ',
70171 'Ȏ' => 'ȏ',
70172 'Ȑ' => 'ȑ',
70173 'Ȓ' => 'ȓ',
70174 'Ȕ' => 'ȕ',
70175 'Ȗ' => 'ȗ',
70176 'Ș' => 'ș',
70177 'Ț' => 'ț',
70178 'Ȝ' => 'ȝ',
70179 'Ȟ' => 'ȟ',
70180 'Ƞ' => 'ƞ',
70181 'Ȣ' => 'ȣ',
70182 'Ȥ' => 'ȥ',
70183 'Ȧ' => 'ȧ',
70184 'Ȩ' => 'ȩ',
70185 'Ȫ' => 'ȫ',
70186 'Ȭ' => 'ȭ',
70187 'Ȯ' => 'ȯ',
70188 'Ȱ' => 'ȱ',
70189 'Ȳ' => 'ȳ',
70190 'Ⱥ' => 'ⱥ',
70191 'Ȼ' => 'ȼ',
70192 'Ƚ' => 'ƚ',
70193 'Ⱦ' => 'ⱦ',
70194 'Ɂ' => 'ɂ',
70195 'Ƀ' => 'ƀ',
70196 'Ʉ' => 'ʉ',
70197 'Ʌ' => 'ʌ',
70198 'Ɇ' => 'ɇ',
70199 'Ɉ' => 'ɉ',
70200 'Ɋ' => 'ɋ',
70201 'Ɍ' => 'ɍ',
70202 'Ɏ' => 'ɏ',
70203 'Ͱ' => 'ͱ',
70204 'Ͳ' => 'ͳ',
70205 'Ͷ' => 'ͷ',
70206 'Ϳ' => 'ϳ',
70207 'Ά' => 'ά',
70208 'Έ' => 'έ',
70209 'Ή' => 'ή',
70210 'Ί' => 'ί',
70211 'Ό' => 'ό',
70212 'Ύ' => 'ύ',
70213 'Ώ' => 'ώ',
70214 'Α' => 'α',
70215 'Β' => 'β',
70216 'Γ' => 'γ',
70217 'Δ' => 'δ',
70218 'Ε' => 'ε',
70219 'Ζ' => 'ζ',
70220 'Η' => 'η',
70221 'Θ' => 'θ',
70222 'Ι' => 'ι',
70223 'Κ' => 'κ',
70224 'Λ' => 'λ',
70225 'Μ' => 'μ',
70226 'Ν' => 'ν',
70227 'Ξ' => 'ξ',
70228 'Ο' => 'ο',
70229 'Π' => 'π',
70230 'Ρ' => 'ρ',
70231 'Σ' => 'σ',
70232 'Τ' => 'τ',
70233 'Υ' => 'υ',
70234 'Φ' => 'φ',
70235 'Χ' => 'χ',
70236 'Ψ' => 'ψ',
70237 'Ω' => 'ω',
70238 'Ϊ' => 'ϊ',
70239 'Ϋ' => 'ϋ',
70240 'Ϗ' => 'ϗ',
70241 'Ϙ' => 'ϙ',
70242 'Ϛ' => 'ϛ',
70243 'Ϝ' => 'ϝ',
70244 'Ϟ' => 'ϟ',
70245 'Ϡ' => 'ϡ',
70246 'Ϣ' => 'ϣ',
70247 'Ϥ' => 'ϥ',
70248 'Ϧ' => 'ϧ',
70249 'Ϩ' => 'ϩ',
70250 'Ϫ' => 'ϫ',
70251 'Ϭ' => 'ϭ',
70252 'Ϯ' => 'ϯ',
70253 'ϴ' => 'θ',
70254 'Ϸ' => 'ϸ',
70255 'Ϲ' => 'ϲ',
70256 'Ϻ' => 'ϻ',
70257 'Ͻ' => 'ͻ',
70258 'Ͼ' => 'ͼ',
70259 'Ͽ' => 'ͽ',
70260 'Ѐ' => 'ѐ',
70261 'Ё' => 'ё',
70262 'Ђ' => 'ђ',
70263 'Ѓ' => 'ѓ',
70264 'Є' => 'є',
70265 'Ѕ' => 'ѕ',
70266 'І' => 'і',
70267 'Ї' => 'ї',
70268 'Ј' => 'ј',
70269 'Љ' => 'љ',
70270 'Њ' => 'њ',
70271 'Ћ' => 'ћ',
70272 'Ќ' => 'ќ',
70273 'Ѝ' => 'ѝ',
70274 'Ў' => 'ў',
70275 'Џ' => 'џ',
70276 'А' => 'а',
70277 'Б' => 'б',
70278 'В' => 'в',
70279 'Г' => 'г',
70280 'Д' => 'д',
70281 'Е' => 'е',
70282 'Ж' => 'ж',
70283 'З' => 'з',
70284 'И' => 'и',
70285 'Й' => 'й',
70286 'К' => 'к',
70287 'Л' => 'л',
70288 'М' => 'м',
70289 'Н' => 'н',
70290 'О' => 'о',
70291 'П' => 'п',
70292 'Р' => 'р',
70293 'С' => 'с',
70294 'Т' => 'т',
70295 'У' => 'у',
70296 'Ф' => 'ф',
70297 'Х' => 'х',
70298 'Ц' => 'ц',
70299 'Ч' => 'ч',
70300 'Ш' => 'ш',
70301 'Щ' => 'щ',
70302 'Ъ' => 'ъ',
70303 'Ы' => 'ы',
70304 'Ь' => 'ь',
70305 'Э' => 'э',
70306 'Ю' => 'ю',
70307 'Я' => 'я',
70308 'Ѡ' => 'ѡ',
70309 'Ѣ' => 'ѣ',
70310 'Ѥ' => 'ѥ',
70311 'Ѧ' => 'ѧ',
70312 'Ѩ' => 'ѩ',
70313 'Ѫ' => 'ѫ',
70314 'Ѭ' => 'ѭ',
70315 'Ѯ' => 'ѯ',
70316 'Ѱ' => 'ѱ',
70317 'Ѳ' => 'ѳ',
70318 'Ѵ' => 'ѵ',
70319 'Ѷ' => 'ѷ',
70320 'Ѹ' => 'ѹ',
70321 'Ѻ' => 'ѻ',
70322 'Ѽ' => 'ѽ',
70323 'Ѿ' => 'ѿ',
70324 'Ҁ' => 'ҁ',
70325 'Ҋ' => 'ҋ',
70326 'Ҍ' => 'ҍ',
70327 'Ҏ' => 'ҏ',
70328 'Ґ' => 'ґ',
70329 'Ғ' => 'ғ',
70330 'Ҕ' => 'ҕ',
70331 'Җ' => 'җ',
70332 'Ҙ' => 'ҙ',
70333 'Қ' => 'қ',
70334 'Ҝ' => 'ҝ',
70335 'Ҟ' => 'ҟ',
70336 'Ҡ' => 'ҡ',
70337 'Ң' => 'ң',
70338 'Ҥ' => 'ҥ',
70339 'Ҧ' => 'ҧ',
70340 'Ҩ' => 'ҩ',
70341 'Ҫ' => 'ҫ',
70342 'Ҭ' => 'ҭ',
70343 'Ү' => 'ү',
70344 'Ұ' => 'ұ',
70345 'Ҳ' => 'ҳ',
70346 'Ҵ' => 'ҵ',
70347 'Ҷ' => 'ҷ',
70348 'Ҹ' => 'ҹ',
70349 'Һ' => 'һ',
70350 'Ҽ' => 'ҽ',
70351 'Ҿ' => 'ҿ',
70352 'Ӏ' => 'ӏ',
70353 'Ӂ' => 'ӂ',
70354 'Ӄ' => 'ӄ',
70355 'Ӆ' => 'ӆ',
70356 'Ӈ' => 'ӈ',
70357 'Ӊ' => 'ӊ',
70358 'Ӌ' => 'ӌ',
70359 'Ӎ' => 'ӎ',
70360 'Ӑ' => 'ӑ',
70361 'Ӓ' => 'ӓ',
70362 'Ӕ' => 'ӕ',
70363 'Ӗ' => 'ӗ',
70364 'Ә' => 'ә',
70365 'Ӛ' => 'ӛ',
70366 'Ӝ' => 'ӝ',
70367 'Ӟ' => 'ӟ',
70368 'Ӡ' => 'ӡ',
70369 'Ӣ' => 'ӣ',
70370 'Ӥ' => 'ӥ',
70371 'Ӧ' => 'ӧ',
70372 'Ө' => 'ө',
70373 'Ӫ' => 'ӫ',
70374 'Ӭ' => 'ӭ',
70375 'Ӯ' => 'ӯ',
70376 'Ӱ' => 'ӱ',
70377 'Ӳ' => 'ӳ',
70378 'Ӵ' => 'ӵ',
70379 'Ӷ' => 'ӷ',
70380 'Ӹ' => 'ӹ',
70381 'Ӻ' => 'ӻ',
70382 'Ӽ' => 'ӽ',
70383 'Ӿ' => 'ӿ',
70384 'Ԁ' => 'ԁ',
70385 'Ԃ' => 'ԃ',
70386 'Ԅ' => 'ԅ',
70387 'Ԇ' => 'ԇ',
70388 'Ԉ' => 'ԉ',
70389 'Ԋ' => 'ԋ',
70390 'Ԍ' => 'ԍ',
70391 'Ԏ' => 'ԏ',
70392 'Ԑ' => 'ԑ',
70393 'Ԓ' => 'ԓ',
70394 'Ԕ' => 'ԕ',
70395 'Ԗ' => 'ԗ',
70396 'Ԙ' => 'ԙ',
70397 'Ԛ' => 'ԛ',
70398 'Ԝ' => 'ԝ',
70399 'Ԟ' => 'ԟ',
70400 'Ԡ' => 'ԡ',
70401 'Ԣ' => 'ԣ',
70402 'Ԥ' => 'ԥ',
70403 'Ԧ' => 'ԧ',
70404 'Ԩ' => 'ԩ',
70405 'Ԫ' => 'ԫ',
70406 'Ԭ' => 'ԭ',
70407 'Ԯ' => 'ԯ',
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 'Ⴐ' => 'ⴐ',
70463 'Ⴑ' => 'ⴑ',
70464 'Ⴒ' => 'ⴒ',
70465 'Ⴓ' => 'ⴓ',
70466 'Ⴔ' => 'ⴔ',
70467 'Ⴕ' => 'ⴕ',
70468 'Ⴖ' => 'ⴖ',
70469 'Ⴗ' => 'ⴗ',
70470 'Ⴘ' => 'ⴘ',
70471 'Ⴙ' => 'ⴙ',
70472 'Ⴚ' => 'ⴚ',
70473 'Ⴛ' => 'ⴛ',
70474 'Ⴜ' => 'ⴜ',
70475 'Ⴝ' => 'ⴝ',
70476 'Ⴞ' => 'ⴞ',
70477 'Ⴟ' => 'ⴟ',
70478 'Ⴠ' => 'ⴠ',
70479 'Ⴡ' => 'ⴡ',
70480 'Ⴢ' => 'ⴢ',
70481 'Ⴣ' => 'ⴣ',
70482 'Ⴤ' => 'ⴤ',
70483 'Ⴥ' => 'ⴥ',
70484 'Ⴧ' => 'ⴧ',
70485 'Ⴭ' => 'ⴭ',
70486 'Ḁ' => 'ḁ',
70487 'Ḃ' => 'ḃ',
70488 'Ḅ' => 'ḅ',
70489 'Ḇ' => 'ḇ',
70490 'Ḉ' => 'ḉ',
70491 'Ḋ' => 'ḋ',
70492 'Ḍ' => 'ḍ',
70493 'Ḏ' => 'ḏ',
70494 'Ḑ' => 'ḑ',
70495 'Ḓ' => 'ḓ',
70496 'Ḕ' => 'ḕ',
70497 'Ḗ' => 'ḗ',
70498 'Ḙ' => 'ḙ',
70499 'Ḛ' => 'ḛ',
70500 'Ḝ' => 'ḝ',
70501 'Ḟ' => 'ḟ',
70502 'Ḡ' => 'ḡ',
70503 'Ḣ' => 'ḣ',
70504 'Ḥ' => 'ḥ',
70505 'Ḧ' => 'ḧ',
70506 'Ḩ' => 'ḩ',
70507 'Ḫ' => 'ḫ',
70508 'Ḭ' => 'ḭ',
70509 'Ḯ' => 'ḯ',
70510 'Ḱ' => 'ḱ',
70511 'Ḳ' => 'ḳ',
70512 'Ḵ' => 'ḵ',
70513 'Ḷ' => 'ḷ',
70514 'Ḹ' => 'ḹ',
70515 'Ḻ' => 'ḻ',
70516 'Ḽ' => 'ḽ',
70517 'Ḿ' => 'ḿ',
70518 'Ṁ' => 'ṁ',
70519 'Ṃ' => 'ṃ',
70520 'Ṅ' => 'ṅ',
70521 'Ṇ' => 'ṇ',
70522 'Ṉ' => 'ṉ',
70523 'Ṋ' => 'ṋ',
70524 'Ṍ' => 'ṍ',
70525 'Ṏ' => 'ṏ',
70526 'Ṑ' => 'ṑ',
70527 'Ṓ' => 'ṓ',
70528 'Ṕ' => 'ṕ',
70529 'Ṗ' => 'ṗ',
70530 'Ṙ' => 'ṙ',
70531 'Ṛ' => 'ṛ',
70532 'Ṝ' => 'ṝ',
70533 'Ṟ' => 'ṟ',
70534 'Ṡ' => 'ṡ',
70535 'Ṣ' => 'ṣ',
70536 'Ṥ' => 'ṥ',
70537 'Ṧ' => 'ṧ',
70538 'Ṩ' => 'ṩ',
70539 'Ṫ' => 'ṫ',
70540 'Ṭ' => 'ṭ',
70541 'Ṯ' => 'ṯ',
70542 'Ṱ' => 'ṱ',
70543 'Ṳ' => 'ṳ',
70544 'Ṵ' => 'ṵ',
70545 'Ṷ' => 'ṷ',
70546 'Ṹ' => 'ṹ',
70547 'Ṻ' => 'ṻ',
70548 'Ṽ' => 'ṽ',
70549 'Ṿ' => 'ṿ',
70550 'Ẁ' => 'ẁ',
70551 'Ẃ' => 'ẃ',
70552 'Ẅ' => 'ẅ',
70553 'Ẇ' => 'ẇ',
70554 'Ẉ' => 'ẉ',
70555 'Ẋ' => 'ẋ',
70556 'Ẍ' => 'ẍ',
70557 'Ẏ' => 'ẏ',
70558 'Ẑ' => 'ẑ',
70559 'Ẓ' => 'ẓ',
70560 'Ẕ' => 'ẕ',
70561 'ẞ' => 'ß',
70562 'Ạ' => 'ạ',
70563 'Ả' => 'ả',
70564 'Ấ' => 'ấ',
70565 'Ầ' => 'ầ',
70566 'Ẩ' => 'ẩ',
70567 'Ẫ' => 'ẫ',
70568 'Ậ' => 'ậ',
70569 'Ắ' => 'ắ',
70570 'Ằ' => 'ằ',
70571 'Ẳ' => 'ẳ',
70572 'Ẵ' => 'ẵ',
70573 'Ặ' => 'ặ',
70574 'Ẹ' => 'ẹ',
70575 'Ẻ' => 'ẻ',
70576 'Ẽ' => 'ẽ',
70577 'Ế' => 'ế',
70578 'Ề' => 'ề',
70579 'Ể' => 'ể',
70580 'Ễ' => 'ễ',
70581 'Ệ' => 'ệ',
70582 'Ỉ' => 'ỉ',
70583 'Ị' => 'ị',
70584 'Ọ' => 'ọ',
70585 'Ỏ' => 'ỏ',
70586 'Ố' => 'ố',
70587 'Ồ' => 'ồ',
70588 'Ổ' => 'ổ',
70589 'Ỗ' => 'ỗ',
70590 'Ộ' => 'ộ',
70591 'Ớ' => 'ớ',
70592 'Ờ' => 'ờ',
70593 'Ở' => 'ở',
70594 'Ỡ' => 'ỡ',
70595 'Ợ' => 'ợ',
70596 'Ụ' => 'ụ',
70597 'Ủ' => 'ủ',
70598 'Ứ' => 'ứ',
70599 'Ừ' => 'ừ',
70600 'Ử' => 'ử',
70601 'Ữ' => 'ữ',
70602 'Ự' => 'ự',
70603 'Ỳ' => 'ỳ',
70604 'Ỵ' => 'ỵ',
70605 'Ỷ' => 'ỷ',
70606 'Ỹ' => 'ỹ',
70607 'Ỻ' => 'ỻ',
70608 'Ỽ' => 'ỽ',
70609 'Ỿ' => 'ỿ',
70610 'Ἀ' => 'ἀ',
70611 'Ἁ' => 'ἁ',
70612 'Ἂ' => 'ἂ',
70613 'Ἃ' => 'ἃ',
70614 'Ἄ' => 'ἄ',
70615 'Ἅ' => 'ἅ',
70616 'Ἆ' => 'ἆ',
70617 'Ἇ' => 'ἇ',
70618 'Ἐ' => 'ἐ',
70619 'Ἑ' => 'ἑ',
70620 'Ἒ' => 'ἒ',
70621 'Ἓ' => 'ἓ',
70622 'Ἔ' => 'ἔ',
70623 'Ἕ' => 'ἕ',
70624 'Ἠ' => 'ἠ',
70625 'Ἡ' => 'ἡ',
70626 'Ἢ' => 'ἢ',
70627 'Ἣ' => 'ἣ',
70628 'Ἤ' => 'ἤ',
70629 'Ἥ' => 'ἥ',
70630 'Ἦ' => 'ἦ',
70631 'Ἧ' => 'ἧ',
70632 'Ἰ' => 'ἰ',
70633 'Ἱ' => 'ἱ',
70634 'Ἲ' => 'ἲ',
70635 'Ἳ' => 'ἳ',
70636 'Ἴ' => 'ἴ',
70637 'Ἵ' => 'ἵ',
70638 'Ἶ' => 'ἶ',
70639 'Ἷ' => 'ἷ',
70640 'Ὀ' => 'ὀ',
70641 'Ὁ' => 'ὁ',
70642 'Ὂ' => 'ὂ',
70643 'Ὃ' => 'ὃ',
70644 'Ὄ' => 'ὄ',
70645 'Ὅ' => 'ὅ',
70646 'Ὑ' => 'ὑ',
70647 'Ὓ' => 'ὓ',
70648 'Ὕ' => 'ὕ',
70649 'Ὗ' => 'ὗ',
70650 'Ὠ' => 'ὠ',
70651 'Ὡ' => 'ὡ',
70652 'Ὢ' => 'ὢ',
70653 'Ὣ' => 'ὣ',
70654 'Ὤ' => 'ὤ',
70655 'Ὥ' => 'ὥ',
70656 'Ὦ' => 'ὦ',
70657 'Ὧ' => 'ὧ',
70658 'ᾈ' => 'ᾀ',
70659 'ᾉ' => 'ᾁ',
70660 'ᾊ' => 'ᾂ',
70661 'ᾋ' => 'ᾃ',
70662 'ᾌ' => 'ᾄ',
70663 'ᾍ' => 'ᾅ',
70664 'ᾎ' => 'ᾆ',
70665 'ᾏ' => 'ᾇ',
70666 'ᾘ' => 'ᾐ',
70667 'ᾙ' => 'ᾑ',
70668 'ᾚ' => 'ᾒ',
70669 'ᾛ' => 'ᾓ',
70670 'ᾜ' => 'ᾔ',
70671 'ᾝ' => 'ᾕ',
70672 'ᾞ' => 'ᾖ',
70673 'ᾟ' => 'ᾗ',
70674 'ᾨ' => 'ᾠ',
70675 'ᾩ' => 'ᾡ',
70676 'ᾪ' => 'ᾢ',
70677 'ᾫ' => 'ᾣ',
70678 'ᾬ' => 'ᾤ',
70679 'ᾭ' => 'ᾥ',
70680 'ᾮ' => 'ᾦ',
70681 'ᾯ' => 'ᾧ',
70682 'Ᾰ' => 'ᾰ',
70683 'Ᾱ' => 'ᾱ',
70684 'Ὰ' => 'ὰ',
70685 'Ά' => 'ά',
70686 'ᾼ' => 'ᾳ',
70687 'Ὲ' => 'ὲ',
70688 'Έ' => 'έ',
70689 'Ὴ' => 'ὴ',
70690 'Ή' => 'ή',
70691 'ῌ' => 'ῃ',
70692 'Ῐ' => 'ῐ',
70693 'Ῑ' => 'ῑ',
70694 'Ὶ' => 'ὶ',
70695 'Ί' => 'ί',
70696 'Ῠ' => 'ῠ',
70697 'Ῡ' => 'ῡ',
70698 'Ὺ' => 'ὺ',
70699 'Ύ' => 'ύ',
70700 'Ῥ' => 'ῥ',
70701 'Ὸ' => 'ὸ',
70702 'Ό' => 'ό',
70703 'Ὼ' => 'ὼ',
70704 'Ώ' => 'ώ',
70705 'ῼ' => 'ῳ',
70706 'Ω' => 'ω',
70707 'K' => 'k',
70708 'Å' => 'å',
70709 'Ⅎ' => 'ⅎ',
70710 'Ⅰ' => 'ⅰ',
70711 'Ⅱ' => 'ⅱ',
70712 'Ⅲ' => 'ⅲ',
70713 'Ⅳ' => 'ⅳ',
70714 'Ⅴ' => 'ⅴ',
70715 'Ⅵ' => 'ⅵ',
70716 'Ⅶ' => 'ⅶ',
70717 'Ⅷ' => 'ⅷ',
70718 'Ⅸ' => 'ⅸ',
70719 'Ⅹ' => 'ⅹ',
70720 'Ⅺ' => 'ⅺ',
70721 'Ⅻ' => 'ⅻ',
70722 'Ⅼ' => 'ⅼ',
70723 'Ⅽ' => 'ⅽ',
70724 'Ⅾ' => 'ⅾ',
70725 'Ⅿ' => 'ⅿ',
70726 'Ↄ' => 'ↄ',
70727 'Ⓐ' => 'ⓐ',
70728 'Ⓑ' => 'ⓑ',
70729 'Ⓒ' => 'ⓒ',
70730 'Ⓓ' => 'ⓓ',
70731 'Ⓔ' => 'ⓔ',
70732 'Ⓕ' => 'ⓕ',
70733 'Ⓖ' => 'ⓖ',
70734 'Ⓗ' => 'ⓗ',
70735 'Ⓘ' => 'ⓘ',
70736 'Ⓙ' => 'ⓙ',
70737 'Ⓚ' => 'ⓚ',
70738 'Ⓛ' => 'ⓛ',
70739 'Ⓜ' => 'ⓜ',
70740 'Ⓝ' => 'ⓝ',
70741 'Ⓞ' => 'ⓞ',
70742 'Ⓟ' => 'ⓟ',
70743 'Ⓠ' => 'ⓠ',
70744 'Ⓡ' => 'ⓡ',
70745 'Ⓢ' => 'ⓢ',
70746 'Ⓣ' => 'ⓣ',
70747 'Ⓤ' => 'ⓤ',
70748 'Ⓥ' => 'ⓥ',
70749 'Ⓦ' => 'ⓦ',
70750 'Ⓧ' => 'ⓧ',
70751 'Ⓨ' => 'ⓨ',
70752 'Ⓩ' => 'ⓩ',
70753 'Ⰰ' => 'ⰰ',
70754 'Ⰱ' => 'ⰱ',
70755 'Ⰲ' => 'ⰲ',
70756 'Ⰳ' => 'ⰳ',
70757 'Ⰴ' => 'ⰴ',
70758 'Ⰵ' => 'ⰵ',
70759 'Ⰶ' => 'ⰶ',
70760 'Ⰷ' => 'ⰷ',
70761 'Ⰸ' => 'ⰸ',
70762 'Ⰹ' => 'ⰹ',
70763 'Ⰺ' => 'ⰺ',
70764 'Ⰻ' => 'ⰻ',
70765 'Ⰼ' => 'ⰼ',
70766 'Ⰽ' => 'ⰽ',
70767 'Ⰾ' => 'ⰾ',
70768 'Ⰿ' => 'ⰿ',
70769 'Ⱀ' => 'ⱀ',
70770 'Ⱁ' => 'ⱁ',
70771 'Ⱂ' => 'ⱂ',
70772 'Ⱃ' => 'ⱃ',
70773 'Ⱄ' => 'ⱄ',
70774 'Ⱅ' => 'ⱅ',
70775 'Ⱆ' => 'ⱆ',
70776 'Ⱇ' => 'ⱇ',
70777 'Ⱈ' => 'ⱈ',
70778 'Ⱉ' => 'ⱉ',
70779 'Ⱊ' => 'ⱊ',
70780 'Ⱋ' => 'ⱋ',
70781 'Ⱌ' => 'ⱌ',
70782 'Ⱍ' => 'ⱍ',
70783 'Ⱎ' => 'ⱎ',
70784 'Ⱏ' => 'ⱏ',
70785 'Ⱐ' => 'ⱐ',
70786 'Ⱑ' => 'ⱑ',
70787 'Ⱒ' => 'ⱒ',
70788 'Ⱓ' => 'ⱓ',
70789 'Ⱔ' => 'ⱔ',
70790 'Ⱕ' => 'ⱕ',
70791 'Ⱖ' => 'ⱖ',
70792 'Ⱗ' => 'ⱗ',
70793 'Ⱘ' => 'ⱘ',
70794 'Ⱙ' => 'ⱙ',
70795 'Ⱚ' => 'ⱚ',
70796 'Ⱛ' => 'ⱛ',
70797 'Ⱜ' => 'ⱜ',
70798 'Ⱝ' => 'ⱝ',
70799 'Ⱞ' => 'ⱞ',
70800 'Ⱡ' => 'ⱡ',
70801 'Ɫ' => 'ɫ',
70802 'Ᵽ' => 'ᵽ',
70803 'Ɽ' => 'ɽ',
70804 'Ⱨ' => 'ⱨ',
70805 'Ⱪ' => 'ⱪ',
70806 'Ⱬ' => 'ⱬ',
70807 'Ɑ' => 'ɑ',
70808 'Ɱ' => 'ɱ',
70809 'Ɐ' => 'ɐ',
70810 'Ɒ' => 'ɒ',
70811 'Ⱳ' => 'ⱳ',
70812 'Ⱶ' => 'ⱶ',
70813 'Ȿ' => 'ȿ',
70814 'Ɀ' => 'ɀ',
70815 'Ⲁ' => 'ⲁ',
70816 'Ⲃ' => 'ⲃ',
70817 'Ⲅ' => 'ⲅ',
70818 'Ⲇ' => 'ⲇ',
70819 'Ⲉ' => 'ⲉ',
70820 'Ⲋ' => 'ⲋ',
70821 'Ⲍ' => 'ⲍ',
70822 'Ⲏ' => 'ⲏ',
70823 'Ⲑ' => 'ⲑ',
70824 'Ⲓ' => 'ⲓ',
70825 'Ⲕ' => 'ⲕ',
70826 'Ⲗ' => 'ⲗ',
70827 'Ⲙ' => 'ⲙ',
70828 'Ⲛ' => 'ⲛ',
70829 'Ⲝ' => 'ⲝ',
70830 'Ⲟ' => 'ⲟ',
70831 'Ⲡ' => 'ⲡ',
70832 'Ⲣ' => 'ⲣ',
70833 'Ⲥ' => 'ⲥ',
70834 'Ⲧ' => 'ⲧ',
70835 'Ⲩ' => 'ⲩ',
70836 'Ⲫ' => 'ⲫ',
70837 'Ⲭ' => 'ⲭ',
70838 'Ⲯ' => 'ⲯ',
70839 'Ⲱ' => 'ⲱ',
70840 'Ⲳ' => 'ⲳ',
70841 'Ⲵ' => 'ⲵ',
70842 'Ⲷ' => 'ⲷ',
70843 'Ⲹ' => 'ⲹ',
70844 'Ⲻ' => 'ⲻ',
70845 'Ⲽ' => 'ⲽ',
70846 'Ⲿ' => 'ⲿ',
70847 'Ⳁ' => 'ⳁ',
70848 'Ⳃ' => 'ⳃ',
70849 'Ⳅ' => 'ⳅ',
70850 'Ⳇ' => 'ⳇ',
70851 'Ⳉ' => 'ⳉ',
70852 'Ⳋ' => 'ⳋ',
70853 'Ⳍ' => 'ⳍ',
70854 'Ⳏ' => 'ⳏ',
70855 'Ⳑ' => 'ⳑ',
70856 'Ⳓ' => 'ⳓ',
70857 'Ⳕ' => 'ⳕ',
70858 'Ⳗ' => 'ⳗ',
70859 'Ⳙ' => 'ⳙ',
70860 'Ⳛ' => 'ⳛ',
70861 'Ⳝ' => 'ⳝ',
70862 'Ⳟ' => 'ⳟ',
70863 'Ⳡ' => 'ⳡ',
70864 'Ⳣ' => 'ⳣ',
70865 'Ⳬ' => 'ⳬ',
70866 'Ⳮ' => 'ⳮ',
70867 'Ⳳ' => 'ⳳ',
70868 'Ꙁ' => 'ꙁ',
70869 'Ꙃ' => 'ꙃ',
70870 'Ꙅ' => 'ꙅ',
70871 'Ꙇ' => 'ꙇ',
70872 'Ꙉ' => 'ꙉ',
70873 'Ꙋ' => 'ꙋ',
70874 'Ꙍ' => 'ꙍ',
70875 'Ꙏ' => 'ꙏ',
70876 'Ꙑ' => 'ꙑ',
70877 'Ꙓ' => 'ꙓ',
70878 'Ꙕ' => 'ꙕ',
70879 'Ꙗ' => 'ꙗ',
70880 'Ꙙ' => 'ꙙ',
70881 'Ꙛ' => 'ꙛ',
70882 'Ꙝ' => 'ꙝ',
70883 'Ꙟ' => 'ꙟ',
70884 'Ꙡ' => 'ꙡ',
70885 'Ꙣ' => 'ꙣ',
70886 'Ꙥ' => 'ꙥ',
70887 'Ꙧ' => 'ꙧ',
70888 'Ꙩ' => 'ꙩ',
70889 'Ꙫ' => 'ꙫ',
70890 'Ꙭ' => 'ꙭ',
70891 'Ꚁ' => 'ꚁ',
70892 'Ꚃ' => 'ꚃ',
70893 'Ꚅ' => 'ꚅ',
70894 'Ꚇ' => 'ꚇ',
70895 'Ꚉ' => 'ꚉ',
70896 'Ꚋ' => 'ꚋ',
70897 'Ꚍ' => 'ꚍ',
70898 'Ꚏ' => 'ꚏ',
70899 'Ꚑ' => 'ꚑ',
70900 'Ꚓ' => 'ꚓ',
70901 'Ꚕ' => 'ꚕ',
70902 'Ꚗ' => 'ꚗ',
70903 'Ꚙ' => 'ꚙ',
70904 'Ꚛ' => 'ꚛ',
70905 'Ꜣ' => 'ꜣ',
70906 'Ꜥ' => 'ꜥ',
70907 'Ꜧ' => 'ꜧ',
70908 'Ꜩ' => 'ꜩ',
70909 'Ꜫ' => 'ꜫ',
70910 'Ꜭ' => 'ꜭ',
70911 'Ꜯ' => 'ꜯ',
70912 'Ꜳ' => 'ꜳ',
70913 'Ꜵ' => 'ꜵ',
70914 'Ꜷ' => 'ꜷ',
70915 'Ꜹ' => 'ꜹ',
70916 'Ꜻ' => 'ꜻ',
70917 'Ꜽ' => 'ꜽ',
70918 'Ꜿ' => 'ꜿ',
70919 'Ꝁ' => 'ꝁ',
70920 'Ꝃ' => 'ꝃ',
70921 'Ꝅ' => 'ꝅ',
70922 'Ꝇ' => 'ꝇ',
70923 'Ꝉ' => 'ꝉ',
70924 'Ꝋ' => 'ꝋ',
70925 'Ꝍ' => 'ꝍ',
70926 'Ꝏ' => 'ꝏ',
70927 'Ꝑ' => 'ꝑ',
70928 'Ꝓ' => 'ꝓ',
70929 'Ꝕ' => 'ꝕ',
70930 'Ꝗ' => 'ꝗ',
70931 'Ꝙ' => 'ꝙ',
70932 'Ꝛ' => 'ꝛ',
70933 'Ꝝ' => 'ꝝ',
70934 'Ꝟ' => 'ꝟ',
70935 'Ꝡ' => 'ꝡ',
70936 'Ꝣ' => 'ꝣ',
70937 'Ꝥ' => 'ꝥ',
70938 'Ꝧ' => 'ꝧ',
70939 'Ꝩ' => 'ꝩ',
70940 'Ꝫ' => 'ꝫ',
70941 'Ꝭ' => 'ꝭ',
70942 'Ꝯ' => 'ꝯ',
70943 'Ꝺ' => 'ꝺ',
70944 'Ꝼ' => 'ꝼ',
70945 'Ᵹ' => 'ᵹ',
70946 'Ꝿ' => 'ꝿ',
70947 'Ꞁ' => 'ꞁ',
70948 'Ꞃ' => 'ꞃ',
70949 'Ꞅ' => 'ꞅ',
70950 'Ꞇ' => 'ꞇ',
70951 'Ꞌ' => 'ꞌ',
70952 'Ɥ' => 'ɥ',
70953 'Ꞑ' => 'ꞑ',
70954 'Ꞓ' => 'ꞓ',
70955 'Ꞗ' => 'ꞗ',
70956 'Ꞙ' => 'ꞙ',
70957 'Ꞛ' => 'ꞛ',
70958 'Ꞝ' => 'ꞝ',
70959 'Ꞟ' => 'ꞟ',
70960 'Ꞡ' => 'ꞡ',
70961 'Ꞣ' => 'ꞣ',
70962 'Ꞥ' => 'ꞥ',
70963 'Ꞧ' => 'ꞧ',
70964 'Ꞩ' => 'ꞩ',
70965 'Ɦ' => 'ɦ',
70966 'Ɜ' => 'ɜ',
70967 'Ɡ' => 'ɡ',
70968 'Ɬ' => 'ɬ',
70969 'Ʞ' => 'ʞ',
70970 'Ʇ' => 'ʇ',
70971 'A' => 'a',
70972 'B' => 'b',
70973 'C' => 'c',
70974 'D' => 'd',
70975 'E' => 'e',
70976 'F' => 'f',
70977 'G' => 'g',
70978 'H' => 'h',
70979 'I' => 'i',
70980 'J' => 'j',
70981 'K' => 'k',
70982 'L' => 'l',
70983 'M' => 'm',
70984 'N' => 'n',
70985 'O' => 'o',
70986 'P' => 'p',
70987 'Q' => 'q',
70988 'R' => 'r',
70989 'S' => 's',
70990 'T' => 't',
70991 'U' => 'u',
70992 'V' => 'v',
70993 'W' => 'w',
70994 'X' => 'x',
70995 'Y' => 'y',
70996 'Z' => 'z',
70997 '𐐀' => '𐐨',
70998 '𐐁' => '𐐩',
70999 '𐐂' => '𐐪',
71000 '𐐃' => '𐐫',
71001 '𐐄' => '𐐬',
71002 '𐐅' => '𐐭',
71003 '𐐆' => '𐐮',
71004 '𐐇' => '𐐯',
71005 '𐐈' => '𐐰',
71006 '𐐉' => '𐐱',
71007 '𐐊' => '𐐲',
71008 '𐐋' => '𐐳',
71009 '𐐌' => '𐐴',
71010 '𐐍' => '𐐵',
71011 '𐐎' => '𐐶',
71012 '𐐏' => '𐐷',
71013 '𐐐' => '𐐸',
71014 '𐐑' => '𐐹',
71015 '𐐒' => '𐐺',
71016 '𐐓' => '𐐻',
71017 '𐐔' => '𐐼',
71018 '𐐕' => '𐐽',
71019 '𐐖' => '𐐾',
71020 '𐐗' => '𐐿',
71021 '𐐘' => '𐑀',
71022 '𐐙' => '𐑁',
71023 '𐐚' => '𐑂',
71024 '𐐛' => '𐑃',
71025 '𐐜' => '𐑄',
71026 '𐐝' => '𐑅',
71027 '𐐞' => '𐑆',
71028 '𐐟' => '𐑇',
71029 '𐐠' => '𐑈',
71030 '𐐡' => '𐑉',
71031 '𐐢' => '𐑊',
71032 '𐐣' => '𐑋',
71033 '𐐤' => '𐑌',
71034 '𐐥' => '𐑍',
71035 '𐐦' => '𐑎',
71036 '𐐧' => '𐑏',
71037 '𑢠' => '𑣀',
71038 '𑢡' => '𑣁',
71039 '𑢢' => '𑣂',
71040 '𑢣' => '𑣃',
71041 '𑢤' => '𑣄',
71042 '𑢥' => '𑣅',
71043 '𑢦' => '𑣆',
71044 '𑢧' => '𑣇',
71045 '𑢨' => '𑣈',
71046 '𑢩' => '𑣉',
71047 '𑢪' => '𑣊',
71048 '𑢫' => '𑣋',
71049 '𑢬' => '𑣌',
71050 '𑢭' => '𑣍',
71051 '𑢮' => '𑣎',
71052 '𑢯' => '𑣏',
71053 '𑢰' => '𑣐',
71054 '𑢱' => '𑣑',
71055 '𑢲' => '𑣒',
71056 '𑢳' => '𑣓',
71057 '𑢴' => '𑣔',
71058 '𑢵' => '𑣕',
71059 '𑢶' => '𑣖',
71060 '𑢷' => '𑣗',
71061 '𑢸' => '𑣘',
71062 '𑢹' => '𑣙',
71063 '𑢺' => '𑣚',
71064 '𑢻' => '𑣛',
71065 '𑢼' => '𑣜',
71066 '𑢽' => '𑣝',
71067 '𑢾' => '𑣞',
71068 '𑢿' => '𑣟',
71069 );
71070
71071 $result =& $data;
71072 unset($data);
71073
71074 return $result;
71075 <?php
71076
71077 static $data = array (
71078 'a' => 'A',
71079 'b' => 'B',
71080 'c' => 'C',
71081 'd' => 'D',
71082 'e' => 'E',
71083 'f' => 'F',
71084 'g' => 'G',
71085 'h' => 'H',
71086 'i' => 'I',
71087 'j' => 'J',
71088 'k' => 'K',
71089 'l' => 'L',
71090 'm' => 'M',
71091 'n' => 'N',
71092 'o' => 'O',
71093 'p' => 'P',
71094 'q' => 'Q',
71095 'r' => 'R',
71096 's' => 'S',
71097 't' => 'T',
71098 'u' => 'U',
71099 'v' => 'V',
71100 'w' => 'W',
71101 'x' => 'X',
71102 'y' => 'Y',
71103 'z' => 'Z',
71104 'µ' => 'Μ',
71105 'à' => 'À',
71106 'á' => 'Á',
71107 'â' => 'Â',
71108 'ã' => 'Ã',
71109 'ä' => 'Ä',
71110 'å' => 'Å',
71111 'æ' => 'Æ',
71112 'ç' => 'Ç',
71113 'è' => 'È',
71114 'é' => 'É',
71115 'ê' => 'Ê',
71116 'ë' => 'Ë',
71117 'ì' => 'Ì',
71118 'í' => 'Í',
71119 'î' => 'Î',
71120 'ï' => 'Ï',
71121 'ð' => 'Ð',
71122 'ñ' => 'Ñ',
71123 'ò' => 'Ò',
71124 'ó' => 'Ó',
71125 'ô' => 'Ô',
71126 'õ' => 'Õ',
71127 'ö' => 'Ö',
71128 'ø' => 'Ø',
71129 'ù' => 'Ù',
71130 'ú' => 'Ú',
71131 'û' => 'Û',
71132 'ü' => 'Ü',
71133 'ý' => 'Ý',
71134 'þ' => 'Þ',
71135 'ÿ' => 'Ÿ',
71136 'ā' => 'Ā',
71137 'ă' => 'Ă',
71138 'ą' => 'Ą',
71139 'ć' => 'Ć',
71140 'ĉ' => 'Ĉ',
71141 'ċ' => 'Ċ',
71142 'č' => 'Č',
71143 'ď' => 'Ď',
71144 'đ' => 'Đ',
71145 'ē' => 'Ē',
71146 'ĕ' => 'Ĕ',
71147 'ė' => 'Ė',
71148 'ę' => 'Ę',
71149 'ě' => 'Ě',
71150 'ĝ' => 'Ĝ',
71151 'ğ' => 'Ğ',
71152 'ġ' => 'Ġ',
71153 'ģ' => 'Ģ',
71154 'ĥ' => 'Ĥ',
71155 'ħ' => 'Ħ',
71156 'ĩ' => 'Ĩ',
71157 'ī' => 'Ī',
71158 'ĭ' => 'Ĭ',
71159 'į' => 'Į',
71160 'ı' => 'I',
71161 'ij' => 'IJ',
71162 'ĵ' => 'Ĵ',
71163 'ķ' => 'Ķ',
71164 'ĺ' => 'Ĺ',
71165 'ļ' => 'Ļ',
71166 'ľ' => 'Ľ',
71167 'ŀ' => 'Ŀ',
71168 'ł' => 'Ł',
71169 'ń' => 'Ń',
71170 'ņ' => 'Ņ',
71171 'ň' => 'Ň',
71172 'ŋ' => 'Ŋ',
71173 'ō' => 'Ō',
71174 'ŏ' => 'Ŏ',
71175 'ő' => 'Ő',
71176 'œ' => 'Œ',
71177 'ŕ' => 'Ŕ',
71178 'ŗ' => 'Ŗ',
71179 'ř' => 'Ř',
71180 'ś' => 'Ś',
71181 'ŝ' => 'Ŝ',
71182 'ş' => 'Ş',
71183 'š' => 'Š',
71184 'ţ' => 'Ţ',
71185 'ť' => 'Ť',
71186 'ŧ' => 'Ŧ',
71187 'ũ' => 'Ũ',
71188 'ū' => 'Ū',
71189 'ŭ' => 'Ŭ',
71190 'ů' => 'Ů',
71191 'ű' => 'Ű',
71192 'ų' => 'Ų',
71193 'ŵ' => 'Ŵ',
71194 'ŷ' => 'Ŷ',
71195 'ź' => 'Ź',
71196 'ż' => 'Ż',
71197 'ž' => 'Ž',
71198 'ſ' => 'S',
71199 'ƀ' => 'Ƀ',
71200 'ƃ' => 'Ƃ',
71201 'ƅ' => 'Ƅ',
71202 'ƈ' => 'Ƈ',
71203 'ƌ' => 'Ƌ',
71204 'ƒ' => 'Ƒ',
71205 'ƕ' => 'Ƕ',
71206 'ƙ' => 'Ƙ',
71207 'ƚ' => 'Ƚ',
71208 'ƞ' => 'Ƞ',
71209 'ơ' => 'Ơ',
71210 'ƣ' => 'Ƣ',
71211 'ƥ' => 'Ƥ',
71212 'ƨ' => 'Ƨ',
71213 'ƭ' => 'Ƭ',
71214 'ư' => 'Ư',
71215 'ƴ' => 'Ƴ',
71216 'ƶ' => 'Ƶ',
71217 'ƹ' => 'Ƹ',
71218 'ƽ' => 'Ƽ',
71219 'ƿ' => 'Ƿ',
71220 'Dž' => 'DŽ',
71221 'dž' => 'DŽ',
71222 'Lj' => 'LJ',
71223 'lj' => 'LJ',
71224 'Nj' => 'NJ',
71225 'nj' => 'NJ',
71226 'ǎ' => 'Ǎ',
71227 'ǐ' => 'Ǐ',
71228 'ǒ' => 'Ǒ',
71229 'ǔ' => 'Ǔ',
71230 'ǖ' => 'Ǖ',
71231 'ǘ' => 'Ǘ',
71232 'ǚ' => 'Ǚ',
71233 'ǜ' => 'Ǜ',
71234 'ǝ' => 'Ǝ',
71235 'ǟ' => 'Ǟ',
71236 'ǡ' => 'Ǡ',
71237 'ǣ' => 'Ǣ',
71238 'ǥ' => 'Ǥ',
71239 'ǧ' => 'Ǧ',
71240 'ǩ' => 'Ǩ',
71241 'ǫ' => 'Ǫ',
71242 'ǭ' => 'Ǭ',
71243 'ǯ' => 'Ǯ',
71244 'Dz' => 'DZ',
71245 'dz' => 'DZ',
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 'ȩ' => 'Ȩ',
71271 'ȫ' => 'Ȫ',
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 'π' => 'Π',
71346 'ρ' => 'Ρ',
71347 'ς' => 'Σ',
71348 'σ' => 'Σ',
71349 'τ' => 'Τ',
71350 'υ' => 'Υ',
71351 'φ' => 'Φ',
71352 'χ' => 'Χ',
71353 'ψ' => 'Ψ',
71354 'ω' => 'Ω',
71355 'ϊ' => 'Ϊ',
71356 'ϋ' => 'Ϋ',
71357 'ό' => 'Ό',
71358 'ύ' => 'Ύ',
71359 'ώ' => 'Ώ',
71360 'ϐ' => 'Β',
71361 'ϑ' => 'Θ',
71362 'ϕ' => 'Φ',
71363 'ϖ' => 'Π',
71364 'ϗ' => 'Ϗ',
71365 'ϙ' => 'Ϙ',
71366 'ϛ' => 'Ϛ',
71367 'ϝ' => 'Ϝ',
71368 'ϟ' => 'Ϟ',
71369 'ϡ' => 'Ϡ',
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 'ⲹ' => 'Ⲹ',
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 'a' => 'A',
72081 'b' => 'B',
72082 'c' => 'C',
72083 'd' => 'D',
72084 'e' => 'E',
72085 'f' => 'F',
72086 'g' => 'G',
72087 'h' => 'H',
72088 'i' => 'I',
72089 'j' => 'J',
72090 'k' => 'K',
72091 'l' => 'L',
72092 'm' => 'M',
72093 'n' => 'N',
72094 'o' => 'O',
72095 'p' => 'P',
72096 'q' => 'Q',
72097 'r' => 'R',
72098 's' => 'S',
72099 't' => 'T',
72100 'u' => 'U',
72101 'v' => 'V',
72102 'w' => 'W',
72103 'x' => 'X',
72104 'y' => 'Y',
72105 'z' => 'Z',
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 $result =& $data;
72181 unset($data);
72182
72183 return $result;
72184 <?php
72185
72186
72187
72188
72189
72190
72191
72192
72193
72194
72195 use Symfony\Polyfill\Mbstring as p;
72196
72197 if (!function_exists('mb_strlen')) {
72198 define('MB_CASE_UPPER', 0);
72199 define('MB_CASE_LOWER', 1);
72200 define('MB_CASE_TITLE', 2);
72201
72202 function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
72203 function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
72204 function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
72205 function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
72206 function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
72207 function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
72208 function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
72209 function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
72210 function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
72211 function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
72212 function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
72213 function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
72214 function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
72215 function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
72216 function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
72217 function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
72218 function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
72219 function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
72220 function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
72221 function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
72222 function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
72223 function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
72224 function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
72225 function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
72226 function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
72227 function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
72228 function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
72229 function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
72230 function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
72231 function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
72232 function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
72233 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); }
72234 }
72235 if (!function_exists('mb_chr')) {
72236 function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
72237 function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
72238 function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
72239 }
72240 <?php
72241
72242
72243
72244
72245
72246
72247
72248
72249
72250
72251 namespace Symfony\Component\Process\Exception;
72252
72253
72254
72255
72256
72257
72258 interface ExceptionInterface
72259 {
72260 }
72261 <?php
72262
72263
72264
72265
72266
72267
72268
72269
72270
72271
72272 namespace Symfony\Component\Process\Exception;
72273
72274
72275
72276
72277
72278
72279 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
72280 {
72281 }
72282 <?php
72283
72284
72285
72286
72287
72288
72289
72290
72291
72292
72293 namespace Symfony\Component\Process\Exception;
72294
72295
72296
72297
72298
72299
72300 class LogicException extends \LogicException implements ExceptionInterface
72301 {
72302 }
72303 <?php
72304
72305
72306
72307
72308
72309
72310
72311
72312
72313
72314 namespace Symfony\Component\Process\Exception;
72315
72316 use Symfony\Component\Process\Process;
72317
72318
72319
72320
72321
72322
72323 class ProcessFailedException extends RuntimeException
72324 {
72325 private $process;
72326
72327 public function __construct(Process $process)
72328 {
72329 if ($process->isSuccessful()) {
72330 throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
72331 }
72332
72333 $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
72334 $process->getCommandLine(),
72335 $process->getExitCode(),
72336 $process->getExitCodeText(),
72337 $process->getWorkingDirectory()
72338 );
72339
72340 if (!$process->isOutputDisabled()) {
72341 $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
72342 $process->getOutput(),
72343 $process->getErrorOutput()
72344 );
72345 }
72346
72347 parent::__construct($error);
72348
72349 $this->process = $process;
72350 }
72351
72352 public function getProcess()
72353 {
72354 return $this->process;
72355 }
72356 }
72357 <?php
72358
72359
72360
72361
72362
72363
72364
72365
72366
72367
72368 namespace Symfony\Component\Process\Exception;
72369
72370 use Symfony\Component\Process\Process;
72371
72372
72373
72374
72375
72376
72377 class ProcessTimedOutException extends RuntimeException
72378 {
72379 const TYPE_GENERAL = 1;
72380 const TYPE_IDLE = 2;
72381
72382 private $process;
72383 private $timeoutType;
72384
72385 public function __construct(Process $process, $timeoutType)
72386 {
72387 $this->process = $process;
72388 $this->timeoutType = $timeoutType;
72389
72390 parent::__construct(sprintf(
72391 'The process "%s" exceeded the timeout of %s seconds.',
72392 $process->getCommandLine(),
72393 $this->getExceededTimeout()
72394 ));
72395 }
72396
72397 public function getProcess()
72398 {
72399 return $this->process;
72400 }
72401
72402 public function isGeneralTimeout()
72403 {
72404 return self::TYPE_GENERAL === $this->timeoutType;
72405 }
72406
72407 public function isIdleTimeout()
72408 {
72409 return self::TYPE_IDLE === $this->timeoutType;
72410 }
72411
72412 public function getExceededTimeout()
72413 {
72414 switch ($this->timeoutType) {
72415 case self::TYPE_GENERAL:
72416 return $this->process->getTimeout();
72417
72418 case self::TYPE_IDLE:
72419 return $this->process->getIdleTimeout();
72420
72421 default:
72422 throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
72423 }
72424 }
72425 }
72426 <?php
72427
72428
72429
72430
72431
72432
72433
72434
72435
72436
72437 namespace Symfony\Component\Process\Exception;
72438
72439
72440
72441
72442
72443
72444 class RuntimeException extends \RuntimeException implements ExceptionInterface
72445 {
72446 }
72447 <?php
72448
72449
72450
72451
72452
72453
72454
72455
72456
72457
72458 namespace Symfony\Component\Process;
72459
72460
72461
72462
72463
72464
72465
72466 class ExecutableFinder
72467 {
72468 private $suffixes = array('.exe', '.bat', '.cmd', '.com');
72469
72470
72471
72472
72473 public function setSuffixes(array $suffixes)
72474 {
72475 $this->suffixes = $suffixes;
72476 }
72477
72478
72479
72480
72481
72482
72483 public function addSuffix($suffix)
72484 {
72485 $this->suffixes[] = $suffix;
72486 }
72487
72488
72489
72490
72491
72492
72493
72494
72495
72496
72497 public function find($name, $default = null, array $extraDirs = array())
72498 {
72499 if (ini_get('open_basedir')) {
72500 $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
72501 $dirs = array();
72502 foreach ($searchPath as $path) {
72503
72504  if (@is_dir($path)) {
72505 $dirs[] = $path;
72506 } else {
72507 if (basename($path) == $name && @is_executable($path)) {
72508 return $path;
72509 }
72510 }
72511 }
72512 } else {
72513 $dirs = array_merge(
72514 explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
72515 $extraDirs
72516 );
72517 }
72518
72519 $suffixes = array('');
72520 if ('\\' === DIRECTORY_SEPARATOR) {
72521 $pathExt = getenv('PATHEXT');
72522 $suffixes = array_merge($suffixes, $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes);
72523 }
72524 foreach ($suffixes as $suffix) {
72525 foreach ($dirs as $dir) {
72526 if (@is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) {
72527 return $file;
72528 }
72529 }
72530 }
72531
72532 return $default;
72533 }
72534 }
72535 Copyright (c) 2004-2017 Fabien Potencier
72536
72537 Permission is hereby granted, free of charge, to any person obtaining a copy
72538 of this software and associated documentation files (the "Software"), to deal
72539 in the Software without restriction, including without limitation the rights
72540 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
72541 copies of the Software, and to permit persons to whom the Software is furnished
72542 to do so, subject to the following conditions:
72543
72544 The above copyright notice and this permission notice shall be included in all
72545 copies or substantial portions of the Software.
72546
72547 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
72548 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72549 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
72550 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
72551 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
72552 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
72553 THE SOFTWARE.
72554 <?php
72555
72556
72557
72558
72559
72560
72561
72562
72563
72564
72565 namespace Symfony\Component\Process;
72566
72567
72568
72569
72570
72571
72572
72573 class PhpExecutableFinder
72574 {
72575 private $executableFinder;
72576
72577 public function __construct()
72578 {
72579 $this->executableFinder = new ExecutableFinder();
72580 }
72581
72582
72583
72584
72585
72586
72587
72588
72589 public function find($includeArgs = true)
72590 {
72591 $args = $this->findArguments();
72592 $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
72593
72594
72595  if (defined('HHVM_VERSION')) {
72596 return (getenv('PHP_BINARY') ?: PHP_BINARY).$args;
72597 }
72598
72599
72600  if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg')) && is_file(PHP_BINARY)) {
72601 return PHP_BINARY.$args;
72602 }
72603
72604 if ($php = getenv('PHP_PATH')) {
72605 if (!is_executable($php)) {
72606 return false;
72607 }
72608
72609 return $php;
72610 }
72611
72612 if ($php = getenv('PHP_PEAR_PHP_BIN')) {
72613 if (is_executable($php)) {
72614 return $php;
72615 }
72616 }
72617
72618 $dirs = array(PHP_BINDIR);
72619 if ('\\' === DIRECTORY_SEPARATOR) {
72620 $dirs[] = 'C:\xampp\php\\';
72621 }
72622
72623 return $this->executableFinder->find('php', false, $dirs);
72624 }
72625
72626
72627
72628
72629
72630
72631 public function findArguments()
72632 {
72633 $arguments = array();
72634
72635 if (defined('HHVM_VERSION')) {
72636 $arguments[] = '--php';
72637 } elseif ('phpdbg' === PHP_SAPI) {
72638 $arguments[] = '-qrr';
72639 }
72640
72641 return $arguments;
72642 }
72643 }
72644 <?php
72645
72646
72647
72648
72649
72650
72651
72652
72653
72654
72655 namespace Symfony\Component\Process;
72656
72657 use Symfony\Component\Process\Exception\RuntimeException;
72658
72659
72660
72661
72662
72663
72664
72665
72666
72667
72668 class PhpProcess extends Process
72669 {
72670
72671
72672
72673
72674
72675
72676
72677 public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = array())
72678 {
72679 $executableFinder = new PhpExecutableFinder();
72680 if (false === $php = $executableFinder->find()) {
72681 $php = null;
72682 }
72683 if ('phpdbg' === PHP_SAPI) {
72684 $file = tempnam(sys_get_temp_dir(), 'dbg');
72685 file_put_contents($file, $script);
72686 register_shutdown_function('unlink', $file);
72687 $php .= ' '.ProcessUtils::escapeArgument($file);
72688 $script = null;
72689 }
72690 if ('\\' !== DIRECTORY_SEPARATOR && null !== $php) {
72691
72692  
72693  
72694  $php = 'exec '.$php;
72695 }
72696
72697 parent::__construct($php, $cwd, $env, $script, $timeout, $options);
72698 }
72699
72700
72701
72702
72703 public function setPhpBinary($php)
72704 {
72705 $this->setCommandLine($php);
72706 }
72707
72708
72709
72710
72711 public function start($callback = null)
72712 {
72713 if (null === $this->getCommandLine()) {
72714 throw new RuntimeException('Unable to find the PHP executable.');
72715 }
72716
72717 parent::start($callback);
72718 }
72719 }
72720 <?php
72721
72722
72723
72724
72725
72726
72727
72728
72729
72730
72731 namespace Symfony\Component\Process\Pipes;
72732
72733
72734
72735
72736
72737
72738 abstract class AbstractPipes implements PipesInterface
72739 {
72740 public $pipes = array();
72741
72742 private $inputBuffer = '';
72743 private $input;
72744 private $blocked = true;
72745
72746
72747
72748
72749 public function __construct($input)
72750 {
72751 if (is_resource($input)) {
72752 $this->input = $input;
72753 } elseif (is_string($input)) {
72754 $this->inputBuffer = $input;
72755 } else {
72756 $this->inputBuffer = (string) $input;
72757 }
72758 }
72759
72760
72761
72762
72763 public function close()
72764 {
72765 foreach ($this->pipes as $pipe) {
72766 fclose($pipe);
72767 }
72768 $this->pipes = array();
72769 }
72770
72771
72772
72773
72774
72775
72776 protected function hasSystemCallBeenInterrupted()
72777 {
72778 $lastError = error_get_last();
72779
72780
72781  return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
72782 }
72783
72784
72785
72786
72787 protected function unblock()
72788 {
72789 if (!$this->blocked) {
72790 return;
72791 }
72792
72793 foreach ($this->pipes as $pipe) {
72794 stream_set_blocking($pipe, 0);
72795 }
72796 if (null !== $this->input) {
72797 stream_set_blocking($this->input, 0);
72798 }
72799
72800 $this->blocked = false;
72801 }
72802
72803
72804
72805
72806 protected function write()
72807 {
72808 if (!isset($this->pipes[0])) {
72809 return;
72810 }
72811 $input = $this->input;
72812 $r = $e = array();
72813 $w = array($this->pipes[0]);
72814
72815
72816  if (false === $n = @stream_select($r, $w, $e, 0, 0)) {
72817 return;
72818 }
72819
72820 foreach ($w as $stdin) {
72821 if (isset($this->inputBuffer[0])) {
72822 $written = fwrite($stdin, $this->inputBuffer);
72823 $this->inputBuffer = substr($this->inputBuffer, $written);
72824 if (isset($this->inputBuffer[0])) {
72825 return array($this->pipes[0]);
72826 }
72827 }
72828
72829 if ($input) {
72830 for (;;) {
72831 $data = fread($input, self::CHUNK_SIZE);
72832 if (!isset($data[0])) {
72833 break;
72834 }
72835 $written = fwrite($stdin, $data);
72836 $data = substr($data, $written);
72837 if (isset($data[0])) {
72838 $this->inputBuffer = $data;
72839
72840 return array($this->pipes[0]);
72841 }
72842 }
72843 if (feof($input)) {
72844
72845  
72846  $this->input = null;
72847 }
72848 }
72849 }
72850
72851
72852  if (null === $this->input && !isset($this->inputBuffer[0])) {
72853 fclose($this->pipes[0]);
72854 unset($this->pipes[0]);
72855 } elseif (!$w) {
72856 return array($this->pipes[0]);
72857 }
72858 }
72859 }
72860 <?php
72861
72862
72863
72864
72865
72866
72867
72868
72869
72870
72871 namespace Symfony\Component\Process\Pipes;
72872
72873
72874
72875
72876
72877
72878
72879
72880 interface PipesInterface
72881 {
72882 const CHUNK_SIZE = 16384;
72883
72884
72885
72886
72887
72888
72889 public function getDescriptors();
72890
72891
72892
72893
72894
72895
72896 public function getFiles();
72897
72898
72899
72900
72901
72902
72903
72904
72905
72906 public function readAndWrite($blocking, $close = false);
72907
72908
72909
72910
72911
72912
72913 public function areOpen();
72914
72915
72916
72917
72918 public function close();
72919 }
72920 <?php
72921
72922
72923
72924
72925
72926
72927
72928
72929
72930
72931 namespace Symfony\Component\Process\Pipes;
72932
72933 use Symfony\Component\Process\Process;
72934
72935
72936
72937
72938
72939
72940
72941
72942 class UnixPipes extends AbstractPipes
72943 {
72944 private $ttyMode;
72945 private $ptyMode;
72946 private $disableOutput;
72947
72948 public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
72949 {
72950 $this->ttyMode = (bool) $ttyMode;
72951 $this->ptyMode = (bool) $ptyMode;
72952 $this->disableOutput = (bool) $disableOutput;
72953
72954 parent::__construct($input);
72955 }
72956
72957 public function __destruct()
72958 {
72959 $this->close();
72960 }
72961
72962
72963
72964
72965 public function getDescriptors()
72966 {
72967 if ($this->disableOutput) {
72968 $nullstream = fopen('/dev/null', 'c');
72969
72970 return array(
72971 array('pipe', 'r'),
72972 $nullstream,
72973 $nullstream,
72974 );
72975 }
72976
72977 if ($this->ttyMode) {
72978 return array(
72979 array('file', '/dev/tty', 'r'),
72980 array('file', '/dev/tty', 'w'),
72981 array('file', '/dev/tty', 'w'),
72982 );
72983 }
72984
72985 if ($this->ptyMode && Process::isPtySupported()) {
72986 return array(
72987 array('pty'),
72988 array('pty'),
72989 array('pty'),
72990 );
72991 }
72992
72993 return array(
72994 array('pipe', 'r'),
72995 array('pipe', 'w'), 
72996  array('pipe', 'w'), 
72997  );
72998 }
72999
73000
73001
73002
73003 public function getFiles()
73004 {
73005 return array();
73006 }
73007
73008
73009
73010
73011 public function readAndWrite($blocking, $close = false)
73012 {
73013 $this->unblock();
73014 $w = $this->write();
73015
73016 $read = $e = array();
73017 $r = $this->pipes;
73018 unset($r[0]);
73019
73020
73021  if (($r || $w) && false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
73022
73023  
73024  if (!$this->hasSystemCallBeenInterrupted()) {
73025 $this->pipes = array();
73026 }
73027
73028 return $read;
73029 }
73030
73031 foreach ($r as $pipe) {
73032
73033  
73034  $read[$type = array_search($pipe, $this->pipes, true)] = '';
73035
73036 do {
73037 $data = fread($pipe, self::CHUNK_SIZE);
73038 $read[$type] .= $data;
73039 } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
73040
73041 if (!isset($read[$type][0])) {
73042 unset($read[$type]);
73043 }
73044
73045 if ($close && feof($pipe)) {
73046 fclose($pipe);
73047 unset($this->pipes[$type]);
73048 }
73049 }
73050
73051 return $read;
73052 }
73053
73054
73055
73056
73057 public function areOpen()
73058 {
73059 return (bool) $this->pipes;
73060 }
73061
73062
73063
73064
73065
73066
73067
73068
73069
73070 public static function create(Process $process, $input)
73071 {
73072 return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
73073 }
73074 }
73075 <?php
73076
73077
73078
73079
73080
73081
73082
73083
73084
73085
73086 namespace Symfony\Component\Process\Pipes;
73087
73088 use Symfony\Component\Process\Process;
73089 use Symfony\Component\Process\Exception\RuntimeException;
73090
73091
73092
73093
73094
73095
73096
73097
73098
73099
73100
73101 class WindowsPipes extends AbstractPipes
73102 {
73103 private $files = array();
73104 private $fileHandles = array();
73105 private $readBytes = array(
73106 Process::STDOUT => 0,
73107 Process::STDERR => 0,
73108 );
73109 private $disableOutput;
73110
73111 public function __construct($disableOutput, $input)
73112 {
73113 $this->disableOutput = (bool) $disableOutput;
73114
73115 if (!$this->disableOutput) {
73116
73117  
73118  
73119  
73120  $pipes = array(
73121 Process::STDOUT => Process::OUT,
73122 Process::STDERR => Process::ERR,
73123 );
73124 $tmpCheck = false;
73125 $tmpDir = sys_get_temp_dir();
73126 $lastError = 'unknown reason';
73127 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
73128 for ($i = 0;; ++$i) {
73129 foreach ($pipes as $pipe => $name) {
73130 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
73131 if (file_exists($file) && !unlink($file)) {
73132 continue 2;
73133 }
73134 $h = fopen($file, 'xb');
73135 if (!$h) {
73136 $error = $lastError;
73137 if ($tmpCheck || $tmpCheck = unlink(tempnam(false, 'sf_check_'))) {
73138 continue;
73139 }
73140 restore_error_handler();
73141 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error));
73142 }
73143 if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) {
73144 continue 2;
73145 }
73146 if (isset($this->files[$pipe])) {
73147 unlink($this->files[$pipe]);
73148 }
73149 $this->files[$pipe] = $file;
73150 }
73151 break;
73152 }
73153 restore_error_handler();
73154 }
73155
73156 parent::__construct($input);
73157 }
73158
73159 public function __destruct()
73160 {
73161 $this->close();
73162 $this->removeFiles();
73163 }
73164
73165
73166
73167
73168 public function getDescriptors()
73169 {
73170 if ($this->disableOutput) {
73171 $nullstream = fopen('NUL', 'c');
73172
73173 return array(
73174 array('pipe', 'r'),
73175 $nullstream,
73176 $nullstream,
73177 );
73178 }
73179
73180
73181  
73182  
73183  return array(
73184 array('pipe', 'r'),
73185 array('file', 'NUL', 'w'),
73186 array('file', 'NUL', 'w'),
73187 );
73188 }
73189
73190
73191
73192
73193 public function getFiles()
73194 {
73195 return $this->files;
73196 }
73197
73198
73199
73200
73201 public function readAndWrite($blocking, $close = false)
73202 {
73203 $this->unblock();
73204 $w = $this->write();
73205 $read = $r = $e = array();
73206
73207 if ($blocking) {
73208 if ($w) {
73209 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
73210 } elseif ($this->fileHandles) {
73211 usleep(Process::TIMEOUT_PRECISION * 1E6);
73212 }
73213 }
73214 foreach ($this->fileHandles as $type => $fileHandle) {
73215 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
73216
73217 if (isset($data[0])) {
73218 $this->readBytes[$type] += strlen($data);
73219 $read[$type] = $data;
73220 }
73221 if ($close) {
73222 fclose($fileHandle);
73223 unset($this->fileHandles[$type]);
73224 }
73225 }
73226
73227 return $read;
73228 }
73229
73230
73231
73232
73233 public function areOpen()
73234 {
73235 return $this->pipes && $this->fileHandles;
73236 }
73237
73238
73239
73240
73241 public function close()
73242 {
73243 parent::close();
73244 foreach ($this->fileHandles as $handle) {
73245 fclose($handle);
73246 }
73247 $this->fileHandles = array();
73248 }
73249
73250
73251
73252
73253
73254
73255
73256
73257
73258 public static function create(Process $process, $input)
73259 {
73260 return new static($process->isOutputDisabled(), $input);
73261 }
73262
73263
73264
73265
73266 private function removeFiles()
73267 {
73268 foreach ($this->files as $filename) {
73269 if (file_exists($filename)) {
73270 @unlink($filename);
73271 }
73272 }
73273 $this->files = array();
73274 }
73275 }
73276 <?php
73277
73278
73279
73280
73281
73282
73283
73284
73285
73286
73287 namespace Symfony\Component\Process;
73288
73289 use Symfony\Component\Process\Exception\InvalidArgumentException;
73290 use Symfony\Component\Process\Exception\LogicException;
73291 use Symfony\Component\Process\Exception\ProcessFailedException;
73292 use Symfony\Component\Process\Exception\ProcessTimedOutException;
73293 use Symfony\Component\Process\Exception\RuntimeException;
73294 use Symfony\Component\Process\Pipes\PipesInterface;
73295 use Symfony\Component\Process\Pipes\UnixPipes;
73296 use Symfony\Component\Process\Pipes\WindowsPipes;
73297
73298
73299
73300
73301
73302
73303
73304
73305 class Process
73306 {
73307 const ERR = 'err';
73308 const OUT = 'out';
73309
73310 const STATUS_READY = 'ready';
73311 const STATUS_STARTED = 'started';
73312 const STATUS_TERMINATED = 'terminated';
73313
73314 const STDIN = 0;
73315 const STDOUT = 1;
73316 const STDERR = 2;
73317
73318
73319  const TIMEOUT_PRECISION = 0.2;
73320
73321 private $callback;
73322 private $commandline;
73323 private $cwd;
73324 private $env;
73325 private $input;
73326 private $starttime;
73327 private $lastOutputTime;
73328 private $timeout;
73329 private $idleTimeout;
73330 private $options;
73331 private $exitcode;
73332 private $fallbackStatus = array();
73333 private $processInformation;
73334 private $outputDisabled = false;
73335 private $stdout;
73336 private $stderr;
73337 private $enhanceWindowsCompatibility = true;
73338 private $enhanceSigchildCompatibility;
73339 private $process;
73340 private $status = self::STATUS_READY;
73341 private $incrementalOutputOffset = 0;
73342 private $incrementalErrorOutputOffset = 0;
73343 private $tty;
73344 private $pty;
73345
73346 private $useFileHandles = false;
73347
73348 private $processPipes;
73349
73350 private $latestSignal;
73351
73352 private static $sigchild;
73353
73354
73355
73356
73357
73358
73359 public static $exitCodes = array(
73360 0 => 'OK',
73361 1 => 'General error',
73362 2 => 'Misuse of shell builtins',
73363
73364 126 => 'Invoked command cannot execute',
73365 127 => 'Command not found',
73366 128 => 'Invalid exit argument',
73367
73368
73369  129 => 'Hangup',
73370 130 => 'Interrupt',
73371 131 => 'Quit and dump core',
73372 132 => 'Illegal instruction',
73373 133 => 'Trace/breakpoint trap',
73374 134 => 'Process aborted',
73375 135 => 'Bus error: "access to undefined portion of memory object"',
73376 136 => 'Floating point exception: "erroneous arithmetic operation"',
73377 137 => 'Kill (terminate immediately)',
73378 138 => 'User-defined 1',
73379 139 => 'Segmentation violation',
73380 140 => 'User-defined 2',
73381 141 => 'Write to pipe with no one reading',
73382 142 => 'Signal raised by alarm',
73383 143 => 'Termination (request to terminate)',
73384
73385  145 => 'Child process terminated, stopped (or continued*)',
73386 146 => 'Continue if stopped',
73387 147 => 'Stop executing temporarily',
73388 148 => 'Terminal stop signal',
73389 149 => 'Background process attempting to read from tty ("in")',
73390 150 => 'Background process attempting to write to tty ("out")',
73391 151 => 'Urgent data available on socket',
73392 152 => 'CPU time limit exceeded',
73393 153 => 'File size limit exceeded',
73394 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
73395 155 => 'Profiling timer expired',
73396
73397  157 => 'Pollable event',
73398
73399  159 => 'Bad syscall',
73400 );
73401
73402
73403
73404
73405
73406
73407
73408
73409
73410
73411
73412 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
73413 {
73414 if (!function_exists('proc_open')) {
73415 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
73416 }
73417
73418 $this->commandline = $commandline;
73419 $this->cwd = $cwd;
73420
73421
73422  
73423  
73424  
73425  if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || '\\' === DIRECTORY_SEPARATOR)) {
73426 $this->cwd = getcwd();
73427 }
73428 if (null !== $env) {
73429 $this->setEnv($env);
73430 }
73431
73432 $this->setInput($input);
73433 $this->setTimeout($timeout);
73434 $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR;
73435 $this->pty = false;
73436 $this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
73437 $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
73438 }
73439
73440 public function __destruct()
73441 {
73442 $this->stop(0);
73443 }
73444
73445 public function __clone()
73446 {
73447 $this->resetProcessData();
73448 }
73449
73450
73451
73452
73453
73454
73455
73456
73457
73458
73459
73460
73461
73462
73463
73464
73465
73466
73467
73468
73469 public function run($callback = null)
73470 {
73471 $this->start($callback);
73472
73473 return $this->wait();
73474 }
73475
73476
73477
73478
73479
73480
73481
73482
73483
73484
73485
73486
73487
73488
73489 public function mustRun($callback = null)
73490 {
73491 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73492 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
73493 }
73494
73495 if (0 !== $this->run($callback)) {
73496 throw new ProcessFailedException($this);
73497 }
73498
73499 return $this;
73500 }
73501
73502
73503
73504
73505
73506
73507
73508
73509
73510
73511
73512
73513
73514
73515
73516
73517
73518
73519
73520
73521 public function start($callback = null)
73522 {
73523 if ($this->isRunning()) {
73524 throw new RuntimeException('Process is already running');
73525 }
73526 if ($this->outputDisabled && null !== $callback) {
73527 throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
73528 }
73529
73530 $this->resetProcessData();
73531 $this->starttime = $this->lastOutputTime = microtime(true);
73532 $this->callback = $this->buildCallback($callback);
73533 $descriptors = $this->getDescriptors();
73534
73535 $commandline = $this->commandline;
73536
73537 if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
73538 $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')';
73539 foreach ($this->processPipes->getFiles() as $offset => $filename) {
73540 $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
73541 }
73542 $commandline .= '"';
73543
73544 if (!isset($this->options['bypass_shell'])) {
73545 $this->options['bypass_shell'] = true;
73546 }
73547 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73548
73549  $descriptors[3] = array('pipe', 'w');
73550
73551
73552  $commandline = '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
73553 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
73554
73555
73556  
73557  $ptsWorkaround = fopen(__FILE__, 'r');
73558 }
73559
73560 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
73561
73562 if (!is_resource($this->process)) {
73563 throw new RuntimeException('Unable to launch a new process.');
73564 }
73565 $this->status = self::STATUS_STARTED;
73566
73567 if (isset($descriptors[3])) {
73568 $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
73569 }
73570
73571 if ($this->tty) {
73572 return;
73573 }
73574
73575 $this->updateStatus(false);
73576 $this->checkTimeout();
73577 }
73578
73579
73580
73581
73582
73583
73584
73585
73586
73587
73588
73589
73590
73591
73592
73593
73594 public function restart($callback = null)
73595 {
73596 if ($this->isRunning()) {
73597 throw new RuntimeException('Process is already running');
73598 }
73599
73600 $process = clone $this;
73601 $process->start($callback);
73602
73603 return $process;
73604 }
73605
73606
73607
73608
73609
73610
73611
73612
73613
73614
73615
73616
73617
73618
73619
73620
73621 public function wait($callback = null)
73622 {
73623 $this->requireProcessIsStarted(__FUNCTION__);
73624
73625 $this->updateStatus(false);
73626 if (null !== $callback) {
73627 $this->callback = $this->buildCallback($callback);
73628 }
73629
73630 do {
73631 $this->checkTimeout();
73632 $running = '\\' === DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
73633 $this->readPipes($running, '\\' !== DIRECTORY_SEPARATOR || !$running);
73634 } while ($running);
73635
73636 while ($this->isRunning()) {
73637 usleep(1000);
73638 }
73639
73640 if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
73641 throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
73642 }
73643
73644 return $this->exitcode;
73645 }
73646
73647
73648
73649
73650
73651
73652 public function getPid()
73653 {
73654 return $this->isRunning() ? $this->processInformation['pid'] : null;
73655 }
73656
73657
73658
73659
73660
73661
73662
73663
73664
73665
73666
73667
73668 public function signal($signal)
73669 {
73670 $this->doSignal($signal, true);
73671
73672 return $this;
73673 }
73674
73675
73676
73677
73678
73679
73680
73681
73682
73683 public function disableOutput()
73684 {
73685 if ($this->isRunning()) {
73686 throw new RuntimeException('Disabling output while the process is running is not possible.');
73687 }
73688 if (null !== $this->idleTimeout) {
73689 throw new LogicException('Output can not be disabled while an idle timeout is set.');
73690 }
73691
73692 $this->outputDisabled = true;
73693
73694 return $this;
73695 }
73696
73697
73698
73699
73700
73701
73702
73703
73704 public function enableOutput()
73705 {
73706 if ($this->isRunning()) {
73707 throw new RuntimeException('Enabling output while the process is running is not possible.');
73708 }
73709
73710 $this->outputDisabled = false;
73711
73712 return $this;
73713 }
73714
73715
73716
73717
73718
73719
73720 public function isOutputDisabled()
73721 {
73722 return $this->outputDisabled;
73723 }
73724
73725
73726
73727
73728
73729
73730
73731
73732
73733 public function getOutput()
73734 {
73735 $this->readPipesForOutput(__FUNCTION__);
73736
73737 if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
73738 return '';
73739 }
73740
73741 return $ret;
73742 }
73743
73744
73745
73746
73747
73748
73749
73750
73751
73752
73753
73754
73755 public function getIncrementalOutput()
73756 {
73757 $this->readPipesForOutput(__FUNCTION__);
73758
73759 $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
73760 $this->incrementalOutputOffset = ftell($this->stdout);
73761
73762 if (false === $latest) {
73763 return '';
73764 }
73765
73766 return $latest;
73767 }
73768
73769
73770
73771
73772
73773
73774 public function clearOutput()
73775 {
73776 ftruncate($this->stdout, 0);
73777 fseek($this->stdout, 0);
73778 $this->incrementalOutputOffset = 0;
73779
73780 return $this;
73781 }
73782
73783
73784
73785
73786
73787
73788
73789
73790
73791 public function getErrorOutput()
73792 {
73793 $this->readPipesForOutput(__FUNCTION__);
73794
73795 if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
73796 return '';
73797 }
73798
73799 return $ret;
73800 }
73801
73802
73803
73804
73805
73806
73807
73808
73809
73810
73811
73812
73813
73814 public function getIncrementalErrorOutput()
73815 {
73816 $this->readPipesForOutput(__FUNCTION__);
73817
73818 $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
73819 $this->incrementalErrorOutputOffset = ftell($this->stderr);
73820
73821 if (false === $latest) {
73822 return '';
73823 }
73824
73825 return $latest;
73826 }
73827
73828
73829
73830
73831
73832
73833 public function clearErrorOutput()
73834 {
73835 ftruncate($this->stderr, 0);
73836 fseek($this->stderr, 0);
73837 $this->incrementalErrorOutputOffset = 0;
73838
73839 return $this;
73840 }
73841
73842
73843
73844
73845
73846
73847
73848
73849 public function getExitCode()
73850 {
73851 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73852 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
73853 }
73854
73855 $this->updateStatus(false);
73856
73857 return $this->exitcode;
73858 }
73859
73860
73861
73862
73863
73864
73865
73866
73867
73868
73869
73870
73871 public function getExitCodeText()
73872 {
73873 if (null === $exitcode = $this->getExitCode()) {
73874 return;
73875 }
73876
73877 return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
73878 }
73879
73880
73881
73882
73883
73884
73885 public function isSuccessful()
73886 {
73887 return 0 === $this->getExitCode();
73888 }
73889
73890
73891
73892
73893
73894
73895
73896
73897
73898
73899
73900 public function hasBeenSignaled()
73901 {
73902 $this->requireProcessIsTerminated(__FUNCTION__);
73903
73904 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73905 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
73906 }
73907
73908 return $this->processInformation['signaled'];
73909 }
73910
73911
73912
73913
73914
73915
73916
73917
73918
73919
73920
73921 public function getTermSignal()
73922 {
73923 $this->requireProcessIsTerminated(__FUNCTION__);
73924
73925 if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) {
73926 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
73927 }
73928
73929 return $this->processInformation['termsig'];
73930 }
73931
73932
73933
73934
73935
73936
73937
73938
73939
73940
73941 public function hasBeenStopped()
73942 {
73943 $this->requireProcessIsTerminated(__FUNCTION__);
73944
73945 return $this->processInformation['stopped'];
73946 }
73947
73948
73949
73950
73951
73952
73953
73954
73955
73956
73957 public function getStopSignal()
73958 {
73959 $this->requireProcessIsTerminated(__FUNCTION__);
73960
73961 return $this->processInformation['stopsig'];
73962 }
73963
73964
73965
73966
73967
73968
73969 public function isRunning()
73970 {
73971 if (self::STATUS_STARTED !== $this->status) {
73972 return false;
73973 }
73974
73975 $this->updateStatus(false);
73976
73977 return $this->processInformation['running'];
73978 }
73979
73980
73981
73982
73983
73984
73985 public function isStarted()
73986 {
73987 return self::STATUS_READY != $this->status;
73988 }
73989
73990
73991
73992
73993
73994
73995 public function isTerminated()
73996 {
73997 $this->updateStatus(false);
73998
73999 return self::STATUS_TERMINATED == $this->status;
74000 }
74001
74002
74003
74004
74005
74006
74007
74008
74009 public function getStatus()
74010 {
74011 $this->updateStatus(false);
74012
74013 return $this->status;
74014 }
74015
74016
74017
74018
74019
74020
74021
74022
74023
74024 public function stop($timeout = 10, $signal = null)
74025 {
74026 $timeoutMicro = microtime(true) + $timeout;
74027 if ($this->isRunning()) {
74028
74029  $this->doSignal(15, false);
74030 do {
74031 usleep(1000);
74032 } while ($this->isRunning() && microtime(true) < $timeoutMicro);
74033
74034 if ($this->isRunning()) {
74035
74036  
74037  $this->doSignal($signal ?: 9, false);
74038 }
74039 }
74040
74041 if ($this->isRunning()) {
74042 if (isset($this->fallbackStatus['pid'])) {
74043 unset($this->fallbackStatus['pid']);
74044
74045 return $this->stop(0, $signal);
74046 }
74047 $this->close();
74048 }
74049
74050 return $this->exitcode;
74051 }
74052
74053
74054
74055
74056
74057
74058
74059
74060 public function addOutput($line)
74061 {
74062 $this->lastOutputTime = microtime(true);
74063
74064 fseek($this->stdout, 0, SEEK_END);
74065 fwrite($this->stdout, $line);
74066 fseek($this->stdout, $this->incrementalOutputOffset);
74067 }
74068
74069
74070
74071
74072
74073
74074
74075
74076 public function addErrorOutput($line)
74077 {
74078 $this->lastOutputTime = microtime(true);
74079
74080 fseek($this->stderr, 0, SEEK_END);
74081 fwrite($this->stderr, $line);
74082 fseek($this->stderr, $this->incrementalErrorOutputOffset);
74083 }
74084
74085
74086
74087
74088
74089
74090 public function getCommandLine()
74091 {
74092 return $this->commandline;
74093 }
74094
74095
74096
74097
74098
74099
74100
74101
74102 public function setCommandLine($commandline)
74103 {
74104 $this->commandline = $commandline;
74105
74106 return $this;
74107 }
74108
74109
74110
74111
74112
74113
74114 public function getTimeout()
74115 {
74116 return $this->timeout;
74117 }
74118
74119
74120
74121
74122
74123
74124 public function getIdleTimeout()
74125 {
74126 return $this->idleTimeout;
74127 }
74128
74129
74130
74131
74132
74133
74134
74135
74136
74137
74138
74139
74140 public function setTimeout($timeout)
74141 {
74142 $this->timeout = $this->validateTimeout($timeout);
74143
74144 return $this;
74145 }
74146
74147
74148
74149
74150
74151
74152
74153
74154
74155
74156
74157
74158
74159 public function setIdleTimeout($timeout)
74160 {
74161 if (null !== $timeout && $this->outputDisabled) {
74162 throw new LogicException('Idle timeout can not be set while the output is disabled.');
74163 }
74164
74165 $this->idleTimeout = $this->validateTimeout($timeout);
74166
74167 return $this;
74168 }
74169
74170
74171
74172
74173
74174
74175
74176
74177
74178
74179 public function setTty($tty)
74180 {
74181 if ('\\' === DIRECTORY_SEPARATOR && $tty) {
74182 throw new RuntimeException('TTY mode is not supported on Windows platform.');
74183 }
74184 if ($tty) {
74185 static $isTtySupported;
74186
74187 if (null === $isTtySupported) {
74188 $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);
74189 }
74190
74191 if (!$isTtySupported) {
74192 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
74193 }
74194 }
74195
74196 $this->tty = (bool) $tty;
74197
74198 return $this;
74199 }
74200
74201
74202
74203
74204
74205
74206 public function isTty()
74207 {
74208 return $this->tty;
74209 }
74210
74211
74212
74213
74214
74215
74216
74217
74218 public function setPty($bool)
74219 {
74220 $this->pty = (bool) $bool;
74221
74222 return $this;
74223 }
74224
74225
74226
74227
74228
74229
74230 public function isPty()
74231 {
74232 return $this->pty;
74233 }
74234
74235
74236
74237
74238
74239
74240 public function getWorkingDirectory()
74241 {
74242 if (null === $this->cwd) {
74243
74244  
74245  return getcwd() ?: null;
74246 }
74247
74248 return $this->cwd;
74249 }
74250
74251
74252
74253
74254
74255
74256
74257
74258 public function setWorkingDirectory($cwd)
74259 {
74260 $this->cwd = $cwd;
74261
74262 return $this;
74263 }
74264
74265
74266
74267
74268
74269
74270 public function getEnv()
74271 {
74272 return $this->env;
74273 }
74274
74275
74276
74277
74278
74279
74280
74281
74282
74283
74284
74285
74286
74287
74288 public function setEnv(array $env)
74289 {
74290
74291  $env = array_filter($env, function ($value) {
74292 return !is_array($value);
74293 });
74294
74295 $this->env = array();
74296 foreach ($env as $key => $value) {
74297 $this->env[$key] = (string) $value;
74298 }
74299
74300 return $this;
74301 }
74302
74303
74304
74305
74306
74307
74308
74309
74310
74311
74312 public function getStdin()
74313 {
74314 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0. Use the getInput() method instead.', E_USER_DEPRECATED);
74315
74316 return $this->getInput();
74317 }
74318
74319
74320
74321
74322
74323
74324 public function getInput()
74325 {
74326 return $this->input;
74327 }
74328
74329
74330
74331
74332
74333
74334
74335
74336
74337
74338
74339
74340
74341
74342 public function setStdin($stdin)
74343 {
74344 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0. Use the setInput() method instead.', E_USER_DEPRECATED);
74345
74346 return $this->setInput($stdin);
74347 }
74348
74349
74350
74351
74352
74353
74354
74355
74356
74357
74358
74359
74360
74361
74362 public function setInput($input)
74363 {
74364 if ($this->isRunning()) {
74365 throw new LogicException('Input can not be set while the process is running.');
74366 }
74367
74368 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
74369
74370 return $this;
74371 }
74372
74373
74374
74375
74376
74377
74378 public function getOptions()
74379 {
74380 return $this->options;
74381 }
74382
74383
74384
74385
74386
74387
74388
74389
74390 public function setOptions(array $options)
74391 {
74392 $this->options = $options;
74393
74394 return $this;
74395 }
74396
74397
74398
74399
74400
74401
74402
74403
74404 public function getEnhanceWindowsCompatibility()
74405 {
74406 return $this->enhanceWindowsCompatibility;
74407 }
74408
74409
74410
74411
74412
74413
74414
74415
74416 public function setEnhanceWindowsCompatibility($enhance)
74417 {
74418 $this->enhanceWindowsCompatibility = (bool) $enhance;
74419
74420 return $this;
74421 }
74422
74423
74424
74425
74426
74427
74428 public function getEnhanceSigchildCompatibility()
74429 {
74430 return $this->enhanceSigchildCompatibility;
74431 }
74432
74433
74434
74435
74436
74437
74438
74439
74440
74441
74442
74443
74444 public function setEnhanceSigchildCompatibility($enhance)
74445 {
74446 $this->enhanceSigchildCompatibility = (bool) $enhance;
74447
74448 return $this;
74449 }
74450
74451
74452
74453
74454
74455
74456
74457
74458
74459 public function checkTimeout()
74460 {
74461 if (self::STATUS_STARTED !== $this->status) {
74462 return;
74463 }
74464
74465 if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
74466 $this->stop(0);
74467
74468 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
74469 }
74470
74471 if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
74472 $this->stop(0);
74473
74474 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
74475 }
74476 }
74477
74478
74479
74480
74481
74482
74483 public static function isPtySupported()
74484 {
74485 static $result;
74486
74487 if (null !== $result) {
74488 return $result;
74489 }
74490
74491 if ('\\' === DIRECTORY_SEPARATOR) {
74492 return $result = false;
74493 }
74494
74495 return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes);
74496 }
74497
74498
74499
74500
74501
74502
74503 private function getDescriptors()
74504 {
74505 if ('\\' === DIRECTORY_SEPARATOR) {
74506 $this->processPipes = WindowsPipes::create($this, $this->input);
74507 } else {
74508 $this->processPipes = UnixPipes::create($this, $this->input);
74509 }
74510
74511 return $this->processPipes->getDescriptors();
74512 }
74513
74514
74515
74516
74517
74518
74519
74520
74521
74522
74523
74524 protected function buildCallback($callback)
74525 {
74526 $that = $this;
74527 $out = self::OUT;
74528 $callback = function ($type, $data) use ($that, $callback, $out) {
74529 if ($out == $type) {
74530 $that->addOutput($data);
74531 } else {
74532 $that->addErrorOutput($data);
74533 }
74534
74535 if (null !== $callback) {
74536 call_user_func($callback, $type, $data);
74537 }
74538 };
74539
74540 return $callback;
74541 }
74542
74543
74544
74545
74546
74547
74548 protected function updateStatus($blocking)
74549 {
74550 if (self::STATUS_STARTED !== $this->status) {
74551 return;
74552 }
74553
74554 $this->processInformation = proc_get_status($this->process);
74555 $running = $this->processInformation['running'];
74556
74557 $this->readPipes($running && $blocking, '\\' !== DIRECTORY_SEPARATOR || !$running);
74558
74559 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
74560 $this->processInformation = $this->fallbackStatus + $this->processInformation;
74561 }
74562
74563 if (!$running) {
74564 $this->close();
74565 }
74566 }
74567
74568
74569
74570
74571
74572
74573 protected function isSigchildEnabled()
74574 {
74575 if (null !== self::$sigchild) {
74576 return self::$sigchild;
74577 }
74578
74579 if (!function_exists('phpinfo') || defined('HHVM_VERSION')) {
74580 return self::$sigchild = false;
74581 }
74582
74583 ob_start();
74584 phpinfo(INFO_GENERAL);
74585
74586 return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
74587 }
74588
74589
74590
74591
74592
74593
74594
74595
74596 private function readPipesForOutput($caller)
74597 {
74598 if ($this->outputDisabled) {
74599 throw new LogicException('Output has been disabled.');
74600 }
74601
74602 $this->requireProcessIsStarted($caller);
74603
74604 $this->updateStatus(false);
74605 }
74606
74607
74608
74609
74610
74611
74612
74613
74614
74615
74616 private function validateTimeout($timeout)
74617 {
74618 $timeout = (float) $timeout;
74619
74620 if (0.0 === $timeout) {
74621 $timeout = null;
74622 } elseif ($timeout < 0) {
74623 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
74624 }
74625
74626 return $timeout;
74627 }
74628
74629
74630
74631
74632
74633
74634
74635 private function readPipes($blocking, $close)
74636 {
74637 $result = $this->processPipes->readAndWrite($blocking, $close);
74638
74639 $callback = $this->callback;
74640 foreach ($result as $type => $data) {
74641 if (3 !== $type) {
74642 $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);
74643 } elseif (!isset($this->fallbackStatus['signaled'])) {
74644 $this->fallbackStatus['exitcode'] = (int) $data;
74645 }
74646 }
74647 }
74648
74649
74650
74651
74652
74653
74654 private function close()
74655 {
74656 $this->processPipes->close();
74657 if (is_resource($this->process)) {
74658 proc_close($this->process);
74659 }
74660 $this->exitcode = $this->processInformation['exitcode'];
74661 $this->status = self::STATUS_TERMINATED;
74662
74663 if (-1 === $this->exitcode) {
74664 if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
74665
74666  $this->exitcode = 128 + $this->processInformation['termsig'];
74667 } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
74668 $this->processInformation['signaled'] = true;
74669 $this->processInformation['termsig'] = -1;
74670 }
74671 }
74672
74673
74674  
74675  
74676  $this->callback = null;
74677
74678 return $this->exitcode;
74679 }
74680
74681
74682
74683
74684 private function resetProcessData()
74685 {
74686 $this->starttime = null;
74687 $this->callback = null;
74688 $this->exitcode = null;
74689 $this->fallbackStatus = array();
74690 $this->processInformation = null;
74691 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
74692 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
74693 $this->process = null;
74694 $this->latestSignal = null;
74695 $this->status = self::STATUS_READY;
74696 $this->incrementalOutputOffset = 0;
74697 $this->incrementalErrorOutputOffset = 0;
74698 }
74699
74700
74701
74702
74703
74704
74705
74706
74707
74708
74709
74710
74711
74712 private function doSignal($signal, $throwException)
74713 {
74714 if (null === $pid = $this->getPid()) {
74715 if ($throwException) {
74716 throw new LogicException('Can not send signal on a non running process.');
74717 }
74718
74719 return false;
74720 }
74721
74722 if ('\\' === DIRECTORY_SEPARATOR) {
74723 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
74724 if ($exitCode && $this->isRunning()) {
74725 if ($throwException) {
74726 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
74727 }
74728
74729 return false;
74730 }
74731 } else {
74732 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
74733 $ok = @proc_terminate($this->process, $signal);
74734 } elseif (function_exists('posix_kill')) {
74735 $ok = @posix_kill($pid, $signal);
74736 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
74737 $ok = false === fgets($pipes[2]);
74738 }
74739 if (!$ok) {
74740 if ($throwException) {
74741 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
74742 }
74743
74744 return false;
74745 }
74746 }
74747
74748 $this->latestSignal = (int) $signal;
74749 $this->fallbackStatus['signaled'] = true;
74750 $this->fallbackStatus['exitcode'] = -1;
74751 $this->fallbackStatus['termsig'] = $this->latestSignal;
74752
74753 return true;
74754 }
74755
74756
74757
74758
74759
74760
74761
74762
74763 private function requireProcessIsStarted($functionName)
74764 {
74765 if (!$this->isStarted()) {
74766 throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
74767 }
74768 }
74769
74770
74771
74772
74773
74774
74775
74776
74777 private function requireProcessIsTerminated($functionName)
74778 {
74779 if (!$this->isTerminated()) {
74780 throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
74781 }
74782 }
74783 }
74784 <?php
74785
74786
74787
74788
74789
74790
74791
74792
74793
74794
74795 namespace Symfony\Component\Process;
74796
74797 use Symfony\Component\Process\Exception\InvalidArgumentException;
74798 use Symfony\Component\Process\Exception\LogicException;
74799
74800
74801
74802
74803 class ProcessBuilder
74804 {
74805 private $arguments;
74806 private $cwd;
74807 private $env = array();
74808 private $input;
74809 private $timeout = 60;
74810 private $options = array();
74811 private $inheritEnv = true;
74812 private $prefix = array();
74813 private $outputDisabled = false;
74814
74815
74816
74817
74818 public function __construct(array $arguments = array())
74819 {
74820 $this->arguments = $arguments;
74821 }
74822
74823
74824
74825
74826
74827
74828
74829
74830 public static function create(array $arguments = array())
74831 {
74832 return new static($arguments);
74833 }
74834
74835
74836
74837
74838
74839
74840
74841
74842 public function add($argument)
74843 {
74844 $this->arguments[] = $argument;
74845
74846 return $this;
74847 }
74848
74849
74850
74851
74852
74853
74854
74855
74856
74857
74858 public function setPrefix($prefix)
74859 {
74860 $this->prefix = is_array($prefix) ? $prefix : array($prefix);
74861
74862 return $this;
74863 }
74864
74865
74866
74867
74868
74869
74870
74871
74872
74873
74874
74875 public function setArguments(array $arguments)
74876 {
74877 $this->arguments = $arguments;
74878
74879 return $this;
74880 }
74881
74882
74883
74884
74885
74886
74887
74888
74889 public function setWorkingDirectory($cwd)
74890 {
74891 $this->cwd = $cwd;
74892
74893 return $this;
74894 }
74895
74896
74897
74898
74899
74900
74901
74902
74903 public function inheritEnvironmentVariables($inheritEnv = true)
74904 {
74905 $this->inheritEnv = $inheritEnv;
74906
74907 return $this;
74908 }
74909
74910
74911
74912
74913
74914
74915
74916
74917
74918
74919
74920
74921 public function setEnv($name, $value)
74922 {
74923 $this->env[$name] = $value;
74924
74925 return $this;
74926 }
74927
74928
74929
74930
74931
74932
74933
74934
74935
74936
74937
74938
74939 public function addEnvironmentVariables(array $variables)
74940 {
74941 $this->env = array_replace($this->env, $variables);
74942
74943 return $this;
74944 }
74945
74946
74947
74948
74949
74950
74951
74952
74953
74954
74955
74956
74957 public function setInput($input)
74958 {
74959 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
74960
74961 return $this;
74962 }
74963
74964
74965
74966
74967
74968
74969
74970
74971
74972
74973
74974
74975 public function setTimeout($timeout)
74976 {
74977 if (null === $timeout) {
74978 $this->timeout = null;
74979
74980 return $this;
74981 }
74982
74983 $timeout = (float) $timeout;
74984
74985 if ($timeout < 0) {
74986 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
74987 }
74988
74989 $this->timeout = $timeout;
74990
74991 return $this;
74992 }
74993
74994
74995
74996
74997
74998
74999
75000
75001
75002 public function setOption($name, $value)
75003 {
75004 $this->options[$name] = $value;
75005
75006 return $this;
75007 }
75008
75009
75010
75011
75012
75013
75014 public function disableOutput()
75015 {
75016 $this->outputDisabled = true;
75017
75018 return $this;
75019 }
75020
75021
75022
75023
75024
75025
75026 public function enableOutput()
75027 {
75028 $this->outputDisabled = false;
75029
75030 return $this;
75031 }
75032
75033
75034
75035
75036
75037
75038
75039
75040 public function getProcess()
75041 {
75042 if (0 === count($this->prefix) && 0 === count($this->arguments)) {
75043 throw new LogicException('You must add() command arguments before calling getProcess().');
75044 }
75045
75046 $options = $this->options;
75047
75048 $arguments = array_merge($this->prefix, $this->arguments);
75049 $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
75050
75051 if ($this->inheritEnv) {
75052
75053  $env = array_replace($_ENV, $_SERVER, $this->env);
75054 } else {
75055 $env = $this->env;
75056 }
75057
75058 $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
75059
75060 if ($this->outputDisabled) {
75061 $process->disableOutput();
75062 }
75063
75064 return $process;
75065 }
75066 }
75067 <?php
75068
75069
75070
75071
75072
75073
75074
75075
75076
75077
75078 namespace Symfony\Component\Process;
75079
75080 use Symfony\Component\Process\Exception\InvalidArgumentException;
75081
75082
75083
75084
75085
75086
75087
75088
75089 class ProcessUtils
75090 {
75091
75092
75093
75094 private function __construct()
75095 {
75096 }
75097
75098
75099
75100
75101
75102
75103
75104
75105 public static function escapeArgument($argument)
75106 {
75107
75108  
75109  
75110  
75111  if ('\\' === DIRECTORY_SEPARATOR) {
75112 if ('' === $argument) {
75113 return escapeshellarg($argument);
75114 }
75115
75116 $escapedArgument = '';
75117 $quote = false;
75118 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
75119 if ('"' === $part) {
75120 $escapedArgument .= '\\"';
75121 } elseif (self::isSurroundedBy($part, '%')) {
75122
75123  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
75124 } else {
75125
75126  if ('\\' === substr($part, -1)) {
75127 $part .= '\\';
75128 }
75129 $quote = true;
75130 $escapedArgument .= $part;
75131 }
75132 }
75133 if ($quote) {
75134 $escapedArgument = '"'.$escapedArgument.'"';
75135 }
75136
75137 return $escapedArgument;
75138 }
75139
75140 return "'".str_replace("'", "'\\''", $argument)."'";
75141 }
75142
75143
75144
75145
75146
75147
75148
75149
75150
75151
75152
75153
75154
75155 public static function validateInput($caller, $input)
75156 {
75157 if (null !== $input) {
75158 if (is_resource($input)) {
75159 return $input;
75160 }
75161 if (is_string($input)) {
75162 return $input;
75163 }
75164 if (is_scalar($input)) {
75165 return (string) $input;
75166 }
75167
75168  if (is_object($input) && method_exists($input, '__toString')) {
75169 @trigger_error('Passing an object as an input is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
75170
75171 return (string) $input;
75172 }
75173
75174 throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
75175 }
75176
75177 return $input;
75178 }
75179
75180 private static function isSurroundedBy($arg, $char)
75181 {
75182 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
75183 }
75184 }
75185 Copyright (c) 2011 Jordi Boggiano
75186
75187 Permission is hereby granted, free of charge, to any person obtaining a copy
75188 of this software and associated documentation files (the "Software"), to deal
75189 in the Software without restriction, including without limitation the rights
75190 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75191 copies of the Software, and to permit persons to whom the Software is furnished
75192 to do so, subject to the following conditions:
75193
75194 The above copyright notice and this permission notice shall be included in all
75195 copies or substantial portions of the Software.
75196
75197 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75198 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75199 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75200 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75201 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75202 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75203 THE SOFTWARE.
75204 <?php
75205
75206
75207
75208
75209
75210
75211
75212
75213
75214
75215 namespace Seld\JsonLint;
75216
75217 class DuplicateKeyException extends ParsingException
75218 {
75219 public function __construct($message, $key, array $details = array())
75220 {
75221 $details['key'] = $key;
75222 parent::__construct($message, $details);
75223 }
75224
75225 public function getKey()
75226 {
75227 return $this->details['key'];
75228 }
75229 }
75230 <?php
75231
75232
75233
75234
75235
75236
75237
75238
75239
75240
75241 namespace Seld\JsonLint;
75242 use stdClass;
75243
75244
75245
75246
75247
75248
75249
75250
75251
75252
75253
75254
75255
75256
75257 class JsonParser
75258 {
75259 const DETECT_KEY_CONFLICTS = 1;
75260 const ALLOW_DUPLICATE_KEYS = 2;
75261 const PARSE_TO_ASSOC = 4;
75262
75263 private $lexer;
75264
75265 private $flags;
75266 private $stack;
75267 private $vstack; 
75268  private $lstack; 
75269
75270 private $symbols = array(
75271 'error' => 2,
75272 'JSONString' => 3,
75273 'STRING' => 4,
75274 'JSONNumber' => 5,
75275 'NUMBER' => 6,
75276 'JSONNullLiteral' => 7,
75277 'NULL' => 8,
75278 'JSONBooleanLiteral' => 9,
75279 'TRUE' => 10,
75280 'FALSE' => 11,
75281 'JSONText' => 12,
75282 'JSONValue' => 13,
75283 'EOF' => 14,
75284 'JSONObject' => 15,
75285 'JSONArray' => 16,
75286 '{' => 17,
75287 '}' => 18,
75288 'JSONMemberList' => 19,
75289 'JSONMember' => 20,
75290 ':' => 21,
75291 ',' => 22,
75292 '[' => 23,
75293 ']' => 24,
75294 'JSONElementList' => 25,
75295 '$accept' => 0,
75296 '$end' => 1,
75297 );
75298
75299 private $terminals_ = array(
75300 2 => "error",
75301 4 => "STRING",
75302 6 => "NUMBER",
75303 8 => "NULL",
75304 10 => "TRUE",
75305 11 => "FALSE",
75306 14 => "EOF",
75307 17 => "{",
75308 18 => "}",
75309 21 => ":",
75310 22 => ",",
75311 23 => "[",
75312 24 => "]",
75313 );
75314
75315 private $productions_ = array(
75316 0,
75317 array(3, 1),
75318 array(5, 1),
75319 array(7, 1),
75320 array(9, 1),
75321 array(9, 1),
75322 array(12, 2),
75323 array(13, 1),
75324 array(13, 1),
75325 array(13, 1),
75326 array(13, 1),
75327 array(13, 1),
75328 array(13, 1),
75329 array(15, 2),
75330 array(15, 3),
75331 array(20, 3),
75332 array(19, 1),
75333 array(19, 3),
75334 array(16, 2),
75335 array(16, 3),
75336 array(25, 1),
75337 array(25, 3)
75338 );
75339
75340 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)),
75341 );
75342
75343 private $defaultActions = array(
75344 16 => array(2, 6)
75345 );
75346
75347
75348
75349
75350
75351
75352 public function lint($input, $flags = 0)
75353 {
75354 try {
75355 $this->parse($input, $flags);
75356 } catch (ParsingException $e) {
75357 return $e;
75358 }
75359 }
75360
75361
75362
75363
75364
75365
75366
75367 public function parse($input, $flags = 0)
75368 {
75369 $this->failOnBOM($input);
75370
75371 $this->flags = $flags;
75372
75373 $this->stack = array(0);
75374 $this->vstack = array(null);
75375 $this->lstack = array();
75376
75377 $yytext = '';
75378 $yylineno = 0;
75379 $yyleng = 0;
75380 $recovering = 0;
75381 $TERROR = 2;
75382 $EOF = 1;
75383
75384 $this->lexer = new Lexer();
75385 $this->lexer->setInput($input);
75386
75387 $yyloc = $this->lexer->yylloc;
75388 $this->lstack[] = $yyloc;
75389
75390 $symbol = null;
75391 $preErrorSymbol = null;
75392 $state = null;
75393 $action = null;
75394 $a = null;
75395 $r = null;
75396 $yyval = new stdClass;
75397 $p = null;
75398 $len = null;
75399 $newState = null;
75400 $expected = null;
75401 $errStr = null;
75402
75403 while (true) {
75404
75405  $state = $this->stack[count($this->stack)-1];
75406
75407
75408  if (isset($this->defaultActions[$state])) {
75409 $action = $this->defaultActions[$state];
75410 } else {
75411 if ($symbol == null) {
75412 $symbol = $this->lex();
75413 }
75414
75415  $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false;
75416 }
75417
75418
75419  if (!$action || !$action[0]) {
75420 if (!$recovering) {
75421
75422  $expected = array();
75423 foreach ($this->table[$state] as $p => $ignore) {
75424 if (isset($this->terminals_[$p]) && $p > 2) {
75425 $expected[] = "'" . $this->terminals_[$p] . "'";
75426 }
75427 }
75428
75429 $message = null;
75430 if (in_array("'STRING'", $expected) && in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
75431 $message = "Invalid string";
75432 if ("'" === substr($this->lexer->match, 0, 1)) {
75433 $message .= ", it appears you used single quotes instead of double quotes";
75434 } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u])}', $this->lexer->getUpcomingInput(), $match)) {
75435 $message .= ", it appears you have an unescaped backslash at: ".$match[1];
75436 } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getUpcomingInput())) {
75437 $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
75438 }
75439 }
75440
75441 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
75442 $errStr .= $this->lexer->showPosition() . "\n";
75443 if ($message) {
75444 $errStr .= $message;
75445 } else {
75446 $errStr .= (count($expected) > 1) ? "Expected one of: " : "Expected: ";
75447 $errStr .= implode(', ', $expected);
75448 }
75449
75450 if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
75451 $errStr .= " - It appears you have an extra trailing comma";
75452 }
75453
75454 $this->parseError($errStr, array(
75455 'text' => $this->lexer->match,
75456 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol,
75457 'line' => $this->lexer->yylineno,
75458 'loc' => $yyloc,
75459 'expected' => $expected,
75460 ));
75461 }
75462
75463
75464  if ($recovering == 3) {
75465 if ($symbol == $EOF) {
75466 throw new ParsingException($errStr ?: 'Parsing halted.');
75467 }
75468
75469
75470  $yyleng = $this->lexer->yyleng;
75471 $yytext = $this->lexer->yytext;
75472 $yylineno = $this->lexer->yylineno;
75473 $yyloc = $this->lexer->yylloc;
75474 $symbol = $this->lex();
75475 }
75476
75477
75478  while (true) {
75479
75480  if (array_key_exists($TERROR, $this->table[$state])) {
75481 break;
75482 }
75483 if ($state == 0) {
75484 throw new ParsingException($errStr ?: 'Parsing halted.');
75485 }
75486 $this->popStack(1);
75487 $state = $this->stack[count($this->stack)-1];
75488 }
75489
75490 $preErrorSymbol = $symbol; 
75491  $symbol = $TERROR; 
75492  $state = $this->stack[count($this->stack)-1];
75493 $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false;
75494 $recovering = 3; 
75495  }
75496
75497
75498  if (is_array($action[0]) && count($action) > 1) {
75499 throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
75500 }
75501
75502 switch ($action[0]) {
75503 case 1: 
75504  $this->stack[] = $symbol;
75505 $this->vstack[] = $this->lexer->yytext;
75506 $this->lstack[] = $this->lexer->yylloc;
75507 $this->stack[] = $action[1]; 
75508  $symbol = null;
75509 if (!$preErrorSymbol) { 
75510  $yyleng = $this->lexer->yyleng;
75511 $yytext = $this->lexer->yytext;
75512 $yylineno = $this->lexer->yylineno;
75513 $yyloc = $this->lexer->yylloc;
75514 if ($recovering > 0) {
75515 $recovering--;
75516 }
75517 } else { 
75518  $symbol = $preErrorSymbol;
75519 $preErrorSymbol = null;
75520 }
75521 break;
75522
75523 case 2: 
75524  $len = $this->productions_[$action[1]][1];
75525
75526
75527  $yyval->token = $this->vstack[count($this->vstack) - $len]; 
75528  
75529  $yyval->store = array( 
75530  'first_line' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_line'],
75531 'last_line' => $this->lstack[count($this->lstack) - 1]['last_line'],
75532 'first_column' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_column'],
75533 'last_column' => $this->lstack[count($this->lstack) - 1]['last_column'],
75534 );
75535 $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack, $this->lstack);
75536
75537 if (!$r instanceof Undefined) {
75538 return $r;
75539 }
75540
75541 if ($len) {
75542 $this->popStack($len);
75543 }
75544
75545 $this->stack[] = $this->productions_[$action[1]][0]; 
75546  $this->vstack[] = $yyval->token;
75547 $this->lstack[] = $yyval->store;
75548 $newState = $this->table[$this->stack[count($this->stack)-2]][$this->stack[count($this->stack)-1]];
75549 $this->stack[] = $newState;
75550 break;
75551
75552 case 3: 
75553
75554 return true;
75555 }
75556 }
75557
75558 return true;
75559 }
75560
75561 protected function parseError($str, $hash)
75562 {
75563 throw new ParsingException($str, $hash);
75564 }
75565
75566
75567  
75568  
75569  private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens)
75570 {
75571
75572  $len = count($tokens) - 1;
75573 switch ($yystate) {
75574 case 1:
75575 $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
75576 $yyval->token = $yytext;
75577 break;
75578 case 2:
75579 if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) {
75580 $yyval->token = floatval($yytext);
75581 } else {
75582 $yyval->token = strpos($yytext, '.') === false ? intval($yytext) : floatval($yytext);
75583 }
75584 break;
75585 case 3:
75586 $yyval->token = null;
75587 break;
75588 case 4:
75589 $yyval->token = true;
75590 break;
75591 case 5:
75592 $yyval->token = false;
75593 break;
75594 case 6:
75595 return $yyval->token = $tokens[$len-1];
75596 case 13:
75597 if ($this->flags & self::PARSE_TO_ASSOC) {
75598 $yyval->token = array();
75599 } else {
75600 $yyval->token = new stdClass;
75601 }
75602 break;
75603 case 14:
75604 $yyval->token = $tokens[$len-1];
75605 break;
75606 case 15:
75607 $yyval->token = array($tokens[$len-2], $tokens[$len]);
75608 break;
75609 case 16:
75610 if (PHP_VERSION_ID < 70100) {
75611 $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
75612 } else {
75613 $property = $tokens[$len][0];
75614 }
75615 if ($this->flags & self::PARSE_TO_ASSOC) {
75616 $yyval->token = array();
75617 $yyval->token[$property] = $tokens[$len][1];
75618 } else {
75619 $yyval->token = new stdClass;
75620 $yyval->token->$property = $tokens[$len][1];
75621 }
75622 break;
75623 case 17:
75624 if ($this->flags & self::PARSE_TO_ASSOC) {
75625 $yyval->token =& $tokens[$len-2];
75626 $key = $tokens[$len][0];
75627 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
75628 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
75629 $errStr .= $this->lexer->showPosition() . "\n";
75630 $errStr .= "Duplicate key: ".$tokens[$len][0];
75631 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
75632 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) {
75633 $duplicateCount = 1;
75634 do {
75635 $duplicateKey = $key . '.' . $duplicateCount++;
75636 } while (isset($tokens[$len-2][$duplicateKey]));
75637 $key = $duplicateKey;
75638 }
75639 $tokens[$len-2][$key] = $tokens[$len][1];
75640 } else {
75641 $yyval->token = $tokens[$len-2];
75642 if (PHP_VERSION_ID < 70100) {
75643 $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
75644 } else {
75645 $key = $tokens[$len][0];
75646 }
75647 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
75648 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
75649 $errStr .= $this->lexer->showPosition() . "\n";
75650 $errStr .= "Duplicate key: ".$tokens[$len][0];
75651 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
75652 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) {
75653 $duplicateCount = 1;
75654 do {
75655 $duplicateKey = $key . '.' . $duplicateCount++;
75656 } while (isset($tokens[$len-2]->$duplicateKey));
75657 $key = $duplicateKey;
75658 }
75659 $tokens[$len-2]->$key = $tokens[$len][1];
75660 }
75661 break;
75662 case 18:
75663 $yyval->token = array();
75664 break;
75665 case 19:
75666 $yyval->token = $tokens[$len-1];
75667 break;
75668 case 20:
75669 $yyval->token = array($tokens[$len]);
75670 break;
75671 case 21:
75672 $tokens[$len-2][] = $tokens[$len];
75673 $yyval->token = $tokens[$len-2];
75674 break;
75675 }
75676
75677 return new Undefined();
75678 }
75679
75680 private function stringInterpolation($match)
75681 {
75682 switch ($match[0]) {
75683 case '\\\\':
75684 return '\\';
75685 case '\"':
75686 return '"';
75687 case '\b':
75688 return chr(8);
75689 case '\f':
75690 return chr(12);
75691 case '\n':
75692 return "\n";
75693 case '\r':
75694 return "\r";
75695 case '\t':
75696 return "\t";
75697 case '\/':
75698 return "/";
75699 default:
75700 return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', 0, 'UTF-8');
75701 }
75702 }
75703
75704 private function popStack($n)
75705 {
75706 $this->stack = array_slice($this->stack, 0, - (2 * $n));
75707 $this->vstack = array_slice($this->vstack, 0, - $n);
75708 $this->lstack = array_slice($this->lstack, 0, - $n);
75709 }
75710
75711 private function lex()
75712 {
75713 $token = $this->lexer->lex() ?: 1; 
75714  
75715  if (!is_numeric($token)) {
75716 $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token;
75717 }
75718
75719 return $token;
75720 }
75721
75722 private function failOnBOM($input)
75723 {
75724
75725  $bom = "\xEF\xBB\xBF";
75726
75727 if (substr($input, 0, 3) === $bom) {
75728 $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array());
75729 }
75730 }
75731 }
75732 <?php
75733
75734
75735
75736
75737
75738
75739
75740
75741
75742
75743 namespace Seld\JsonLint;
75744
75745
75746
75747
75748
75749
75750 class Lexer
75751 {
75752 private $EOF = 1;
75753 private $rules = array(
75754 0 => '/^\s+/',
75755 1 => '/^-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/',
75756 2 => '{^"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x1f\\\\"]++)*+"}',
75757 3 => '/^\{/',
75758 4 => '/^\}/',
75759 5 => '/^\[/',
75760 6 => '/^\]/',
75761 7 => '/^,/',
75762 8 => '/^:/',
75763 9 => '/^true\b/',
75764 10 => '/^false\b/',
75765 11 => '/^null\b/',
75766 12 => '/^$/',
75767 13 => '/^./',
75768 );
75769
75770 private $conditions = array(
75771 "INITIAL" => array(
75772 "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13),
75773 "inclusive" => true,
75774 ),
75775 );
75776
75777 private $conditionStack;
75778 private $input;
75779 private $more;
75780 private $done;
75781 private $matched;
75782
75783 public $match;
75784 public $yylineno;
75785 public $yyleng;
75786 public $yytext;
75787 public $yylloc;
75788
75789 public function lex()
75790 {
75791 $r = $this->next();
75792 if (!$r instanceof Undefined) {
75793 return $r;
75794 }
75795
75796 return $this->lex();
75797 }
75798
75799 public function setInput($input)
75800 {
75801 $this->input = $input;
75802 $this->more = false;
75803 $this->done = false;
75804 $this->yylineno = $this->yyleng = 0;
75805 $this->yytext = $this->matched = $this->match = '';
75806 $this->conditionStack = array('INITIAL');
75807 $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
75808
75809 return $this;
75810 }
75811
75812 public function showPosition()
75813 {
75814 $pre = str_replace("\n", '', $this->getPastInput());
75815 $c = str_repeat('-', max(0, strlen($pre) - 1)); 
75816
75817 return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
75818 }
75819
75820 public function getPastInput()
75821 {
75822 $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match));
75823
75824 return (strlen($past) > 20 ? '...' : '') . substr($past, -20);
75825 }
75826
75827 public function getUpcomingInput()
75828 {
75829 $next = $this->match;
75830 if (strlen($next) < 20) {
75831 $next .= substr($this->input, 0, 20 - strlen($next));
75832 }
75833
75834 return substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '');
75835 }
75836
75837 protected function parseError($str, $hash)
75838 {
75839 throw new \Exception($str);
75840 }
75841
75842 private function next()
75843 {
75844 if ($this->done) {
75845 return $this->EOF;
75846 }
75847 if ($this->input === '') {
75848 $this->done = true;
75849 }
75850
75851 $token = null;
75852 $match = null;
75853 $col = null;
75854 $lines = null;
75855
75856 if (!$this->more) {
75857 $this->yytext = '';
75858 $this->match = '';
75859 }
75860
75861 $rules = $this->getCurrentRules();
75862 $rulesLen = count($rules);
75863
75864 for ($i=0; $i < $rulesLen; $i++) {
75865 if (preg_match($this->rules[$rules[$i]], $this->input, $match)) {
75866 preg_match_all('/\n.*/', $match[0], $lines);
75867 $lines = $lines[0];
75868 if ($lines) {
75869 $this->yylineno += count($lines);
75870 }
75871
75872 $this->yylloc = array(
75873 'first_line' => $this->yylloc['last_line'],
75874 'last_line' => $this->yylineno+1,
75875 'first_column' => $this->yylloc['last_column'],
75876 'last_column' => $lines ? strlen($lines[count($lines) - 1]) - 1 : $this->yylloc['last_column'] + strlen($match[0]),
75877 );
75878 $this->yytext .= $match[0];
75879 $this->match .= $match[0];
75880 $this->yyleng = strlen($this->yytext);
75881 $this->more = false;
75882 $this->input = substr($this->input, strlen($match[0]));
75883 $this->matched .= $match[0];
75884 $token = $this->performAction($rules[$i], $this->conditionStack[count($this->conditionStack)-1]);
75885 if ($token) {
75886 return $token;
75887 }
75888
75889 return new Undefined();
75890 }
75891 }
75892
75893 if ($this->input === "") {
75894 return $this->EOF;
75895 }
75896
75897 $this->parseError(
75898 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(),
75899 array(
75900 'text' => "",
75901 'token' => null,
75902 'line' => $this->yylineno,
75903 )
75904 );
75905 }
75906
75907 private function getCurrentRules()
75908 {
75909 return $this->conditions[$this->conditionStack[count($this->conditionStack)-1]]['rules'];
75910 }
75911
75912 private function performAction($avoiding_name_collisions, $YY_START)
75913 {
75914 switch ($avoiding_name_collisions) {
75915 case 0:
75916 break;
75917 case 1:
75918 return 6;
75919 break;
75920 case 2:
75921 $this->yytext = substr($this->yytext, 1, $this->yyleng-2);
75922
75923 return 4;
75924 case 3:
75925 return 17;
75926 case 4:
75927 return 18;
75928 case 5:
75929 return 23;
75930 case 6:
75931 return 24;
75932 case 7:
75933 return 22;
75934 case 8:
75935 return 21;
75936 case 9:
75937 return 10;
75938 case 10:
75939 return 11;
75940 case 11:
75941 return 8;
75942 case 12:
75943 return 14;
75944 case 13:
75945 return 'INVALID';
75946 }
75947 }
75948 }
75949 <?php
75950
75951
75952
75953
75954
75955
75956
75957
75958
75959
75960 namespace Seld\JsonLint;
75961
75962 class ParsingException extends \Exception
75963 {
75964 protected $details;
75965
75966 public function __construct($message, $details = array())
75967 {
75968 $this->details = $details;
75969 parent::__construct($message);
75970 }
75971
75972 public function getDetails()
75973 {
75974 return $this->details;
75975 }
75976 }
75977 <?php
75978
75979
75980
75981
75982
75983
75984
75985
75986
75987
75988 namespace Seld\JsonLint;
75989
75990 class Undefined
75991 {
75992 }
75993 Copyright (c) 2015 Jordi Boggiano
75994
75995 Permission is hereby granted, free of charge, to any person obtaining a copy
75996 of this software and associated documentation files (the "Software"), to deal
75997 in the Software without restriction, including without limitation the rights
75998 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75999 copies of the Software, and to permit persons to whom the Software is furnished
76000 to do so, subject to the following conditions:
76001
76002 The above copyright notice and this permission notice shall be included in all
76003 copies or substantial portions of the Software.
76004
76005 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
76006 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
76007 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
76008 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76009 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
76010 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
76011 THE SOFTWARE.
76012 <?php
76013
76014 require __DIR__.'/../vendor/autoload.php';
76015
76016 echo 'Say hello (visible): ';
76017
76018 $answer = Seld\CliPrompt\CliPrompt::prompt();
76019
76020 echo 'You answered: '.$answer . PHP_EOL;
76021
76022 echo 'Say hello (hidden): ';
76023
76024 $answer = Seld\CliPrompt\CliPrompt::hiddenPrompt();
76025
76026 echo 'You answered: '.$answer . PHP_EOL;
76027 <?php
76028
76029
76030
76031
76032
76033
76034
76035
76036
76037
76038 namespace Seld\CliPrompt;
76039
76040 class CliPrompt
76041 {
76042
76043
76044
76045
76046
76047 public static function prompt()
76048 {
76049 $stdin = fopen('php://stdin', 'r');
76050 $answer = self::trimAnswer(fgets($stdin, 4096));
76051 fclose($stdin);
76052
76053 return $answer;
76054 }
76055
76056
76057
76058
76059
76060
76061
76062
76063
76064
76065 public static function hiddenPrompt($allowFallback = false)
76066 {
76067
76068  if (defined('PHP_WINDOWS_VERSION_BUILD')) {
76069
76070  $exe = __DIR__.'\\..\\res\\hiddeninput.exe';
76071
76072
76073  if ('phar:' === substr(__FILE__, 0, 5)) {
76074 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
76075
76076
76077  
76078  $source = fopen($exe, 'r');
76079 $target = fopen($tmpExe, 'w+');
76080 stream_copy_to_stream($source, $target);
76081 fclose($source);
76082 fclose($target);
76083 unset($source, $target);
76084
76085 $exe = $tmpExe;
76086 }
76087
76088 $output = shell_exec($exe);
76089
76090
76091  if (isset($tmpExe)) {
76092 unlink($tmpExe);
76093 }
76094
76095 if ($output !== null) {
76096
76097  echo PHP_EOL;
76098
76099 return self::trimAnswer($output);
76100 }
76101 }
76102
76103 if (file_exists('/usr/bin/env')) {
76104
76105  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
76106 foreach (array('bash', 'zsh', 'ksh', 'csh', 'sh') as $sh) {
76107 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
76108 $shell = $sh;
76109 break;
76110 }
76111 }
76112
76113 if (isset($shell)) {
76114 $readCmd = ($shell === 'csh') ? 'set mypassword = $<' : 'read -r mypassword';
76115 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
76116 $output = shell_exec($command);
76117
76118 if ($output !== null) {
76119
76120  echo PHP_EOL;
76121
76122 return self::trimAnswer($output);
76123 }
76124 }
76125 }
76126
76127
76128  if (!$allowFallback) {
76129 throw new \RuntimeException('Could not prompt for input in a secure fashion, aborting');
76130 }
76131
76132 return self::prompt();
76133 }
76134
76135 private static function trimAnswer($str)
76136 {
76137 return preg_replace('{\r?\n$}D', '', $str);
76138 }
76139 }
76140 MIT License
76141
76142 Copyright (c) 2016
76143
76144 Permission is hereby granted, free of charge, to any person obtaining a copy
76145 of this software and associated documentation files (the "Software"), to deal
76146 in the Software without restriction, including without limitation the rights
76147 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
76148 copies of the Software, and to permit persons to whom the Software is
76149 furnished to do so, subject to the following conditions:
76150
76151 The above copyright notice and this permission notice shall be included in all
76152 copies or substantial portions of the Software.
76153
76154 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
76155 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
76156 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
76157 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76158 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
76159 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
76160 SOFTWARE.
76161 <?php
76162
76163 require __DIR__ . '/../vendor/autoload.php';
76164
76165 $data = json_decode(file_get_contents('data.json'));
76166
76167
76168 $validator = new JsonSchema\Validator();
76169 $validator->check($data, (object) array('$ref' => 'file://' . realpath('schema.json')));
76170
76171 if ($validator->isValid()) {
76172 echo "The supplied JSON validates against the schema.\n";
76173 } else {
76174 echo "JSON does not validate. Violations:\n";
76175 foreach ($validator->getErrors() as $error) {
76176 echo sprintf("[%s] %s\n", $error['property'], $error['message']);
76177 }
76178 }
76179 <?php
76180
76181
76182
76183
76184
76185
76186
76187
76188 namespace JsonSchema\Constraints;
76189
76190 use JsonSchema\Entity\JsonPointer;
76191 use JsonSchema\Exception\InvalidArgumentException;
76192 use JsonSchema\Exception\ValidationException;
76193 use JsonSchema\Validator;
76194
76195
76196
76197
76198
76199 class BaseConstraint
76200 {
76201
76202
76203
76204 protected $errors = array();
76205
76206
76207
76208
76209 protected $errorMask = Validator::ERROR_NONE;
76210
76211
76212
76213
76214 protected $factory;
76215
76216
76217
76218
76219 public function __construct(Factory $factory = null)
76220 {
76221 $this->factory = $factory ?: new Factory();
76222 }
76223
76224 public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null)
76225 {
76226 $error = array(
76227 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')),
76228 'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
76229 'message' => $message,
76230 'constraint' => $constraint,
76231 'context' => $this->factory->getErrorContext(),
76232 );
76233
76234 if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
76235 throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
76236 }
76237
76238 if (is_array($more) && count($more) > 0) {
76239 $error += $more;
76240 }
76241
76242 $this->errors[] = $error;
76243 $this->errorMask |= $error['context'];
76244 }
76245
76246 public function addErrors(array $errors)
76247 {
76248 if ($errors) {
76249 $this->errors = array_merge($this->errors, $errors);
76250 $errorMask = &$this->errorMask;
76251 array_walk($errors, function ($error) use (&$errorMask) {
76252 if (isset($error['context'])) {
76253 $errorMask |= $error['context'];
76254 }
76255 });
76256 }
76257 }
76258
76259 public function getErrors($errorContext = Validator::ERROR_ALL)
76260 {
76261 if ($errorContext === Validator::ERROR_ALL) {
76262 return $this->errors;
76263 }
76264
76265 return array_filter($this->errors, function ($error) use ($errorContext) {
76266 if ($errorContext & $error['context']) {
76267 return true;
76268 }
76269 });
76270 }
76271
76272 public function numErrors($errorContext = Validator::ERROR_ALL)
76273 {
76274 if ($errorContext === Validator::ERROR_ALL) {
76275 return count($this->errors);
76276 }
76277
76278 return count($this->getErrors($errorContext));
76279 }
76280
76281 public function isValid()
76282 {
76283 return !$this->getErrors();
76284 }
76285
76286
76287
76288
76289
76290 public function reset()
76291 {
76292 $this->errors = array();
76293 $this->errorMask = Validator::ERROR_NONE;
76294 }
76295
76296
76297
76298
76299
76300
76301 public function getErrorMask()
76302 {
76303 return $this->errorMask;
76304 }
76305
76306
76307
76308
76309
76310
76311
76312
76313 public static function arrayToObjectRecursive($array)
76314 {
76315 $json = json_encode($array);
76316 if (json_last_error() !== \JSON_ERROR_NONE) {
76317 $message = 'Unable to encode schema array as JSON';
76318 if (function_exists('json_last_error_msg')) {
76319 $message .= ': ' . json_last_error_msg();
76320 }
76321 throw new InvalidArgumentException($message);
76322 }
76323
76324 return (object) json_decode($json);
76325 }
76326 }
76327 <?php
76328
76329
76330
76331
76332
76333
76334
76335
76336 namespace JsonSchema\Constraints;
76337
76338 use JsonSchema\Entity\JsonPointer;
76339
76340
76341
76342
76343
76344
76345
76346 class CollectionConstraint extends Constraint
76347 {
76348
76349
76350
76351 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null)
76352 {
76353
76354  if (isset($schema->minItems) && count($value) < $schema->minItems) {
76355 $this->addError($path, 'There must be a minimum of ' . $schema->minItems . ' items in the array', 'minItems', array('minItems' => $schema->minItems));
76356 }
76357
76358
76359  if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
76360 $this->addError($path, 'There must be a maximum of ' . $schema->maxItems . ' items in the array', 'maxItems', array('maxItems' => $schema->maxItems));
76361 }
76362
76363
76364  if (isset($schema->uniqueItems) && $schema->uniqueItems) {
76365 $unique = $value;
76366 if (is_array($value) && count($value)) {
76367 $unique = array_map(function ($e) {
76368 return var_export($e, true);
76369 }, $value);
76370 }
76371 if (count(array_unique($unique)) != count($value)) {
76372 $this->addError($path, 'There are no duplicates allowed in the array', 'uniqueItems');
76373 }
76374 }
76375
76376
76377  if (isset($schema->items)) {
76378 $this->validateItems($value, $schema, $path, $i);
76379 }
76380 }
76381
76382
76383
76384
76385
76386
76387
76388
76389
76390 protected function validateItems(&$value, $schema = null, JsonPointer $path = null, $i = null)
76391 {
76392 if (is_object($schema->items)) {
76393
76394
76395 if (isset($schema->items->type)
76396 && (
76397 $schema->items->type == 'string'
76398 || $schema->items->type == 'number'
76399 || $schema->items->type == 'integer'
76400 )
76401 && !isset($schema->additionalItems)
76402 ) {
76403
76404  $type = $schema->items->type;
76405 $typeValidator = $this->factory->createInstanceFor('type');
76406 $validator = $this->factory->createInstanceFor($type === 'integer' ? 'number' : $type);
76407
76408 foreach ($value as $k => &$v) {
76409 $k_path = $this->incrementPath($path, $k);
76410 $typeValidator->check($v, $schema->items, $k_path, $i);
76411
76412 $validator->check($v, $schema->items, $k_path, $i);
76413 }
76414 unset($v); 
76415
76416 $this->addErrors($typeValidator->getErrors());
76417 $this->addErrors($validator->getErrors());
76418 } else {
76419 foreach ($value as $k => &$v) {
76420 $initErrors = $this->getErrors();
76421
76422
76423  $this->checkUndefined($v, $schema->items, $path, $k);
76424
76425
76426  if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
76427 $secondErrors = $this->getErrors();
76428 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
76429 }
76430
76431
76432  if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
76433 $this->errors = $secondErrors;
76434 } elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
76435 $this->errors = $initErrors;
76436 }
76437 }
76438 unset($v); 
76439
76440 }
76441 } else {
76442
76443  foreach ($value as $k => &$v) {
76444 if (array_key_exists($k, $schema->items)) {
76445 $this->checkUndefined($v, $schema->items[$k], $path, $k);
76446 } else {
76447
76448  if (property_exists($schema, 'additionalItems')) {
76449 if ($schema->additionalItems !== false) {
76450 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
76451 } else {
76452 $this->addError(
76453 $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems));
76454 }
76455 } else {
76456
76457  $this->checkUndefined($v, new \stdClass(), $path, $k);
76458 }
76459 }
76460 }
76461 unset($v); 
76462
76463
76464
76465  if (count($value) > 0) {
76466 for ($k = count($value); $k < count($schema->items); $k++) {
76467 $undefinedInstance = $this->factory->createInstanceFor('undefined');
76468 $this->checkUndefined($undefinedInstance, $schema->items[$k], $path, $k);
76469 }
76470 }
76471 }
76472 }
76473 }
76474 <?php
76475
76476
76477
76478
76479
76480
76481
76482
76483 namespace JsonSchema\Constraints;
76484
76485 use JsonSchema\Entity\JsonPointer;
76486 use JsonSchema\SchemaStorage;
76487 use JsonSchema\Uri\UriRetriever;
76488 use JsonSchema\UriRetrieverInterface;
76489
76490
76491
76492
76493
76494
76495
76496 abstract class Constraint extends BaseConstraint implements ConstraintInterface
76497 {
76498 protected $inlineSchemaProperty = '$schema';
76499
76500 const CHECK_MODE_NONE = 0x00000000;
76501 const CHECK_MODE_NORMAL = 0x00000001;
76502 const CHECK_MODE_TYPE_CAST = 0x00000002;
76503 const CHECK_MODE_COERCE_TYPES = 0x00000004;
76504 const CHECK_MODE_APPLY_DEFAULTS = 0x00000008;
76505 const CHECK_MODE_EXCEPTIONS = 0x00000010;
76506 const CHECK_MODE_DISABLE_FORMAT = 0x00000020;
76507 const CHECK_MODE_ONLY_REQUIRED_DEFAULTS = 0x00000080;
76508 const CHECK_MODE_VALIDATE_SCHEMA = 0x00000100;
76509
76510
76511
76512
76513
76514
76515
76516
76517
76518 protected function incrementPath(JsonPointer $path = null, $i)
76519 {
76520 $path = $path ?: new JsonPointer('');
76521 $path = $path->withPropertyPaths(
76522 array_merge(
76523 $path->getPropertyPaths(),
76524 array_filter(array($i), 'strlen')
76525 )
76526 );
76527
76528 return $path;
76529 }
76530
76531
76532
76533
76534
76535
76536
76537
76538
76539 protected function checkArray(&$value, $schema = null, JsonPointer $path = null, $i = null)
76540 {
76541 $validator = $this->factory->createInstanceFor('collection');
76542 $validator->check($value, $schema, $path, $i);
76543
76544 $this->addErrors($validator->getErrors());
76545 }
76546
76547
76548
76549
76550
76551
76552
76553
76554
76555
76556
76557 protected function checkObject(&$value, $schema = null, JsonPointer $path = null, $properties = null,
76558 $additionalProperties = null, $patternProperties = null, $appliedDefaults = array())
76559 {
76560 $validator = $this->factory->createInstanceFor('object');
76561 $validator->check($value, $schema, $path, $properties, $additionalProperties, $patternProperties, $appliedDefaults);
76562
76563 $this->addErrors($validator->getErrors());
76564 }
76565
76566
76567
76568
76569
76570
76571
76572
76573
76574 protected function checkType(&$value, $schema = null, JsonPointer $path = null, $i = null)
76575 {
76576 $validator = $this->factory->createInstanceFor('type');
76577 $validator->check($value, $schema, $path, $i);
76578
76579 $this->addErrors($validator->getErrors());
76580 }
76581
76582
76583
76584
76585
76586
76587
76588
76589
76590 protected function checkUndefined(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
76591 {
76592 $validator = $this->factory->createInstanceFor('undefined');
76593
76594 $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i, $fromDefault);
76595
76596 $this->addErrors($validator->getErrors());
76597 }
76598
76599
76600
76601
76602
76603
76604
76605
76606
76607 protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
76608 {
76609 $validator = $this->factory->createInstanceFor('string');
76610 $validator->check($value, $schema, $path, $i);
76611
76612 $this->addErrors($validator->getErrors());
76613 }
76614
76615
76616
76617
76618
76619
76620
76621
76622
76623 protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
76624 {
76625 $validator = $this->factory->createInstanceFor('number');
76626 $validator->check($value, $schema, $path, $i);
76627
76628 $this->addErrors($validator->getErrors());
76629 }
76630
76631
76632
76633
76634
76635
76636
76637
76638
76639 protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
76640 {
76641 $validator = $this->factory->createInstanceFor('enum');
76642 $validator->check($value, $schema, $path, $i);
76643
76644 $this->addErrors($validator->getErrors());
76645 }
76646
76647
76648
76649
76650
76651
76652
76653
76654
76655 protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
76656 {
76657 $validator = $this->factory->createInstanceFor('format');
76658 $validator->check($value, $schema, $path, $i);
76659
76660 $this->addErrors($validator->getErrors());
76661 }
76662
76663
76664
76665
76666
76667
76668 protected function getTypeCheck()
76669 {
76670 return $this->factory->getTypeCheck();
76671 }
76672
76673
76674
76675
76676
76677
76678 protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
76679 {
76680 $result = array_map(
76681 function ($path) {
76682 return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
76683 },
76684 $pointer->getPropertyPaths()
76685 );
76686
76687 return trim(implode('', $result), '.');
76688 }
76689 }
76690 <?php
76691
76692
76693
76694
76695
76696
76697
76698
76699 namespace JsonSchema\Constraints;
76700
76701 use JsonSchema\Entity\JsonPointer;
76702
76703
76704
76705
76706
76707
76708 interface ConstraintInterface
76709 {
76710
76711
76712
76713
76714
76715 public function getErrors();
76716
76717
76718
76719
76720
76721
76722 public function addErrors(array $errors);
76723
76724
76725
76726
76727
76728
76729
76730
76731
76732 public function addError(JsonPointer $path = null, $message, $constraint='', array $more = null);
76733
76734
76735
76736
76737
76738
76739 public function isValid();
76740
76741
76742
76743
76744
76745
76746
76747
76748
76749
76750
76751
76752
76753 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null);
76754 }
76755 <?php
76756
76757
76758
76759
76760
76761
76762
76763
76764 namespace JsonSchema\Constraints;
76765
76766 use JsonSchema\Entity\JsonPointer;
76767
76768
76769
76770
76771
76772
76773
76774 class EnumConstraint extends Constraint
76775 {
76776
76777
76778
76779 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76780 {
76781
76782  if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
76783 return;
76784 }
76785 $type = gettype($element);
76786
76787 foreach ($schema->enum as $enum) {
76788 $enumType = gettype($enum);
76789 if ($this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && $type == 'array' && $enumType == 'object') {
76790 if ((object) $element == $enum) {
76791 return;
76792 }
76793 }
76794
76795 if ($type === gettype($enum)) {
76796 if ($type == 'object') {
76797 if ($element == $enum) {
76798 return;
76799 }
76800 } elseif ($element === $enum) {
76801 return;
76802 }
76803 }
76804 }
76805
76806 $this->addError($path, 'Does not have a value in the enumeration ' . json_encode($schema->enum), 'enum', array('enum' => $schema->enum));
76807 }
76808 }
76809 <?php
76810
76811
76812
76813
76814
76815
76816
76817
76818 namespace JsonSchema\Constraints;
76819
76820 use JsonSchema\Constraints\Constraint;
76821 use JsonSchema\Exception\InvalidArgumentException;
76822 use JsonSchema\Exception\InvalidConfigException;
76823 use JsonSchema\SchemaStorage;
76824 use JsonSchema\SchemaStorageInterface;
76825 use JsonSchema\Uri\UriRetriever;
76826 use JsonSchema\UriRetrieverInterface;
76827 use JsonSchema\Validator;
76828
76829
76830
76831
76832 class Factory
76833 {
76834
76835
76836
76837 protected $schemaStorage;
76838
76839
76840
76841
76842 protected $uriRetriever;
76843
76844
76845
76846
76847 private $checkMode = Constraint::CHECK_MODE_NORMAL;
76848
76849
76850
76851
76852 private $typeCheck = array();
76853
76854
76855
76856
76857 protected $errorContext = Validator::ERROR_DOCUMENT_VALIDATION;
76858
76859
76860
76861
76862 protected $constraintMap = array(
76863 'array' => 'JsonSchema\Constraints\CollectionConstraint',
76864 'collection' => 'JsonSchema\Constraints\CollectionConstraint',
76865 'object' => 'JsonSchema\Constraints\ObjectConstraint',
76866 'type' => 'JsonSchema\Constraints\TypeConstraint',
76867 'undefined' => 'JsonSchema\Constraints\UndefinedConstraint',
76868 'string' => 'JsonSchema\Constraints\StringConstraint',
76869 'number' => 'JsonSchema\Constraints\NumberConstraint',
76870 'enum' => 'JsonSchema\Constraints\EnumConstraint',
76871 'format' => 'JsonSchema\Constraints\FormatConstraint',
76872 'schema' => 'JsonSchema\Constraints\SchemaConstraint',
76873 'validator' => 'JsonSchema\Validator'
76874 );
76875
76876
76877
76878
76879 private $instanceCache = array();
76880
76881
76882
76883
76884
76885
76886 public function __construct(
76887 SchemaStorageInterface $schemaStorage = null,
76888 UriRetrieverInterface $uriRetriever = null,
76889 $checkMode = Constraint::CHECK_MODE_NORMAL
76890 ) {
76891
76892  $this->setConfig($checkMode);
76893
76894 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
76895 $this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
76896 }
76897
76898
76899
76900
76901
76902
76903 public function setConfig($checkMode = Constraint::CHECK_MODE_NORMAL)
76904 {
76905 $this->checkMode = $checkMode;
76906 }
76907
76908
76909
76910
76911
76912
76913 public function addConfig($options)
76914 {
76915 $this->checkMode |= $options;
76916 }
76917
76918
76919
76920
76921
76922
76923 public function removeConfig($options)
76924 {
76925 $this->checkMode &= ~$options;
76926 }
76927
76928
76929
76930
76931
76932
76933
76934
76935 public function getConfig($options = null)
76936 {
76937 if ($options === null) {
76938 return $this->checkMode;
76939 }
76940
76941 return $this->checkMode & $options;
76942 }
76943
76944
76945
76946
76947 public function getUriRetriever()
76948 {
76949 return $this->uriRetriever;
76950 }
76951
76952 public function getSchemaStorage()
76953 {
76954 return $this->schemaStorage;
76955 }
76956
76957 public function getTypeCheck()
76958 {
76959 if (!isset($this->typeCheck[$this->checkMode])) {
76960 $this->typeCheck[$this->checkMode] = ($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST)
76961 ? new TypeCheck\LooseTypeCheck()
76962 : new TypeCheck\StrictTypeCheck();
76963 }
76964
76965 return $this->typeCheck[$this->checkMode];
76966 }
76967
76968
76969
76970
76971
76972
76973
76974 public function setConstraintClass($name, $class)
76975 {
76976
76977  if (!class_exists($class)) {
76978 throw new InvalidArgumentException('Unknown constraint ' . $name);
76979 }
76980
76981  if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
76982 throw new InvalidArgumentException('Invalid class ' . $name);
76983 }
76984 $this->constraintMap[$name] = $class;
76985
76986 return $this;
76987 }
76988
76989
76990
76991
76992
76993
76994
76995
76996
76997
76998 public function createInstanceFor($constraintName)
76999 {
77000 if (!isset($this->constraintMap[$constraintName])) {
77001 throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
77002 }
77003
77004 if (!isset($this->instanceCache[$constraintName])) {
77005 $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
77006 }
77007
77008 return clone $this->instanceCache[$constraintName];
77009 }
77010
77011
77012
77013
77014
77015
77016 public function getErrorContext()
77017 {
77018 return $this->errorContext;
77019 }
77020
77021
77022
77023
77024
77025
77026 public function setErrorContext($errorContext)
77027 {
77028 $this->errorContext = $errorContext;
77029 }
77030 }
77031 <?php
77032
77033
77034
77035
77036
77037
77038
77039
77040 namespace JsonSchema\Constraints;
77041
77042 use JsonSchema\Entity\JsonPointer;
77043 use JsonSchema\Rfc3339;
77044
77045
77046
77047
77048
77049
77050
77051
77052 class FormatConstraint extends Constraint
77053 {
77054
77055
77056
77057 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
77058 {
77059 if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
77060 return;
77061 }
77062
77063 switch ($schema->format) {
77064 case 'date':
77065 if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
77066 $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format));
77067 }
77068 break;
77069
77070 case 'time':
77071 if (!$this->validateDateTime($element, 'H:i:s')) {
77072 $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format));
77073 }
77074 break;
77075
77076 case 'date-time':
77077 if (null === Rfc3339::createFromString($element)) {
77078 $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));
77079 }
77080 break;
77081
77082 case 'utc-millisec':
77083 if (!$this->validateDateTime($element, 'U')) {
77084 $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format));
77085 }
77086 break;
77087
77088 case 'regex':
77089 if (!$this->validateRegex($element)) {
77090 $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format));
77091 }
77092 break;
77093
77094 case 'color':
77095 if (!$this->validateColor($element)) {
77096 $this->addError($path, 'Invalid color', 'format', array('format' => $schema->format));
77097 }
77098 break;
77099
77100 case 'style':
77101 if (!$this->validateStyle($element)) {
77102 $this->addError($path, 'Invalid style', 'format', array('format' => $schema->format));
77103 }
77104 break;
77105
77106 case 'phone':
77107 if (!$this->validatePhone($element)) {
77108 $this->addError($path, 'Invalid phone number', 'format', array('format' => $schema->format));
77109 }
77110 break;
77111
77112 case 'uri':
77113 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
77114 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
77115 }
77116 break;
77117
77118 case 'uriref':
77119 case 'uri-reference':
77120 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
77121
77122  
77123  
77124  if (substr($element, 0, 2) === '//') { 
77125  $validURL = filter_var('scheme:' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
77126 } elseif (substr($element, 0, 1) === '/') { 
77127  $validURL = filter_var('scheme://host' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
77128 } elseif (strlen($element)) { 
77129  $pathParts = explode('/', $element, 2);
77130 if (strpos($pathParts[0], ':') !== false) {
77131 $validURL = null;
77132 } else {
77133 $validURL = filter_var('scheme://host/' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
77134 }
77135 } else {
77136 $validURL = null;
77137 }
77138 if ($validURL === null) {
77139 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
77140 }
77141 }
77142 break;
77143
77144 case 'email':
77145 $filterFlags = FILTER_NULL_ON_FAILURE;
77146 if (defined('FILTER_FLAG_EMAIL_UNICODE')) {
77147
77148  $filterFlags |= constant('FILTER_FLAG_EMAIL_UNICODE'); 
77149  }
77150 if (null === filter_var($element, FILTER_VALIDATE_EMAIL, $filterFlags)) {
77151 $this->addError($path, 'Invalid email', 'format', array('format' => $schema->format));
77152 }
77153 break;
77154
77155 case 'ip-address':
77156 case 'ipv4':
77157 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
77158 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
77159 }
77160 break;
77161
77162 case 'ipv6':
77163 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
77164 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
77165 }
77166 break;
77167
77168 case 'host-name':
77169 case 'hostname':
77170 if (!$this->validateHostname($element)) {
77171 $this->addError($path, 'Invalid hostname', 'format', array('format' => $schema->format));
77172 }
77173 break;
77174
77175 default:
77176
77177  
77178  
77179  
77180  
77181  
77182  break;
77183 }
77184 }
77185
77186 protected function validateDateTime($datetime, $format)
77187 {
77188 $dt = \DateTime::createFromFormat($format, $datetime);
77189
77190 if (!$dt) {
77191 return false;
77192 }
77193
77194 if ($datetime === $dt->format($format)) {
77195 return true;
77196 }
77197
77198
77199  
77200  
77201  
77202  if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', $datetime))) {
77203 return true;
77204 }
77205
77206 return false;
77207 }
77208
77209 protected function validateRegex($regex)
77210 {
77211 return false !== @preg_match('/' . $regex . '/u', '');
77212 }
77213
77214 protected function validateColor($color)
77215 {
77216 if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
77217 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
77218 'red', 'silver', 'teal', 'white', 'yellow'))) {
77219 return true;
77220 }
77221
77222 return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
77223 }
77224
77225 protected function validateStyle($style)
77226 {
77227 $properties = explode(';', rtrim($style, ';'));
77228 $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
77229
77230 return empty($invalidEntries);
77231 }
77232
77233 protected function validatePhone($phone)
77234 {
77235 return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
77236 }
77237
77238 protected function validateHostname($host)
77239 {
77240 $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';
77241
77242 return preg_match($hostnameRegex, $host);
77243 }
77244 }
77245 <?php
77246
77247
77248
77249
77250
77251
77252
77253
77254 namespace JsonSchema\Constraints;
77255
77256 use JsonSchema\Entity\JsonPointer;
77257
77258
77259
77260
77261
77262
77263
77264 class NumberConstraint extends Constraint
77265 {
77266
77267
77268
77269 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
77270 {
77271
77272  if (isset($schema->exclusiveMinimum)) {
77273 if (isset($schema->minimum)) {
77274 if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
77275 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum));
77276 } elseif ($element < $schema->minimum) {
77277 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
77278 }
77279 } else {
77280 $this->addError($path, 'Use of exclusiveMinimum requires presence of minimum', 'missingMinimum');
77281 }
77282 } elseif (isset($schema->minimum) && $element < $schema->minimum) {
77283 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
77284 }
77285
77286
77287  if (isset($schema->exclusiveMaximum)) {
77288 if (isset($schema->maximum)) {
77289 if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
77290 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum));
77291 } elseif ($element > $schema->maximum) {
77292 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
77293 }
77294 } else {
77295 $this->addError($path, 'Use of exclusiveMaximum requires presence of maximum', 'missingMaximum');
77296 }
77297 } elseif (isset($schema->maximum) && $element > $schema->maximum) {
77298 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
77299 }
77300
77301
77302  if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
77303 $this->addError($path, 'Is not divisible by ' . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy));
77304 }
77305
77306
77307  if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
77308 $this->addError($path, 'Must be a multiple of ' . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf));
77309 }
77310
77311 $this->checkFormat($element, $schema, $path, $i);
77312 }
77313
77314 private function fmod($number1, $number2)
77315 {
77316 $number1 = abs($number1);
77317 $modulus = fmod($number1, $number2);
77318 $precision = abs(0.0000000001);
77319 $diff = (float) ($modulus - $number2);
77320
77321 if (-$precision < $diff && $diff < $precision) {
77322 return 0.0;
77323 }
77324
77325 $decimals1 = mb_strpos($number1, '.') ? mb_strlen($number1) - mb_strpos($number1, '.') - 1 : 0;
77326 $decimals2 = mb_strpos($number2, '.') ? mb_strlen($number2) - mb_strpos($number2, '.') - 1 : 0;
77327
77328 return (float) round($modulus, max($decimals1, $decimals2));
77329 }
77330 }
77331 <?php
77332
77333
77334
77335
77336
77337
77338
77339
77340 namespace JsonSchema\Constraints;
77341
77342 use JsonSchema\Entity\JsonPointer;
77343
77344
77345
77346
77347
77348
77349
77350 class ObjectConstraint extends Constraint
77351 {
77352
77353
77354
77355 protected $appliedDefaults = array();
77356
77357
77358
77359
77360 public function check(&$element, $schema = null, JsonPointer $path = null, $properties = null,
77361 $additionalProp = null, $patternProperties = null, $appliedDefaults = array())
77362 {
77363 if ($element instanceof UndefinedConstraint) {
77364 return;
77365 }
77366
77367 $this->appliedDefaults = $appliedDefaults;
77368
77369 $matches = array();
77370 if ($patternProperties) {
77371
77372  $matches = $this->validatePatternProperties($element, $path, $patternProperties);
77373 }
77374
77375 if ($properties) {
77376
77377  $this->validateProperties($element, $properties, $path);
77378 }
77379
77380
77381  $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp);
77382 }
77383
77384 public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties)
77385 {
77386 $try = array('/', '#', '+', '~', '%');
77387 $matches = array();
77388 foreach ($patternProperties as $pregex => $schema) {
77389 $delimiter = '/';
77390
77391  foreach ($try as $delimiter) {
77392 if (strpos($pregex, $delimiter) === false) { 
77393  break;
77394 }
77395 }
77396
77397
77398  if (@preg_match($delimiter . $pregex . $delimiter . 'u', '') === false) {
77399 $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex));
77400 continue;
77401 }
77402 foreach ($element as $i => $value) {
77403 if (preg_match($delimiter . $pregex . $delimiter . 'u', $i)) {
77404 $matches[] = $i;
77405 $this->checkUndefined($value, $schema ?: new \stdClass(), $path, $i, in_array($i, $this->appliedDefaults));
77406 }
77407 }
77408 }
77409
77410 return $matches;
77411 }
77412
77413
77414
77415
77416
77417
77418
77419
77420
77421
77422
77423 public function validateElement($element, $matches, $schema = null, JsonPointer $path = null,
77424 $properties = null, $additionalProp = null)
77425 {
77426 $this->validateMinMaxConstraint($element, $schema, $path);
77427
77428 foreach ($element as $i => $value) {
77429 $definition = $this->getProperty($properties, $i);
77430
77431
77432  if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
77433 $this->addError($path, 'The property ' . $i . ' is not defined and the definition does not allow additional properties', 'additionalProp');
77434 }
77435
77436
77437  if (!in_array($i, $matches) && $additionalProp && !$definition) {
77438 if ($additionalProp === true) {
77439 $this->checkUndefined($value, null, $path, $i, in_array($i, $this->appliedDefaults));
77440 } else {
77441 $this->checkUndefined($value, $additionalProp, $path, $i, in_array($i, $this->appliedDefaults));
77442 }
77443 }
77444
77445
77446  $require = $this->getProperty($definition, 'requires');
77447 if ($require && !$this->getProperty($element, $require)) {
77448 $this->addError($path, 'The presence of the property ' . $i . ' requires that ' . $require . ' also be present', 'requires');
77449 }
77450
77451 $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
77452 if (is_object($property)) {
77453 $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
77454 }
77455 }
77456 }
77457
77458
77459
77460
77461
77462
77463
77464
77465 public function validateProperties(&$element, $properties = null, JsonPointer $path = null)
77466 {
77467 $undefinedConstraint = $this->factory->createInstanceFor('undefined');
77468
77469 foreach ($properties as $i => $value) {
77470 $property = &$this->getProperty($element, $i, $undefinedConstraint);
77471 $definition = $this->getProperty($properties, $i);
77472
77473 if (is_object($definition)) {
77474
77475  $this->checkUndefined($property, $definition, $path, $i, in_array($i, $this->appliedDefaults));
77476 }
77477 }
77478 }
77479
77480
77481
77482
77483
77484
77485
77486
77487
77488
77489 protected function &getProperty(&$element, $property, $fallback = null)
77490 {
77491 if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) ) {
77492 return $element[$property];
77493 } elseif (is_object($element) && property_exists($element, $property)) {
77494 return $element->$property;
77495 }
77496
77497 return $fallback;
77498 }
77499
77500
77501
77502
77503
77504
77505
77506
77507 protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null)
77508 {
77509
77510  if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
77511 if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
77512 $this->addError($path, 'Must contain a minimum of ' . $objectDefinition->minProperties . ' properties', 'minProperties', array('minProperties' => $objectDefinition->minProperties));
77513 }
77514 }
77515
77516  if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
77517 if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
77518 $this->addError($path, 'Must contain no more than ' . $objectDefinition->maxProperties . ' properties', 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties));
77519 }
77520 }
77521 }
77522 }
77523 <?php
77524
77525
77526
77527
77528
77529
77530
77531
77532 namespace JsonSchema\Constraints;
77533
77534 use JsonSchema\Entity\JsonPointer;
77535 use JsonSchema\Exception\InvalidArgumentException;
77536 use JsonSchema\Exception\InvalidSchemaException;
77537 use JsonSchema\Exception\RuntimeException;
77538 use JsonSchema\SchemaStorage;
77539 use JsonSchema\Validator;
77540
77541
77542
77543
77544
77545
77546
77547 class SchemaConstraint extends Constraint
77548 {
77549 const DEFAULT_SCHEMA_SPEC = 'http://json-schema.org/draft-04/schema#';
77550
77551
77552
77553
77554 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
77555 {
77556 if ($schema !== null) {
77557
77558  $validationSchema = $schema;
77559 } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
77560
77561  $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
77562 } else {
77563 throw new InvalidArgumentException('no schema found to verify against');
77564 }
77565
77566
77567  if (is_array($validationSchema)) {
77568 $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema);
77569 }
77570
77571
77572  
77573  if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) {
77574 if (!$this->getTypeCheck()->isObject($validationSchema)) {
77575 throw new RuntimeException('Cannot validate the schema of a non-object');
77576 }
77577 if ($this->getTypeCheck()->propertyExists($validationSchema, '$schema')) {
77578 $schemaSpec = $this->getTypeCheck()->propertyGet($validationSchema, '$schema');
77579 } else {
77580 $schemaSpec = self::DEFAULT_SCHEMA_SPEC;
77581 }
77582
77583
77584  $schemaStorage = $this->factory->getSchemaStorage();
77585 if (!$this->getTypeCheck()->isObject($schemaSpec)) {
77586 $schemaSpec = $schemaStorage->getSchema($schemaSpec);
77587 }
77588
77589
77590  $initialErrorCount = $this->numErrors();
77591 $initialConfig = $this->factory->getConfig();
77592 $initialContext = $this->factory->getErrorContext();
77593 $this->factory->removeConfig(self::CHECK_MODE_VALIDATE_SCHEMA | self::CHECK_MODE_APPLY_DEFAULTS);
77594 $this->factory->addConfig(self::CHECK_MODE_TYPE_CAST);
77595 $this->factory->setErrorContext(Validator::ERROR_SCHEMA_VALIDATION);
77596
77597
77598  try {
77599 $this->check($validationSchema, $schemaSpec);
77600 } catch (\Exception $e) {
77601 if ($this->factory->getConfig(self::CHECK_MODE_EXCEPTIONS)) {
77602 throw new InvalidSchemaException('Schema did not pass validation', 0, $e);
77603 }
77604 }
77605 if ($this->numErrors() > $initialErrorCount) {
77606 $this->addError($path, 'Schema is not valid', 'schema');
77607 }
77608
77609
77610  $this->factory->setConfig($initialConfig);
77611 $this->factory->setErrorContext($initialContext);
77612 }
77613
77614
77615  $this->checkUndefined($element, $validationSchema, $path, $i);
77616 }
77617 }
77618 <?php
77619
77620
77621
77622
77623
77624
77625
77626
77627 namespace JsonSchema\Constraints;
77628
77629 use JsonSchema\Entity\JsonPointer;
77630
77631
77632
77633
77634
77635
77636
77637 class StringConstraint extends Constraint
77638 {
77639
77640
77641
77642 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
77643 {
77644
77645  if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
77646 $this->addError($path, 'Must be at most ' . $schema->maxLength . ' characters long', 'maxLength', array(
77647 'maxLength' => $schema->maxLength,
77648 ));
77649 }
77650
77651
77652  if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
77653 $this->addError($path, 'Must be at least ' . $schema->minLength . ' characters long', 'minLength', array(
77654 'minLength' => $schema->minLength,
77655 ));
77656 }
77657
77658
77659  if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#u', $element)) {
77660 $this->addError($path, 'Does not match the regex pattern ' . $schema->pattern, 'pattern', array(
77661 'pattern' => $schema->pattern,
77662 ));
77663 }
77664
77665 $this->checkFormat($element, $schema, $path, $i);
77666 }
77667
77668 private function strlen($string)
77669 {
77670 if (extension_loaded('mbstring')) {
77671 return mb_strlen($string, mb_detect_encoding($string));
77672 }
77673
77674
77675  return strlen($string); 
77676  }
77677 }
77678 <?php
77679
77680 namespace JsonSchema\Constraints\TypeCheck;
77681
77682 class LooseTypeCheck implements TypeCheckInterface
77683 {
77684 public static function isObject($value)
77685 {
77686 return
77687 is_object($value) ||
77688 (is_array($value) && (count($value) == 0 || self::isAssociativeArray($value)));
77689 }
77690
77691 public static function isArray($value)
77692 {
77693 return
77694 is_array($value) &&
77695 (count($value) == 0 || !self::isAssociativeArray($value));
77696 }
77697
77698 public static function propertyGet($value, $property)
77699 {
77700 if (is_object($value)) {
77701 return $value->{$property};
77702 }
77703
77704 return $value[$property];
77705 }
77706
77707 public static function propertySet(&$value, $property, $data)
77708 {
77709 if (is_object($value)) {
77710 $value->{$property} = $data;
77711 } else {
77712 $value[$property] = $data;
77713 }
77714 }
77715
77716 public static function propertyExists($value, $property)
77717 {
77718 if (is_object($value)) {
77719 return property_exists($value, $property);
77720 }
77721
77722 return array_key_exists($property, $value);
77723 }
77724
77725 public static function propertyCount($value)
77726 {
77727 if (is_object($value)) {
77728 return count(get_object_vars($value));
77729 }
77730
77731 return count($value);
77732 }
77733
77734
77735
77736
77737
77738
77739
77740
77741 private static function isAssociativeArray($arr)
77742 {
77743 return array_keys($arr) !== range(0, count($arr) - 1);
77744 }
77745 }
77746 <?php
77747
77748 namespace JsonSchema\Constraints\TypeCheck;
77749
77750 class StrictTypeCheck implements TypeCheckInterface
77751 {
77752 public static function isObject($value)
77753 {
77754 return is_object($value);
77755 }
77756
77757 public static function isArray($value)
77758 {
77759 return is_array($value);
77760 }
77761
77762 public static function propertyGet($value, $property)
77763 {
77764 return $value->{$property};
77765 }
77766
77767 public static function propertySet(&$value, $property, $data)
77768 {
77769 $value->{$property} = $data;
77770 }
77771
77772 public static function propertyExists($value, $property)
77773 {
77774 return property_exists($value, $property);
77775 }
77776
77777 public static function propertyCount($value)
77778 {
77779 return count(get_object_vars($value));
77780 }
77781 }
77782 <?php
77783
77784 namespace JsonSchema\Constraints\TypeCheck;
77785
77786 interface TypeCheckInterface
77787 {
77788 public static function isObject($value);
77789
77790 public static function isArray($value);
77791
77792 public static function propertyGet($value, $property);
77793
77794 public static function propertySet(&$value, $property, $data);
77795
77796 public static function propertyExists($value, $property);
77797
77798 public static function propertyCount($value);
77799 }
77800 <?php
77801
77802
77803
77804
77805
77806
77807
77808
77809 namespace JsonSchema\Constraints;
77810
77811 use JsonSchema\Entity\JsonPointer;
77812 use JsonSchema\Exception\InvalidArgumentException;
77813 use UnexpectedValueException as StandardUnexpectedValueException;
77814
77815
77816
77817
77818
77819
77820
77821 class TypeConstraint extends Constraint
77822 {
77823
77824
77825
77826 public static $wording = array(
77827 'integer' => 'an integer',
77828 'number' => 'a number',
77829 'boolean' => 'a boolean',
77830 'object' => 'an object',
77831 'array' => 'an array',
77832 'string' => 'a string',
77833 'null' => 'a null',
77834 'any' => null, 
77835  0 => null, 
77836  );
77837
77838
77839
77840
77841 public function check(&$value = null, $schema = null, JsonPointer $path = null, $i = null)
77842 {
77843 $type = isset($schema->type) ? $schema->type : null;
77844 $isValid = false;
77845 $wording = array();
77846
77847 if (is_array($type)) {
77848 $this->validateTypesArray($value, $type, $wording, $isValid, $path);
77849 } elseif (is_object($type)) {
77850 $this->checkUndefined($value, $type, $path);
77851
77852 return;
77853 } else {
77854 $isValid = $this->validateType($value, $type);
77855 }
77856
77857 if ($isValid === false) {
77858 if (!is_array($type)) {
77859 $this->validateTypeNameWording($type);
77860 $wording[] = self::$wording[$type];
77861 }
77862 $this->addError($path, ucwords(gettype($value)) . ' value found, but ' .
77863 $this->implodeWith($wording, ', ', 'or') . ' is required', 'type');
77864 }
77865 }
77866
77867
77868
77869
77870
77871
77872
77873
77874
77875
77876
77877
77878 protected function validateTypesArray(&$value, array $type, &$validTypesWording, &$isValid, $path)
77879 {
77880 foreach ($type as $tp) {
77881
77882  
77883  if (is_object($tp)) {
77884 if (!$isValid) {
77885 $validator = $this->factory->createInstanceFor('type');
77886 $subSchema = new \stdClass();
77887 $subSchema->type = $tp;
77888 $validator->check($value, $subSchema, $path, null);
77889 $error = $validator->getErrors();
77890 $isValid = !(bool) $error;
77891 $validTypesWording[] = self::$wording['object'];
77892 }
77893 } else {
77894 $this->validateTypeNameWording($tp);
77895 $validTypesWording[] = self::$wording[$tp];
77896 if (!$isValid) {
77897 $isValid = $this->validateType($value, $tp);
77898 }
77899 }
77900 }
77901 }
77902
77903
77904
77905
77906
77907
77908
77909
77910
77911
77912
77913
77914 protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = false)
77915 {
77916 if ($listEnd === false || !isset($elements[1])) {
77917 return implode($delimiter, $elements);
77918 }
77919 $lastElement = array_slice($elements, -1);
77920 $firsElements = join($delimiter, array_slice($elements, 0, -1));
77921 $implodedElements = array_merge(array($firsElements), $lastElement);
77922
77923 return join(" $listEnd ", $implodedElements);
77924 }
77925
77926
77927
77928
77929
77930
77931
77932
77933
77934 protected function validateTypeNameWording($type)
77935 {
77936 if (!isset(self::$wording[$type])) {
77937 throw new StandardUnexpectedValueException(
77938 sprintf(
77939 'No wording for %s available, expected wordings are: [%s]',
77940 var_export($type, true),
77941 implode(', ', array_filter(self::$wording)))
77942 );
77943 }
77944 }
77945
77946
77947
77948
77949
77950
77951
77952
77953
77954
77955
77956 protected function validateType(&$value, $type)
77957 {
77958
77959  if (!$type) {
77960 return true;
77961 }
77962
77963 if ('any' === $type) {
77964 return true;
77965 }
77966
77967 if ('object' === $type) {
77968 return $this->getTypeCheck()->isObject($value);
77969 }
77970
77971 if ('array' === $type) {
77972 return $this->getTypeCheck()->isArray($value);
77973 }
77974
77975 $coerce = $this->factory->getConfig(Constraint::CHECK_MODE_COERCE_TYPES);
77976
77977 if ('integer' === $type) {
77978 if ($coerce) {
77979 $value = $this->toInteger($value);
77980 }
77981
77982 return is_int($value);
77983 }
77984
77985 if ('number' === $type) {
77986 if ($coerce) {
77987 $value = $this->toNumber($value);
77988 }
77989
77990 return is_numeric($value) && !is_string($value);
77991 }
77992
77993 if ('boolean' === $type) {
77994 if ($coerce) {
77995 $value = $this->toBoolean($value);
77996 }
77997
77998 return is_bool($value);
77999 }
78000
78001 if ('string' === $type) {
78002 return is_string($value);
78003 }
78004
78005 if ('email' === $type) {
78006 return is_string($value);
78007 }
78008
78009 if ('null' === $type) {
78010 return is_null($value);
78011 }
78012
78013 throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
78014 }
78015
78016
78017
78018
78019
78020
78021
78022
78023 protected function toBoolean($value)
78024 {
78025 if ($value === 'true') {
78026 return true;
78027 }
78028
78029 if ($value === 'false') {
78030 return false;
78031 }
78032
78033 return $value;
78034 }
78035
78036
78037
78038
78039
78040
78041
78042
78043 protected function toNumber($value)
78044 {
78045 if (is_numeric($value)) {
78046 return $value + 0; 
78047  }
78048
78049 return $value;
78050 }
78051
78052 protected function toInteger($value)
78053 {
78054 if (is_numeric($value) && (int) $value == $value) {
78055 return (int) $value; 
78056  }
78057
78058 return $value;
78059 }
78060 }
78061 <?php
78062
78063
78064
78065
78066
78067
78068
78069
78070 namespace JsonSchema\Constraints;
78071
78072 use JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
78073 use JsonSchema\Entity\JsonPointer;
78074 use JsonSchema\Exception\ValidationException;
78075 use JsonSchema\Uri\UriResolver;
78076
78077
78078
78079
78080
78081
78082
78083 class UndefinedConstraint extends Constraint
78084 {
78085
78086
78087
78088 protected $appliedDefaults = array();
78089
78090
78091
78092
78093 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
78094 {
78095 if (is_null($schema) || !is_object($schema)) {
78096 return;
78097 }
78098
78099 $path = $this->incrementPath($path ?: new JsonPointer(''), $i);
78100 if ($fromDefault) {
78101 $path->setFromDefault();
78102 }
78103
78104
78105  $this->validateCommonProperties($value, $schema, $path, $i);
78106
78107
78108  $this->validateOfProperties($value, $schema, $path, '');
78109
78110
78111  $this->validateTypes($value, $schema, $path, $i);
78112 }
78113
78114
78115
78116
78117
78118
78119
78120
78121
78122 public function validateTypes(&$value, $schema = null, JsonPointer $path, $i = null)
78123 {
78124
78125  if ($this->getTypeCheck()->isArray($value)) {
78126 $this->checkArray($value, $schema, $path, $i);
78127 }
78128
78129
78130  if (LooseTypeCheck::isObject($value)) { 
78131  
78132  
78133  $this->checkObject(
78134 $value,
78135 $schema,
78136 $path,
78137 isset($schema->properties) ? $schema->properties : null,
78138 isset($schema->additionalProperties) ? $schema->additionalProperties : null,
78139 isset($schema->patternProperties) ? $schema->patternProperties : null,
78140 $this->appliedDefaults
78141 );
78142 }
78143
78144
78145  if (is_string($value)) {
78146 $this->checkString($value, $schema, $path, $i);
78147 }
78148
78149
78150  if (is_numeric($value)) {
78151 $this->checkNumber($value, $schema, $path, $i);
78152 }
78153
78154
78155  if (isset($schema->enum)) {
78156 $this->checkEnum($value, $schema, $path, $i);
78157 }
78158 }
78159
78160
78161
78162
78163
78164
78165
78166
78167
78168 protected function validateCommonProperties(&$value, $schema = null, JsonPointer $path, $i = '')
78169 {
78170
78171  if (isset($schema->extends)) {
78172 if (is_string($schema->extends)) {
78173 $schema->extends = $this->validateUri($schema, $schema->extends);
78174 }
78175 if (is_array($schema->extends)) {
78176 foreach ($schema->extends as $extends) {
78177 $this->checkUndefined($value, $extends, $path, $i);
78178 }
78179 } else {
78180 $this->checkUndefined($value, $schema->extends, $path, $i);
78181 }
78182 }
78183
78184
78185  if (!$path->fromDefault()) {
78186 $this->applyDefaultValues($value, $schema, $path);
78187 }
78188
78189
78190  if ($this->getTypeCheck()->isObject($value)) {
78191 if (!($value instanceof self) && isset($schema->required) && is_array($schema->required)) {
78192
78193  foreach ($schema->required as $required) {
78194 if (!$this->getTypeCheck()->propertyExists($value, $required)) {
78195 $this->addError(
78196 $this->incrementPath($path ?: new JsonPointer(''), $required),
78197 'The property ' . $required . ' is required',
78198 'required'
78199 );
78200 }
78201 }
78202 } elseif (isset($schema->required) && !is_array($schema->required)) {
78203
78204  if ($schema->required && $value instanceof self) {
78205 $propertyPaths = $path->getPropertyPaths();
78206 $propertyName = end($propertyPaths);
78207 $this->addError(
78208 $path,
78209 'The property ' . $propertyName . ' is required',
78210 'required'
78211 );
78212 }
78213 }
78214 }
78215
78216
78217  if (!($value instanceof self)) {
78218 $this->checkType($value, $schema, $path, $i);
78219 }
78220
78221
78222  if (isset($schema->disallow)) {
78223 $initErrors = $this->getErrors();
78224
78225 $typeSchema = new \stdClass();
78226 $typeSchema->type = $schema->disallow;
78227 $this->checkType($value, $typeSchema, $path);
78228
78229
78230  if (count($this->getErrors()) == count($initErrors)) {
78231 $this->addError($path, 'Disallowed value was matched', 'disallow');
78232 } else {
78233 $this->errors = $initErrors;
78234 }
78235 }
78236
78237 if (isset($schema->not)) {
78238 $initErrors = $this->getErrors();
78239 $this->checkUndefined($value, $schema->not, $path, $i);
78240
78241
78242  if (count($this->getErrors()) == count($initErrors)) {
78243 $this->addError($path, 'Matched a schema which it should not', 'not');
78244 } else {
78245 $this->errors = $initErrors;
78246 }
78247 }
78248
78249
78250  if (isset($schema->dependencies) && $this->getTypeCheck()->isObject($value)) {
78251 $this->validateDependencies($value, $schema->dependencies, $path);
78252 }
78253 }
78254
78255
78256
78257
78258
78259
78260
78261
78262
78263
78264 private function shouldApplyDefaultValue($requiredOnly, $schema, $name = null, $parentSchema = null)
78265 {
78266
78267  if (!$requiredOnly) {
78268 return true;
78269 }
78270
78271  if (
78272 $name !== null
78273 && isset($parentSchema->required)
78274 && is_array($parentSchema->required)
78275 && in_array($name, $parentSchema->required)
78276 ) {
78277 return true;
78278 }
78279
78280  if (isset($schema->required) && !is_array($schema->required) && $schema->required) {
78281 return true;
78282 }
78283
78284  return false;
78285 }
78286
78287
78288
78289
78290
78291
78292
78293
78294 protected function applyDefaultValues(&$value, $schema, $path)
78295 {
78296
78297  if (!$this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
78298 return;
78299 }
78300
78301
78302  $requiredOnly = $this->factory->getConfig(self::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);
78303 if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
78304
78305  foreach ($schema->properties as $currentProperty => $propertyDefinition) {
78306 if (
78307 !LooseTypeCheck::propertyExists($value, $currentProperty)
78308 && property_exists($propertyDefinition, 'default')
78309 && $this->shouldApplyDefaultValue($requiredOnly, $propertyDefinition, $currentProperty, $schema)
78310 ) {
78311
78312  if (is_object($propertyDefinition->default)) {
78313 LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
78314 } else {
78315 LooseTypeCheck::propertySet($value, $currentProperty, $propertyDefinition->default);
78316 }
78317 $this->appliedDefaults[] = $currentProperty;
78318 }
78319 }
78320 } elseif (isset($schema->items) && LooseTypeCheck::isArray($value)) {
78321 $items = array();
78322 if (LooseTypeCheck::isArray($schema->items)) {
78323 $items = $schema->items;
78324 } elseif (isset($schema->minItems) && count($value) < $schema->minItems) {
78325 $items = array_fill(count($value), $schema->minItems - count($value), $schema->items);
78326 }
78327
78328  foreach ($items as $currentItem => $itemDefinition) {
78329 if (
78330 !array_key_exists($currentItem, $value)
78331 && property_exists($itemDefinition, 'default')
78332 && $this->shouldApplyDefaultValue($requiredOnly, $itemDefinition)) {
78333 if (is_object($itemDefinition->default)) {
78334 $value[$currentItem] = clone $itemDefinition->default;
78335 } else {
78336 $value[$currentItem] = $itemDefinition->default;
78337 }
78338 }
78339 $path->setFromDefault();
78340 }
78341 } elseif (
78342 $value instanceof self
78343 && property_exists($schema, 'default')
78344 && $this->shouldApplyDefaultValue($requiredOnly, $schema)) {
78345
78346  $value = is_object($schema->default) ? clone $schema->default : $schema->default;
78347 $path->setFromDefault();
78348 }
78349 }
78350
78351
78352
78353
78354
78355
78356
78357
78358
78359 protected function validateOfProperties(&$value, $schema, JsonPointer $path, $i = '')
78360 {
78361
78362  if ($value instanceof self) {
78363 return;
78364 }
78365
78366 if (isset($schema->allOf)) {
78367 $isValid = true;
78368 foreach ($schema->allOf as $allOf) {
78369 $initErrors = $this->getErrors();
78370 $this->checkUndefined($value, $allOf, $path, $i);
78371 $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
78372 }
78373 if (!$isValid) {
78374 $this->addError($path, 'Failed to match all schemas', 'allOf');
78375 }
78376 }
78377
78378 if (isset($schema->anyOf)) {
78379 $isValid = false;
78380 $startErrors = $this->getErrors();
78381 $caughtException = null;
78382 foreach ($schema->anyOf as $anyOf) {
78383 $initErrors = $this->getErrors();
78384 try {
78385 $this->checkUndefined($value, $anyOf, $path, $i);
78386 if ($isValid = (count($this->getErrors()) == count($initErrors))) {
78387 break;
78388 }
78389 } catch (ValidationException $e) {
78390 $isValid = false;
78391 }
78392 }
78393 if (!$isValid) {
78394 $this->addError($path, 'Failed to match at least one schema', 'anyOf');
78395 } else {
78396 $this->errors = $startErrors;
78397 }
78398 }
78399
78400 if (isset($schema->oneOf)) {
78401 $allErrors = array();
78402 $matchedSchemas = 0;
78403 $startErrors = $this->getErrors();
78404 foreach ($schema->oneOf as $oneOf) {
78405 try {
78406 $this->errors = array();
78407 $this->checkUndefined($value, $oneOf, $path, $i);
78408 if (count($this->getErrors()) == 0) {
78409 $matchedSchemas++;
78410 }
78411 $allErrors = array_merge($allErrors, array_values($this->getErrors()));
78412 } catch (ValidationException $e) {
78413
78414  
78415  }
78416 }
78417 if ($matchedSchemas !== 1) {
78418 $this->addErrors(array_merge($allErrors, $startErrors));
78419 $this->addError($path, 'Failed to match exactly one schema', 'oneOf');
78420 } else {
78421 $this->errors = $startErrors;
78422 }
78423 }
78424 }
78425
78426
78427
78428
78429
78430
78431
78432
78433
78434 protected function validateDependencies($value, $dependencies, JsonPointer $path, $i = '')
78435 {
78436 foreach ($dependencies as $key => $dependency) {
78437 if ($this->getTypeCheck()->propertyExists($value, $key)) {
78438 if (is_string($dependency)) {
78439
78440  if (!$this->getTypeCheck()->propertyExists($value, $dependency)) {
78441 $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
78442 }
78443 } elseif (is_array($dependency)) {
78444
78445  foreach ($dependency as $d) {
78446 if (!$this->getTypeCheck()->propertyExists($value, $d)) {
78447 $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
78448 }
78449 }
78450 } elseif (is_object($dependency)) {
78451
78452  $this->checkUndefined($value, $dependency, $path, $i);
78453 }
78454 }
78455 }
78456 }
78457
78458 protected function validateUri($schema, $schemaUri = null)
78459 {
78460 $resolver = new UriResolver();
78461 $retriever = $this->factory->getUriRetriever();
78462
78463 $jsonSchema = null;
78464 if ($resolver->isValid($schemaUri)) {
78465 $schemaId = property_exists($schema, 'id') ? $schema->id : null;
78466 $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
78467 }
78468
78469 return $jsonSchema;
78470 }
78471 }
78472 <?php
78473
78474
78475
78476
78477
78478
78479
78480
78481 namespace JsonSchema\Entity;
78482
78483 use JsonSchema\Exception\InvalidArgumentException;
78484
78485
78486
78487
78488
78489
78490 class JsonPointer
78491 {
78492
78493 private $filename;
78494
78495
78496 private $propertyPaths = array();
78497
78498
78499
78500
78501 private $fromDefault = false;
78502
78503
78504
78505
78506
78507
78508 public function __construct($value)
78509 {
78510 if (!is_string($value)) {
78511 throw new InvalidArgumentException('Ref value must be a string');
78512 }
78513
78514 $splitRef = explode('#', $value, 2);
78515 $this->filename = $splitRef[0];
78516 if (array_key_exists(1, $splitRef)) {
78517 $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
78518 }
78519 }
78520
78521
78522
78523
78524
78525
78526 private function decodePropertyPaths($propertyPathString)
78527 {
78528 $paths = array();
78529 foreach (explode('/', trim($propertyPathString, '/')) as $path) {
78530 $path = $this->decodePath($path);
78531 if (is_string($path) && '' !== $path) {
78532 $paths[] = $path;
78533 }
78534 }
78535
78536 return $paths;
78537 }
78538
78539
78540
78541
78542 private function encodePropertyPaths()
78543 {
78544 return array_map(
78545 array($this, 'encodePath'),
78546 $this->getPropertyPaths()
78547 );
78548 }
78549
78550
78551
78552
78553
78554
78555 private function decodePath($path)
78556 {
78557 return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
78558 }
78559
78560
78561
78562
78563
78564
78565 private function encodePath($path)
78566 {
78567 return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
78568 }
78569
78570
78571
78572
78573 public function getFilename()
78574 {
78575 return $this->filename;
78576 }
78577
78578
78579
78580
78581 public function getPropertyPaths()
78582 {
78583 return $this->propertyPaths;
78584 }
78585
78586
78587
78588
78589
78590
78591 public function withPropertyPaths(array $propertyPaths)
78592 {
78593 $new = clone $this;
78594 $new->propertyPaths = $propertyPaths;
78595
78596 return $new;
78597 }
78598
78599
78600
78601
78602 public function getPropertyPathAsString()
78603 {
78604 return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
78605 }
78606
78607
78608
78609
78610 public function __toString()
78611 {
78612 return $this->getFilename() . $this->getPropertyPathAsString();
78613 }
78614
78615
78616
78617
78618 public function setFromDefault()
78619 {
78620 $this->fromDefault = true;
78621 }
78622
78623
78624
78625
78626
78627
78628 public function fromDefault()
78629 {
78630 return $this->fromDefault;
78631 }
78632 }
78633 <?php
78634
78635 namespace JsonSchema\Exception;
78636
78637 interface ExceptionInterface
78638 {
78639 }
78640 <?php
78641
78642
78643
78644
78645
78646
78647
78648
78649 namespace JsonSchema\Exception;
78650
78651
78652
78653
78654 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
78655 {
78656 }
78657 <?php
78658
78659
78660
78661
78662
78663
78664
78665
78666 namespace JsonSchema\Exception;
78667
78668
78669
78670
78671 class InvalidConfigException extends RuntimeException
78672 {
78673 }
78674 <?php
78675
78676
78677
78678
78679
78680
78681
78682
78683 namespace JsonSchema\Exception;
78684
78685
78686
78687
78688 class InvalidSchemaException extends RuntimeException
78689 {
78690 }
78691 <?php
78692
78693
78694
78695
78696
78697
78698
78699
78700 namespace JsonSchema\Exception;
78701
78702
78703
78704
78705 class InvalidSchemaMediaTypeException extends RuntimeException
78706 {
78707 }
78708 <?php
78709
78710
78711
78712
78713
78714
78715
78716
78717 namespace JsonSchema\Exception;
78718
78719
78720
78721
78722 class InvalidSourceUriException extends InvalidArgumentException
78723 {
78724 }
78725 <?php
78726
78727
78728
78729
78730
78731
78732
78733
78734 namespace JsonSchema\Exception;
78735
78736
78737
78738
78739 class JsonDecodingException extends RuntimeException
78740 {
78741 public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
78742 {
78743 switch ($code) {
78744 case JSON_ERROR_DEPTH:
78745 $message = 'The maximum stack depth has been exceeded';
78746 break;
78747 case JSON_ERROR_STATE_MISMATCH:
78748 $message = 'Invalid or malformed JSON';
78749 break;
78750 case JSON_ERROR_CTRL_CHAR:
78751 $message = 'Control character error, possibly incorrectly encoded';
78752 break;
78753 case JSON_ERROR_UTF8:
78754 $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
78755 break;
78756 case JSON_ERROR_SYNTAX:
78757 $message = 'JSON syntax is malformed';
78758 break;
78759 default:
78760 $message = 'Syntax error';
78761 }
78762 parent::__construct($message, $code, $previous);
78763 }
78764 }
78765 <?php
78766
78767
78768
78769
78770
78771
78772
78773
78774 namespace JsonSchema\Exception;
78775
78776
78777
78778
78779 class ResourceNotFoundException extends RuntimeException
78780 {
78781 }
78782 <?php
78783
78784
78785
78786
78787
78788
78789
78790
78791 namespace JsonSchema\Exception;
78792
78793
78794
78795
78796 class RuntimeException extends \RuntimeException implements ExceptionInterface
78797 {
78798 }
78799 <?php
78800
78801
78802
78803
78804
78805
78806
78807
78808 namespace JsonSchema\Exception;
78809
78810
78811
78812
78813
78814
78815 class UnresolvableJsonPointerException extends InvalidArgumentException
78816 {
78817 }
78818 <?php
78819
78820
78821
78822
78823
78824
78825
78826
78827 namespace JsonSchema\Exception;
78828
78829
78830
78831
78832 class UriResolverException extends RuntimeException
78833 {
78834 }
78835 <?php
78836
78837
78838
78839
78840
78841
78842
78843
78844 namespace JsonSchema\Exception;
78845
78846 class ValidationException extends RuntimeException
78847 {
78848 }
78849 <?php
78850
78851
78852
78853
78854
78855
78856
78857
78858 namespace JsonSchema\Iterator;
78859
78860
78861
78862
78863
78864
78865 class ObjectIterator implements \Iterator, \Countable
78866 {
78867
78868 private $object;
78869
78870
78871 private $position = 0;
78872
78873
78874 private $data = array();
78875
78876
78877 private $initialized = false;
78878
78879
78880
78881
78882 public function __construct($object)
78883 {
78884 $this->object = $object;
78885 }
78886
78887
78888
78889
78890 public function current()
78891 {
78892 $this->initialize();
78893
78894 return $this->data[$this->position];
78895 }
78896
78897
78898
78899
78900 public function next()
78901 {
78902 $this->initialize();
78903 $this->position++;
78904 }
78905
78906
78907
78908
78909 public function key()
78910 {
78911 $this->initialize();
78912
78913 return $this->position;
78914 }
78915
78916
78917
78918
78919 public function valid()
78920 {
78921 $this->initialize();
78922
78923 return isset($this->data[$this->position]);
78924 }
78925
78926
78927
78928
78929 public function rewind()
78930 {
78931 $this->initialize();
78932 $this->position = 0;
78933 }
78934
78935
78936
78937
78938 public function count()
78939 {
78940 $this->initialize();
78941
78942 return count($this->data);
78943 }
78944
78945
78946
78947
78948 private function initialize()
78949 {
78950 if (!$this->initialized) {
78951 $this->data = $this->buildDataFromObject($this->object);
78952 $this->initialized = true;
78953 }
78954 }
78955
78956
78957
78958
78959
78960
78961 private function buildDataFromObject($object)
78962 {
78963 $result = array();
78964
78965 $stack = new \SplStack();
78966 $stack->push($object);
78967
78968 while (!$stack->isEmpty()) {
78969 $current = $stack->pop();
78970 if (is_object($current)) {
78971 array_push($result, $current);
78972 }
78973
78974 foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
78975 if (is_object($propertyValue) || is_array($propertyValue)) {
78976 $stack->push($propertyValue);
78977 }
78978 }
78979 }
78980
78981 return $result;
78982 }
78983
78984
78985
78986
78987
78988
78989 private function getDataFromItem($item)
78990 {
78991 if (!is_object($item) && !is_array($item)) {
78992 return array();
78993 }
78994
78995 return is_object($item) ? get_object_vars($item) : $item;
78996 }
78997 }
78998 <?php
78999
79000 namespace JsonSchema;
79001
79002 class Rfc3339
79003 {
79004 const REGEX = '/^(\d{4}-\d{2}-\d{2}[T ]{1}\d{2}:\d{2}:\d{2})(\.\d+)?(Z|([+-]\d{2}):?(\d{2}))$/';
79005
79006
79007
79008
79009
79010
79011
79012
79013 public static function createFromString($string)
79014 {
79015 if (!preg_match(self::REGEX, strtoupper($string), $matches)) {
79016 return null;
79017 }
79018
79019 $dateAndTime = $matches[1];
79020 $microseconds = $matches[2] ?: '.000000';
79021 $timeZone = 'Z' !== $matches[3] ? $matches[4] . ':' . $matches[5] : '+00:00';
79022 $dateFormat = strpos($dateAndTime, 'T') === false ? 'Y-m-d H:i:s.uP' : 'Y-m-d\TH:i:s.uP';
79023 $dateTime = \DateTime::createFromFormat($dateFormat, $dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
79024
79025 return $dateTime ?: null;
79026 }
79027 }
79028 <?php
79029
79030 namespace JsonSchema;
79031
79032 use JsonSchema\Constraints\BaseConstraint;
79033 use JsonSchema\Entity\JsonPointer;
79034 use JsonSchema\Exception\UnresolvableJsonPointerException;
79035 use JsonSchema\Uri\UriResolver;
79036 use JsonSchema\Uri\UriRetriever;
79037
79038 class SchemaStorage implements SchemaStorageInterface
79039 {
79040 const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema/';
79041
79042 protected $uriRetriever;
79043 protected $uriResolver;
79044 protected $schemas = array();
79045
79046 public function __construct(
79047 UriRetrieverInterface $uriRetriever = null,
79048 UriResolverInterface $uriResolver = null
79049 ) {
79050 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
79051 $this->uriResolver = $uriResolver ?: new UriResolver();
79052 }
79053
79054
79055
79056
79057 public function getUriRetriever()
79058 {
79059 return $this->uriRetriever;
79060 }
79061
79062
79063
79064
79065 public function getUriResolver()
79066 {
79067 return $this->uriResolver;
79068 }
79069
79070
79071
79072
79073 public function addSchema($id, $schema = null)
79074 {
79075 if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) {
79076
79077  
79078  
79079  $schema = $this->uriRetriever->retrieve($id);
79080 }
79081
79082
79083  if (is_array($schema)) {
79084 $schema = BaseConstraint::arrayToObjectRecursive($schema);
79085 }
79086
79087
79088  
79089  if (is_object($schema) && property_exists($schema, 'id')) {
79090 if ($schema->id == 'http://json-schema.org/draft-04/schema#') {
79091 $schema->properties->id->format = 'uri-reference';
79092 } elseif ($schema->id == 'http://json-schema.org/draft-03/schema#') {
79093 $schema->properties->id->format = 'uri-reference';
79094 $schema->properties->{'$ref'}->format = 'uri-reference';
79095 }
79096 }
79097
79098
79099  $this->expandRefs($schema, $id);
79100
79101 $this->schemas[$id] = $schema;
79102 }
79103
79104
79105
79106
79107
79108
79109
79110 private function expandRefs(&$schema, $base = null)
79111 {
79112 if (!is_object($schema)) {
79113 if (is_array($schema)) {
79114 foreach ($schema as &$member) {
79115 $this->expandRefs($member, $base);
79116 }
79117 }
79118
79119 return;
79120 }
79121
79122 if (property_exists($schema, 'id') && is_string($schema->id) && $base != $schema->id) {
79123 $base = $this->uriResolver->resolve($schema->id, $base);
79124 }
79125
79126 if (property_exists($schema, '$ref') && is_string($schema->{'$ref'})) {
79127 $refPointer = new JsonPointer($this->uriResolver->resolve($schema->{'$ref'}, $base));
79128 $schema->{'$ref'} = (string) $refPointer;
79129 }
79130
79131 foreach ($schema as &$member) {
79132 $this->expandRefs($member, $base);
79133 }
79134 }
79135
79136
79137
79138
79139 public function getSchema($id)
79140 {
79141 if (!array_key_exists($id, $this->schemas)) {
79142 $this->addSchema($id);
79143 }
79144
79145 return $this->schemas[$id];
79146 }
79147
79148
79149
79150
79151 public function resolveRef($ref)
79152 {
79153 $jsonPointer = new JsonPointer($ref);
79154
79155
79156  $fileName = $jsonPointer->getFilename();
79157 if (!strlen($fileName)) {
79158 throw new UnresolvableJsonPointerException(sprintf(
79159 "Could not resolve fragment '%s': no file is defined",
79160 $jsonPointer->getPropertyPathAsString()
79161 ));
79162 }
79163
79164
79165  $refSchema = $this->getSchema($fileName);
79166 foreach ($jsonPointer->getPropertyPaths() as $path) {
79167 if (is_object($refSchema) && property_exists($refSchema, $path)) {
79168 $refSchema = $this->resolveRefSchema($refSchema->{$path});
79169 } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) {
79170 $refSchema = $this->resolveRefSchema($refSchema[$path]);
79171 } else {
79172 throw new UnresolvableJsonPointerException(sprintf(
79173 'File: %s is found, but could not resolve fragment: %s',
79174 $jsonPointer->getFilename(),
79175 $jsonPointer->getPropertyPathAsString()
79176 ));
79177 }
79178 }
79179
79180 return $refSchema;
79181 }
79182
79183
79184
79185
79186 public function resolveRefSchema($refSchema)
79187 {
79188 if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) {
79189 $newSchema = $this->resolveRef($refSchema->{'$ref'});
79190 $refSchema = (object) (get_object_vars($refSchema) + get_object_vars($newSchema));
79191 unset($refSchema->{'$ref'});
79192 }
79193
79194 return $refSchema;
79195 }
79196 }
79197 <?php
79198
79199 namespace JsonSchema;
79200
79201 interface SchemaStorageInterface
79202 {
79203
79204
79205
79206
79207
79208
79209 public function addSchema($id, $schema = null);
79210
79211
79212
79213
79214
79215
79216
79217
79218 public function getSchema($id);
79219
79220
79221
79222
79223
79224
79225
79226
79227 public function resolveRef($ref);
79228
79229
79230
79231
79232
79233
79234
79235
79236 public function resolveRefSchema($refSchema);
79237 }
79238 <?php
79239
79240
79241
79242
79243
79244
79245 namespace JsonSchema\Uri\Retrievers;
79246
79247
79248
79249
79250
79251
79252
79253 abstract class AbstractRetriever implements UriRetrieverInterface
79254 {
79255
79256
79257
79258
79259
79260 protected $contentType;
79261
79262
79263
79264
79265
79266
79267 public function getContentType()
79268 {
79269 return $this->contentType;
79270 }
79271 }
79272 <?php
79273
79274
79275
79276
79277
79278
79279
79280
79281 namespace JsonSchema\Uri\Retrievers;
79282
79283 use JsonSchema\Exception\RuntimeException;
79284 use JsonSchema\Validator;
79285
79286
79287
79288
79289
79290
79291 class Curl extends AbstractRetriever
79292 {
79293 protected $messageBody;
79294
79295 public function __construct()
79296 {
79297 if (!function_exists('curl_init')) {
79298
79299  throw new RuntimeException('cURL not installed'); 
79300  }
79301 }
79302
79303
79304
79305
79306
79307
79308 public function retrieve($uri)
79309 {
79310 $ch = curl_init();
79311
79312 curl_setopt($ch, CURLOPT_URL, $uri);
79313 curl_setopt($ch, CURLOPT_HEADER, true);
79314 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
79315 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
79316
79317 $response = curl_exec($ch);
79318 if (false === $response) {
79319 throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
79320 }
79321
79322 $this->fetchMessageBody($response);
79323 $this->fetchContentType($response);
79324
79325 curl_close($ch);
79326
79327 return $this->messageBody;
79328 }
79329
79330
79331
79332
79333 private function fetchMessageBody($response)
79334 {
79335 preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
79336 $this->messageBody = $match[1];
79337 }
79338
79339
79340
79341
79342
79343
79344 protected function fetchContentType($response)
79345 {
79346 if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
79347 $this->contentType = trim($match[1]);
79348
79349 return true;
79350 }
79351
79352 return false;
79353 }
79354 }
79355 <?php
79356
79357
79358
79359
79360
79361
79362
79363
79364 namespace JsonSchema\Uri\Retrievers;
79365
79366 use JsonSchema\Exception\ResourceNotFoundException;
79367
79368
79369
79370
79371
79372
79373 class FileGetContents extends AbstractRetriever
79374 {
79375 protected $messageBody;
79376
79377
79378
79379
79380
79381
79382 public function retrieve($uri)
79383 {
79384 $errorMessage = null;
79385 set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
79386 $errorMessage = $errstr;
79387 });
79388 $response = file_get_contents($uri);
79389 restore_error_handler();
79390
79391 if ($errorMessage) {
79392 throw new ResourceNotFoundException($errorMessage);
79393 }
79394
79395 if (false === $response) {
79396 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
79397 }
79398
79399 if ($response == ''
79400 && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
79401 ) {
79402 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
79403 }
79404
79405 $this->messageBody = $response;
79406 if (!empty($http_response_header)) {
79407
79408  
79409  $this->fetchContentType($http_response_header); 
79410  } else { 
79411  
79412  $this->contentType = null;
79413 }
79414
79415 return $this->messageBody;
79416 }
79417
79418
79419
79420
79421
79422
79423 private function fetchContentType(array $headers)
79424 {
79425 foreach ($headers as $header) {
79426 if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
79427 return true;
79428 }
79429 }
79430
79431 return false;
79432 }
79433
79434
79435
79436
79437
79438
79439 protected static function getContentTypeMatchInHeader($header)
79440 {
79441 if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
79442 return trim($match[1]);
79443 }
79444
79445 return null;
79446 }
79447 }
79448 <?php
79449
79450 namespace JsonSchema\Uri\Retrievers;
79451
79452 use JsonSchema\Validator;
79453
79454
79455
79456
79457
79458
79459
79460
79461
79462
79463
79464
79465
79466 class PredefinedArray extends AbstractRetriever
79467 {
79468
79469
79470
79471
79472
79473 private $schemas;
79474
79475
79476
79477
79478
79479
79480
79481 public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
79482 {
79483 $this->schemas = $schemas;
79484 $this->contentType = $contentType;
79485 }
79486
79487
79488
79489
79490
79491
79492 public function retrieve($uri)
79493 {
79494 if (!array_key_exists($uri, $this->schemas)) {
79495 throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
79496 'The JSON schema "%s" was not found.',
79497 $uri
79498 ));
79499 }
79500
79501 return $this->schemas[$uri];
79502 }
79503 }
79504 <?php
79505
79506
79507
79508
79509
79510
79511
79512
79513 namespace JsonSchema\Uri\Retrievers;
79514
79515
79516
79517
79518
79519
79520 interface UriRetrieverInterface
79521 {
79522
79523
79524
79525
79526
79527
79528
79529
79530
79531 public function retrieve($uri);
79532
79533
79534
79535
79536
79537
79538 public function getContentType();
79539 }
79540 <?php
79541
79542
79543
79544
79545
79546
79547
79548
79549 namespace JsonSchema\Uri;
79550
79551 use JsonSchema\Exception\UriResolverException;
79552 use JsonSchema\UriResolverInterface;
79553
79554
79555
79556
79557
79558
79559 class UriResolver implements UriResolverInterface
79560 {
79561
79562
79563
79564
79565
79566
79567
79568 public function parse($uri)
79569 {
79570 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
79571
79572 $components = array();
79573 if (5 < count($match)) {
79574 $components = array(
79575 'scheme' => $match[2],
79576 'authority' => $match[4],
79577 'path' => $match[5]
79578 );
79579 }
79580 if (7 < count($match)) {
79581 $components['query'] = $match[7];
79582 }
79583 if (9 < count($match)) {
79584 $components['fragment'] = $match[9];
79585 }
79586
79587 return $components;
79588 }
79589
79590
79591
79592
79593
79594
79595
79596
79597 public function generate(array $components)
79598 {
79599 $uri = $components['scheme'] . '://'
79600 . $components['authority']
79601 . $components['path'];
79602
79603 if (array_key_exists('query', $components) && strlen($components['query'])) {
79604 $uri .= '?' . $components['query'];
79605 }
79606 if (array_key_exists('fragment', $components)) {
79607 $uri .= '#' . $components['fragment'];
79608 }
79609
79610 return $uri;
79611 }
79612
79613
79614
79615
79616 public function resolve($uri, $baseUri = null)
79617 {
79618
79619  if (
79620 !is_null($baseUri) &&
79621 !filter_var($baseUri, \FILTER_VALIDATE_URL) &&
79622 !preg_match('|^[^/]+://|u', $baseUri)
79623 ) {
79624 if (is_file($baseUri)) {
79625 $baseUri = 'file://' . realpath($baseUri);
79626 } elseif (is_dir($baseUri)) {
79627 $baseUri = 'file://' . realpath($baseUri) . '/';
79628 } else {
79629 $baseUri = 'file://' . getcwd() . '/' . $baseUri;
79630 }
79631 }
79632
79633 if ($uri == '') {
79634 return $baseUri;
79635 }
79636
79637 $components = $this->parse($uri);
79638 $path = $components['path'];
79639
79640 if (!empty($components['scheme'])) {
79641 return $uri;
79642 }
79643 $baseComponents = $this->parse($baseUri);
79644 $basePath = $baseComponents['path'];
79645
79646 $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
79647 if (isset($components['fragment'])) {
79648 $baseComponents['fragment'] = $components['fragment'];
79649 }
79650
79651 return $this->generate($baseComponents);
79652 }
79653
79654
79655
79656
79657
79658
79659
79660
79661
79662
79663
79664 public static function combineRelativePathWithBasePath($relativePath, $basePath)
79665 {
79666 $relativePath = self::normalizePath($relativePath);
79667 if ($relativePath == '') {
79668 return $basePath;
79669 }
79670 if ($relativePath[0] == '/') {
79671 return $relativePath;
79672 }
79673
79674 $basePathSegments = explode('/', $basePath);
79675
79676 preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
79677 $numLevelUp = strlen($match[0]) /3 + 1;
79678 if ($numLevelUp >= count($basePathSegments)) {
79679 throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
79680 }
79681
79682 $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
79683 $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
79684
79685 return implode('/', $basePathSegments) . '/' . $path;
79686 }
79687
79688
79689
79690
79691
79692
79693
79694
79695 private static function normalizePath($path)
79696 {
79697 $path = preg_replace('|((?<!\.)\./)*|', '', $path);
79698 $path = preg_replace('|//|', '/', $path);
79699
79700 return $path;
79701 }
79702
79703
79704
79705
79706
79707
79708 public function isValid($uri)
79709 {
79710 $components = $this->parse($uri);
79711
79712 return !empty($components);
79713 }
79714 }
79715 <?php
79716
79717
79718
79719
79720
79721
79722
79723
79724 namespace JsonSchema\Uri;
79725
79726 use JsonSchema\Exception\InvalidSchemaMediaTypeException;
79727 use JsonSchema\Exception\JsonDecodingException;
79728 use JsonSchema\Exception\ResourceNotFoundException;
79729 use JsonSchema\Uri\Retrievers\FileGetContents;
79730 use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
79731 use JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
79732 use JsonSchema\Validator;
79733
79734
79735
79736
79737
79738
79739 class UriRetriever implements BaseUriRetrieverInterface
79740 {
79741
79742
79743
79744 protected $translationMap = array(
79745
79746  '|^https?://json-schema.org/draft-(0[34])/schema#?|' => 'package://dist/schema/json-schema-draft-$1.json'
79747 );
79748
79749
79750
79751
79752 protected $uriRetriever = null;
79753
79754
79755
79756
79757
79758
79759 private $schemaCache = array();
79760
79761
79762
79763
79764
79765
79766
79767
79768
79769 public function confirmMediaType($uriRetriever, $uri)
79770 {
79771 $contentType = $uriRetriever->getContentType();
79772
79773 if (is_null($contentType)) {
79774
79775  return;
79776 }
79777
79778 if (in_array($contentType, array(Validator::SCHEMA_MEDIA_TYPE, 'application/json'))) {
79779 return;
79780 }
79781
79782 if (substr($uri, 0, 23) == 'http://json-schema.org/') {
79783
79784  return true;
79785 }
79786
79787 throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
79788 }
79789
79790
79791
79792
79793
79794
79795
79796
79797
79798 public function getUriRetriever()
79799 {
79800 if (is_null($this->uriRetriever)) {
79801 $this->setUriRetriever(new FileGetContents());
79802 }
79803
79804 return $this->uriRetriever;
79805 }
79806
79807
79808
79809
79810
79811
79812
79813
79814
79815
79816
79817
79818
79819
79820
79821 public function resolvePointer($jsonSchema, $uri)
79822 {
79823 $resolver = new UriResolver();
79824 $parsed = $resolver->parse($uri);
79825 if (empty($parsed['fragment'])) {
79826 return $jsonSchema;
79827 }
79828
79829 $path = explode('/', $parsed['fragment']);
79830 while ($path) {
79831 $pathElement = array_shift($path);
79832 if (!empty($pathElement)) {
79833 $pathElement = str_replace('~1', '/', $pathElement);
79834 $pathElement = str_replace('~0', '~', $pathElement);
79835 if (!empty($jsonSchema->$pathElement)) {
79836 $jsonSchema = $jsonSchema->$pathElement;
79837 } else {
79838 throw new ResourceNotFoundException(
79839 'Fragment "' . $parsed['fragment'] . '" not found'
79840 . ' in ' . $uri
79841 );
79842 }
79843
79844 if (!is_object($jsonSchema)) {
79845 throw new ResourceNotFoundException(
79846 'Fragment part "' . $pathElement . '" is no object '
79847 . ' in ' . $uri
79848 );
79849 }
79850 }
79851 }
79852
79853 return $jsonSchema;
79854 }
79855
79856
79857
79858
79859 public function retrieve($uri, $baseUri = null, $translate = true)
79860 {
79861 $resolver = new UriResolver();
79862 $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
79863
79864
79865  $arParts = $resolver->parse($resolvedUri);
79866 if (isset($arParts['fragment'])) {
79867 unset($arParts['fragment']);
79868 $fetchUri = $resolver->generate($arParts);
79869 }
79870
79871
79872  if ($translate) {
79873 $fetchUri = $this->translate($fetchUri);
79874 }
79875
79876 $jsonSchema = $this->loadSchema($fetchUri);
79877
79878
79879  $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
79880
79881 if ($jsonSchema instanceof \stdClass) {
79882 $jsonSchema->id = $resolvedUri;
79883 }
79884
79885 return $jsonSchema;
79886 }
79887
79888
79889
79890
79891
79892
79893
79894
79895
79896 protected function loadSchema($fetchUri)
79897 {
79898 if (isset($this->schemaCache[$fetchUri])) {
79899 return $this->schemaCache[$fetchUri];
79900 }
79901
79902 $uriRetriever = $this->getUriRetriever();
79903 $contents = $this->uriRetriever->retrieve($fetchUri);
79904 $this->confirmMediaType($uriRetriever, $fetchUri);
79905 $jsonSchema = json_decode($contents);
79906
79907 if (JSON_ERROR_NONE < $error = json_last_error()) {
79908 throw new JsonDecodingException($error);
79909 }
79910
79911 $this->schemaCache[$fetchUri] = $jsonSchema;
79912
79913 return $jsonSchema;
79914 }
79915
79916
79917
79918
79919
79920
79921
79922
79923 public function setUriRetriever(UriRetrieverInterface $uriRetriever)
79924 {
79925 $this->uriRetriever = $uriRetriever;
79926
79927 return $this;
79928 }
79929
79930
79931
79932
79933
79934
79935
79936
79937 public function parse($uri)
79938 {
79939 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
79940
79941 $components = array();
79942 if (5 < count($match)) {
79943 $components = array(
79944 'scheme' => $match[2],
79945 'authority' => $match[4],
79946 'path' => $match[5]
79947 );
79948 }
79949
79950 if (7 < count($match)) {
79951 $components['query'] = $match[7];
79952 }
79953
79954 if (9 < count($match)) {
79955 $components['fragment'] = $match[9];
79956 }
79957
79958 return $components;
79959 }
79960
79961
79962
79963
79964
79965
79966
79967
79968 public function generate(array $components)
79969 {
79970 $uri = $components['scheme'] . '://'
79971 . $components['authority']
79972 . $components['path'];
79973
79974 if (array_key_exists('query', $components)) {
79975 $uri .= $components['query'];
79976 }
79977
79978 if (array_key_exists('fragment', $components)) {
79979 $uri .= $components['fragment'];
79980 }
79981
79982 return $uri;
79983 }
79984
79985
79986
79987
79988
79989
79990
79991
79992
79993 public function resolve($uri, $baseUri = null)
79994 {
79995 $components = $this->parse($uri);
79996 $path = $components['path'];
79997
79998 if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
79999 return $uri;
80000 }
80001
80002 $baseComponents = $this->parse($baseUri);
80003 $basePath = $baseComponents['path'];
80004
80005 $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
80006
80007 return $this->generate($baseComponents);
80008 }
80009
80010
80011
80012
80013
80014
80015 public function isValid($uri)
80016 {
80017 $components = $this->parse($uri);
80018
80019 return !empty($components);
80020 }
80021
80022
80023
80024
80025 public function setTranslation($from, $to)
80026 {
80027 $this->translationMap[$from] = $to;
80028 }
80029
80030
80031
80032
80033 public function translate($uri)
80034 {
80035 foreach ($this->translationMap as $from => $to) {
80036 $uri = preg_replace($from, $to, $uri);
80037 }
80038
80039
80040  $uri = preg_replace('|^package://|', sprintf('file://%s/', realpath(__DIR__ . '/../../..')), $uri);
80041
80042 return $uri;
80043 }
80044 }
80045 <?php
80046
80047
80048
80049
80050
80051
80052
80053
80054 namespace JsonSchema;
80055
80056
80057
80058
80059 interface UriResolverInterface
80060 {
80061
80062
80063
80064
80065
80066
80067
80068
80069 public function resolve($uri, $baseUri = null);
80070 }
80071 <?php
80072
80073
80074
80075
80076
80077
80078
80079
80080 namespace JsonSchema;
80081
80082
80083
80084
80085 interface UriRetrieverInterface
80086 {
80087
80088
80089
80090
80091
80092
80093
80094
80095 public function retrieve($uri, $baseUri = null);
80096 }
80097 <?php
80098
80099
80100
80101
80102
80103
80104
80105
80106 namespace JsonSchema;
80107
80108 use JsonSchema\Constraints\BaseConstraint;
80109 use JsonSchema\Constraints\Constraint;
80110 use JsonSchema\Exception\InvalidConfigException;
80111 use JsonSchema\SchemaStorage;
80112
80113
80114
80115
80116
80117
80118
80119
80120
80121 class Validator extends BaseConstraint
80122 {
80123 const SCHEMA_MEDIA_TYPE = 'application/schema+json';
80124
80125 const ERROR_NONE = 0x00000000;
80126 const ERROR_ALL = 0xFFFFFFFF;
80127 const ERROR_DOCUMENT_VALIDATION = 0x00000001;
80128 const ERROR_SCHEMA_VALIDATION = 0x00000002;
80129
80130
80131
80132
80133
80134
80135
80136
80137
80138
80139 public function validate(&$value, $schema = null, $checkMode = null)
80140 {
80141
80142  if (is_array($schema)) {
80143 $schema = self::arrayToObjectRecursive($schema);
80144 }
80145
80146
80147  $initialCheckMode = $this->factory->getConfig();
80148 if ($checkMode !== null) {
80149 $this->factory->setConfig($checkMode);
80150 }
80151
80152
80153  if (is_object($schema) && property_exists($schema, 'id')) {
80154 $schemaURI = $schema->id;
80155 } else {
80156 $schemaURI = SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI;
80157 }
80158 $this->factory->getSchemaStorage()->addSchema($schemaURI, $schema);
80159
80160 $validator = $this->factory->createInstanceFor('schema');
80161 $validator->check(
80162 $value,
80163 $this->factory->getSchemaStorage()->getSchema($schemaURI)
80164 );
80165
80166 $this->factory->setConfig($initialCheckMode);
80167
80168 $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
80169
80170 return $validator->getErrorMask();
80171 }
80172
80173
80174
80175
80176 public function check($value, $schema)
80177 {
80178 return $this->validate($value, $schema);
80179 }
80180
80181
80182
80183
80184 public function coerce(&$value, $schema)
80185 {
80186 return $this->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
80187 }
80188 }
80189 Copyright (C) 2015 Composer
80190
80191 Permission is hereby granted, free of charge, to any person obtaining a copy of
80192 this software and associated documentation files (the "Software"), to deal in
80193 the Software without restriction, including without limitation the rights to
80194 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
80195 of the Software, and to permit persons to whom the Software is furnished to do
80196 so, subject to the following conditions:
80197
80198 The above copyright notice and this permission notice shall be included in all
80199 copies or substantial portions of the Software.
80200
80201 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
80202 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
80203 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
80204 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
80205 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
80206 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
80207 SOFTWARE.
80208 <?php
80209
80210
80211
80212
80213
80214
80215
80216
80217
80218
80219 namespace Composer\Spdx;
80220
80221 class SpdxLicenses
80222 {
80223
80224 const LICENSES_FILE = 'spdx-licenses.json';
80225
80226
80227 const EXCEPTIONS_FILE = 'spdx-exceptions.json';
80228
80229
80230
80231
80232
80233
80234
80235
80236
80237
80238
80239
80240
80241
80242 private $licenses;
80243
80244
80245
80246
80247 private $licensesExpression;
80248
80249
80250
80251
80252
80253
80254
80255
80256
80257
80258
80259
80260
80261
80262 private $exceptions;
80263
80264
80265
80266
80267 private $exceptionsExpression;
80268
80269 public function __construct()
80270 {
80271 $this->loadLicenses();
80272 $this->loadExceptions();
80273 }
80274
80275
80276
80277
80278
80279
80280
80281
80282
80283
80284
80285
80286
80287 public function getLicenseByIdentifier($identifier)
80288 {
80289 $key = strtolower($identifier);
80290
80291 if (!isset($this->licenses[$key])) {
80292 return;
80293 }
80294
80295 list($identifier, $name, $isOsiApproved, $isDeprecatedLicenseId) = $this->licenses[$key];
80296
80297 return array(
80298 $name,
80299 $isOsiApproved,
80300 'https://spdx.org/licenses/' . $identifier . '.html#licenseText',
80301 $isDeprecatedLicenseId,
80302 );
80303 }
80304
80305
80306
80307
80308
80309
80310 public function getLicenses()
80311 {
80312 return $this->licenses;
80313 }
80314
80315
80316
80317
80318
80319
80320
80321
80322
80323
80324
80325
80326
80327 public function getExceptionByIdentifier($identifier)
80328 {
80329 $key = strtolower($identifier);
80330
80331 if (!isset($this->exceptions[$key])) {
80332 return;
80333 }
80334
80335 list($identifier, $name) = $this->exceptions[$key];
80336
80337 return array(
80338 $name,
80339 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText',
80340 );
80341 }
80342
80343
80344
80345
80346
80347
80348
80349
80350 public function getIdentifierByName($name)
80351 {
80352 foreach ($this->licenses as $licenseData) {
80353 if ($licenseData[1] === $name) {
80354 return $licenseData[0];
80355 }
80356 }
80357
80358 foreach ($this->exceptions as $licenseData) {
80359 if ($licenseData[1] === $name) {
80360 return $licenseData[0];
80361 }
80362 }
80363 }
80364
80365
80366
80367
80368
80369
80370
80371
80372 public function isOsiApprovedByIdentifier($identifier)
80373 {
80374 return $this->licenses[strtolower($identifier)][2];
80375 }
80376
80377
80378
80379
80380
80381
80382
80383
80384 public function isDeprecatedByIdentifier($identifier)
80385 {
80386 return $this->licenses[strtolower($identifier)][3];
80387 }
80388
80389
80390
80391
80392
80393
80394
80395
80396 public function validate($license)
80397 {
80398 if (is_array($license)) {
80399 $count = count($license);
80400 if ($count !== count(array_filter($license, 'is_string'))) {
80401 throw new \InvalidArgumentException('Array of strings expected.');
80402 }
80403 $license = $count > 1 ? '(' . implode(' OR ', $license) . ')' : (string) reset($license);
80404 }
80405
80406 if (!is_string($license)) {
80407 throw new \InvalidArgumentException(sprintf(
80408 'Array or String expected, %s given.',
80409 gettype($license)
80410 ));
80411 }
80412
80413 return $this->isValidLicenseString($license);
80414 }
80415
80416
80417
80418
80419 public static function getResourcesDir()
80420 {
80421 return dirname(__DIR__) . '/res';
80422 }
80423
80424 private function loadLicenses()
80425 {
80426 if (null !== $this->licenses) {
80427 return;
80428 }
80429
80430 $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
80431 $this->licenses = array();
80432
80433 foreach (json_decode($json, true) as $identifier => $license) {
80434 $this->licenses[strtolower($identifier)] = array($identifier, $license[0], $license[1], $license[2]);
80435 }
80436 }
80437
80438 private function loadExceptions()
80439 {
80440 if (null !== $this->exceptions) {
80441 return;
80442 }
80443
80444 $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
80445 $this->exceptions = array();
80446
80447 foreach (json_decode($json, true) as $identifier => $exception) {
80448 $this->exceptions[strtolower($identifier)] = array($identifier, $exception[0]);
80449 }
80450 }
80451
80452
80453
80454
80455 private function getLicensesExpression()
80456 {
80457 if (null === $this->licensesExpression) {
80458 $licenses = array_map('preg_quote', array_keys($this->licenses));
80459 rsort($licenses);
80460 $licenses = implode('|', $licenses);
80461 $this->licensesExpression = $licenses;
80462 }
80463
80464 return $this->licensesExpression;
80465 }
80466
80467
80468
80469
80470 private function getExceptionsExpression()
80471 {
80472 if (null === $this->exceptionsExpression) {
80473 $exceptions = array_map('preg_quote', array_keys($this->exceptions));
80474 rsort($exceptions);
80475 $exceptions = implode('|', $exceptions);
80476 $this->exceptionsExpression = $exceptions;
80477 }
80478
80479 return $this->exceptionsExpression;
80480 }
80481
80482
80483
80484
80485
80486
80487
80488
80489 private function isValidLicenseString($license)
80490 {
80491 if (isset($this->licenses[strtolower($license)])) {
80492 return true;
80493 }
80494
80495 $licenses = $this->getLicensesExpression();
80496 $exceptions = $this->getExceptionsExpression();
80497
80498 $regex = <<<REGEX
80499 {
80500 (?(DEFINE)
80501     # idstring: 1*( ALPHA / DIGIT / - / . )
80502     (?<idstring>[\pL\pN.-]{1,})
80503
80504     # license-id: taken from list
80505     (?<licenseid>${licenses})
80506
80507     # license-exception-id: taken from list
80508     (?<licenseexceptionid>${exceptions})
80509
80510     # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
80511     (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))
80512
80513     # simple-expresssion: license-id / license-id+ / license-ref
80514     (?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref))
80515
80516     # compound-expression: 1*(
80517     #   simple-expression /
80518     #   simple-expression WITH license-exception-id /
80519     #   compound-expression AND compound-expression /
80520     #   compound-expression OR compound-expression
80521     # ) / ( compound-expression ) )
80522     (?<compound_head>
80523         (?&simple_expression) ( \s+ WITH \s+ (?&licenseexceptionid))?
80524             | \( \s* (?&compound_expression) \s* \)
80525     )
80526     (?<compound_expression>
80527         (?&compound_head) (?: \s+ (?:AND|OR) \s+ (?&compound_expression))?
80528     )
80529
80530     # license-expression: 1*1(simple-expression / compound-expression)
80531     (?<license_expression>(?&compound_expression) | (?&simple_expression))
80532 ) # end of define
80533
80534 ^(NONE | NOASSERTION | (?&license_expression))$
80535 }xi
80536 REGEX;
80537
80538 $match = preg_match($regex, $license);
80539
80540 if (0 === $match) {
80541 return false;
80542 }
80543
80544 if (false === $match) {
80545 throw new \RuntimeException('Regex failed to compile/run.');
80546 }
80547
80548 return true;
80549 }
80550 }
80551 Copyright (C) 2015 Composer
80552
80553 Permission is hereby granted, free of charge, to any person obtaining a copy of
80554 this software and associated documentation files (the "Software"), to deal in
80555 the Software without restriction, including without limitation the rights to
80556 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
80557 of the Software, and to permit persons to whom the Software is furnished to do
80558 so, subject to the following conditions:
80559
80560 The above copyright notice and this permission notice shall be included in all
80561 copies or substantial portions of the Software.
80562
80563 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
80564 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
80565 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
80566 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
80567 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
80568 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
80569 SOFTWARE.
80570 <?php
80571
80572
80573
80574
80575
80576
80577
80578
80579
80580
80581 namespace Composer\Semver;
80582
80583 use Composer\Semver\Constraint\Constraint;
80584
80585 class Comparator
80586 {
80587
80588
80589
80590
80591
80592
80593
80594
80595 public static function greaterThan($version1, $version2)
80596 {
80597 return self::compare($version1, '>', $version2);
80598 }
80599
80600
80601
80602
80603
80604
80605
80606
80607
80608 public static function greaterThanOrEqualTo($version1, $version2)
80609 {
80610 return self::compare($version1, '>=', $version2);
80611 }
80612
80613
80614
80615
80616
80617
80618
80619
80620
80621 public static function lessThan($version1, $version2)
80622 {
80623 return self::compare($version1, '<', $version2);
80624 }
80625
80626
80627
80628
80629
80630
80631
80632
80633
80634 public static function lessThanOrEqualTo($version1, $version2)
80635 {
80636 return self::compare($version1, '<=', $version2);
80637 }
80638
80639
80640
80641
80642
80643
80644
80645
80646
80647 public static function equalTo($version1, $version2)
80648 {
80649 return self::compare($version1, '==', $version2);
80650 }
80651
80652
80653
80654
80655
80656
80657
80658
80659
80660 public static function notEqualTo($version1, $version2)
80661 {
80662 return self::compare($version1, '!=', $version2);
80663 }
80664
80665
80666
80667
80668
80669
80670
80671
80672
80673
80674 public static function compare($version1, $operator, $version2)
80675 {
80676 $constraint = new Constraint($operator, $version2);
80677
80678 return $constraint->matches(new Constraint('==', $version1));
80679 }
80680 }
80681 <?php
80682
80683
80684
80685
80686
80687
80688
80689
80690
80691
80692 namespace Composer\Semver\Constraint;
80693
80694 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);
80695
80696
80697
80698
80699 abstract class AbstractConstraint implements ConstraintInterface
80700 {
80701
80702 protected $prettyString;
80703
80704
80705
80706
80707
80708
80709 public function matches(ConstraintInterface $provider)
80710 {
80711 if ($provider instanceof $this) {
80712
80713  return $this->matchSpecific($provider);
80714 }
80715
80716
80717  return $provider->matches($this);
80718 }
80719
80720
80721
80722
80723 public function setPrettyString($prettyString)
80724 {
80725 $this->prettyString = $prettyString;
80726 }
80727
80728
80729
80730
80731 public function getPrettyString()
80732 {
80733 if ($this->prettyString) {
80734 return $this->prettyString;
80735 }
80736
80737 return $this->__toString();
80738 }
80739
80740
80741  
80742  
80743 }
80744 <?php
80745
80746
80747
80748
80749
80750
80751
80752
80753
80754
80755 namespace Composer\Semver\Constraint;
80756
80757
80758
80759
80760 class Constraint implements ConstraintInterface
80761 {
80762
80763 const OP_EQ = 0;
80764 const OP_LT = 1;
80765 const OP_LE = 2;
80766 const OP_GT = 3;
80767 const OP_GE = 4;
80768 const OP_NE = 5;
80769
80770
80771
80772
80773
80774
80775 private static $transOpStr = array(
80776 '=' => self::OP_EQ,
80777 '==' => self::OP_EQ,
80778 '<' => self::OP_LT,
80779 '<=' => self::OP_LE,
80780 '>' => self::OP_GT,
80781 '>=' => self::OP_GE,
80782 '<>' => self::OP_NE,
80783 '!=' => self::OP_NE,
80784 );
80785
80786
80787
80788
80789
80790
80791 private static $transOpInt = array(
80792 self::OP_EQ => '==',
80793 self::OP_LT => '<',
80794 self::OP_LE => '<=',
80795 self::OP_GT => '>',
80796 self::OP_GE => '>=',
80797 self::OP_NE => '!=',
80798 );
80799
80800
80801 protected $operator;
80802
80803
80804 protected $version;
80805
80806
80807 protected $prettyString;
80808
80809
80810
80811
80812
80813
80814 public function matches(ConstraintInterface $provider)
80815 {
80816 if ($provider instanceof $this) {
80817 return $this->matchSpecific($provider);
80818 }
80819
80820
80821  return $provider->matches($this);
80822 }
80823
80824
80825
80826
80827 public function setPrettyString($prettyString)
80828 {
80829 $this->prettyString = $prettyString;
80830 }
80831
80832
80833
80834
80835 public function getPrettyString()
80836 {
80837 if ($this->prettyString) {
80838 return $this->prettyString;
80839 }
80840
80841 return $this->__toString();
80842 }
80843
80844
80845
80846
80847
80848
80849 public static function getSupportedOperators()
80850 {
80851 return array_keys(self::$transOpStr);
80852 }
80853
80854
80855
80856
80857
80858
80859
80860
80861
80862 public function __construct($operator, $version)
80863 {
80864 if (!isset(self::$transOpStr[$operator])) {
80865 throw new \InvalidArgumentException(sprintf(
80866 'Invalid operator "%s" given, expected one of: %s',
80867 $operator,
80868 implode(', ', self::getSupportedOperators())
80869 ));
80870 }
80871
80872 $this->operator = self::$transOpStr[$operator];
80873 $this->version = $version;
80874 }
80875
80876
80877
80878
80879
80880
80881
80882
80883
80884
80885
80886 public function versionCompare($a, $b, $operator, $compareBranches = false)
80887 {
80888 if (!isset(self::$transOpStr[$operator])) {
80889 throw new \InvalidArgumentException(sprintf(
80890 'Invalid operator "%s" given, expected one of: %s',
80891 $operator,
80892 implode(', ', self::getSupportedOperators())
80893 ));
80894 }
80895
80896 $aIsBranch = 'dev-' === substr($a, 0, 4);
80897 $bIsBranch = 'dev-' === substr($b, 0, 4);
80898
80899 if ($aIsBranch && $bIsBranch) {
80900 return $operator === '==' && $a === $b;
80901 }
80902
80903
80904  if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
80905 return false;
80906 }
80907
80908 return version_compare($a, $b, $operator);
80909 }
80910
80911
80912
80913
80914
80915
80916
80917 public function matchSpecific(Constraint $provider, $compareBranches = false)
80918 {
80919 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
80920 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
80921
80922 $isEqualOp = self::OP_EQ === $this->operator;
80923 $isNonEqualOp = self::OP_NE === $this->operator;
80924 $isProviderEqualOp = self::OP_EQ === $provider->operator;
80925 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
80926
80927
80928  
80929  if ($isNonEqualOp || $isProviderNonEqualOp) {
80930 return !$isEqualOp && !$isProviderEqualOp
80931 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
80932 }
80933
80934
80935  
80936  if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
80937 return true;
80938 }
80939
80940 if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
80941
80942  
80943  if ($provider->version === $this->version
80944 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
80945 && self::$transOpInt[$this->operator] !== $noEqualOp) {
80946 return false;
80947 }
80948
80949 return true;
80950 }
80951
80952 return false;
80953 }
80954
80955
80956
80957
80958 public function __toString()
80959 {
80960 return self::$transOpInt[$this->operator] . ' ' . $this->version;
80961 }
80962 }
80963 <?php
80964
80965
80966
80967
80968
80969
80970
80971
80972
80973
80974 namespace Composer\Semver\Constraint;
80975
80976 interface ConstraintInterface
80977 {
80978
80979
80980
80981
80982
80983 public function matches(ConstraintInterface $provider);
80984
80985
80986
80987
80988 public function getPrettyString();
80989
80990
80991
80992
80993 public function __toString();
80994 }
80995 <?php
80996
80997
80998
80999
81000
81001
81002
81003
81004
81005
81006 namespace Composer\Semver\Constraint;
81007
81008
81009
81010
81011 class EmptyConstraint implements ConstraintInterface
81012 {
81013
81014 protected $prettyString;
81015
81016
81017
81018
81019
81020
81021 public function matches(ConstraintInterface $provider)
81022 {
81023 return true;
81024 }
81025
81026
81027
81028
81029 public function setPrettyString($prettyString)
81030 {
81031 $this->prettyString = $prettyString;
81032 }
81033
81034
81035
81036
81037 public function getPrettyString()
81038 {
81039 if ($this->prettyString) {
81040 return $this->prettyString;
81041 }
81042
81043 return $this->__toString();
81044 }
81045
81046
81047
81048
81049 public function __toString()
81050 {
81051 return '[]';
81052 }
81053 }
81054 <?php
81055
81056
81057
81058
81059
81060
81061
81062
81063
81064
81065 namespace Composer\Semver\Constraint;
81066
81067
81068
81069
81070 class MultiConstraint implements ConstraintInterface
81071 {
81072
81073 protected $constraints;
81074
81075
81076 protected $prettyString;
81077
81078
81079 protected $conjunctive;
81080
81081
81082
81083
81084
81085 public function __construct(array $constraints, $conjunctive = true)
81086 {
81087 $this->constraints = $constraints;
81088 $this->conjunctive = $conjunctive;
81089 }
81090
81091
81092
81093
81094 public function getConstraints()
81095 {
81096 return $this->constraints;
81097 }
81098
81099
81100
81101
81102 public function isConjunctive()
81103 {
81104 return $this->conjunctive;
81105 }
81106
81107
81108
81109
81110 public function isDisjunctive()
81111 {
81112 return !$this->conjunctive;
81113 }
81114
81115
81116
81117
81118
81119
81120 public function matches(ConstraintInterface $provider)
81121 {
81122 if (false === $this->conjunctive) {
81123 foreach ($this->constraints as $constraint) {
81124 if ($constraint->matches($provider)) {
81125 return true;
81126 }
81127 }
81128
81129 return false;
81130 }
81131
81132 foreach ($this->constraints as $constraint) {
81133 if (!$constraint->matches($provider)) {
81134 return false;
81135 }
81136 }
81137
81138 return true;
81139 }
81140
81141
81142
81143
81144 public function setPrettyString($prettyString)
81145 {
81146 $this->prettyString = $prettyString;
81147 }
81148
81149
81150
81151
81152 public function getPrettyString()
81153 {
81154 if ($this->prettyString) {
81155 return $this->prettyString;
81156 }
81157
81158 return $this->__toString();
81159 }
81160
81161
81162
81163
81164 public function __toString()
81165 {
81166 $constraints = array();
81167 foreach ($this->constraints as $constraint) {
81168 $constraints[] = (string) $constraint;
81169 }
81170
81171 return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
81172 }
81173 }
81174 <?php
81175
81176
81177
81178
81179
81180
81181
81182
81183
81184
81185 namespace Composer\Semver;
81186
81187 use Composer\Semver\Constraint\Constraint;
81188
81189 class Semver
81190 {
81191 const SORT_ASC = 1;
81192 const SORT_DESC = -1;
81193
81194
81195 private static $versionParser;
81196
81197
81198
81199
81200
81201
81202
81203
81204
81205 public static function satisfies($version, $constraints)
81206 {
81207 if (null === self::$versionParser) {
81208 self::$versionParser = new VersionParser();
81209 }
81210
81211 $versionParser = self::$versionParser;
81212 $provider = new Constraint('==', $versionParser->normalize($version));
81213 $constraints = $versionParser->parseConstraints($constraints);
81214
81215 return $constraints->matches($provider);
81216 }
81217
81218
81219
81220
81221
81222
81223
81224
81225
81226 public static function satisfiedBy(array $versions, $constraints)
81227 {
81228 $versions = array_filter($versions, function ($version) use ($constraints) {
81229 return Semver::satisfies($version, $constraints);
81230 });
81231
81232 return array_values($versions);
81233 }
81234
81235
81236
81237
81238
81239
81240
81241
81242 public static function sort(array $versions)
81243 {
81244 return self::usort($versions, self::SORT_ASC);
81245 }
81246
81247
81248
81249
81250
81251
81252
81253
81254 public static function rsort(array $versions)
81255 {
81256 return self::usort($versions, self::SORT_DESC);
81257 }
81258
81259
81260
81261
81262
81263
81264
81265 private static function usort(array $versions, $direction)
81266 {
81267 if (null === self::$versionParser) {
81268 self::$versionParser = new VersionParser();
81269 }
81270
81271 $versionParser = self::$versionParser;
81272 $normalized = array();
81273
81274
81275  
81276  foreach ($versions as $key => $version) {
81277 $normalized[] = array($versionParser->normalize($version), $key);
81278 }
81279
81280 usort($normalized, function (array $left, array $right) use ($direction) {
81281 if ($left[0] === $right[0]) {
81282 return 0;
81283 }
81284
81285 if (Comparator::lessThan($left[0], $right[0])) {
81286 return -$direction;
81287 }
81288
81289 return $direction;
81290 });
81291
81292
81293  $sorted = array();
81294 foreach ($normalized as $item) {
81295 $sorted[] = $versions[$item[1]];
81296 }
81297
81298 return $sorted;
81299 }
81300 }
81301 <?php
81302
81303
81304
81305
81306
81307
81308
81309
81310
81311
81312 namespace Composer\Semver;
81313
81314 use Composer\Semver\Constraint\ConstraintInterface;
81315 use Composer\Semver\Constraint\EmptyConstraint;
81316 use Composer\Semver\Constraint\MultiConstraint;
81317 use Composer\Semver\Constraint\Constraint;
81318
81319
81320
81321
81322
81323
81324 class VersionParser
81325 {
81326
81327
81328
81329
81330
81331
81332
81333
81334
81335
81336
81337
81338
81339 private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
81340
81341
81342 private static $stabilities = array('stable', 'RC', 'beta', 'alpha', 'dev');
81343
81344
81345
81346
81347
81348
81349
81350
81351 public static function parseStability($version)
81352 {
81353 $version = preg_replace('{#.+$}i', '', $version);
81354
81355 if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
81356 return 'dev';
81357 }
81358
81359 preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
81360 if (!empty($match[3])) {
81361 return 'dev';
81362 }
81363
81364 if (!empty($match[1])) {
81365 if ('beta' === $match[1] || 'b' === $match[1]) {
81366 return 'beta';
81367 }
81368 if ('alpha' === $match[1] || 'a' === $match[1]) {
81369 return 'alpha';
81370 }
81371 if ('rc' === $match[1]) {
81372 return 'RC';
81373 }
81374 }
81375
81376 return 'stable';
81377 }
81378
81379
81380
81381
81382
81383
81384 public static function normalizeStability($stability)
81385 {
81386 $stability = strtolower($stability);
81387
81388 return $stability === 'rc' ? 'RC' : $stability;
81389 }
81390
81391
81392
81393
81394
81395
81396
81397
81398
81399
81400
81401 public function normalize($version, $fullVersion = null)
81402 {
81403 $version = trim($version);
81404 if (null === $fullVersion) {
81405 $fullVersion = $version;
81406 }
81407
81408
81409  if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
81410 $version = $match[1];
81411 }
81412
81413
81414  if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
81415 return '9999999-dev';
81416 }
81417
81418
81419  if ('dev-' === strtolower(substr($version, 0, 4))) {
81420 return 'dev-' . substr($version, 4);
81421 }
81422
81423
81424  if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
81425 $version = $match[1];
81426 }
81427
81428
81429  if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
81430 $version = $matches[1]
81431 . (!empty($matches[2]) ? $matches[2] : '.0')
81432 . (!empty($matches[3]) ? $matches[3] : '.0')
81433 . (!empty($matches[4]) ? $matches[4] : '.0');
81434 $index = 5;
81435
81436  } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) {
81437 $version = preg_replace('{\D}', '.', $matches[1]);
81438 $index = 2;
81439 }
81440
81441
81442  if (isset($index)) {
81443 if (!empty($matches[$index])) {
81444 if ('stable' === $matches[$index]) {
81445 return $version;
81446 }
81447 $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? ltrim($matches[$index + 1], '.-') : '');
81448 }
81449
81450 if (!empty($matches[$index + 2])) {
81451 $version .= '-dev';
81452 }
81453
81454 return $version;
81455 }
81456
81457
81458  if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
81459 try {
81460 return $this->normalizeBranch($match[1]);
81461 } catch (\Exception $e) {
81462 }
81463 }
81464
81465 $extraMessage = '';
81466 if (preg_match('{ +as +' . preg_quote($version) . '$}', $fullVersion)) {
81467 $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
81468 } elseif (preg_match('{^' . preg_quote($version) . ' +as +}', $fullVersion)) {
81469 $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
81470 }
81471
81472 throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage);
81473 }
81474
81475
81476
81477
81478
81479
81480
81481
81482 public function parseNumericAliasPrefix($branch)
81483 {
81484 if (preg_match('{^(?P<version>(\d++\\.)*\d++)(?:\.x)?-dev$}i', $branch, $matches)) {
81485 return $matches['version'] . '.';
81486 }
81487
81488 return false;
81489 }
81490
81491
81492
81493
81494
81495
81496
81497
81498 public function normalizeBranch($name)
81499 {
81500 $name = trim($name);
81501
81502 if (in_array($name, array('master', 'trunk', 'default'))) {
81503 return $this->normalize($name);
81504 }
81505
81506 if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
81507 $version = '';
81508 for ($i = 1; $i < 5; ++$i) {
81509 $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
81510 }
81511
81512 return str_replace('x', '9999999', $version) . '-dev';
81513 }
81514
81515 return 'dev-' . $name;
81516 }
81517
81518
81519
81520
81521
81522
81523
81524
81525 public function parseConstraints($constraints)
81526 {
81527 $prettyConstraint = $constraints;
81528
81529 if (preg_match('{^([^,\s]*?)@(' . implode('|', self::$stabilities) . ')$}i', $constraints, $match)) {
81530 $constraints = empty($match[1]) ? '*' : $match[1];
81531 }
81532
81533 if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) {
81534 $constraints = $match[1];
81535 }
81536
81537 $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
81538 $orGroups = array();
81539 foreach ($orConstraints as $constraints) {
81540 $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
81541 if (count($andConstraints) > 1) {
81542 $constraintObjects = array();
81543 foreach ($andConstraints as $constraint) {
81544 foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
81545 $constraintObjects[] = $parsedConstraint;
81546 }
81547 }
81548 } else {
81549 $constraintObjects = $this->parseConstraint($andConstraints[0]);
81550 }
81551
81552 if (1 === count($constraintObjects)) {
81553 $constraint = $constraintObjects[0];
81554 } else {
81555 $constraint = new MultiConstraint($constraintObjects);
81556 }
81557
81558 $orGroups[] = $constraint;
81559 }
81560
81561 if (1 === count($orGroups)) {
81562 $constraint = $orGroups[0];
81563 } elseif (2 === count($orGroups)
81564
81565  
81566  && $orGroups[0] instanceof MultiConstraint
81567 && $orGroups[1] instanceof MultiConstraint
81568 && 2 === count($orGroups[0]->getConstraints())
81569 && 2 === count($orGroups[1]->getConstraints())
81570 && ($a = (string) $orGroups[0])
81571 && substr($a, 0, 3) === '[>=' && (false !== ($posA = strpos($a, '<', 4)))
81572 && ($b = (string) $orGroups[1])
81573 && substr($b, 0, 3) === '[>=' && (false !== ($posB = strpos($b, '<', 4)))
81574 && substr($a, $posA + 2, -1) === substr($b, 4, $posB - 5)
81575 ) {
81576 $constraint = new MultiConstraint(array(
81577 new Constraint('>=', substr($a, 4, $posA - 5)),
81578 new Constraint('<', substr($b, $posB + 2, -1)),
81579 ));
81580 } else {
81581 $constraint = new MultiConstraint($orGroups, false);
81582 }
81583
81584 $constraint->setPrettyString($prettyConstraint);
81585
81586 return $constraint;
81587 }
81588
81589
81590
81591
81592
81593
81594
81595
81596 private function parseConstraint($constraint)
81597 {
81598 if (preg_match('{^([^,\s]+?)@(' . implode('|', self::$stabilities) . ')$}i', $constraint, $match)) {
81599 $constraint = $match[1];
81600 if ($match[2] !== 'stable') {
81601 $stabilityModifier = $match[2];
81602 }
81603 }
81604
81605 if (preg_match('{^v?[xX*](\.[xX*])*$}i', $constraint)) {
81606 return array(new EmptyConstraint());
81607 }
81608
81609 $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?' . self::$modifierRegex . '(?:\+[^\s]+)?';
81610
81611
81612  
81613  
81614  
81615  
81616  if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
81617 if (substr($constraint, 0, 2) === '~>') {
81618 throw new \UnexpectedValueException(
81619 'Could not parse version constraint ' . $constraint . ': ' .
81620 'Invalid operator "~>", you probably meant to use the "~" operator'
81621 );
81622 }
81623
81624
81625  if (isset($matches[4]) && '' !== $matches[4]) {
81626 $position = 4;
81627 } elseif (isset($matches[3]) && '' !== $matches[3]) {
81628 $position = 3;
81629 } elseif (isset($matches[2]) && '' !== $matches[2]) {
81630 $position = 2;
81631 } else {
81632 $position = 1;
81633 }
81634
81635
81636  $stabilitySuffix = '';
81637 if (!empty($matches[5])) {
81638 $stabilitySuffix .= '-' . $this->expandStability($matches[5]) . (!empty($matches[6]) ? $matches[6] : '');
81639 }
81640
81641 if (!empty($matches[7])) {
81642 $stabilitySuffix .= '-dev';
81643 }
81644
81645 if (!$stabilitySuffix) {
81646 $stabilitySuffix = '-dev';
81647 }
81648
81649 $lowVersion = $this->manipulateVersionString($matches, $position, 0) . $stabilitySuffix;
81650 $lowerBound = new Constraint('>=', $lowVersion);
81651
81652
81653  
81654  $highPosition = max(1, $position - 1);
81655 $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
81656 $upperBound = new Constraint('<', $highVersion);
81657
81658 return array(
81659 $lowerBound,
81660 $upperBound,
81661 );
81662 }
81663
81664
81665  
81666  
81667  
81668  
81669  if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
81670
81671  if ('0' !== $matches[1] || '' === $matches[2]) {
81672 $position = 1;
81673 } elseif ('0' !== $matches[2] || '' === $matches[3]) {
81674 $position = 2;
81675 } else {
81676 $position = 3;
81677 }
81678
81679
81680  $stabilitySuffix = '';
81681 if (empty($matches[5]) && empty($matches[7])) {
81682 $stabilitySuffix .= '-dev';
81683 }
81684
81685 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
81686 $lowerBound = new Constraint('>=', $lowVersion);
81687
81688
81689  
81690  $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
81691 $upperBound = new Constraint('<', $highVersion);
81692
81693 return array(
81694 $lowerBound,
81695 $upperBound,
81696 );
81697 }
81698
81699
81700  
81701  
81702  
81703  if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
81704 if (isset($matches[3]) && '' !== $matches[3]) {
81705 $position = 3;
81706 } elseif (isset($matches[2]) && '' !== $matches[2]) {
81707 $position = 2;
81708 } else {
81709 $position = 1;
81710 }
81711
81712 $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
81713 $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
81714
81715 if ($lowVersion === '0.0.0.0-dev') {
81716 return array(new Constraint('<', $highVersion));
81717 }
81718
81719 return array(
81720 new Constraint('>=', $lowVersion),
81721 new Constraint('<', $highVersion),
81722 );
81723 }
81724
81725
81726  
81727  
81728  
81729  
81730  
81731  if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
81732
81733  $lowStabilitySuffix = '';
81734 if (empty($matches[6]) && empty($matches[8])) {
81735 $lowStabilitySuffix = '-dev';
81736 }
81737
81738 $lowVersion = $this->normalize($matches['from']);
81739 $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
81740
81741 $empty = function ($x) {
81742 return ($x === 0 || $x === '0') ? false : empty($x);
81743 };
81744
81745 if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) {
81746 $highVersion = $this->normalize($matches['to']);
81747 $upperBound = new Constraint('<=', $highVersion);
81748 } else {
81749 $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]);
81750 $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev';
81751 $upperBound = new Constraint('<', $highVersion);
81752 }
81753
81754 return array(
81755 $lowerBound,
81756 $upperBound,
81757 );
81758 }
81759
81760
81761  if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
81762 try {
81763 $version = $this->normalize($matches[2]);
81764
81765 if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') {
81766 $version .= '-' . $stabilityModifier;
81767 } elseif ('<' === $matches[1] || '>=' === $matches[1]) {
81768 if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
81769 if (substr($matches[2], 0, 4) !== 'dev-') {
81770 $version .= '-dev';
81771 }
81772 }
81773 }
81774
81775 return array(new Constraint($matches[1] ?: '=', $version));
81776 } catch (\Exception $e) {
81777 }
81778 }
81779
81780 $message = 'Could not parse version constraint ' . $constraint;
81781 if (isset($e)) {
81782 $message .= ': ' . $e->getMessage();
81783 }
81784
81785 throw new \UnexpectedValueException($message);
81786 }
81787
81788
81789
81790
81791
81792
81793
81794
81795
81796
81797
81798
81799
81800 private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
81801 {
81802 for ($i = 4; $i > 0; --$i) {
81803 if ($i > $position) {
81804 $matches[$i] = $pad;
81805 } elseif ($i === $position && $increment) {
81806 $matches[$i] += $increment;
81807
81808  if ($matches[$i] < 0) {
81809 $matches[$i] = $pad;
81810 --$position;
81811
81812
81813  if ($i === 1) {
81814 return;
81815 }
81816 }
81817 }
81818 }
81819
81820 return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
81821 }
81822
81823
81824
81825
81826
81827
81828
81829
81830 private function expandStability($stability)
81831 {
81832 $stability = strtolower($stability);
81833
81834 switch ($stability) {
81835 case 'a':
81836 return 'alpha';
81837 case 'b':
81838 return 'beta';
81839 case 'p':
81840 case 'pl':
81841 return 'patch';
81842 case 'rc':
81843 return 'RC';
81844 default:
81845 return $stability;
81846 }
81847 }
81848 }
81849 Copyright (C) 2016 Composer
81850
81851 Permission is hereby granted, free of charge, to any person obtaining a copy of
81852 this software and associated documentation files (the "Software"), to deal in
81853 the Software without restriction, including without limitation the rights to
81854 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
81855 of the Software, and to permit persons to whom the Software is furnished to do
81856 so, subject to the following conditions:
81857
81858 The above copyright notice and this permission notice shall be included in all
81859 copies or substantial portions of the Software.
81860
81861 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81862 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81863 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
81864 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81865 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
81866 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
81867 SOFTWARE.
81868 <?php
81869
81870
81871
81872
81873
81874
81875
81876
81877
81878
81879 namespace Composer\CaBundle;
81880
81881 use Psr\Log\LoggerInterface;
81882 use Symfony\Component\Process\PhpProcess;
81883
81884
81885
81886
81887
81888 class CaBundle
81889 {
81890 private static $caPath;
81891 private static $caFileValidity = array();
81892 private static $useOpensslParse;
81893
81894
81895
81896
81897
81898
81899
81900
81901
81902
81903
81904
81905
81906
81907
81908
81909
81910
81911
81912
81913
81914
81915
81916
81917
81918
81919
81920
81921
81922
81923
81924
81925
81926
81927
81928
81929
81930
81931 public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
81932 {
81933 if (self::$caPath !== null) {
81934 return self::$caPath;
81935 }
81936
81937
81938  
81939  $envCertFile = getenv('SSL_CERT_FILE');
81940 if ($envCertFile && is_readable($envCertFile) && static::validateCaFile($envCertFile, $logger)) {
81941 return self::$caPath = $envCertFile;
81942 }
81943
81944
81945  
81946  $envCertDir = getenv('SSL_CERT_DIR');
81947 if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) {
81948 return self::$caPath = $envCertDir;
81949 }
81950
81951 $configured = ini_get('openssl.cafile');
81952 if ($configured && strlen($configured) > 0 && is_readable($configured) && static::validateCaFile($configured, $logger)) {
81953 return self::$caPath = $configured;
81954 }
81955
81956 $configured = ini_get('openssl.capath');
81957 if ($configured && is_dir($configured) && is_readable($configured)) {
81958 return self::$caPath = $configured;
81959 }
81960
81961 $caBundlePaths = array(
81962 '/etc/pki/tls/certs/ca-bundle.crt', 
81963  '/etc/ssl/certs/ca-certificates.crt', 
81964  '/etc/ssl/ca-bundle.pem', 
81965  '/usr/local/share/certs/ca-root-nss.crt', 
81966  '/usr/ssl/certs/ca-bundle.crt', 
81967  '/opt/local/share/curl/curl-ca-bundle.crt', 
81968  '/usr/local/share/curl/curl-ca-bundle.crt', 
81969  '/usr/share/ssl/certs/ca-bundle.crt', 
81970  '/etc/ssl/cert.pem', 
81971  '/usr/local/etc/ssl/cert.pem', 
81972  '/usr/local/etc/openssl/cert.pem', 
81973  );
81974
81975 foreach ($caBundlePaths as $caBundle) {
81976 if (@is_readable($caBundle) && static::validateCaFile($caBundle, $logger)) {
81977 return self::$caPath = $caBundle;
81978 }
81979 }
81980
81981 foreach ($caBundlePaths as $caBundle) {
81982 $caBundle = dirname($caBundle);
81983 if (@is_dir($caBundle) && glob($caBundle.'/*')) {
81984 return self::$caPath = $caBundle;
81985 }
81986 }
81987
81988 return self::$caPath = static::getBundledCaBundlePath(); 
81989  }
81990
81991
81992
81993
81994
81995
81996
81997
81998 public static function getBundledCaBundlePath()
81999 {
82000 $caBundleFile = __DIR__.'/../res/cacert.pem';
82001
82002
82003  
82004  if (0 === strpos($caBundleFile, 'phar://')) {
82005 file_put_contents(
82006 $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
82007 file_get_contents($caBundleFile)
82008 );
82009
82010 register_shutdown_function(function() use ($tempCaBundleFile) {
82011 @unlink($tempCaBundleFile);
82012 });
82013
82014 $caBundleFile = $tempCaBundleFile;
82015 }
82016
82017 return $caBundleFile;
82018 }
82019
82020
82021
82022
82023
82024
82025
82026
82027
82028 public static function validateCaFile($filename, LoggerInterface $logger = null)
82029 {
82030 static $warned = false;
82031
82032 if (isset(self::$caFileValidity[$filename])) {
82033 return self::$caFileValidity[$filename];
82034 }
82035
82036 $contents = file_get_contents($filename);
82037
82038
82039  
82040  if (!static::isOpensslParseSafe()) {
82041 if (!$warned && $logger) {
82042 $logger->warning(sprintf(
82043 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
82044 PHP_VERSION
82045 ));
82046 $warned = true;
82047 }
82048
82049 $isValid = !empty($contents);
82050 } else {
82051 $isValid = (bool) openssl_x509_parse($contents);
82052 }
82053
82054 if ($logger) {
82055 $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
82056 }
82057
82058 return self::$caFileValidity[$filename] = $isValid;
82059 }
82060
82061
82062
82063
82064
82065
82066
82067
82068
82069 public static function isOpensslParseSafe()
82070 {
82071 if (null !== self::$useOpensslParse) {
82072 return self::$useOpensslParse;
82073 }
82074
82075 if (PHP_VERSION_ID >= 50600) {
82076 return self::$useOpensslParse = true;
82077 }
82078
82079
82080  
82081  
82082  
82083  if (
82084 (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
82085 || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
82086 || (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
82087 ) {
82088
82089  return self::$useOpensslParse = true;
82090 }
82091
82092 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
82093
82094  return self::$useOpensslParse = false;
82095 }
82096
82097 $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
82098 $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
82099
82100 if (preg_match($regex, PHP_VERSION, $m)) {
82101 return ((int) $m[1]) >= $fixedVersion;
82102 }
82103
82104 return false;
82105 };
82106
82107
82108  if (
82109 $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) 
82110  || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) 
82111  || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) 
82112  ) {
82113 return self::$useOpensslParse = true;
82114 }
82115
82116
82117  if (!class_exists('Symfony\Component\Process\PhpProcess')) {
82118 return self::$useOpensslParse = false;
82119 }
82120
82121
82122  
82123  
82124  
82125  
82126  
82127
82128
82129  
82130  $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
82131 $script = <<<'EOT'
82132
82133 error_reporting(-1);
82134 $info = openssl_x509_parse(base64_decode('%s'));
82135 var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
82136
82137 EOT;
82138 $script = '<'."?php\n".sprintf($script, $cert);
82139
82140 try {
82141 $process = new PhpProcess($script);
82142 $process->mustRun();
82143 } catch (\Exception $e) {
82144
82145  
82146  return self::$useOpensslParse = false;
82147 }
82148
82149 $output = preg_split('{\r?\n}', trim($process->getOutput()));
82150 $errorOutput = trim($process->getErrorOutput());
82151
82152 if (
82153 count($output) === 3
82154 && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
82155 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
82156 && $output[2] === 'int(-1)'
82157 && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
82158 ) {
82159
82160  return self::$useOpensslParse = true;
82161 }
82162
82163 return self::$useOpensslParse = false;
82164 }
82165
82166
82167
82168
82169 public static function reset()
82170 {
82171 self::$caFileValidity = array();
82172 self::$caPath = null;
82173 self::$useOpensslParse = null;
82174 }
82175 }
82176 Copyright (c) 2012 PHP Framework Interoperability Group
82177
82178 Permission is hereby granted, free of charge, to any person obtaining a copy 
82179 of this software and associated documentation files (the "Software"), to deal
82180 in the Software without restriction, including without limitation the rights 
82181 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
82182 copies of the Software, and to permit persons to whom the Software is 
82183 furnished to do so, subject to the following conditions:
82184
82185 The above copyright notice and this permission notice shall be included in 
82186 all copies or substantial portions of the Software.
82187
82188 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
82189 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
82190 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
82191 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
82192 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
82193 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
82194 THE SOFTWARE.
82195 <?php
82196
82197 namespace Psr\Log;
82198
82199
82200
82201
82202
82203
82204
82205
82206 abstract class AbstractLogger implements LoggerInterface
82207 {
82208
82209
82210
82211
82212
82213
82214
82215
82216 public function emergency($message, array $context = array())
82217 {
82218 $this->log(LogLevel::EMERGENCY, $message, $context);
82219 }
82220
82221
82222
82223
82224
82225
82226
82227
82228
82229
82230
82231
82232 public function alert($message, array $context = array())
82233 {
82234 $this->log(LogLevel::ALERT, $message, $context);
82235 }
82236
82237
82238
82239
82240
82241
82242
82243
82244
82245
82246
82247 public function critical($message, array $context = array())
82248 {
82249 $this->log(LogLevel::CRITICAL, $message, $context);
82250 }
82251
82252
82253
82254
82255
82256
82257
82258
82259
82260
82261 public function error($message, array $context = array())
82262 {
82263 $this->log(LogLevel::ERROR, $message, $context);
82264 }
82265
82266
82267
82268
82269
82270
82271
82272
82273
82274
82275
82276
82277 public function warning($message, array $context = array())
82278 {
82279 $this->log(LogLevel::WARNING, $message, $context);
82280 }
82281
82282
82283
82284
82285
82286
82287
82288
82289
82290 public function notice($message, array $context = array())
82291 {
82292 $this->log(LogLevel::NOTICE, $message, $context);
82293 }
82294
82295
82296
82297
82298
82299
82300
82301
82302
82303
82304
82305 public function info($message, array $context = array())
82306 {
82307 $this->log(LogLevel::INFO, $message, $context);
82308 }
82309
82310
82311
82312
82313
82314
82315
82316
82317
82318 public function debug($message, array $context = array())
82319 {
82320 $this->log(LogLevel::DEBUG, $message, $context);
82321 }
82322 }
82323 <?php
82324
82325 namespace Psr\Log;
82326
82327 class InvalidArgumentException extends \InvalidArgumentException
82328 {
82329 }
82330 <?php
82331
82332 namespace Psr\Log;
82333
82334
82335
82336
82337 class LogLevel
82338 {
82339 const EMERGENCY = 'emergency';
82340 const ALERT = 'alert';
82341 const CRITICAL = 'critical';
82342 const ERROR = 'error';
82343 const WARNING = 'warning';
82344 const NOTICE = 'notice';
82345 const INFO = 'info';
82346 const DEBUG = 'debug';
82347 }
82348 <?php
82349
82350 namespace Psr\Log;
82351
82352
82353
82354
82355 interface LoggerAwareInterface
82356 {
82357
82358
82359
82360
82361
82362
82363
82364 public function setLogger(LoggerInterface $logger);
82365 }
82366 <?php
82367
82368 namespace Psr\Log;
82369
82370
82371
82372
82373 trait LoggerAwareTrait
82374 {
82375
82376
82377
82378
82379
82380 protected $logger;
82381
82382
82383
82384
82385
82386
82387 public function setLogger(LoggerInterface $logger)
82388 {
82389 $this->logger = $logger;
82390 }
82391 }
82392 <?php
82393
82394 namespace Psr\Log;
82395
82396
82397
82398
82399
82400
82401
82402
82403
82404
82405
82406
82407
82408
82409
82410
82411 interface LoggerInterface
82412 {
82413
82414
82415
82416
82417
82418
82419
82420
82421 public function emergency($message, array $context = array());
82422
82423
82424
82425
82426
82427
82428
82429
82430
82431
82432
82433
82434 public function alert($message, array $context = array());
82435
82436
82437
82438
82439
82440
82441
82442
82443
82444
82445
82446 public function critical($message, array $context = array());
82447
82448
82449
82450
82451
82452
82453
82454
82455
82456
82457 public function error($message, array $context = array());
82458
82459
82460
82461
82462
82463
82464
82465
82466
82467
82468
82469
82470 public function warning($message, array $context = array());
82471
82472
82473
82474
82475
82476
82477
82478
82479
82480 public function notice($message, array $context = array());
82481
82482
82483
82484
82485
82486
82487
82488
82489
82490
82491
82492 public function info($message, array $context = array());
82493
82494
82495
82496
82497
82498
82499
82500
82501
82502 public function debug($message, array $context = array());
82503
82504
82505
82506
82507
82508
82509
82510
82511
82512
82513 public function log($level, $message, array $context = array());
82514 }
82515 <?php
82516
82517 namespace Psr\Log;
82518
82519
82520
82521
82522
82523
82524
82525
82526
82527 trait LoggerTrait
82528 {
82529
82530
82531
82532
82533
82534
82535
82536
82537 public function emergency($message, array $context = array())
82538 {
82539 $this->log(LogLevel::EMERGENCY, $message, $context);
82540 }
82541
82542
82543
82544
82545
82546
82547
82548
82549
82550
82551
82552
82553 public function alert($message, array $context = array())
82554 {
82555 $this->log(LogLevel::ALERT, $message, $context);
82556 }
82557
82558
82559
82560
82561
82562
82563
82564
82565
82566
82567
82568 public function critical($message, array $context = array())
82569 {
82570 $this->log(LogLevel::CRITICAL, $message, $context);
82571 }
82572
82573
82574
82575
82576
82577
82578
82579
82580
82581
82582 public function error($message, array $context = array())
82583 {
82584 $this->log(LogLevel::ERROR, $message, $context);
82585 }
82586
82587
82588
82589
82590
82591
82592
82593
82594
82595
82596
82597
82598 public function warning($message, array $context = array())
82599 {
82600 $this->log(LogLevel::WARNING, $message, $context);
82601 }
82602
82603
82604
82605
82606
82607
82608
82609
82610
82611 public function notice($message, array $context = array())
82612 {
82613 $this->log(LogLevel::NOTICE, $message, $context);
82614 }
82615
82616
82617
82618
82619
82620
82621
82622
82623
82624
82625
82626 public function info($message, array $context = array())
82627 {
82628 $this->log(LogLevel::INFO, $message, $context);
82629 }
82630
82631
82632
82633
82634
82635
82636
82637
82638
82639 public function debug($message, array $context = array())
82640 {
82641 $this->log(LogLevel::DEBUG, $message, $context);
82642 }
82643
82644
82645
82646
82647
82648
82649
82650
82651
82652
82653 abstract public function log($level, $message, array $context = array());
82654 }
82655 <?php
82656
82657 namespace Psr\Log;
82658
82659
82660
82661
82662
82663
82664
82665
82666
82667 class NullLogger extends AbstractLogger
82668 {
82669
82670
82671
82672
82673
82674
82675
82676
82677
82678 public function log($level, $message, array $context = array())
82679 {
82680
82681  }
82682 }
82683 <?php
82684
82685 namespace Psr\Log\Test;
82686
82687 use Psr\Log\LoggerInterface;
82688 use Psr\Log\LogLevel;
82689
82690
82691
82692
82693
82694
82695
82696 abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase
82697 {
82698
82699
82700
82701 abstract public function getLogger();
82702
82703
82704
82705
82706
82707
82708
82709
82710
82711
82712 abstract public function getLogs();
82713
82714 public function testImplements()
82715 {
82716 $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
82717 }
82718
82719
82720
82721
82722 public function testLogsAtAllLevels($level, $message)
82723 {
82724 $logger = $this->getLogger();
82725 $logger->{$level}($message, array('user' => 'Bob'));
82726 $logger->log($level, $message, array('user' => 'Bob'));
82727
82728 $expected = array(
82729 $level.' message of level '.$level.' with context: Bob',
82730 $level.' message of level '.$level.' with context: Bob',
82731 );
82732 $this->assertEquals($expected, $this->getLogs());
82733 }
82734
82735 public function provideLevelsAndMessages()
82736 {
82737 return array(
82738 LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
82739 LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
82740 LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
82741 LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
82742 LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
82743 LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
82744 LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
82745 LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
82746 );
82747 }
82748
82749
82750
82751
82752 public function testThrowsOnInvalidLevel()
82753 {
82754 $logger = $this->getLogger();
82755 $logger->log('invalid level', 'Foo');
82756 }
82757
82758 public function testContextReplacement()
82759 {
82760 $logger = $this->getLogger();
82761 $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
82762
82763 $expected = array('info {Message {nothing} Bob Bar a}');
82764 $this->assertEquals($expected, $this->getLogs());
82765 }
82766
82767 public function testObjectCastToString()
82768 {
82769 if (method_exists($this, 'createPartialMock')) {
82770 $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
82771 } else {
82772 $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
82773 }
82774 $dummy->expects($this->once())
82775 ->method('__toString')
82776 ->will($this->returnValue('DUMMY'));
82777
82778 $this->getLogger()->warning($dummy);
82779
82780 $expected = array('warning DUMMY');
82781 $this->assertEquals($expected, $this->getLogs());
82782 }
82783
82784 public function testContextCanContainAnything()
82785 {
82786 $context = array(
82787 'bool' => true,
82788 'null' => null,
82789 'string' => 'Foo',
82790 'int' => 0,
82791 'float' => 0.5,
82792 'nested' => array('with object' => new DummyTest),
82793 'object' => new \DateTime,
82794 'resource' => fopen('php://memory', 'r'),
82795 );
82796
82797 $this->getLogger()->warning('Crazy context data', $context);
82798
82799 $expected = array('warning Crazy context data');
82800 $this->assertEquals($expected, $this->getLogs());
82801 }
82802
82803 public function testContextExceptionKeyCanBeExceptionOrOtherValues()
82804 {
82805 $logger = $this->getLogger();
82806 $logger->warning('Random message', array('exception' => 'oops'));
82807 $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
82808
82809 $expected = array(
82810 'warning Random message',
82811 'critical Uncaught Exception!'
82812 );
82813 $this->assertEquals($expected, $this->getLogs());
82814 }
82815 }
82816
82817 class DummyTest
82818 {
82819 public function __toString()
82820 {
82821 }
82822 }
82823 <?php
82824
82825
82826
82827 require_once __DIR__ . '/composer/autoload_real.php';
82828
82829 return ComposerAutoloaderInitComposerPhar1517412498::getLoader();
82830 <?php
82831
82832
82833
82834 $vendorDir = dirname(dirname(__FILE__));
82835 $baseDir = dirname($vendorDir);
82836
82837 return array(
82838 );
82839 <?php
82840
82841
82842
82843 $vendorDir = dirname(dirname(__FILE__));
82844 $baseDir = dirname($vendorDir);
82845
82846 return array(
82847 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
82848 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
82849 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
82850 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
82851 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
82852 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
82853 'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
82854 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
82855 'Seld\\CliPrompt\\' => array($vendorDir . '/seld/cli-prompt/src'),
82856 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
82857 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
82858 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
82859 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
82860 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
82861 'Composer\\' => array($baseDir . '/src/Composer'),
82862 );
82863 <?php
82864
82865
82866
82867 $vendorDir = dirname(dirname(__FILE__));
82868 $baseDir = dirname($vendorDir);
82869
82870 return array(
82871 );
82872 <?php
82873
82874
82875
82876 $vendorDir = dirname(dirname(__FILE__));
82877 $baseDir = dirname($vendorDir);
82878
82879 return array(
82880 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
82881 );
82882 <?php
82883
82884
82885
82886 class ComposerAutoloaderInitComposerPhar1517412498
82887 {
82888 private static $loader;
82889
82890 public static function loadClassLoader($class)
82891 {
82892 if ('Composer\Autoload\ClassLoader' === $class) {
82893 require __DIR__ . '/ClassLoader.php';
82894 }
82895 }
82896
82897 public static function getLoader()
82898 {
82899 if (null !== self::$loader) {
82900 return self::$loader;
82901 }
82902
82903 spl_autoload_register(array('ComposerAutoloaderInitComposerPhar1517412498', 'loadClassLoader'), true, true);
82904 self::$loader = $loader = new \Composer\Autoload\ClassLoader();
82905 spl_autoload_unregister(array('ComposerAutoloaderInitComposerPhar1517412498', 'loadClassLoader'));
82906
82907 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
82908 if ($useStaticLoader) {
82909 require_once __DIR__ . '/autoload_static.php';
82910
82911 call_user_func(\Composer\Autoload\ComposerStaticInitComposerPhar1517412498::getInitializer($loader));
82912 } else {
82913 $map = require __DIR__ . '/autoload_namespaces.php';
82914 foreach ($map as $namespace => $path) {
82915 $loader->set($namespace, $path);
82916 }
82917
82918 $map = require __DIR__ . '/autoload_psr4.php';
82919 foreach ($map as $namespace => $path) {
82920 $loader->setPsr4($namespace, $path);
82921 }
82922
82923 $classMap = require __DIR__ . '/autoload_classmap.php';
82924 if ($classMap) {
82925 $loader->addClassMap($classMap);
82926 }
82927 }
82928
82929 $loader->register(true);
82930
82931 if ($useStaticLoader) {
82932 $includeFiles = Composer\Autoload\ComposerStaticInitComposerPhar1517412498::$files;
82933 } else {
82934 $includeFiles = require __DIR__ . '/autoload_files.php';
82935 }
82936 foreach ($includeFiles as $fileIdentifier => $file) {
82937 composerRequireComposerPhar1517412498($fileIdentifier, $file);
82938 }
82939
82940 return $loader;
82941 }
82942 }
82943
82944 function composerRequireComposerPhar1517412498($fileIdentifier, $file)
82945 {
82946 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
82947 require $file;
82948
82949 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
82950 }
82951 }
82952 <?php
82953
82954
82955
82956 namespace Composer\Autoload;
82957
82958 class ComposerStaticInitComposerPhar1517412498
82959 {
82960 public static $files = array (
82961 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
82962 );
82963
82964 public static $prefixLengthsPsr4 = array (
82965 'S' => 
82966 array (
82967 'Symfony\\Polyfill\\Mbstring\\' => 26,
82968 'Symfony\\Component\\Process\\' => 26,
82969 'Symfony\\Component\\Finder\\' => 25,
82970 'Symfony\\Component\\Filesystem\\' => 29,
82971 'Symfony\\Component\\Debug\\' => 24,
82972 'Symfony\\Component\\Console\\' => 26,
82973 'Seld\\PharUtils\\' => 15,
82974 'Seld\\JsonLint\\' => 14,
82975 'Seld\\CliPrompt\\' => 15,
82976 ),
82977 'P' => 
82978 array (
82979 'Psr\\Log\\' => 8,
82980 ),
82981 'J' => 
82982 array (
82983 'JsonSchema\\' => 11,
82984 ),
82985 'C' => 
82986 array (
82987 'Composer\\Spdx\\' => 14,
82988 'Composer\\Semver\\' => 16,
82989 'Composer\\CaBundle\\' => 18,
82990 'Composer\\' => 9,
82991 ),
82992 );
82993
82994 public static $prefixDirsPsr4 = array (
82995 'Symfony\\Polyfill\\Mbstring\\' => 
82996 array (
82997 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
82998 ),
82999 'Symfony\\Component\\Process\\' => 
83000 array (
83001 0 => __DIR__ . '/..' . '/symfony/process',
83002 ),
83003 'Symfony\\Component\\Finder\\' => 
83004 array (
83005 0 => __DIR__ . '/..' . '/symfony/finder',
83006 ),
83007 'Symfony\\Component\\Filesystem\\' => 
83008 array (
83009 0 => __DIR__ . '/..' . '/symfony/filesystem',
83010 ),
83011 'Symfony\\Component\\Debug\\' => 
83012 array (
83013 0 => __DIR__ . '/..' . '/symfony/debug',
83014 ),
83015 'Symfony\\Component\\Console\\' => 
83016 array (
83017 0 => __DIR__ . '/..' . '/symfony/console',
83018 ),
83019 'Seld\\PharUtils\\' => 
83020 array (
83021 0 => __DIR__ . '/..' . '/seld/phar-utils/src',
83022 ),
83023 'Seld\\JsonLint\\' => 
83024 array (
83025 0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
83026 ),
83027 'Seld\\CliPrompt\\' => 
83028 array (
83029 0 => __DIR__ . '/..' . '/seld/cli-prompt/src',
83030 ),
83031 'Psr\\Log\\' => 
83032 array (
83033 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
83034 ),
83035 'JsonSchema\\' => 
83036 array (
83037 0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema',
83038 ),
83039 'Composer\\Spdx\\' => 
83040 array (
83041 0 => __DIR__ . '/..' . '/composer/spdx-licenses/src',
83042 ),
83043 'Composer\\Semver\\' => 
83044 array (
83045 0 => __DIR__ . '/..' . '/composer/semver/src',
83046 ),
83047 'Composer\\CaBundle\\' => 
83048 array (
83049 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
83050 ),
83051 'Composer\\' => 
83052 array (
83053 0 => __DIR__ . '/../..' . '/src/Composer',
83054 ),
83055 );
83056
83057 public static function getInitializer(ClassLoader $loader)
83058 {
83059 return \Closure::bind(function () use ($loader) {
83060 $loader->prefixLengthsPsr4 = ComposerStaticInitComposerPhar1517412498::$prefixLengthsPsr4;
83061 $loader->prefixDirsPsr4 = ComposerStaticInitComposerPhar1517412498::$prefixDirsPsr4;
83062
83063 }, null, ClassLoader::class);
83064 }
83065 }
83066 <?php
83067
83068
83069
83070
83071
83072
83073
83074
83075
83076
83077
83078 namespace Composer\Autoload;
83079
83080
83081
83082
83083
83084
83085
83086
83087
83088
83089
83090
83091
83092
83093
83094
83095
83096
83097
83098
83099
83100
83101
83102
83103
83104
83105
83106
83107
83108 class ClassLoader
83109 {
83110
83111  private $prefixLengthsPsr4 = array();
83112 private $prefixDirsPsr4 = array();
83113 private $fallbackDirsPsr4 = array();
83114
83115
83116  private $prefixesPsr0 = array();
83117 private $fallbackDirsPsr0 = array();
83118
83119 private $useIncludePath = false;
83120 private $classMap = array();
83121 private $classMapAuthoritative = false;
83122 private $missingClasses = array();
83123 private $apcuPrefix;
83124
83125 public function getPrefixes()
83126 {
83127 if (!empty($this->prefixesPsr0)) {
83128 return call_user_func_array('array_merge', $this->prefixesPsr0);
83129 }
83130
83131 return array();
83132 }
83133
83134 public function getPrefixesPsr4()
83135 {
83136 return $this->prefixDirsPsr4;
83137 }
83138
83139 public function getFallbackDirs()
83140 {
83141 return $this->fallbackDirsPsr0;
83142 }
83143
83144 public function getFallbackDirsPsr4()
83145 {
83146 return $this->fallbackDirsPsr4;
83147 }
83148
83149 public function getClassMap()
83150 {
83151 return $this->classMap;
83152 }
83153
83154
83155
83156
83157 public function addClassMap(array $classMap)
83158 {
83159 if ($this->classMap) {
83160 $this->classMap = array_merge($this->classMap, $classMap);
83161 } else {
83162 $this->classMap = $classMap;
83163 }
83164 }
83165
83166
83167
83168
83169
83170
83171
83172
83173
83174 public function add($prefix, $paths, $prepend = false)
83175 {
83176 if (!$prefix) {
83177 if ($prepend) {
83178 $this->fallbackDirsPsr0 = array_merge(
83179 (array) $paths,
83180 $this->fallbackDirsPsr0
83181 );
83182 } else {
83183 $this->fallbackDirsPsr0 = array_merge(
83184 $this->fallbackDirsPsr0,
83185 (array) $paths
83186 );
83187 }
83188
83189 return;
83190 }
83191
83192 $first = $prefix[0];
83193 if (!isset($this->prefixesPsr0[$first][$prefix])) {
83194 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
83195
83196 return;
83197 }
83198 if ($prepend) {
83199 $this->prefixesPsr0[$first][$prefix] = array_merge(
83200 (array) $paths,
83201 $this->prefixesPsr0[$first][$prefix]
83202 );
83203 } else {
83204 $this->prefixesPsr0[$first][$prefix] = array_merge(
83205 $this->prefixesPsr0[$first][$prefix],
83206 (array) $paths
83207 );
83208 }
83209 }
83210
83211
83212
83213
83214
83215
83216
83217
83218
83219
83220
83221 public function addPsr4($prefix, $paths, $prepend = false)
83222 {
83223 if (!$prefix) {
83224
83225  if ($prepend) {
83226 $this->fallbackDirsPsr4 = array_merge(
83227 (array) $paths,
83228 $this->fallbackDirsPsr4
83229 );
83230 } else {
83231 $this->fallbackDirsPsr4 = array_merge(
83232 $this->fallbackDirsPsr4,
83233 (array) $paths
83234 );
83235 }
83236 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
83237
83238  $length = strlen($prefix);
83239 if ('\\' !== $prefix[$length - 1]) {
83240 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
83241 }
83242 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
83243 $this->prefixDirsPsr4[$prefix] = (array) $paths;
83244 } elseif ($prepend) {
83245
83246  $this->prefixDirsPsr4[$prefix] = array_merge(
83247 (array) $paths,
83248 $this->prefixDirsPsr4[$prefix]
83249 );
83250 } else {
83251
83252  $this->prefixDirsPsr4[$prefix] = array_merge(
83253 $this->prefixDirsPsr4[$prefix],
83254 (array) $paths
83255 );
83256 }
83257 }
83258
83259
83260
83261
83262
83263
83264
83265
83266 public function set($prefix, $paths)
83267 {
83268 if (!$prefix) {
83269 $this->fallbackDirsPsr0 = (array) $paths;
83270 } else {
83271 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
83272 }
83273 }
83274
83275
83276
83277
83278
83279
83280
83281
83282
83283
83284 public function setPsr4($prefix, $paths)
83285 {
83286 if (!$prefix) {
83287 $this->fallbackDirsPsr4 = (array) $paths;
83288 } else {
83289 $length = strlen($prefix);
83290 if ('\\' !== $prefix[$length - 1]) {
83291 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
83292 }
83293 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
83294 $this->prefixDirsPsr4[$prefix] = (array) $paths;
83295 }
83296 }
83297
83298
83299
83300
83301
83302
83303 public function setUseIncludePath($useIncludePath)
83304 {
83305 $this->useIncludePath = $useIncludePath;
83306 }
83307
83308
83309
83310
83311
83312
83313
83314 public function getUseIncludePath()
83315 {
83316 return $this->useIncludePath;
83317 }
83318
83319
83320
83321
83322
83323
83324
83325 public function setClassMapAuthoritative($classMapAuthoritative)
83326 {
83327 $this->classMapAuthoritative = $classMapAuthoritative;
83328 }
83329
83330
83331
83332
83333
83334
83335 public function isClassMapAuthoritative()
83336 {
83337 return $this->classMapAuthoritative;
83338 }
83339
83340
83341
83342
83343
83344
83345 public function setApcuPrefix($apcuPrefix)
83346 {
83347 $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
83348 }
83349
83350
83351
83352
83353
83354
83355 public function getApcuPrefix()
83356 {
83357 return $this->apcuPrefix;
83358 }
83359
83360
83361
83362
83363
83364
83365 public function register($prepend = false)
83366 {
83367 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
83368 }
83369
83370
83371
83372
83373 public function unregister()
83374 {
83375 spl_autoload_unregister(array($this, 'loadClass'));
83376 }
83377
83378
83379
83380
83381
83382
83383
83384 public function loadClass($class)
83385 {
83386 if ($file = $this->findFile($class)) {
83387 includeFile($file);
83388
83389 return true;
83390 }
83391 }
83392
83393
83394
83395
83396
83397
83398
83399
83400 public function findFile($class)
83401 {
83402
83403  if (isset($this->classMap[$class])) {
83404 return $this->classMap[$class];
83405 }
83406 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
83407 return false;
83408 }
83409 if (null !== $this->apcuPrefix) {
83410 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
83411 if ($hit) {
83412 return $file;
83413 }
83414 }
83415
83416 $file = $this->findFileWithExtension($class, '.php');
83417
83418
83419  if (false === $file && defined('HHVM_VERSION')) {
83420 $file = $this->findFileWithExtension($class, '.hh');
83421 }
83422
83423 if (null !== $this->apcuPrefix) {
83424 apcu_add($this->apcuPrefix.$class, $file);
83425 }
83426
83427 if (false === $file) {
83428
83429  $this->missingClasses[$class] = true;
83430 }
83431
83432 return $file;
83433 }
83434
83435 private function findFileWithExtension($class, $ext)
83436 {
83437
83438  $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
83439
83440 $first = $class[0];
83441 if (isset($this->prefixLengthsPsr4[$first])) {
83442 $subPath = $class;
83443 while (false !== $lastPos = strrpos($subPath, '\\')) {
83444 $subPath = substr($subPath, 0, $lastPos);
83445 $search = $subPath.'\\';
83446 if (isset($this->prefixDirsPsr4[$search])) {
83447 $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
83448 foreach ($this->prefixDirsPsr4[$search] as $dir) {
83449 if (file_exists($file = $dir . $pathEnd)) {
83450 return $file;
83451 }
83452 }
83453 }
83454 }
83455 }
83456
83457
83458  foreach ($this->fallbackDirsPsr4 as $dir) {
83459 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
83460 return $file;
83461 }
83462 }
83463
83464
83465  if (false !== $pos = strrpos($class, '\\')) {
83466
83467  $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
83468 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
83469 } else {
83470
83471  $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
83472 }
83473
83474 if (isset($this->prefixesPsr0[$first])) {
83475 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
83476 if (0 === strpos($class, $prefix)) {
83477 foreach ($dirs as $dir) {
83478 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
83479 return $file;
83480 }
83481 }
83482 }
83483 }
83484 }
83485
83486
83487  foreach ($this->fallbackDirsPsr0 as $dir) {
83488 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
83489 return $file;
83490 }
83491 }
83492
83493
83494  if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
83495 return $file;
83496 }
83497
83498 return false;
83499 }
83500 }
83501
83502
83503
83504
83505
83506
83507 function includeFile($file)
83508 {
83509 include $file;
83510 }
83511 ##
83512 ## Bundle of CA Root Certificates
83513 ##
83514 ## Certificate data from Mozilla as of: Wed Sep 20 03:12:05 2017 GMT
83515 ##
83516 ## This is a bundle of X.509 certificates of public Certificate Authorities
83517 ## (CA). These were automatically extracted from Mozilla's root certificates
83518 ## file (certdata.txt).  This file can be found in the mozilla source tree:
83519 ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
83520 ##
83521 ## It contains the certificates in PEM format and therefore
83522 ## can be directly used with curl / libcurl / php_curl, or with
83523 ## an Apache+mod_ssl webserver for SSL client authentication.
83524 ## Just configure this file as the SSLCACertificateFile.
83525 ##
83526 ## Conversion done with mk-ca-bundle.pl version 1.27.
83527 ## SHA256: 2b2dbe5244e0047e088c597998883a913f6c5fffd1cb5c0fe5a368c8466cb2ec
83528 ##
83529
83530
83531 GlobalSign Root CA
83532 ==================
83533 -----BEGIN CERTIFICATE-----
83534 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
83535 GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
83536 b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
83537 BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
83538 VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
83539 DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
83540 THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
83541 Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
83542 c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
83543 gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
83544 HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
83545 AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
83546 Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
83547 j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
83548 hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
83549 X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
83550 -----END CERTIFICATE-----
83551
83552 GlobalSign Root CA - R2
83553 =======================
83554 -----BEGIN CERTIFICATE-----
83555 MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
83556 YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
83557 bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
83558 aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
83559 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
83560 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
83561 s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
83562 S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
83563 TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
83564 ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
83565 FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
83566 YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
83567 BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
83568 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
83569 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
83570 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
83571 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
83572 -----END CERTIFICATE-----
83573
83574 Verisign Class 3 Public Primary Certification Authority - G3
83575 ============================================================
83576 -----BEGIN CERTIFICATE-----
83577 MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
83578 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
83579 cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
83580 IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
83581 dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
83582 CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
83583 dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
83584 cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
83585 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
83586 ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
83587 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
83588 cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
83589 EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
83590 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
83591 ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
83592 j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
83593 /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
83594 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
83595 t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
83596 -----END CERTIFICATE-----
83597
83598 Entrust.net Premium 2048 Secure Server CA
83599 =========================================
83600 -----BEGIN CERTIFICATE-----
83601 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
83602 ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
83603 bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
83604 BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
83605 NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
83606 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
83607 MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
83608 ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
83609 MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
83610 Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
83611 hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
83612 nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
83613 VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
83614 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
83615 KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
83616 T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
83617 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
83618 J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
83619 nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
83620 -----END CERTIFICATE-----
83621
83622 Baltimore CyberTrust Root
83623 =========================
83624 -----BEGIN CERTIFICATE-----
83625 MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
83626 ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
83627 ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
83628 SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
83629 dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
83630 uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
83631 UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
83632 G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
83633 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
83634 l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
83635 VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
83636 BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
83637 cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
83638 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
83639 Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
83640 RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
83641 -----END CERTIFICATE-----
83642
83643 AddTrust External Root
83644 ======================
83645 -----BEGIN CERTIFICATE-----
83646 MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
83647 QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
83648 VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
83649 NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
83650 cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
83651 Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
83652 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
83653 Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
83654 aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
83655 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
83656 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
83657 BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
83658 VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
83659 VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
83660 IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
83661 j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
83662 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
83663 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
83664 G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
83665 -----END CERTIFICATE-----
83666
83667 Entrust Root Certification Authority
83668 ====================================
83669 -----BEGIN CERTIFICATE-----
83670 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
83671 BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
83672 b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
83673 A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
83674 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
83675 MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
83676 Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
83677 dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
83678 ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
83679 A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
83680 Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
83681 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
83682 rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
83683 DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
83684 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
83685 hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
83686 A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
83687 Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
83688 v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
83689 W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
83690 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
83691 -----END CERTIFICATE-----
83692
83693 GeoTrust Global CA
83694 ==================
83695 -----BEGIN CERTIFICATE-----
83696 MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
83697 Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
83698 MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
83699 LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
83700 CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
83701 BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
83702 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
83703 T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
83704 vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
83705 AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
83706 DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
83707 zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
83708 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
83709 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
83710 XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
83711 Mw==
83712 -----END CERTIFICATE-----
83713
83714 GeoTrust Universal CA
83715 =====================
83716 -----BEGIN CERTIFICATE-----
83717 MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
83718 R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
83719 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
83720 Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
83721 ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
83722 JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
83723 RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
83724 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
83725 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
83726 qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
83727 Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
83728 Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
83729 KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
83730 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
83731 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
83732 hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
83733 aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
83734 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
83735 oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
83736 xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
83737 KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
83738 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
83739 xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
83740 p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
83741 P/rmMuGNG2+k5o7Y+SlIis5z/iw=
83742 -----END CERTIFICATE-----
83743
83744 GeoTrust Universal CA 2
83745 =======================
83746 -----BEGIN CERTIFICATE-----
83747 MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
83748 R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
83749 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
83750 SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
83751 A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
83752 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
83753 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
83754 JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
83755 QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
83756 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
83757 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
83758 ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
83759 SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
83760 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
83761 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
83762 BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
83763 dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
83764 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
83765 mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
83766 A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
83767 Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
83768 pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
83769 FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
83770 gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
83771 X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
83772 -----END CERTIFICATE-----
83773
83774 Visa eCommerce Root
83775 ===================
83776 -----BEGIN CERTIFICATE-----
83777 MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
83778 EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
83779 QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
83780 WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
83781 VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
83782 bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
83783 F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
83784 RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
83785 TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
83786 /k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
83787 GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
83788 MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
83789 CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
83790 YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
83791 zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
83792 YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
83793 398znM/jra6O1I7mT1GvFpLgXPYHDw==
83794 -----END CERTIFICATE-----
83795
83796 Certum Root CA
83797 ==============
83798 -----BEGIN CERTIFICATE-----
83799 MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK
83800 ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla
83801 Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u
83802 by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x
83803 wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL
83804 kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ
83805 89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K
83806 Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P
83807 NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq
83808 hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+
83809 GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg
83810 GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/
83811 0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS
83812 qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw==
83813 -----END CERTIFICATE-----
83814
83815 Comodo AAA Services root
83816 ========================
83817 -----BEGIN CERTIFICATE-----
83818 MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
83819 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
83820 TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
83821 MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
83822 c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
83823 BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
83824 ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
83825 C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
83826 i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
83827 Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
83828 Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
83829 Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
83830 BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
83831 cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
83832 LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
83833 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
83834 Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
83835 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
83836 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
83837 -----END CERTIFICATE-----
83838
83839 QuoVadis Root CA
83840 ================
83841 -----BEGIN CERTIFICATE-----
83842 MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
83843 ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
83844 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
83845 MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
83846 cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
83847 EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
83848 AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
83849 J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
83850 F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
83851 YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
83852 AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
83853 PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
83854 ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
83855 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
83856 YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
83857 ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
83858 Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
83859 Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
83860 BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
83861 FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
83862 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
83863 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
83864 fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
83865 LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
83866 gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
83867 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
83868 5nrQNiOKSnQ2+Q==
83869 -----END CERTIFICATE-----
83870
83871 QuoVadis Root CA 2
83872 ==================
83873 -----BEGIN CERTIFICATE-----
83874 MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
83875 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
83876 ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
83877 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
83878 DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
83879 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
83880 lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
83881 lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
83882 lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
83883 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
83884 wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
83885 D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
83886 BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
83887 J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
83888 DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
83889 a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
83890 ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
83891 Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
83892 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
83893 VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
83894 +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
83895 IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
83896 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
83897 f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
83898 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
83899 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
83900 -----END CERTIFICATE-----
83901
83902 QuoVadis Root CA 3
83903 ==================
83904 -----BEGIN CERTIFICATE-----
83905 MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
83906 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
83907 OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
83908 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
83909 DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
83910 DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
83911 KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
83912 DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
83913 BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
83914 p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
83915 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
83916 MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
83917 Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
83918 uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
83919 BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
83920 YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
83921 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
83922 BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
83923 VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
83924 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
83925 AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
83926 qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
83927 hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
83928 POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
83929 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
83930 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
83931 bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
83932 g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
83933 vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
83934 qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
83935 -----END CERTIFICATE-----
83936
83937 Security Communication Root CA
83938 ==============================
83939 -----BEGIN CERTIFICATE-----
83940 MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
83941 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
83942 HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
83943 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
83944 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
83945 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
83946 DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
83947 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
83948 DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
83949 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
83950 DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
83951 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
83952 mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
83953 s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
83954 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
83955 FL39vmwLAw==
83956 -----END CERTIFICATE-----
83957
83958 Sonera Class 2 Root CA
83959 ======================
83960 -----BEGIN CERTIFICATE-----
83961 MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
83962 U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
83963 NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
83964 IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
83965 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
83966 dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
83967 f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
83968 tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
83969 nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
83970 XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
83971 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
83972 cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
83973 Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
83974 EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
83975 llpwrN9M
83976 -----END CERTIFICATE-----
83977
83978 Camerfirma Chambers of Commerce Root
83979 ====================================
83980 -----BEGIN CERTIFICATE-----
83981 MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
83982 QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
83983 ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx
83984 NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp
83985 cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn
83986 MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC
83987 AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU
83988 xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH
83989 NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW
83990 DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV
83991 d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud
83992 EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v
83993 cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P
83994 AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh
83995 bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD
83996 VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
83997 aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi
83998 fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD
83999 L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN
84000 UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n
84001 ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1
84002 erfutGWaIZDgqtCYvDi1czyL+Nw=
84003 -----END CERTIFICATE-----
84004
84005 Camerfirma Global Chambersign Root
84006 ==================================
84007 -----BEGIN CERTIFICATE-----
84008 MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
84009 QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
84010 ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx
84011 NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
84012 YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg
84013 MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw
84014 ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J
84015 1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O
84016 by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl
84017 6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c
84018 8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/
84019 BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j
84020 aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B
84021 Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj
84022 aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y
84023 ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
84024 bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA
84025 PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y
84026 gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ
84027 PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4
84028 IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes
84029 t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
84030 -----END CERTIFICATE-----
84031
84032 XRamp Global CA Root
84033 ====================
84034 -----BEGIN CERTIFICATE-----
84035 MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
84036 BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
84037 dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
84038 dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
84039 HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
84040 U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
84041 dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
84042 IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
84043 foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
84044 zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
84045 AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
84046 xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
84047 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
84048 oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
84049 AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
84050 /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
84051 qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
84052 nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
84053 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
84054 -----END CERTIFICATE-----
84055
84056 Go Daddy Class 2 CA
84057 ===================
84058 -----BEGIN CERTIFICATE-----
84059 MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
84060 VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
84061 ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
84062 A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
84063 RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
84064 ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
84065 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
84066 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
84067 YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
84068 vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
84069 BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
84070 atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
84071 MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
84072 A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
84073 PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
84074 I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
84075 HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
84076 Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
84077 vZ8=
84078 -----END CERTIFICATE-----
84079
84080 Starfield Class 2 CA
84081 ====================
84082 -----BEGIN CERTIFICATE-----
84083 MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
84084 U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
84085 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
84086 MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
84087 A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
84088 SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
84089 bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
84090 JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
84091 epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
84092 F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
84093 MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
84094 hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
84095 bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
84096 QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
84097 afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
84098 PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
84099 xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
84100 KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
84101 QBFGmh95DmK/D5fs4C8fF5Q=
84102 -----END CERTIFICATE-----
84103
84104 StartCom Certification Authority
84105 ================================
84106 -----BEGIN CERTIFICATE-----
84107 MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
84108 U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
84109 ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
84110 NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
84111 LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
84112 U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
84113 ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
84114 o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
84115 Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
84116 eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
84117 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
84118 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
84119 osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
84120 untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
84121 UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
84122 37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
84123 FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0
84124 Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj
84125 YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH
84126 AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw
84127 Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg
84128 U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5
84129 LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl
84130 cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh
84131 cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT
84132 dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC
84133 AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh
84134 3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm
84135 vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk
84136 fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3
84137 fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ
84138 EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
84139 yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl
84140 1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/
84141 lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro
84142 g14=
84143 -----END CERTIFICATE-----
84144
84145 Taiwan GRCA
84146 ===========
84147 -----BEGIN CERTIFICATE-----
84148 MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
84149 EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
84150 DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
84151 dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
84152 ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
84153 w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
84154 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
84155 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
84156 htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
84157 J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
84158 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
84159 B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
84160 O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
84161 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
84162 HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
84163 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
84164 TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
84165 Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
84166 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
84167 D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
84168 DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
84169 Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
84170 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
84171 CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
84172 +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
84173 -----END CERTIFICATE-----
84174
84175 DigiCert Assured ID Root CA
84176 ===========================
84177 -----BEGIN CERTIFICATE-----
84178 MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
84179 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
84180 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
84181 MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
84182 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
84183 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
84184 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
84185 UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
84186 /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
84187 oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
84188 GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
84189 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
84190 hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
84191 EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
84192 SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
84193 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
84194 +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
84195 -----END CERTIFICATE-----
84196
84197 DigiCert Global Root CA
84198 =======================
84199 -----BEGIN CERTIFICATE-----
84200 MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
84201 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
84202 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
84203 MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
84204 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
84205 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
84206 TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
84207 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
84208 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
84209 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
84210 o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
84211 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
84212 BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
84213 EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
84214 tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
84215 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
84216 CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
84217 -----END CERTIFICATE-----
84218
84219 DigiCert High Assurance EV Root CA
84220 ==================================
84221 -----BEGIN CERTIFICATE-----
84222 MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
84223 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
84224 KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
84225 MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
84226 MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
84227 Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
84228 Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
84229 OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
84230 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
84231 NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
84232 h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
84233 Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
84234 JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
84235 V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
84236 myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
84237 mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
84238 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
84239 -----END CERTIFICATE-----
84240
84241 Certplus Class 2 Primary CA
84242 ===========================
84243 -----BEGIN CERTIFICATE-----
84244 MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
84245 BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
84246 OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
84247 dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
84248 ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
84249 5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
84250 Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
84251 YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
84252 e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
84253 CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
84254 YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
84255 L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
84256 P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
84257 TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
84258 7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
84259 //1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
84260 l7+ijrRU
84261 -----END CERTIFICATE-----
84262
84263 DST Root CA X3
84264 ==============
84265 -----BEGIN CERTIFICATE-----
84266 MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
84267 ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
84268 DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
84269 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
84270 ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
84271 rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
84272 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
84273 xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
84274 utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
84275 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
84276 MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
84277 dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
84278 GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
84279 RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
84280 fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
84281 -----END CERTIFICATE-----
84282
84283 DST ACES CA X6
84284 ==============
84285 -----BEGIN CERTIFICATE-----
84286 MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG
84287 EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT
84288 MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha
84289 MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE
84290 CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC
84291 AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI
84292 DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa
84293 pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow
84294 GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy
84295 MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud
84296 EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu
84297 Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy
84298 dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU
84299 CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2
84300 5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t
84301 Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
84302 nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs
84303 vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3
84304 oKfN5XozNmr6mis=
84305 -----END CERTIFICATE-----
84306
84307 SwissSign Gold CA - G2
84308 ======================
84309 -----BEGIN CERTIFICATE-----
84310 MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
84311 EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
84312 MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
84313 c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
84314 AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
84315 t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
84316 jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
84317 vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
84318 ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
84319 AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
84320 jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
84321 peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
84322 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
84323 GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
84324 AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
84325 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
84326 L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
84327 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
84328 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
84329 Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
84330 Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
84331 mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
84332 vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
84333 KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
84334 NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
84335 viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
84336 -----END CERTIFICATE-----
84337
84338 SwissSign Silver CA - G2
84339 ========================
84340 -----BEGIN CERTIFICATE-----
84341 MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
84342 BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
84343 DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
84344 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
84345 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
84346 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
84347 +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
84348 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
84349 MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
84350 qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
84351 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
84352 ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
84353 celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
84354 CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
84355 BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
84356 tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
84357 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
84358 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
84359 kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
84360 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
84361 /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
84362 DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
84363 e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
84364 WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
84365 DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
84366 DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
84367 -----END CERTIFICATE-----
84368
84369 GeoTrust Primary Certification Authority
84370 ========================================
84371 -----BEGIN CERTIFICATE-----
84372 MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
84373 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
84374 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
84375 CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
84376 cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
84377 CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
84378 b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
84379 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
84380 RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
84381 tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
84382 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
84383 hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
84384 Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
84385 NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
84386 Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
84387 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
84388 -----END CERTIFICATE-----
84389
84390 thawte Primary Root CA
84391 ======================
84392 -----BEGIN CERTIFICATE-----
84393 MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
84394 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
84395 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
84396 cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
84397 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
84398 SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
84399 KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
84400 FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
84401 oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
84402 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
84403 q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
84404 aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
84405 afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
84406 VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
84407 AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
84408 uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
84409 xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
84410 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
84411 z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
84412 -----END CERTIFICATE-----
84413
84414 VeriSign Class 3 Public Primary Certification Authority - G5
84415 ============================================================
84416 -----BEGIN CERTIFICATE-----
84417 MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
84418 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
84419 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
84420 IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
84421 ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
84422 yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
84423 biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
84424 dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
84425 YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
84426 ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
84427 j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
84428 Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
84429 Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
84430 fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
84431 BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
84432 Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
84433 aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
84434 SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
84435 X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
84436 KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
84437 Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
84438 ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
84439 -----END CERTIFICATE-----
84440
84441 SecureTrust CA
84442 ==============
84443 -----BEGIN CERTIFICATE-----
84444 MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
84445 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
84446 dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
84447 BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
84448 ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
84449 OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
84450 DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
84451 GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
84452 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
84453 ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
84454 BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
84455 aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
84456 KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
84457 SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
84458 mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
84459 nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
84460 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
84461 -----END CERTIFICATE-----
84462
84463 Secure Global CA
84464 ================
84465 -----BEGIN CERTIFICATE-----
84466 MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
84467 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
84468 bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
84469 MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
84470 Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
84471 YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
84472 bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
84473 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
84474 HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
84475 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
84476 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
84477 oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
84478 MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
84479 OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
84480 CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
84481 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
84482 f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
84483 -----END CERTIFICATE-----
84484
84485 COMODO Certification Authority
84486 ==============================
84487 -----BEGIN CERTIFICATE-----
84488 MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
84489 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
84490 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
84491 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
84492 MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
84493 T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
84494 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
84495 +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
84496 xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
84497 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
84498 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
84499 rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
84500 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
84501 b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
84502 AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
84503 OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
84504 RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
84505 IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
84506 +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
84507 -----END CERTIFICATE-----
84508
84509 Network Solutions Certificate Authority
84510 =======================================
84511 -----BEGIN CERTIFICATE-----
84512 MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
84513 EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
84514 IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
84515 MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
84516 MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
84517 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
84518 jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
84519 aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
84520 crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
84521 /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
84522 AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
84523 BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
84524 bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
84525 A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
84526 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
84527 GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
84528 wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
84529 ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
84530 -----END CERTIFICATE-----
84531
84532 COMODO ECC Certification Authority
84533 ==================================
84534 -----BEGIN CERTIFICATE-----
84535 MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
84536 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
84537 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
84538 dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
84539 GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
84540 Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
84541 b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
84542 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
84543 wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
84544 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
84545 FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
84546 U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
84547 -----END CERTIFICATE-----
84548
84549 Security Communication EV RootCA1
84550 =================================
84551 -----BEGIN CERTIFICATE-----
84552 MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
84553 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh
84554 dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE
84555 BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl
84556 Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
84557 AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO
84558 /VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX
84559 WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z
84560 ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4
84561 bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK
84562 9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
84563 SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm
84564 iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG
84565 Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW
84566 mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW
84567 T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
84568 -----END CERTIFICATE-----
84569
84570 OISTE WISeKey Global Root GA CA
84571 ===============================
84572 -----BEGIN CERTIFICATE-----
84573 MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
84574 BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
84575 A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
84576 bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
84577 VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
84578 IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
84579 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
84580 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
84581 Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
84582 d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
84583 /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
84584 LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
84585 AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
84586 KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
84587 MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
84588 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
84589 hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
84590 okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
84591 -----END CERTIFICATE-----
84592
84593 Certigna
84594 ========
84595 -----BEGIN CERTIFICATE-----
84596 MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
84597 EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
84598 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
84599 Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
84600 XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
84601 GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
84602 ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
84603 DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
84604 Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
84605 tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
84606 BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
84607 SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
84608 hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
84609 ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
84610 PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
84611 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
84612 WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
84613 -----END CERTIFICATE-----
84614
84615 Deutsche Telekom Root CA 2
84616 ==========================
84617 -----BEGIN CERTIFICATE-----
84618 MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
84619 RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
84620 A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
84621 MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
84622 A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
84623 b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
84624 bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
84625 KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
84626 AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
84627 Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
84628 jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
84629 HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
84630 E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
84631 zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
84632 rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
84633 dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
84634 Cm26OWMohpLzGITY+9HPBVZkVw==
84635 -----END CERTIFICATE-----
84636
84637 Cybertrust Global Root
84638 ======================
84639 -----BEGIN CERTIFICATE-----
84640 MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
84641 ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
84642 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
84643 ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
84644 +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
84645 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
84646 AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
84647 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
84648 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
84649 BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
84650 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
84651 A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
84652 lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
84653 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
84654 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
84655 X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
84656 WL1WMRJOEcgh4LMRkWXbtKaIOM5V
84657 -----END CERTIFICATE-----
84658
84659 ePKI Root Certification Authority
84660 =================================
84661 -----BEGIN CERTIFICATE-----
84662 MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
84663 EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
84664 Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
84665 MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
84666 MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
84667 AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
84668 IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
84669 lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
84670 qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
84671 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
84672 WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
84673 ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
84674 lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
84675 vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
84676 Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
84677 MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
84678 ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
84679 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
84680 KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
84681 xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
84682 NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
84683 GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
84684 xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
84685 gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
84686 sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
84687 BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
84688 -----END CERTIFICATE-----
84689
84690 T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3
84691 =============================================================================================================================
84692 -----BEGIN CERTIFICATE-----
84693 MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH
84694 DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q
84695 aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry
84696 b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV
84697 BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg
84698 S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4
84699 MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl
84700 IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF
84701 n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl
84702 IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft
84703 dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl
84704 cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B
84705 AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO
84706 Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1
84707 xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR
84708 6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
84709 hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd
84710 BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
84711 MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4
84712 N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT
84713 y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh
84714 LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M
84715 dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI=
84716 -----END CERTIFICATE-----
84717
84718 certSIGN ROOT CA
84719 ================
84720 -----BEGIN CERTIFICATE-----
84721 MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
84722 VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
84723 Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
84724 CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
84725 JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
84726 rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
84727 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
84728 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
84729 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
84730 Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
84731 AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
84732 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
84733 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
84734 vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
84735 TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
84736 -----END CERTIFICATE-----
84737
84738 GeoTrust Primary Certification Authority - G3
84739 =============================================
84740 -----BEGIN CERTIFICATE-----
84741 MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
84742 BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
84743 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
84744 eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
84745 NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
84746 YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
84747 LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
84748 hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
84749 K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
84750 c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
84751 IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
84752 dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
84753 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
84754 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
84755 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
84756 Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
84757 AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
84758 t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
84759 -----END CERTIFICATE-----
84760
84761 thawte Primary Root CA - G2
84762 ===========================
84763 -----BEGIN CERTIFICATE-----
84764 MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
84765 VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
84766 IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
84767 Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
84768 MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
84769 b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
84770 IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
84771 LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
84772 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
84773 mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
84774 G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
84775 rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
84776 -----END CERTIFICATE-----
84777
84778 thawte Primary Root CA - G3
84779 ===========================
84780 -----BEGIN CERTIFICATE-----
84781 MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
84782 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
84783 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
84784 cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
84785 ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
84786 d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
84787 VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
84788 A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
84789 MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
84790 P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
84791 +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
84792 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
84793 vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
84794 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
84795 KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
84796 A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
84797 t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
84798 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
84799 er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
84800 -----END CERTIFICATE-----
84801
84802 GeoTrust Primary Certification Authority - G2
84803 =============================================
84804 -----BEGIN CERTIFICATE-----
84805 MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
84806 VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
84807 Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
84808 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
84809 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
84810 MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
84811 b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
84812 BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
84813 KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
84814 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
84815 EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
84816 ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
84817 npaqBA+K
84818 -----END CERTIFICATE-----
84819
84820 VeriSign Universal Root Certification Authority
84821 ===============================================
84822 -----BEGIN CERTIFICATE-----
84823 MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
84824 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
84825 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
84826 IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
84827 IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
84828 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
84829 cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
84830 IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
84831 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
84832 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
84833 MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
84834 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
84835 AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
84836 tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
84837 CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
84838 a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
84839 DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
84840 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
84841 Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
84842 P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
84843 wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
84844 mJO37M2CYfE45k+XmCpajQ==
84845 -----END CERTIFICATE-----
84846
84847 VeriSign Class 3 Public Primary Certification Authority - G4
84848 ============================================================
84849 -----BEGIN CERTIFICATE-----
84850 MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
84851 VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
84852 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
84853 ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
84854 YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
84855 MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
84856 cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
84857 b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
84858 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
84859 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
84860 rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
84861 /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
84862 HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
84863 Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
84864 A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
84865 AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
84866 -----END CERTIFICATE-----
84867
84868 NetLock Arany (Class Gold) Főtanúsítvány
84869 ========================================
84870 -----BEGIN CERTIFICATE-----
84871 MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
84872 A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
84873 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
84874 cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
84875 MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
84876 ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
84877 biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
84878 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
84879 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
84880 /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
84881 H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
84882 fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
84883 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
84884 BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
84885 qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
84886 YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
84887 bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
84888 NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
84889 dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
84890 -----END CERTIFICATE-----
84891
84892 Staat der Nederlanden Root CA - G2
84893 ==================================
84894 -----BEGIN CERTIFICATE-----
84895 MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
84896 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
84897 Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
84898 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
84899 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
84900 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
84901 vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
84902 CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
84903 e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
84904 OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
84905 CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
84906 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
84907 trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
84908 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
84909 AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
84910 ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
84911 HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
84912 A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
84913 +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
84914 f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
84915 kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
84916 CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
84917 URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
84918 CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
84919 oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
84920 IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
84921 66+KAQ==
84922 -----END CERTIFICATE-----
84923
84924 Hongkong Post Root CA 1
84925 =======================
84926 -----BEGIN CERTIFICATE-----
84927 MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
84928 DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
84929 NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
84930 IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
84931 AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
84932 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
84933 auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
84934 qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
84935 V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
84936 HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
84937 h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
84938 l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
84939 IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
84940 T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
84941 c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
84942 -----END CERTIFICATE-----
84943
84944 SecureSign RootCA11
84945 ===================
84946 -----BEGIN CERTIFICATE-----
84947 MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
84948 SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
84949 b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
84950 KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
84951 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
84952 TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
84953 wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
84954 g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
84955 O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
84956 bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
84957 t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
84958 OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
84959 bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
84960 Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
84961 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
84962 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
84963 -----END CERTIFICATE-----
84964
84965 ACEDICOM Root
84966 =============
84967 -----BEGIN CERTIFICATE-----
84968 MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD
84969 T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4
84970 MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG
84971 A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF
84972 AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk
84973 WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD
84974 YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew
84975 MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb
84976 m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk
84977 HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT
84978 xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2
84979 3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9
84980 2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq
84981 TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz
84982 4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU
84983 9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
84984 bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg
84985 aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP
84986 eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk
84987 zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1
84988 ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI
84989 KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq
84990 nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE
84991 I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp
84992 MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o
84993 tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA==
84994 -----END CERTIFICATE-----
84995
84996 Microsec e-Szigno Root CA 2009
84997 ==============================
84998 -----BEGIN CERTIFICATE-----
84999 MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
85000 MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
85001 c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
85002 dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
85003 BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
85004 U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
85005 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
85006 fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
85007 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
85008 pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
85009 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
85010 AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
85011 QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
85012 FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
85013 lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
85014 I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
85015 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
85016 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
85017 LXpUq3DDfSJlgnCW
85018 -----END CERTIFICATE-----
85019
85020 GlobalSign Root CA - R3
85021 =======================
85022 -----BEGIN CERTIFICATE-----
85023 MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
85024 YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
85025 bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
85026 aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
85027 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
85028 iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
85029 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
85030 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
85031 OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
85032 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
85033 FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
85034 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
85035 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
85036 bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
85037 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
85038 kpeDMdmztcpHWD9f
85039 -----END CERTIFICATE-----
85040
85041 Autoridad de Certificacion Firmaprofesional CIF A62634068
85042 =========================================================
85043 -----BEGIN CERTIFICATE-----
85044 MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
85045 BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
85046 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
85047 QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
85048 NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
85049 Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
85050 B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
85051 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
85052 ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
85053 plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
85054 MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
85055 LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
85056 bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
85057 vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
85058 EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
85059 DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
85060 cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
85061 bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
85062 ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
85063 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
85064 R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
85065 T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
85066 Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
85067 osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
85068 crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
85069 saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
85070 KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
85071 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
85072 -----END CERTIFICATE-----
85073
85074 Izenpe.com
85075 ==========
85076 -----BEGIN CERTIFICATE-----
85077 MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
85078 EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
85079 MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
85080 QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
85081 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
85082 ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
85083 +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
85084 PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
85085 OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
85086 F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
85087 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
85088 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
85089 leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
85090 AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
85091 SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
85092 NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
85093 MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
85094 BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
85095 Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
85096 kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
85097 hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
85098 g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
85099 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
85100 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
85101 ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
85102 Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
85103 WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
85104 -----END CERTIFICATE-----
85105
85106 Chambers of Commerce Root - 2008
85107 ================================
85108 -----BEGIN CERTIFICATE-----
85109 MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
85110 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
85111 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
85112 QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
85113 Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
85114 ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
85115 EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
85116 cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
85117 AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
85118 XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
85119 h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
85120 ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
85121 NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
85122 D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
85123 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
85124 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
85125 ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
85126 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
85127 G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
85128 BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
85129 bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
85130 bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
85131 CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
85132 AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
85133 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
85134 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
85135 RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
85136 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
85137 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
85138 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
85139 zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
85140 nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
85141 OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
85142 -----END CERTIFICATE-----
85143
85144 Global Chambersign Root - 2008
85145 ==============================
85146 -----BEGIN CERTIFICATE-----
85147 MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
85148 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
85149 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
85150 QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
85151 NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
85152 Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
85153 QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
85154 aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
85155 VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
85156 XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
85157 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
85158 /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
85159 TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
85160 H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
85161 Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
85162 HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
85163 wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
85164 AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
85165 BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
85166 BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
85167 aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
85168 aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
85169 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
85170 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
85171 /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
85172 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
85173 dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
85174 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
85175 foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
85176 qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
85177 P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
85178 c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
85179 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
85180 -----END CERTIFICATE-----
85181
85182 Go Daddy Root Certificate Authority - G2
85183 ========================================
85184 -----BEGIN CERTIFICATE-----
85185 MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
85186 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
85187 MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
85188 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
85189 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
85190 A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
85191 hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
85192 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
85193 +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
85194 fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
85195 NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
85196 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
85197 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
85198 vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
85199 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
85200 N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
85201 LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
85202 -----END CERTIFICATE-----
85203
85204 Starfield Root Certificate Authority - G2
85205 =========================================
85206 -----BEGIN CERTIFICATE-----
85207 MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
85208 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
85209 b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
85210 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
85211 DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
85212 VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
85213 dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
85214 W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
85215 bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
85216 N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
85217 ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
85218 JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
85219 AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
85220 TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
85221 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
85222 F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
85223 pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
85224 c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
85225 -----END CERTIFICATE-----
85226
85227 Starfield Services Root Certificate Authority - G2
85228 ==================================================
85229 -----BEGIN CERTIFICATE-----
85230 MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
85231 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
85232 b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
85233 IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
85234 BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
85235 dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
85236 Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
85237 AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
85238 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
85239 hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
85240 LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
85241 rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
85242 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
85243 SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
85244 E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
85245 xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
85246 iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
85247 YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
85248 -----END CERTIFICATE-----
85249
85250 AffirmTrust Commercial
85251 ======================
85252 -----BEGIN CERTIFICATE-----
85253 MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
85254 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
85255 MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
85256 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
85257 AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
85258 DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
85259 C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
85260 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
85261 MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
85262 HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
85263 AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
85264 hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
85265 qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
85266 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
85267 sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
85268 -----END CERTIFICATE-----
85269
85270 AffirmTrust Networking
85271 ======================
85272 -----BEGIN CERTIFICATE-----
85273 MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
85274 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
85275 MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
85276 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
85277 AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
85278 Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
85279 dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
85280 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
85281 h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
85282 HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
85283 AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
85284 UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
85285 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
85286 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
85287 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
85288 -----END CERTIFICATE-----
85289
85290 AffirmTrust Premium
85291 ===================
85292 -----BEGIN CERTIFICATE-----
85293 MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
85294 BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
85295 OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
85296 dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
85297 MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
85298 BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
85299 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
85300 +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
85301 GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
85302 p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
85303 S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
85304 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
85305 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
85306 +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
85307 /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
85308 MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
85309 Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
85310 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
85311 L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
85312 +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
85313 BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
85314 IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
85315 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
85316 zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
85317 -----END CERTIFICATE-----
85318
85319 AffirmTrust Premium ECC
85320 =======================
85321 -----BEGIN CERTIFICATE-----
85322 MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
85323 BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
85324 MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
85325 cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
85326 IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
85327 N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
85328 BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
85329 BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
85330 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
85331 eQ==
85332 -----END CERTIFICATE-----
85333
85334 Certum Trusted Network CA
85335 =========================
85336 -----BEGIN CERTIFICATE-----
85337 MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
85338 ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
85339 biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
85340 MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
85341 ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
85342 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
85343 AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
85344 l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
85345 J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
85346 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
85347 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
85348 Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
85349 DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
85350 jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
85351 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
85352 Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
85353 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
85354 -----END CERTIFICATE-----
85355
85356 Certinomis - Autorité Racine
85357 ============================
85358 -----BEGIN CERTIFICATE-----
85359 MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
85360 Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg
85361 LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG
85362 A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw
85363 JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD
85364 ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa
85365 wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly
85366 Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw
85367 2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N
85368 jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q
85369 c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC
85370 lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb
85371 xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g
85372 530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna
85373 4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
85374 A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ
85375 KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x
85376 WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva
85377 R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40
85378 nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B
85379 CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv
85380 JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE
85381 qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b
85382 WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE
85383 wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/
85384 vgt2Fl43N+bYdJeimUV5
85385 -----END CERTIFICATE-----
85386
85387 TWCA Root Certification Authority
85388 =================================
85389 -----BEGIN CERTIFICATE-----
85390 MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
85391 VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
85392 dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
85393 EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
85394 IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
85395 AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
85396 QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
85397 oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
85398 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
85399 y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
85400 BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
85401 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
85402 mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
85403 QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
85404 T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
85405 Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
85406 -----END CERTIFICATE-----
85407
85408 Security Communication RootCA2
85409 ==============================
85410 -----BEGIN CERTIFICATE-----
85411 MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
85412 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
85413 dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
85414 SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
85415 aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
85416 ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
85417 +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
85418 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
85419 spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
85420 EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
85421 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
85422 CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
85423 u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
85424 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
85425 tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
85426 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
85427 -----END CERTIFICATE-----
85428
85429 EC-ACC
85430 ======
85431 -----BEGIN CERTIFICATE-----
85432 MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
85433 BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
85434 ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
85435 VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
85436 CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
85437 BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
85438 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
85439 SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
85440 Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
85441 cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
85442 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
85443 w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
85444 ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
85445 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
85446 E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
85447 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
85448 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
85449 VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
85450 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
85451 dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
85452 lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
85453 Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
85454 l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
85455 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
85456 5EI=
85457 -----END CERTIFICATE-----
85458
85459 Hellenic Academic and Research Institutions RootCA 2011
85460 =======================================================
85461 -----BEGIN CERTIFICATE-----
85462 MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
85463 O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
85464 aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
85465 IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
85466 AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
85467 IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
85468 IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
85469 AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
85470 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
85471 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
85472 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
85473 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
85474 MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
85475 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
85476 b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
85477 XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
85478 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
85479 /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
85480 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
85481 -----END CERTIFICATE-----
85482
85483 Actalis Authentication Root CA
85484 ==============================
85485 -----BEGIN CERTIFICATE-----
85486 MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
85487 BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
85488 AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
85489 MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
85490 IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
85491 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
85492 wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
85493 by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
85494 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
85495 YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
85496 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
85497 EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
85498 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
85499 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
85500 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
85501 iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
85502 ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
85503 WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
85504 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
85505 K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
85506 Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
85507 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
85508 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
85509 lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
85510 OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
85511 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
85512 -----END CERTIFICATE-----
85513
85514 Trustis FPS Root CA
85515 ===================
85516 -----BEGIN CERTIFICATE-----
85517 MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
85518 EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
85519 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
85520 BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
85521 KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
85522 RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
85523 H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
85524 cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
85525 o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
85526 AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
85527 BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
85528 GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
85529 yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
85530 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
85531 l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
85532 iB6XzCGcKQENZetX2fNXlrtIzYE=
85533 -----END CERTIFICATE-----
85534
85535 StartCom Certification Authority
85536 ================================
85537 -----BEGIN CERTIFICATE-----
85538 MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
85539 U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
85540 ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
85541 NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
85542 LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
85543 U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
85544 ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
85545 o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
85546 Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
85547 eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
85548 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
85549 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
85550 osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
85551 untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
85552 UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
85553 37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
85554 VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ
85555 Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0
85556 dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu
85557 c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv
85558 bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0
85559 aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0
85560 aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t
85561 L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG
85562 cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5
85563 fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm
85564 N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN
85565 Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T
85566 tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX
85567 e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA
85568 2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs
85569 HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
85570 JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib
85571 D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8=
85572 -----END CERTIFICATE-----
85573
85574 StartCom Certification Authority G2
85575 ===================================
85576 -----BEGIN CERTIFICATE-----
85577 MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
85578 U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
85579 RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE
85580 ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp
85581 dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O
85582 o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG
85583 4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi
85584 Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul
85585 Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs
85586 O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H
85587 vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L
85588 nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS
85589 FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa
85590 z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E
85591 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ
85592 KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
85593 2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk
85594 J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+
85595 JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG
85596 /+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc
85597 nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld
85598 blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc
85599 l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm
85600 7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm
85601 obp573PYtlNXLfbQ4ddI
85602 -----END CERTIFICATE-----
85603
85604 Buypass Class 2 Root CA
85605 =======================
85606 -----BEGIN CERTIFICATE-----
85607 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
85608 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
85609 DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
85610 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
85611 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
85612 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
85613 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
85614 /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
85615 CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
85616 awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
85617 zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
85618 Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
85619 Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
85620 M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
85621 VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
85622 AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
85623 A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
85624 osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
85625 aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
85626 DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
85627 LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
85628 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
85629 wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
85630 CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
85631 rJgWVqA=
85632 -----END CERTIFICATE-----
85633
85634 Buypass Class 3 Root CA
85635 =======================
85636 -----BEGIN CERTIFICATE-----
85637 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
85638 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
85639 DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
85640 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
85641 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
85642 sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
85643 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
85644 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
85645 ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
85646 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
85647 /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
85648 RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
85649 Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
85650 j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
85651 VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
85652 AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
85653 cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
85654 uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
85655 Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
85656 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
85657 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
85658 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
85659 UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
85660 eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
85661 Cp/HuZc=
85662 -----END CERTIFICATE-----
85663
85664 T-TeleSec GlobalRoot Class 3
85665 ============================
85666 -----BEGIN CERTIFICATE-----
85667 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
85668 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
85669 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
85670 MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
85671 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
85672 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
85673 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
85674 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
85675 NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
85676 iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
85677 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
85678 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
85679 AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
85680 fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
85681 ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
85682 P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
85683 e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
85684 -----END CERTIFICATE-----
85685
85686 EE Certification Centre Root CA
85687 ===============================
85688 -----BEGIN CERTIFICATE-----
85689 MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
85690 EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
85691 dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
85692 MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
85693 UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
85694 ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
85695 DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
85696 TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
85697 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
85698 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
85699 P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
85700 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
85701 MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
85702 BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
85703 xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
85704 lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
85705 uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
85706 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
85707 dcGWxZ0=
85708 -----END CERTIFICATE-----
85709
85710 TURKTRUST Certificate Services Provider Root 2007
85711 =================================================
85712 -----BEGIN CERTIFICATE-----
85713 MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
85714 bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
85715 MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
85716 QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X
85717 DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl
85718 a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN
85719 BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
85720 bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw
85721 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N
85722 YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv
85723 KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya
85724 KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT
85725 rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC
85726 AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP
85727 BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s
85728 Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I
85729 aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO
85730 Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb
85731 BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK
85732 poRq0Tl9
85733 -----END CERTIFICATE-----
85734
85735 D-TRUST Root Class 3 CA 2 2009
85736 ==============================
85737 -----BEGIN CERTIFICATE-----
85738 MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85739 DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
85740 Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
85741 LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
85742 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
85743 ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
85744 BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
85745 KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
85746 p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
85747 AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
85748 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
85749 eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
85750 MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
85751 PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
85752 OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
85753 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
85754 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
85755 dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
85756 X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
85757 -----END CERTIFICATE-----
85758
85759 D-TRUST Root Class 3 CA 2 EV 2009
85760 =================================
85761 -----BEGIN CERTIFICATE-----
85762 MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85763 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
85764 OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85765 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
85766 OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
85767 egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
85768 zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
85769 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
85770 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
85771 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
85772 cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
85773 ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
85774 MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
85775 b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
85776 c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
85777 PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
85778 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
85779 ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
85780 NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
85781 w9y4AyHqnxbxLFS1
85782 -----END CERTIFICATE-----
85783
85784 PSCProcert
85785 ==========
85786 -----BEGIN CERTIFICATE-----
85787 MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1dG9yaWRhZCBk
85788 ZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9sYW5vMQswCQYDVQQGEwJWRTEQ
85789 MA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlzdHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lz
85790 dGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBl
85791 cmludGVuZGVuY2lhIGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUw
85792 IwYJKoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEwMFoXDTIw
85793 MTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHByb2NlcnQubmV0LnZlMQ8w
85794 DQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGExKjAoBgNVBAsTIVByb3ZlZWRvciBkZSBD
85795 ZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZp
85796 Y2FjaW9uIEVsZWN0cm9uaWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIw
85797 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo97BVC
85798 wfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74BCXfgI8Qhd19L3uA
85799 3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38GieU89RLAu9MLmV+QfI4tL3czkkoh
85800 RqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmO
85801 EO8GqQKJ/+MMbpfg353bIdD0PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG2
85802 0qCZyFSTXai20b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH
85803 0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/6mnbVSKVUyqU
85804 td+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1mv6JpIzi4mWCZDlZTOpx+FIyw
85805 Bm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvp
85806 r2uKGcfLFFb14dq12fy/czja+eevbqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/
85807 AgEBMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAz
85808 Ni0wMB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFDgBStuyId
85809 xuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRp
85810 ZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQH
85811 EwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5h
85812 Y2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5k
85813 ZW5jaWEgZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG
85814 9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQDAgEGME0GA1UdEQRG
85815 MESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0wMDAwMDKgGwYFYIZeAgKgEgwQUklG
85816 LUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEagRKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52
85817 ZS9sY3IvQ0VSVElGSUNBRE8tUkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNy
85818 YWl6LnN1c2NlcnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v
85819 Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsGAQUFBwIBFh5o
85820 dHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcNAQELBQADggIBACtZ6yKZu4Sq
85821 T96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmN
85822 g7+mvTV+LFwxNG9s2/NkAZiqlCxB3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4q
85823 uxtxj7mkoP3YldmvWb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1
85824 n8GhHVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHmpHmJWhSn
85825 FFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXzsOfIt+FTvZLm8wyWuevo
85826 5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bEqCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq
85827 3TNWOByyrYDT13K9mmyZY+gAu0F2BbdbmRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5
85828 poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y
85829 eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km
85830 -----END CERTIFICATE-----
85831
85832 CA Disig Root R1
85833 ================
85834 -----BEGIN CERTIFICATE-----
85835 MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNVBAYTAlNLMRMw
85836 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
85837 ZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQyMDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sx
85838 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
85839 c2lnIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy
85840 3QRkD2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/oOI7bm+V8
85841 u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3AfQ+lekLZWnDZv6fXARz2
85842 m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJeIgpFy4QxTaz+29FHuvlglzmxZcfe+5nk
85843 CiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8noc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTa
85844 YVKvJrT1cU/J19IG32PK/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6
85845 vpmumwKjrckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD3AjL
85846 LhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE7cderVC6xkGbrPAX
85847 ZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkCyC2fg69naQanMVXVz0tv/wQFx1is
85848 XxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLdqvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNV
85849 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ
85850 04IwDQYJKoZIhvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR
85851 xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaASfX8MPWbTx9B
85852 LxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXoHqJPYNcHKfyyo6SdbhWSVhlM
85853 CrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpBemOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5Gfb
85854 VSUZP/3oNn6z4eGBrxEWi1CXYBmCAMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85
85855 YmLLW1AL14FABZyb7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKS
85856 ds+xDzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvkF7mGnjix
85857 lAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqFa3qdnom2piiZk4hA9z7N
85858 UaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsTQ6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJ
85859 a7+h89n07eLw4+1knj0vllJPgFOL
85860 -----END CERTIFICATE-----
85861
85862 CA Disig Root R2
85863 ================
85864 -----BEGIN CERTIFICATE-----
85865 MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
85866 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
85867 ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
85868 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
85869 c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
85870 w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
85871 xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
85872 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
85873 GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
85874 g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
85875 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
85876 koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
85877 Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
85878 Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
85879 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
85880 Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
85881 tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
85882 sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
85883 dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
85884 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
85885 mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
85886 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
85887 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
85888 UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
85889 7+ZtsH8tZ/3zbBt1RqPlShfppNcL
85890 -----END CERTIFICATE-----
85891
85892 ACCVRAIZ1
85893 =========
85894 -----BEGIN CERTIFICATE-----
85895 MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
85896 SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
85897 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
85898 UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
85899 DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
85900 jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
85901 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
85902 aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
85903 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
85904 WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
85905 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
85906 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
85907 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
85908 Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
85909 Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
85910 Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
85911 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
85912 Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
85913 QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
85914 AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
85915 YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
85916 AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
85917 IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
85918 aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
85919 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
85920 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
85921 hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
85922 R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
85923 YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
85924 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
85925 TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
85926 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
85927 I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
85928 Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
85929 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
85930 EfbRD0tVNEYqi4Y7
85931 -----END CERTIFICATE-----
85932
85933 TWCA Global Root CA
85934 ===================
85935 -----BEGIN CERTIFICATE-----
85936 MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
85937 CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
85938 QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
85939 EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
85940 Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
85941 nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
85942 r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
85943 Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
85944 tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
85945 KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
85946 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
85947 yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
85948 kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
85949 zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
85950 AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
85951 cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
85952 LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
85953 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
85954 /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
85955 lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
85956 A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
85957 i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
85958 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
85959 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
85960 -----END CERTIFICATE-----
85961
85962 TeliaSonera Root CA v1
85963 ======================
85964 -----BEGIN CERTIFICATE-----
85965 MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
85966 CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
85967 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
85968 VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
85969 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
85970 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
85971 B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
85972 Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
85973 oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
85974 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
85975 oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
85976 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
85977 TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
85978 AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
85979 DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
85980 zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
85981 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
85982 pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
85983 G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
85984 c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
85985 JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
85986 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
85987 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
85988 WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
85989 -----END CERTIFICATE-----
85990
85991 E-Tugra Certification Authority
85992 ===============================
85993 -----BEGIN CERTIFICATE-----
85994 MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
85995 DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
85996 ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
85997 ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
85998 NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
85999 QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
86000 cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
86001 DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
86002 MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
86003 hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
86004 CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
86005 ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
86006 BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
86007 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
86008 rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
86009 jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
86010 rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
86011 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
86012 /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
86013 MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
86014 kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
86015 XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
86016 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
86017 a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
86018 dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
86019 KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
86020 Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
86021 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
86022 C7TbO6Orb1wdtn7os4I07QZcJA==
86023 -----END CERTIFICATE-----
86024
86025 T-TeleSec GlobalRoot Class 2
86026 ============================
86027 -----BEGIN CERTIFICATE-----
86028 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
86029 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
86030 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
86031 MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
86032 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
86033 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
86034 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
86035 SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
86036 vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
86037 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
86038 WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
86039 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
86040 YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
86041 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
86042 vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
86043 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
86044 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
86045 -----END CERTIFICATE-----
86046
86047 Atos TrustedRoot 2011
86048 =====================
86049 -----BEGIN CERTIFICATE-----
86050 MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
86051 cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
86052 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
86053 A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
86054 hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
86055 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
86056 DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
86057 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
86058 z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
86059 l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
86060 bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
86061 CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
86062 k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
86063 TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
86064 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
86065 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
86066 -----END CERTIFICATE-----
86067
86068 QuoVadis Root CA 1 G3
86069 =====================
86070 -----BEGIN CERTIFICATE-----
86071 MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
86072 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
86073 b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
86074 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
86075 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
86076 PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
86077 PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
86078 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
86079 ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
86080 g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
86081 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
86082 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
86083 iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
86084 t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86085 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
86086 hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
86087 MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
86088 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
86089 Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
86090 +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
86091 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
86092 wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
86093 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
86094 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
86095 hMJKzRwuJIczYOXD
86096 -----END CERTIFICATE-----
86097
86098 QuoVadis Root CA 2 G3
86099 =====================
86100 -----BEGIN CERTIFICATE-----
86101 MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
86102 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
86103 b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
86104 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
86105 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
86106 ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
86107 NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
86108 oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
86109 MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
86110 V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
86111 L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
86112 sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
86113 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
86114 lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86115 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
86116 hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
86117 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
86118 pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
86119 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
86120 dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
86121 U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
86122 mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
86123 zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
86124 JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
86125 O3jtZsSOeWmD3n+M
86126 -----END CERTIFICATE-----
86127
86128 QuoVadis Root CA 3 G3
86129 =====================
86130 -----BEGIN CERTIFICATE-----
86131 MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
86132 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
86133 b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
86134 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
86135 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
86136 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
86137 Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
86138 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
86139 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
86140 VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
86141 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
86142 Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
86143 dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
86144 rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86145 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
86146 hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
86147 KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
86148 t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
86149 TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
86150 DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
86151 Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
86152 hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
86153 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
86154 dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
86155 PpxxVJkES/1Y+Zj0
86156 -----END CERTIFICATE-----
86157
86158 DigiCert Assured ID Root G2
86159 ===========================
86160 -----BEGIN CERTIFICATE-----
86161 MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
86162 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
86163 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
86164 MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
86165 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
86166 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
86167 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
86168 bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
86169 VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
86170 YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
86171 lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
86172 w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
86173 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
86174 d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
86175 hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
86176 jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
86177 IhNzbM8m9Yop5w==
86178 -----END CERTIFICATE-----
86179
86180 DigiCert Assured ID Root G3
86181 ===========================
86182 -----BEGIN CERTIFICATE-----
86183 MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
86184 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
86185 VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
86186 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
86187 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
86188 BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
86189 RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
86190 KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
86191 UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
86192 YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
86193 1vUhZscv6pZjamVFkpUBtA==
86194 -----END CERTIFICATE-----
86195
86196 DigiCert Global Root G2
86197 =======================
86198 -----BEGIN CERTIFICATE-----
86199 MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
86200 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
86201 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
86202 MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
86203 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
86204 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
86205 kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
86206 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
86207 BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
86208 UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
86209 o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
86210 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
86211 F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
86212 WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
86213 QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
86214 iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
86215 MrY=
86216 -----END CERTIFICATE-----
86217
86218 DigiCert Global Root G3
86219 =======================
86220 -----BEGIN CERTIFICATE-----
86221 MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
86222 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
86223 VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
86224 MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
86225 aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
86226 AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
86227 YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
86228 BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
86229 Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
86230 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
86231 VOKa5Vt8sycX
86232 -----END CERTIFICATE-----
86233
86234 DigiCert Trusted Root G4
86235 ========================
86236 -----BEGIN CERTIFICATE-----
86237 MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
86238 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
86239 HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
86240 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
86241 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
86242 CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
86243 pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
86244 k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
86245 vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
86246 QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
86247 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
86248 mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
86249 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
86250 dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
86251 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
86252 DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
86253 ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
86254 ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
86255 yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
86256 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
86257 ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
86258 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
86259 /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
86260 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
86261 G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
86262 82Z+
86263 -----END CERTIFICATE-----
86264
86265 WoSign
86266 ======
86267 -----BEGIN CERTIFICATE-----
86268 MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQG
86269 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNVBAMTIUNlcnRpZmljYXRpb24g
86270 QXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJ
86271 BgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNh
86272 dGlvbiBBdXRob3JpdHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
86273 vcqNrLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1UfcIiePyO
86274 CbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcSccf+Hb0v1naMQFXQoOXXDX
86275 2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2ZjC1vt7tj/id07sBMOby8w7gLJKA84X5
86276 KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4Mx1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR
86277 +ScPewavVIMYe+HdVHpRaG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ez
86278 EC8wQjchzDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDaruHqk
86279 lWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221KmYo0SLwX3OSACCK2
86280 8jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvASh0JWzko/amrzgD5LkhLJuYwTKVY
86281 yrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWvHYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0C
86282 AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R
86283 8bNLtwYgFP6HEtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1
86284 LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJMuYhOZO9sxXq
86285 T2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2eJXLOC62qx1ViC777Y7NhRCOj
86286 y+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VNg64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC
86287 2nz4SNAzqfkHx5Xh9T71XXG68pWpdIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes
86288 5cVAWubXbHssw1abR80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/
86289 EaEQPkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGcexGATVdVh
86290 mVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+J7x6v+Db9NpSvd4MVHAx
86291 kUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMlOtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGi
86292 kpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWTee5Ehr7XHuQe+w==
86293 -----END CERTIFICATE-----
86294
86295 WoSign China
86296 ============
86297 -----BEGIN CERTIFICATE-----
86298 MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQG
86299 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMMEkNBIOayg+mAmuagueiv
86300 geS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYD
86301 VQQKExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjAN
86302 BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k
86303 8H/rD195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld19AXbbQs5
86304 uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExfv5RxadmWPgxDT74wwJ85
86305 dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnkUkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5
86306 Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+LNVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFy
86307 b7Ao65vh4YOhn0pdr8yb+gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc
86308 76DbT52VqyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6KyX2m
86309 +Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0GAbQOXDBGVWCvOGU6
86310 yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaKJ/kR8slC/k7e3x9cxKSGhxYzoacX
86311 GKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwECAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
86312 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUA
86313 A4ICAQBqinA4WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6
86314 yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj/feTZU7n85iY
86315 r83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6jBAyvd0zaziGfjk9DgNyp115
86316 j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0A
86317 kLppRQjbbpCBhqcqBT/mhDn4t/lXX0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97
86318 qA4bLJyuQHCH2u2nFoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Y
86319 jj4Du9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10lO1Hm13ZB
86320 ONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Leie2uPAmvylezkolwQOQv
86321 T8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR12KvxAmLBsX5VYc8T1yaw15zLKYs4SgsO
86322 kI26oQ==
86323 -----END CERTIFICATE-----
86324
86325 COMODO RSA Certification Authority
86326 ==================================
86327 -----BEGIN CERTIFICATE-----
86328 MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
86329 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
86330 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
86331 biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
86332 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
86333 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
86334 dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
86335 dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
86336 FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
86337 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
86338 x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
86339 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
86340 OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
86341 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
86342 GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
86343 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
86344 FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
86345 DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
86346 rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
86347 nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
86348 tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
86349 sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
86350 pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
86351 zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
86352 ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
86353 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
86354 LaZRfyHBNVOFBkpdn627G190
86355 -----END CERTIFICATE-----
86356
86357 USERTrust RSA Certification Authority
86358 =====================================
86359 -----BEGIN CERTIFICATE-----
86360 MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
86361 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
86362 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
86363 dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
86364 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
86365 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
86366 dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
86367 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
86368 Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
86369 RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
86370 +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
86371 /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
86372 Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
86373 lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
86374 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
86375 eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
86376 BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
86377 MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
86378 FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
86379 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
86380 Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
86381 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
86382 FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
86383 yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
86384 J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
86385 sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
86386 Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
86387 -----END CERTIFICATE-----
86388
86389 USERTrust ECC Certification Authority
86390 =====================================
86391 -----BEGIN CERTIFICATE-----
86392 MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
86393 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
86394 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
86395 biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
86396 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
86397 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
86398 biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
86399 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
86400 nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
86401 HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
86402 HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
86403 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
86404 -----END CERTIFICATE-----
86405
86406 GlobalSign ECC Root CA - R4
86407 ===========================
86408 -----BEGIN CERTIFICATE-----
86409 MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
86410 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
86411 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
86412 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
86413 EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
86414 OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
86415 AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
86416 MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
86417 JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
86418 -----END CERTIFICATE-----
86419
86420 GlobalSign ECC Root CA - R5
86421 ===========================
86422 -----BEGIN CERTIFICATE-----
86423 MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
86424 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
86425 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
86426 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
86427 EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
86428 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
86429 h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
86430 BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
86431 uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
86432 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
86433 -----END CERTIFICATE-----
86434
86435 Staat der Nederlanden Root CA - G3
86436 ==================================
86437 -----BEGIN CERTIFICATE-----
86438 MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
86439 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
86440 Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
86441 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
86442 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
86443 olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
86444 x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
86445 EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
86446 Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
86447 mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
86448 1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
86449 07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
86450 FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
86451 41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
86452 AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
86453 yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
86454 U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
86455 KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
86456 v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
86457 8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
86458 8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
86459 mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
86460 1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
86461 JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
86462 tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
86463 -----END CERTIFICATE-----
86464
86465 Staat der Nederlanden EV Root CA
86466 ================================
86467 -----BEGIN CERTIFICATE-----
86468 MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
86469 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
86470 RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
86471 MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
86472 cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
86473 SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
86474 O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
86475 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
86476 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
86477 XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
86478 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
86479 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
86480 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
86481 fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
86482 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
86483 ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
86484 eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
86485 c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
86486 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
86487 b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
86488 f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
86489 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
86490 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
86491 DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
86492 eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
86493 -----END CERTIFICATE-----
86494
86495 IdenTrust Commercial Root CA 1
86496 ==============================
86497 -----BEGIN CERTIFICATE-----
86498 MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
86499 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
86500 b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
86501 MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
86502 IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
86503 hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
86504 mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
86505 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
86506 XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
86507 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
86508 NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
86509 WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
86510 xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
86511 uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
86512 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
86513 hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
86514 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
86515 ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
86516 ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
86517 YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
86518 feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
86519 kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
86520 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
86521 Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
86522 cGzM7vRX+Bi6hG6H
86523 -----END CERTIFICATE-----
86524
86525 IdenTrust Public Sector Root CA 1
86526 =================================
86527 -----BEGIN CERTIFICATE-----
86528 MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
86529 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
86530 ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
86531 UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
86532 b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
86533 P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
86534 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
86535 rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
86536 qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
86537 mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
86538 ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
86539 LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
86540 iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
86541 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
86542 Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
86543 DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
86544 t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
86545 mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
86546 GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
86547 m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
86548 NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
86549 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
86550 ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
86551 ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
86552 3Wl9af0AVqW3rLatt8o+Ae+c
86553 -----END CERTIFICATE-----
86554
86555 Entrust Root Certification Authority - G2
86556 =========================================
86557 -----BEGIN CERTIFICATE-----
86558 MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
86559 BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
86560 bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
86561 b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
86562 HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
86563 DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
86564 OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
86565 eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
86566 MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
86567 /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
86568 HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
86569 s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
86570 TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
86571 AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
86572 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
86573 iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
86574 Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
86575 nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
86576 vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
86577 e4pIb4tF9g==
86578 -----END CERTIFICATE-----
86579
86580 Entrust Root Certification Authority - EC1
86581 ==========================================
86582 -----BEGIN CERTIFICATE-----
86583 MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
86584 FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
86585 YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
86586 ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
86587 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
86588 FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
86589 LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
86590 dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
86591 IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
86592 AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
86593 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
86594 FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
86595 vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
86596 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
86597 -----END CERTIFICATE-----
86598
86599 CFCA EV ROOT
86600 ============
86601 -----BEGIN CERTIFICATE-----
86602 MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
86603 CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
86604 IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
86605 MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
86606 DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
86607 BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
86608 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
86609 uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
86610 ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
86611 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
86612 py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
86613 gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
86614 hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
86615 tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
86616 BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
86617 /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
86618 ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
86619 ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
86620 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
86621 E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
86622 BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
86623 aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
86624 PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
86625 kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
86626 ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
86627 -----END CERTIFICATE-----
86628
86629 TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5
86630 ====================================================
86631 -----BEGIN CERTIFICATE-----
86632 MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UEBhMCVFIxDzAN
86633 BgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
86634 bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1Qg
86635 RWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAw
86636 ODA3MDFaFw0yMzA0MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0w
86637 SwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnE
86638 n2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRp
86639 ZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
86640 CgKCAQEApCUZ4WWe60ghUEoI5RHwWrom/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537
86641 jVJp45wnEFPzpALFp/kRGml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1m
86642 ep5Fimh34khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z5UNP
86643 9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0hO8EuPbJbKoCPrZV
86644 4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QIDAQABo0IwQDAdBgNVHQ4EFgQUVpkH
86645 HtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
86646 hvcNAQELBQADggEBAJ5FdnsXSDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPo
86647 BP5yCccLqh0lVX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq
86648 URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nfpeYVhDfwwvJl
86649 lpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CFYv4HAqGEVka+lgqaE9chTLd8
86650 B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW+qtB4Uu2NQvAmxU=
86651 -----END CERTIFICATE-----
86652
86653 Certinomis - Root CA
86654 ====================
86655 -----BEGIN CERTIFICATE-----
86656 MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
86657 Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg
86658 LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx
86659 EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD
86660 ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos
86661 P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo
86662 d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap
86663 z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00
86664 8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x
86665 RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE
86666 6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t
86667 FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV
86668 PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH
86669 i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj
86670 YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I
86671 6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF
86672 AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV
86673 WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw
86674 Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX
86675 lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ
86676 y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9
86677 Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng
86678 DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi
86679 I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM
86680 cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr
86681 hkIGuUE=
86682 -----END CERTIFICATE-----
86683
86684 OISTE WISeKey Global Root GB CA
86685 ===============================
86686 -----BEGIN CERTIFICATE-----
86687 MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
86688 EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
86689 ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
86690 MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
86691 VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
86692 b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
86693 scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
86694 rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
86695 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
86696 Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
86697 GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
86698 /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
86699 hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
86700 dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
86701 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
86702 HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
86703 Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
86704 -----END CERTIFICATE-----
86705
86706 Certification Authority of WoSign G2
86707 ====================================
86708 -----BEGIN CERTIFICATE-----
86709 MIIDfDCCAmSgAwIBAgIQayXaioidfLwPBbOxemFFRDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQG
86710 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxLTArBgNVBAMTJENlcnRpZmljYXRpb24g
86711 QXV0aG9yaXR5IG9mIFdvU2lnbiBHMjAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMFgx
86712 CzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEtMCsGA1UEAxMkQ2VydGlm
86713 aWNhdGlvbiBBdXRob3JpdHkgb2YgV29TaWduIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
86714 CgKCAQEAvsXEoCKASU+/2YcRxlPhuw+9YH+v9oIOH9ywjj2X4FA8jzrvZjtFB5sg+OPXJYY1kBai
86715 XW8wGQiHC38Gsp1ij96vkqVg1CuAmlI/9ZqD6TRay9nVYlzmDuDfBpgOgHzKtB0TiGsOqCR3A9Du
86716 W/PKaZE1OVbFbeP3PU9ekzgkyhjpJMuSA93MHD0JcOQg5PGurLtzaaNjOg9FD6FKmsLRY6zLEPg9
86717 5k4ot+vElbGs/V6r+kHLXZ1L3PR8du9nfwB6jdKgGlxNIuG12t12s9R23164i5jIFFTMaxeSt+BK
86718 v0mUYQs4kI9dJGwlezt52eJ+na2fmKEG/HgUYFf47oB3sQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
86719 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU+mCp62XF3RYUCE4MD42b4Pdkr2cwDQYJKoZI
86720 hvcNAQELBQADggEBAFfDejaCnI2Y4qtAqkePx6db7XznPWZaOzG73/MWM5H8fHulwqZm46qwtyeY
86721 P0nXYGdnPzZPSsvxFPpahygc7Y9BMsaV+X3avXtbwrAh449G3CE4Q3RM+zD4F3LBMvzIkRfEzFg3
86722 TgvMWvchNSiDbGAtROtSjFA9tWwS1/oJu2yySrHFieT801LYYRf+epSEj3m2M1m6D8QL4nCgS3gu
86723 +sif/a+RZQp4OBXllxcU3fngLDT4ONCEIgDAFFEYKwLcMFrw6AF8NTojrwjkr6qOKEJJLvD1mTS+
86724 7Q9LGOHSJDy7XUe3IfKN0QqZjuNuPq1w4I+5ysxugTH2e5x6eeRncRg=
86725 -----END CERTIFICATE-----
86726
86727 CA WoSign ECC Root
86728 ==================
86729 -----BEGIN CERTIFICATE-----
86730 MIICCTCCAY+gAwIBAgIQaEpYcIBr8I8C+vbe6LCQkDAKBggqhkjOPQQDAzBGMQswCQYDVQQGEwJD
86731 TjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMTEkNBIFdvU2lnbiBFQ0MgUm9v
86732 dDAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQK
86733 ExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAxMSQ0EgV29TaWduIEVDQyBSb290MHYwEAYHKoZI
86734 zj0CAQYFK4EEACIDYgAE4f2OuEMkq5Z7hcK6C62N4DrjJLnSsb6IOsq/Srj57ywvr1FQPEd1bPiU
86735 t5v8KB7FVMxjnRZLU8HnIKvNrCXSf4/CwVqCXjCLelTOA7WRf6qU0NGKSMyCBSah1VES1ns2o0Iw
86736 QDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqv3VWqP2h4syhf3R
86737 MluARZPzA7gwCgYIKoZIzj0EAwMDaAAwZQIxAOSkhLCB1T2wdKyUpOgOPQB0TKGXa/kNUTyh2Tv0
86738 Daupn75OcsqF1NnstTJFGG+rrQIwfcf3aWMvoeGY7xMQ0Xk/0f7qO3/eVvSQsRUR2LIiFdAvwyYu
86739 a/GRspBl9JrmkO5K
86740 -----END CERTIFICATE-----
86741
86742 SZAFIR ROOT CA2
86743 ===============
86744 -----BEGIN CERTIFICATE-----
86745 MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
86746 A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
86747 BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
86748 BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
86749 VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
86750 qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
86751 DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
86752 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
86753 ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
86754 ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
86755 AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
86756 AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
86757 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
86758 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
86759 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
86760 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
86761 -----END CERTIFICATE-----
86762
86763 Certum Trusted Network CA 2
86764 ===========================
86765 -----BEGIN CERTIFICATE-----
86766 MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
86767 BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
86768 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
86769 ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
86770 TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
86771 cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
86772 IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
86773 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
86774 CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
86775 Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
86776 uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
86777 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
86778 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
86779 Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
86780 hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
86781 BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86782 AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
86783 hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
86784 Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
86785 L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
86786 clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
86787 pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
86788 w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
86789 J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
86790 ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
86791 is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
86792 zAYspsbiDrW5viSP
86793 -----END CERTIFICATE-----
86794
86795 Hellenic Academic and Research Institutions RootCA 2015
86796 =======================================================
86797 -----BEGIN CERTIFICATE-----
86798 MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
86799 BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
86800 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
86801 YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
86802 MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
86803 QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
86804 BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
86805 MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
86806 bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
86807 iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
86808 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
86809 FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
86810 i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
86811 GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
86812 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
86813 iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
86814 Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86815 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
86816 hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
86817 D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
86818 d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
86819 d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
86820 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
86821 davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
86822 Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
86823 J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
86824 JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
86825 p/UsQu0yrbYhnr68
86826 -----END CERTIFICATE-----
86827
86828 Hellenic Academic and Research Institutions ECC RootCA 2015
86829 ===========================================================
86830 -----BEGIN CERTIFICATE-----
86831 MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
86832 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
86833 cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
86834 aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
86835 MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
86836 IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
86837 VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
86838 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
86839 dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
86840 Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
86841 BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
86842 GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
86843 dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
86844 -----END CERTIFICATE-----
86845
86846 Certplus Root CA G1
86847 ===================
86848 -----BEGIN CERTIFICATE-----
86849 MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUAMD4xCzAJBgNV
86850 BAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTAe
86851 Fw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhD
86852 ZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQAD
86853 ggIPADCCAgoCggIBANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHN
86854 r49aiZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt6kuJPKNx
86855 Qv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP0FG7Yn2ksYyy/yARujVj
86856 BYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTv
86857 LRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDEEW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2
86858 z4QTd28n6v+WZxcIbekN1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc
86859 4nBvCGrch2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCTmehd
86860 4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV4EJQeIQEQWGw9CEj
86861 jy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPOWftwenMGE9nTdDckQQoRb5fc5+R+
86862 ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G
86863 A1UdDgQWBBSowcCbkahDFXxdBie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHY
86864 lwuBsTANBgkqhkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh
86865 66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7/SMNkPX0XtPG
86866 YX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BSS7CTKtQ+FjPlnsZlFT5kOwQ/
86867 2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F
86868 6ALEUz65noe8zDUa3qHpimOHZR4RKttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilX
86869 CNQ314cnrUlZp5GrRHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWe
86870 tUNy6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEVV/xuZDDC
86871 VRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5g4VCXA9DO2pJNdWY9BW/
86872 +mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl++O/QmueD6i9a5jc2NvLi6Td11n0bt3+
86873 qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo=
86874 -----END CERTIFICATE-----
86875
86876 Certplus Root CA G2
86877 ===================
86878 -----BEGIN CERTIFICATE-----
86879 MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4xCzAJBgNVBAYT
86880 AkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjAeFw0x
86881 NDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0
86882 cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IA
86883 BM0PW1aC3/BFGtat93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uN
86884 Am8xIk0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0PAQH/BAQD
86885 AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMB8GA1Ud
86886 IwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqGSM49BAMDA2gAMGUCMHD+sAvZ94OX7PNV
86887 HdTcswYO/jOYnYs5kGuUIe22113WTNchp+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjl
86888 vPl5adytRSv3tjFzzAalU5ORGpOucGpnutee5WEaXw==
86889 -----END CERTIFICATE-----
86890
86891 OpenTrust Root CA G1
86892 ====================
86893 -----BEGIN CERTIFICATE-----
86894 MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV
86895 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx
86896 MB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
86897 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEB
86898 AQUAA4ICDwAwggIKAoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7fa
86899 Yp6bwiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX/uMftk87
86900 ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR077F9jAHiOH3BX2pfJLKO
86901 YheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGPuY4zbGneWK2gDqdkVBFpRGZPTBKnjix9
86902 xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLxp2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO
86903 9z0M+Yo0FMT7MzUj8czxKselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq
86904 3ywgsNw2TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+WG+Oi
86905 n6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPwvFEVVJSmdz7QdFG9
86906 URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYYEQRVzXR7z2FwefR7LFxckvzluFqr
86907 TJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
86908 /zAdBgNVHQ4EFgQUl0YhVyE12jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/Px
86909 N3DlCPaTKbYwDQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E
86910 PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kfgLMtMrpkZ2Cv
86911 uVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbSFXJfLkur1J1juONI5f6ELlgK
86912 n0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLh
86913 X4SPgPL0DTatdrOjteFkdjpY3H1PXlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80
86914 nR14SohWZ25g/4/Ii+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcm
86915 GS3tTAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L9109S5zvE/
86916 bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/KyPu1svf0OnWZzsD2097+o
86917 4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJAwSQiumPv+i2tCqjI40cHLI5kqiPAlxA
86918 OXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj1oxx
86919 -----END CERTIFICATE-----
86920
86921 OpenTrust Root CA G2
86922 ====================
86923 -----BEGIN CERTIFICATE-----
86924 MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUAMEAxCzAJBgNV
86925 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcy
86926 MB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
86927 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEB
86928 AQUAA4ICDwAwggIKAoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+
86929 Ntmh/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78eCbY2albz
86930 4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/61UWY0jUJ9gNDlP7ZvyCV
86931 eYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fEFY8ElggGQgT4hNYdvJGmQr5J1WqIP7wt
86932 UdGejeBSzFfdNTVY27SPJIjki9/ca1TSgSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz
86933 3GIZ38i1MH/1PCZ1Eb3XG7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj
86934 3CzMpSZyYhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaHvGOz
86935 9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4t/bQWVyJ98LVtZR0
86936 0dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/gh7PU3+06yzbXfZqfUAkBXKJOAGT
86937 y3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
86938 /zAdBgNVHQ4EFgQUajn6QiL35okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59
86939 M4PLuG53hq8wDQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz
86940 Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0nXGEL8pZ0keI
86941 mUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qTRmTFAHneIWv2V6CG1wZy7HBG
86942 S4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpTwm+bREx50B1ws9efAvSyB7DH5fitIw6mVskp
86943 EndI2S9G/Tvw/HRwkqWOOAgfZDC2t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ
86944 6e18CL13zSdkzJTaTkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97kr
86945 gCf2o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU3jg9CcCo
86946 SmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eAiN1nE28daCSLT7d0geX0
86947 YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14fWKGVyasvc0rQLW6aWQ9VGHgtPFGml4vm
86948 u7JwqkwR3v98KzfUetF3NI/n+UL3PIEMS1IK
86949 -----END CERTIFICATE-----
86950
86951 OpenTrust Root CA G3
86952 ====================
86953 -----BEGIN CERTIFICATE-----
86954 MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAxCzAJBgNVBAYT
86955 AkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEczMB4X
86956 DTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9w
86957 ZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQA
86958 IgNiAARK7liuTcpm3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5B
86959 ta1doYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4GA1UdDwEB
86960 /wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAf
86961 BgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAKBggqhkjOPQQDAwNpADBmAjEAj6jcnboM
86962 BBf6Fek9LykBl7+BFjNAk2z8+e2AcG+qj9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta
86963 3U1fJAuwACEl74+nBCZx4nxp5V2a+EEfOzmTk51V6s2N8fvB
86964 -----END CERTIFICATE-----
86965
86966 ISRG Root X1
86967 ============
86968 -----BEGIN CERTIFICATE-----
86969 MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
86970 BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
86971 EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
86972 EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
86973 DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
86974 Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
86975 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
86976 b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
86977 Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
86978 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
86979 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
86980 hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
86981 usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
86982 OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
86983 A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
86984 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
86985 ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
86986 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
86987 hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
86988 TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
86989 e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
86990 JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
86991 YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
86992 JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
86993 m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
86994 -----END CERTIFICATE-----
86995
86996 AC RAIZ FNMT-RCM
86997 ================
86998 -----BEGIN CERTIFICATE-----
86999 MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
87000 AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
87001 MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
87002 TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
87003 ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
87004 qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
87005 btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
87006 j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
87007 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
87008 WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
87009 tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
87010 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
87011 ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
87012 i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
87013 FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
87014 dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
87015 nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
87016 D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
87017 j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
87018 Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
87019 +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
87020 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
87021 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
87022 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
87023 rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
87024 -----END CERTIFICATE-----
87025
87026 Amazon Root CA 1
87027 ================
87028 -----BEGIN CERTIFICATE-----
87029 MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
87030 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
87031 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
87032 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
87033 ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
87034 FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
87035 gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
87036 dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
87037 VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
87038 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
87039 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
87040 CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
87041 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
87042 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
87043 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
87044 -----END CERTIFICATE-----
87045
87046 Amazon Root CA 2
87047 ================
87048 -----BEGIN CERTIFICATE-----
87049 MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
87050 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
87051 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
87052 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
87053 ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
87054 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
87055 N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
87056 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
87057 fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
87058 kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
87059 btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
87060 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
87061 c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
87062 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
87063 DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
87064 A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
87065 +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
87066 YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
87067 xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
87068 gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
87069 aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
87070 Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
87071 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
87072 JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
87073 -----END CERTIFICATE-----
87074
87075 Amazon Root CA 3
87076 ================
87077 -----BEGIN CERTIFICATE-----
87078 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
87079 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
87080 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
87081 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
87082 f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
87083 Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
87084 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
87085 eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
87086 -----END CERTIFICATE-----
87087
87088 Amazon Root CA 4
87089 ================
87090 -----BEGIN CERTIFICATE-----
87091 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
87092 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
87093 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
87094 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
87095 /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
87096 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
87097 HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
87098 MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
87099 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
87100 -----END CERTIFICATE-----
87101
87102 LuxTrust Global Root 2
87103 ======================
87104 -----BEGIN CERTIFICATE-----
87105 MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG
87106 A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh
87107 bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW
87108 MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC
87109 AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm
87110 Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2
87111 xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC
87112 wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm
87113 1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm
87114 FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF
87115 wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/
87116 a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U
87117 ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ
87118 MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB
87119 /zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5
87120 Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
87121 +Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ
87122 FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN
87123 H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW
87124 7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu
87125 ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA
87126 VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR
87127 TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
87128 /f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc
87129 7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
87130 iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
87131 -----END CERTIFICATE-----
87132
87133 TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
87134 =============================================
87135 -----BEGIN CERTIFICATE-----
87136 MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
87137 D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
87138 IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
87139 TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
87140 ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
87141 VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
87142 c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
87143 bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
87144 IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
87145 MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
87146 6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
87147 wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
87148 3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
87149 WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
87150 ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
87151 KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
87152 AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
87153 lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
87154 e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
87155 q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
87156 -----END CERTIFICATE-----
87157 <?php
87158
87159 if (PHP_SAPI !== 'cli') {
87160     echo 'Warning: Composer should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
87161 }
87162
87163 require __DIR__.'/../src/bootstrap.php';
87164
87165 use Composer\Factory;
87166 use Composer\XdebugHandler;
87167 use Composer\Console\Application;
87168
87169 error_reporting(-1);
87170
87171 // Create output for XdebugHandler and Application
87172 $output = Factory::createOutput();
87173
87174 $xdebug = new XdebugHandler($output);
87175 $xdebug->check();
87176 unset($xdebug);
87177
87178 if (function_exists('ini_set')) {
87179     @ini_set('display_errors', 1);
87180
87181     $memoryInBytes = function ($value) {
87182         $unit = strtolower(substr($value, -1, 1));
87183         $value = (int) $value;
87184         switch($unit) {
87185             case 'g':
87186                 $value *= 1024;
87187                 // no break (cumulative multiplier)
87188             case 'm':
87189                 $value *= 1024;
87190                 // no break (cumulative multiplier)
87191             case 'k':
87192                 $value *= 1024;
87193         }
87194
87195         return $value;
87196     };
87197
87198     $memoryLimit = trim(ini_get('memory_limit'));
87199     // Increase memory_limit if it is lower than 1.5GB
87200     if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
87201         @ini_set('memory_limit', '1536M');
87202     }
87203     // Set user defined memory limit
87204     if ($memoryLimit = getenv('COMPOSER_MEMORY_LIMIT')) {
87205         @ini_set('memory_limit', $memoryLimit);
87206     }
87207     unset($memoryInBytes, $memoryLimit);
87208 }
87209
87210 putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
87211
87212 // run the command application
87213 $application = new Application();
87214 $application->run(null, $output);
87215
87216 Copyright (c) Nils Adermann, Jordi Boggiano
87217
87218 Permission is hereby granted, free of charge, to any person obtaining a copy
87219 of this software and associated documentation files (the "Software"), to deal
87220 in the Software without restriction, including without limitation the rights
87221 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
87222 copies of the Software, and to permit persons to whom the Software is furnished
87223 to do so, subject to the following conditions:
87224
87225 The above copyright notice and this permission notice shall be included in all
87226 copies or substantial portions of the Software.
87227
87228 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
87229 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87230 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
87231 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
87232 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
87233 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
87234 THE SOFTWARE.
87235
87236 \ 2=Ââ\1cFz\15I)6#õ\8e\9faw&ã¬\ 2\0\0\0GBMB