]> git.mxchange.org Git - friendica.git/blob - bin/composer.phar
Merge pull request #5419 from annando/fixes
[friendica.git] / bin / composer.phar
1 #!/usr/bin/env php
2 <?php
3 /*
4  * This file is part of Composer.
5  *
6  * (c) Nils Adermann <naderman@naderman.de>
7  *     Jordi Boggiano <j.boggiano@seld.be>
8  *
9  * For the full copyright and license information, please view
10  * the license that is located at the bottom of this file.
11  */
12
13 // Avoid APC causing random fatal errors per https://github.com/composer/composer/issues/264
14 if (extension_loaded('apc') && ini_get('apc.enable_cli') && ini_get('apc.cache_by_default')) {
15     if (version_compare(phpversion('apc'), '3.0.12', '>=')) {
16         ini_set('apc.cache_by_default', 0);
17     } else {
18         fwrite(STDERR, 'Warning: APC <= 3.0.12 may cause fatal errors when running composer commands.'.PHP_EOL);
19         fwrite(STDERR, 'Update APC, or set apc.enable_cli or apc.cache_by_default to 0 in your php.ini.'.PHP_EOL);
20     }
21 }
22
23 Phar::mapPhar('composer.phar');
24 require 'phar://composer.phar/bin/composer';
25
26 __HALT_COMPILER(); ?>\r
27 ù\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\9a\8bOZþa\0\0tG\9d\94\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Autoload/ClassMapGenerator.php«\11\0\0\9a\8bOZ«\11\0\0\10ëÊ\9a\ 1\0\0\0\0\0\0\16\0\0\0src/Composer/Cache.phpt\13\0\0\9a\8bOZt\13\0\0\0\11&#¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Command/AboutCommand.phpË\ 2\0\0\9a\8bOZË\ 2\0\0º¡Ãh¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/ArchiveCommand.phpL\14\0\0\9a\8bOZL\14\0\0\85\r;V¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/BaseCommand.phpÉ        \0\0\9a\8bOZÉ \0\0\97P!£¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Command/BaseDependencyCommand.phpÉ\18\0\0\9a\8bOZÉ\18\0\0D{²Ð¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Command/CheckPlatformReqsCommand.php\82\f\0\0\9a\8bOZ\82\f\0\0\a\88D\86\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/ClearCacheCommand.php]\ 5\0\0\9a\8bOZ]\ 5\0\0\1f\82ß´¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/ConfigCommand.php\87H\0\0\9a\8bOZ\87H\0\0Ä×\ 5Ö¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Command/CreateProjectCommand.php 5\0\0\9a\8bOZ 5\0\0\14\82Z\16\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/DependsCommand.php·\ 2\0\0\9a\8bOZ·\ 2\0\0o±¹ú¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/DiagnoseCommand.phpÕG\0\0\9a\8bOZÕG\0\0ðõü\v\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Command/DumpAutoloadCommand.php\12
28 \0\0\9a\8bOZ\12
29 \0\0'K¬\9e\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ExecCommand.phpi\a\0\0\9a\8bOZi\a\0\0\ 4\80\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/GlobalCommand.phpü\a\0\0\9a\8bOZü\a\0\0ÝH\8f\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/HomeCommand.phpÃ\ e\0\0\9a\8bOZÃ\ e\0\0¯àyB¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/InitCommand.phpuI\0\0\9a\8bOZuI\0\0\1f\1f±Ð¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/InstallCommand.phpý\13\0\0\9a\8bOZý\13\0\00ö:\89\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/LicensesCommand.php&\ e\0\0\9a\8bOZ&\ e\0\0Óv\83\1e\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/OutdatedCommand.php°
30 \0\0\9a\8bOZ°
31 \0\07àzk¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/ProhibitsCommand.phpË\ 2\0\0\9a\8bOZË\ 2\0\0\1ag\8fð¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/RemoveCommand.php\9b\15\0\0\9a\8bOZ\9b\15\0\0>Sþ\98\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/RequireCommand.phpÖ \0\0\9a\8bOZÖ \0\0B÷õE¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/RunScriptCommand.php\9f\f\0\0\9a\8bOZ\9f\f\0\0ûØO    ¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Command/ScriptAliasCommand.phpo\ 5\0\0\9a\8bOZo\ 5\0\0\r5Þl¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/SearchCommand.phpã\b\0\0\9a\8bOZã\b\0\0ñ\v¼w¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/SelfUpdateCommand.php\101\0\0\9a\8bOZ\101\0\0üÛ))¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ShowCommand.phpug\0\0\9a\8bOZug\0\0ÀÕé\13\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/StatusCommand.php/\15\0\0\9a\8bOZ/\15\0\0ôE\12\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/SuggestsCommand.php¨\r\0\0\9a\8bOZ¨\r\0\0¼Ñ\ 5\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/UpdateCommand.php¯#\0\0\9a\8bOZ¯#\0\0\97ú\8d\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/ValidateCommand.php#\14\0\0\9a\8bOZ#\14\0\0\89\0\9d\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Composer.phpù       \0\0\9a\8bOZù \0\0\b\11\ 1\0\0\0\0\0\0\17\0\0\0src/Composer/Config.phpÅ"\0\0\9a\8bOZÅ"\0\0\9d¡¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Config/ConfigSourceInterface.php\ e\ 2\0\0\9a\8bOZ\ e\ 2\0\0³\f[/¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Config/JsonConfigSource.php!\13\0\0\9a\8bOZ!\13\0\0¾S\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Console/Application.php§3\0\0\9a\8bOZ§3\0\0\89D;q¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Console/HtmlOutputFormatter.php3\ 6\0\0\9a\8bOZ3\ 6\0\0Ú\81Eu¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/DependencyResolver/Decisions.phpQ\ f\0\0\9a\8bOZQ\ f\0\0?\98¬$¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/DefaultPolicy.php\ 2\17\0\0\9a\8bOZ\ 2\17\0\0õÝv\7f\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/GenericRule.php·\ 3\0\0\9a\8bOZ·\ 3\0\0Ì~¯³¶\ 1\0\0\0\0\0\0>\0\0\0src/Composer/DependencyResolver/Operation/InstallOperation.phpC\ 2\0\0\9a\8bOZC\ 2\0\0´\õ*¶\ 1\0\0\0\0\0\0I\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php÷\ 2\0\0\9a\8bOZ÷\ 2\0\0ïÎà÷¶\ 1\0\0\0\0\0\0K\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpý\ 2\0\0\9a\8bOZý\ 2\0\0\193#\86\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ\0\0\0\9a\8bOZÓ\0\0\0Ùâ&ä¶\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/SolverOperation.php¹\ 1\0\0\9a\8bOZ¹\ 1\0\0&¢e
32\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/UninstallOperation.phpI\ 2\0\0\9a\8bOZI\ 2\0\0FûÂɶ\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/UpdateOperation.phph\ 3\0\0\9a\8bOZh\ 3\0\0öSÕ]¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/PolicyInterface.php­\ 1\0\0\9a\8bOZ­\ 1\0\0\18\9f\8b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Pool.php°"\0\0\9a\8bOZ°"\0\0\1d   \8e\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Problem.php\99\16\0\0\9a\8bOZ\99\16\0\0\ 3´\87Ķ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Request.php\83\ 4\0\0\9a\8bOZ\83\ 4\0\0åVP\84\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Rule.php¶\18\0\0\9a\8bOZ¶\18\0\0Ú{\8d\8d\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/Rule2Literals.php§\ 4\0\0\9a\8bOZ§\ 4\0\0~Ð'ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/RuleSet.phpª
33 \0\0\9a\8bOZª
34 \0\0\82\e\ 1\0\0\0\0\0\04\0\0\0src/Composer/DependencyResolver/RuleSetGenerator.phpL\e\0\0\9a\8bOZL\e\0\0¡³`\ 5\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/RuleSetIterator.php\11\ 6\0\0\9a\8bOZ\11\ 6\0\0\9bCü$¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchChain.phpi\ 1\0\0\9a\8bOZi\ 1\0\0\9a\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchGraph.phpá\ 6\0\0\9a\8bOZá\ 6\0\0\89rôv¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/RuleWatchNode.phpé\ 3\0\0\9a\8bOZé\ 3\0\0hØÑ´¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/DependencyResolver/Solver.php\9f8\0\0\9a\8bOZ\9f8\0\0\1epöb¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/DependencyResolver/SolverBugException.php\98\ 1\0\0\9a\8bOZ\98\ 1\0\0\7f"qN¶\ 1\0\0\0\0\0\0;\0\0\0src/Composer/DependencyResolver/SolverProblemsException.phpô\a\0\0\9a\8bOZô\a\0\0×|Ŧ¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/Transaction.phpÙ\13\0\0\9a\8bOZÙ\13\0\05ÖHÀ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Downloader/ArchiveDownloader.php³      \0\0\9a\8bOZ³ \0\0ÖðÞ\9f\ 1\0\0\0\0\0\01\0\0\0src/Composer/Downloader/ChangeReportInterface.phpÌ\0\0\0\9a\8bOZÌ\0\0\0¯à¨¿¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Downloader/DownloadManager.phpG\15\0\0\9a\8bOZG\15\0\0\8a(í»¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/DownloaderInterface.phpÊ\ 1\0\0\9a\8bOZÊ\ 1\0\0gs!l¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Downloader/DvcsDownloaderInterface.phpÑ\0\0\0\9a\8bOZÑ\0\0\0\9c¿¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/FileDownloader.php\8d\18\0\0\9a\8bOZ\8d\18\0\01\82ã\14\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/FilesystemException.php
35 \ 1\0\0\9a\8bOZ
36 \ 1\0\0.-\1e\8b\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Downloader/FossilDownloader.php`\v\0\0\9a\8bOZ`\v\0\0ÿI©u¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/GitDownloader.php?4\0\0\9a\8bOZ?4\0\0e\8d\17\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/GzipDownloader.phpó\ 6\0\0\9a\8bOZó\ 6\0\0}Úo¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/HgDownloader.php8 \0\0\9a\8bOZ8 \0\0ëyàn¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PathDownloader.phpK\11\0\0\9a\8bOZK\11\0\09\95&c¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Downloader/PearPackageExtractor.phpu\e\0\0\9a\8bOZu\e\0\0z\84\15\87\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/PerforceDownloader.php§\a\0\0\9a\8bOZ§\a\0\0â\83\10¨¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PharDownloader.phpå\0\0\0\9a\8bOZå\0\0\0ÞÉ\1fç¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/RarDownloader.php\9e\a\0\0\9a\8bOZ\9e\a\0\06      3U¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/SvnDownloader.phpß\11\0\0\9a\8bOZß\11\0\0¤(\93 ¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/TarDownloader.phpã\0\0\0\9a\8bOZã\0\0\0Í\92X?¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/TransportException.php=\ 2\0\0\9a\8bOZ=\ 2\0\0ZÎÈÞ¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Downloader/VcsCapableDownloaderInterface.phpÔ\0\0\0\9a\8bOZÔ\0\0\0`§ôö¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/VcsDownloader.php"\16\0\0\9a\8bOZ"\16\0\0\9c\1a\9f\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/XzDownloader.php§\ 4\0\0\9a\8bOZ§\ 4\0\0W$;á¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/ZipDownloader.php\98\13\0\0\9a\8bOZ\98\13\0\0\9b@\ 2ü¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/EventDispatcher/Event.php \ 2\0\0\9a\8bOZ \ 2\0\0±\99jï¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/EventDispatcher/EventDispatcher.phpß0\0\0\9a\8bOZß0\0\0}f\18\a\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/EventSubscriberInterface.php©\0\0\0\9a\8bOZ©\0\0\0\ 1\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/ScriptExecutionException.phpv\0\0\0\9a\8bOZv\0\0\0wZ8S¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Exception/NoSslException.phpf\0\0\0\9a\8bOZf\0\0\0ËíM\9d\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Factory.phpU=\0\0\9a\8bOZU=\0\0%êÿí¶\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/BaseIO.php\8c\10\0\0\9a\8bOZ\8c\10\0\0(\82l\91\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/IO/BufferIO.php*\ 4\0\0\9a\8bOZ*\ 4\0\0¢®hT¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/IO/ConsoleIO.phpé\15\0\0\9a\8bOZé\15\0\0k\810å¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/IO/IOInterface.phpì\ 5\0\0\9a\8bOZì\ 5\0\0\0Õ\9d\ e\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/NullIO.phpÀ\ 4\0\0\9a\8bOZÀ\ 4\0\0F`sʶ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/Installer.phpX\9c\0\0\9a\8bOZX\9c\0\0éå*\1c\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/BinaryInstaller.phpÛ\11\0\0\9a\8bOZÛ\11\0\0<x> ¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Installer/BinaryPresenceInterface.phpË\0\0\0\9a\8bOZË\0\0\0À5\9a¨¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/InstallationManager.php-\17\0\0\9a\8bOZ-\17\0\0¾}\8c\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Installer/InstallerEvent.php\ e\ 6\0\0\9a\8bOZ\ e\ 6\0\0lÔzi¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/InstallerEvents.phpÞ\0\0\0\9a\8bOZÞ\0\0\0ì\9f@G¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Installer/InstallerInterface.phpã\ 2\0\0\9a\8bOZã\ 2\0\0^\83\93ʶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/LibraryInstaller.php^\13\0\0\9a\8bOZ^\13\0\0\10\1aÍr¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Installer/MetapackageInstaller.php\9c\ 4\0\0\9a\8bOZ\9c\ 4\0\0Æ\12Å!¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/NoopInstaller.php+\ 5\0\0\9a\8bOZ+\ 5\0\0À·M}¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Installer/PackageEvent.phpe\ 3\0\0\9a\8bOZe\ 3\0\0;° \1a\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PackageEvents.php¸\ 1\0\0\9a\8bOZ¸\ 1\0\0dbØs¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/PearBinaryInstaller.phpâ\f\0\0\9a\8bOZâ\f\0\0;øiU¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PearInstaller.php¢\a\0\0\9a\8bOZ¢\a\0\0È\82¶Ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/PluginInstaller.php\9f\ 6\0\0\9a\8bOZ\9f\ 6\0\0<tú,¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/ProjectInstaller.php\1d\ 6\0\0\9a\8bOZ\1d\ 6\0\0*0@P¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Installer/SuggestedPackagesReporter.php\10\a\0\0\9a\8bOZ\10\a\0\0+±]Ķ\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Json/JsonFile.phpï\13\0\0\9a\8bOZï\13\0\0_(\18\v\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Json/JsonFormatter.php\ 6\ 6\0\0\9a\8bOZ\ 6\ 6\0\0\1eÐqu¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Json/JsonManipulator.php°2\0\0\9a\8bOZ°2\0\0\8eè\ 4ζ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Json/JsonValidationException.php\\ 1\0\0\9a\8bOZ\\ 1\0\0.Xóܶ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Package/AliasPackage.php\ 5\17\0\0\9a\8bOZ\ 5\17\0\0¹\97~\9a\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFilter.php       \ 2\0\0\9a\8bOZ \ 2\0\0yY+¦¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFinder.phpÞ\ 5\0\0\9a\8bOZÞ\ 5\0\0\f²²¹¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Archiver/ArchiveManager.php°\f\0\0\9a\8bOZ°\f\0\0gþÒ)¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/ArchiverInterface.php\a\ 1\0\0\9a\8bOZ\a\ 1\0\0ñ´>\v\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/BaseExcludeFilter.php\96\ 6\0\0\9a\8bOZ\96\ 6\0\0y¶=ƶ\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ComposerExcludeFilter.php\1f\ 1\0\0\9a\8bOZ\1f\ 1\0\0\8bSZ0¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Package/Archiver/GitExcludeFilter.phpq\ 3\0\0\9a\8bOZq\ 3\0\05¾i&¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Archiver/HgExcludeFilter.php\v\ 5\0\0\9a\8bOZ\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\9a\8bOZ>\ 6\0\0 5\89í¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/Archiver/ZipArchiver.php¼\ 4\0\0\9a\8bOZ¼\ 4\0\0\91XÝë¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/BasePackage.php&\r\0\0\9a\8bOZ&\r\0\0\e'\1fݶ\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Package/CompletePackage.phpü\ 6\0\0\9a\8bOZü\ 6\0\0þM˶¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/CompletePackageInterface.phpõ\ 1\0\0\9a\8bOZõ\ 1\0\0¦Ê\81ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Dumper/ArrayDumper.phpë\v\0\0\9a\8bOZë\v\0\0Ó8WE¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Package/Link.php\88\ 5\0\0\9a\8bOZ\88\ 5\0\0å¶Y«¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/EmptyConstraint.php\82\ 1\0\0\9a\8bOZ\82\ 1\0\0\ eé~\8b\ 1\0\0\0\0\0\0?\0\0\0src/Composer/Package/LinkConstraint/LinkConstraintInterface.phpd\ 1\0\0\9a\8bOZd\ 1\0\0¤ôLn¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/MultiConstraint.php\82\ 1\0\0\9a\8bOZ\82\ 1\0\0ób`ý¶\ 1\0\0\0\0\0\0:\0\0\0src/Composer/Package/LinkConstraint/SpecificConstraint.phpi\ 1\0\0\9a\8bOZi\ 1\0\0Þ\94\9a\ 1\0\0\0\0\0\09\0\0\0src/Composer/Package/LinkConstraint/VersionConstraint.phpX\ 1\0\0\9a\8bOZX\ 1\0\0\ 2}`y¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Loader/ArrayLoader.php\1f\1e\0\0\9a\8bOZ\1f\1e\0\0n~\9c\9b\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Loader/InvalidPackageException.phpE\ 2\0\0\9a\8bOZE\ 2\0\0xb\13¾¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Loader/JsonLoader.phpù\ 1\0\0\9a\8bOZù\ 1\0\0!~\88\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Loader/LoaderInterface.php²\0\0\0\9a\8bOZ²\0\0\0¦}úζ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Loader/RootPackageLoader.php$\17\0\0\9a\8bOZ$\17\0\0Ârü°¶\ 1\0\0\0\0\0\05\0\0\0src/Composer/Package/Loader/ValidatingArrayLoader.php\ 69\0\0\9a\8bOZ\ 69\0\0Ñ\ 5J\ f\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Package/Locker.php©!\0\0\9a\8bOZ©!\0\0A\8aõë¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Package/Package.phpÉ\1a\0\0\9a\8bOZÉ\1a\0\0\8f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/PackageInterface.php \a\0\0\9a\8bOZ \a\0\0ûÇ^ƶ\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/RootAliasPackage.php\1f   \0\0\9a\8bOZ\1f \0\0      _\80ø¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/RootPackage.php\11\ 5\0\0\9a\8bOZ\11\ 5\0\0\ 2\8eÎ_¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/RootPackageInterface.php¹\ 3\0\0\9a\8bOZ¹\ 3\0\0"maV¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Version/VersionGuesser.php[\1e\0\0\9a\8bOZ[\1e\0\0á-\ 3ó¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Version/VersionParser.phpo\ 4\0\0\9a\8bOZo\ 4\0\0m\1e\80\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Version/VersionSelector.phpK\f\0\0\9a\8bOZK\f\0\0²<\ fȶ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Plugin/Capability/Capability.phpW\0\0\0\9a\8bOZW\0\0\0æ_¨1¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Plugin/Capability/CommandProvider.php\97\0\0\0\9a\8bOZ\97\0\0\0ûOâ>¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Plugin/Capable.php\7f\0\0\0\9a\8bOZ\7f\0\0\0Æq\15\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/CommandEvent.phpâ\ 2\0\0\9a\8bOZâ\ 2\0\0³ÆÇW¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/PluginEvents.phpÂ\0\0\0\9a\8bOZÂ\0\0\0^Íþ\ 6\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Plugin/PluginInterface.phpô\0\0\0\9a\8bOZô\0\0\0)'*ض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Plugin/PluginManager.php\1f$\0\0\9a\8bOZ\1f$\0\0ë\8e"»¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Plugin/PreFileDownloadEvent.php`\ 2\0\0\9a\8bOZ`\ 2\0\0\09-ζ\ 1\0\0\0\0\0\04\0\0\0src/Composer/Question/StrictConfirmationQuestion.php\1e\ 5\0\0\9a\8bOZ\1e\ 5\0\0'.³è¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Repository/ArrayRepository.php\13\ e\0\0\9a\8bOZ\13\ e\0\0éÌt\0\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ArtifactRepository.php»\f\0\0\9a\8bOZ»\f\0\0\88Ý÷<¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/BaseRepository.php]\r\0\0\9a\8bOZ]\r\0\0ä&3\87\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ComposerRepository.php[T\0\0\9a\8bOZ[T\0\0¤uV1¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/CompositeRepository.php;\b\0\0\9a\8bOZ;\b\0\0¤¯S\1f\ 1\0\0\0\0\0\0;\0\0\0src/Composer/Repository/ConfigurableRepositoryInterface.php\85\0\0\0\9a\8bOZ\85\0\0\0±\9f_\1c\ 1\0\0\0\0\0\00\0\0\0src/Composer/Repository/FilesystemRepository.php$\ 5\0\0\9a\8bOZ$\ 5\0\0¾Ãá\85\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/InstalledArrayRepository.php£\0\0\0\9a\8bOZ£\0\0\0/ö~>¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Repository/InstalledFilesystemRepository.php£\0\0\0\9a\8bOZ£\0\0\0V
37 \95\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/InstalledRepositoryInterface.php\87\0\0\0\9a\8bOZ\87\0\0\0\18£9p¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/Repository/InvalidRepositoryException.phpn\0\0\0\9a\8bOZn\0\0\0à\93ë\98\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/PackageRepository.phpj\ 3\0\0\9a\8bOZj\ 3\0\0¥ôò̶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PathRepository.phpw
38 \0\0\9a\8bOZw
39 \0\0\0~õ³¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Pear/BaseChannelReader.phpI\ 5\0\0\9a\8bOZI\ 5\0\0c\b6³¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ChannelInfo.phpÄ\ 1\0\0\9a\8bOZÄ\ 1\0\0:T*ɶ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Pear/ChannelReader.phpí\ 6\0\0\9a\8bOZí\ 6\0\0?ÈYT¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest10Reader.php® \0\0\9a\8bOZ® \0\0\99ÖÛú¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest11Reader.php& \0\0\9a\8bOZ& \0\0òUb\b\ 1\0\0\0\0\0\05\0\0\0src/Composer/Repository/Pear/DependencyConstraint.phpq\ 2\0\0\9a\8bOZq\ 2\0\09\ e\17\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Pear/DependencyInfo.phpq\ 1\0\0\9a\8bOZq\ 1\0\0fºTò¶\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/Pear/PackageDependencyParser.php\85\16\0\0\9a\8bOZ\85\16\0\0÷$Li¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/PackageInfo.php°\ 3\0\0\9a\8bOZ°\ 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\9a\8bOZ\92\ 1\0\0o\93\8aö\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PearRepository.phpª\16\0\0\9a\8bOZª\16\0\0)\9f\83\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/PlatformRepository.php\ 1\e\0\0\9a\8bOZ\ 1\e\0\0\ 3_Mì¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryFactory.php\95\11\0\0\9a\8bOZ\95\11\0\0\80\83§\1d\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/RepositoryInterface.phpÛ\ 1\0\0\9a\8bOZÛ\ 1\0\0\92\11âÁ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryManager.php,
40 \0\0\9a\8bOZ,
41 \0\0¾\85\\95\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/RepositorySecurityException.phpo\0\0\0\9a\8bOZo\0\0\0pÕ«ª¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Vcs/BitbucketDriver.phpô\1e\0\0\9a\8bOZô\1e\0\0\ 4x¤ü¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/FossilDriver.php\9d\12\0\0\9a\8bOZ\9d\12\0\0\ eÀ]µ¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/GitBitbucketDriver.phpê\ 5\0\0\9a\8bOZê\ 5\0\0Ã\8e»\14\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/GitDriver.php¼\11\0\0\9a\8bOZ¼\11\0\0\8a©Ðê¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitHubDriver.php\84+\0\0\9a\8bOZ\84+\0\0¡\93\19\9b\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitLabDriver.phpÍ#\0\0\9a\8bOZÍ#\0\0ßNìʶ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/Vcs/HgBitbucketDriver.phpä\ 5\0\0\9a\8bOZä\ 5\0\0i\9büà¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Repository/Vcs/HgDriver.phpe\12\0\0\9a\8bOZe\12\0\0O!O\13\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Vcs/PerforceDriver.php'     \0\0\9a\8bOZ' \0\0ÙóH\ 5\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/SvnDriver.php\15\e\0\0\9a\8bOZ\15\e\0\0\1dÕzï¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/VcsDriver.phpæ
42 \0\0\9a\8bOZæ
43 \0\0eׯ-¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/VcsDriverInterface.php÷\ 2\0\0\9a\8bOZ÷\ 2\0\0ÇX[\89\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/VcsRepository.php´\1e\0\0\9a\8bOZ´\1e\0\0\ 1ªÖG¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Repository/WritableArrayRepository.php\ f\ 3\0\0\9a\8bOZ\ f\ 3\0\0¾G\17\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/WritableRepositoryInterface.php\89\ 1\0\0\9a\8bOZ\89\ 1\0\0\91/sï¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/CommandEvent.phpW\0\0\0\9a\8bOZW\0\0\0£VZt¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Script/Event.phpµ\ 2\0\0\9a\8bOZµ\ 2\0\0lt¦M¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/PackageEvent.php\9c\0\0\0\9a\8bOZ\9c\0\0\0§ÿÉ\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/ScriptEvents.phpP\ 4\0\0\9a\8bOZP\ 4\0\0\87\8f\ 4¶¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/SelfUpdate/Keys.php\9d\ 1\0\0\9a\8bOZ\9d\ 1\0\0\vîÊN¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/SelfUpdate/Versions.phpì\ 5\0\0\9a\8bOZì\ 5\0\0͵\91\83\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/AuthHelper.phpË\ 3\0\0\9a\8bOZË\ 3\0\0>zx\96\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/Bitbucket.php%\15\0\0\9a\8bOZ%\15\0\0n=gÓ¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/ComposerMirror.php±\ 4\0\0\9a\8bOZ±\ 4\0\0­½øض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ConfigValidator.php¥\ e\0\0\9a\8bOZ¥\ e\0\0\9eê¶\ 1\0\0\0\0\0\0"\0\0\0src/Composer/Util/ErrorHandler.php\87\ 4\0\0\9a\8bOZ\87\ 4\0\0He\1c\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/Filesystem.php\1c/\0\0\9a\8bOZ\1c/\0\0ɧÿ¿¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Git.php!&\0\0\9a\8bOZ!&\0\0lsý׶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitHub.phpÏ
44 \0\0\9a\8bOZÏ
45 \0\0ÁØ\å¶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitLab.php\99\f\0\0\9a\8bOZ\99\f\0\0\17BLF¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/IniHelper.php]\ 3\0\0\9a\8bOZ]\ 3\0\0®äéä¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/NoProxyPattern.php¾\ 6\0\0\9a\8bOZ¾\ 6\0\0Z+°m¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Perforce.php\821\0\0\9a\8bOZ\821\0\0,\9cbx¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Platform.phpü\ 4\0\0\9a\8bOZü\ 4\0\0s­fç¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ProcessExecutor.phpÚ\v\0\0\9a\8bOZÚ\v\0\0£ÒÙ\ 5\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Util/RemoteFilesystem.phpýb\0\0\9a\8bOZýb\0\0Mùjж\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Silencer.phpé\ 2\0\0\9a\8bOZé\ 2\0\0\93Vjf¶\ 1\0\0\0\0\0\0!\0\0\0src/Composer/Util/SpdxLicense.php\ 3\ 1\0\0\9a\8bOZ\ 3\ 1\0\0¾7
46 ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Util/StreamContextFactory.php\18\10\0\0\9a\8bOZ\18\10\0\0ËH*v¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Svn.php¾\11\0\0\9a\8bOZ¾\11\0\0Ík\93ܶ\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/TlsHelper.phpp
47 \0\0\9a\8bOZp
48 \0\0¤eÞæ¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Url.php¾\a\0\0\9a\8bOZ¾\a\0\0Ôء϶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/XdebugHandler.php\93\ f\0\0\9a\8bOZ\93\ f\0\0ÕWÖ>¶\ 1\0\0\0\0\0\0\11\0\0\0src/bootstrap.php¹\ 1\0\0\9a\8bOZ¹\ 1\0\0\15I}\9c\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Autoload/ClassLoader.phpl4\0\0\9a\8bOZl4\0\0\92ø[÷¶\ 1\0\0\0\0\0\0#\0\0\0res/composer-repository-schema.jsonð\ f\0\0\9a\8bOZð\ f\0\0\81GÐà¶\ 1\0\0\0\0\0\0\18\0\0\0res/composer-schema.jsony\95\0\0\9a\8bOZy\95\0\0³Ì¶`¶\ 1\0\0\0\0\0\06\0\0\0vendor/composer/spdx-licenses/res/spdx-exceptions.json}\a\0\0\9a\8bOZ}\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\9a\8bOZà\8c\0\0£\7f\1a\ 1\0\0\0\0\0\0*\0\0\0vendor/seld/cli-prompt/res/hiddeninput.exe\0$\0\0\9a\8bOZ\0$\0\0\95\8d¥v¶\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Application.php#W\0\0\9a\8bOZ#W\0\0\eèðz¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Command/Command.phpò"\0\0\9a\8bOZò"\0\0ÊRÑç¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/HelpCommand.phpØ\a\0\0\9a\8bOZØ\a\0\0$Y\1c«¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/ListCommand.phpZ\b\0\0\9a\8bOZZ\b\0\0É£ \16\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/ConsoleEvents.phpé\0\0\0\9a\8bOZé\0\0\0RÛÔe¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/console/Descriptor/ApplicationDescription.phpÐ\b\0\0\9a\8bOZÐ\b\0\0\99\8e5°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Descriptor/Descriptor.php\8e\a\0\0\9a\8bOZ\8e\a\0\0éð8\9f\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Descriptor/DescriptorInterface.phpü\0\0\0\9a\8bOZü\0\0\0±Q\aµ¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/JsonDescriptor.phpá\r\0\0\9a\8bOZá\r\0\0\87    àƶ\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Descriptor/MarkdownDescriptor.php¹\ e\0\0\9a\8bOZ¹\ e\0\0k\9f.a¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/TextDescriptor.php²\1e\0\0\9a\8bOZ²\1e\0\0\8f­ùâ¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Descriptor/XmlDescriptor.php\ 2\1c\0\0\9a\8bOZ\ 2\1c\0\0
49 ]\85ζ\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Event/ConsoleCommandEvent.php°\ 1\0\0\9a\8bOZ°\ 1\0\0\a!\0ȶ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Event/ConsoleEvent.phpÅ\ 2\0\0\9a\8bOZÅ\ 2\0\0ÒxÛ\¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleExceptionEvent.php\12\ 3\0\0\9a\8bOZ\12\ 3\0\0á\162é¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleTerminateEvent.phpz\ 2\0\0\9a\8bOZz\ 2\0\0³,îL¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/CommandNotFoundException.phpÔ\ 1\0\0\9a\8bOZÔ\ 1\0\0È÷ L¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Exception/ExceptionInterface.phpf\0\0\0\9a\8bOZf\0\0\0¡ABª¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/InvalidArgumentException.php¦\0\0\0\9a\8bOZ¦\0\0\0Ö̽Z¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/console/Exception/InvalidOptionException.php¦\0\0\0\9a\8bOZ¦\0\0\0\13Ë×H¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Exception/LogicException.php\92\0\0\0\9a\8bOZ\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\9a\8bOZ\96\0\0\0Ùí,6¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Formatter/OutputFormatter.php2\ e\0\0\9a\8bOZ2\ e\0\0RÌYh¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Formatter/OutputFormatterInterface.php\8c\ 1\0\0\9a\8bOZ\8c\ 1\0\0òññÀ¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyle.phpJ\10\0\0\9a\8bOZJ\10\0\0ÏDSȶ\ 1\0\0\0\0\0\0B\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php\84\ 1\0\0\9a\8bOZ\84\ 1\0\0÷½\10\ 1\0\0\0\0\0\0>\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleStack.php>\ 5\0\0\9a\8bOZ>\ 5\0\0[\86¿\96\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Helper/DebugFormatterHelper.phpx\b\0\0\9a\8bOZx\b\0\0N©Ø¼¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/DescriptorHelper.phpw\ 5\0\0\9a\8bOZw\ 5\0\0ÅHð.¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Helper/DialogHelper.phpú\1e\0\0\9a\8bOZú\1e\0\0¼\fO\81\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/FormatterHelper.phpc\ 4\0\0\9a\8bOZc\ 4\0\0\93ý«N¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Helper/Helper.php¨\a\0\0\9a\8bOZ¨\a\0\0\9coû3¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/HelperInterface.phpå\0\0\0\9a\8bOZå\0\0\0\1f\8a \18\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/HelperSet.phpÉ\a\0\0\9a\8bOZÉ\a\0\0\9cf\15\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/InputAwareHelper.phpc\ 1\0\0\9a\8bOZc\ 1\0\0ñø\90\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Helper/ProcessHelper.phpÑ     \0\0\9a\8bOZÑ \0\0@±ã\81\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/ProgressBar.phpk%\0\0\9a\8bOZk%\0\0ì\19îa¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/ProgressHelper.php\\e\0\0\9a\8bOZ\\e\0\0\91ÃYÓ¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Helper/ProgressIndicator.phpK\14\0\0\9a\8bOZK\14\0\0í\1cÍ°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/QuestionHelper.php  \1c\0\0\9a\8bOZ \1c\0\0L\17ú4¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Helper/SymfonyQuestionHelper.phpl
50 \0\0\9a\8bOZl
51 \0\0\1e÷ÞL¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/console/Helper/Table.php¨*\0\0\9a\8bOZ¨*\0\0e{))¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/TableCell.php\80\ 3\0\0\9a\8bOZ\80\ 3\0\0Ìî*Û¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/TableHelper.php\ e\f\0\0\9a\8bOZ\ e\f\0\0QRº\1e\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/TableSeparator.phpÊ\0\0\0\9a\8bOZÊ\0\0\0az\1f\1c\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Helper/TableStyle.php\1f
52 \0\0\9a\8bOZ\1f
53 \0\0PÞµ¦¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Input/ArgvInput.php7\16\0\0\9a\8bOZ7\16\0\0ØQ|ʶ\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Input/ArrayInput.php\14\v\0\0\9a\8bOZ\14\v\0\0ʹóþ¶\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Input/Input.php¢\v\0\0\9a\8bOZ¢\v\0\0\94\87B"¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Input/InputArgument.php\10\ 6\0\0\9a\8bOZ\10\ 6\0\0&<¦¯¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Input/InputAwareInterface.php\9a\0\0\0\9a\8bOZ\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\9a\8bOZ\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\9a\8bOZ\9d\ 3\0\0®#£\10\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/InputOption.php\18\f\0\0\9a\8bOZ\18\f\0\0ùýN4¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/StringInput.php\96\ 6\0\0\9a\8bOZ\96\ 6\0\0cì\(¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/console/LICENSE)\ 4\0\0\9a\8bOZ)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Logger/ConsoleLogger.php.    \0\0\9a\8bOZ. \0\0¤\8c\85ζ\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Output/BufferedOutput.php_\ 1\0\0\9a\8bOZ_\ 1\0\0\8b >P¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Output/ConsoleOutput.php°\a\0\0\9a\8bOZ°\a\0\0]k~o¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Output/ConsoleOutputInterface.phpà\0\0\0\9a\8bOZà\0\0\0\87\86Æʶ\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Output/NullOutput.phpÏ\ 3\0\0\9a\8bOZÏ\ 3\0\0®\98\8b\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Output/Output.php\98  \0\0\9a\8bOZ\98 \0\0\1fpf\¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Output/OutputInterface.php\17\ 3\0\0\9a\8bOZ\17\ 3\0\0\0ì\ 6\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Output/StreamOutput.phpÂ\ 5\0\0\9a\8bOZÂ\ 5\0\0\ 4¥<I¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Question/ChoiceQuestion.phpw
54 \0\0\9a\8bOZw
55 \0\02\15t\ 6\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Question/ConfirmationQuestion.phpç\ 2\0\0\9a\8bOZç\ 2\0\0\r­òf¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Question/Question.phpË     \0\0\9a\8bOZË \0\0ÒqµR¶\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/console/Shell.phpå\ f\0\0\9a\8bOZå\ f\0\0\95\9axS¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Style/OutputStyle.php\\ 5\0\0\9a\8bOZ\\ 5\0\0wפ\ 4\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Style/StyleInterface.phpÏ\ 3\0\0\9a\8bOZÏ\ 3\0\0&nÅѶ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Style/SymfonyStyle.php¶\1f\0\0\9a\8bOZ¶\1f\0\0ª×\10ì¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Tester/ApplicationTester.phpÏ\ 5\0\0\9a\8bOZÏ\ 5\0\0s\9e9i¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Tester/CommandTester.phpª\ 6\0\0\9a\8bOZª\ 6\0\0µ.âr¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/debug/BufferingLogger.phpt\ 1\0\0\9a\8bOZt\ 1\0\0=\0hܶ\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/debug/Debug.phpé\ 2\0\0\9a\8bOZé\ 2\0\0Àxa?¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/DebugClassLoader.php¡\1d\0\0\9a\8bOZ¡\1d\0\0ó\80v\87\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/debug/ErrorHandler.php\80C\0\0\9a\8bOZ\80C\0\0¥æõ¾¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/debug/Exception/ClassNotFoundException.php\84\ 1\0\0\9a\8bOZ\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\9a\8bOZ\98\ 1\0\0-
56 d2¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/debug/Exception/DummyException.php\ 2\ 1\0\0\9a\8bOZ\ 2\ 1\0\0-"ûd¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalErrorException.phpï\ 6\0\0\9a\8bOZï\ 6\0\0æ\ffz¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalThrowableError.phpD\ 2\0\0\9a\8bOZD\ 2\0\0¡\fÂí¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/debug/Exception/FlattenException.php²\16\0\0\9a\8bOZ²\16\0\0HòÑ\ f\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/debug/Exception/OutOfMemoryException.php~\0\0\0\9a\8bOZ~\0\0\0ë¨oâ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/debug/Exception/UndefinedFunctionException.php\88\ 1\0\0\9a\8bOZ\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\9a\8bOZ\86\ 1\0\0¨LÚ:¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/ExceptionHandler.php\193\0\0\9a\8bOZ\193\0\0\8a\ 1\0\0\0\0\0\0I\0\0\0vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php7\12\0\0\9a\8bOZ7\12\0\0Ñj/=¶\ 1\0\0\0\0\0\0E\0\0\0vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php\ 3\ 1\0\0\9a\8bOZ\ 3\ 1\0\0ĹBV¶\ 1\0\0\0\0\0\0M\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.phpu\b\0\0\9a\8bOZu\b\0\0éj\ 3\19\ 1\0\0\0\0\0\0K\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.phpN\ 5\0\0\9a\8bOZN\ 5\0\0Ço-ç¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/symfony/debug/LICENSE)\ 4\0\0\9a\8bOZ)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/filesystem/Exception/ExceptionInterface.phpi\0\0\0\9a\8bOZi\0\0\0$ ÿ\9b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/filesystem/Exception/FileNotFoundException.php¼\ 1\0\0\9a\8bOZ¼\ 1\0\0pí\¶¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/filesystem/Exception/IOException.php\87\ 1\0\0\9a\8bOZ\87\ 1\0\0\80ü#Ѷ\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/filesystem/Exception/IOExceptionInterface.php¦\0\0\0\9a\8bOZ¦\0\0\0jÙwM¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/filesystem/Filesystem.phpö2\0\0\9a\8bOZö2\0\0ëP\81ò¶\ 1\0\0\0\0\0\0!\0\0\0vendor/symfony/filesystem/LICENSE)\ 4\0\0\9a\8bOZ)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/filesystem/LockHandler.php¢\ 5\0\0\9a\8bOZ¢\ 5\0\0D\91;i¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Adapter/AbstractAdapter.php\\v\0\0\9a\8bOZ\\v\0\0Æ\93É\80\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Adapter/AbstractFindAdapter.php\8b\19\0\0\9a\8bOZ\8b\19\0\0]vk1¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/finder/Adapter/AdapterInterface.php\9b\ 3\0\0\9a\8bOZ\9b\ 3\0\0M\aþ\e\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/BsdFindAdapter.php2\a\0\0\9a\8bOZ2\a\0\0Q/ÇC¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/GnuFindAdapter.php\15\a\0\0\9a\8bOZ\15\a\0\0(\fí?¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/finder/Adapter/PhpAdapter.phpô\a\0\0\9a\8bOZô\a\0\0\16\1d:?¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Comparator/Comparator.php\8c\ 3\0\0\9a\8bOZ\8c\ 3\0\0\16wþT¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Comparator/DateComparator.php#\ 3\0\0\9a\8bOZ#\ 3\0\0\16°\1fζ\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Comparator/NumberComparator.php|\ 3\0\0\9a\8bOZ|\ 3\0\0ITÇͶ\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Exception/AccessDeniedException.php\84\0\0\0\9a\8bOZ\84\0\0\0½¾s\9c\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Exception/AdapterFailureException.php¬\ 2\0\0\9a\8bOZ¬\ 2\0\0\91\9e\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/finder/Exception/ExceptionInterface.php\84\0\0\0\9a\8bOZ\84\0\0\0\1cGz-¶\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Exception/OperationNotPermitedException.php)\ 1\0\0\9a\8bOZ)\ 1\0\0ìcj=¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/finder/Exception/ShellCommandFailureException.phpº\ 2\0\0\9a\8bOZº\ 2\0\0\18Êø\1c\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Expression/Expression.php\a\ 6\0\0\9a\8bOZ\a\ 6\0\0µoÔ\ 6\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/finder/Expression/Glob.phpf\ 4\0\0\9a\8bOZf\ 4\0\0lïÜP¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/finder/Expression/Regex.php\ 4\ f\0\0\9a\8bOZ\ 4\ f\0\0Qr\93¡¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Expression/ValueInterface.phpÍ\ 1\0\0\9a\8bOZÍ\ 1\0\0²~øb¶\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/finder/Finder.php¹-\0\0\9a\8bOZ¹-\0\0Q\1aÿ2¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/finder/Glob.phpK\ 5\0\0\9a\8bOZK\ 5\0\0já±n¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/finder/Iterator/CustomFilterIterator.php[\ 2\0\0\9a\8bOZ[\ 2\0\0­\ 4åW¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpx\ 2\0\0\9a\8bOZx\ 2\0\0\ fô\ 3\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpî\ 1\0\0\9a\8bOZî\ 1\0\0üÍ\9d\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.phpí\ 5\0\0\9a\8bOZí\ 5\0\0n\ 5õH¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/finder/Iterator/FilePathsIterator.php \ 6\0\0\9a\8bOZ \ 6\0\0fQCe¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FileTypeFilterIterator.phpZ\ 2\0\0\9a\8bOZZ\ 2\0\0(\1a&ø¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/finder/Iterator/FilecontentFilterIterator.php5\ 2\0\0\9a\8bOZ5\ 2\0\0\9aí\1f\14\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FilenameFilterIterator.phpr\ 1\0\0\9a\8bOZr\ 1\0\0t\b\1a\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Iterator/FilterIterator.phpÃ\ 2\0\0\9a\8bOZÃ\ 2\0\0\9a+µÞ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php-\ 5\0\0\9a\8bOZ-\ 5\0\0ºÎÒ_¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Iterator/PathFilterIterator.phpÏ\ 1\0\0\9a\8bOZÏ\ 1\0\0º\1cªÇ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php\13   \0\0\9a\8bOZ\13 \0\0 \12ÿ¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpe\ 2\0\0\9a\8bOZe\ 2\0\0\9f\92áé¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Iterator/SortableIterator.php*\ 6\0\0\9a\8bOZ*\ 6\0\0\80õ´^¶\ 1\0\0\0\0\0\0\1d\0\0\0vendor/symfony/finder/LICENSE)\ 4\0\0\9a\8bOZ)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/finder/Shell/Command.php?\v\0\0\9a\8bOZ?\v\0\0\9aPw\89\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/Shell/Shell.phpp\ 4\0\0\9a\8bOZp\ 4\0\0\18Ó}g¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/SplFileInfo.phpý\ 2\0\0\9a\8bOZý\ 2\0\0\13`ØÓ¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/polyfill-mbstring/LICENSE)\ 4\0\0\9a\8bOZ)\ 4\0\0î*L\14\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/polyfill-mbstring/Mbstring.phpÄ6\0\0\9a\8bOZÄ6\0\0U.\17ݶ\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php2A\0\0\9a\8bOZ2A\0\0½\11=¨¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php¡A\0\0\9a\8bOZ¡A\0\0\ eÚ    Í¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/polyfill-mbstring/bootstrap.php±\ f\0\0\9a\8bOZ±\ f\0\0|\8a©Ò¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/process/Exception/ExceptionInterface.phpf\0\0\0\9a\8bOZf\0\0\0]ö>T¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/InvalidArgumentException.php¨\0\0\0\9a\8bOZ¨\0\0\0ÐÀ+_¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/process/Exception/LogicException.php\94\0\0\0\9a\8bOZ\94\0\0\0 ³ãñ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/process/Exception/ProcessFailedException.phpx\ 3\0\0\9a\8bOZx\ 3\0\0¨Ìzy¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/ProcessTimedOutException.php\1f\ 4\0\0\9a\8bOZ\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\9a\8bOZ\98\0\0\0¢\eØ:¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/process/ExecutableFinder.php\99\ 4\0\0\9a\8bOZ\99\ 4\0\0|O¿é¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/process/LICENSE)\ 4\0\0\9a\8bOZ)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/PhpExecutableFinder.phpg\ 4\0\0\9a\8bOZg\ 4\0\0\8dçµ\ 6\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/process/PhpProcess.phpú\ 3\0\0\9a\8bOZú\ 3\0\0¯\93Õ\81\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/Pipes/AbstractPipes.php]\a\0\0\9a\8bOZ]\a\0\0g\18\16\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/process/Pipes/PipesInterface.phpD\ 1\0\0\9a\8bOZD\ 1\0\0vØ\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/process/Pipes/UnixPipes.phpâ\a\0\0\9a\8bOZâ\a\0\0\7fß\10Ŷ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/process/Pipes/WindowsPipes.php\89\v\0\0\9a\8bOZ\89\v\0\0\bÀ"¢¶\ 1\0\0\0\0\0\0"\0\0\0vendor/symfony/process/Process.php£R\0\0\9a\8bOZ£R\0\0\8b\84&E¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/process/ProcessBuilder.phpß
57 \0\0\9a\8bOZß
58 \0\0^\83\17\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/process/ProcessUtils.phpK\ 6\0\0\9a\8bOZK\ 6\0\0µ½~ò¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/seld/jsonlint/LICENSE"\ 4\0\0\9a\8bOZ"\ 4\0\0a\83sy¶\ 1\0\0\0\0\0\0@\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php*\ 1\0\0\9a\8bOZ*\ 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\9a\8bOZ/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\9a\8bOZ\ 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\9a\8bOZ\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\9a\8bOZ>\0\0\0ÿq\9f\9f\ 1\0\0\0\0\0\0\1e\0\0\0vendor/seld/cli-prompt/LICENSE"\ 4\0\0\9a\8bOZ"\ 4\0\0\88ñ?e¶\ 1\0\0\0\0\0\0&\0\0\0vendor/seld/cli-prompt/res/example.php'\ 1\0\0\9a\8bOZ'\ 1\0\0I\1c\ 5£¶\ 1\0\0\0\0\0\0(\0\0\0vendor/seld/cli-prompt/src/CliPrompt.phpC\ 6\0\0\9a\8bOZC\ 6\0\0Ð}\8d\ 1\0\0\0\0\0\0(\0\0\0vendor/justinrainbow/json-schema/LICENSE \ 4\0\0\9a\8bOZ \ 4\0\0ºç\ 6©¶\ 1\0\0\0\0\0\0.\0\0\0vendor/justinrainbow/json-schema/demo/demo.phpñ\ 1\0\0\9a\8bOZñ\ 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\9a\8bOZ¡ \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\9a\8bOZ)\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\9a\8bOZ\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\9a\8bOZ¼\ 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\9a\8bOZ]\ 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\9a\8bOZ;\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\9a\8bOZ\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
59 \0\0\9a\8bOZ\9a
60 \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\9a\8bOZÃ\11\0\0©Å¼x¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.phpN \0\0\9a\8bOZN \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\9a\8bOZ\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\9a\8bOZa\ 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\9a\8bOZp\ 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\9a\8bOZ\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\9a\8bOZ&\ 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\9a\8bOZr!\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\9a\8bOZè\ 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\9a\8bOZI\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\9a\8bOZ\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\9a\8bOZl\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\9a\8bOZl\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\9a\8bOZu\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\9a\8bOZw\0\0\0N-ò[¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ\ 2\0\0\9a\8bOZÞ\ 2\0\0\r
61\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpo\0\0\0\9a\8bOZo\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\9a\8bOZ\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\9a\8bOZ\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\9a\8bOZj\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\9a\8bOZf\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\9a\8bOZþ\ 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\9a\8bOZ \ 2\0\0f4÷³¶\ 1\0\0\0\0\0\0A\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php\9c\r\0\0\9a\8bOZ\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\9a\8bOZ\ 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\9a\8bOZá\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\9a\8bOZ¥\ 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\9a\8bOZ%\ 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\9a\8bOZ,\ 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\9a\8bOZ®\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\9a\8bOZ\ 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\9a\8bOZ&\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\9a\8bOZ\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\9a\8bOZ\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\9a\8bOZÇ\ 5\0\0ù\85oÞ¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/spdx-licenses/LICENSE\1c\ 4\0\0\9a\8bOZ\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\02\0\0\0vendor/composer/spdx-licenses/src/SpdxLicenses.phpm\12\0\0\9a\8bOZm\12\0\052Áö¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/composer/semver/LICENSE\1c\ 4\0\0\9a\8bOZ\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\0)\0\0\0vendor/composer/semver/src/Comparator.php\ 2\ 4\0\0\9a\8bOZ\ 2\ 4\0\0wl\83ï¶\ 1\0\0\0\0\0\0<\0\0\0vendor/composer/semver/src/Constraint/AbstractConstraint.php×\ 2\0\0\9a\8bOZ×\ 2\0\0õî>\8e\ 1\0\0\0\0\0\04\0\0\0vendor/composer/semver/src/Constraint/Constraint.phpª\f\0\0\9a\8bOZª\f\0\0ÇO7²¶\ 1\0\0\0\0\0\0=\0\0\0vendor/composer/semver/src/Constraint/ConstraintInterface.phpß\0\0\0\9a\8bOZß\0\0\00C,\87\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/EmptyConstraint.phpé\ 1\0\0\9a\8bOZé\ 1\0\0!-Ø\99\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/MultiConstraint.php1\ 5\0\0\9a\8bOZ1\ 5\0\0í xU¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/semver/src/Semver.phpv\ 6\0\0\9a\8bOZv\ 6\0\0\8b×È\9b\ 1\0\0\0\0\0\0,\0\0\0vendor/composer/semver/src/VersionParser.php¿*\0\0\9a\8bOZ¿*\0\0\13)mƶ\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/ca-bundle/LICENSE\1c\ 4\0\0\9a\8bOZ\1c\ 4\0\0*!^`¶\ 1\0\0\0\0\0\0*\0\0\0vendor/composer/ca-bundle/src/CaBundle.php\15\1d\0\0\9a\8bOZ\15\1d\0\0Ê\v~Ķ\ 1\0\0\0\0\0\0\16\0\0\0vendor/psr/log/LICENSE=\ 4\0\0\9a\8bOZ=\ 4\0\0\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/AbstractLogger.php;\ 4\0\0\9a\8bOZ;\ 4\0\0ñ>3[¶\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/InvalidArgumentException.php`\0\0\0\9a\8bOZ`\0\0\0 \88X1¶\ 1\0\0\0\0\0\0#\0\0\0vendor/psr/log/Psr/Log/LogLevel.phpû\0\0\0\9a\8bOZû\0\0\0jðñ8¶\ 1\0\0\0\0\0\0/\0\0\0vendor/psr/log/Psr/Log/LoggerAwareInterface.php|\0\0\0\9a\8bOZ|\0\0\0$\13£\88\ 1\0\0\0\0\0\0+\0\0\0vendor/psr/log/Psr/Log/LoggerAwareTrait.php§\0\0\0\9a\8bOZ§\0\0\0T½úB¶\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/LoggerInterface.phpÆ\ 2\0\0\9a\8bOZÆ\ 2\0\0»\12sg¶\ 1\0\0\0\0\0\0&\0\0\0vendor/psr/log/Psr/Log/LoggerTrait.phpi\ 4\0\0\9a\8bOZi\ 4\0\035§Þ¶\ 1\0\0\0\0\0\0%\0\0\0vendor/psr/log/Psr/Log/NullLogger.php\9e\0\0\0\9a\8bOZ\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\9a\8bOZü\f\0\0iq0ض\ 1\0\0\0\0\0\0\13\0\0\0vendor/autoload.php\82\0\0\0\9a\8bOZ\82\0\0\0B\v!\b\ 1\0\0\0\0\0\0'\0\0\0vendor/composer/autoload_namespaces.phpd\0\0\0\9a\8bOZd\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_psr4.php\98\ 4\0\0\9a\8bOZ\98\ 4\0\0\9e\1c{¢¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/autoload_classmap.phpd\0\0\0\9a\8bOZd\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0"\0\0\0vendor/composer/autoload_files.phpÃ\0\0\0\9a\8bOZÃ\0\0\0ÒÂür¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_real.phpI\a\0\0\9a\8bOZI\a\0\0upå<¶\ 1\0\0\0\0\0\0#\0\0\0vendor/composer/autoload_static.php¬  \0\0\9a\8bOZ¬ \0\0­qÞ©¶\ 1\0\0\0\0\0\0\1f\0\0\0vendor/composer/ClassLoader.php\81\18\0\0\9a\8bOZ\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\9a\8bOZ\1d\9a\ 3\0\1aÛ¾§¶\ 1\0\0\0\0\0\0\f\0\0\0bin/composer \ 6\0\0\9a\8bOZ \ 6\0\0Ð\7f\9e\ 1\0\0\0\0\0\0\a\0\0\0LICENSE.\ 4\0\0\9a\8bOZ.\ 4\0\0 Õ\b\ 3\ 1\0\0\0\0\0\0<?php
62
63
64
65
66
67
68
69
70
71
72
73 namespace Composer\Autoload;
74
75 use Composer\Config;
76 use Composer\EventDispatcher\EventDispatcher;
77 use Composer\Installer\InstallationManager;
78 use Composer\IO\IOInterface;
79 use Composer\Package\AliasPackage;
80 use Composer\Package\PackageInterface;
81 use Composer\Repository\InstalledRepositoryInterface;
82 use Composer\Util\Filesystem;
83 use Composer\Script\ScriptEvents;
84
85
86
87
88
89 class AutoloadGenerator
90 {
91
92
93
94 private $eventDispatcher;
95
96
97
98
99 private $io;
100
101
102
103
104 private $devMode = false;
105
106
107
108
109 private $classMapAuthoritative = false;
110
111
112
113
114 private $apcu = false;
115
116
117
118
119 private $runScripts = false;
120
121 public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
122 {
123 $this->eventDispatcher = $eventDispatcher;
124 $this->io = $io;
125 }
126
127 public function setDevMode($devMode = true)
128 {
129 $this->devMode = (bool) $devMode;
130 }
131
132
133
134
135
136
137
138 public function setClassMapAuthoritative($classMapAuthoritative)
139 {
140 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
141 }
142
143
144
145
146
147
148 public function setApcu($apcu)
149 {
150 $this->apcu = (bool) $apcu;
151 }
152
153
154
155
156
157
158 public function setRunScripts($runScripts = true)
159 {
160 $this->runScripts = (bool) $runScripts;
161 }
162
163 public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
164 {
165 if ($this->classMapAuthoritative) {
166
167  $scanPsr0Packages = true;
168 }
169 if ($this->runScripts) {
170 $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
171 'optimize' => (bool) $scanPsr0Packages,
172 ));
173 }
174
175 $filesystem = new Filesystem();
176 $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
177
178  
179  
180  $basePath = $filesystem->normalizePath(realpath(realpath(getcwd())));
181 $vendorPath = $filesystem->normalizePath(realpath(realpath($config->get('vendor-dir'))));
182 $useGlobalIncludePath = (bool) $config->get('use-include-path');
183 $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
184 $targetDir = $vendorPath.'/'.$targetDir;
185 $filesystem->ensureDirectoryExists($targetDir);
186
187 $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
188 $vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
189 $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
190
191 $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
192 $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
193
194 $namespacesFile = <<<EOF
195 <?php
196
197 // autoload_namespaces.php @generated by Composer
198
199 \$vendorDir = $vendorPathCode52;
200 \$baseDir = $appBaseDirCode;
201
202 return array(
203
204 EOF;
205
206 $psr4File = <<<EOF
207 <?php
208
209 // autoload_psr4.php @generated by Composer
210
211 \$vendorDir = $vendorPathCode52;
212 \$baseDir = $appBaseDirCode;
213
214 return array(
215
216 EOF;
217
218
219  $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
220 $autoloads = $this->parseAutoloads($packageMap, $mainPackage);
221
222
223  foreach ($autoloads['psr-0'] as $namespace => $paths) {
224 $exportedPaths = array();
225 foreach ($paths as $path) {
226 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
227 }
228 $exportedPrefix = var_export($namespace, true);
229 $namespacesFile .= "    $exportedPrefix => ";
230 $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
231 }
232 $namespacesFile .= ");\n";
233
234
235  foreach ($autoloads['psr-4'] as $namespace => $paths) {
236 $exportedPaths = array();
237 foreach ($paths as $path) {
238 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
239 }
240 $exportedPrefix = var_export($namespace, true);
241 $psr4File .= "    $exportedPrefix => ";
242 $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
243 }
244 $psr4File .= ");\n";
245
246 $classmapFile = <<<EOF
247 <?php
248
249 // autoload_classmap.php @generated by Composer
250
251 \$vendorDir = $vendorPathCode52;
252 \$baseDir = $appBaseDirCode;
253
254 return array(
255
256 EOF;
257
258
259  $targetDirLoader = null;
260 $mainAutoload = $mainPackage->getAutoload();
261 if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
262 $levels = substr_count($filesystem->normalizePath($mainPackage->getTargetDir()), '/') + 1;
263 $prefixes = implode(', ', array_map(function ($prefix) {
264 return var_export($prefix, true);
265 }, array_keys($mainAutoload['psr-0'])));
266 $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
267
268 $targetDirLoader = <<<EOF
269
270     public static function autoload(\$class)
271     {
272         \$dir = $baseDirFromTargetDirCode . '/';
273         \$prefixes = array($prefixes);
274         foreach (\$prefixes as \$prefix) {
275             if (0 !== strpos(\$class, \$prefix)) {
276                 continue;
277             }
278             \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), $levels)).'.php';
279             if (!\$path = stream_resolve_include_path(\$path)) {
280                 return false;
281             }
282             require \$path;
283
284             return true;
285         }
286     }
287
288 EOF;
289 }
290
291 $blacklist = null;
292 if (!empty($autoloads['exclude-from-classmap'])) {
293 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
294 }
295
296
297  $classMap = array();
298 if ($scanPsr0Packages) {
299 $namespacesToScan = array();
300
301
302  foreach (array('psr-0', 'psr-4') as $psrType) {
303 foreach ($autoloads[$psrType] as $namespace => $paths) {
304 $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
305 }
306 }
307
308 krsort($namespacesToScan);
309
310 foreach ($namespacesToScan as $namespace => $groups) {
311 foreach ($groups as $group) {
312 foreach ($group['paths'] as $dir) {
313 $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
314 if (!is_dir($dir)) {
315 continue;
316 }
317
318 $namespaceFilter = $namespace === '' ? null : $namespace;
319 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespaceFilter, $classMap);
320 }
321 }
322 }
323 }
324
325 foreach ($autoloads['classmap'] as $dir) {
326 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, $classMap);
327 }
328
329 ksort($classMap);
330 foreach ($classMap as $class => $code) {
331 $classmapFile .= '    '.var_export($class, true).' => '.$code;
332 }
333 $classmapFile .= ");\n";
334
335 if (!$suffix) {
336 if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
337 $content = file_get_contents($vendorPath.'/autoload.php');
338 if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
339 $suffix = $match[1];
340 }
341 }
342
343 if (!$suffix) {
344 $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true));
345 }
346 }
347
348 file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
349 file_put_contents($targetDir.'/autoload_psr4.php', $psr4File);
350 file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);
351 $includePathFilePath = $targetDir.'/include_paths.php';
352 if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
353 file_put_contents($includePathFilePath, $includePathFileContents);
354 } elseif (file_exists($includePathFilePath)) {
355 unlink($includePathFilePath);
356 }
357 $includeFilesFilePath = $targetDir.'/autoload_files.php';
358 if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
359 file_put_contents($includeFilesFilePath, $includeFilesFileContents);
360 } elseif (file_exists($includeFilesFilePath)) {
361 unlink($includeFilesFilePath);
362 }
363 file_put_contents($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
364 file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
365 file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
366
367 $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
368 $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
369
370 if ($this->runScripts) {
371 $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
372 'optimize' => (bool) $scanPsr0Packages,
373 ));
374 }
375 }
376
377 private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist = null, $namespaceFilter = null, array $classMap = array())
378 {
379 foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter) as $class => $path) {
380 $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
381 if (!isset($classMap[$class])) {
382 $classMap[$class] = $pathCode;
383 } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
384 $this->io->writeError(
385 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
386 ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
387 );
388 }
389 }
390
391 return $classMap;
392 }
393
394 private function generateClassMap($dir, $blacklist = null, $namespaceFilter = null, $showAmbiguousWarning = true)
395 {
396 return ClassMapGenerator::createMap($dir, $blacklist, $showAmbiguousWarning ? $this->io : null, $namespaceFilter);
397 }
398
399 public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
400 {
401
402  $packageMap = array(array($mainPackage, ''));
403
404 foreach ($packages as $package) {
405 if ($package instanceof AliasPackage) {
406 continue;
407 }
408 $this->validatePackage($package);
409
410 $packageMap[] = array(
411 $package,
412 $installationManager->getInstallPath($package),
413 );
414 }
415
416 return $packageMap;
417 }
418
419
420
421
422
423
424 protected function validatePackage(PackageInterface $package)
425 {
426 $autoload = $package->getAutoload();
427 if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
428 $name = $package->getName();
429 $package->getTargetDir();
430 throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '$name'.");
431 }
432 if (!empty($autoload['psr-4'])) {
433 foreach ($autoload['psr-4'] as $namespace => $dirs) {
434 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
435 throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '$namespace' does not, use '$namespace\\'.");
436 }
437 }
438 }
439 }
440
441
442
443
444
445
446
447
448 public function parseAutoloads(array $packageMap, PackageInterface $mainPackage)
449 {
450 $mainPackageMap = array_shift($packageMap);
451 $sortedPackageMap = $this->sortPackageMap($packageMap);
452 $sortedPackageMap[] = $mainPackageMap;
453 array_unshift($packageMap, $mainPackageMap);
454
455 $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
456 $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
457 $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
458 $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
459 $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
460
461 krsort($psr0);
462 krsort($psr4);
463
464 return array(
465 'psr-0' => $psr0,
466 'psr-4' => $psr4,
467 'classmap' => $classmap,
468 'files' => $files,
469 'exclude-from-classmap' => $exclude,
470 );
471 }
472
473
474
475
476
477
478
479 public function createLoader(array $autoloads)
480 {
481 $loader = new ClassLoader();
482
483 if (isset($autoloads['psr-0'])) {
484 foreach ($autoloads['psr-0'] as $namespace => $path) {
485 $loader->add($namespace, $path);
486 }
487 }
488
489 if (isset($autoloads['psr-4'])) {
490 foreach ($autoloads['psr-4'] as $namespace => $path) {
491 $loader->addPsr4($namespace, $path);
492 }
493 }
494
495 if (isset($autoloads['classmap'])) {
496 $blacklist = null;
497 if (!empty($autoloads['exclude-from-classmap'])) {
498 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
499 }
500
501 foreach ($autoloads['classmap'] as $dir) {
502 try {
503 $loader->addClassMap($this->generateClassMap($dir, $blacklist, null, false));
504 } catch (\RuntimeException $e) {
505 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
506 }
507 }
508 }
509
510 return $loader;
511 }
512
513 protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
514 {
515 $includePaths = array();
516
517 foreach ($packageMap as $item) {
518 list($package, $installPath) = $item;
519
520 if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
521 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
522 }
523
524 foreach ($package->getIncludePaths() as $includePath) {
525 $includePath = trim($includePath, '/');
526 $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
527 }
528 }
529
530 if (!$includePaths) {
531 return;
532 }
533
534 $includePathsCode = '';
535 foreach ($includePaths as $path) {
536 $includePathsCode .= "    " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
537 }
538
539 return <<<EOF
540 <?php
541
542 // include_paths.php @generated by Composer
543
544 \$vendorDir = $vendorPathCode;
545 \$baseDir = $appBaseDirCode;
546
547 return array(
548 $includePathsCode);
549
550 EOF;
551 }
552
553 protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
554 {
555 $filesCode = '';
556 foreach ($files as $fileIdentifier => $functionFile) {
557 $filesCode .= '    ' . var_export($fileIdentifier, true) . ' => '
558 . $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile) . ",\n";
559 }
560
561 if (!$filesCode) {
562 return false;
563 }
564
565 return <<<EOF
566 <?php
567
568 // autoload_files.php @generated by Composer
569
570 \$vendorDir = $vendorPathCode;
571 \$baseDir = $appBaseDirCode;
572
573 return array(
574 $filesCode);
575
576 EOF;
577 }
578
579 protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $path)
580 {
581 if (!$filesystem->isAbsolutePath($path)) {
582 $path = $basePath . '/' . $path;
583 }
584 $path = $filesystem->normalizePath($path);
585
586 $baseDir = '';
587 if (strpos($path.'/', $vendorPath.'/') === 0) {
588 $path = substr($path, strlen($vendorPath));
589 $baseDir = '$vendorDir';
590
591 if ($path !== false) {
592 $baseDir .= " . ";
593 }
594 } else {
595 $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, true));
596 if (!$filesystem->isAbsolutePath($path)) {
597 $baseDir = '$baseDir . ';
598 $path = '/' . $path;
599 }
600 }
601
602 if (preg_match('/\.phar.+$/', $path)) {
603 $baseDir = "'phar://' . " . $baseDir;
604 }
605
606 return $baseDir . (($path !== false) ? var_export($path, true) : "");
607 }
608
609 protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix)
610 {
611 $lastChar = $vendorPathToTargetDirCode[strlen($vendorPathToTargetDirCode) - 1];
612 if ("'" === $lastChar || '"' === $lastChar) {
613 $vendorPathToTargetDirCode = substr($vendorPathToTargetDirCode, 0, -1).'/autoload_real.php'.$lastChar;
614 } else {
615 $vendorPathToTargetDirCode .= " . '/autoload_real.php'";
616 }
617
618 return <<<AUTOLOAD
619 <?php
620
621 // autoload.php @generated by Composer
622
623 require_once $vendorPathToTargetDirCode;
624
625 return ComposerAutoloaderInit$suffix::getLoader();
626
627 AUTOLOAD;
628 }
629
630 protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion = 70000)
631 {
632 $file = <<<HEADER
633 <?php
634
635 // autoload_real.php @generated by Composer
636
637 class ComposerAutoloaderInit$suffix
638 {
639     private static \$loader;
640
641     public static function loadClassLoader(\$class)
642     {
643         if ('Composer\\Autoload\\ClassLoader' === \$class) {
644             require __DIR__ . '/ClassLoader.php';
645         }
646     }
647
648     public static function getLoader()
649     {
650         if (null !== self::\$loader) {
651             return self::\$loader;
652         }
653
654         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader);
655         self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
656         spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
657
658
659 HEADER;
660
661 if ($useIncludePath) {
662 $file .= <<<'INCLUDE_PATH'
663         $includePaths = require __DIR__ . '/include_paths.php';
664         $includePaths[] = get_include_path();
665         set_include_path(implode(PATH_SEPARATOR, $includePaths));
666
667
668 INCLUDE_PATH;
669 }
670
671 $file .= <<<STATIC_INIT
672         \$useStaticLoader = PHP_VERSION_ID >= $staticPhpVersion && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
673         if (\$useStaticLoader) {
674             require_once __DIR__ . '/autoload_static.php';
675
676             call_user_func(\Composer\Autoload\ComposerStaticInit$suffix::getInitializer(\$loader));
677         } else {
678
679 STATIC_INIT;
680
681 if (!$this->classMapAuthoritative) {
682 $file .= <<<'PSR04'
683             $map = require __DIR__ . '/autoload_namespaces.php';
684             foreach ($map as $namespace => $path) {
685                 $loader->set($namespace, $path);
686             }
687
688             $map = require __DIR__ . '/autoload_psr4.php';
689             foreach ($map as $namespace => $path) {
690                 $loader->setPsr4($namespace, $path);
691             }
692
693
694 PSR04;
695 }
696
697 if ($useClassMap) {
698 $file .= <<<'CLASSMAP'
699             $classMap = require __DIR__ . '/autoload_classmap.php';
700             if ($classMap) {
701                 $loader->addClassMap($classMap);
702             }
703
704 CLASSMAP;
705 }
706
707 $file .= "        }\n\n";
708
709 if ($this->classMapAuthoritative) {
710 $file .= <<<'CLASSMAPAUTHORITATIVE'
711         $loader->setClassMapAuthoritative(true);
712
713 CLASSMAPAUTHORITATIVE;
714 }
715
716 if ($this->apcu) {
717 $apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
718 $file .= <<<APCU
719         \$loader->setApcuPrefix('$apcuPrefix');
720
721 APCU;
722 }
723
724 if ($useGlobalIncludePath) {
725 $file .= <<<'INCLUDEPATH'
726         $loader->setUseIncludePath(true);
727
728 INCLUDEPATH;
729 }
730
731 if ($targetDirLoader) {
732 $file .= <<<REGISTER_TARGET_DIR_AUTOLOAD
733         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true, true);
734
735
736 REGISTER_TARGET_DIR_AUTOLOAD;
737 }
738
739 $file .= <<<REGISTER_LOADER
740         \$loader->register($prependAutoloader);
741
742
743 REGISTER_LOADER;
744
745 if ($useIncludeFiles) {
746 $file .= <<<INCLUDE_FILES
747         if (\$useStaticLoader) {
748             \$includeFiles = Composer\Autoload\ComposerStaticInit$suffix::\$files;
749         } else {
750             \$includeFiles = require __DIR__ . '/autoload_files.php';
751         }
752         foreach (\$includeFiles as \$fileIdentifier => \$file) {
753             composerRequire$suffix(\$fileIdentifier, \$file);
754         }
755
756
757 INCLUDE_FILES;
758 }
759
760 $file .= <<<METHOD_FOOTER
761         return \$loader;
762     }
763
764 METHOD_FOOTER;
765
766 $file .= $targetDirLoader;
767
768 if ($useIncludeFiles) {
769 return $file . <<<FOOTER
770 }
771
772 function composerRequire$suffix(\$fileIdentifier, \$file)
773 {
774     if (empty(\$GLOBALS['__composer_autoload_files'][\$fileIdentifier])) {
775         require \$file;
776
777         \$GLOBALS['__composer_autoload_files'][\$fileIdentifier] = true;
778     }
779 }
780
781 FOOTER;
782 }
783
784 return $file . <<<FOOTER
785 }
786
787 FOOTER;
788 }
789
790 protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion)
791 {
792 $staticPhpVersion = 50600;
793
794 $file = <<<HEADER
795 <?php
796
797 // autoload_static.php @generated by Composer
798
799 namespace Composer\Autoload;
800
801 class ComposerStaticInit$suffix
802 {
803
804 HEADER;
805
806 $loader = new ClassLoader();
807
808 $map = require $targetDir . '/autoload_namespaces.php';
809 foreach ($map as $namespace => $path) {
810 $loader->set($namespace, $path);
811 }
812
813 $map = require $targetDir . '/autoload_psr4.php';
814 foreach ($map as $namespace => $path) {
815 $loader->setPsr4($namespace, $path);
816 }
817
818 $classMap = require $targetDir . '/autoload_classmap.php';
819 if ($classMap) {
820 $loader->addClassMap($classMap);
821 }
822
823 $filesystem = new Filesystem();
824
825 $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
826 $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
827
828 $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
829 $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
830
831 $initializer = '';
832 $prefix = "\0Composer\Autoload\ClassLoader\0";
833 $prefixLen = strlen($prefix);
834 if (file_exists($targetDir . '/autoload_files.php')) {
835 $maps = array('files' => require $targetDir . '/autoload_files.php');
836 } else {
837 $maps = array();
838 }
839
840 foreach ((array) $loader as $prop => $value) {
841 if ($value && 0 === strpos($prop, $prefix)) {
842 $maps[substr($prop, $prefixLen)] = $value;
843 }
844 }
845
846 foreach ($maps as $prop => $value) {
847 if (count($value) > 32767) {
848
849  
850  $staticPhpVersion = 70000;
851 }
852 $value = var_export($value, true);
853 $value = str_replace($absoluteVendorPathCode, $vendorPathCode, $value);
854 $value = str_replace($absoluteAppBaseDirCode, $appBaseDirCode, $value);
855 $value = ltrim(preg_replace('/^ */m', '    $0$0', $value));
856
857 $file .= sprintf("    public static $%s = %s;\n\n", $prop, $value);
858 if ('files' !== $prop) {
859 $initializer .= "            \$loader->$prop = ComposerStaticInit$suffix::\$$prop;\n";
860 }
861 }
862
863 return $file . <<<INITIALIZER
864     public static function getInitializer(ClassLoader \$loader)
865     {
866         return \Closure::bind(function () use (\$loader) {
867 $initializer
868         }, null, ClassLoader::class);
869     }
870 }
871
872 INITIALIZER;
873 }
874
875 protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
876 {
877 $autoloads = array();
878
879 foreach ($packageMap as $item) {
880 list($package, $installPath) = $item;
881
882 $autoload = $package->getAutoload();
883 if ($this->devMode && $package === $mainPackage) {
884 $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
885 }
886
887
888  if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
889 continue;
890 }
891 if (null !== $package->getTargetDir() && $package !== $mainPackage) {
892 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
893 }
894
895 foreach ($autoload[$type] as $namespace => $paths) {
896 foreach ((array) $paths as $path) {
897 if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
898
899  if ($package === $mainPackage) {
900 $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
901 $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
902 } else {
903
904  $path = $package->getTargetDir() . '/' . $path;
905 }
906 }
907
908 if ($type === 'exclude-from-classmap') {
909
910  $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
911
912
913  $path = str_replace('\\*\\*', '.+?', $path);
914 $path = str_replace('\\*', '[^/]+?', $path);
915
916
917  $updir = null;
918 $path = preg_replace_callback(
919 '{^((?:(?:\\\\\\.){1,2}+/)+)}',
920 function ($matches) use (&$updir) {
921 if (isset($matches[1])) {
922
923  $updir = str_replace('\\.', '.', $matches[1]);
924 }
925
926 return '';
927 },
928 $path
929 );
930 if (empty($installPath)) {
931 $installPath = strtr(getcwd(), '\\', '/');
932 }
933
934 $resolvedPath = realpath($installPath . '/' . $updir);
935 $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path;
936 continue;
937 }
938
939 $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
940
941 if ($type === 'files') {
942 $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
943 continue;
944 } elseif ($type === 'classmap') {
945 $autoloads[] = $relativePath;
946 continue;
947 }
948
949 $autoloads[$namespace][] = $relativePath;
950 }
951 }
952 }
953
954 return $autoloads;
955 }
956
957 protected function getFileIdentifier(PackageInterface $package, $path)
958 {
959 return md5($package->getName() . ':' . $path);
960 }
961
962
963
964
965
966
967
968
969
970 protected function sortPackageMap(array $packageMap)
971 {
972 $packages = array();
973 $paths = array();
974 $usageList = array();
975
976 foreach ($packageMap as $item) {
977 list($package, $path) = $item;
978 $name = $package->getName();
979 $packages[$name] = $package;
980 $paths[$name] = $path;
981
982 foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) {
983 $target = $link->getTarget();
984 $usageList[$target][] = $name;
985 }
986 }
987
988 $computing = array();
989 $computed = array();
990 $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
991
992  if (isset($computed[$name])) {
993 return $computed[$name];
994 }
995
996
997  if (isset($computing[$name])) {
998 return 0;
999 }
1000
1001 $computing[$name] = true;
1002 $weight = 0;
1003
1004 if (isset($usageList[$name])) {
1005 foreach ($usageList[$name] as $user) {
1006 $weight -= 1 - $computeImportance($user);
1007 }
1008 }
1009
1010 unset($computing[$name]);
1011 $computed[$name] = $weight;
1012
1013 return $weight;
1014 };
1015
1016 $weightList = array();
1017
1018 foreach ($packages as $name => $package) {
1019 $weight = $computeImportance($name);
1020 $weightList[$name] = $weight;
1021 }
1022
1023 $stable_sort = function (&$array) {
1024 static $transform, $restore;
1025
1026 $i = 0;
1027
1028 if (!$transform) {
1029 $transform = function (&$v, $k) use (&$i) {
1030 $v = array($v, ++$i, $k, $v);
1031 };
1032
1033 $restore = function (&$v, $k) {
1034 $v = $v[3];
1035 };
1036 }
1037
1038 array_walk($array, $transform);
1039 asort($array);
1040 array_walk($array, $restore);
1041 };
1042
1043 $stable_sort($weightList);
1044
1045 $sortedPackageMap = array();
1046
1047 foreach (array_keys($weightList) as $name) {
1048 $sortedPackageMap[] = array($packages[$name], $paths[$name]);
1049 }
1050
1051 return $sortedPackageMap;
1052 }
1053
1054
1055
1056
1057
1058
1059
1060 protected function safeCopy($source, $target)
1061 {
1062 $source = fopen($source, 'r');
1063 $target = fopen($target, 'w+');
1064
1065 stream_copy_to_stream($source, $target);
1066 fclose($source);
1067 fclose($target);
1068 }
1069 }
1070 <?php
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088 namespace Composer\Autoload;
1089
1090 use Symfony\Component\Finder\Finder;
1091 use Composer\IO\IOInterface;
1092 use Composer\Util\Filesystem;
1093
1094
1095
1096
1097
1098
1099
1100 class ClassMapGenerator
1101 {
1102
1103
1104
1105
1106
1107
1108 public static function dump($dirs, $file)
1109 {
1110 $maps = array();
1111
1112 foreach ($dirs as $dir) {
1113 $maps = array_merge($maps, static::createMap($dir));
1114 }
1115
1116 file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
1117 }
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130 public static function createMap($path, $blacklist = null, IOInterface $io = null, $namespace = null)
1131 {
1132 if (is_string($path)) {
1133 if (is_file($path)) {
1134 $path = array(new \SplFileInfo($path));
1135 } elseif (is_dir($path)) {
1136 $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
1137 } else {
1138 throw new \RuntimeException(
1139 'Could not scan for classes inside "'.$path.
1140 '" which does not appear to be a file nor a folder'
1141 );
1142 }
1143 }
1144
1145 $map = array();
1146 $filesystem = new Filesystem();
1147 $cwd = realpath(getcwd());
1148
1149 foreach ($path as $file) {
1150 $filePath = $file->getPathname();
1151 if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
1152 continue;
1153 }
1154
1155 if (!$filesystem->isAbsolutePath($filePath)) {
1156 $filePath = $cwd . '/' . $filePath;
1157 $filePath = $filesystem->normalizePath($filePath);
1158 } else {
1159 $filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath);
1160 }
1161
1162
1163  if ($blacklist && preg_match($blacklist, strtr(realpath($filePath), '\\', '/'))) {
1164 continue;
1165 }
1166
1167 $classes = self::findClasses($filePath);
1168
1169 foreach ($classes as $class) {
1170
1171  if (null !== $namespace && 0 !== strpos($class, $namespace)) {
1172 continue;
1173 }
1174
1175 if (!isset($map[$class])) {
1176 $map[$class] = $filePath;
1177 } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
1178 $io->writeError(
1179 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
1180 ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
1181 );
1182 }
1183 }
1184 }
1185
1186 return $map;
1187 }
1188
1189
1190
1191
1192
1193
1194
1195
1196 private static function findClasses($path)
1197 {
1198 $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
1199 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
1200 $extraTypes .= '|enum';
1201 }
1202
1203
1204  
1205  $contents = @php_strip_whitespace($path);
1206 if (!$contents) {
1207 if (!file_exists($path)) {
1208 $message = 'File at "%s" does not exist, check your classmap definitions';
1209 } elseif (!is_readable($path)) {
1210 $message = 'File at "%s" is not readable, check its permissions';
1211 } elseif ('' === trim(file_get_contents($path))) {
1212
1213  return array();
1214 } else {
1215 $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
1216 }
1217 $error = error_get_last();
1218 if (isset($error['message'])) {
1219 $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
1220 }
1221 throw new \RuntimeException(sprintf($message, $path));
1222 }
1223
1224
1225  if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
1226 return array();
1227 }
1228
1229
1230  $contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents);
1231
1232  $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
1233
1234  if (substr($contents, 0, 2) !== '<?') {
1235 $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
1236 if ($replacements === 0) {
1237 return array();
1238 }
1239 }
1240
1241  $contents = preg_replace('{\?>.+<\?}s', '?><?', $contents);
1242
1243  $pos = strrpos($contents, '?>');
1244 if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
1245 $contents = substr($contents, 0, $pos);
1246 }
1247
1248 preg_match_all('{
1249             (?:
1250                  \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
1251                | \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*+ [\{;]
1252             )
1253         }ix', $contents, $matches);
1254
1255 $classes = array();
1256 $namespace = '';
1257
1258 for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
1259 if (!empty($matches['ns'][$i])) {
1260 $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
1261 } else {
1262 $name = $matches['name'][$i];
1263
1264  if ($name === 'extends' || $name === 'implements') {
1265 continue;
1266 }
1267 if ($name[0] === ':') {
1268
1269  $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
1270 } elseif ($matches['type'][$i] === 'enum') {
1271
1272  
1273  
1274  
1275  $name = rtrim($name, ':');
1276 }
1277 $classes[] = ltrim($namespace . $name, '\\');
1278 }
1279 }
1280
1281 return $classes;
1282 }
1283 }
1284 <?php
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296 namespace Composer;
1297
1298 use Composer\IO\IOInterface;
1299 use Composer\Util\Filesystem;
1300 use Composer\Util\Silencer;
1301 use Symfony\Component\Finder\Finder;
1302
1303
1304
1305
1306
1307
1308 class Cache
1309 {
1310 private static $cacheCollected = false;
1311 private $io;
1312 private $root;
1313 private $enabled = true;
1314 private $whitelist;
1315 private $filesystem;
1316
1317
1318
1319
1320
1321
1322
1323 public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
1324 {
1325 $this->io = $io;
1326 $this->root = rtrim($cacheDir, '/\\') . '/';
1327 $this->whitelist = $whitelist;
1328 $this->filesystem = $filesystem ?: new Filesystem();
1329
1330 if (preg_match('{(^|[\\\\/])(\$null|NUL|/dev/null)([\\\\/]|$)}', $cacheDir)) {
1331 $this->enabled = false;
1332
1333 return;
1334 }
1335
1336 if (
1337 (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, true))
1338 || !is_writable($this->root)
1339 ) {
1340 $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
1341 $this->enabled = false;
1342 }
1343 }
1344
1345 public function isEnabled()
1346 {
1347 return $this->enabled;
1348 }
1349
1350 public function getRoot()
1351 {
1352 return $this->root;
1353 }
1354
1355 public function read($file)
1356 {
1357 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1358 if ($this->enabled && file_exists($this->root . $file)) {
1359 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1360
1361 return file_get_contents($this->root . $file);
1362 }
1363
1364 return false;
1365 }
1366
1367 public function write($file, $contents)
1368 {
1369 if ($this->enabled) {
1370 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1371
1372 $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
1373
1374 try {
1375 return file_put_contents($this->root . $file, $contents);
1376 } catch (\ErrorException $e) {
1377 $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', true, IOInterface::DEBUG);
1378 if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
1379
1380  unlink($this->root . $file);
1381
1382 $message = sprintf(
1383 '<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available</warning>',
1384 $this->root . $file,
1385 $m[1],
1386 $m[2],
1387 @disk_free_space($this->root . dirname($file))
1388 );
1389
1390 $this->io->writeError($message);
1391
1392 return false;
1393 }
1394
1395 throw $e;
1396 }
1397 }
1398
1399 return false;
1400 }
1401
1402
1403
1404
1405 public function copyFrom($file, $source)
1406 {
1407 if ($this->enabled) {
1408 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1409 $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
1410
1411 if (!file_exists($source)) {
1412 $this->io->writeError('<error>'.$source.' does not exist, can not write into cache</error>');
1413 } elseif ($this->io->isDebug()) {
1414 $this->io->writeError('Writing '.$this->root . $file.' into cache from '.$source);
1415 }
1416
1417 return copy($source, $this->root . $file);
1418 }
1419
1420 return false;
1421 }
1422
1423
1424
1425
1426 public function copyTo($file, $target)
1427 {
1428 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1429 if ($this->enabled && file_exists($this->root . $file)) {
1430 try {
1431 touch($this->root . $file, filemtime($this->root . $file), time());
1432 } catch (\ErrorException $e) {
1433
1434  
1435  Silencer::call('touch', $this->root . $file);
1436 }
1437
1438 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1439
1440 return copy($this->root . $file, $target);
1441 }
1442
1443 return false;
1444 }
1445
1446 public function gcIsNecessary()
1447 {
1448 return (!self::$cacheCollected && !mt_rand(0, 50));
1449 }
1450
1451 public function remove($file)
1452 {
1453 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1454 if ($this->enabled && file_exists($this->root . $file)) {
1455 return $this->filesystem->unlink($this->root . $file);
1456 }
1457
1458 return false;
1459 }
1460
1461 public function clear()
1462 {
1463 if ($this->enabled) {
1464 return $this->filesystem->removeDirectory($this->root);
1465 }
1466
1467 return false;
1468 }
1469
1470 public function gc($ttl, $maxSize)
1471 {
1472 if ($this->enabled) {
1473 $expire = new \DateTime();
1474 $expire->modify('-'.$ttl.' seconds');
1475
1476 $finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
1477 foreach ($finder as $file) {
1478 $this->filesystem->unlink($file->getPathname());
1479 }
1480
1481 $totalSize = $this->filesystem->size($this->root);
1482 if ($totalSize > $maxSize) {
1483 $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
1484 while ($totalSize > $maxSize && $iterator->valid()) {
1485 $filepath = $iterator->current()->getPathname();
1486 $totalSize -= $this->filesystem->size($filepath);
1487 $this->filesystem->unlink($filepath);
1488 $iterator->next();
1489 }
1490 }
1491
1492 self::$cacheCollected = true;
1493
1494 return true;
1495 }
1496
1497 return false;
1498 }
1499
1500 public function sha1($file)
1501 {
1502 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1503 if ($this->enabled && file_exists($this->root . $file)) {
1504 return sha1_file($this->root . $file);
1505 }
1506
1507 return false;
1508 }
1509
1510 public function sha256($file)
1511 {
1512 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1513 if ($this->enabled && file_exists($this->root . $file)) {
1514 return hash_file('sha256', $this->root . $file);
1515 }
1516
1517 return false;
1518 }
1519
1520 protected function getFinder()
1521 {
1522 return Finder::create()->in($this->root)->files();
1523 }
1524 }
1525 <?php
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537 namespace Composer\Command;
1538
1539 use Symfony\Component\Console\Input\InputInterface;
1540 use Symfony\Component\Console\Output\OutputInterface;
1541
1542
1543
1544
1545 class AboutCommand extends BaseCommand
1546 {
1547 protected function configure()
1548 {
1549 $this
1550 ->setName('about')
1551 ->setDescription('Shows the short information about Composer.')
1552 ->setHelp(<<<EOT
1553 <info>php composer.phar about</info>
1554 EOT
1555 )
1556 ;
1557 }
1558
1559 protected function execute(InputInterface $input, OutputInterface $output)
1560 {
1561 $this->getIO()->write(<<<EOT
1562 <info>Composer - Package Management for PHP</info>
1563 <comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
1564 See https://getcomposer.org/ for more information.</comment>
1565 EOT
1566 );
1567 }
1568 }
1569 <?php
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581 namespace Composer\Command;
1582
1583 use Composer\Factory;
1584 use Composer\IO\IOInterface;
1585 use Composer\Config;
1586 use Composer\Composer;
1587 use Composer\Repository\CompositeRepository;
1588 use Composer\Repository\RepositoryFactory;
1589 use Composer\Script\ScriptEvents;
1590 use Composer\Plugin\CommandEvent;
1591 use Composer\Plugin\PluginEvents;
1592 use Composer\Util\Filesystem;
1593 use Symfony\Component\Console\Input\InputArgument;
1594 use Symfony\Component\Console\Input\InputInterface;
1595 use Symfony\Component\Console\Input\InputOption;
1596 use Symfony\Component\Console\Output\OutputInterface;
1597
1598
1599
1600
1601
1602
1603 class ArchiveCommand extends BaseCommand
1604 {
1605 protected function configure()
1606 {
1607 $this
1608 ->setName('archive')
1609 ->setDescription('Creates an archive of this composer package.')
1610 ->setDefinition(array(
1611 new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project'),
1612 new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'),
1613 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar or zip'),
1614 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
1615 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
1616 .' Note that the format will be appended.'),
1617 new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
1618 ))
1619 ->setHelp(<<<EOT
1620 The <info>archive</info> command creates an archive of the specified format
1621 containing the files and directories of the Composer project or the specified
1622 package in the specified version and writes it to the specified directory.
1623
1624 <info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
1625
1626 EOT
1627 )
1628 ;
1629 }
1630
1631 protected function execute(InputInterface $input, OutputInterface $output)
1632 {
1633 $config = Factory::createConfig();
1634 $composer = $this->getComposer(false);
1635 if ($composer) {
1636 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
1637 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
1638 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
1639 }
1640
1641 if (null === $input->getOption('format')) {
1642 $input->setOption('format', $config->get('archive-format'));
1643 }
1644 if (null === $input->getOption('dir')) {
1645 $input->setOption('dir', $config->get('archive-dir'));
1646 }
1647
1648 $returnCode = $this->archive(
1649 $this->getIO(),
1650 $config,
1651 $input->getArgument('package'),
1652 $input->getArgument('version'),
1653 $input->getOption('format'),
1654 $input->getOption('dir'),
1655 $input->getOption('file'),
1656 $input->getOption('ignore-filters'),
1657 $composer
1658 );
1659
1660 if (0 === $returnCode && $composer) {
1661 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
1662 }
1663
1664 return $returnCode;
1665 }
1666
1667 protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null, $ignoreFilters = false, Composer $composer = null)
1668 {
1669 if ($composer) {
1670 $archiveManager = $composer->getArchiveManager();
1671 } else {
1672 $factory = new Factory;
1673 $downloadManager = $factory->createDownloadManager($io, $config);
1674 $archiveManager = $factory->createArchiveManager($config, $downloadManager);
1675 }
1676
1677 if ($packageName) {
1678 $package = $this->selectPackage($io, $packageName, $version);
1679
1680 if (!$package) {
1681 return 1;
1682 }
1683 } else {
1684 $package = $this->getComposer()->getPackage();
1685 }
1686
1687 $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
1688 $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
1689 $fs = new Filesystem;
1690 $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
1691
1692 $io->writeError('Created: ', false);
1693 $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
1694
1695 return 0;
1696 }
1697
1698 protected function selectPackage(IOInterface $io, $packageName, $version = null)
1699 {
1700 $io->writeError('<info>Searching for the specified package.</info>');
1701
1702 if ($composer = $this->getComposer(false)) {
1703 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
1704 $repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
1705 } else {
1706 $defaultRepos = RepositoryFactory::defaultRepos($this->getIO());
1707 $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
1708 $repo = new CompositeRepository($defaultRepos);
1709 }
1710
1711 $packages = $repo->findPackages($packageName, $version);
1712
1713 if (count($packages) > 1) {
1714 $package = reset($packages);
1715 $io->writeError('<info>Found multiple matches, selected '.$package->getPrettyString().'.</info>');
1716 $io->writeError('Alternatives were '.implode(', ', array_map(function ($p) {
1717 return $p->getPrettyString();
1718 }, $packages)).'.');
1719 $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
1720 } elseif ($packages) {
1721 $package = reset($packages);
1722 $io->writeError('<info>Found an exact match '.$package->getPrettyString().'.</info>');
1723 } else {
1724 $io->writeError('<error>Could not find a package matching '.$packageName.'.</error>');
1725
1726 return false;
1727 }
1728
1729 return $package;
1730 }
1731 }
1732 <?php
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744 namespace Composer\Command;
1745
1746 use Composer\Composer;
1747 use Composer\Config;
1748 use Composer\Console\Application;
1749 use Composer\IO\IOInterface;
1750 use Composer\IO\NullIO;
1751 use Symfony\Component\Console\Input\InputInterface;
1752 use Symfony\Component\Console\Output\OutputInterface;
1753 use Symfony\Component\Console\Command\Command;
1754
1755
1756
1757
1758
1759
1760
1761 abstract class BaseCommand extends Command
1762 {
1763
1764
1765
1766 private $composer;
1767
1768
1769
1770
1771 private $io;
1772
1773
1774
1775
1776
1777
1778
1779 public function getComposer($required = true, $disablePlugins = null)
1780 {
1781 if (null === $this->composer) {
1782 $application = $this->getApplication();
1783 if ($application instanceof Application) {
1784
1785 $this->composer = $application->getComposer($required, $disablePlugins);
1786 } elseif ($required) {
1787 throw new \RuntimeException(
1788 'Could not create a Composer\Composer instance, you must inject '.
1789 'one if this command is not used with a Composer\Console\Application instance'
1790 );
1791 }
1792 }
1793
1794 return $this->composer;
1795 }
1796
1797
1798
1799
1800 public function setComposer(Composer $composer)
1801 {
1802 $this->composer = $composer;
1803 }
1804
1805
1806
1807
1808 public function resetComposer()
1809 {
1810 $this->composer = null;
1811 $this->getApplication()->resetComposer();
1812 }
1813
1814
1815
1816
1817
1818
1819
1820
1821 public function isProxyCommand()
1822 {
1823 return false;
1824 }
1825
1826
1827
1828
1829 public function getIO()
1830 {
1831 if (null === $this->io) {
1832 $application = $this->getApplication();
1833 if ($application instanceof Application) {
1834
1835 $this->io = $application->getIO();
1836 } else {
1837 $this->io = new NullIO();
1838 }
1839 }
1840
1841 return $this->io;
1842 }
1843
1844
1845
1846
1847 public function setIO(IOInterface $io)
1848 {
1849 $this->io = $io;
1850 }
1851
1852
1853
1854
1855 protected function initialize(InputInterface $input, OutputInterface $output)
1856 {
1857 if (true === $input->hasParameterOption(array('--no-ansi')) && $input->hasOption('no-progress')) {
1858 $input->setOption('no-progress', true);
1859 }
1860
1861 parent::initialize($input, $output);
1862 }
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873 protected function getPreferredInstallOptions(Config $config, InputInterface $input, $keepVcsRequiresPreferSource = false)
1874 {
1875 $preferSource = false;
1876 $preferDist = false;
1877
1878 switch ($config->get('preferred-install')) {
1879 case 'source':
1880 $preferSource = true;
1881 break;
1882 case 'dist':
1883 $preferDist = true;
1884 break;
1885 case 'auto':
1886 default:
1887
1888  break;
1889 }
1890
1891 if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
1892 $preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
1893 $preferDist = $input->getOption('prefer-dist');
1894 }
1895
1896 return array($preferSource, $preferDist);
1897 }
1898 }
1899 <?php
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911 namespace Composer\Command;
1912
1913 use Composer\DependencyResolver\Pool;
1914 use Composer\Package\Link;
1915 use Composer\Package\PackageInterface;
1916 use Composer\Repository\ArrayRepository;
1917 use Composer\Repository\CompositeRepository;
1918 use Composer\Repository\PlatformRepository;
1919 use Composer\Repository\RepositoryFactory;
1920 use Composer\Plugin\CommandEvent;
1921 use Composer\Plugin\PluginEvents;
1922 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
1923 use Composer\Package\Version\VersionParser;
1924 use Symfony\Component\Console\Helper\Table;
1925 use Symfony\Component\Console\Input\InputArgument;
1926 use Symfony\Component\Console\Input\InputInterface;
1927 use Symfony\Component\Console\Input\InputOption;
1928 use Symfony\Component\Console\Output\OutputInterface;
1929
1930
1931
1932
1933
1934
1935 class BaseDependencyCommand extends BaseCommand
1936 {
1937 const ARGUMENT_PACKAGE = 'package';
1938 const ARGUMENT_CONSTRAINT = 'constraint';
1939 const OPTION_RECURSIVE = 'recursive';
1940 const OPTION_TREE = 'tree';
1941
1942 protected $colors;
1943
1944
1945
1946
1947 protected function configure()
1948 {
1949 $this->setDefinition(array(
1950 new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
1951 new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
1952 new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
1953 new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
1954 ));
1955 }
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965 protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
1966 {
1967
1968  $composer = $this->getComposer();
1969 $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
1970 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
1971
1972
1973  $platformOverrides = $composer->getConfig()->get('platform') ?: array();
1974 $repository = new CompositeRepository(array(
1975 new ArrayRepository(array($composer->getPackage())),
1976 $composer->getRepositoryManager()->getLocalRepository(),
1977 new PlatformRepository(array(), $platformOverrides),
1978 ));
1979 $pool = new Pool();
1980 $pool->addRepository($repository);
1981
1982
1983  list($needle, $textConstraint) = array_pad(
1984 explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
1985 2,
1986 $input->getArgument(self::ARGUMENT_CONSTRAINT)
1987 );
1988
1989
1990  $packages = $pool->whatProvides($needle);
1991 if (empty($packages)) {
1992 throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
1993 }
1994
1995
1996  
1997  if (!$repository->findPackage($needle, $textConstraint)) {
1998 $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
1999 if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
2000 $repository->addRepository(new ArrayRepository(array(clone $match)));
2001 }
2002 }
2003
2004
2005  $needles = array($needle);
2006 if ($inverted) {
2007 foreach ($packages as $package) {
2008 $needles = array_merge($needles, array_map(function (Link $link) {
2009 return $link->getTarget();
2010 }, $package->getReplaces()));
2011 }
2012 }
2013
2014
2015  if ('*' !== $textConstraint) {
2016 $versionParser = new VersionParser();
2017 $constraint = $versionParser->parseConstraints($textConstraint);
2018 } else {
2019 $constraint = null;
2020 }
2021
2022
2023  $renderTree = $input->getOption(self::OPTION_TREE);
2024 $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
2025
2026
2027  $results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
2028 if (empty($results)) {
2029 $extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
2030 $this->getIO()->writeError(sprintf('<info>There is no installed package depending on "%s"%s</info>',
2031 $needle, $extra));
2032 } elseif ($renderTree) {
2033 $this->initStyles($output);
2034 $root = $packages[0];
2035 $this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
2036 $this->printTree($results);
2037 } else {
2038 $this->printTable($output, $results);
2039 }
2040
2041 return 0;
2042 }
2043
2044
2045
2046
2047
2048
2049
2050 protected function printTable(OutputInterface $output, $results)
2051 {
2052 $table = array();
2053 $doubles = array();
2054 do {
2055 $queue = array();
2056 $rows = array();
2057 foreach ($results as $result) {
2058
2059
2060
2061
2062 list($package, $link, $children) = $result;
2063 $unique = (string) $link;
2064 if (isset($doubles[$unique])) {
2065 continue;
2066 }
2067 $doubles[$unique] = true;
2068 $version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
2069 $rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
2070 if ($children) {
2071 $queue = array_merge($queue, $children);
2072 }
2073 }
2074 $results = $queue;
2075 $table = array_merge($rows, $table);
2076 } while (!empty($results));
2077
2078
2079  $renderer = new Table($output);
2080 $renderer->setStyle('compact');
2081 $renderer->getStyle()->setVerticalBorderChar('');
2082 $renderer->getStyle()->setCellRowContentFormat('%s  ');
2083 $renderer->setRows($table)->render();
2084 }
2085
2086
2087
2088
2089
2090
2091 protected function initStyles(OutputInterface $output)
2092 {
2093 $this->colors = array(
2094 'green',
2095 'yellow',
2096 'cyan',
2097 'magenta',
2098 'blue',
2099 );
2100
2101 foreach ($this->colors as $color) {
2102 $style = new OutputFormatterStyle($color);
2103 $output->getFormatter()->setStyle($color, $style);
2104 }
2105 }
2106
2107
2108
2109
2110
2111
2112
2113
2114 protected function printTree($results, $prefix = '', $level = 1)
2115 {
2116 $count = count($results);
2117 $idx = 0;
2118 foreach ($results as $result) {
2119
2120
2121
2122
2123
2124 list($package, $link, $children) = $result;
2125
2126 $color = $this->colors[$level % count($this->colors)];
2127 $prevColor = $this->colors[($level - 1) % count($this->colors)];
2128 $isLast = (++$idx == $count);
2129 $versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
2130 $packageText = rtrim(sprintf('<%s>%s</%1$s> %s', $color, $package->getPrettyName(), $versionText));
2131 $linkText = sprintf('%s <%s>%s</%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
2132 $circularWarn = $children === false ? '(circular dependency aborted here)' : '';
2133 $this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
2134 if ($children) {
2135 $this->printTree($children, $prefix . ($isLast ? '   ' : '│  '), $level + 1);
2136 }
2137 }
2138 }
2139
2140 private function writeTreeLine($line)
2141 {
2142 $io = $this->getIO();
2143 if (!$io->isDecorated()) {
2144 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
2145 }
2146
2147 $io->write($line);
2148 }
2149 }
2150 <?php
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162 namespace Composer\Command;
2163
2164 use Composer\Package\Link;
2165 use Composer\Package\PackageInterface;
2166 use Composer\Semver\Constraint\Constraint;
2167 use Symfony\Component\Console\Helper\Table;
2168 use Symfony\Component\Console\Input\InputInterface;
2169 use Symfony\Component\Console\Output\OutputInterface;
2170 use Composer\Repository\PlatformRepository;
2171
2172 class CheckPlatformReqsCommand extends BaseCommand
2173 {
2174 protected function configure()
2175 {
2176 $this->setName('check-platform-reqs')
2177 ->setDescription('Check that platform requirements are satisfied.')
2178 ->setHelp(<<<EOT
2179 Checks that your PHP and extensions versions match the platform requirements of the installed packages.
2180
2181 <info>php composer.phar check-platform-reqs</info>
2182
2183 EOT
2184 );
2185 }
2186
2187 protected function execute(InputInterface $input, OutputInterface $output)
2188 {
2189 $composer = $this->getComposer();
2190
2191 $repos = $composer->getRepositoryManager()->getLocalRepository();
2192
2193 $allPackages = array_merge(array($composer->getPackage()), $repos->getPackages());
2194 $requires = $composer->getPackage()->getDevRequires();
2195 foreach ($requires as $require => $link) {
2196 $requires[$require] = array($link);
2197 }
2198
2199
2200
2201
2202 foreach ($allPackages as $package) {
2203 foreach ($package->getRequires() as $require => $link) {
2204 $requires[$require][] = $link;
2205 }
2206 }
2207 ksort($requires);
2208
2209 $platformRepo = new PlatformRepository(array(), array());
2210 $currentPlatformPackages = $platformRepo->getPackages();
2211 $currentPlatformPackageMap = array();
2212
2213
2214
2215
2216 foreach ($currentPlatformPackages as $currentPlatformPackage) {
2217 $currentPlatformPackageMap[$currentPlatformPackage->getName()] = $currentPlatformPackage;
2218 }
2219
2220 $results = array();
2221
2222 $exitCode = 0;
2223
2224
2225
2226
2227 foreach ($requires as $require => $links) {
2228 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $require)) {
2229 if (isset($currentPlatformPackageMap[$require])) {
2230 $pass = true;
2231 $version = $currentPlatformPackageMap[$require]->getVersion();
2232
2233 foreach ($links as $link) {
2234 if (!$link->getConstraint()->matches(new Constraint('=', $version))) {
2235 $results[] = array(
2236 $currentPlatformPackageMap[$require]->getPrettyName(),
2237 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2238 $link,
2239 '<error>failed</error>',
2240 );
2241 $pass = false;
2242
2243 $exitCode = max($exitCode, 1);
2244 }
2245 }
2246
2247 if ($pass) {
2248 $results[] = array(
2249 $currentPlatformPackageMap[$require]->getPrettyName(),
2250 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2251 null,
2252 '<info>success</info>',
2253 );
2254 }
2255 } else {
2256 $results[] = array(
2257 $require,
2258 'n/a',
2259 $links[0],
2260 '<error>missing</error>',
2261 );
2262
2263 $exitCode = max($exitCode, 2);
2264 }
2265 }
2266 }
2267
2268 $this->printTable($output, $results);
2269
2270 return $exitCode;
2271 }
2272
2273 protected function printTable(OutputInterface $output, $results)
2274 {
2275 $table = array();
2276 $rows = array();
2277 foreach ($results as $result) {
2278
2279
2280
2281 list($platformPackage, $version, $link, $status) = $result;
2282 $rows[] = array(
2283 $platformPackage,
2284 $version,
2285 $link ? sprintf('%s %s %s (%s)', $link->getSource(), $link->getDescription(), $link->getTarget(), $link->getPrettyConstraint()) : '',
2286 $status,
2287 );
2288 }
2289 $table = array_merge($rows, $table);
2290
2291
2292  $renderer = new Table($output);
2293 $renderer->setStyle('compact');
2294 $renderer->getStyle()->setVerticalBorderChar('');
2295 $renderer->getStyle()->setCellRowContentFormat('%s  ');
2296 $renderer->setRows($table)->render();
2297 }
2298 }
2299 <?php
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311 namespace Composer\Command;
2312
2313 use Composer\Cache;
2314 use Composer\Factory;
2315 use Symfony\Component\Console\Input\InputInterface;
2316 use Symfony\Component\Console\Output\OutputInterface;
2317
2318
2319
2320
2321 class ClearCacheCommand extends BaseCommand
2322 {
2323 protected function configure()
2324 {
2325 $this
2326 ->setName('clear-cache')
2327 ->setAliases(array('clearcache'))
2328 ->setDescription('Clears composer\'s internal package cache.')
2329 ->setHelp(<<<EOT
2330 The <info>clear-cache</info> deletes all cached packages from composer's
2331 cache directory.
2332 EOT
2333 )
2334 ;
2335 }
2336
2337 protected function execute(InputInterface $input, OutputInterface $output)
2338 {
2339 $config = Factory::createConfig();
2340 $io = $this->getIO();
2341
2342 $cachePaths = array(
2343 'cache-vcs-dir' => $config->get('cache-vcs-dir'),
2344 'cache-repo-dir' => $config->get('cache-repo-dir'),
2345 'cache-files-dir' => $config->get('cache-files-dir'),
2346 'cache-dir' => $config->get('cache-dir'),
2347 );
2348
2349 foreach ($cachePaths as $key => $cachePath) {
2350 $cachePath = realpath($cachePath);
2351 if (!$cachePath) {
2352 $io->writeError("<info>Cache directory does not exist ($key): $cachePath</info>");
2353
2354 continue;
2355 }
2356 $cache = new Cache($io, $cachePath);
2357 if (!$cache->isEnabled()) {
2358 $io->writeError("<info>Cache is not enabled ($key): $cachePath</info>");
2359
2360 continue;
2361 }
2362
2363 $io->writeError("<info>Clearing cache ($key): $cachePath</info>");
2364 $cache->clear();
2365 }
2366
2367 $io->writeError('<info>All caches cleared.</info>');
2368 }
2369 }
2370 <?php
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382 namespace Composer\Command;
2383
2384 use Composer\Util\Platform;
2385 use Composer\Util\Silencer;
2386 use Symfony\Component\Console\Input\InputInterface;
2387 use Symfony\Component\Console\Input\InputArgument;
2388 use Symfony\Component\Console\Input\InputOption;
2389 use Symfony\Component\Console\Output\OutputInterface;
2390 use Composer\Config;
2391 use Composer\Config\JsonConfigSource;
2392 use Composer\Factory;
2393 use Composer\Json\JsonFile;
2394 use Composer\Semver\VersionParser;
2395 use Composer\Package\BasePackage;
2396
2397
2398
2399
2400
2401 class ConfigCommand extends BaseCommand
2402 {
2403
2404
2405
2406 protected $config;
2407
2408
2409
2410
2411 protected $configFile;
2412
2413
2414
2415
2416 protected $configSource;
2417
2418
2419
2420
2421 protected $authConfigFile;
2422
2423
2424
2425
2426 protected $authConfigSource;
2427
2428
2429
2430
2431 protected function configure()
2432 {
2433 $this
2434 ->setName('config')
2435 ->setDescription('Sets config options.')
2436 ->setDefinition(array(
2437 new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'),
2438 new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'),
2439 new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
2440 new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
2441 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
2442 new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
2443 new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
2444 new InputArgument('setting-key', null, 'Setting key'),
2445 new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
2446 ))
2447 ->setHelp(<<<EOT
2448 This command allows you to edit composer config settings and repositories
2449 in either the local composer.json file or the global config.json file.
2450
2451 Additionally it lets you edit most properties in the local composer.json.
2452
2453 To set a config setting:
2454
2455     <comment>%command.full_name% bin-dir bin/</comment>
2456
2457 To read a config setting:
2458
2459     <comment>%command.full_name% bin-dir</comment>
2460     Outputs: <info>bin</info>
2461
2462 To edit the global config.json file:
2463
2464     <comment>%command.full_name% --global</comment>
2465
2466 To add a repository:
2467
2468     <comment>%command.full_name% repositories.foo vcs https://bar.com</comment>
2469
2470 To remove a repository (repo is a short alias for repositories):
2471
2472     <comment>%command.full_name% --unset repo.foo</comment>
2473
2474 To disable packagist:
2475
2476     <comment>%command.full_name% repo.packagist false</comment>
2477
2478 You can alter repositories in the global config.json file by passing in the
2479 <info>--global</info> option.
2480
2481 To edit the file in an external editor:
2482
2483     <comment>%command.full_name% --editor</comment>
2484
2485 To choose your editor you can set the "EDITOR" env variable.
2486
2487 To get a list of configuration values in the file:
2488
2489     <comment>%command.full_name% --list</comment>
2490
2491 You can always pass more than one option. As an example, if you want to edit the
2492 global config.json file.
2493
2494     <comment>%command.full_name% --editor --global</comment>
2495 EOT
2496 )
2497 ;
2498 }
2499
2500
2501
2502
2503 protected function initialize(InputInterface $input, OutputInterface $output)
2504 {
2505 parent::initialize($input, $output);
2506
2507 if ($input->getOption('global') && null !== $input->getOption('file')) {
2508 throw new \RuntimeException('--file and --global can not be combined');
2509 }
2510
2511 $io = $this->getIO();
2512 $this->config = Factory::createConfig($io);
2513
2514
2515  
2516  $configFile = $input->getOption('global')
2517 ? ($this->config->get('home') . '/config.json')
2518 : ($input->getOption('file') ?: Factory::getComposerFile());
2519
2520
2521  if (
2522 ($configFile === 'composer.json' || $configFile === './composer.json')
2523 && !file_exists($configFile)
2524 && realpath(getcwd()) === realpath($this->config->get('home'))
2525 ) {
2526 file_put_contents($configFile, "{\n}\n");
2527 }
2528
2529 $this->configFile = new JsonFile($configFile, null, $io);
2530 $this->configSource = new JsonConfigSource($this->configFile);
2531
2532 $authConfigFile = $input->getOption('global')
2533 ? ($this->config->get('home') . '/auth.json')
2534 : dirname(realpath($configFile)) . '/auth.json';
2535
2536 $this->authConfigFile = new JsonFile($authConfigFile, null, $io);
2537 $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
2538
2539
2540  if ($input->getOption('global') && !$this->configFile->exists()) {
2541 touch($this->configFile->getPath());
2542 $this->configFile->write(array('config' => new \ArrayObject));
2543 Silencer::call('chmod', $this->configFile->getPath(), 0600);
2544 }
2545 if ($input->getOption('global') && !$this->authConfigFile->exists()) {
2546 touch($this->authConfigFile->getPath());
2547 $this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject));
2548 Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
2549 }
2550
2551 if (!$this->configFile->exists()) {
2552 throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
2553 }
2554 }
2555
2556
2557
2558
2559 protected function execute(InputInterface $input, OutputInterface $output)
2560 {
2561
2562  if ($input->getOption('editor')) {
2563 $editor = escapeshellcmd(getenv('EDITOR'));
2564 if (!$editor) {
2565 if (Platform::isWindows()) {
2566 $editor = 'notepad';
2567 } else {
2568 foreach (array('editor', 'vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
2569 if (exec('which '.$candidate)) {
2570 $editor = $candidate;
2571 break;
2572 }
2573 }
2574 }
2575 }
2576
2577 $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
2578 system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
2579
2580 return 0;
2581 }
2582
2583 if (!$input->getOption('global')) {
2584 $this->config->merge($this->configFile->read());
2585 $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
2586 }
2587
2588
2589  if ($input->getOption('list')) {
2590 $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
2591
2592 return 0;
2593 }
2594
2595 $settingKey = $input->getArgument('setting-key');
2596 if (!$settingKey) {
2597 return 0;
2598 }
2599
2600
2601  if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
2602 throw new \RuntimeException('You can not combine a setting value with --unset');
2603 }
2604
2605
2606  if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
2607 $properties = array('name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra');
2608 $rawData = $this->configFile->read();
2609 $data = $this->config->all();
2610 if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
2611 if (!isset($matches[1]) || $matches[1] === '') {
2612 $value = isset($data['repositories']) ? $data['repositories'] : array();
2613 } else {
2614 if (!isset($data['repositories'][$matches[1]])) {
2615 throw new \InvalidArgumentException('There is no '.$matches[1].' repository defined');
2616 }
2617
2618 $value = $data['repositories'][$matches[1]];
2619 }
2620 } elseif (strpos($settingKey, '.')) {
2621 $bits = explode('.', $settingKey);
2622 if ($bits[0] === 'extra') {
2623 $data = $rawData;
2624 } else {
2625 $data = $data['config'];
2626 }
2627 $match = false;
2628 foreach ($bits as $bit) {
2629 $key = isset($key) ? $key.'.'.$bit : $bit;
2630 $match = false;
2631 if (isset($data[$key])) {
2632 $match = true;
2633 $data = $data[$key];
2634 unset($key);
2635 }
2636 }
2637
2638 if (!$match) {
2639 throw new \RuntimeException($settingKey.' is not defined.');
2640 }
2641
2642 $value = $data;
2643 } elseif (isset($data['config'][$settingKey])) {
2644 $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
2645 } elseif (in_array($settingKey, $properties, true) && isset($rawData[$settingKey])) {
2646 $value = $rawData[$settingKey];
2647 } else {
2648 throw new \RuntimeException($settingKey.' is not defined');
2649 }
2650
2651 if (is_array($value)) {
2652 $value = json_encode($value);
2653 }
2654
2655 $this->getIO()->write($value);
2656
2657 return 0;
2658 }
2659
2660 $values = $input->getArgument('setting-value'); 
2661
2662 $booleanValidator = function ($val) {
2663 return in_array($val, array('true', 'false', '1', '0'), true);
2664 };
2665 $booleanNormalizer = function ($val) {
2666 return $val !== 'false' && (bool) $val;
2667 };
2668
2669
2670  $uniqueConfigValues = array(
2671 'process-timeout' => array('is_numeric', 'intval'),
2672 'use-include-path' => array($booleanValidator, $booleanNormalizer),
2673 'preferred-install' => array(
2674 function ($val) {
2675 return in_array($val, array('auto', 'source', 'dist'), true);
2676 },
2677 function ($val) {
2678 return $val;
2679 },
2680 ),
2681 'store-auths' => array(
2682 function ($val) {
2683 return in_array($val, array('true', 'false', 'prompt'), true);
2684 },
2685 function ($val) {
2686 if ('prompt' === $val) {
2687 return 'prompt';
2688 }
2689
2690 return $val !== 'false' && (bool) $val;
2691 },
2692 ),
2693 'notify-on-install' => array($booleanValidator, $booleanNormalizer),
2694 'vendor-dir' => array('is_string', function ($val) {
2695 return $val;
2696 }),
2697 'bin-dir' => array('is_string', function ($val) {
2698 return $val;
2699 }),
2700 'archive-dir' => array('is_string', function ($val) {
2701 return $val;
2702 }),
2703 'archive-format' => array('is_string', function ($val) {
2704 return $val;
2705 }),
2706 'data-dir' => array('is_string', function ($val) {
2707 return $val;
2708 }),
2709 'cache-dir' => array('is_string', function ($val) {
2710 return $val;
2711 }),
2712 'cache-files-dir' => array('is_string', function ($val) {
2713 return $val;
2714 }),
2715 'cache-repo-dir' => array('is_string', function ($val) {
2716 return $val;
2717 }),
2718 'cache-vcs-dir' => array('is_string', function ($val) {
2719 return $val;
2720 }),
2721 'cache-ttl' => array('is_numeric', 'intval'),
2722 'cache-files-ttl' => array('is_numeric', 'intval'),
2723 'cache-files-maxsize' => array(
2724 function ($val) {
2725 return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0;
2726 },
2727 function ($val) {
2728 return $val;
2729 },
2730 ),
2731 'bin-compat' => array(
2732 function ($val) {
2733 return in_array($val, array('auto', 'full'));
2734 },
2735 function ($val) {
2736 return $val;
2737 },
2738 ),
2739 'discard-changes' => array(
2740 function ($val) {
2741 return in_array($val, array('stash', 'true', 'false', '1', '0'), true);
2742 },
2743 function ($val) {
2744 if ('stash' === $val) {
2745 return 'stash';
2746 }
2747
2748 return $val !== 'false' && (bool) $val;
2749 },
2750 ),
2751 'autoloader-suffix' => array('is_string', function ($val) {
2752 return $val === 'null' ? null : $val;
2753 }),
2754 'sort-packages' => array($booleanValidator, $booleanNormalizer),
2755 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
2756 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
2757 'apcu-autoloader' => array($booleanValidator, $booleanNormalizer),
2758 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
2759 'disable-tls' => array($booleanValidator, $booleanNormalizer),
2760 'secure-http' => array($booleanValidator, $booleanNormalizer),
2761 'cafile' => array(
2762 function ($val) {
2763 return file_exists($val) && is_readable($val);
2764 },
2765 function ($val) {
2766 return $val === 'null' ? null : $val;
2767 },
2768 ),
2769 'capath' => array(
2770 function ($val) {
2771 return is_dir($val) && is_readable($val);
2772 },
2773 function ($val) {
2774 return $val === 'null' ? null : $val;
2775 },
2776 ),
2777 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
2778 'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
2779 );
2780 $multiConfigValues = array(
2781 'github-protocols' => array(
2782 function ($vals) {
2783 if (!is_array($vals)) {
2784 return 'array expected';
2785 }
2786
2787 foreach ($vals as $val) {
2788 if (!in_array($val, array('git', 'https', 'ssh'))) {
2789 return 'valid protocols include: git, https, ssh';
2790 }
2791 }
2792
2793 return true;
2794 },
2795 function ($vals) {
2796 return $vals;
2797 },
2798 ),
2799 'github-domains' => array(
2800 function ($vals) {
2801 if (!is_array($vals)) {
2802 return 'array expected';
2803 }
2804
2805 return true;
2806 },
2807 function ($vals) {
2808 return $vals;
2809 },
2810 ),
2811 'gitlab-domains' => array(
2812 function ($vals) {
2813 if (!is_array($vals)) {
2814 return 'array expected';
2815 }
2816
2817 return true;
2818 },
2819 function ($vals) {
2820 return $vals;
2821 },
2822 ),
2823 );
2824
2825 if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) {
2826 return $this->configSource->removeConfigSetting($settingKey);
2827 }
2828 if (isset($uniqueConfigValues[$settingKey])) {
2829 return $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
2830 }
2831 if (isset($multiConfigValues[$settingKey])) {
2832 return $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
2833 }
2834
2835
2836  $uniqueProps = array(
2837 'name' => array('is_string', function ($val) {
2838 return $val;
2839 }),
2840 'type' => array('is_string', function ($val) {
2841 return $val;
2842 }),
2843 'description' => array('is_string', function ($val) {
2844 return $val;
2845 }),
2846 'homepage' => array('is_string', function ($val) {
2847 return $val;
2848 }),
2849 'version' => array('is_string', function ($val) {
2850 return $val;
2851 }),
2852 'minimum-stability' => array(
2853 function ($val) {
2854 return isset(BasePackage::$stabilities[VersionParser::normalizeStability($val)]);
2855 },
2856 function ($val) {
2857 return VersionParser::normalizeStability($val);
2858 },
2859 ),
2860 'prefer-stable' => array($booleanValidator, $booleanNormalizer),
2861 );
2862 $multiProps = array(
2863 'keywords' => array(
2864 function ($vals) {
2865 if (!is_array($vals)) {
2866 return 'array expected';
2867 }
2868
2869 return true;
2870 },
2871 function ($vals) {
2872 return $vals;
2873 },
2874 ),
2875 'license' => array(
2876 function ($vals) {
2877 if (!is_array($vals)) {
2878 return 'array expected';
2879 }
2880
2881 return true;
2882 },
2883 function ($vals) {
2884 return $vals;
2885 },
2886 ),
2887 );
2888
2889 if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) {
2890 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');
2891 }
2892 if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
2893 return $this->configSource->removeProperty($settingKey);
2894 }
2895 if (isset($uniqueProps[$settingKey])) {
2896 return $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
2897 }
2898 if (isset($multiProps[$settingKey])) {
2899 return $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
2900 }
2901
2902
2903  if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
2904 if ($input->getOption('unset')) {
2905 return $this->configSource->removeRepository($matches[1]);
2906 }
2907
2908 if (2 === count($values)) {
2909 return $this->configSource->addRepository($matches[1], array(
2910 'type' => $values[0],
2911 'url' => $values[1],
2912 ));
2913 }
2914
2915 if (1 === count($values)) {
2916 $value = strtolower($values[0]);
2917 if (true === $booleanValidator($value)) {
2918 if (false === $booleanNormalizer($value)) {
2919 return $this->configSource->addRepository($matches[1], false);
2920 }
2921 } else {
2922 $value = JsonFile::parseJson($values[0]);
2923
2924 return $this->configSource->addRepository($matches[1], $value);
2925 }
2926 }
2927
2928 throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
2929 }
2930
2931
2932  if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) {
2933 if ($input->getOption('unset')) {
2934 return $this->configSource->removeProperty($settingKey);
2935 }
2936
2937 return $this->configSource->addProperty($settingKey, $values[0]);
2938 }
2939
2940
2941  if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
2942 if ($input->getOption('unset')) {
2943 return $this->configSource->removeConfigSetting($settingKey);
2944 }
2945
2946 return $this->configSource->addConfigSetting($settingKey, $values[0]);
2947 }
2948 if ($settingKey === 'platform' && $input->getOption('unset')) {
2949 return $this->configSource->removeConfigSetting($settingKey);
2950 }
2951
2952
2953  if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic)\.(.+)/', $settingKey, $matches)) {
2954 if ($input->getOption('unset')) {
2955 $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2956 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2957
2958 return;
2959 }
2960
2961 if ($matches[1] === 'bitbucket-oauth') {
2962 if (2 !== count($values)) {
2963 throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got '.count($values));
2964 }
2965 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2966 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
2967 } elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token'), true)) {
2968 if (1 !== count($values)) {
2969 throw new \RuntimeException('Too many arguments, expected only one token');
2970 }
2971 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2972 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], $values[0]);
2973 } elseif ($matches[1] === 'http-basic') {
2974 if (2 !== count($values)) {
2975 throw new \RuntimeException('Expected two arguments (username, password), got '.count($values));
2976 }
2977 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2978 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
2979 }
2980
2981 return;
2982 }
2983
2984 throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
2985 }
2986
2987 protected function handleSingleValue($key, array $callbacks, array $values, $method)
2988 {
2989 list($validator, $normalizer) = $callbacks;
2990 if (1 !== count($values)) {
2991 throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
2992 }
2993
2994 if (true !== $validation = $validator($values[0])) {
2995 throw new \RuntimeException(sprintf(
2996 '"%s" is an invalid value'.($validation ? ' ('.$validation.')' : ''),
2997 $values[0]
2998 ));
2999 }
3000
3001 return call_user_func(array($this->configSource, $method), $key, $normalizer($values[0]));
3002 }
3003
3004 protected function handleMultiValue($key, array $callbacks, array $values, $method)
3005 {
3006 list($validator, $normalizer) = $callbacks;
3007 if (true !== $validation = $validator($values)) {
3008 throw new \RuntimeException(sprintf(
3009 '%s is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3010 json_encode($values)
3011 ));
3012 }
3013
3014 return call_user_func(array($this->configSource, $method), $key, $normalizer($values));
3015 }
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025 protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
3026 {
3027 $origK = $k;
3028 $io = $this->getIO();
3029 foreach ($contents as $key => $value) {
3030 if ($k === null && !in_array($key, array('config', 'repositories'))) {
3031 continue;
3032 }
3033
3034 $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null;
3035
3036 if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
3037 $k .= preg_replace('{^config\.}', '', $key . '.');
3038 $this->listConfiguration($value, $rawVal, $output, $k);
3039 $k = $origK;
3040
3041 continue;
3042 }
3043
3044 if (is_array($value)) {
3045 $value = array_map(function ($val) {
3046 return is_array($val) ? json_encode($val) : $val;
3047 }, $value);
3048
3049 $value = '['.implode(', ', $value).']';
3050 }
3051
3052 if (is_bool($value)) {
3053 $value = var_export($value, true);
3054 }
3055
3056 if (is_string($rawVal) && $rawVal != $value) {
3057 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>');
3058 } else {
3059 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>');
3060 }
3061 }
3062 }
3063 }
3064 <?php
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076 namespace Composer\Command;
3077
3078 use Composer\Config;
3079 use Composer\Factory;
3080 use Composer\Installer;
3081 use Composer\Installer\ProjectInstaller;
3082 use Composer\Installer\InstallationManager;
3083 use Composer\Installer\SuggestedPackagesReporter;
3084 use Composer\IO\IOInterface;
3085 use Composer\Package\BasePackage;
3086 use Composer\DependencyResolver\Pool;
3087 use Composer\DependencyResolver\Operation\InstallOperation;
3088 use Composer\Package\Version\VersionSelector;
3089 use Composer\Package\AliasPackage;
3090 use Composer\Repository\RepositoryFactory;
3091 use Composer\Repository\CompositeRepository;
3092 use Composer\Repository\PlatformRepository;
3093 use Composer\Repository\InstalledFilesystemRepository;
3094 use Composer\Script\ScriptEvents;
3095 use Composer\Util\Silencer;
3096 use Symfony\Component\Console\Input\InputArgument;
3097 use Symfony\Component\Console\Input\InputInterface;
3098 use Symfony\Component\Console\Input\InputOption;
3099 use Symfony\Component\Console\Output\OutputInterface;
3100 use Symfony\Component\Finder\Finder;
3101 use Composer\Json\JsonFile;
3102 use Composer\Config\JsonConfigSource;
3103 use Composer\Util\Filesystem;
3104 use Composer\Package\Version\VersionParser;
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114 class CreateProjectCommand extends BaseCommand
3115 {
3116
3117
3118
3119 protected $suggestedPackagesReporter;
3120
3121 protected function configure()
3122 {
3123 $this
3124 ->setName('create-project')
3125 ->setDescription('Creates new project from a package into given directory.')
3126 ->setDefinition(array(
3127 new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'),
3128 new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'),
3129 new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
3130 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
3131 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
3132 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
3133 new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
3134 new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
3135 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
3136 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
3137 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
3138 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'),
3139 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
3140 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.'),
3141 new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deletion vcs folder.'),
3142 new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
3143 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
3144 ))
3145 ->setHelp(<<<EOT
3146 The <info>create-project</info> command creates a new project from a given
3147 package into a new directory. If executed without params and in a directory
3148 with a composer.json file it installs the packages for the current project.
3149
3150 You can use this command to bootstrap new projects or setup a clean
3151 version-controlled installation for developers of your project.
3152
3153 <info>php composer.phar create-project vendor/project target-directory [version]</info>
3154
3155 You can also specify the version with the package name using = or : as separator.
3156
3157 <info>php composer.phar create-project vendor/project:version target-directory</info>
3158
3159 To install unstable packages, either specify the version you want, or use the
3160 --stability=dev (where dev can be one of RC, beta, alpha or dev).
3161
3162 To setup a developer workable version you should create the project using the source
3163 controlled code by appending the <info>'--prefer-source'</info> flag.
3164
3165 To install a package from another repository than the default one you
3166 can pass the <info>'--repository=https://myrepository.org'</info> flag.
3167
3168 EOT
3169 )
3170 ;
3171 }
3172
3173 protected function execute(InputInterface $input, OutputInterface $output)
3174 {
3175 $config = Factory::createConfig();
3176 $io = $this->getIO();
3177
3178 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input, true);
3179
3180 if ($input->getOption('dev')) {
3181 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
3182 }
3183 if ($input->getOption('no-custom-installers')) {
3184 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
3185 $input->setOption('no-plugins', true);
3186 }
3187
3188 return $this->installProject(
3189 $io,
3190 $config,
3191 $input,
3192 $input->getArgument('package'),
3193 $input->getArgument('directory'),
3194 $input->getArgument('version'),
3195 $input->getOption('stability'),
3196 $preferSource,
3197 $preferDist,
3198 !$input->getOption('no-dev'),
3199 $input->getOption('repository') ?: $input->getOption('repository-url'),
3200 $input->getOption('no-plugins'),
3201 $input->getOption('no-scripts'),
3202 $input->getOption('keep-vcs'),
3203 $input->getOption('no-progress'),
3204 $input->getOption('no-install'),
3205 $input->getOption('ignore-platform-reqs'),
3206 !$input->getOption('no-secure-http')
3207 );
3208 }
3209
3210 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)
3211 {
3212 $oldCwd = getcwd();
3213
3214
3215  $io->loadConfiguration($config);
3216
3217 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
3218
3219 if ($packageName !== null) {
3220 $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $keepVcs, $noProgress, $ignorePlatformReqs, $secureHttp);
3221 } else {
3222 $installedFromVcs = false;
3223 }
3224
3225 $composer = Factory::create($io, null, $disablePlugins);
3226 $composer->getDownloadManager()->setOutputProgress(!$noProgress);
3227
3228 $fs = new Filesystem();
3229
3230 if ($noScripts === false) {
3231
3232  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
3233 }
3234
3235
3236  $config = $composer->getConfig();
3237 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
3238
3239
3240  if ($noInstall === false) {
3241 $installer = Installer::create($io, $composer);
3242 $installer->setPreferSource($preferSource)
3243 ->setPreferDist($preferDist)
3244 ->setDevMode($installDevPackages)
3245 ->setRunScripts(!$noScripts)
3246 ->setIgnorePlatformRequirements($ignorePlatformReqs)
3247 ->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
3248 ->setOptimizeAutoloader($config->get('optimize-autoloader'));
3249
3250 if ($disablePlugins) {
3251 $installer->disablePlugins();
3252 }
3253
3254 $status = $installer->run();
3255 if (0 !== $status) {
3256 return $status;
3257 }
3258 }
3259
3260 $hasVcs = $installedFromVcs;
3261 if (!$keepVcs && $installedFromVcs
3262 && (
3263 !$io->isInteractive()
3264 || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true)
3265 )
3266 ) {
3267 $finder = new Finder();
3268 $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
3269 foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_') as $vcsName) {
3270 $finder->name($vcsName);
3271 }
3272
3273 try {
3274 $dirs = iterator_to_array($finder);
3275 unset($finder);
3276 foreach ($dirs as $dir) {
3277 if (!$fs->removeDirectory($dir)) {
3278 throw new \RuntimeException('Could not remove '.$dir);
3279 }
3280 }
3281 } catch (\Exception $e) {
3282 $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
3283 }
3284
3285 $hasVcs = false;
3286 }
3287
3288
3289  if (!$hasVcs) {
3290 $package = $composer->getPackage();
3291 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3292 foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
3293 foreach ($package->{'get'.$meta['method']}() as $link) {
3294 if ($link->getPrettyConstraint() === 'self.version') {
3295 $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
3296 }
3297 }
3298 }
3299 }
3300
3301 if ($noScripts === false) {
3302
3303  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
3304 }
3305
3306 chdir($oldCwd);
3307 $vendorComposerDir = $config->get('vendor-dir').'/composer';
3308 if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
3309 Silencer::call('rmdir', $vendorComposerDir);
3310 $vendorDir = $config->get('vendor-dir');
3311 if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
3312 Silencer::call('rmdir', $vendorDir);
3313 }
3314 }
3315
3316 return 0;
3317 }
3318
3319 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)
3320 {
3321 if (!$secureHttp) {
3322 $config->merge(array('config' => array('secure-http' => false)));
3323 }
3324
3325 if (null === $repository) {
3326 $sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config));
3327 } else {
3328 $sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true);
3329 }
3330
3331 $parser = new VersionParser();
3332 $requirements = $parser->parseNameVersionPairs(array($packageName));
3333 $name = strtolower($requirements[0]['name']);
3334 if (!$packageVersion && isset($requirements[0]['version'])) {
3335 $packageVersion = $requirements[0]['version'];
3336 }
3337
3338 if (null === $stability) {
3339 if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
3340 $stability = $match[1];
3341 } else {
3342 $stability = VersionParser::parseStability($packageVersion);
3343 }
3344 }
3345
3346 $stability = VersionParser::normalizeStability($stability);
3347
3348 if (!isset(BasePackage::$stabilities[$stability])) {
3349 throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
3350 }
3351
3352 $pool = new Pool($stability);
3353 $pool->addRepository($sourceRepo);
3354
3355 $phpVersion = null;
3356 $prettyPhpVersion = null;
3357 if (!$ignorePlatformReqs) {
3358 $platformOverrides = $config->get('platform') ?: array();
3359
3360  $platform = new PlatformRepository(array(), $platformOverrides);
3361 $phpPackage = $platform->findPackage('php', '*');
3362 $phpVersion = $phpPackage->getVersion();
3363 $prettyPhpVersion = $phpPackage->getPrettyVersion();
3364 }
3365
3366
3367  $versionSelector = new VersionSelector($pool);
3368 $package = $versionSelector->findBestCandidate($name, $packageVersion, $phpVersion, $stability);
3369
3370 if (!$package) {
3371 $errorMessage = "Could not find package $name with " . ($packageVersion ? "version $packageVersion" : "stability $stability");
3372 if ($phpVersion && $versionSelector->findBestCandidate($name, $packageVersion, null, $stability)) {
3373 throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version '.$prettyPhpVersion.'.');
3374 }
3375
3376 throw new \InvalidArgumentException($errorMessage .'.');
3377 }
3378
3379 if (null === $directory) {
3380 $parts = explode("/", $name, 2);
3381 $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
3382 }
3383
3384
3385  if (function_exists('pcntl_signal')) {
3386 declare(ticks=100);
3387 pcntl_signal(SIGINT, function () use ($directory) {
3388 $fs = new Filesystem();
3389 $fs->removeDirectory($directory);
3390 exit(130);
3391 });
3392 }
3393
3394 $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')</info>');
3395
3396 if ($disablePlugins) {
3397 $io->writeError('<info>Plugins have been disabled.</info>');
3398 }
3399
3400 if ($package instanceof AliasPackage) {
3401 $package = $package->getAliasOf();
3402 }
3403
3404 if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) {
3405 $package->setSourceReference(substr($package->getPrettyVersion(), 4));
3406 }
3407
3408 $dm = $this->createDownloadManager($io, $config);
3409 $dm->setPreferSource($preferSource)
3410 ->setPreferDist($preferDist)
3411 ->setOutputProgress(!$noProgress);
3412
3413 $projectInstaller = new ProjectInstaller($directory, $dm);
3414 $im = $this->createInstallationManager();
3415 $im->addInstaller($projectInstaller);
3416 $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
3417 $im->notifyInstalls($io);
3418
3419
3420  $this->suggestedPackagesReporter->addSuggestionsFromPackage($package);
3421
3422 $installedFromVcs = 'source' === $package->getInstallationSource();
3423
3424 $io->writeError('<info>Created project in ' . $directory . '</info>');
3425 chdir($directory);
3426
3427 $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
3428 putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
3429
3430 return $installedFromVcs;
3431 }
3432
3433 protected function createDownloadManager(IOInterface $io, Config $config)
3434 {
3435 $factory = new Factory();
3436
3437 return $factory->createDownloadManager($io, $config);
3438 }
3439
3440 protected function createInstallationManager()
3441 {
3442 return new InstallationManager();
3443 }
3444 }
3445 <?php
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457 namespace Composer\Command;
3458
3459 use Symfony\Component\Console\Input\InputInterface;
3460 use Symfony\Component\Console\Output\OutputInterface;
3461
3462
3463
3464
3465 class DependsCommand extends BaseDependencyCommand
3466 {
3467
3468
3469
3470 protected function configure()
3471 {
3472 parent::configure();
3473
3474 $this
3475 ->setName('depends')
3476 ->setAliases(array('why'))
3477 ->setDescription('Shows which packages cause the given package to be installed.')
3478 ->setHelp(<<<EOT
3479 Displays detailed information about where a package is referenced.
3480
3481 <info>php composer.phar depends composer/composer</info>
3482
3483 EOT
3484 )
3485 ;
3486 }
3487
3488
3489
3490
3491
3492
3493
3494
3495 protected function execute(InputInterface $input, OutputInterface $output)
3496 {
3497 return parent::doExecute($input, $output, false);
3498 }
3499 }
3500 <?php
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512 namespace Composer\Command;
3513
3514 use Composer\Composer;
3515 use Composer\Factory;
3516 use Composer\Config;
3517 use Composer\Downloader\TransportException;
3518 use Composer\Plugin\CommandEvent;
3519 use Composer\Plugin\PluginEvents;
3520 use Composer\Util\ConfigValidator;
3521 use Composer\Util\IniHelper;
3522 use Composer\Util\ProcessExecutor;
3523 use Composer\Util\RemoteFilesystem;
3524 use Composer\Util\StreamContextFactory;
3525 use Composer\SelfUpdate\Keys;
3526 use Composer\SelfUpdate\Versions;
3527 use Composer\IO\NullIO;
3528 use Symfony\Component\Console\Input\InputInterface;
3529 use Symfony\Component\Console\Output\OutputInterface;
3530
3531
3532
3533
3534 class DiagnoseCommand extends BaseCommand
3535 {
3536
3537 protected $rfs;
3538
3539
3540 protected $process;
3541
3542
3543 protected $exitCode = 0;
3544
3545 protected function configure()
3546 {
3547 $this
3548 ->setName('diagnose')
3549 ->setDescription('Diagnoses the system to identify common errors.')
3550 ->setHelp(<<<EOT
3551 The <info>diagnose</info> command checks common errors to help debugging problems.
3552
3553 The process exit code will be 1 in case of warnings and 2 for errors.
3554
3555 EOT
3556 )
3557 ;
3558 }
3559
3560
3561
3562
3563 protected function execute(InputInterface $input, OutputInterface $output)
3564 {
3565 $composer = $this->getComposer(false);
3566 $io = $this->getIO();
3567
3568 if ($composer) {
3569 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
3570 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
3571
3572 $io->write('Checking composer.json: ', false);
3573 $this->outputResult($this->checkComposerSchema());
3574 }
3575
3576 if ($composer) {
3577 $config = $composer->getConfig();
3578 } else {
3579 $config = Factory::createConfig();
3580 }
3581
3582 $config->merge(array('config' => array('secure-http' => false)));
3583 $config->prohibitUrlByConfig('http://packagist.org', new NullIO);
3584
3585 $this->rfs = Factory::createRemoteFilesystem($io, $config);
3586 $this->process = new ProcessExecutor($io);
3587
3588 $io->write('Checking platform settings: ', false);
3589 $this->outputResult($this->checkPlatform());
3590
3591 $io->write('Checking git settings: ', false);
3592 $this->outputResult($this->checkGit());
3593
3594 $io->write('Checking http connectivity to packagist: ', false);
3595 $this->outputResult($this->checkHttp('http', $config));
3596
3597 $io->write('Checking https connectivity to packagist: ', false);
3598 $this->outputResult($this->checkHttp('https', $config));
3599
3600 $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
3601 if (!empty($opts['http']['proxy'])) {
3602 $io->write('Checking HTTP proxy: ', false);
3603 $this->outputResult($this->checkHttpProxy());
3604 $io->write('Checking HTTP proxy support for request_fulluri: ', false);
3605 $this->outputResult($this->checkHttpProxyFullUriRequestParam());
3606 $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
3607 $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
3608 }
3609
3610 if ($oauth = $config->get('github-oauth')) {
3611 foreach ($oauth as $domain => $token) {
3612 $io->write('Checking '.$domain.' oauth access: ', false);
3613 $this->outputResult($this->checkGithubOauth($domain, $token));
3614 }
3615 } else {
3616 $io->write('Checking github.com rate limit: ', false);
3617 try {
3618 $rate = $this->getGithubRateLimit('github.com');
3619 $this->outputResult(true);
3620 if (10 > $rate['remaining']) {
3621 $io->write('<warning>WARNING</warning>');
3622 $io->write(sprintf(
3623 '<comment>Github has a rate limit on their API. '
3624 . 'You currently have <options=bold>%u</options=bold> '
3625 . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
3626 . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
3627 . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>',
3628 $rate['remaining'],
3629 $rate['limit']
3630 ));
3631 }
3632 } catch (\Exception $e) {
3633 if ($e instanceof TransportException && $e->getCode() === 401) {
3634 $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
3635 } else {
3636 $this->outputResult($e);
3637 }
3638 }
3639 }
3640
3641 $io->write('Checking disk free space: ', false);
3642 $this->outputResult($this->checkDiskSpace($config));
3643
3644 if ('phar:' === substr(__FILE__, 0, 5)) {
3645 $io->write('Checking pubkeys: ', false);
3646 $this->outputResult($this->checkPubKeys($config));
3647
3648 $io->write('Checking composer version: ', false);
3649 $this->outputResult($this->checkVersion($config));
3650 }
3651
3652 $io->write(sprintf('Composer version: <comment>%s</comment>', Composer::VERSION));
3653
3654 $io->write(sprintf('PHP version: <comment>%s</comment>', PHP_VERSION));
3655
3656 if (defined('PHP_BINARY')) {
3657 $io->write(sprintf('PHP binary path: <comment>%s</comment>', PHP_BINARY));
3658 }
3659
3660 return $this->exitCode;
3661 }
3662
3663 private function checkComposerSchema()
3664 {
3665 $validator = new ConfigValidator($this->getIO());
3666 list($errors, , $warnings) = $validator->validate(Factory::getComposerFile());
3667
3668 if ($errors || $warnings) {
3669 $messages = array(
3670 'error' => $errors,
3671 'warning' => $warnings,
3672 );
3673
3674 $output = '';
3675 foreach ($messages as $style => $msgs) {
3676 foreach ($msgs as $msg) {
3677 $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . PHP_EOL;
3678 }
3679 }
3680
3681 return rtrim($output);
3682 }
3683
3684 return true;
3685 }
3686
3687 private function checkGit()
3688 {
3689 $this->process->execute('git config color.ui', $output);
3690 if (strtolower(trim($output)) === 'always') {
3691 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>';
3692 }
3693
3694 return true;
3695 }
3696
3697 private function checkHttp($proto, Config $config)
3698 {
3699 $disableTls = false;
3700 $result = array();
3701 if ($proto === 'https' && $config->get('disable-tls') === true) {
3702 $disableTls = true;
3703 $result[] = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
3704 }
3705 if ($proto === 'https' && !extension_loaded('openssl') && !$disableTls) {
3706 $result[] = '<error>Composer is configured to use SSL/TLS protection but the openssl extension is not available.</error>';
3707 }
3708
3709 try {
3710 $this->rfs->getContents('packagist.org', $proto . '://packagist.org/packages.json', false);
3711 } catch (TransportException $e) {
3712 if (false !== strpos($e->getMessage(), 'cafile')) {
3713 $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
3714 $result[] = '<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>';
3715 $result[] = '<error>You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option.</error>';
3716 } else {
3717 array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage());
3718 }
3719 }
3720
3721 if (count($result) > 0) {
3722 return $result;
3723 }
3724
3725 return true;
3726 }
3727
3728 private function checkHttpProxy()
3729 {
3730 $protocol = extension_loaded('openssl') ? 'https' : 'http';
3731 try {
3732 $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://packagist.org/packages.json', false), true);
3733 $hash = reset($json['provider-includes']);
3734 $hash = $hash['sha256'];
3735 $path = str_replace('%hash%', $hash, key($json['provider-includes']));
3736 $provider = $this->rfs->getContents('packagist.org', $protocol . '://packagist.org/'.$path, false);
3737
3738 if (hash('sha256', $provider) !== $hash) {
3739 return 'It seems that your proxy is modifying http traffic on the fly';
3740 }
3741 } catch (\Exception $e) {
3742 return $e;
3743 }
3744
3745 return true;
3746 }
3747
3748
3749
3750
3751
3752
3753
3754
3755 private function checkHttpProxyFullUriRequestParam()
3756 {
3757 $url = 'http://packagist.org/packages.json';
3758 try {
3759 $this->rfs->getContents('packagist.org', $url, false);
3760 } catch (TransportException $e) {
3761 try {
3762 $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
3763 } catch (TransportException $e) {
3764 return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
3765 }
3766
3767 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"';
3768 }
3769
3770 return true;
3771 }
3772
3773
3774
3775
3776
3777
3778
3779
3780 private function checkHttpsProxyFullUriRequestParam()
3781 {
3782 if (!extension_loaded('openssl')) {
3783 return 'You need the openssl extension installed for this check';
3784 }
3785
3786 $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
3787 try {
3788 $this->rfs->getContents('github.com', $url, false);
3789 } catch (TransportException $e) {
3790 try {
3791 $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
3792 } catch (TransportException $e) {
3793 return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
3794 }
3795
3796 return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
3797 }
3798
3799 return true;
3800 }
3801
3802 private function checkGithubOauth($domain, $token)
3803 {
3804 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3805 try {
3806 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
3807
3808 return $this->rfs->getContents($domain, $url, false, array(
3809 'retry-auth-failure' => false,
3810 )) ? true : 'Unexpected error';
3811 } catch (\Exception $e) {
3812 if ($e instanceof TransportException && $e->getCode() === 401) {
3813 return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
3814 }
3815
3816 return $e;
3817 }
3818 }
3819
3820
3821
3822
3823
3824
3825
3826 private function getGithubRateLimit($domain, $token = null)
3827 {
3828 if ($token) {
3829 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3830 }
3831
3832 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
3833 $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
3834 $data = json_decode($json, true);
3835
3836 return $data['resources']['core'];
3837 }
3838
3839 private function checkDiskSpace($config)
3840 {
3841 $minSpaceFree = 1024 * 1024;
3842 if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
3843 || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
3844 ) {
3845 return '<error>The disk hosting '.$dir.' is full</error>';
3846 }
3847
3848 return true;
3849 }
3850
3851 private function checkPubKeys($config)
3852 {
3853 $home = $config->get('home');
3854 $errors = array();
3855 $io = $this->getIO();
3856
3857 if (file_exists($home.'/keys.tags.pub') && file_exists($home.'/keys.dev.pub')) {
3858 $io->write('');
3859 }
3860
3861 if (file_exists($home.'/keys.tags.pub')) {
3862 $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.tags.pub'));
3863 } else {
3864 $errors[] = '<error>Missing pubkey for tags verification</error>';
3865 }
3866
3867 if (file_exists($home.'/keys.dev.pub')) {
3868 $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.dev.pub'));
3869 } else {
3870 $errors[] = '<error>Missing pubkey for dev verification</error>';
3871 }
3872
3873 if ($errors) {
3874 $errors[] = '<error>Run composer self-update --update-keys to set them up</error>';
3875 }
3876
3877 return $errors ?: true;
3878 }
3879
3880 private function checkVersion($config)
3881 {
3882 $versionsUtil = new Versions($config, $this->rfs);
3883 $latest = $versionsUtil->getLatest();
3884
3885 if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
3886 return '<comment>You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')</comment>';
3887 }
3888
3889 return true;
3890 }
3891
3892
3893
3894
3895 private function outputResult($result)
3896 {
3897 $io = $this->getIO();
3898 if (true === $result) {
3899 $io->write('<info>OK</info>');
3900
3901 return;
3902 }
3903
3904 $hadError = false;
3905 if ($result instanceof \Exception) {
3906 $result = '<error>['.get_class($result).'] '.$result->getMessage().'</error>';
3907 }
3908
3909 if (!$result) {
3910
3911  $hadError = true;
3912 } else {
3913 if (!is_array($result)) {
3914 $result = array($result);
3915 }
3916 foreach ($result as $message) {
3917 if (false !== strpos($message, '<error>')) {
3918 $hadError = true;
3919 }
3920 }
3921 }
3922
3923 if ($hadError) {
3924 $io->write('<error>FAIL</error>');
3925 $this->exitCode = 2;
3926 } else {
3927 $io->write('<warning>WARNING</warning>');
3928 $this->exitCode = 1;
3929 }
3930
3931 if ($result) {
3932 foreach ($result as $message) {
3933 $io->write($message);
3934 }
3935 }
3936 }
3937
3938 private function checkPlatform()
3939 {
3940 $output = '';
3941 $out = function ($msg, $style) use (&$output) {
3942 $output .= '<'.$style.'>'.$msg.'</'.$style.'>'.PHP_EOL;
3943 };
3944
3945
3946  $errors = array();
3947 $warnings = array();
3948 $displayIniMessage = false;
3949
3950 $iniMessage = PHP_EOL.PHP_EOL.IniHelper::getMessage();
3951 $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.';
3952
3953 if (!function_exists('json_decode')) {
3954 $errors['json'] = true;
3955 }
3956
3957 if (!extension_loaded('Phar')) {
3958 $errors['phar'] = true;
3959 }
3960
3961 if (!extension_loaded('filter')) {
3962 $errors['filter'] = true;
3963 }
3964
3965 if (!extension_loaded('hash')) {
3966 $errors['hash'] = true;
3967 }
3968
3969 if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
3970 $errors['iconv_mbstring'] = true;
3971 }
3972
3973 if (!ini_get('allow_url_fopen')) {
3974 $errors['allow_url_fopen'] = true;
3975 }
3976
3977 if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
3978 $errors['ioncube'] = ioncube_loader_version();
3979 }
3980
3981 if (PHP_VERSION_ID < 50302) {
3982 $errors['php'] = PHP_VERSION;
3983 }
3984
3985 if (!isset($errors['php']) && PHP_VERSION_ID < 50304) {
3986 $warnings['php'] = PHP_VERSION;
3987 }
3988
3989 if (!extension_loaded('openssl')) {
3990 $errors['openssl'] = true;
3991 }
3992
3993 if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) {
3994 $warnings['openssl_version'] = true;
3995 }
3996
3997 if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) {
3998 $warnings['apc_cli'] = true;
3999 }
4000
4001 if (!extension_loaded('zlib')) {
4002 $warnings['zlib'] = true;
4003 }
4004
4005 ob_start();
4006 phpinfo(INFO_GENERAL);
4007 $phpinfo = ob_get_clean();
4008 if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
4009 $configure = $match[1];
4010
4011 if (false !== strpos($configure, '--enable-sigchild')) {
4012 $warnings['sigchild'] = true;
4013 }
4014
4015 if (false !== strpos($configure, '--with-curlwrappers')) {
4016 $warnings['curlwrappers'] = true;
4017 }
4018 }
4019
4020 if (ini_get('xdebug.profiler_enabled')) {
4021 $warnings['xdebug_profile'] = true;
4022 } elseif (extension_loaded('xdebug')) {
4023 $warnings['xdebug_loaded'] = true;
4024 }
4025
4026 if (!empty($errors)) {
4027 foreach ($errors as $error => $current) {
4028 switch ($error) {
4029 case 'json':
4030 $text = PHP_EOL."The json extension is missing.".PHP_EOL;
4031 $text .= "Install it or recompile php without --disable-json";
4032 break;
4033
4034 case 'phar':
4035 $text = PHP_EOL."The phar extension is missing.".PHP_EOL;
4036 $text .= "Install it or recompile php without --disable-phar";
4037 break;
4038
4039 case 'filter':
4040 $text = PHP_EOL."The filter extension is missing.".PHP_EOL;
4041 $text .= "Install it or recompile php without --disable-filter";
4042 break;
4043
4044 case 'hash':
4045 $text = PHP_EOL."The hash extension is missing.".PHP_EOL;
4046 $text .= "Install it or recompile php without --disable-hash";
4047 break;
4048
4049 case 'iconv_mbstring':
4050 $text = PHP_EOL."The iconv OR mbstring extension is required and both are missing.".PHP_EOL;
4051 $text .= "Install either of them or recompile php without --disable-iconv";
4052 break;
4053
4054 case 'unicode':
4055 $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
4056 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4057 $text .= "    detect_unicode = Off";
4058 $displayIniMessage = true;
4059 break;
4060
4061 case 'suhosin':
4062 $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
4063 $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;
4064 $text .= "    suhosin.executor.include.whitelist = phar ".$current;
4065 $displayIniMessage = true;
4066 break;
4067
4068 case 'php':
4069 $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
4070 break;
4071
4072 case 'allow_url_fopen':
4073 $text = PHP_EOL."The allow_url_fopen setting is incorrect.".PHP_EOL;
4074 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4075 $text .= "    allow_url_fopen = On";
4076 $displayIniMessage = true;
4077 break;
4078
4079 case 'ioncube':
4080 $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
4081 $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;
4082 $text .= "    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
4083 $displayIniMessage = true;
4084 break;
4085
4086 case 'openssl':
4087 $text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
4088 $text .= "If possible you should enable it or recompile php with --with-openssl";
4089 break;
4090 }
4091 $out($text, 'error');
4092 }
4093
4094 $output .= PHP_EOL;
4095 }
4096
4097 if (!empty($warnings)) {
4098 foreach ($warnings as $warning => $current) {
4099 switch ($warning) {
4100 case 'apc_cli':
4101 $text = "The apc.enable_cli setting is incorrect.".PHP_EOL;
4102 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4103 $text .= "  apc.enable_cli = Off";
4104 $displayIniMessage = true;
4105 break;
4106
4107 case 'zlib':
4108 $text = 'The zlib extension is not loaded, this can slow down Composer a lot.'.PHP_EOL;
4109 $text .= 'If possible, enable it or recompile php with --with-zlib'.PHP_EOL;
4110 $displayIniMessage = true;
4111 break;
4112
4113 case 'sigchild':
4114 $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms.".PHP_EOL;
4115 $text .= "Recompile it without this flag if possible, see also:".PHP_EOL;
4116 $text .= "  https://bugs.php.net/bug.php?id=22999";
4117 break;
4118
4119 case 'curlwrappers':
4120 $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.".PHP_EOL;
4121 $text .= " Recompile it without this flag if possible";
4122 break;
4123
4124 case 'php':
4125 $text = "Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL;
4126 $text .= " Composer works with 5.3.2+ for most people, but there might be edge case issues.";
4127 break;
4128
4129 case 'openssl_version':
4130
4131  $opensslVersion = strstr(trim(strstr(OPENSSL_VERSION_TEXT, ' ')), ' ', true);
4132 $opensslVersion = $opensslVersion ?: OPENSSL_VERSION_TEXT;
4133
4134 $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1.".PHP_EOL;
4135 $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above.";
4136 break;
4137
4138 case 'xdebug_loaded':
4139 $text = "The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL;
4140 $text .= " Disabling it when using Composer is recommended.";
4141 break;
4142
4143 case 'xdebug_profile':
4144 $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL;
4145 $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL;
4146 $text .= "  xdebug.profiler_enabled = 0";
4147 $displayIniMessage = true;
4148 break;
4149 }
4150 $out($text, 'comment');
4151 }
4152 }
4153
4154 if ($displayIniMessage) {
4155 $out($iniMessage, 'comment');
4156 }
4157
4158 return !$warnings && !$errors ? true : $output;
4159 }
4160 }
4161 <?php
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173 namespace Composer\Command;
4174
4175 use Composer\Plugin\CommandEvent;
4176 use Composer\Plugin\PluginEvents;
4177 use Symfony\Component\Console\Input\InputInterface;
4178 use Symfony\Component\Console\Input\InputOption;
4179 use Symfony\Component\Console\Output\OutputInterface;
4180
4181
4182
4183
4184 class DumpAutoloadCommand extends BaseCommand
4185 {
4186 protected function configure()
4187 {
4188 $this
4189 ->setName('dump-autoload')
4190 ->setAliases(array('dumpautoload'))
4191 ->setDescription('Dumps the autoloader.')
4192 ->setDefinition(array(
4193 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
4194 new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
4195 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
4196 new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
4197 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
4198 ))
4199 ->setHelp(<<<EOT
4200 <info>php composer.phar dump-autoload</info>
4201 EOT
4202 )
4203 ;
4204 }
4205
4206 protected function execute(InputInterface $input, OutputInterface $output)
4207 {
4208 $composer = $this->getComposer();
4209
4210 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
4211 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
4212
4213 $installationManager = $composer->getInstallationManager();
4214 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
4215 $package = $composer->getPackage();
4216 $config = $composer->getConfig();
4217
4218 $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
4219 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
4220 $apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
4221
4222 if ($authoritative) {
4223 $this->getIO()->writeError('<info>Generating optimized autoload files (authoritative)</info>');
4224 } elseif ($optimize) {
4225 $this->getIO()->writeError('<info>Generating optimized autoload files</info>');
4226 } else {
4227 $this->getIO()->writeError('<info>Generating autoload files</info>');
4228 }
4229
4230 $generator = $composer->getAutoloadGenerator();
4231 $generator->setDevMode(!$input->getOption('no-dev'));
4232 $generator->setClassMapAuthoritative($authoritative);
4233 $generator->setApcu($apcu);
4234 $generator->setRunScripts(!$input->getOption('no-scripts'));
4235 $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
4236 }
4237 }
4238 <?php
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250 namespace Composer\Command;
4251
4252 use Symfony\Component\Console\Input\InputInterface;
4253 use Symfony\Component\Console\Input\InputOption;
4254 use Symfony\Component\Console\Output\OutputInterface;
4255 use Symfony\Component\Console\Input\InputArgument;
4256
4257
4258
4259
4260 class ExecCommand extends BaseCommand
4261 {
4262 protected function configure()
4263 {
4264 $this
4265 ->setName('exec')
4266 ->setDescription('Executes a vendored binary/script.')
4267 ->setDefinition(array(
4268 new InputOption('list', 'l', InputOption::VALUE_NONE),
4269 new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit'),
4270 new InputArgument(
4271 'args',
4272 InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
4273 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
4274 ),
4275 ))
4276 ;
4277 }
4278
4279 protected function execute(InputInterface $input, OutputInterface $output)
4280 {
4281 $composer = $this->getComposer();
4282 $binDir = $composer->getConfig()->get('bin-dir');
4283 if ($input->getOption('list') || !$input->getArgument('binary')) {
4284 $bins = glob($binDir . '/*');
4285 $bins = array_merge($bins, array_map(function ($e) {
4286 return "$e (local)";
4287 }, $composer->getPackage()->getBinaries()));
4288
4289 if (!$bins) {
4290 throw new \RuntimeException("No binaries found in composer.json or in bin-dir ($binDir)");
4291 }
4292
4293 $this->getIO()->write(<<<EOT
4294 <comment>Available binaries:</comment>
4295 EOT
4296 );
4297
4298 foreach ($bins as $bin) {
4299
4300  if (isset($previousBin) && $bin === $previousBin.'.bat') {
4301 continue;
4302 }
4303
4304 $previousBin = $bin;
4305 $bin = basename($bin);
4306 $this->getIO()->write(<<<EOT
4307 <info>- $bin</info>
4308 EOT
4309 );
4310 }
4311
4312 return 0;
4313 }
4314
4315 $binary = $input->getArgument('binary');
4316
4317 $dispatcher = $composer->getEventDispatcher();
4318 $dispatcher->addListener('__exec_command', $binary);
4319 if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
4320 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
4321 }
4322
4323 return $dispatcher->dispatchScript('__exec_command', true, $input->getArgument('args'));
4324 }
4325 }
4326 <?php
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338 namespace Composer\Command;
4339
4340 use Composer\Factory;
4341 use Symfony\Component\Console\Input\InputInterface;
4342 use Symfony\Component\Console\Input\InputArgument;
4343 use Symfony\Component\Console\Input\StringInput;
4344 use Symfony\Component\Console\Output\OutputInterface;
4345
4346
4347
4348
4349 class GlobalCommand extends BaseCommand
4350 {
4351 protected function configure()
4352 {
4353 $this
4354 ->setName('global')
4355 ->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME).')
4356 ->setDefinition(array(
4357 new InputArgument('command-name', InputArgument::REQUIRED, ''),
4358 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
4359 ))
4360 ->setHelp(<<<EOT
4361 Use this command as a wrapper to run other Composer commands
4362 within the global context of COMPOSER_HOME.
4363
4364 You can use this to install CLI utilities globally, all you need
4365 is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.
4366
4367 COMPOSER_HOME is c:\Users\<user>\AppData\Roaming\Composer on Windows
4368 and /home/<user>/.composer on unix systems.
4369
4370 If your system uses freedesktop.org standards, then it will first check
4371 XDG_CONFIG_HOME or default to /home/<user>/.config/composer
4372
4373 Note: This path may vary depending on customizations to bin-dir in
4374 composer.json or the environmental variable COMPOSER_BIN_DIR.
4375
4376 EOT
4377 )
4378 ;
4379 }
4380
4381 public function run(InputInterface $input, OutputInterface $output)
4382 {
4383
4384  $tokens = preg_split('{\s+}', $input->__toString());
4385 $args = array();
4386 foreach ($tokens as $token) {
4387 if ($token && $token[0] !== '-') {
4388 $args[] = $token;
4389 if (count($args) >= 2) {
4390 break;
4391 }
4392 }
4393 }
4394
4395
4396  if (count($args) < 2) {
4397 return parent::run($input, $output);
4398 }
4399
4400
4401  $config = Factory::createConfig();
4402 chdir($config->get('home'));
4403 $this->getIO()->writeError('<info>Changed current directory to '.$config->get('home').'</info>');
4404
4405
4406  $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
4407 $this->getApplication()->resetComposer();
4408
4409 return $this->getApplication()->run($input, $output);
4410 }
4411
4412
4413
4414
4415 public function isProxyCommand()
4416 {
4417 return true;
4418 }
4419 }
4420 <?php
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432 namespace Composer\Command;
4433
4434 use Composer\Package\CompletePackageInterface;
4435 use Composer\Repository\RepositoryInterface;
4436 use Composer\Repository\ArrayRepository;
4437 use Composer\Repository\RepositoryFactory;
4438 use Composer\Util\Platform;
4439 use Composer\Util\ProcessExecutor;
4440 use Symfony\Component\Console\Input\InputArgument;
4441 use Symfony\Component\Console\Input\InputOption;
4442 use Symfony\Component\Console\Input\InputInterface;
4443 use Symfony\Component\Console\Output\OutputInterface;
4444
4445
4446
4447
4448 class HomeCommand extends BaseCommand
4449 {
4450
4451
4452
4453 protected function configure()
4454 {
4455 $this
4456 ->setName('browse')
4457 ->setAliases(array('home'))
4458 ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
4459 ->setDefinition(array(
4460 new InputArgument('packages', InputArgument::IS_ARRAY, 'Package(s) to browse to.'),
4461 new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
4462 new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
4463 ))
4464 ->setHelp(<<<EOT
4465 The home command opens or shows a package's repository URL or
4466 homepage in your default browser.
4467
4468 To open the homepage by default, use -H or --homepage.
4469 To show instead of open the repository or homepage URL, use -s or --show.
4470 EOT
4471 );
4472 }
4473
4474
4475
4476
4477 protected function execute(InputInterface $input, OutputInterface $output)
4478 {
4479 $repos = $this->initializeRepos();
4480 $io = $this->getIO();
4481 $return = 0;
4482
4483 $packages = $input->getArgument('packages');
4484 if (!$packages) {
4485 $io->writeError('No package specified, opening homepage for the root package');
4486 $packages = array($this->getComposer()->getPackage()->getName());
4487 }
4488
4489 foreach ($packages as $packageName) {
4490 $handled = false;
4491 $packageExists = false;
4492 foreach ($repos as $repo) {
4493 foreach ($repo->findPackages($packageName) as $package) {
4494 $packageExists = true;
4495 if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
4496 $handled = true;
4497 break 2;
4498 }
4499 }
4500 }
4501
4502 if (!$packageExists) {
4503 $return = 1;
4504 $io->writeError('<warning>Package '.$packageName.' not found</warning>');
4505 }
4506
4507 if (!$handled) {
4508 $return = 1;
4509 $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
4510 }
4511 }
4512
4513 return $return;
4514 }
4515
4516 private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
4517 {
4518 $support = $package->getSupport();
4519 $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
4520 if (!$url || $showHomepage) {
4521 $url = $package->getHomepage();
4522 }
4523
4524 if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
4525 return false;
4526 }
4527
4528 if ($showOnly) {
4529 $this->getIO()->write(sprintf('<info>%s</info>', $url));
4530 } else {
4531 $this->openBrowser($url);
4532 }
4533
4534 return true;
4535 }
4536
4537
4538
4539
4540
4541
4542 private function openBrowser($url)
4543 {
4544 $url = ProcessExecutor::escape($url);
4545
4546 $process = new ProcessExecutor($this->getIO());
4547 if (Platform::isWindows()) {
4548 return $process->execute('start "web" explorer "' . $url . '"', $output);
4549 }
4550
4551 $linux = $process->execute('which xdg-open', $output);
4552 $osx = $process->execute('which open', $output);
4553
4554 if (0 === $linux) {
4555 $process->execute('xdg-open ' . $url, $output);
4556 } elseif (0 === $osx) {
4557 $process->execute('open ' . $url, $output);
4558 } else {
4559 $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
4560 }
4561 }
4562
4563
4564
4565
4566
4567
4568
4569
4570 private function initializeRepos()
4571 {
4572 $composer = $this->getComposer(false);
4573
4574 if ($composer) {
4575 return array_merge(
4576 array(new ArrayRepository(array($composer->getPackage()))), 
4577  array($composer->getRepositoryManager()->getLocalRepository()), 
4578  $composer->getRepositoryManager()->getRepositories() 
4579  );
4580 }
4581
4582 return RepositoryFactory::defaultRepos($this->getIO());
4583 }
4584 }
4585 <?php
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597 namespace Composer\Command;
4598
4599 use Composer\DependencyResolver\Pool;
4600 use Composer\Factory;
4601 use Composer\Json\JsonFile;
4602 use Composer\Package\BasePackage;
4603 use Composer\Package\Version\VersionParser;
4604 use Composer\Package\Version\VersionSelector;
4605 use Composer\Repository\CompositeRepository;
4606 use Composer\Repository\PlatformRepository;
4607 use Composer\Repository\RepositoryFactory;
4608 use Composer\Util\ProcessExecutor;
4609 use Symfony\Component\Console\Input\InputInterface;
4610 use Symfony\Component\Console\Input\InputOption;
4611 use Symfony\Component\Console\Output\OutputInterface;
4612 use Symfony\Component\Process\ExecutableFinder;
4613 use Symfony\Component\Process\Process;
4614
4615
4616
4617
4618
4619 class InitCommand extends BaseCommand
4620 {
4621
4622 protected $repos;
4623
4624
4625 private $gitConfig;
4626
4627
4628 private $pools;
4629
4630
4631
4632
4633 protected function configure()
4634 {
4635 $this
4636 ->setName('init')
4637 ->setDescription('Creates a basic composer.json file in current directory.')
4638 ->setDefinition(array(
4639 new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
4640 new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
4641 new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
4642
4643  new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of package (e.g. library, project, metapackage, composer-plugin)'),
4644 new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
4645 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"'),
4646 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"'),
4647 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
4648 new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
4649 new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
4650 ))
4651 ->setHelp(<<<EOT
4652 The <info>init</info> command creates a basic composer.json file
4653 in the current directory.
4654
4655 <info>php composer.phar init</info>
4656
4657 EOT
4658 )
4659 ;
4660 }
4661
4662
4663
4664
4665 protected function execute(InputInterface $input, OutputInterface $output)
4666 {
4667 $io = $this->getIO();
4668
4669 $whitelist = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license');
4670 $options = array_filter(array_intersect_key($input->getOptions(), array_flip($whitelist)));
4671
4672 if (isset($options['author'])) {
4673 $options['authors'] = $this->formatAuthors($options['author']);
4674 unset($options['author']);
4675 }
4676
4677 $repositories = $input->getOption('repository');
4678 if ($repositories) {
4679 $config = Factory::createConfig($io);
4680 foreach ($repositories as $repo) {
4681 $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
4682 }
4683 }
4684
4685 if (isset($options['stability'])) {
4686 $options['minimum-stability'] = $options['stability'];
4687 unset($options['stability']);
4688 }
4689
4690 $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass;
4691 if (array() === $options['require']) {
4692 $options['require'] = new \stdClass;
4693 }
4694
4695 if (isset($options['require-dev'])) {
4696 $options['require-dev'] = $this->formatRequirements($options['require-dev']);
4697 if (array() === $options['require-dev']) {
4698 $options['require-dev'] = new \stdClass;
4699 }
4700 }
4701
4702 $file = new JsonFile(Factory::getComposerFile());
4703 $json = $file->encode($options);
4704
4705 if ($input->isInteractive()) {
4706 $io->writeError(array('', $json, ''));
4707 if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
4708 $io->writeError('<error>Command aborted</error>');
4709
4710 return 1;
4711 }
4712 }
4713
4714 $file->write($options);
4715
4716 if ($input->isInteractive() && is_dir('.git')) {
4717 $ignoreFile = realpath('.gitignore');
4718
4719 if (false === $ignoreFile) {
4720 $ignoreFile = realpath('.') . '/.gitignore';
4721 }
4722
4723 if (!$this->hasVendorIgnore($ignoreFile)) {
4724 $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
4725
4726 if ($io->askConfirmation($question, true)) {
4727 $this->addVendorIgnore($ignoreFile);
4728 }
4729 }
4730 }
4731 }
4732
4733
4734
4735
4736 protected function interact(InputInterface $input, OutputInterface $output)
4737 {
4738 $git = $this->getGitConfig();
4739 $io = $this->getIO();
4740 $formatter = $this->getHelperSet()->get('formatter');
4741
4742
4743  $repositories = $input->getOption('repository');
4744 if ($repositories) {
4745 $config = Factory::createConfig($io);
4746 $repos = array(new PlatformRepository);
4747 foreach ($repositories as $repo) {
4748 $repos[] = RepositoryFactory::fromString($io, $config, $repo);
4749 }
4750 $repos[] = RepositoryFactory::createRepo($io, $config, array(
4751 'type' => 'composer',
4752 'url' => 'https://packagist.org',
4753 ));
4754
4755 $this->repos = new CompositeRepository($repos);
4756 unset($repos, $config, $repositories);
4757 }
4758
4759 $io->writeError(array(
4760 '',
4761 $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
4762 '',
4763 ));
4764
4765
4766  $io->writeError(array(
4767 '',
4768 'This command will guide you through creating your composer.json config.',
4769 '',
4770 ));
4771
4772 $cwd = realpath(".");
4773
4774 if (!$name = $input->getOption('name')) {
4775 $name = basename($cwd);
4776 $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
4777 $name = strtolower($name);
4778 if (!empty($_SERVER['COMPOSER_DEFAULT_VENDOR'])) {
4779 $name = $_SERVER['COMPOSER_DEFAULT_VENDOR'] . '/' . $name;
4780 } elseif (isset($git['github.user'])) {
4781 $name = $git['github.user'] . '/' . $name;
4782 } elseif (!empty($_SERVER['USERNAME'])) {
4783 $name = $_SERVER['USERNAME'] . '/' . $name;
4784 } elseif (!empty($_SERVER['USER'])) {
4785 $name = $_SERVER['USER'] . '/' . $name;
4786 } elseif (get_current_user()) {
4787 $name = get_current_user() . '/' . $name;
4788 } else {
4789
4790  $name = $name . '/' . $name;
4791 }
4792 $name = strtolower($name);
4793 } else {
4794 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $name)) {
4795 throw new \InvalidArgumentException(
4796 '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_.-]+'
4797 );
4798 }
4799 }
4800
4801 $name = $io->askAndValidate(
4802 'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
4803 function ($value) use ($name) {
4804 if (null === $value) {
4805 return $name;
4806 }
4807
4808 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $value)) {
4809 throw new \InvalidArgumentException(
4810 '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_.-]+'
4811 );
4812 }
4813
4814 return $value;
4815 },
4816 null,
4817 $name
4818 );
4819 $input->setOption('name', $name);
4820
4821 $description = $input->getOption('description') ?: false;
4822 $description = $io->ask(
4823 'Description [<comment>'.$description.'</comment>]: ',
4824 $description
4825 );
4826 $input->setOption('description', $description);
4827
4828 if (null === $author = $input->getOption('author')) {
4829 if (!empty($_SERVER['COMPOSER_DEFAULT_AUTHOR'])) {
4830 $author_name = $_SERVER['COMPOSER_DEFAULT_AUTHOR'];
4831 } elseif (isset($git['user.name'])) {
4832 $author_name = $git['user.name'];
4833 }
4834
4835 if (!empty($_SERVER['COMPOSER_DEFAULT_EMAIL'])) {
4836 $author_email = $_SERVER['COMPOSER_DEFAULT_EMAIL'];
4837 } elseif (isset($git['user.email'])) {
4838 $author_email = $git['user.email'];
4839 }
4840
4841 if (isset($author_name) && isset($author_email)) {
4842 $author = sprintf('%s <%s>', $author_name, $author_email);
4843 }
4844 }
4845
4846 $self = $this;
4847 $author = $io->askAndValidate(
4848 'Author [<comment>'.$author.'</comment>, n to skip]: ',
4849 function ($value) use ($self, $author) {
4850 if ($value === 'n' || $value === 'no') {
4851 return;
4852 }
4853 $value = $value ?: $author;
4854 $author = $self->parseAuthorString($value);
4855
4856 return sprintf('%s <%s>', $author['name'], $author['email']);
4857 },
4858 null,
4859 $author
4860 );
4861 $input->setOption('author', $author);
4862
4863 $minimumStability = $input->getOption('stability') ?: null;
4864 $minimumStability = $io->askAndValidate(
4865 'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
4866 function ($value) use ($self, $minimumStability) {
4867 if (null === $value) {
4868 return $minimumStability;
4869 }
4870
4871 if (!isset(BasePackage::$stabilities[$value])) {
4872 throw new \InvalidArgumentException(
4873 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
4874 implode(', ', array_keys(BasePackage::$stabilities))
4875 );
4876 }
4877
4878 return $value;
4879 },
4880 null,
4881 $minimumStability
4882 );
4883 $input->setOption('stability', $minimumStability);
4884
4885 $type = $input->getOption('type') ?: false;
4886 $type = $io->ask(
4887 'Package Type (e.g. library, project, metapackage, composer-plugin) [<comment>'.$type.'</comment>]: ',
4888 $type
4889 );
4890 $input->setOption('type', $type);
4891
4892 if (null === $license = $input->getOption('license')) {
4893 if (!empty($_SERVER['COMPOSER_DEFAULT_LICENSE'])) {
4894 $license = $_SERVER['COMPOSER_DEFAULT_LICENSE'];
4895 }
4896 }
4897
4898 $license = $io->ask(
4899 'License [<comment>'.$license.'</comment>]: ',
4900 $license
4901 );
4902 $input->setOption('license', $license);
4903
4904 $io->writeError(array('', 'Define your dependencies.', ''));
4905
4906 $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
4907 $require = $input->getOption('require');
4908 $requirements = array();
4909 if ($require || $io->askConfirmation($question, true)) {
4910 $requirements = $this->determineRequirements($input, $output, $require);
4911 }
4912 $input->setOption('require', $requirements);
4913
4914 $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
4915 $requireDev = $input->getOption('require-dev');
4916 $devRequirements = array();
4917 if ($requireDev || $io->askConfirmation($question, true)) {
4918 $devRequirements = $this->determineRequirements($input, $output, $requireDev);
4919 }
4920 $input->setOption('require-dev', $devRequirements);
4921 }
4922
4923
4924
4925
4926
4927
4928 public function parseAuthorString($author)
4929 {
4930 if (preg_match('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P<email>.+?)>$/u', $author, $match)) {
4931 if ($this->isValidEmail($match['email'])) {
4932 return array(
4933 'name' => trim($match['name']),
4934 'email' => $match['email'],
4935 );
4936 }
4937 }
4938
4939 throw new \InvalidArgumentException(
4940 'Invalid author string.  Must be in the format: '.
4941 'John Smith <john@example.com>'
4942 );
4943 }
4944
4945 protected function findPackages($name)
4946 {
4947 return $this->getRepos()->search($name);
4948 }
4949
4950 protected function getRepos()
4951 {
4952 if (!$this->repos) {
4953 $this->repos = new CompositeRepository(array_merge(
4954 array(new PlatformRepository),
4955 RepositoryFactory::defaultRepos($this->getIO())
4956 ));
4957 }
4958
4959 return $this->repos;
4960 }
4961
4962 protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable')
4963 {
4964 if ($requires) {
4965 $requires = $this->normalizeRequirements($requires);
4966 $result = array();
4967 $io = $this->getIO();
4968
4969 foreach ($requires as $requirement) {
4970 if (!isset($requirement['version'])) {
4971
4972  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability);
4973 $requirement['version'] = $version;
4974
4975
4976  $requirement['name'] = $name;
4977
4978 $io->writeError(sprintf(
4979 'Using version <info>%s</info> for <info>%s</info>',
4980 $requirement['version'],
4981 $requirement['name']
4982 ));
4983 } else {
4984
4985  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $requirement['version'], 'dev');
4986
4987
4988  $requirement['name'] = $name;
4989 }
4990
4991 $result[] = $requirement['name'] . ' ' . $requirement['version'];
4992 }
4993
4994 return $result;
4995 }
4996
4997 $versionParser = new VersionParser();
4998 $io = $this->getIO();
4999 while (null !== $package = $io->ask('Search for a package: ')) {
5000 $matches = $this->findPackages($package);
5001
5002 if (count($matches)) {
5003 $exactMatch = null;
5004 $choices = array();
5005 foreach ($matches as $position => $foundPackage) {
5006 $abandoned = '';
5007 if (isset($foundPackage['abandoned'])) {
5008 if (is_string($foundPackage['abandoned'])) {
5009 $replacement = sprintf('Use %s instead', $foundPackage['abandoned']);
5010 } else {
5011 $replacement = 'No replacement was suggested';
5012 }
5013 $abandoned = sprintf('<warning>Abandoned. %s.</warning>', $replacement);
5014 }
5015
5016 $choices[] = sprintf(' <info>%5s</info> %s %s', "[$position]", $foundPackage['name'], $abandoned);
5017 if ($foundPackage['name'] === $package) {
5018 $exactMatch = true;
5019 break;
5020 }
5021 }
5022
5023
5024  if (!$exactMatch) {
5025 $io->writeError(array(
5026 '',
5027 sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
5028 '',
5029 ));
5030
5031 $io->writeError($choices);
5032 $io->writeError('');
5033
5034 $validator = function ($selection) use ($matches, $versionParser) {
5035 if ('' === $selection) {
5036 return false;
5037 }
5038
5039 if (is_numeric($selection) && isset($matches[(int) $selection])) {
5040 $package = $matches[(int) $selection];
5041
5042 return $package['name'];
5043 }
5044
5045 if (preg_match('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
5046 if (isset($packageMatches['version'])) {
5047
5048
5049
5050  $versionParser->parseConstraints($packageMatches['version']);
5051
5052 return $packageMatches['name'].' '.$packageMatches['version'];
5053 }
5054
5055
5056  return $packageMatches['name'];
5057 }
5058
5059 throw new \Exception('Not a valid selection');
5060 };
5061
5062 $package = $io->askAndValidate(
5063 'Enter package # to add, or the complete package name if it is not listed: ',
5064 $validator,
5065 3,
5066 false
5067 );
5068 }
5069
5070
5071  if (false !== $package && false === strpos($package, ' ')) {
5072 $validator = function ($input) {
5073 $input = trim($input);
5074
5075 return $input ?: false;
5076 };
5077
5078 $constraint = $io->askAndValidate(
5079 'Enter the version constraint to require (or leave blank to use the latest version): ',
5080 $validator,
5081 3,
5082 false
5083 );
5084
5085 if (false === $constraint) {
5086 list($name, $constraint) = $this->findBestVersionAndNameForPackage($input, $package, $phpVersion, $preferredStability);
5087
5088 $io->writeError(sprintf(
5089 'Using version <info>%s</info> for <info>%s</info>',
5090 $constraint,
5091 $package
5092 ));
5093 }
5094
5095 $package .= ' '.$constraint;
5096 }
5097
5098 if (false !== $package) {
5099 $requires[] = $package;
5100 }
5101 }
5102 }
5103
5104 return $requires;
5105 }
5106
5107 protected function formatAuthors($author)
5108 {
5109 return array($this->parseAuthorString($author));
5110 }
5111
5112 protected function formatRequirements(array $requirements)
5113 {
5114 $requires = array();
5115 $requirements = $this->normalizeRequirements($requirements);
5116 foreach ($requirements as $requirement) {
5117 $requires[$requirement['name']] = $requirement['version'];
5118 }
5119
5120 return $requires;
5121 }
5122
5123 protected function getGitConfig()
5124 {
5125 if (null !== $this->gitConfig) {
5126 return $this->gitConfig;
5127 }
5128
5129 $finder = new ExecutableFinder();
5130 $gitBin = $finder->find('git');
5131
5132 $cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
5133 $cmd->run();
5134
5135 if ($cmd->isSuccessful()) {
5136 $this->gitConfig = array();
5137 preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER);
5138 foreach ($matches as $match) {
5139 $this->gitConfig[$match[1]] = $match[2];
5140 }
5141
5142 return $this->gitConfig;
5143 }
5144
5145 return $this->gitConfig = array();
5146 }
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164 protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
5165 {
5166 if (!file_exists($ignoreFile)) {
5167 return false;
5168 }
5169
5170 $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
5171
5172 $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES);
5173 foreach ($lines as $line) {
5174 if (preg_match($pattern, $line)) {
5175 return true;
5176 }
5177 }
5178
5179 return false;
5180 }
5181
5182 protected function normalizeRequirements(array $requirements)
5183 {
5184 $parser = new VersionParser();
5185
5186 return $parser->parseNameVersionPairs($requirements);
5187 }
5188
5189 protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
5190 {
5191 $contents = "";
5192 if (file_exists($ignoreFile)) {
5193 $contents = file_get_contents($ignoreFile);
5194
5195 if ("\n" !== substr($contents, 0, -1)) {
5196 $contents .= "\n";
5197 }
5198 }
5199
5200 file_put_contents($ignoreFile, $contents . $vendor. "\n");
5201 }
5202
5203 protected function isValidEmail($email)
5204 {
5205
5206  if (!function_exists('filter_var')) {
5207 return true;
5208 }
5209
5210
5211  if (PHP_VERSION_ID < 50303) {
5212 return true;
5213 }
5214
5215 return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
5216 }
5217
5218 private function getPool(InputInterface $input, $minimumStability = null)
5219 {
5220 $key = $minimumStability ?: 'default';
5221
5222 if (!isset($this->pools[$key])) {
5223 $this->pools[$key] = $pool = new Pool($minimumStability ?: $this->getMinimumStability($input));
5224 $pool->addRepository($this->getRepos());
5225 }
5226
5227 return $this->pools[$key];
5228 }
5229
5230 private function getMinimumStability(InputInterface $input)
5231 {
5232 if ($input->hasOption('stability')) {
5233 return $input->getOption('stability') ?: 'stable';
5234 }
5235
5236 $file = Factory::getComposerFile();
5237 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
5238 if (!empty($composer['minimum-stability'])) {
5239 return $composer['minimum-stability'];
5240 }
5241 }
5242
5243 return 'stable';
5244 }
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260 private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null)
5261 {
5262
5263  $versionSelector = new VersionSelector($this->getPool($input, $minimumStability));
5264 $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
5265
5266
5267  if ($input->hasOption('ignore-platform-reqs') && $input->getOption('ignore-platform-reqs')) {
5268 $phpVersion = null;
5269 $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
5270 }
5271
5272 if (!$package) {
5273
5274  if ($phpVersion && $versionSelector->findBestCandidate($name, $requiredVersion, null, $preferredStability)) {
5275 throw new \InvalidArgumentException(sprintf(
5276 'Package %s at version %s has a PHP requirement incompatible with your PHP version (%s)', $name, $requiredVersion, $phpVersion
5277 ));
5278 }
5279
5280  if ($requiredVersion && $versionSelector->findBestCandidate($name, null, $phpVersion, $preferredStability)) {
5281 throw new \InvalidArgumentException(sprintf(
5282 'Could not find package %s in a version matching %s', $name, $requiredVersion
5283 ));
5284 }
5285
5286  if ($phpVersion && $versionSelector->findBestCandidate($name)) {
5287 throw new \InvalidArgumentException(sprintf(
5288 'Could not find package %s in any version matching your PHP version (%s)', $name, $phpVersion
5289 ));
5290 }
5291
5292 $similar = $this->findSimilar($name);
5293 if ($similar) {
5294 throw new \InvalidArgumentException(sprintf(
5295 "Could not find package %s.\n\nDid you mean " . (count($similar) > 1 ? 'one of these' : 'this') . "?\n    %s",
5296 $name,
5297 implode("\n    ", $similar)
5298 ));
5299 }
5300
5301 throw new \InvalidArgumentException(sprintf(
5302 '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).',
5303 $name,
5304 $this->getMinimumStability($input)
5305 ));
5306 }
5307
5308 return array(
5309 $package->getPrettyName(),
5310 $versionSelector->findRecommendedRequireVersion($package)
5311 );
5312 }
5313
5314 private function findSimilar($package)
5315 {
5316 try {
5317 $results = $this->repos->search($package);
5318 } catch (\Exception $e) {
5319
5320  return array();
5321 }
5322 $similarPackages = array();
5323
5324 foreach ($results as $result) {
5325 $similarPackages[$result['name']] = levenshtein($package, $result['name']);
5326 }
5327 asort($similarPackages);
5328
5329 return array_keys(array_slice($similarPackages, 0, 5));
5330 }
5331 }
5332 <?php
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344 namespace Composer\Command;
5345
5346 use Composer\Installer;
5347 use Composer\Plugin\CommandEvent;
5348 use Composer\Plugin\PluginEvents;
5349 use Symfony\Component\Console\Input\InputInterface;
5350 use Symfony\Component\Console\Input\InputOption;
5351 use Symfony\Component\Console\Input\InputArgument;
5352 use Symfony\Component\Console\Output\OutputInterface;
5353
5354
5355
5356
5357
5358
5359
5360 class InstallCommand extends BaseCommand
5361 {
5362 protected function configure()
5363 {
5364 $this
5365 ->setName('install')
5366 ->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
5367 ->setDefinition(array(
5368 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5369 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5370 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
5371 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
5372 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
5373 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
5374 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
5375 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5376 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5377 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5378 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
5379 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5380 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5381 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5382 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5383 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
5384 ))
5385 ->setHelp(<<<EOT
5386 The <info>install</info> command reads the composer.lock file from
5387 the current directory, processes it, and downloads and installs all the
5388 libraries and dependencies outlined in that file. If the file does not
5389 exist it will look for composer.json and do the same.
5390
5391 <info>php composer.phar install</info>
5392
5393 EOT
5394 )
5395 ;
5396 }
5397
5398 protected function execute(InputInterface $input, OutputInterface $output)
5399 {
5400 $io = $this->getIO();
5401 if ($args = $input->getArgument('packages')) {
5402 $io->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
5403
5404 return 1;
5405 }
5406
5407 if ($input->getOption('no-custom-installers')) {
5408 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
5409 $input->setOption('no-plugins', true);
5410 }
5411
5412 if ($input->getOption('dev')) {
5413 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
5414 }
5415
5416 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5417 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5418
5419 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
5420 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5421
5422 $install = Installer::create($io, $composer);
5423
5424 $config = $composer->getConfig();
5425 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
5426
5427 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
5428 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
5429 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
5430
5431 $install
5432 ->setDryRun($input->getOption('dry-run'))
5433 ->setVerbose($input->getOption('verbose'))
5434 ->setPreferSource($preferSource)
5435 ->setPreferDist($preferDist)
5436 ->setDevMode(!$input->getOption('no-dev'))
5437 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
5438 ->setRunScripts(!$input->getOption('no-scripts'))
5439 ->setSkipSuggest($input->getOption('no-suggest'))
5440 ->setOptimizeAutoloader($optimize)
5441 ->setClassMapAuthoritative($authoritative)
5442 ->setApcuAutoloader($apcu)
5443 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5444 ;
5445
5446 if ($input->getOption('no-plugins')) {
5447 $install->disablePlugins();
5448 }
5449
5450 return $install->run();
5451 }
5452 }
5453 <?php
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465 namespace Composer\Command;
5466
5467 use Composer\Json\JsonFile;
5468 use Composer\Plugin\CommandEvent;
5469 use Composer\Plugin\PluginEvents;
5470 use Composer\Package\PackageInterface;
5471 use Composer\Repository\RepositoryInterface;
5472 use Symfony\Component\Console\Helper\Table;
5473 use Symfony\Component\Console\Input\InputInterface;
5474 use Symfony\Component\Console\Input\InputOption;
5475 use Symfony\Component\Console\Output\OutputInterface;
5476
5477
5478
5479
5480 class LicensesCommand extends BaseCommand
5481 {
5482 protected function configure()
5483 {
5484 $this
5485 ->setName('licenses')
5486 ->setDescription('Shows information about licenses of dependencies.')
5487 ->setDefinition(array(
5488 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5489 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
5490 ))
5491 ->setHelp(<<<EOT
5492 The license command displays detailed information about the licenses of
5493 the installed dependencies.
5494
5495 EOT
5496 )
5497 ;
5498 }
5499
5500 protected function execute(InputInterface $input, OutputInterface $output)
5501 {
5502 $composer = $this->getComposer();
5503
5504 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
5505 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5506
5507 $root = $composer->getPackage();
5508 $repo = $composer->getRepositoryManager()->getLocalRepository();
5509
5510 if ($input->getOption('no-dev')) {
5511 $packages = $this->filterRequiredPackages($repo, $root);
5512 } else {
5513 $packages = $this->appendPackages($repo->getPackages(), array());
5514 }
5515
5516 ksort($packages);
5517 $io = $this->getIO();
5518
5519 switch ($format = $input->getOption('format')) {
5520 case 'text':
5521 $io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
5522 $io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
5523 $io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
5524 $io->write('Dependencies:');
5525 $io->write('');
5526
5527 $table = new Table($output);
5528 $table->setStyle('compact');
5529 $table->getStyle()->setVerticalBorderChar('');
5530 $table->getStyle()->setCellRowContentFormat('%s  ');
5531 $table->setHeaders(array('Name', 'Version', 'License'));
5532 foreach ($packages as $package) {
5533 $table->addRow(array(
5534 $package->getPrettyName(),
5535 $package->getFullPrettyVersion(),
5536 implode(', ', $package->getLicense()) ?: 'none',
5537 ));
5538 }
5539 $table->render();
5540 break;
5541
5542 case 'json':
5543 $dependencies = array();
5544 foreach ($packages as $package) {
5545 $dependencies[$package->getPrettyName()] = array(
5546 'version' => $package->getFullPrettyVersion(),
5547 'license' => $package->getLicense(),
5548 );
5549 }
5550
5551 $io->write(JsonFile::encode(array(
5552 'name' => $root->getPrettyName(),
5553 'version' => $root->getFullPrettyVersion(),
5554 'license' => $root->getLicense(),
5555 'dependencies' => $dependencies,
5556 )));
5557 break;
5558
5559 default:
5560 throw new \RuntimeException(sprintf('Unsupported format "%s".  See help for supported formats.', $format));
5561 }
5562 }
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572 private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
5573 {
5574 $requires = array_keys($package->getRequires());
5575
5576 $packageListNames = array_keys($bucket);
5577 $packages = array_filter(
5578 $repo->getPackages(),
5579 function ($package) use ($requires, $packageListNames) {
5580 return in_array($package->getName(), $requires) && !in_array($package->getName(), $packageListNames);
5581 }
5582 );
5583
5584 $bucket = $this->appendPackages($packages, $bucket);
5585
5586 foreach ($packages as $package) {
5587 $bucket = $this->filterRequiredPackages($repo, $package, $bucket);
5588 }
5589
5590 return $bucket;
5591 }
5592
5593
5594
5595
5596
5597
5598
5599
5600 public function appendPackages(array $packages, array $bucket)
5601 {
5602 foreach ($packages as $package) {
5603 $bucket[$package->getName()] = $package;
5604 }
5605
5606 return $bucket;
5607 }
5608 }
5609 <?php
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621 namespace Composer\Command;
5622
5623 use Symfony\Component\Console\Input\InputInterface;
5624 use Symfony\Component\Console\Input\InputArgument;
5625 use Symfony\Component\Console\Input\ArrayInput;
5626 use Symfony\Component\Console\Input\InputOption;
5627 use Symfony\Component\Console\Output\OutputInterface;
5628
5629
5630
5631
5632 class OutdatedCommand extends ShowCommand
5633 {
5634 protected function configure()
5635 {
5636 $this
5637 ->setName('outdated')
5638 ->setDescription('Shows a list of installed packages that have updates available, including their latest version.')
5639 ->setDefinition(array(
5640 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
5641 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'),
5642 new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'),
5643 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
5644 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
5645 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
5646 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5647 ))
5648 ->setHelp(<<<EOT
5649 The outdated command is just a proxy for `composer show -l`
5650
5651 The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:
5652
5653 - <info>green</info> (=): Dependency is in the latest version and is up to date.
5654 - <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
5655   compatibility breaks according to semver, so upgrade when you can but it
5656   may involve work.
5657 - <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
5658
5659
5660 EOT
5661 )
5662 ;
5663 }
5664
5665 protected function execute(InputInterface $input, OutputInterface $output)
5666 {
5667 $args = array(
5668 'show',
5669 '--latest' => true,
5670 );
5671 if (!$input->getOption('all')) {
5672 $args['--outdated'] = true;
5673 }
5674 if ($input->getOption('direct')) {
5675 $args['--direct'] = true;
5676 }
5677 if ($input->getArgument('package')) {
5678 $args['package'] = $input->getArgument('package');
5679 }
5680 if ($input->getOption('strict')) {
5681 $args['--strict'] = true;
5682 }
5683 if ($input->getOption('minor-only')) {
5684 $args['--minor-only'] = true;
5685 }
5686 $args['--format'] = $input->getOption('format');
5687
5688 $input = new ArrayInput($args);
5689
5690 return $this->getApplication()->run($input, $output);
5691 }
5692
5693
5694
5695
5696 public function isProxyCommand()
5697 {
5698 return true;
5699 }
5700 }
5701 <?php
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713 namespace Composer\Command;
5714
5715 use Symfony\Component\Console\Input\InputInterface;
5716 use Symfony\Component\Console\Output\OutputInterface;
5717
5718
5719
5720
5721 class ProhibitsCommand extends BaseDependencyCommand
5722 {
5723
5724
5725
5726 protected function configure()
5727 {
5728 parent::configure();
5729
5730 $this
5731 ->setName('prohibits')
5732 ->setAliases(array('why-not'))
5733 ->setDescription('Shows which packages prevent the given package from being installed.')
5734 ->setHelp(<<<EOT
5735 Displays detailed information about why a package cannot be installed.
5736
5737 <info>php composer.phar prohibits composer/composer</info>
5738
5739 EOT
5740 )
5741 ;
5742 }
5743
5744
5745
5746
5747
5748
5749
5750
5751 protected function execute(InputInterface $input, OutputInterface $output)
5752 {
5753 return parent::doExecute($input, $output, true);
5754 }
5755 }
5756 <?php
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768 namespace Composer\Command;
5769
5770 use Composer\Config\JsonConfigSource;
5771 use Composer\Installer;
5772 use Composer\Plugin\CommandEvent;
5773 use Composer\Plugin\PluginEvents;
5774 use Composer\Json\JsonFile;
5775 use Composer\Factory;
5776 use Symfony\Component\Console\Input\InputInterface;
5777 use Symfony\Component\Console\Input\InputOption;
5778 use Symfony\Component\Console\Input\InputArgument;
5779 use Symfony\Component\Console\Output\OutputInterface;
5780
5781
5782
5783
5784
5785 class RemoveCommand extends BaseCommand
5786 {
5787 protected function configure()
5788 {
5789 $this
5790 ->setName('remove')
5791 ->setDescription('Removes a package from the require or require-dev.')
5792 ->setDefinition(array(
5793 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
5794 new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
5795 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5796 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
5797 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5798 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
5799 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
5800 new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
5801 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5802 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5803 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5804 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5805 ))
5806 ->setHelp(<<<EOT
5807 The <info>remove</info> command removes a package from the current
5808 list of installed packages
5809
5810 <info>php composer.phar remove</info>
5811
5812 EOT
5813 )
5814 ;
5815 }
5816
5817 protected function execute(InputInterface $input, OutputInterface $output)
5818 {
5819 $packages = $input->getArgument('packages');
5820 $packages = array_map('strtolower', $packages);
5821
5822 $file = Factory::getComposerFile();
5823
5824 $jsonFile = new JsonFile($file);
5825 $composer = $jsonFile->read();
5826 $composerBackup = file_get_contents($jsonFile->getPath());
5827
5828 $json = new JsonConfigSource($jsonFile);
5829
5830 $type = $input->getOption('dev') ? 'require-dev' : 'require';
5831 $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
5832 $io = $this->getIO();
5833
5834 if ($input->getOption('update-with-dependencies')) {
5835 $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>');
5836 }
5837
5838
5839  foreach (array('require', 'require-dev') as $linkType) {
5840 if (isset($composer[$linkType])) {
5841 foreach ($composer[$linkType] as $name => $version) {
5842 $composer[$linkType][strtolower($name)] = $name;
5843 }
5844 }
5845 }
5846
5847 foreach ($packages as $package) {
5848 if (isset($composer[$type][$package])) {
5849 $json->removeLink($type, $composer[$type][$package]);
5850 } elseif (isset($composer[$altType][$package])) {
5851 $io->writeError('<warning>'.$composer[$altType][$package].' could not be found in '.$type.' but it is present in '.$altType.'</warning>');
5852 if ($io->isInteractive()) {
5853 if ($io->askConfirmation('Do you want to remove it from '.$altType.' [<comment>yes</comment>]? ', true)) {
5854 $json->removeLink($altType, $composer[$altType][$package]);
5855 }
5856 }
5857 } else {
5858 $io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
5859 }
5860 }
5861
5862 if ($input->getOption('no-update')) {
5863 return 0;
5864 }
5865
5866
5867  $this->resetComposer();
5868 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5869 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5870
5871 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
5872 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5873
5874 $install = Installer::create($io, $composer);
5875
5876 $updateDevMode = !$input->getOption('update-no-dev');
5877 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
5878 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
5879 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
5880
5881 $install
5882 ->setVerbose($input->getOption('verbose'))
5883 ->setDevMode($updateDevMode)
5884 ->setOptimizeAutoloader($optimize)
5885 ->setClassMapAuthoritative($authoritative)
5886 ->setApcuAutoloader($apcu)
5887 ->setUpdate(true)
5888 ->setUpdateWhitelist($packages)
5889 ->setWhitelistTransitiveDependencies(!$input->getOption('no-update-with-dependencies'))
5890 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5891 ->setRunScripts(!$input->getOption('no-scripts'))
5892 ;
5893
5894 $status = $install->run();
5895 if ($status !== 0) {
5896 $io->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
5897 file_put_contents($jsonFile->getPath(), $composerBackup);
5898 }
5899
5900 return $status;
5901 }
5902 }
5903 <?php
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915 namespace Composer\Command;
5916
5917 use Symfony\Component\Console\Input\InputInterface;
5918 use Symfony\Component\Console\Input\InputArgument;
5919 use Symfony\Component\Console\Input\InputOption;
5920 use Symfony\Component\Console\Output\OutputInterface;
5921 use Composer\Factory;
5922 use Composer\Installer;
5923 use Composer\Json\JsonFile;
5924 use Composer\Json\JsonManipulator;
5925 use Composer\Package\Version\VersionParser;
5926 use Composer\Plugin\CommandEvent;
5927 use Composer\Plugin\PluginEvents;
5928 use Composer\Repository\CompositeRepository;
5929 use Composer\Repository\PlatformRepository;
5930
5931
5932
5933
5934
5935 class RequireCommand extends InitCommand
5936 {
5937 protected function configure()
5938 {
5939 $this
5940 ->setName('require')
5941 ->setDescription('Adds required packages to your composer.json and installs them.')
5942 ->setDefinition(array(
5943 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"'),
5944 new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
5945 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5946 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5947 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5948 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5949 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
5950 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5951 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
5952 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
5953 new InputOption('update-with-all-dependencies', null, InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
5954 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5955 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
5956 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
5957 new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
5958 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5959 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5960 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5961 ))
5962 ->setHelp(<<<EOT
5963 The require command adds required packages to your composer.json and installs them.
5964
5965 If you do not specify a package, composer will prompt you to search for a package, and given results, provide a list of 
5966 matches to require.
5967
5968 If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.
5969
5970 If you do not want to install the new dependencies immediately you can call it with --no-update
5971
5972 EOT
5973 )
5974 ;
5975 }
5976
5977 protected function execute(InputInterface $input, OutputInterface $output)
5978 {
5979 $file = Factory::getComposerFile();
5980 $io = $this->getIO();
5981
5982 $newlyCreated = !file_exists($file);
5983 if ($newlyCreated && !file_put_contents($file, "{\n}\n")) {
5984 $io->writeError('<error>'.$file.' could not be created.</error>');
5985
5986 return 1;
5987 }
5988 if (!is_readable($file)) {
5989 $io->writeError('<error>'.$file.' is not readable.</error>');
5990
5991 return 1;
5992 }
5993 if (!is_writable($file)) {
5994 $io->writeError('<error>'.$file.' is not writable.</error>');
5995
5996 return 1;
5997 }
5998
5999 if (filesize($file) === 0) {
6000 file_put_contents($file, "{\n}\n");
6001 }
6002
6003 $json = new JsonFile($file);
6004 $composerBackup = file_get_contents($json->getPath());
6005
6006 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6007 $repos = $composer->getRepositoryManager()->getRepositories();
6008
6009 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6010
6011  $this->repos = new CompositeRepository(array_merge(
6012 array(new PlatformRepository(array(), $platformOverrides)),
6013 $repos
6014 ));
6015
6016 if ($composer->getPackage()->getPreferStable()) {
6017 $preferredStability = 'stable';
6018 } else {
6019 $preferredStability = $composer->getPackage()->getMinimumStability();
6020 }
6021
6022 $phpVersion = $this->repos->findPackage('php', '*')->getPrettyVersion();
6023 $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability);
6024
6025 $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
6026 $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
6027 $requirements = $this->formatRequirements($requirements);
6028
6029
6030  $versionParser = new VersionParser();
6031 foreach ($requirements as $constraint) {
6032 $versionParser->parseConstraints($constraint);
6033 }
6034
6035 $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
6036
6037 if (!$this->updateFileCleanly($json, $requirements, $requireKey, $removeKey, $sortPackages)) {
6038 $composerDefinition = $json->read();
6039 foreach ($requirements as $package => $version) {
6040 $composerDefinition[$requireKey][$package] = $version;
6041 unset($composerDefinition[$removeKey][$package]);
6042 }
6043 $json->write($composerDefinition);
6044 }
6045
6046 $io->writeError('<info>'.$file.' has been '.($newlyCreated ? 'created' : 'updated').'</info>');
6047
6048 if ($input->getOption('no-update')) {
6049 return 0;
6050 }
6051 $updateDevMode = !$input->getOption('update-no-dev');
6052 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6053 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6054 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6055
6056
6057  $this->resetComposer();
6058 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6059 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6060
6061 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
6062 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6063
6064 $install = Installer::create($io, $composer);
6065
6066 $install
6067 ->setVerbose($input->getOption('verbose'))
6068 ->setPreferSource($input->getOption('prefer-source'))
6069 ->setPreferDist($input->getOption('prefer-dist'))
6070 ->setDevMode($updateDevMode)
6071 ->setRunScripts(!$input->getOption('no-scripts'))
6072 ->setSkipSuggest($input->getOption('no-suggest'))
6073 ->setOptimizeAutoloader($optimize)
6074 ->setClassMapAuthoritative($authoritative)
6075 ->setApcuAutoloader($apcu)
6076 ->setUpdate(true)
6077 ->setUpdateWhitelist(array_keys($requirements))
6078 ->setWhitelistTransitiveDependencies($input->getOption('update-with-dependencies'))
6079 ->setWhitelistAllDependencies($input->getOption('update-with-all-dependencies'))
6080 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6081 ->setPreferStable($input->getOption('prefer-stable'))
6082 ->setPreferLowest($input->getOption('prefer-lowest'))
6083 ;
6084
6085 $status = $install->run();
6086 if ($status !== 0) {
6087 if ($newlyCreated) {
6088 $io->writeError("\n".'<error>Installation failed, deleting '.$file.'.</error>');
6089 unlink($json->getPath());
6090 } else {
6091 $io->writeError("\n".'<error>Installation failed, reverting '.$file.' to its original content.</error>');
6092 file_put_contents($json->getPath(), $composerBackup);
6093 }
6094 }
6095
6096 return $status;
6097 }
6098
6099 private function updateFileCleanly($json, array $new, $requireKey, $removeKey, $sortPackages)
6100 {
6101 $contents = file_get_contents($json->getPath());
6102
6103 $manipulator = new JsonManipulator($contents);
6104
6105 foreach ($new as $package => $constraint) {
6106 if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
6107 return false;
6108 }
6109 if (!$manipulator->removeSubNode($removeKey, $package)) {
6110 return false;
6111 }
6112 }
6113
6114 file_put_contents($json->getPath(), $manipulator->getContents());
6115
6116 return true;
6117 }
6118
6119 protected function interact(InputInterface $input, OutputInterface $output)
6120 {
6121 return;
6122 }
6123 }
6124 <?php
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136 namespace Composer\Command;
6137
6138 use Composer\Script\Event as ScriptEvent;
6139 use Composer\Script\ScriptEvents;
6140 use Composer\Util\ProcessExecutor;
6141 use Symfony\Component\Console\Input\InputInterface;
6142 use Symfony\Component\Console\Input\InputOption;
6143 use Symfony\Component\Console\Input\InputArgument;
6144 use Symfony\Component\Console\Output\OutputInterface;
6145
6146
6147
6148
6149 class RunScriptCommand extends BaseCommand
6150 {
6151
6152
6153
6154 protected $scriptEvents = array(
6155 ScriptEvents::PRE_INSTALL_CMD,
6156 ScriptEvents::POST_INSTALL_CMD,
6157 ScriptEvents::PRE_UPDATE_CMD,
6158 ScriptEvents::POST_UPDATE_CMD,
6159 ScriptEvents::PRE_STATUS_CMD,
6160 ScriptEvents::POST_STATUS_CMD,
6161 ScriptEvents::POST_ROOT_PACKAGE_INSTALL,
6162 ScriptEvents::POST_CREATE_PROJECT_CMD,
6163 ScriptEvents::PRE_ARCHIVE_CMD,
6164 ScriptEvents::POST_ARCHIVE_CMD,
6165 ScriptEvents::PRE_AUTOLOAD_DUMP,
6166 ScriptEvents::POST_AUTOLOAD_DUMP,
6167 );
6168
6169 protected function configure()
6170 {
6171 $this
6172 ->setName('run-script')
6173 ->setDescription('Runs the scripts defined in composer.json.')
6174 ->setDefinition(array(
6175 new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),
6176 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6177 new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'),
6178 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6179 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6180 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.'),
6181 ))
6182 ->setHelp(<<<EOT
6183 The <info>run-script</info> command runs scripts defined in composer.json:
6184
6185 <info>php composer.phar run-script post-update-cmd</info>
6186 EOT
6187 )
6188 ;
6189 }
6190
6191 protected function execute(InputInterface $input, OutputInterface $output)
6192 {
6193 if ($input->getOption('list')) {
6194 return $this->listScripts();
6195 } elseif (!$input->getArgument('script')) {
6196 throw new \RuntimeException('Missing required argument "script"');
6197 }
6198
6199 $script = $input->getArgument('script');
6200 if (!in_array($script, $this->scriptEvents)) {
6201 if (defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
6202 throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
6203 }
6204 }
6205
6206 $composer = $this->getComposer();
6207 $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
6208 $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode);
6209 $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event);
6210 if (!$hasListeners) {
6211 throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
6212 }
6213
6214 $args = $input->getArgument('args');
6215
6216 if (null !== $timeout = $input->getOption('timeout')) {
6217 if (!ctype_digit($timeout)) {
6218 throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever');
6219 }
6220
6221  ProcessExecutor::setTimeout((int) $timeout);
6222 }
6223
6224 return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
6225 }
6226
6227 protected function listScripts()
6228 {
6229 $scripts = $this->getComposer()->getPackage()->getScripts();
6230
6231 if (!count($scripts)) {
6232 return 0;
6233 }
6234
6235 $io = $this->getIO();
6236 $io->writeError('<info>scripts:</info>');
6237 foreach ($scripts as $name => $script) {
6238 $io->write('  ' . $name);
6239 }
6240
6241 return 0;
6242 }
6243 }
6244 <?php
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256 namespace Composer\Command;
6257
6258 use Symfony\Component\Console\Input\InputInterface;
6259 use Symfony\Component\Console\Input\InputOption;
6260 use Symfony\Component\Console\Input\InputArgument;
6261 use Symfony\Component\Console\Output\OutputInterface;
6262
6263
6264
6265
6266 class ScriptAliasCommand extends BaseCommand
6267 {
6268 private $script;
6269 private $description;
6270
6271 public function __construct($script, $description)
6272 {
6273 $this->script = $script;
6274 $this->description = empty($description) ? 'Runs the '.$script.' script as defined in composer.json.' : $description;
6275
6276 parent::__construct();
6277 }
6278
6279 protected function configure()
6280 {
6281 $this
6282 ->setName($this->script)
6283 ->setDescription($this->description)
6284 ->setDefinition(array(
6285 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6286 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6287 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6288 ))
6289 ->setHelp(<<<EOT
6290 The <info>run-script</info> command runs scripts defined in composer.json:
6291
6292 <info>php composer.phar run-script post-update-cmd</info>
6293 EOT
6294 )
6295 ;
6296 }
6297
6298 protected function execute(InputInterface $input, OutputInterface $output)
6299 {
6300 $composer = $this->getComposer();
6301
6302 $args = $input->getArguments();
6303
6304 return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args']);
6305 }
6306 }
6307 <?php
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319 namespace Composer\Command;
6320
6321 use Composer\Factory;
6322 use Symfony\Component\Console\Input\InputInterface;
6323 use Symfony\Component\Console\Input\InputArgument;
6324 use Symfony\Component\Console\Input\InputOption;
6325 use Symfony\Component\Console\Output\OutputInterface;
6326 use Composer\Repository\CompositeRepository;
6327 use Composer\Repository\PlatformRepository;
6328 use Composer\Repository\RepositoryInterface;
6329 use Composer\Plugin\CommandEvent;
6330 use Composer\Plugin\PluginEvents;
6331
6332
6333
6334
6335 class SearchCommand extends BaseCommand
6336 {
6337 protected $matches;
6338 protected $lowMatches = array();
6339 protected $tokens;
6340 protected $output;
6341 protected $onlyName;
6342
6343 protected function configure()
6344 {
6345 $this
6346 ->setName('search')
6347 ->setDescription('Searches for packages.')
6348 ->setDefinition(array(
6349 new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
6350 new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
6351 new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
6352 ))
6353 ->setHelp(<<<EOT
6354 The search command searches for packages by its name
6355 <info>php composer.phar search symfony composer</info>
6356
6357 EOT
6358 )
6359 ;
6360 }
6361
6362 protected function execute(InputInterface $input, OutputInterface $output)
6363 {
6364
6365  $platformRepo = new PlatformRepository;
6366 $io = $this->getIO();
6367 if (!($composer = $this->getComposer(false))) {
6368 $composer = Factory::create($this->getIO(), array());
6369 }
6370 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6371 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6372 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6373
6374 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
6375 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6376
6377 $onlyName = $input->getOption('only-name');
6378 $type = $input->getOption('type') ?: null;
6379
6380 $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
6381 $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
6382
6383 foreach ($results as $result) {
6384 $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
6385 }
6386 }
6387 }
6388 <?php
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400 namespace Composer\Command;
6401
6402 use Composer\Composer;
6403 use Composer\Factory;
6404 use Composer\Config;
6405 use Composer\Util\Filesystem;
6406 use Composer\SelfUpdate\Keys;
6407 use Composer\SelfUpdate\Versions;
6408 use Composer\IO\IOInterface;
6409 use Composer\Downloader\FilesystemException;
6410 use Symfony\Component\Console\Input\InputInterface;
6411 use Symfony\Component\Console\Input\InputOption;
6412 use Symfony\Component\Console\Input\InputArgument;
6413 use Symfony\Component\Console\Output\OutputInterface;
6414 use Symfony\Component\Finder\Finder;
6415
6416
6417
6418
6419
6420
6421 class SelfUpdateCommand extends BaseCommand
6422 {
6423 const HOMEPAGE = 'getcomposer.org';
6424 const OLD_INSTALL_EXT = '-old.phar';
6425
6426 protected function configure()
6427 {
6428 $this
6429 ->setName('self-update')
6430 ->setAliases(array('selfupdate'))
6431 ->setDescription('Updates composer.phar to the latest version.')
6432 ->setDefinition(array(
6433 new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'),
6434 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'),
6435 new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'),
6436 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6437 new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'),
6438 new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'),
6439 new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'),
6440 new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'),
6441 new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit'),
6442 ))
6443 ->setHelp(<<<EOT
6444 The <info>self-update</info> command checks getcomposer.org for newer
6445 versions of composer and if found, installs the latest.
6446
6447 <info>php composer.phar self-update</info>
6448
6449 EOT
6450 )
6451 ;
6452 }
6453
6454 protected function execute(InputInterface $input, OutputInterface $output)
6455 {
6456 $config = Factory::createConfig();
6457
6458 if ($config->get('disable-tls') === true) {
6459 $baseUrl = 'http://' . self::HOMEPAGE;
6460 } else {
6461 $baseUrl = 'https://' . self::HOMEPAGE;
6462 }
6463
6464 $io = $this->getIO();
6465 $remoteFilesystem = Factory::createRemoteFilesystem($io, $config);
6466
6467 $versionsUtil = new Versions($config, $remoteFilesystem);
6468
6469
6470  foreach (array('stable', 'preview', 'snapshot') as $channel) {
6471 if ($input->getOption($channel)) {
6472 $versionsUtil->setChannel($channel);
6473 }
6474 }
6475
6476 if ($input->getOption('set-channel-only')) {
6477 return 0;
6478 }
6479
6480 $cacheDir = $config->get('cache-dir');
6481 $rollbackDir = $config->get('data-dir');
6482 $home = $config->get('home');
6483 $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
6484
6485 if ($input->getOption('update-keys')) {
6486 return $this->fetchKeys($io, $config);
6487 }
6488
6489
6490  $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
6491
6492
6493  if (!is_writable($tmpDir)) {
6494 throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written');
6495 }
6496
6497 if ($input->getOption('rollback')) {
6498 return $this->rollback($output, $rollbackDir, $localFilename);
6499 }
6500
6501 $latest = $versionsUtil->getLatest();
6502 $latestVersion = $latest['version'];
6503 $updateVersion = $input->getArgument('version') ?: $latestVersion;
6504
6505 if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
6506 $io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
6507
6508 return 1;
6509 }
6510
6511 if (Composer::VERSION === $updateVersion) {
6512 $io->writeError(sprintf('<info>You are already using composer version %s (%s channel).</info>', $updateVersion, $versionsUtil->getChannel()));
6513
6514
6515  if ($input->getOption('clean-backups')) {
6516 $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir));
6517 }
6518
6519 return 0;
6520 }
6521
6522 $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar';
6523 $backupFile = sprintf(
6524 '%s/%s-%s%s',
6525 $rollbackDir,
6526 strtr(Composer::RELEASE_DATE, ' :', '_-'),
6527 preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION),
6528 self::OLD_INSTALL_EXT
6529 );
6530
6531 $updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion);
6532
6533 $io->write(sprintf("Updating to version <info>%s</info> (%s channel).", $updateVersion, $versionsUtil->getChannel()));
6534 $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
6535 $signature = $remoteFilesystem->getContents(self::HOMEPAGE, $remoteFilename.'.sig', false);
6536 $io->writeError('   ', false);
6537 $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
6538 $io->writeError('');
6539
6540 if (!file_exists($tempFilename) || !$signature) {
6541 $io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
6542
6543 return 1;
6544 }
6545
6546
6547  if (!extension_loaded('openssl') && $config->get('disable-tls')) {
6548 $io->writeError('<warning>Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls</warning>');
6549 } else {
6550 if (!extension_loaded('openssl')) {
6551 throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. '
6552 . '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.');
6553 }
6554
6555 $sigFile = 'file://'.$home.'/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub');
6556 if (!file_exists($sigFile)) {
6557 file_put_contents($home.'/keys.dev.pub', <<<DEVPUBKEY
6558 -----BEGIN PUBLIC KEY-----
6559 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f
6560 FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi
6561 i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A
6562 hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f
6563 o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk
6564 8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn
6565 8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf
6566 TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9
6567 pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72
6568 8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4
6569 r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE
6570 wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ==
6571 -----END PUBLIC KEY-----
6572 DEVPUBKEY
6573 );
6574 file_put_contents($home.'/keys.tags.pub', <<<TAGSPUBKEY
6575 -----BEGIN PUBLIC KEY-----
6576 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2
6577 MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh
6578 vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO
6579 bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M
6580 mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf
6581 noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM
6582 nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ
6583 rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr
6584 RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK
6585 tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e
6586 TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95
6587 RGv89BPD+2DLnJysngsvVaUCAwEAAQ==
6588 -----END PUBLIC KEY-----
6589 TAGSPUBKEY
6590 );
6591 }
6592
6593 $pubkeyid = openssl_pkey_get_public($sigFile);
6594 $algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384';
6595 if (!in_array('SHA384', openssl_get_md_methods())) {
6596 throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
6597 }
6598 $signature = json_decode($signature, true);
6599 $signature = base64_decode($signature['sha384']);
6600 $verified = 1 === openssl_verify(file_get_contents($tempFilename), $signature, $pubkeyid, $algo);
6601 openssl_free_key($pubkeyid);
6602 if (!$verified) {
6603 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');
6604 }
6605 }
6606
6607
6608  if ($input->getOption('clean-backups')) {
6609 $this->cleanBackups($rollbackDir);
6610 }
6611
6612 if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
6613 @unlink($tempFilename);
6614 $io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
6615 $io->writeError('<error>Please re-run the self-update command to try again.</error>');
6616
6617 return 1;
6618 }
6619
6620 if (file_exists($backupFile)) {
6621 $io->writeError(sprintf(
6622 'Use <info>composer self-update --rollback</info> to return to version <comment>%s</comment>',
6623 Composer::VERSION
6624 ));
6625 } else {
6626 $io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
6627 }
6628 }
6629
6630 protected function fetchKeys(IOInterface $io, Config $config)
6631 {
6632 if (!$io->isInteractive()) {
6633 throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
6634 }
6635
6636 $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
6637
6638 $validator = function ($value) {
6639 if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
6640 throw new \UnexpectedValueException('Invalid input');
6641 }
6642
6643 return trim($value)."\n";
6644 };
6645
6646 $devKey = '';
6647 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
6648 $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
6649 while ($line = $io->ask('')) {
6650 $devKey .= trim($line)."\n";
6651 if (trim($line) === '-----END PUBLIC KEY-----') {
6652 break;
6653 }
6654 }
6655 }
6656 file_put_contents($keyPath = $config->get('home').'/keys.dev.pub', $match[0]);
6657 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6658
6659 $tagsKey = '';
6660 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
6661 $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
6662 while ($line = $io->ask('')) {
6663 $tagsKey .= trim($line)."\n";
6664 if (trim($line) === '-----END PUBLIC KEY-----') {
6665 break;
6666 }
6667 }
6668 }
6669 file_put_contents($keyPath = $config->get('home').'/keys.tags.pub', $match[0]);
6670 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6671
6672 $io->write('Public keys stored in '.$config->get('home'));
6673 }
6674
6675 protected function rollback(OutputInterface $output, $rollbackDir, $localFilename)
6676 {
6677 $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
6678 if (!$rollbackVersion) {
6679 throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"');
6680 }
6681
6682 $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
6683
6684 if (!is_file($oldFile)) {
6685 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
6686 }
6687 if (!is_readable($oldFile)) {
6688 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
6689 }
6690
6691 $io = $this->getIO();
6692 $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
6693 if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
6694 $io->writeError('<error>The backup file was corrupted ('.$err->getMessage().').</error>');
6695
6696 return 1;
6697 }
6698
6699 return 0;
6700 }
6701
6702
6703
6704
6705
6706
6707
6708
6709 protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
6710 {
6711 try {
6712 @chmod($newFilename, fileperms($localFilename));
6713 if (!ini_get('phar.readonly')) {
6714
6715  $phar = new \Phar($newFilename);
6716
6717  unset($phar);
6718 }
6719
6720
6721  if ($backupTarget && file_exists($localFilename)) {
6722 @copy($localFilename, $backupTarget);
6723 }
6724
6725 rename($newFilename, $localFilename);
6726
6727 return null;
6728 } catch (\Exception $e) {
6729 if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
6730 throw $e;
6731 }
6732
6733 return $e;
6734 }
6735 }
6736
6737 protected function cleanBackups($rollbackDir, $except = null)
6738 {
6739 $finder = $this->getOldInstallationFinder($rollbackDir);
6740 $io = $this->getIO();
6741 $fs = new Filesystem;
6742
6743 foreach ($finder as $file) {
6744 if ($except && $file->getBasename(self::OLD_INSTALL_EXT) === $except) {
6745 continue;
6746 }
6747 $file = (string) $file;
6748 $io->writeError('<info>Removing: '.$file.'</info>');
6749 $fs->remove($file);
6750 }
6751 }
6752
6753 protected function getLastBackupVersion($rollbackDir)
6754 {
6755 $finder = $this->getOldInstallationFinder($rollbackDir);
6756 $finder->sortByName();
6757 $files = iterator_to_array($finder);
6758
6759 if (count($files)) {
6760 return basename(end($files), self::OLD_INSTALL_EXT);
6761 }
6762
6763 return false;
6764 }
6765
6766 protected function getOldInstallationFinder($rollbackDir)
6767 {
6768 $finder = Finder::create()
6769 ->depth(0)
6770 ->files()
6771 ->name('*' . self::OLD_INSTALL_EXT)
6772 ->in($rollbackDir);
6773
6774 return $finder;
6775 }
6776 }
6777 <?php
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789 namespace Composer\Command;
6790
6791 use Composer\Composer;
6792 use Composer\DependencyResolver\DefaultPolicy;
6793 use Composer\DependencyResolver\Pool;
6794 use Composer\Json\JsonFile;
6795 use Composer\Package\BasePackage;
6796 use Composer\Package\CompletePackageInterface;
6797 use Composer\Package\PackageInterface;
6798 use Composer\Package\Version\VersionParser;
6799 use Composer\Package\Version\VersionSelector;
6800 use Composer\Plugin\CommandEvent;
6801 use Composer\Plugin\PluginEvents;
6802 use Composer\Repository\ArrayRepository;
6803 use Composer\Repository\ComposerRepository;
6804 use Composer\Repository\CompositeRepository;
6805 use Composer\Repository\PlatformRepository;
6806 use Composer\Repository\RepositoryFactory;
6807 use Composer\Repository\RepositoryInterface;
6808 use Composer\Semver\Constraint\ConstraintInterface;
6809 use Composer\Semver\Semver;
6810 use Composer\Spdx\SpdxLicenses;
6811 use Composer\Util\Platform;
6812 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
6813 use Symfony\Component\Console\Input\InputArgument;
6814 use Symfony\Component\Console\Input\InputInterface;
6815 use Symfony\Component\Console\Input\InputOption;
6816 use Symfony\Component\Console\Output\OutputInterface;
6817 use Symfony\Component\Console\Terminal;
6818
6819
6820
6821
6822
6823
6824
6825 class ShowCommand extends BaseCommand
6826 {
6827
6828 protected $versionParser;
6829 protected $colors;
6830
6831
6832 private $pool;
6833
6834 protected function configure()
6835 {
6836 $this
6837 ->setName('show')
6838 ->setAliases(array('info'))
6839 ->setDescription('Shows information about packages.')
6840 ->setDefinition(array(
6841 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
6842 new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
6843 new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'),
6844 new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'),
6845 new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
6846 new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
6847 new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
6848 new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
6849 new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
6850 new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
6851 new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'),
6852 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'),
6853 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
6854 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
6855 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
6856 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
6857 ))
6858 ->setHelp(<<<EOT
6859 The show command displays detailed information about a package, or
6860 lists all packages available.
6861
6862 EOT
6863 )
6864 ;
6865 }
6866
6867 protected function execute(InputInterface $input, OutputInterface $output)
6868 {
6869 $this->versionParser = new VersionParser;
6870 if ($input->getOption('tree')) {
6871 $this->initStyles($output);
6872 }
6873
6874 $composer = $this->getComposer(false);
6875 $io = $this->getIO();
6876
6877 if ($input->getOption('installed')) {
6878 $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>');
6879 }
6880
6881 if ($input->getOption('outdated')) {
6882 $input->setOption('latest', true);
6883 }
6884
6885 if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) {
6886 $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)');
6887
6888 return 1;
6889 }
6890
6891 if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) {
6892 $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)');
6893
6894 return 1;
6895 }
6896
6897 $format = $input->getOption('format');
6898 if (!in_array($format, array('text', 'json'))) {
6899 $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
6900
6901 return 1;
6902 }
6903
6904
6905  $platformOverrides = array();
6906 if ($composer) {
6907 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6908 }
6909 $platformRepo = new PlatformRepository(array(), $platformOverrides);
6910 $phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
6911
6912 if ($input->getOption('self')) {
6913 $package = $this->getComposer()->getPackage();
6914 $repos = $installedRepo = new ArrayRepository(array($package));
6915 } elseif ($input->getOption('platform')) {
6916 $repos = $installedRepo = $platformRepo;
6917 } elseif ($input->getOption('available')) {
6918 $installedRepo = $platformRepo;
6919 if ($composer) {
6920 $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
6921 } else {
6922 $defaultRepos = RepositoryFactory::defaultRepos($io);
6923 $repos = new CompositeRepository($defaultRepos);
6924 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
6925 }
6926 } elseif ($input->getOption('all') && $composer) {
6927 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6928 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6929 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6930 } elseif ($input->getOption('all')) {
6931 $defaultRepos = RepositoryFactory::defaultRepos($io);
6932 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
6933 $installedRepo = $platformRepo;
6934 $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
6935 } else {
6936 $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
6937 $rootPkg = $this->getComposer()->getPackage();
6938 if (!$installedRepo->getPackages() && ($rootPkg->getRequires() || $rootPkg->getDevRequires())) {
6939 $io->writeError('<warning>No dependencies installed. Try running composer install or update.</warning>');
6940 }
6941 }
6942
6943 if ($composer) {
6944 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
6945 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6946 }
6947
6948 if ($input->getOption('latest') && null === $composer) {
6949 $io->writeError('No composer.json found in the current directory, disabling "latest" option');
6950 $input->setOption('latest', false);
6951 }
6952
6953 $packageFilter = $input->getArgument('package');
6954
6955
6956  if (($packageFilter && false === strpos($packageFilter, '*')) || !empty($package)) {
6957 if ('json' === $format) {
6958 $io->writeError('Format "json" is only supported for package listings, falling back to format "text"');
6959 }
6960 if (empty($package)) {
6961 list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version'));
6962
6963 if (empty($package)) {
6964 $options = $input->getOptions();
6965 if (!isset($options['working-dir']) || !file_exists('composer.json')) {
6966 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found');
6967 }
6968
6969 $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
6970
6971 return 1;
6972 }
6973 } else {
6974 $versions = array($package->getPrettyVersion() => $package->getVersion());
6975 }
6976
6977 $exitCode = 0;
6978 if ($input->getOption('tree')) {
6979 $this->displayPackageTree($package, $installedRepo, $repos);
6980 } else {
6981 $latestPackage = null;
6982 if ($input->getOption('latest')) {
6983 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion);
6984 }
6985 if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
6986 $exitCode = 1;
6987 }
6988 $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
6989 $this->printLinks($package, 'requires');
6990 $this->printLinks($package, 'devRequires', 'requires (dev)');
6991 if ($package->getSuggests()) {
6992 $io->write("\n<info>suggests</info>");
6993 foreach ($package->getSuggests() as $suggested => $reason) {
6994 $io->write($suggested . ' <comment>' . $reason . '</comment>');
6995 }
6996 }
6997 $this->printLinks($package, 'provides');
6998 $this->printLinks($package, 'conflicts');
6999 $this->printLinks($package, 'replaces');
7000 }
7001
7002 return $exitCode;
7003 }
7004
7005
7006  if ($input->getOption('tree')) {
7007 if ('json' === $format) {
7008 $io->writeError('Format "json" is only supported for package listings, falling back to format "text"');
7009 }
7010 $rootRequires = $this->getRootRequires();
7011 $packages = $installedRepo->getPackages();
7012 usort($packages, 'strcmp');
7013 foreach ($packages as $package) {
7014 if (in_array($package->getName(), $rootRequires, true)) {
7015 $this->displayPackageTree($package, $installedRepo, $repos);
7016 }
7017 }
7018
7019 return 0;
7020 }
7021
7022 if ($repos instanceof CompositeRepository) {
7023 $repos = $repos->getRepositories();
7024 } elseif (!is_array($repos)) {
7025 $repos = array($repos);
7026 }
7027
7028
7029  $packages = array();
7030 if (null !== $packageFilter) {
7031 $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
7032 }
7033
7034 $packageListFilter = array();
7035 if ($input->getOption('direct')) {
7036 $packageListFilter = $this->getRootRequires();
7037 }
7038
7039 if (class_exists('Symfony\Component\Console\Terminal')) {
7040 $terminal = new Terminal();
7041 $width = $terminal->getWidth();
7042 } else {
7043
7044  list($width) = $this->getApplication()->getTerminalDimensions();
7045 }
7046 if (null === $width) {
7047
7048  
7049  $width = PHP_INT_MAX;
7050 }
7051 if (Platform::isWindows()) {
7052 $width--;
7053 } else {
7054 $width = max(80, $width);
7055 }
7056
7057 if ($input->getOption('path') && null === $composer) {
7058 $io->writeError('No composer.json found in the current directory, disabling "path" option');
7059 $input->setOption('path', false);
7060 }
7061
7062 foreach ($repos as $repo) {
7063 if ($repo === $platformRepo) {
7064 $type = 'platform';
7065 } elseif (
7066 $repo === $installedRepo
7067 || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
7068 ) {
7069 $type = 'installed';
7070 } else {
7071 $type = 'available';
7072 }
7073 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
7074 foreach ($repo->getProviderNames() as $name) {
7075 if (!$packageFilter || preg_match($packageFilter, $name)) {
7076 $packages[$type][$name] = $name;
7077 }
7078 }
7079 } else {
7080 foreach ($repo->getPackages() as $package) {
7081 if (!isset($packages[$type][$package->getName()])
7082 || !is_object($packages[$type][$package->getName()])
7083 || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
7084 ) {
7085 if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
7086 if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
7087 $packages[$type][$package->getName()] = $package;
7088 }
7089 }
7090 }
7091 }
7092 }
7093 }
7094
7095 $showAllTypes = $input->getOption('all');
7096 $showLatest = $input->getOption('latest');
7097 $showMinorOnly = $input->getOption('minor-only');
7098 $indent = $showAllTypes ? '  ' : '';
7099 $latestPackages = array();
7100 $exitCode = 0;
7101 $viewData = array();
7102 $viewMetaData = array();
7103 foreach (array('platform' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
7104 if (isset($packages[$type])) {
7105 ksort($packages[$type]);
7106
7107 $nameLength = $versionLength = $latestLength = 0;
7108 foreach ($packages[$type] as $package) {
7109 if (is_object($package)) {
7110 $nameLength = max($nameLength, strlen($package->getPrettyName()));
7111 if ($showVersion) {
7112 $versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
7113 if ($showLatest) {
7114 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion, $showMinorOnly);
7115 if ($latestPackage === false) {
7116 continue;
7117 }
7118
7119 $latestPackages[$package->getPrettyName()] = $latestPackage;
7120 $latestLength = max($latestLength, strlen($latestPackage->getFullPrettyVersion()));
7121 }
7122 }
7123 } else {
7124 $nameLength = max($nameLength, strlen($package));
7125 }
7126 }
7127
7128 $writePath = !$input->getOption('name-only') && $input->getOption('path');
7129 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
7130 $writeLatest = $writeVersion && $showLatest;
7131 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
7132
7133 $hasOutdatedPackages = false;
7134
7135 $viewData[$type] = array();
7136 $viewMetaData[$type] = array(
7137 'nameLength' => $nameLength,
7138 'versionLength' => $versionLength,
7139 'latestLength' => $latestLength,
7140 );
7141 foreach ($packages[$type] as $package) {
7142 $packageViewData = array();
7143 if (is_object($package)) {
7144 $latestPackage = null;
7145 if ($showLatest && isset($latestPackages[$package->getPrettyName()])) {
7146 $latestPackage = $latestPackages[$package->getPrettyName()];
7147 }
7148 if ($input->getOption('outdated') && $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
7149 continue;
7150 } elseif ($input->getOption('outdated') || $input->getOption('strict')) {
7151 $hasOutdatedPackages = true;
7152 }
7153
7154 $packageViewData['name'] = $package->getPrettyName();
7155 if ($writeVersion) {
7156 $packageViewData['version'] = $package->getFullPrettyVersion();
7157 }
7158 if ($writeLatest && $latestPackage) {
7159 $packageViewData['latest'] = $latestPackage->getFullPrettyVersion();
7160 $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
7161 }
7162 if ($writeDescription) {
7163 $packageViewData['description'] = $package->getDescription();
7164 }
7165 if ($writePath) {
7166 $packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
7167 }
7168
7169 if ($latestPackage && $latestPackage->isAbandoned()) {
7170 $replacement = (is_string($latestPackage->getReplacementPackage()))
7171 ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead'
7172 : 'No replacement was suggested';
7173 $packageWarning = sprintf(
7174 'Package %s is abandoned, you should avoid using it. %s.',
7175 $package->getPrettyName(),
7176 $replacement
7177 );
7178 $packageViewData['warning'] = $packageWarning;
7179 }
7180 } else {
7181 $packageViewData['name'] = $package;
7182 }
7183 $viewData[$type][] = $packageViewData;
7184 }
7185 if ($input->getOption('strict') && $hasOutdatedPackages) {
7186 $exitCode = 1;
7187 break;
7188 }
7189 }
7190 }
7191
7192 if ('json' === $format) {
7193 $io->write(JsonFile::encode($viewData));
7194 } else {
7195 foreach ($viewData as $type => $packages) {
7196 $nameLength = $viewMetaData[$type]['nameLength'];
7197 $versionLength = $viewMetaData[$type]['versionLength'];
7198 $latestLength = $viewMetaData[$type]['latestLength'];
7199
7200 $writeVersion = $nameLength + $versionLength + 3 <= $width;
7201 $writeLatest = $nameLength + $versionLength + $latestLength + 3 <= $width;
7202 $writeDescription = $nameLength + $versionLength + $latestLength + 24 <= $width;
7203
7204 if ($writeLatest && !$io->isDecorated()) {
7205 $latestLength += 2;
7206 }
7207
7208 if ($showAllTypes) {
7209 if ('available' === $type) {
7210 $io->write('<comment>' . $type . '</comment>:');
7211 } else {
7212 $io->write('<info>' . $type . '</info>:');
7213 }
7214 }
7215
7216 foreach ($packages as $package) {
7217 $io->write($indent . str_pad($package['name'], $nameLength, ' '), false);
7218 if (isset($package['version']) && $writeVersion) {
7219 $io->write(' ' . str_pad($package['version'], $versionLength, ' '), false);
7220 }
7221 if (isset($package['latest']) && $writeLatest) {
7222 $latestVersion = $package['latest'];
7223 $updateStatus = $package['latest-status'];
7224 $style = $this->updateStatusToVersionStyle($updateStatus);
7225 if (!$io->isDecorated()) {
7226 $latestVersion = str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('=', '!', '~'), $updateStatus) . ' ' . $latestVersion;
7227 }
7228 $io->write(' <' . $style . '>' . str_pad($latestVersion, $latestLength, ' ') . '</' . $style . '>', false);
7229 }
7230 if (isset($package['description']) && $writeDescription) {
7231 $description = strtok($package['description'], "\r\n");
7232 $remaining = $width - $nameLength - $versionLength - 4;
7233 if ($writeLatest) {
7234 $remaining -= $latestLength;
7235 }
7236 if (strlen($description) > $remaining) {
7237 $description = substr($description, 0, $remaining - 3) . '...';
7238 }
7239 $io->write(' ' . $description, false);
7240 }
7241 if (isset($package['path'])) {
7242 $io->write(' ' . $package['path'], false);
7243 }
7244 $io->write('');
7245 if (isset($package['warning'])) {
7246 $io->write('<warning>' . $package['warning'] . '</warning>');
7247 }
7248 }
7249
7250 if ($showAllTypes) {
7251 $io->write('');
7252 }
7253 }
7254 }
7255
7256 return $exitCode;
7257 }
7258
7259 protected function getRootRequires()
7260 {
7261 $rootPackage = $this->getComposer()->getPackage();
7262
7263 return array_map(
7264 'strtolower',
7265 array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))
7266 );
7267 }
7268
7269 protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package)
7270 {
7271 return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package));
7272 }
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284 protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
7285 {
7286 $name = strtolower($name);
7287 $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
7288
7289 $policy = new DefaultPolicy();
7290 $pool = new Pool('dev');
7291 $pool->addRepository($repos);
7292
7293 $matchedPackage = null;
7294 $versions = array();
7295 $matches = $pool->whatProvides($name, $constraint);
7296 foreach ($matches as $index => $package) {
7297
7298  if ($package->getName() !== $name) {
7299 unset($matches[$index]);
7300 continue;
7301 }
7302
7303
7304  if (null === $version && $installedRepo->hasPackage($package)) {
7305 $matchedPackage = $package;
7306 }
7307
7308 $versions[$package->getPrettyVersion()] = $package->getVersion();
7309 $matches[$index] = $package->getId();
7310 }
7311
7312
7313  if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
7314 $matchedPackage = $pool->literalToPackage($preferred[0]);
7315 }
7316
7317 return array($matchedPackage, $versions);
7318 }
7319
7320
7321
7322
7323
7324
7325
7326
7327 protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
7328 {
7329 $io = $this->getIO();
7330 $io->write('<info>name</info>     : ' . $package->getPrettyName());
7331 $io->write('<info>descrip.</info> : ' . $package->getDescription());
7332 $io->write('<info>keywords</info> : ' . implode(', ', $package->getKeywords() ?: array()));
7333 $this->printVersions($package, $versions, $installedRepo);
7334 if ($latestPackage) {
7335 $style = $this->getVersionStyle($latestPackage, $package);
7336 $io->write('<info>latest</info>   : <'.$style.'>' . $latestPackage->getPrettyVersion() . '</'.$style.'>');
7337 } else {
7338 $latestPackage = $package;
7339 }
7340 $io->write('<info>type</info>     : ' . $package->getType());
7341 $this->printLicenses($package);
7342 $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
7343 $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
7344 $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
7345
7346 if ($latestPackage->isAbandoned()) {
7347 $replacement = ($latestPackage->getReplacementPackage() !== null)
7348 ? ' The author suggests using the ' . $latestPackage->getReplacementPackage(). ' package instead.'
7349 : null;
7350
7351 $io->writeError(
7352 sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
7353 );
7354 }
7355
7356 if ($package->getSupport()) {
7357 $io->write("\n<info>support</info>");
7358 foreach ($package->getSupport() as $type => $value) {
7359 $io->write('<comment>' . $type . '</comment> : '.$value);
7360 }
7361 }
7362
7363 if ($package->getAutoload()) {
7364 $io->write("\n<info>autoload</info>");
7365 foreach ($package->getAutoload() as $type => $autoloads) {
7366 $io->write('<comment>' . $type . '</comment>');
7367
7368 if ($type === 'psr-0') {
7369 foreach ($autoloads as $name => $path) {
7370 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7371 }
7372 } elseif ($type === 'psr-4') {
7373 foreach ($autoloads as $name => $path) {
7374 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7375 }
7376 } elseif ($type === 'classmap') {
7377 $io->write(implode(', ', $autoloads));
7378 }
7379 }
7380 if ($package->getIncludePaths()) {
7381 $io->write('<comment>include-path</comment>');
7382 $io->write(implode(', ', $package->getIncludePaths()));
7383 }
7384 }
7385 }
7386
7387
7388
7389
7390
7391
7392
7393
7394 protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
7395 {
7396 uasort($versions, 'version_compare');
7397 $versions = array_keys(array_reverse($versions));
7398
7399
7400  if ($installedRepo->hasPackage($package)) {
7401 $installedVersion = $package->getPrettyVersion();
7402 $key = array_search($installedVersion, $versions);
7403 if (false !== $key) {
7404 $versions[$key] = '<info>* ' . $installedVersion . '</info>';
7405 }
7406 }
7407
7408 $versions = implode(', ', $versions);
7409
7410 $this->getIO()->write('<info>versions</info> : ' . $versions);
7411 }
7412
7413
7414
7415
7416
7417
7418
7419
7420 protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
7421 {
7422 $title = $title ?: $linkType;
7423 $io = $this->getIO();
7424 if ($links = $package->{'get'.ucfirst($linkType)}()) {
7425 $io->write("\n<info>" . $title . "</info>");
7426
7427 foreach ($links as $link) {
7428 $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
7429 }
7430 }
7431 }
7432
7433
7434
7435
7436
7437
7438 protected function printLicenses(CompletePackageInterface $package)
7439 {
7440 $spdxLicenses = new SpdxLicenses();
7441
7442 $licenses = $package->getLicense();
7443 $io = $this->getIO();
7444
7445 foreach ($licenses as $licenseId) {
7446 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
7447
7448 if (!$license) {
7449 $out = $licenseId;
7450 } else {
7451
7452  if ($license[1] === true) {
7453 $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
7454 } else {
7455 $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
7456 }
7457 }
7458
7459 $io->write('<info>license</info>  : ' . $out);
7460 }
7461 }
7462
7463
7464
7465
7466
7467
7468 protected function initStyles(OutputInterface $output)
7469 {
7470 $this->colors = array(
7471 'green',
7472 'yellow',
7473 'cyan',
7474 'magenta',
7475 'blue',
7476 );
7477
7478 foreach ($this->colors as $color) {
7479 $style = new OutputFormatterStyle($color);
7480 $output->getFormatter()->setStyle($color, $style);
7481 }
7482 }
7483
7484
7485
7486
7487
7488
7489
7490
7491 protected function displayPackageTree(PackageInterface $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos)
7492 {
7493 $io = $this->getIO();
7494 $io->write(sprintf('<info>%s</info>', $package->getPrettyName()), false);
7495 $io->write(' ' . $package->getPrettyVersion(), false);
7496 $io->write(' ' . strtok($package->getDescription(), "\r\n"));
7497
7498 if (is_object($package)) {
7499 $requires = $package->getRequires();
7500 ksort($requires);
7501 $treeBar = '├';
7502 $j = 0;
7503 $total = count($requires);
7504 foreach ($requires as $requireName => $require) {
7505 $j++;
7506 if ($j == 0) {
7507 $this->writeTreeLine($treeBar);
7508 }
7509 if ($j == $total) {
7510 $treeBar = '└';
7511 }
7512 $level = 1;
7513 $color = $this->colors[$level];
7514 $info = sprintf('%s──<%s>%s</%s> %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint());
7515 $this->writeTreeLine($info);
7516
7517 $treeBar = str_replace('└', ' ', $treeBar);
7518 $packagesInTree = array($package->getName(), $requireName);
7519
7520 $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree, $treeBar, $level + 1);
7521 }
7522 }
7523 }
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536 protected function displayTree($name, $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos, array $packagesInTree, $previousTreeBar = '├', $level = 1)
7537 {
7538 $previousTreeBar = str_replace('├', '│', $previousTreeBar);
7539 list($package, $versions) = $this->getPackage($installedRepo, $distantRepos, $name, $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint());
7540 if (is_object($package)) {
7541 $requires = $package->getRequires();
7542 ksort($requires);
7543 $treeBar = $previousTreeBar . '  ├';
7544 $i = 0;
7545 $total = count($requires);
7546 foreach ($requires as $requireName => $require) {
7547 $currentTree = $packagesInTree;
7548 $i++;
7549 if ($i == $total) {
7550 $treeBar = $previousTreeBar . '  └';
7551 }
7552 $colorIdent = $level % count($this->colors);
7553 $color = $this->colors[$colorIdent];
7554
7555 $circularWarn = in_array($requireName, $currentTree) ? '(circular dependency aborted here)' : '';
7556 $info = rtrim(sprintf('%s──<%s>%s</%s> %s %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint(), $circularWarn));
7557 $this->writeTreeLine($info);
7558
7559 $treeBar = str_replace('└', ' ', $treeBar);
7560 if (!in_array($requireName, $currentTree)) {
7561 $currentTree[] = $requireName;
7562 $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $currentTree, $treeBar, $level + 1);
7563 }
7564 }
7565 }
7566 }
7567
7568 private function updateStatusToVersionStyle($updateStatus)
7569 {
7570
7571  
7572  
7573  return str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('info', 'highlight', 'comment'), $updateStatus);
7574 }
7575
7576 private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package)
7577 {
7578 if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) {
7579 return 'up-to-date';
7580 }
7581
7582 $constraint = $package->getVersion();
7583 if (0 !== strpos($constraint, 'dev-')) {
7584 $constraint = '^'.$constraint;
7585 }
7586 if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) {
7587
7588  return 'semver-safe-update';
7589 }
7590
7591
7592  return 'update-possible';
7593 }
7594
7595 private function writeTreeLine($line)
7596 {
7597 $io = $this->getIO();
7598 if (!$io->isDecorated()) {
7599 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
7600 }
7601
7602 $io->write($line);
7603 }
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615 private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
7616 {
7617
7618  $name = $package->getName();
7619 $versionSelector = new VersionSelector($this->getPool($composer));
7620 $stability = $composer->getPackage()->getMinimumStability();
7621 $flags = $composer->getPackage()->getStabilityFlags();
7622 if (isset($flags[$name])) {
7623 $stability = array_search($flags[$name], BasePackage::$stabilities, true);
7624 }
7625
7626 $bestStability = $stability;
7627 if ($composer->getPackage()->getPreferStable()) {
7628 $bestStability = $package->getStability();
7629 }
7630
7631 $targetVersion = null;
7632 if (0 === strpos($package->getVersion(), 'dev-')) {
7633 $targetVersion = $package->getVersion();
7634 }
7635
7636 if ($targetVersion === null && $minorOnly) {
7637 $targetVersion = '^' . $package->getVersion();
7638 }
7639
7640 return $versionSelector->findBestCandidate($name, $targetVersion, $phpVersion, $bestStability);
7641 }
7642
7643 private function getPool(Composer $composer)
7644 {
7645 if (!$this->pool) {
7646 $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
7647 $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
7648 }
7649
7650 return $this->pool;
7651 }
7652 }
7653 <?php
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665 namespace Composer\Command;
7666
7667 use Symfony\Component\Console\Input\InputInterface;
7668 use Symfony\Component\Console\Input\InputOption;
7669 use Symfony\Component\Console\Output\OutputInterface;
7670 use Composer\Downloader\ChangeReportInterface;
7671 use Composer\Downloader\DvcsDownloaderInterface;
7672 use Composer\Downloader\VcsCapableDownloaderInterface;
7673 use Composer\Package\Dumper\ArrayDumper;
7674 use Composer\Package\Version\VersionGuesser;
7675 use Composer\Package\Version\VersionParser;
7676 use Composer\Plugin\CommandEvent;
7677 use Composer\Plugin\PluginEvents;
7678 use Composer\Script\ScriptEvents;
7679 use Composer\Util\ProcessExecutor;
7680
7681
7682
7683
7684
7685 class StatusCommand extends BaseCommand
7686 {
7687 const EXIT_CODE_ERRORS = 1;
7688 const EXIT_CODE_UNPUSHED_CHANGES = 2;
7689 const EXIT_CODE_VERSION_CHANGES = 4;
7690
7691 protected function configure()
7692 {
7693 $this
7694 ->setName('status')
7695 ->setDescription('Shows a list of locally modified packages.')
7696 ->setDefinition(array(
7697 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
7698 ))
7699 ->setHelp(<<<EOT
7700 The status command displays a list of dependencies that have
7701 been modified locally.
7702
7703 EOT
7704 )
7705 ;
7706 }
7707
7708 protected function execute(InputInterface $input, OutputInterface $output)
7709 {
7710
7711  $composer = $this->getComposer();
7712
7713 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
7714 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7715
7716 $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
7717
7718 $dm = $composer->getDownloadManager();
7719 $im = $composer->getInstallationManager();
7720
7721
7722  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
7723
7724 $errors = array();
7725 $io = $this->getIO();
7726 $unpushedChanges = array();
7727 $vcsVersionChanges = array();
7728
7729 $parser = new VersionParser;
7730 $guesser = new VersionGuesser($composer->getConfig(), new ProcessExecutor($io), $parser);
7731 $dumper = new ArrayDumper;
7732
7733
7734  foreach ($installedRepo->getCanonicalPackages() as $package) {
7735 $downloader = $dm->getDownloaderForInstalledPackage($package);
7736 $targetDir = $im->getInstallPath($package);
7737
7738 if ($downloader instanceof ChangeReportInterface) {
7739 if (is_link($targetDir)) {
7740 $errors[$targetDir] = $targetDir . ' is a symbolic link.';
7741 }
7742
7743 if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
7744 $errors[$targetDir] = $changes;
7745 }
7746 }
7747
7748 if ($downloader instanceof VcsCapableDownloaderInterface) {
7749 if ($currentRef = $downloader->getVcsReference($package, $targetDir)) {
7750 switch ($package->getInstallationSource()) {
7751 case 'source':
7752 $previousRef = $package->getSourceReference();
7753 break;
7754 case 'dist':
7755 $previousRef = $package->getDistReference();
7756 break;
7757 default:
7758 $previousRef = null;
7759 }
7760
7761 $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir);
7762
7763 if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef) {
7764 $vcsVersionChanges[$targetDir] = array(
7765 'previous' => array(
7766 'version' => $package->getPrettyVersion(),
7767 'ref' => $previousRef,
7768 ),
7769 'current' => array(
7770 'version' => $currentVersion['pretty_version'],
7771 'ref' => $currentVersion['commit'],
7772 ),
7773 );
7774 }
7775 }
7776 }
7777
7778 if ($downloader instanceof DvcsDownloaderInterface) {
7779 if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
7780 $unpushedChanges[$targetDir] = $unpushed;
7781 }
7782 }
7783 }
7784
7785
7786  if (!$errors && !$unpushedChanges && !$vcsVersionChanges) {
7787 $io->writeError('<info>No local changes</info>');
7788
7789 return 0;
7790 }
7791
7792 if ($errors) {
7793 $io->writeError('<error>You have changes in the following dependencies:</error>');
7794
7795 foreach ($errors as $path => $changes) {
7796 if ($input->getOption('verbose')) {
7797 $indentedChanges = implode("\n", array_map(function ($line) {
7798 return '    ' . ltrim($line);
7799 }, explode("\n", $changes)));
7800 $io->write('<info>'.$path.'</info>:');
7801 $io->write($indentedChanges);
7802 } else {
7803 $io->write($path);
7804 }
7805 }
7806 }
7807
7808 if ($unpushedChanges) {
7809 $io->writeError('<warning>You have unpushed changes on the current branch in the following dependencies:</warning>');
7810
7811 foreach ($unpushedChanges as $path => $changes) {
7812 if ($input->getOption('verbose')) {
7813 $indentedChanges = implode("\n", array_map(function ($line) {
7814 return '    ' . ltrim($line);
7815 }, explode("\n", $changes)));
7816 $io->write('<info>'.$path.'</info>:');
7817 $io->write($indentedChanges);
7818 } else {
7819 $io->write($path);
7820 }
7821 }
7822 }
7823
7824 if ($vcsVersionChanges) {
7825 $io->writeError('<warning>You have version variations in the following dependencies:</warning>');
7826
7827 foreach ($vcsVersionChanges as $path => $changes) {
7828 if ($input->getOption('verbose')) {
7829
7830  $currentVersion = $changes['current']['version'] ?: $changes['current']['ref'];
7831 $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref'];
7832
7833 if ($io->isVeryVerbose()) {
7834
7835  $currentVersion .= sprintf(' (%s)', $changes['current']['ref']);
7836 $previousVersion .= sprintf(' (%s)', $changes['previous']['ref']);
7837 }
7838
7839 $io->write('<info>'.$path.'</info>:');
7840 $io->write(sprintf('    From <comment>%s</comment> to <comment>%s</comment>', $previousVersion, $currentVersion));
7841 } else {
7842 $io->write($path);
7843 }
7844 }
7845 }
7846
7847 if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) {
7848 $io->writeError('Use --verbose (-v) to see a list of files');
7849 }
7850
7851
7852  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
7853
7854 return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0);
7855 }
7856 }
7857 <?php
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869 namespace Composer\Command;
7870
7871 use Composer\Repository\PlatformRepository;
7872 use Symfony\Component\Console\Input\InputArgument;
7873 use Symfony\Component\Console\Input\InputInterface;
7874 use Symfony\Component\Console\Input\InputOption;
7875 use Symfony\Component\Console\Output\OutputInterface;
7876
7877 class SuggestsCommand extends BaseCommand
7878 {
7879 protected function configure()
7880 {
7881 $this
7882 ->setName('suggests')
7883 ->setDescription('Shows package suggestions.')
7884 ->setDefinition(array(
7885 new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package'),
7886 new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'),
7887 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
7888 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
7889 ))
7890 ->setHelp(<<<EOT
7891
7892 The <info>%command.name%</info> command shows a sorted list of suggested packages.
7893
7894 Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
7895
7896 EOT
7897 )
7898 ;
7899 }
7900
7901 protected function execute(InputInterface $input, OutputInterface $output)
7902 {
7903 $lock = $this->getComposer()->getLocker()->getLockData();
7904
7905 if (empty($lock)) {
7906 throw new \RuntimeException('Lockfile seems to be empty?');
7907 }
7908
7909 $packages = $lock['packages'];
7910
7911 if (!$input->getOption('no-dev')) {
7912 $packages += $lock['packages-dev'];
7913 }
7914
7915 $filter = $input->getArgument('packages');
7916
7917
7918  $installed = array();
7919 foreach ($packages as $package) {
7920 $installed[] = $package['name'];
7921
7922 if (!empty($package['provide'])) {
7923 $installed = array_merge($installed, array_keys($package['provide']));
7924 }
7925
7926 if (!empty($package['replace'])) {
7927 $installed = array_merge($installed, array_keys($package['replace']));
7928 }
7929 }
7930
7931
7932  $installed = array_flip($installed);
7933 ksort($installed);
7934
7935
7936  $platform = new PlatformRepository(array(), $this->getComposer()->getConfig()->get('platform') ?: array());
7937
7938
7939  $suggesters = array();
7940 $suggested = array();
7941 foreach ($packages as $package) {
7942 $packageName = $package['name'];
7943 if ((!empty($filter) && !in_array($packageName, $filter)) || empty($package['suggest'])) {
7944 continue;
7945 }
7946 foreach ($package['suggest'] as $suggestion => $reason) {
7947 if (false === strpos('/', $suggestion) && null !== $platform->findPackage($suggestion, '*')) {
7948 continue;
7949 }
7950 if (!isset($installed[$suggestion])) {
7951 $suggesters[$packageName][$suggestion] = $reason;
7952 $suggested[$suggestion][$packageName] = $reason;
7953 }
7954 }
7955 }
7956 ksort($suggesters);
7957 ksort($suggested);
7958
7959
7960  $mode = 0;
7961 $io = $this->getIO();
7962 if ($input->getOption('by-package') || $io->isVerbose()) {
7963 $mode |= 1;
7964 }
7965 if ($input->getOption('by-suggestion')) {
7966 $mode |= 2;
7967 }
7968
7969
7970  if ($mode === 0) {
7971 foreach (array_keys($suggested) as $suggestion) {
7972 $io->write(sprintf('<info>%s</info>', $suggestion));
7973 }
7974
7975 return;
7976 }
7977
7978
7979  if ($mode & 1) {
7980 foreach ($suggesters as $suggester => $suggestions) {
7981 $io->write(sprintf('<comment>%s</comment> suggests:', $suggester));
7982
7983 foreach ($suggestions as $suggestion => $reason) {
7984 $io->write(sprintf(' - <info>%s</info>: %s', $suggestion, $reason ?: '*'));
7985 }
7986 $io->write('');
7987 }
7988 }
7989
7990
7991  if ($mode & 2) {
7992
7993  if ($mode & 1) {
7994 $io->write(str_repeat('-', 78));
7995 }
7996 foreach ($suggested as $suggestion => $suggesters) {
7997 $io->write(sprintf('<comment>%s</comment> is suggested by:', $suggestion));
7998
7999 foreach ($suggesters as $suggester => $reason) {
8000 $io->write(sprintf(' - <info>%s</info>: %s', $suggester, $reason ?: '*'));
8001 }
8002 $io->write('');
8003 }
8004 }
8005 }
8006 }
8007 <?php
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019 namespace Composer\Command;
8020
8021 use Composer\Composer;
8022 use Composer\Installer;
8023 use Composer\IO\IOInterface;
8024 use Composer\Plugin\CommandEvent;
8025 use Composer\Plugin\PluginEvents;
8026 use Symfony\Component\Console\Helper\Table;
8027 use Symfony\Component\Console\Input\InputInterface;
8028 use Symfony\Component\Console\Input\InputOption;
8029 use Symfony\Component\Console\Input\InputArgument;
8030 use Symfony\Component\Console\Output\OutputInterface;
8031 use Symfony\Component\Console\Question\Question;
8032
8033
8034
8035
8036
8037 class UpdateCommand extends BaseCommand
8038 {
8039 protected function configure()
8040 {
8041 $this
8042 ->setName('update')
8043 ->setAliases(array('upgrade'))
8044 ->setDescription('Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
8045 ->setDefinition(array(
8046 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
8047 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
8048 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
8049 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
8050 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
8051 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
8052 new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
8053 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
8054 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
8055 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
8056 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
8057 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
8058 new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also dependencies of whitelisted packages to the whitelist, except those defined in root package.'),
8059 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.'),
8060 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
8061 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
8062 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
8063 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
8064 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
8065 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
8066 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
8067 new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
8068 new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
8069 ))
8070 ->setHelp(<<<EOT
8071 The <info>update</info> command reads the composer.json file from the
8072 current directory, processes it, and updates, removes or installs all the
8073 dependencies.
8074
8075 <info>php composer.phar update</info>
8076
8077 To limit the update operation to a few packages, you can list the package(s)
8078 you want to update as such:
8079
8080 <info>php composer.phar update vendor/package1 foo/mypackage [...]</info>
8081
8082 You may also use an asterisk (*) pattern to limit the update operation to package(s)
8083 from a specific vendor:
8084
8085 <info>php composer.phar update vendor/package1 foo/* [...]</info>
8086
8087 To select packages names interactively with auto-completion use <info>-i</info>.
8088
8089 EOT
8090 )
8091 ;
8092 }
8093
8094 protected function execute(InputInterface $input, OutputInterface $output)
8095 {
8096 $io = $this->getIO();
8097 if ($input->getOption('no-custom-installers')) {
8098 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
8099 $input->setOption('no-plugins', true);
8100 }
8101
8102 if ($input->getOption('dev')) {
8103 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
8104 }
8105
8106 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
8107
8108 $packages = $input->getArgument('packages');
8109
8110 if ($input->getOption('interactive')) {
8111 $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
8112 }
8113
8114 if ($input->getOption('root-reqs')) {
8115 $require = array_keys($composer->getPackage()->getRequires());
8116 if (!$input->getOption('no-dev')) {
8117 $requireDev = array_keys($composer->getPackage()->getDevRequires());
8118 $require = array_merge($require, $requireDev);
8119 }
8120
8121 if (!empty($packages)) {
8122 $packages = array_intersect($packages, $require);
8123 } else {
8124 $packages = $require;
8125 }
8126 }
8127
8128 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
8129
8130 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
8131 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8132
8133 $install = Installer::create($io, $composer);
8134
8135 $config = $composer->getConfig();
8136 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
8137
8138 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
8139 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
8140 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
8141
8142 $install
8143 ->setDryRun($input->getOption('dry-run'))
8144 ->setVerbose($input->getOption('verbose'))
8145 ->setPreferSource($preferSource)
8146 ->setPreferDist($preferDist)
8147 ->setDevMode(!$input->getOption('no-dev'))
8148 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
8149 ->setRunScripts(!$input->getOption('no-scripts'))
8150 ->setSkipSuggest($input->getOption('no-suggest'))
8151 ->setOptimizeAutoloader($optimize)
8152 ->setClassMapAuthoritative($authoritative)
8153 ->setApcuAutoloader($apcu)
8154 ->setUpdate(true)
8155 ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages)
8156 ->setWhitelistTransitiveDependencies($input->getOption('with-dependencies'))
8157 ->setWhitelistAllDependencies($input->getOption('with-all-dependencies'))
8158 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
8159 ->setPreferStable($input->getOption('prefer-stable'))
8160 ->setPreferLowest($input->getOption('prefer-lowest'))
8161 ;
8162
8163 if ($input->getOption('no-plugins')) {
8164 $install->disablePlugins();
8165 }
8166
8167 return $install->run();
8168 }
8169
8170 private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages)
8171 {
8172 if (!$input->isInteractive()) {
8173 throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
8174 }
8175
8176 $requires = array_merge(
8177 $composer->getPackage()->getRequires(),
8178 $composer->getPackage()->getDevRequires()
8179 );
8180 $autocompleterValues = array();
8181 foreach ($requires as $require) {
8182 $target = $require->getTarget();
8183 $autocompleterValues[strtolower($target)] = $target;
8184 }
8185
8186 $installedPackages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
8187 foreach ($installedPackages as $package) {
8188 $autocompleterValues[$package->getName()] = $package->getPrettyName();
8189 }
8190
8191 $helper = $this->getHelper('question');
8192 $question = new Question('<comment>Enter package name: </comment>', null);
8193
8194 $io->writeError('<info>Press enter without value to end submission</info>');
8195
8196 do {
8197 $autocompleterValues = array_diff($autocompleterValues, $packages);
8198 $question->setAutocompleterValues($autocompleterValues);
8199 $addedPackage = $helper->ask($input, $output, $question);
8200
8201 if (!is_string($addedPackage) || empty($addedPackage)) {
8202 break;
8203 }
8204
8205 $addedPackage = strtolower($addedPackage);
8206 if (!in_array($addedPackage, $packages)) {
8207 $packages[] = $addedPackage;
8208 }
8209 } while (true);
8210
8211 $packages = array_filter($packages);
8212 if (!$packages) {
8213 throw new \InvalidArgumentException('You must enter minimum one package.');
8214 }
8215
8216 $table = new Table($output);
8217 $table->setHeaders(array('Selected packages'));
8218 foreach ($packages as $package) {
8219 $table->addRow(array($package));
8220 }
8221 $table->render();
8222
8223 if ($io->askConfirmation(sprintf(
8224 'Would you like to continue and update the above package%s [<comment>yes</comment>]? ',
8225 1 === count($packages) ? '' : 's'
8226 ), true)) {
8227 return $packages;
8228 }
8229
8230 throw new \RuntimeException('Installation aborted.');
8231 }
8232 }
8233 <?php
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245 namespace Composer\Command;
8246
8247 use Composer\Factory;
8248 use Composer\Package\Loader\ValidatingArrayLoader;
8249 use Composer\Plugin\CommandEvent;
8250 use Composer\Plugin\PluginEvents;
8251 use Composer\Util\ConfigValidator;
8252 use Symfony\Component\Console\Input\InputArgument;
8253 use Symfony\Component\Console\Input\InputInterface;
8254 use Symfony\Component\Console\Input\InputOption;
8255 use Symfony\Component\Console\Output\OutputInterface;
8256
8257
8258
8259
8260
8261
8262
8263 class ValidateCommand extends BaseCommand
8264 {
8265
8266
8267
8268 protected function configure()
8269 {
8270 $this
8271 ->setName('validate')
8272 ->setDescription('Validates a composer.json and composer.lock.')
8273 ->setDefinition(array(
8274 new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'),
8275 new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
8276 new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
8277 new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
8278 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
8279 new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file'),
8280 ))
8281 ->setHelp(<<<EOT
8282 The validate command validates a given composer.json and composer.lock
8283
8284 Exit codes in case of errors are:
8285 1 validation warning(s), only when --strict is given
8286 2 validation error(s)
8287 3 file unreadable or missing
8288
8289 EOT
8290 );
8291 }
8292
8293
8294
8295
8296
8297
8298
8299 protected function execute(InputInterface $input, OutputInterface $output)
8300 {
8301 $file = $input->getArgument('file') ?: Factory::getComposerFile();
8302 $io = $this->getIO();
8303
8304 if (!file_exists($file)) {
8305 $io->writeError('<error>' . $file . ' not found.</error>');
8306
8307 return 3;
8308 }
8309 if (!is_readable($file)) {
8310 $io->writeError('<error>' . $file . ' is not readable.</error>');
8311
8312 return 3;
8313 }
8314
8315 $validator = new ConfigValidator($io);
8316 $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
8317 $checkPublish = !$input->getOption('no-check-publish');
8318 $checkLock = !$input->getOption('no-check-lock');
8319 $isStrict = $input->getOption('strict');
8320 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8321
8322 $lockErrors = array();
8323 $composer = Factory::create($io, $file);
8324 $locker = $composer->getLocker();
8325 if ($locker->isLocked() && !$locker->isFresh()) {
8326 $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update`.';
8327 }
8328
8329 $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true);
8330
8331 $exitCode = $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 2 : ($isStrict && $warnings ? 1 : 0);
8332
8333 if ($input->getOption('with-dependencies')) {
8334 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
8335 foreach ($localRepo->getPackages() as $package) {
8336 $path = $composer->getInstallationManager()->getInstallPath($package);
8337 $file = $path . '/composer.json';
8338 if (is_dir($path) && file_exists($file)) {
8339 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8340 $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
8341
8342 $depCode = $errors || ($publishErrors && $checkPublish) ? 2 : ($isStrict && $warnings ? 1 : 0);
8343 $exitCode = max($depCode, $exitCode);
8344 }
8345 }
8346 }
8347
8348 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
8349 $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8350 $exitCode = max($eventCode, $exitCode);
8351
8352 return $exitCode;
8353 }
8354
8355 private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false)
8356 {
8357 if (!$errors && !$publishErrors && !$warnings) {
8358 $io->write('<info>' . $name . ' is valid</info>');
8359 } elseif (!$errors && !$publishErrors) {
8360 $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
8361 if ($printSchemaUrl) {
8362 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8363 }
8364 } elseif (!$errors) {
8365 $io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
8366 $io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
8367 if ($printSchemaUrl) {
8368 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8369 }
8370 } else {
8371 $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
8372 }
8373
8374
8375  if ($checkPublish) {
8376 $errors = array_merge($errors, $publishErrors);
8377 } else {
8378 $warnings = array_merge($warnings, $publishErrors);
8379 }
8380
8381
8382  if ($checkLock) {
8383 $errors = array_merge($errors, $lockErrors);
8384 } else {
8385 $warnings = array_merge($warnings, $lockErrors);
8386 }
8387
8388 $messages = array(
8389 'error' => $errors,
8390 'warning' => $warnings,
8391 );
8392
8393 foreach ($messages as $style => $msgs) {
8394 foreach ($msgs as $msg) {
8395 $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
8396 }
8397 }
8398 }
8399 }
8400 <?php
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412 namespace Composer;
8413
8414 use Composer\Package\RootPackageInterface;
8415 use Composer\Package\Locker;
8416 use Composer\Repository\RepositoryManager;
8417 use Composer\Installer\InstallationManager;
8418 use Composer\Plugin\PluginManager;
8419 use Composer\Downloader\DownloadManager;
8420 use Composer\EventDispatcher\EventDispatcher;
8421 use Composer\Autoload\AutoloadGenerator;
8422 use Composer\Package\Archiver\ArchiveManager;
8423
8424
8425
8426
8427
8428
8429 class Composer
8430 {
8431 const VERSION = '1.6.2';
8432 const BRANCH_ALIAS_VERSION = '';
8433 const RELEASE_DATE = '2018-01-05 15:28:41';
8434
8435
8436
8437
8438 private $package;
8439
8440
8441
8442
8443 private $locker;
8444
8445
8446
8447
8448 private $repositoryManager;
8449
8450
8451
8452
8453 private $downloadManager;
8454
8455
8456
8457
8458 private $installationManager;
8459
8460
8461
8462
8463 private $pluginManager;
8464
8465
8466
8467
8468 private $config;
8469
8470
8471
8472
8473 private $eventDispatcher;
8474
8475
8476
8477
8478 private $autoloadGenerator;
8479
8480
8481
8482
8483 private $archiveManager;
8484
8485
8486
8487
8488
8489 public function setPackage(RootPackageInterface $package)
8490 {
8491 $this->package = $package;
8492 }
8493
8494
8495
8496
8497 public function getPackage()
8498 {
8499 return $this->package;
8500 }
8501
8502
8503
8504
8505 public function setConfig(Config $config)
8506 {
8507 $this->config = $config;
8508 }
8509
8510
8511
8512
8513 public function getConfig()
8514 {
8515 return $this->config;
8516 }
8517
8518
8519
8520
8521 public function setLocker(Locker $locker)
8522 {
8523 $this->locker = $locker;
8524 }
8525
8526
8527
8528
8529 public function getLocker()
8530 {
8531 return $this->locker;
8532 }
8533
8534
8535
8536
8537 public function setRepositoryManager(RepositoryManager $manager)
8538 {
8539 $this->repositoryManager = $manager;
8540 }
8541
8542
8543
8544
8545 public function getRepositoryManager()
8546 {
8547 return $this->repositoryManager;
8548 }
8549
8550
8551
8552
8553 public function setDownloadManager(DownloadManager $manager)
8554 {
8555 $this->downloadManager = $manager;
8556 }
8557
8558
8559
8560
8561 public function getDownloadManager()
8562 {
8563 return $this->downloadManager;
8564 }
8565
8566
8567
8568
8569 public function setArchiveManager(ArchiveManager $manager)
8570 {
8571 $this->archiveManager = $manager;
8572 }
8573
8574
8575
8576
8577 public function getArchiveManager()
8578 {
8579 return $this->archiveManager;
8580 }
8581
8582
8583
8584
8585 public function setInstallationManager(InstallationManager $manager)
8586 {
8587 $this->installationManager = $manager;
8588 }
8589
8590
8591
8592
8593 public function getInstallationManager()
8594 {
8595 return $this->installationManager;
8596 }
8597
8598
8599
8600
8601 public function setPluginManager(PluginManager $manager)
8602 {
8603 $this->pluginManager = $manager;
8604 }
8605
8606
8607
8608
8609 public function getPluginManager()
8610 {
8611 return $this->pluginManager;
8612 }
8613
8614
8615
8616
8617 public function setEventDispatcher(EventDispatcher $eventDispatcher)
8618 {
8619 $this->eventDispatcher = $eventDispatcher;
8620 }
8621
8622
8623
8624
8625 public function getEventDispatcher()
8626 {
8627 return $this->eventDispatcher;
8628 }
8629
8630
8631
8632
8633 public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
8634 {
8635 $this->autoloadGenerator = $autoloadGenerator;
8636 }
8637
8638
8639
8640
8641 public function getAutoloadGenerator()
8642 {
8643 return $this->autoloadGenerator;
8644 }
8645 }
8646 <?php
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658 namespace Composer;
8659
8660 use Composer\Config\ConfigSourceInterface;
8661 use Composer\Downloader\TransportException;
8662 use Composer\IO\IOInterface;
8663 use Composer\Util\Platform;
8664
8665
8666
8667
8668 class Config
8669 {
8670 const RELATIVE_PATHS = 1;
8671
8672 public static $defaultConfig = array(
8673 'process-timeout' => 300,
8674 'use-include-path' => false,
8675 'preferred-install' => 'auto',
8676 'notify-on-install' => true,
8677 'github-protocols' => array('https', 'ssh', 'git'),
8678 'vendor-dir' => 'vendor',
8679 'bin-dir' => '{$vendor-dir}/bin',
8680 'cache-dir' => '{$home}/cache',
8681 'data-dir' => '{$home}',
8682 'cache-files-dir' => '{$cache-dir}/files',
8683 'cache-repo-dir' => '{$cache-dir}/repo',
8684 'cache-vcs-dir' => '{$cache-dir}/vcs',
8685 'cache-ttl' => 15552000, 
8686  'cache-files-ttl' => null, 
8687  'cache-files-maxsize' => '300MiB',
8688 'bin-compat' => 'auto',
8689 'discard-changes' => false,
8690 'autoloader-suffix' => null,
8691 'sort-packages' => false,
8692 'optimize-autoloader' => false,
8693 'classmap-authoritative' => false,
8694 'apcu-autoloader' => false,
8695 'prepend-autoloader' => true,
8696 'github-domains' => array('github.com'),
8697 'bitbucket-expose-hostname' => true,
8698 'disable-tls' => false,
8699 'secure-http' => true,
8700 'cafile' => null,
8701 'capath' => null,
8702 'github-expose-hostname' => true,
8703 'gitlab-domains' => array('gitlab.com'),
8704 'store-auths' => 'prompt',
8705 'platform' => array(),
8706 'archive-format' => 'tar',
8707 'archive-dir' => '.',
8708 'htaccess-protect' => true,
8709
8710  
8711  
8712  
8713  
8714  
8715  );
8716
8717 public static $defaultRepositories = array(
8718 'packagist.org' => array(
8719 'type' => 'composer',
8720 'url' => 'https?://packagist.org',
8721 'allow_ssl_downgrade' => true,
8722 ),
8723 );
8724
8725 private $config;
8726 private $baseDir;
8727 private $repositories;
8728
8729 private $configSource;
8730
8731 private $authConfigSource;
8732 private $useEnvironment;
8733 private $warnedHosts = array();
8734
8735
8736
8737
8738
8739 public function __construct($useEnvironment = true, $baseDir = null)
8740 {
8741
8742  $this->config = static::$defaultConfig;
8743 $this->repositories = static::$defaultRepositories;
8744 $this->useEnvironment = (bool) $useEnvironment;
8745 $this->baseDir = $baseDir;
8746 }
8747
8748 public function setConfigSource(ConfigSourceInterface $source)
8749 {
8750 $this->configSource = $source;
8751 }
8752
8753 public function getConfigSource()
8754 {
8755 return $this->configSource;
8756 }
8757
8758 public function setAuthConfigSource(ConfigSourceInterface $source)
8759 {
8760 $this->authConfigSource = $source;
8761 }
8762
8763 public function getAuthConfigSource()
8764 {
8765 return $this->authConfigSource;
8766 }
8767
8768
8769
8770
8771
8772
8773 public function merge($config)
8774 {
8775
8776  if (!empty($config['config']) && is_array($config['config'])) {
8777 foreach ($config['config'] as $key => $val) {
8778 if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic')) && isset($this->config[$key])) {
8779 $this->config[$key] = array_merge($this->config[$key], $val);
8780 } elseif ('preferred-install' === $key && isset($this->config[$key])) {
8781 if (is_array($val) || is_array($this->config[$key])) {
8782 if (is_string($val)) {
8783 $val = array('*' => $val);
8784 }
8785 if (is_string($this->config[$key])) {
8786 $this->config[$key] = array('*' => $this->config[$key]);
8787 }
8788 $this->config[$key] = array_merge($this->config[$key], $val);
8789
8790  if (isset($this->config[$key]['*'])) {
8791 $wildcard = $this->config[$key]['*'];
8792 unset($this->config[$key]['*']);
8793 $this->config[$key]['*'] = $wildcard;
8794 }
8795 } else {
8796 $this->config[$key] = $val;
8797 }
8798 } else {
8799 $this->config[$key] = $val;
8800 }
8801 }
8802 }
8803
8804 if (!empty($config['repositories']) && is_array($config['repositories'])) {
8805 $this->repositories = array_reverse($this->repositories, true);
8806 $newRepos = array_reverse($config['repositories'], true);
8807 foreach ($newRepos as $name => $repository) {
8808
8809  if (false === $repository) {
8810 $this->disableRepoByName($name);
8811 continue;
8812 }
8813
8814
8815  if (is_array($repository) && 1 === count($repository) && false === current($repository)) {
8816 $this->disableRepoByName(key($repository));
8817 continue;
8818 }
8819
8820
8821  if (is_int($name)) {
8822 $this->repositories[] = $repository;
8823 } else {
8824 if ($name === 'packagist') { 
8825  $this->repositories[$name . '.org'] = $repository;
8826 } else {
8827 $this->repositories[$name] = $repository;
8828 }
8829 }
8830 }
8831 $this->repositories = array_reverse($this->repositories, true);
8832 }
8833 }
8834
8835
8836
8837
8838 public function getRepositories()
8839 {
8840 return $this->repositories;
8841 }
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851 public function get($key, $flags = 0)
8852 {
8853 switch ($key) {
8854 case 'vendor-dir':
8855 case 'bin-dir':
8856 case 'process-timeout':
8857 case 'data-dir':
8858 case 'cache-dir':
8859 case 'cache-files-dir':
8860 case 'cache-repo-dir':
8861 case 'cache-vcs-dir':
8862 case 'cafile':
8863 case 'capath':
8864 case 'htaccess-protect':
8865
8866  $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
8867
8868 $val = $this->getComposerEnv($env);
8869 $val = rtrim((string) $this->process(false !== $val ? $val : $this->config[$key], $flags), '/\\');
8870 $val = Platform::expandPath($val);
8871
8872 if (substr($key, -4) !== '-dir') {
8873 return $val;
8874 }
8875
8876 return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
8877
8878 case 'cache-ttl':
8879 return (int) $this->config[$key];
8880
8881 case 'cache-files-maxsize':
8882 if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
8883 throw new \RuntimeException(
8884 "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
8885 );
8886 }
8887 $size = $matches[1];
8888 if (isset($matches[2])) {
8889 switch (strtolower($matches[2])) {
8890 case 'g':
8891 $size *= 1024;
8892
8893  case 'm':
8894 $size *= 1024;
8895
8896  case 'k':
8897 $size *= 1024;
8898 break;
8899 }
8900 }
8901
8902 return $size;
8903
8904 case 'cache-files-ttl':
8905 if (isset($this->config[$key])) {
8906 return (int) $this->config[$key];
8907 }
8908
8909 return (int) $this->config['cache-ttl'];
8910
8911 case 'home':
8912 $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $this->config[$key]);
8913
8914 return rtrim($this->process($val, $flags), '/\\');
8915
8916 case 'bin-compat':
8917 $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
8918
8919 if (!in_array($value, array('auto', 'full'))) {
8920 throw new \RuntimeException(
8921 "Invalid value for 'bin-compat': {$value}. Expected auto, full"
8922 );
8923 }
8924
8925 return $value;
8926
8927 case 'discard-changes':
8928 if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
8929 if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
8930 throw new \RuntimeException(
8931 "Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"
8932 );
8933 }
8934 if ('stash' === $env) {
8935 return 'stash';
8936 }
8937
8938
8939  return $env !== 'false' && (bool) $env;
8940 }
8941
8942 if (!in_array($this->config[$key], array(true, false, 'stash'), true)) {
8943 throw new \RuntimeException(
8944 "Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"
8945 );
8946 }
8947
8948 return $this->config[$key];
8949
8950 case 'github-protocols':
8951 $protos = $this->config['github-protocols'];
8952 if ($this->config['secure-http'] && false !== ($index = array_search('git', $protos))) {
8953 unset($protos[$index]);
8954 }
8955 if (reset($protos) === 'http') {
8956 throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
8957 }
8958
8959 return $protos;
8960
8961 case 'disable-tls':
8962 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
8963
8964 case 'secure-http':
8965 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
8966
8967 default:
8968 if (!isset($this->config[$key])) {
8969 return null;
8970 }
8971
8972 return $this->process($this->config[$key], $flags);
8973 }
8974 }
8975
8976 public function all($flags = 0)
8977 {
8978 $all = array(
8979 'repositories' => $this->getRepositories(),
8980 );
8981 foreach (array_keys($this->config) as $key) {
8982 $all['config'][$key] = $this->get($key, $flags);
8983 }
8984
8985 return $all;
8986 }
8987
8988 public function raw()
8989 {
8990 return array(
8991 'repositories' => $this->getRepositories(),
8992 'config' => $this->config,
8993 );
8994 }
8995
8996
8997
8998
8999
9000
9001
9002 public function has($key)
9003 {
9004 return array_key_exists($key, $this->config);
9005 }
9006
9007
9008
9009
9010
9011
9012
9013
9014 private function process($value, $flags)
9015 {
9016 $config = $this;
9017
9018 if (!is_string($value)) {
9019 return $value;
9020 }
9021
9022 return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
9023 return $config->get($match[1], $flags);
9024 }, $value);
9025 }
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035 private function realpath($path)
9036 {
9037 if (preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) {
9038 return $path;
9039 }
9040
9041 return $this->baseDir . '/' . $path;
9042 }
9043
9044
9045
9046
9047
9048
9049
9050
9051
9052
9053 private function getComposerEnv($var)
9054 {
9055 if ($this->useEnvironment) {
9056 return getenv($var);
9057 }
9058
9059 return false;
9060 }
9061
9062 private function disableRepoByName($name)
9063 {
9064 if (isset($this->repositories[$name])) {
9065 unset($this->repositories[$name]);
9066 } elseif ($name === 'packagist') { 
9067  unset($this->repositories['packagist.org']);
9068 }
9069 }
9070
9071
9072
9073
9074
9075
9076
9077 public function prohibitUrlByConfig($url, IOInterface $io = null)
9078 {
9079
9080  if (false === filter_var($url, FILTER_VALIDATE_URL)) {
9081 return;
9082 }
9083
9084
9085  $scheme = parse_url($url, PHP_URL_SCHEME);
9086 if (in_array($scheme, array('http', 'git', 'ftp', 'svn'))) {
9087 if ($this->get('secure-http')) {
9088 throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
9089 } elseif ($io) {
9090 $host = parse_url($url, PHP_URL_HOST);
9091 if (!isset($this->warnedHosts[$host])) {
9092 $io->writeError("<warning>Warning: Accessing $host over $scheme which is an insecure protocol.</warning>");
9093 }
9094 $this->warnedHosts[$host] = true;
9095 }
9096 }
9097 }
9098 }
9099 <?php
9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111 namespace Composer\Config;
9112
9113
9114
9115
9116
9117
9118
9119 interface ConfigSourceInterface
9120 {
9121
9122
9123
9124
9125
9126
9127 public function addRepository($name, $config);
9128
9129
9130
9131
9132
9133
9134 public function removeRepository($name);
9135
9136
9137
9138
9139
9140
9141
9142 public function addConfigSetting($name, $value);
9143
9144
9145
9146
9147
9148
9149 public function removeConfigSetting($name);
9150
9151
9152
9153
9154
9155
9156
9157 public function addProperty($name, $value);
9158
9159
9160
9161
9162
9163
9164 public function removeProperty($name);
9165
9166
9167
9168
9169
9170
9171
9172
9173 public function addLink($type, $name, $value);
9174
9175
9176
9177
9178
9179
9180
9181 public function removeLink($type, $name);
9182
9183
9184
9185
9186
9187
9188 public function getName();
9189 }
9190 <?php
9191
9192
9193
9194
9195
9196
9197
9198
9199
9200
9201
9202 namespace Composer\Config;
9203
9204 use Composer\Json\JsonFile;
9205 use Composer\Json\JsonManipulator;
9206 use Composer\Util\Silencer;
9207
9208
9209
9210
9211
9212
9213
9214 class JsonConfigSource implements ConfigSourceInterface
9215 {
9216
9217
9218
9219 private $file;
9220
9221
9222
9223
9224 private $authConfig;
9225
9226
9227
9228
9229
9230
9231
9232 public function __construct(JsonFile $file, $authConfig = false)
9233 {
9234 $this->file = $file;
9235 $this->authConfig = $authConfig;
9236 }
9237
9238
9239
9240
9241 public function getName()
9242 {
9243 return $this->file->getPath();
9244 }
9245
9246
9247
9248
9249 public function addRepository($name, $config)
9250 {
9251 $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
9252
9253  
9254  if (isset($config['repositories'])) {
9255 foreach ($config['repositories'] as $index => $val) {
9256 if ($index === $repo) {
9257 continue;
9258 }
9259 if (is_numeric($index) && ($val === array('packagist' => false) || $val === array('packagist.org' => false))) {
9260 unset($config['repositories'][$index]);
9261 $config['repositories']['packagist.org'] = false;
9262 break;
9263 }
9264 }
9265 }
9266
9267 $config['repositories'][$repo] = $repoConfig;
9268 });
9269 }
9270
9271
9272
9273
9274 public function removeRepository($name)
9275 {
9276 $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
9277 unset($config['repositories'][$repo]);
9278 });
9279 }
9280
9281
9282
9283
9284 public function addConfigSetting($name, $value)
9285 {
9286 $authConfig = $this->authConfig;
9287 $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) {
9288 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9289 list($key, $host) = explode('.', $key, 2);
9290 if ($authConfig) {
9291 $config[$key][$host] = $val;
9292 } else {
9293 $config['config'][$key][$host] = $val;
9294 }
9295 } else {
9296 $config['config'][$key] = $val;
9297 }
9298 });
9299 }
9300
9301
9302
9303
9304 public function removeConfigSetting($name)
9305 {
9306 $authConfig = $this->authConfig;
9307 $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) {
9308 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9309 list($key, $host) = explode('.', $key, 2);
9310 if ($authConfig) {
9311 unset($config[$key][$host]);
9312 } else {
9313 unset($config['config'][$key][$host]);
9314 }
9315 } else {
9316 unset($config['config'][$key]);
9317 }
9318 });
9319 }
9320
9321
9322
9323
9324 public function addProperty($name, $value)
9325 {
9326 $this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) {
9327 if (substr($key, 0, 6) === 'extra.') {
9328 $bits = explode('.', $key);
9329 $last = array_pop($bits);
9330 $arr = &$config['extra'];
9331 foreach ($bits as $bit) {
9332 if (!isset($arr[$bit])) {
9333 $arr[$bit] = array();
9334 }
9335 $arr = &$arr[$bit];
9336 }
9337 $arr[$last] = $val;
9338 } else {
9339 $config[$key] = $val;
9340 }
9341 });
9342 }
9343
9344
9345
9346
9347 public function removeProperty($name)
9348 {
9349 $authConfig = $this->authConfig;
9350 $this->manipulateJson('removeProperty', $name, function (&$config, $key) {
9351 if (substr($key, 0, 6) === 'extra.') {
9352 $bits = explode('.', $key);
9353 $last = array_pop($bits);
9354 $arr = &$config['extra'];
9355 foreach ($bits as $bit) {
9356 if (!isset($arr[$bit])) {
9357 return;
9358 }
9359 $arr = &$arr[$bit];
9360 }
9361 unset($arr[$last]);
9362 } else {
9363 unset($config[$key]);
9364 }
9365 });
9366 }
9367
9368
9369
9370
9371 public function addLink($type, $name, $value)
9372 {
9373 $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
9374 $config[$type][$name] = $value;
9375 });
9376 }
9377
9378
9379
9380
9381 public function removeLink($type, $name)
9382 {
9383 $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
9384 unset($config[$type][$name]);
9385 });
9386 }
9387
9388 protected function manipulateJson($method, $args, $fallback)
9389 {
9390 $args = func_get_args();
9391
9392  array_shift($args);
9393 $fallback = array_pop($args);
9394
9395 if ($this->file->exists()) {
9396 if (!is_writable($this->file->getPath())) {
9397 throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
9398 }
9399
9400 if (!is_readable($this->file->getPath())) {
9401 throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
9402 }
9403
9404 $contents = file_get_contents($this->file->getPath());
9405 } elseif ($this->authConfig) {
9406 $contents = "{\n}\n";
9407 } else {
9408 $contents = "{\n    \"config\": {\n    }\n}\n";
9409 }
9410
9411 $manipulator = new JsonManipulator($contents);
9412
9413 $newFile = !$this->file->exists();
9414
9415
9416  if ($this->authConfig && $method === 'addConfigSetting') {
9417 $method = 'addSubNode';
9418 list($mainNode, $name) = explode('.', $args[0], 2);
9419 $args = array($mainNode, $name, $args[1]);
9420 } elseif ($this->authConfig && $method === 'removeConfigSetting') {
9421 $method = 'removeSubNode';
9422 list($mainNode, $name) = explode('.', $args[0], 2);
9423 $args = array($mainNode, $name);
9424 }
9425
9426
9427  if (call_user_func_array(array($manipulator, $method), $args)) {
9428 file_put_contents($this->file->getPath(), $manipulator->getContents());
9429 } else {
9430
9431  $config = $this->file->read();
9432 $this->arrayUnshiftRef($args, $config);
9433 call_user_func_array($fallback, $args);
9434 $this->file->write($config);
9435 }
9436
9437 if ($newFile) {
9438 Silencer::call('chmod', $this->file->getPath(), 0600);
9439 }
9440 }
9441
9442
9443
9444
9445
9446
9447
9448
9449 private function arrayUnshiftRef(&$array, &$value)
9450 {
9451 $return = array_unshift($array, '');
9452 $array[0] = &$value;
9453
9454 return $return;
9455 }
9456 }
9457 <?php
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468
9469 namespace Composer\Console;
9470
9471 use Composer\Util\Platform;
9472 use Composer\Util\Silencer;
9473 use Symfony\Component\Console\Application as BaseApplication;
9474 use Symfony\Component\Console\Input\InputInterface;
9475 use Symfony\Component\Console\Input\InputOption;
9476 use Symfony\Component\Console\Output\OutputInterface;
9477 use Composer\Command;
9478 use Composer\Composer;
9479 use Composer\Factory;
9480 use Composer\IO\IOInterface;
9481 use Composer\IO\ConsoleIO;
9482 use Composer\Json\JsonValidationException;
9483 use Composer\Util\ErrorHandler;
9484 use Composer\EventDispatcher\ScriptExecutionException;
9485 use Composer\Exception\NoSslException;
9486
9487
9488
9489
9490
9491
9492
9493
9494 class Application extends BaseApplication
9495 {
9496
9497
9498
9499 protected $composer;
9500
9501
9502
9503
9504 protected $io;
9505
9506 private static $logo = '   ______
9507   / ____/___  ____ ___  ____  ____  ________  _____
9508  / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
9509 / /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
9510 \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
9511                     /_/
9512 ';
9513
9514 private $hasPluginCommands = false;
9515 private $disablePluginsByDefault = false;
9516
9517 public function __construct()
9518 {
9519 static $shutdownRegistered = false;
9520
9521 if (function_exists('ini_set') && extension_loaded('xdebug')) {
9522 ini_set('xdebug.show_exception_trace', false);
9523 ini_set('xdebug.scream', false);
9524 }
9525
9526 if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
9527 date_default_timezone_set(Silencer::call('date_default_timezone_get'));
9528 }
9529
9530 if (!$shutdownRegistered) {
9531 $shutdownRegistered = true;
9532
9533 register_shutdown_function(function () {
9534 $lastError = error_get_last();
9535
9536 if ($lastError && $lastError['message'] &&
9537 (strpos($lastError['message'], 'Allowed memory') !== false  ||
9538 strpos($lastError['message'], 'exceeded memory') !== false )) {
9539 echo "\n". 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
9540 }
9541 });
9542 }
9543
9544 parent::__construct('Composer', Composer::VERSION);
9545 }
9546
9547
9548
9549
9550 public function run(InputInterface $input = null, OutputInterface $output = null)
9551 {
9552 if (null === $output) {
9553 $output = Factory::createOutput();
9554 }
9555
9556 return parent::run($input, $output);
9557 }
9558
9559
9560
9561
9562 public function doRun(InputInterface $input, OutputInterface $output)
9563 {
9564 $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
9565
9566 $io = $this->io = new ConsoleIO($input, $output, $this->getHelperSet());
9567 ErrorHandler::register($io);
9568
9569
9570  if ($newWorkDir = $this->getNewWorkingDir($input)) {
9571 $oldWorkingDir = getcwd();
9572 chdir($newWorkDir);
9573 $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
9574 }
9575
9576
9577  $commandName = '';
9578 if ($name = $this->getCommandName($input)) {
9579 try {
9580 $commandName = $this->find($name)->getName();
9581 } catch (\InvalidArgumentException $e) {
9582 }
9583 }
9584
9585
9586  if ($io->isInteractive() && !$newWorkDir && !in_array($commandName, array('', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project'), true) && !file_exists(Factory::getComposerFile())) {
9587 $dir = dirname(getcwd());
9588 $home = realpath(getenv('HOME') ?: getenv('USERPROFILE') ?: '/');
9589
9590
9591  while (dirname($dir) !== $dir && $dir !== $home) {
9592 if (file_exists($dir.'/'.Factory::getComposerFile())) {
9593 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)) {
9594 $oldWorkingDir = getcwd();
9595 chdir($dir);
9596 }
9597 break;
9598 }
9599 $dir = dirname($dir);
9600 }
9601 }
9602
9603 if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
9604 try {
9605 foreach ($this->getPluginCommands() as $command) {
9606 if ($this->has($command->getName())) {
9607 $io->writeError('<warning>Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped</warning>');
9608 } else {
9609 $this->add($command);
9610 }
9611 }
9612 } catch (NoSslException $e) {
9613
9614  }
9615
9616 $this->hasPluginCommands = true;
9617 }
9618
9619
9620  $isProxyCommand = false;
9621 if ($name = $this->getCommandName($input)) {
9622 try {
9623 $command = $this->find($name);
9624 $commandName = $command->getName();
9625 $isProxyCommand = ($command instanceof Command\BaseCommand && $command->isProxyCommand());
9626 } catch (\InvalidArgumentException $e) {
9627 }
9628 }
9629
9630 if (!$isProxyCommand) {
9631 $io->writeError(sprintf(
9632 'Running %s (%s) with %s on %s',
9633 Composer::VERSION,
9634 Composer::RELEASE_DATE,
9635 defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
9636 function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
9637 ), true, IOInterface::DEBUG);
9638
9639 if (PHP_VERSION_ID < 50302) {
9640 $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>');
9641 }
9642
9643 if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
9644 $io->writeError('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
9645 }
9646
9647 if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
9648 $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']));
9649 }
9650
9651 if (getenv('COMPOSER_NO_INTERACTION')) {
9652 $input->setInteractive(false);
9653 }
9654
9655 if (!Platform::isWindows() && function_exists('exec') && !getenv('COMPOSER_ALLOW_SUPERUSER')) {
9656 if (function_exists('posix_getuid') && posix_getuid() === 0) {
9657 if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
9658 $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
9659 }
9660 if ($uid = (int) getenv('SUDO_UID')) {
9661
9662  
9663  Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
9664 }
9665 }
9666
9667  Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
9668 }
9669
9670
9671  Silencer::call(function () use ($io) {
9672 $tempfile = sys_get_temp_dir() . '/temp-' . md5(microtime());
9673 if (!(file_put_contents($tempfile, __FILE__) && (file_get_contents($tempfile) == __FILE__) && unlink($tempfile) && !file_exists($tempfile))) {
9674 $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()));
9675 }
9676 });
9677
9678
9679  $file = Factory::getComposerFile();
9680 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
9681 if (isset($composer['scripts']) && is_array($composer['scripts'])) {
9682 foreach ($composer['scripts'] as $script => $dummy) {
9683 if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
9684 if ($this->has($script)) {
9685 $io->writeError('<warning>A script named '.$script.' would override a Composer command and has been skipped</warning>');
9686 } else {
9687 $description = null;
9688
9689 if (isset($composer['scripts-descriptions'][$script])) {
9690 $description = $composer['scripts-descriptions'][$script];
9691 }
9692
9693 $this->add(new Command\ScriptAliasCommand($script, $description));
9694 }
9695 }
9696 }
9697 }
9698 }
9699 }
9700
9701 try {
9702 if ($input->hasParameterOption('--profile')) {
9703 $startTime = microtime(true);
9704 $this->io->enableDebugging($startTime);
9705 }
9706
9707 $result = parent::doRun($input, $output);
9708
9709 if (isset($oldWorkingDir)) {
9710 chdir($oldWorkingDir);
9711 }
9712
9713 if (isset($startTime)) {
9714 $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');
9715 }
9716
9717 restore_error_handler();
9718
9719 return $result;
9720 } catch (ScriptExecutionException $e) {
9721 return $e->getCode();
9722 } catch (\Exception $e) {
9723 $this->hintCommonErrors($e);
9724 restore_error_handler();
9725 throw $e;
9726 }
9727 }
9728
9729
9730
9731
9732
9733
9734 private function getNewWorkingDir(InputInterface $input)
9735 {
9736 $workingDir = $input->getParameterOption(array('--working-dir', '-d'));
9737 if (false !== $workingDir && !is_dir($workingDir)) {
9738 throw new \RuntimeException('Invalid working directory specified, '.$workingDir.' does not exist.');
9739 }
9740
9741 return $workingDir;
9742 }
9743
9744
9745
9746
9747 private function hintCommonErrors($exception)
9748 {
9749 $io = $this->getIO();
9750
9751 Silencer::suppress();
9752 try {
9753 $composer = $this->getComposer(false, true);
9754 if ($composer) {
9755 $config = $composer->getConfig();
9756
9757 $minSpaceFree = 1024 * 1024;
9758 if ((($df = disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
9759 || (($df = disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
9760 || (($df = disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
9761 ) {
9762 $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>', true, IOInterface::QUIET);
9763 }
9764 }
9765 } catch (\Exception $e) {
9766 }
9767 Silencer::restore();
9768
9769 if (Platform::isWindows() && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
9770 $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', true, IOInterface::QUIET);
9771 $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);
9772 }
9773
9774 if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
9775 $io->writeError('<error>The following exception is caused by a lack of memory or swap, or not having swap configured</error>', true, IOInterface::QUIET);
9776 $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
9777 }
9778 }
9779
9780
9781
9782
9783
9784
9785
9786 public function getComposer($required = true, $disablePlugins = null)
9787 {
9788 if (null === $disablePlugins) {
9789 $disablePlugins = $this->disablePluginsByDefault;
9790 }
9791
9792 if (null === $this->composer) {
9793 try {
9794 $this->composer = Factory::create($this->io, null, $disablePlugins);
9795 } catch (\InvalidArgumentException $e) {
9796 if ($required) {
9797 $this->io->writeError($e->getMessage());
9798 exit(1);
9799 }
9800 } catch (JsonValidationException $e) {
9801 $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
9802 $message = $e->getMessage() . ':' . PHP_EOL . $errors;
9803 throw new JsonValidationException($message);
9804 }
9805 }
9806
9807 return $this->composer;
9808 }
9809
9810
9811
9812
9813 public function resetComposer()
9814 {
9815 $this->composer = null;
9816 }
9817
9818
9819
9820
9821 public function getIO()
9822 {
9823 return $this->io;
9824 }
9825
9826 public function getHelp()
9827 {
9828 return self::$logo . parent::getHelp();
9829 }
9830
9831
9832
9833
9834 protected function getDefaultCommands()
9835 {
9836 $commands = array_merge(parent::getDefaultCommands(), array(
9837 new Command\AboutCommand(),
9838 new Command\ConfigCommand(),
9839 new Command\DependsCommand(),
9840 new Command\ProhibitsCommand(),
9841 new Command\InitCommand(),
9842 new Command\InstallCommand(),
9843 new Command\CreateProjectCommand(),
9844 new Command\UpdateCommand(),
9845 new Command\SearchCommand(),
9846 new Command\ValidateCommand(),
9847 new Command\ShowCommand(),
9848 new Command\SuggestsCommand(),
9849 new Command\RequireCommand(),
9850 new Command\DumpAutoloadCommand(),
9851 new Command\StatusCommand(),
9852 new Command\ArchiveCommand(),
9853 new Command\DiagnoseCommand(),
9854 new Command\RunScriptCommand(),
9855 new Command\LicensesCommand(),
9856 new Command\GlobalCommand(),
9857 new Command\ClearCacheCommand(),
9858 new Command\RemoveCommand(),
9859 new Command\HomeCommand(),
9860 new Command\ExecCommand(),
9861 new Command\OutdatedCommand(),
9862 new Command\CheckPlatformReqsCommand(),
9863 ));
9864
9865 if ('phar:' === substr(__FILE__, 0, 5)) {
9866 $commands[] = new Command\SelfUpdateCommand();
9867 }
9868
9869 return $commands;
9870 }
9871
9872
9873
9874
9875 public function getLongVersion()
9876 {
9877 if (Composer::BRANCH_ALIAS_VERSION) {
9878 return sprintf(
9879 '<info>%s</info> version <comment>%s (%s)</comment> %s',
9880 $this->getName(),
9881 Composer::BRANCH_ALIAS_VERSION,
9882 $this->getVersion(),
9883 Composer::RELEASE_DATE
9884 );
9885 }
9886
9887 return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE;
9888 }
9889
9890
9891
9892
9893 protected function getDefaultInputDefinition()
9894 {
9895 $definition = parent::getDefaultInputDefinition();
9896 $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
9897 $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'));
9898 $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
9899
9900 return $definition;
9901 }
9902
9903 private function getPluginCommands()
9904 {
9905 $commands = array();
9906
9907 $composer = $this->getComposer(false, false);
9908 if (null === $composer) {
9909 $composer = Factory::createGlobal($this->io, false);
9910 }
9911
9912 if (null !== $composer) {
9913 $pm = $composer->getPluginManager();
9914 foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $composer, 'io' => $this->io)) as $capability) {
9915 $newCommands = $capability->getCommands();
9916 if (!is_array($newCommands)) {
9917 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands');
9918 }
9919 foreach ($newCommands as $command) {
9920 if (!$command instanceof Command\BaseCommand) {
9921 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects');
9922 }
9923 }
9924 $commands = array_merge($commands, $newCommands);
9925 }
9926 }
9927
9928 return $commands;
9929 }
9930 }
9931 <?php
9932
9933
9934
9935
9936
9937
9938
9939
9940
9941
9942
9943 namespace Composer\Console;
9944
9945 use Symfony\Component\Console\Formatter\OutputFormatter;
9946
9947
9948
9949
9950 class HtmlOutputFormatter extends OutputFormatter
9951 {
9952 private static $availableForegroundColors = array(
9953 30 => 'black',
9954 31 => 'red',
9955 32 => 'green',
9956 33 => 'yellow',
9957 34 => 'blue',
9958 35 => 'magenta',
9959 36 => 'cyan',
9960 37 => 'white',
9961 );
9962 private static $availableBackgroundColors = array(
9963 40 => 'black',
9964 41 => 'red',
9965 42 => 'green',
9966 43 => 'yellow',
9967 44 => 'blue',
9968 45 => 'magenta',
9969 46 => 'cyan',
9970 47 => 'white',
9971 );
9972 private static $availableOptions = array(
9973 1 => 'bold',
9974 4 => 'underscore',
9975
9976  
9977  
9978  );
9979
9980
9981
9982
9983 public function __construct(array $styles = array())
9984 {
9985 parent::__construct(true, $styles);
9986 }
9987
9988 public function format($message)
9989 {
9990 $formatted = parent::format($message);
9991
9992 $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
9993
9994 return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted);
9995 }
9996
9997 private function formatHtml($matches)
9998 {
9999 $out = '<span style="';
10000 foreach (explode(';', $matches[1]) as $code) {
10001 if (isset(self::$availableForegroundColors[$code])) {
10002 $out .= 'color:'.self::$availableForegroundColors[$code].';';
10003 } elseif (isset(self::$availableBackgroundColors[$code])) {
10004 $out .= 'background-color:'.self::$availableBackgroundColors[$code].';';
10005 } elseif (isset(self::$availableOptions[$code])) {
10006 switch (self::$availableOptions[$code]) {
10007 case 'bold':
10008 $out .= 'font-weight:bold;';
10009 break;
10010
10011 case 'underscore':
10012 $out .= 'text-decoration:underline;';
10013 break;
10014 }
10015 }
10016 }
10017
10018 return $out.'">'.$matches[2].'</span>';
10019 }
10020 }
10021 <?php
10022
10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033 namespace Composer\DependencyResolver;
10034
10035
10036
10037
10038
10039
10040 class Decisions implements \Iterator, \Countable
10041 {
10042 const DECISION_LITERAL = 0;
10043 const DECISION_REASON = 1;
10044
10045 protected $pool;
10046 protected $decisionMap;
10047 protected $decisionQueue = array();
10048
10049 public function __construct($pool)
10050 {
10051 $this->pool = $pool;
10052 $this->decisionMap = array();
10053 }
10054
10055 public function decide($literal, $level, $why)
10056 {
10057 $this->addDecision($literal, $level);
10058 $this->decisionQueue[] = array(
10059 self::DECISION_LITERAL => $literal,
10060 self::DECISION_REASON => $why,
10061 );
10062 }
10063
10064 public function satisfy($literal)
10065 {
10066 $packageId = abs($literal);
10067
10068 return (
10069 $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 ||
10070 $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0
10071 );
10072 }
10073
10074 public function conflict($literal)
10075 {
10076 $packageId = abs($literal);
10077
10078 return (
10079 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0) ||
10080 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0)
10081 );
10082 }
10083
10084 public function decided($literalOrPackageId)
10085 {
10086 return !empty($this->decisionMap[abs($literalOrPackageId)]);
10087 }
10088
10089 public function undecided($literalOrPackageId)
10090 {
10091 return empty($this->decisionMap[abs($literalOrPackageId)]);
10092 }
10093
10094 public function decidedInstall($literalOrPackageId)
10095 {
10096 $packageId = abs($literalOrPackageId);
10097
10098 return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
10099 }
10100
10101 public function decisionLevel($literalOrPackageId)
10102 {
10103 $packageId = abs($literalOrPackageId);
10104 if (isset($this->decisionMap[$packageId])) {
10105 return abs($this->decisionMap[$packageId]);
10106 }
10107
10108 return 0;
10109 }
10110
10111 public function decisionRule($literalOrPackageId)
10112 {
10113 $packageId = abs($literalOrPackageId);
10114
10115 foreach ($this->decisionQueue as $i => $decision) {
10116 if ($packageId === abs($decision[self::DECISION_LITERAL])) {
10117 return $decision[self::DECISION_REASON];
10118 }
10119 }
10120
10121 return null;
10122 }
10123
10124 public function atOffset($queueOffset)
10125 {
10126 return $this->decisionQueue[$queueOffset];
10127 }
10128
10129 public function validOffset($queueOffset)
10130 {
10131 return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
10132 }
10133
10134 public function lastReason()
10135 {
10136 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
10137 }
10138
10139 public function lastLiteral()
10140 {
10141 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
10142 }
10143
10144 public function reset()
10145 {
10146 while ($decision = array_pop($this->decisionQueue)) {
10147 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
10148 }
10149 }
10150
10151 public function resetToOffset($offset)
10152 {
10153 while (count($this->decisionQueue) > $offset + 1) {
10154 $decision = array_pop($this->decisionQueue);
10155 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
10156 }
10157 }
10158
10159 public function revertLast()
10160 {
10161 $this->decisionMap[abs($this->lastLiteral())] = 0;
10162 array_pop($this->decisionQueue);
10163 }
10164
10165 public function count()
10166 {
10167 return count($this->decisionQueue);
10168 }
10169
10170 public function rewind()
10171 {
10172 end($this->decisionQueue);
10173 }
10174
10175 public function current()
10176 {
10177 return current($this->decisionQueue);
10178 }
10179
10180 public function key()
10181 {
10182 return key($this->decisionQueue);
10183 }
10184
10185 public function next()
10186 {
10187 return prev($this->decisionQueue);
10188 }
10189
10190 public function valid()
10191 {
10192 return false !== current($this->decisionQueue);
10193 }
10194
10195 public function isEmpty()
10196 {
10197 return count($this->decisionQueue) === 0;
10198 }
10199
10200 protected function addDecision($literal, $level)
10201 {
10202 $packageId = abs($literal);
10203
10204 $previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
10205 if ($previousDecision != 0) {
10206 $literalString = $this->pool->literalToString($literal);
10207 $package = $this->pool->literalToPackage($literal);
10208 throw new SolverBugException(
10209 "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
10210 );
10211 }
10212
10213 if ($literal > 0) {
10214 $this->decisionMap[$packageId] = $level;
10215 } else {
10216 $this->decisionMap[$packageId] = -$level;
10217 }
10218 }
10219 }
10220 <?php
10221
10222
10223
10224
10225
10226
10227
10228
10229
10230
10231
10232 namespace Composer\DependencyResolver;
10233
10234 use Composer\Package\PackageInterface;
10235 use Composer\Package\AliasPackage;
10236 use Composer\Package\BasePackage;
10237 use Composer\Semver\Constraint\Constraint;
10238
10239
10240
10241
10242
10243 class DefaultPolicy implements PolicyInterface
10244 {
10245 private $preferStable;
10246 private $preferLowest;
10247
10248 public function __construct($preferStable = false, $preferLowest = false)
10249 {
10250 $this->preferStable = $preferStable;
10251 $this->preferLowest = $preferLowest;
10252 }
10253
10254 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
10255 {
10256 if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
10257 return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
10258 }
10259
10260 $constraint = new Constraint($operator, $b->getVersion());
10261 $version = new Constraint('==', $a->getVersion());
10262
10263 return $constraint->matchSpecific($version, true);
10264 }
10265
10266 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
10267 {
10268 $packages = array();
10269
10270 foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
10271 if ($candidate !== $package) {
10272 $packages[] = $candidate;
10273 }
10274 }
10275
10276 return $packages;
10277 }
10278
10279 public function getPriority(Pool $pool, PackageInterface $package)
10280 {
10281 return $pool->getPriority($package->getRepository());
10282 }
10283
10284 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
10285 {
10286 $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
10287
10288 foreach ($packages as &$literals) {
10289 $policy = $this;
10290 usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10291 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
10292 });
10293 }
10294
10295 foreach ($packages as &$literals) {
10296 $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
10297
10298 $literals = $this->pruneToBestVersion($pool, $literals);
10299
10300 $literals = $this->pruneRemoteAliases($pool, $literals);
10301 }
10302
10303 $selected = call_user_func_array('array_merge', $packages);
10304
10305
10306  usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10307 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
10308 });
10309
10310 return $selected;
10311 }
10312
10313 protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
10314 {
10315 $packages = array();
10316 foreach ($literals as $literal) {
10317 $packageName = $pool->literalToPackage($literal)->getName();
10318
10319 if (!isset($packages[$packageName])) {
10320 $packages[$packageName] = array();
10321 }
10322
10323 if (isset($installedMap[abs($literal)])) {
10324 array_unshift($packages[$packageName], $literal);
10325 } else {
10326 $packages[$packageName][] = $literal;
10327 }
10328 }
10329
10330 return $packages;
10331 }
10332
10333
10334
10335
10336 public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
10337 {
10338 if ($a->getRepository() === $b->getRepository()) {
10339
10340  if ($a->getName() === $b->getName()) {
10341 $aAliased = $a instanceof AliasPackage;
10342 $bAliased = $b instanceof AliasPackage;
10343 if ($aAliased && !$bAliased) {
10344 return -1; 
10345  }
10346 if (!$aAliased && $bAliased) {
10347 return 1; 
10348  }
10349 }
10350
10351 if (!$ignoreReplace) {
10352
10353  if ($this->replaces($a, $b)) {
10354 return 1; 
10355  }
10356 if ($this->replaces($b, $a)) {
10357 return -1; 
10358  }
10359
10360
10361  
10362  if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
10363 $requiredVendor = substr($requiredPackage, 0, $pos);
10364
10365 $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
10366 $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
10367
10368 if ($bIsSameVendor !== $aIsSameVendor) {
10369 return $aIsSameVendor ? -1 : 1;
10370 }
10371 }
10372 }
10373
10374
10375  if ($a->id === $b->id) {
10376 return 0;
10377 }
10378
10379 return ($a->id < $b->id) ? -1 : 1;
10380 }
10381
10382 if (isset($installedMap[$a->id])) {
10383 return -1;
10384 }
10385
10386 if (isset($installedMap[$b->id])) {
10387 return 1;
10388 }
10389
10390 return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
10391 }
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403 protected function replaces(PackageInterface $source, PackageInterface $target)
10404 {
10405 foreach ($source->getReplaces() as $link) {
10406 if ($link->getTarget() === $target->getName()
10407
10408
10409  ) {
10410 return true;
10411 }
10412 }
10413
10414 return false;
10415 }
10416
10417 protected function pruneToBestVersion(Pool $pool, $literals)
10418 {
10419 $operator = $this->preferLowest ? '<' : '>';
10420 $bestLiterals = array($literals[0]);
10421 $bestPackage = $pool->literalToPackage($literals[0]);
10422 foreach ($literals as $i => $literal) {
10423 if (0 === $i) {
10424 continue;
10425 }
10426
10427 $package = $pool->literalToPackage($literal);
10428
10429 if ($this->versionCompare($package, $bestPackage, $operator)) {
10430 $bestPackage = $package;
10431 $bestLiterals = array($literal);
10432 } elseif ($this->versionCompare($package, $bestPackage, '==')) {
10433 $bestLiterals[] = $literal;
10434 }
10435 }
10436
10437 return $bestLiterals;
10438 }
10439
10440
10441
10442
10443 protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
10444 {
10445 $selected = array();
10446
10447 $priority = null;
10448
10449 foreach ($literals as $literal) {
10450 $package = $pool->literalToPackage($literal);
10451
10452 if (isset($installedMap[$package->id])) {
10453 $selected[] = $literal;
10454 continue;
10455 }
10456
10457 if (null === $priority) {
10458 $priority = $this->getPriority($pool, $package);
10459 }
10460
10461 if ($this->getPriority($pool, $package) != $priority) {
10462 break;
10463 }
10464
10465 $selected[] = $literal;
10466 }
10467
10468 return $selected;
10469 }
10470
10471
10472
10473
10474
10475
10476 protected function pruneRemoteAliases(Pool $pool, array $literals)
10477 {
10478 $hasLocalAlias = false;
10479
10480 foreach ($literals as $literal) {
10481 $package = $pool->literalToPackage($literal);
10482
10483 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10484 $hasLocalAlias = true;
10485 break;
10486 }
10487 }
10488
10489 if (!$hasLocalAlias) {
10490 return $literals;
10491 }
10492
10493 $selected = array();
10494 foreach ($literals as $literal) {
10495 $package = $pool->literalToPackage($literal);
10496
10497 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10498 $selected[] = $literal;
10499 }
10500 }
10501
10502 return $selected;
10503 }
10504 }
10505 <?php
10506
10507
10508
10509
10510
10511
10512
10513
10514
10515
10516
10517 namespace Composer\DependencyResolver;
10518
10519 use Composer\Package\PackageInterface;
10520 use Composer\Package\Link;
10521
10522
10523
10524
10525 class GenericRule extends Rule
10526 {
10527 protected $literals;
10528
10529
10530
10531
10532
10533
10534
10535 public function __construct(array $literals, $reason, $reasonData, $job = null)
10536 {
10537 parent::__construct($reason, $reasonData, $job);
10538
10539
10540  sort($literals);
10541
10542 $this->literals = $literals;
10543 }
10544
10545 public function getLiterals()
10546 {
10547 return $this->literals;
10548 }
10549
10550 public function getHash()
10551 {
10552 $data = unpack('ihash', md5(implode(',', $this->literals), true));
10553
10554 return $data['hash'];
10555 }
10556
10557
10558
10559
10560
10561
10562
10563
10564
10565 public function equals(Rule $rule)
10566 {
10567 return $this->literals === $rule->getLiterals();
10568 }
10569
10570 public function isAssertion()
10571 {
10572 return 1 === count($this->literals);
10573 }
10574
10575
10576
10577
10578
10579
10580 public function __toString()
10581 {
10582 $result = ($this->isDisabled()) ? 'disabled(' : '(';
10583
10584 foreach ($this->literals as $i => $literal) {
10585 if ($i != 0) {
10586 $result .= '|';
10587 }
10588 $result .= $literal;
10589 }
10590
10591 $result .= ')';
10592
10593 return $result;
10594 }
10595 }
10596 <?php
10597
10598
10599
10600
10601
10602
10603
10604
10605
10606
10607
10608 namespace Composer\DependencyResolver\Operation;
10609
10610 use Composer\Package\PackageInterface;
10611
10612
10613
10614
10615
10616
10617 class InstallOperation extends SolverOperation
10618 {
10619 protected $package;
10620
10621
10622
10623
10624
10625
10626
10627 public function __construct(PackageInterface $package, $reason = null)
10628 {
10629 parent::__construct($reason);
10630
10631 $this->package = $package;
10632 }
10633
10634
10635
10636
10637
10638
10639 public function getPackage()
10640 {
10641 return $this->package;
10642 }
10643
10644
10645
10646
10647
10648
10649 public function getJobType()
10650 {
10651 return 'install';
10652 }
10653
10654
10655
10656
10657 public function __toString()
10658 {
10659 return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
10660 }
10661 }
10662 <?php
10663
10664
10665
10666
10667
10668
10669
10670
10671
10672
10673
10674 namespace Composer\DependencyResolver\Operation;
10675
10676 use Composer\Package\AliasPackage;
10677 use Composer\Package\PackageInterface;
10678
10679
10680
10681
10682
10683
10684 class MarkAliasInstalledOperation extends SolverOperation
10685 {
10686 protected $package;
10687
10688
10689
10690
10691
10692
10693
10694 public function __construct(AliasPackage $package, $reason = null)
10695 {
10696 parent::__construct($reason);
10697
10698 $this->package = $package;
10699 }
10700
10701
10702
10703
10704
10705
10706 public function getPackage()
10707 {
10708 return $this->package;
10709 }
10710
10711
10712
10713
10714
10715
10716 public function getJobType()
10717 {
10718 return 'markAliasInstalled';
10719 }
10720
10721
10722
10723
10724 public function __toString()
10725 {
10726 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
10727 }
10728 }
10729 <?php
10730
10731
10732
10733
10734
10735
10736
10737
10738
10739
10740
10741 namespace Composer\DependencyResolver\Operation;
10742
10743 use Composer\Package\AliasPackage;
10744 use Composer\Package\PackageInterface;
10745
10746
10747
10748
10749
10750
10751 class MarkAliasUninstalledOperation extends SolverOperation
10752 {
10753 protected $package;
10754
10755
10756
10757
10758
10759
10760
10761 public function __construct(AliasPackage $package, $reason = null)
10762 {
10763 parent::__construct($reason);
10764
10765 $this->package = $package;
10766 }
10767
10768
10769
10770
10771
10772
10773 public function getPackage()
10774 {
10775 return $this->package;
10776 }
10777
10778
10779
10780
10781
10782
10783 public function getJobType()
10784 {
10785 return 'markAliasUninstalled';
10786 }
10787
10788
10789
10790
10791 public function __toString()
10792 {
10793 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
10794 }
10795 }
10796 <?php
10797
10798
10799
10800
10801
10802
10803
10804
10805
10806
10807
10808 namespace Composer\DependencyResolver\Operation;
10809
10810
10811
10812
10813
10814
10815 interface OperationInterface
10816 {
10817
10818
10819
10820
10821
10822 public function getJobType();
10823
10824
10825
10826
10827
10828
10829 public function getReason();
10830
10831
10832
10833
10834
10835
10836 public function __toString();
10837 }
10838 <?php
10839
10840
10841
10842
10843
10844
10845
10846
10847
10848
10849
10850 namespace Composer\DependencyResolver\Operation;
10851
10852 use Composer\Package\PackageInterface;
10853
10854
10855
10856
10857
10858
10859 abstract class SolverOperation implements OperationInterface
10860 {
10861 protected $reason;
10862
10863
10864
10865
10866
10867
10868 public function __construct($reason = null)
10869 {
10870 $this->reason = $reason;
10871 }
10872
10873
10874
10875
10876
10877
10878 public function getReason()
10879 {
10880 return $this->reason;
10881 }
10882
10883 protected function formatVersion(PackageInterface $package)
10884 {
10885 return $package->getFullPrettyVersion();
10886 }
10887 }
10888 <?php
10889
10890
10891
10892
10893
10894
10895
10896
10897
10898
10899
10900 namespace Composer\DependencyResolver\Operation;
10901
10902 use Composer\Package\PackageInterface;
10903
10904
10905
10906
10907
10908
10909 class UninstallOperation extends SolverOperation
10910 {
10911 protected $package;
10912
10913
10914
10915
10916
10917
10918
10919 public function __construct(PackageInterface $package, $reason = null)
10920 {
10921 parent::__construct($reason);
10922
10923 $this->package = $package;
10924 }
10925
10926
10927
10928
10929
10930
10931 public function getPackage()
10932 {
10933 return $this->package;
10934 }
10935
10936
10937
10938
10939
10940
10941 public function getJobType()
10942 {
10943 return 'uninstall';
10944 }
10945
10946
10947
10948
10949 public function __toString()
10950 {
10951 return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
10952 }
10953 }
10954 <?php
10955
10956
10957
10958
10959
10960
10961
10962
10963
10964
10965
10966 namespace Composer\DependencyResolver\Operation;
10967
10968 use Composer\Package\PackageInterface;
10969
10970
10971
10972
10973
10974
10975 class UpdateOperation extends SolverOperation
10976 {
10977 protected $initialPackage;
10978 protected $targetPackage;
10979
10980
10981
10982
10983
10984
10985
10986
10987 public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
10988 {
10989 parent::__construct($reason);
10990
10991 $this->initialPackage = $initial;
10992 $this->targetPackage = $target;
10993 }
10994
10995
10996
10997
10998
10999
11000 public function getInitialPackage()
11001 {
11002 return $this->initialPackage;
11003 }
11004
11005
11006
11007
11008
11009
11010 public function getTargetPackage()
11011 {
11012 return $this->targetPackage;
11013 }
11014
11015
11016
11017
11018
11019
11020 public function getJobType()
11021 {
11022 return 'update';
11023 }
11024
11025
11026
11027
11028 public function __toString()
11029 {
11030 return 'Updating '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
11031 $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
11032 }
11033 }
11034 <?php
11035
11036
11037
11038
11039
11040
11041
11042
11043
11044
11045
11046 namespace Composer\DependencyResolver;
11047
11048 use Composer\Package\PackageInterface;
11049
11050
11051
11052
11053 interface PolicyInterface
11054 {
11055 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
11056
11057 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
11058
11059 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null);
11060 }
11061 <?php
11062
11063
11064
11065
11066
11067
11068
11069
11070
11071
11072
11073 namespace Composer\DependencyResolver;
11074
11075 use Composer\Package\BasePackage;
11076 use Composer\Package\AliasPackage;
11077 use Composer\Package\Version\VersionParser;
11078 use Composer\Semver\Constraint\ConstraintInterface;
11079 use Composer\Semver\Constraint\Constraint;
11080 use Composer\Semver\Constraint\EmptyConstraint;
11081 use Composer\Repository\RepositoryInterface;
11082 use Composer\Repository\CompositeRepository;
11083 use Composer\Repository\ComposerRepository;
11084 use Composer\Repository\InstalledRepositoryInterface;
11085 use Composer\Repository\PlatformRepository;
11086 use Composer\Package\PackageInterface;
11087
11088
11089
11090
11091
11092
11093
11094 class Pool implements \Countable
11095 {
11096 const MATCH_NAME = -1;
11097 const MATCH_NONE = 0;
11098 const MATCH = 1;
11099 const MATCH_PROVIDE = 2;
11100 const MATCH_REPLACE = 3;
11101 const MATCH_FILTERED = 4;
11102
11103 protected $repositories = array();
11104 protected $providerRepos = array();
11105 protected $packages = array();
11106 protected $packageByName = array();
11107 protected $packageByExactName = array();
11108 protected $acceptableStabilities;
11109 protected $stabilityFlags;
11110 protected $versionParser;
11111 protected $providerCache = array();
11112 protected $filterRequires;
11113 protected $whitelist = null;
11114 protected $id = 1;
11115
11116 public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
11117 {
11118 $this->versionParser = new VersionParser;
11119 $this->acceptableStabilities = array();
11120 foreach (BasePackage::$stabilities as $stability => $value) {
11121 if ($value <= BasePackage::$stabilities[$minimumStability]) {
11122 $this->acceptableStabilities[$stability] = $value;
11123 }
11124 }
11125 $this->stabilityFlags = $stabilityFlags;
11126 $this->filterRequires = $filterRequires;
11127 foreach ($filterRequires as $name => $constraint) {
11128 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
11129 unset($this->filterRequires[$name]);
11130 }
11131 }
11132 }
11133
11134 public function setWhitelist($whitelist)
11135 {
11136 $this->whitelist = $whitelist;
11137 $this->providerCache = array();
11138 }
11139
11140
11141
11142
11143
11144
11145
11146 public function addRepository(RepositoryInterface $repo, $rootAliases = array())
11147 {
11148 if ($repo instanceof CompositeRepository) {
11149 $repos = $repo->getRepositories();
11150 } else {
11151 $repos = array($repo);
11152 }
11153
11154 foreach ($repos as $repo) {
11155 $this->repositories[] = $repo;
11156
11157 $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
11158
11159 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
11160 $this->providerRepos[] = $repo;
11161 $repo->setRootAliases($rootAliases);
11162 $repo->resetPackageIds();
11163 } else {
11164 foreach ($repo->getPackages() as $package) {
11165 $names = $package->getNames();
11166 $stability = $package->getStability();
11167 if ($exempt || $this->isPackageAcceptable($names, $stability)) {
11168 $package->setId($this->id++);
11169 $this->packages[] = $package;
11170 $this->packageByExactName[$package->getName()][$package->id] = $package;
11171
11172 foreach ($names as $provided) {
11173 $this->packageByName[$provided][] = $package;
11174 }
11175
11176
11177  $name = $package->getName();
11178 if (isset($rootAliases[$name][$package->getVersion()])) {
11179 $alias = $rootAliases[$name][$package->getVersion()];
11180 if ($package instanceof AliasPackage) {
11181 $package = $package->getAliasOf();
11182 }
11183 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
11184 $aliasPackage->setRootPackageAlias(true);
11185 $aliasPackage->setId($this->id++);
11186
11187 $package->getRepository()->addPackage($aliasPackage);
11188 $this->packages[] = $aliasPackage;
11189 $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
11190
11191 foreach ($aliasPackage->getNames() as $name) {
11192 $this->packageByName[$name][] = $aliasPackage;
11193 }
11194 }
11195 }
11196 }
11197 }
11198 }
11199 }
11200
11201 public function getPriority(RepositoryInterface $repo)
11202 {
11203 $priority = array_search($repo, $this->repositories, true);
11204
11205 if (false === $priority) {
11206 throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
11207 }
11208
11209 return -$priority;
11210 }
11211
11212
11213
11214
11215
11216
11217
11218 public function packageById($id)
11219 {
11220 return $this->packages[$id - 1];
11221 }
11222
11223
11224
11225
11226 public function count()
11227 {
11228 return count($this->packages);
11229 }
11230
11231
11232
11233
11234
11235
11236
11237
11238
11239
11240
11241
11242 public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
11243 {
11244 if ($bypassFilters) {
11245 return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
11246 }
11247
11248 $key = ((int) $mustMatchName).$constraint;
11249 if (isset($this->providerCache[$name][$key])) {
11250 return $this->providerCache[$name][$key];
11251 }
11252
11253 return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
11254 }
11255
11256
11257
11258
11259 private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
11260 {
11261 $candidates = array();
11262
11263 foreach ($this->providerRepos as $repo) {
11264 foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
11265 $candidates[] = $candidate;
11266 if ($candidate->id < 1) {
11267 $candidate->setId($this->id++);
11268 $this->packages[$this->id - 2] = $candidate;
11269 }
11270 }
11271 }
11272
11273 if ($mustMatchName) {
11274 $candidates = array_filter($candidates, function ($candidate) use ($name) {
11275 return $candidate->getName() == $name;
11276 });
11277 if (isset($this->packageByExactName[$name])) {
11278 $candidates = array_merge($candidates, $this->packageByExactName[$name]);
11279 }
11280 } elseif (isset($this->packageByName[$name])) {
11281 $candidates = array_merge($candidates, $this->packageByName[$name]);
11282 }
11283
11284 $matches = $provideMatches = array();
11285 $nameMatch = false;
11286
11287 foreach ($candidates as $candidate) {
11288 $aliasOfCandidate = null;
11289
11290
11291  
11292  if ($candidate instanceof AliasPackage) {
11293 $aliasOfCandidate = $candidate->getAliasOf();
11294 }
11295
11296 if ($this->whitelist !== null && !$bypassFilters && (
11297 (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
11298 ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
11299 )) {
11300 continue;
11301 }
11302 switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
11303 case self::MATCH_NONE:
11304 break;
11305
11306 case self::MATCH_NAME:
11307 $nameMatch = true;
11308 break;
11309
11310 case self::MATCH:
11311 $nameMatch = true;
11312 $matches[] = $candidate;
11313 break;
11314
11315 case self::MATCH_PROVIDE:
11316 $provideMatches[] = $candidate;
11317 break;
11318
11319 case self::MATCH_REPLACE:
11320 $matches[] = $candidate;
11321 break;
11322
11323 case self::MATCH_FILTERED:
11324 break;
11325
11326 default:
11327 throw new \UnexpectedValueException('Unexpected match type');
11328 }
11329 }
11330
11331
11332  if ($nameMatch) {
11333 return $matches;
11334 }
11335
11336 return array_merge($matches, $provideMatches);
11337 }
11338
11339 public function literalToPackage($literal)
11340 {
11341 $packageId = abs($literal);
11342
11343 return $this->packageById($packageId);
11344 }
11345
11346 public function literalToPrettyString($literal, $installedMap)
11347 {
11348 $package = $this->literalToPackage($literal);
11349
11350 if (isset($installedMap[$package->id])) {
11351 $prefix = ($literal > 0 ? 'keep' : 'remove');
11352 } else {
11353 $prefix = ($literal > 0 ? 'install' : 'don\'t install');
11354 }
11355
11356 return $prefix.' '.$package->getPrettyString();
11357 }
11358
11359 public function isPackageAcceptable($name, $stability)
11360 {
11361 foreach ((array) $name as $n) {
11362
11363  if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
11364 return true;
11365 }
11366
11367
11368  if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
11369 return true;
11370 }
11371 }
11372
11373 return false;
11374 }
11375
11376
11377
11378
11379
11380
11381
11382
11383
11384
11385 private function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
11386 {
11387 $candidateName = $candidate->getName();
11388 $candidateVersion = $candidate->getVersion();
11389 $isDev = $candidate->getStability() === 'dev';
11390 $isAlias = $candidate instanceof AliasPackage;
11391
11392 if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
11393 $requireFilter = $this->filterRequires[$name];
11394 } else {
11395 $requireFilter = new EmptyConstraint;
11396 }
11397
11398 if ($candidateName === $name) {
11399 $pkgConstraint = new Constraint('==', $candidateVersion);
11400
11401 if ($constraint === null || $constraint->matches($pkgConstraint)) {
11402 return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
11403 }
11404
11405 return self::MATCH_NAME;
11406 }
11407
11408 $provides = $candidate->getProvides();
11409 $replaces = $candidate->getReplaces();
11410
11411
11412  if (isset($replaces[0]) || isset($provides[0])) {
11413 foreach ($provides as $link) {
11414 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11415 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11416 }
11417 }
11418
11419 foreach ($replaces as $link) {
11420 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11421 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11422 }
11423 }
11424
11425 return self::MATCH_NONE;
11426 }
11427
11428 if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
11429 return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11430 }
11431
11432 if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
11433 return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11434 }
11435
11436 return self::MATCH_NONE;
11437 }
11438 }
11439 <?php
11440
11441
11442
11443
11444
11445
11446
11447
11448
11449
11450
11451 namespace Composer\DependencyResolver;
11452
11453
11454
11455
11456
11457
11458 class Problem
11459 {
11460
11461
11462
11463
11464 protected $reasonSeen;
11465
11466
11467
11468
11469
11470 protected $reasons = array();
11471
11472 protected $section = 0;
11473
11474 protected $pool;
11475
11476 public function __construct(Pool $pool)
11477 {
11478 $this->pool = $pool;
11479 }
11480
11481
11482
11483
11484
11485
11486 public function addRule(Rule $rule)
11487 {
11488 $this->addReason(spl_object_hash($rule), array(
11489 'rule' => $rule,
11490 'job' => $rule->getJob(),
11491 ));
11492 }
11493
11494
11495
11496
11497
11498
11499 public function getReasons()
11500 {
11501 return $this->reasons;
11502 }
11503
11504
11505
11506
11507
11508
11509
11510 public function getPrettyString(array $installedMap = array())
11511 {
11512 $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
11513
11514 if (count($reasons) === 1) {
11515 reset($reasons);
11516 $reason = current($reasons);
11517
11518 $rule = $reason['rule'];
11519 $job = $reason['job'];
11520
11521 if (isset($job['constraint'])) {
11522 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11523 } else {
11524 $packages = array();
11525 }
11526
11527 if ($job && $job['cmd'] === 'install' && empty($packages)) {
11528
11529
11530  if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') {
11531 $available = $this->pool->whatProvides($job['packageName']);
11532 $version = count($available) ? $available[0]->getPrettyVersion() : phpversion();
11533
11534 $msg = "\n    - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but ';
11535
11536 if (defined('HHVM_VERSION')) {
11537 return $msg . 'your HHVM version does not satisfy that requirement.';
11538 }
11539
11540 if ($job['packageName'] === 'hhvm') {
11541 return $msg . 'you are running this with PHP and not HHVM.';
11542 }
11543
11544 return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
11545 }
11546
11547
11548  if (0 === stripos($job['packageName'], 'ext-')) {
11549 $ext = substr($job['packageName'], 4);
11550 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
11551
11552 return "\n    - The requested PHP extension ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
11553 }
11554
11555
11556  if (0 === stripos($job['packageName'], 'lib-')) {
11557 if (strtolower($job['packageName']) === 'lib-icu') {
11558 $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.';
11559
11560 return "\n    - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error;
11561 }
11562
11563 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.';
11564 }
11565
11566 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $job['packageName'])) {
11567 $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $job['packageName']);
11568
11569 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.';
11570 }
11571
11572 if ($providers = $this->pool->whatProvides($job['packageName'], $job['constraint'], true, true)) {
11573 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.';
11574 }
11575
11576 if ($providers = $this->pool->whatProvides($job['packageName'], null, true, true)) {
11577 return "\n    - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
11578 }
11579
11580 return "\n    - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.';
11581 }
11582 }
11583
11584 $messages = array();
11585
11586 foreach ($reasons as $reason) {
11587 $rule = $reason['rule'];
11588 $job = $reason['job'];
11589
11590 if ($job) {
11591 $messages[] = $this->jobToText($job);
11592 } elseif ($rule) {
11593 if ($rule instanceof Rule) {
11594 $messages[] = $rule->getPrettyString($this->pool, $installedMap);
11595 }
11596 }
11597 }
11598
11599 return "\n    - ".implode("\n    - ", $messages);
11600 }
11601
11602
11603
11604
11605
11606
11607
11608 protected function addReason($id, $reason)
11609 {
11610 if (!isset($this->reasonSeen[$id])) {
11611 $this->reasonSeen[$id] = true;
11612 $this->reasons[$this->section][] = $reason;
11613 }
11614 }
11615
11616 public function nextSection()
11617 {
11618 $this->section++;
11619 }
11620
11621
11622
11623
11624
11625
11626
11627 protected function jobToText($job)
11628 {
11629 switch ($job['cmd']) {
11630 case 'install':
11631 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11632 if (!$packages) {
11633 return 'No package found to satisfy install request for '.$job['packageName'].$this->constraintToText($job['constraint']);
11634 }
11635
11636 return 'Installation request for '.$job['packageName'].$this->constraintToText($job['constraint']).' -> satisfiable by '.$this->getPackageList($packages).'.';
11637 case 'update':
11638 return 'Update request for '.$job['packageName'].$this->constraintToText($job['constraint']).'.';
11639 case 'remove':
11640 return 'Removal request for '.$job['packageName'].$this->constraintToText($job['constraint']).'';
11641 }
11642
11643 if (isset($job['constraint'])) {
11644 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11645 } else {
11646 $packages = array();
11647 }
11648
11649 return 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.$this->getPackageList($packages).'])';
11650 }
11651
11652 protected function getPackageList($packages)
11653 {
11654 $prepared = array();
11655 foreach ($packages as $package) {
11656 $prepared[$package->getName()]['name'] = $package->getPrettyName();
11657 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
11658 }
11659 foreach ($prepared as $name => $package) {
11660 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
11661 }
11662
11663 return implode(', ', $prepared);
11664 }
11665
11666
11667
11668
11669
11670
11671
11672 protected function constraintToText($constraint)
11673 {
11674 return ($constraint) ? ' '.$constraint->getPrettyString() : '';
11675 }
11676 }
11677 <?php
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688
11689 namespace Composer\DependencyResolver;
11690
11691 use Composer\Semver\Constraint\ConstraintInterface;
11692
11693
11694
11695
11696 class Request
11697 {
11698 protected $jobs;
11699
11700 public function __construct()
11701 {
11702 $this->jobs = array();
11703 }
11704
11705 public function install($packageName, ConstraintInterface $constraint = null)
11706 {
11707 $this->addJob($packageName, 'install', $constraint);
11708 }
11709
11710 public function update($packageName, ConstraintInterface $constraint = null)
11711 {
11712 $this->addJob($packageName, 'update', $constraint);
11713 }
11714
11715 public function remove($packageName, ConstraintInterface $constraint = null)
11716 {
11717 $this->addJob($packageName, 'remove', $constraint);
11718 }
11719
11720
11721
11722
11723
11724
11725
11726
11727
11728 public function fix($packageName, ConstraintInterface $constraint = null)
11729 {
11730 $this->addJob($packageName, 'install', $constraint, true);
11731 }
11732
11733 protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
11734 {
11735 $packageName = strtolower($packageName);
11736
11737 $this->jobs[] = array(
11738 'cmd' => $cmd,
11739 'packageName' => $packageName,
11740 'constraint' => $constraint,
11741 'fixed' => $fixed,
11742 );
11743 }
11744
11745 public function updateAll()
11746 {
11747 $this->jobs[] = array('cmd' => 'update-all');
11748 }
11749
11750 public function getJobs()
11751 {
11752 return $this->jobs;
11753 }
11754 }
11755 <?php
11756
11757
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767 namespace Composer\DependencyResolver;
11768
11769 use Composer\Package\CompletePackage;
11770 use Composer\Package\Link;
11771 use Composer\Package\PackageInterface;
11772
11773
11774
11775
11776
11777 abstract class Rule
11778 {
11779
11780  const RULE_INTERNAL_ALLOW_UPDATE = 1;
11781 const RULE_JOB_INSTALL = 2;
11782 const RULE_JOB_REMOVE = 3;
11783 const RULE_PACKAGE_CONFLICT = 6;
11784 const RULE_PACKAGE_REQUIRES = 7;
11785 const RULE_PACKAGE_OBSOLETES = 8;
11786 const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
11787 const RULE_PACKAGE_SAME_NAME = 10;
11788 const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
11789 const RULE_LEARNED = 12;
11790 const RULE_PACKAGE_ALIAS = 13;
11791
11792
11793  const BITFIELD_TYPE = 0;
11794 const BITFIELD_REASON = 8;
11795 const BITFIELD_DISABLED = 16;
11796
11797 protected $bitfield;
11798 protected $reasonData;
11799
11800
11801
11802
11803
11804
11805 public function __construct($reason, $reasonData, $job = null)
11806 {
11807 $this->reasonData = $reasonData;
11808
11809 if ($job) {
11810 $this->job = $job;
11811 }
11812
11813 $this->bitfield = (0 << self::BITFIELD_DISABLED) |
11814 ($reason << self::BITFIELD_REASON) |
11815 (255 << self::BITFIELD_TYPE);
11816 }
11817
11818 abstract public function getLiterals();
11819
11820 abstract public function getHash();
11821
11822 public function getJob()
11823 {
11824 return isset($this->job) ? $this->job : null;
11825 }
11826
11827 abstract public function equals(Rule $rule);
11828
11829 public function getReason()
11830 {
11831 return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
11832 }
11833
11834 public function getReasonData()
11835 {
11836 return $this->reasonData;
11837 }
11838
11839 public function getRequiredPackage()
11840 {
11841 if ($this->getReason() === self::RULE_JOB_INSTALL) {
11842 return $this->reasonData;
11843 }
11844
11845 if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
11846 return $this->reasonData->getTarget();
11847 }
11848 }
11849
11850 public function setType($type)
11851 {
11852 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
11853 }
11854
11855 public function getType()
11856 {
11857 return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
11858 }
11859
11860 public function disable()
11861 {
11862 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
11863 }
11864
11865 public function enable()
11866 {
11867 $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED);
11868 }
11869
11870 public function isDisabled()
11871 {
11872 return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
11873 }
11874
11875 public function isEnabled()
11876 {
11877 return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
11878 }
11879
11880 abstract public function isAssertion();
11881
11882 public function getPrettyString(Pool $pool, array $installedMap = array())
11883 {
11884 $literals = $this->getLiterals();
11885
11886 $ruleText = '';
11887 foreach ($literals as $i => $literal) {
11888 if ($i != 0) {
11889 $ruleText .= '|';
11890 }
11891 $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
11892 }
11893
11894 switch ($this->getReason()) {
11895 case self::RULE_INTERNAL_ALLOW_UPDATE:
11896 return $ruleText;
11897
11898 case self::RULE_JOB_INSTALL:
11899 return "Install command rule ($ruleText)";
11900
11901 case self::RULE_JOB_REMOVE:
11902 return "Remove command rule ($ruleText)";
11903
11904 case self::RULE_PACKAGE_CONFLICT:
11905 $package1 = $pool->literalToPackage($literals[0]);
11906 $package2 = $pool->literalToPackage($literals[1]);
11907
11908 return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
11909
11910 case self::RULE_PACKAGE_REQUIRES:
11911 $sourceLiteral = array_shift($literals);
11912 $sourcePackage = $pool->literalToPackage($sourceLiteral);
11913
11914 $requires = array();
11915 foreach ($literals as $literal) {
11916 $requires[] = $pool->literalToPackage($literal);
11917 }
11918
11919 $text = $this->reasonData->getPrettyString($sourcePackage);
11920 if ($requires) {
11921 $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
11922 } else {
11923 $targetName = $this->reasonData->getTarget();
11924
11925 if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
11926
11927  if (defined('HHVM_VERSION')) {
11928 return $text . ' -> your HHVM version does not satisfy that requirement.';
11929 }
11930
11931 if ($targetName === 'hhvm') {
11932 return $text . ' -> you are running this with PHP and not HHVM.';
11933 }
11934
11935 $packages = $pool->whatProvides($targetName);
11936 $package = count($packages) ? current($packages) : phpversion();
11937
11938 if (!($package instanceof CompletePackage)) {
11939 return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
11940 }
11941
11942 $extra = $package->getExtra();
11943
11944 if (!empty($extra['config.platform'])) {
11945 $text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
11946 } else {
11947 $text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
11948 }
11949
11950 return $text;
11951 }
11952
11953 if (0 === strpos($targetName, 'ext-')) {
11954
11955  $ext = substr($targetName, 4);
11956 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
11957
11958 return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
11959 }
11960
11961 if (0 === strpos($targetName, 'lib-')) {
11962
11963  $lib = substr($targetName, 4);
11964
11965 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.';
11966 }
11967
11968 if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
11969 return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
11970 }
11971
11972 return $text . ' -> no matching package found.';
11973 }
11974
11975 return $text;
11976
11977 case self::RULE_PACKAGE_OBSOLETES:
11978 return $ruleText;
11979 case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
11980 return $ruleText;
11981 case self::RULE_PACKAGE_SAME_NAME:
11982 return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $literals) . '.';
11983 case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
11984 return $ruleText;
11985 case self::RULE_LEARNED:
11986 return 'Conclusion: '.$ruleText;
11987 case self::RULE_PACKAGE_ALIAS:
11988 return $ruleText;
11989 default:
11990 return '('.$ruleText.')';
11991 }
11992 }
11993
11994
11995
11996
11997
11998
11999
12000 protected function formatPackagesUnique($pool, array $packages)
12001 {
12002 $prepared = array();
12003 foreach ($packages as $package) {
12004 if (!is_object($package)) {
12005 $package = $pool->literalToPackage($package);
12006 }
12007 $prepared[$package->getName()]['name'] = $package->getPrettyName();
12008 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
12009 }
12010 foreach ($prepared as $name => $package) {
12011 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
12012 }
12013
12014 return implode(', ', $prepared);
12015 }
12016 }
12017 <?php
12018
12019
12020
12021
12022
12023
12024
12025
12026
12027
12028
12029 namespace Composer\DependencyResolver;
12030
12031 use Composer\Package\PackageInterface;
12032 use Composer\Package\Link;
12033
12034
12035
12036
12037 class Rule2Literals extends Rule
12038 {
12039 protected $literal1;
12040 protected $literal2;
12041
12042
12043
12044
12045
12046
12047
12048
12049 public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
12050 {
12051 parent::__construct($reason, $reasonData, $job);
12052
12053 if ($literal1 < $literal2) {
12054 $this->literal1 = $literal1;
12055 $this->literal2 = $literal2;
12056 } else {
12057 $this->literal1 = $literal2;
12058 $this->literal2 = $literal1;
12059 }
12060 }
12061
12062 public function getLiterals()
12063 {
12064 return array($this->literal1, $this->literal2);
12065 }
12066
12067 public function getHash()
12068 {
12069 $data = unpack('ihash', md5($this->literal1.','.$this->literal2, true));
12070
12071 return $data['hash'];
12072 }
12073
12074
12075
12076
12077
12078
12079
12080
12081
12082 public function equals(Rule $rule)
12083 {
12084 $literals = $rule->getLiterals();
12085 if (2 != count($literals)) {
12086 return false;
12087 }
12088
12089 if ($this->literal1 !== $literals[0]) {
12090 return false;
12091 }
12092
12093 if ($this->literal2 !== $literals[1]) {
12094 return false;
12095 }
12096
12097 return true;
12098 }
12099
12100 public function isAssertion()
12101 {
12102 return false;
12103 }
12104
12105
12106
12107
12108
12109
12110 public function __toString()
12111 {
12112 $result = ($this->isDisabled()) ? 'disabled(' : '(';
12113
12114 $result .= $this->literal1 . '|' . $this->literal2 . ')';
12115
12116 return $result;
12117 }
12118 }
12119 <?php
12120
12121
12122
12123
12124
12125
12126
12127
12128
12129
12130
12131 namespace Composer\DependencyResolver;
12132
12133
12134
12135
12136 class RuleSet implements \IteratorAggregate, \Countable
12137 {
12138
12139  const TYPE_PACKAGE = 0;
12140 const TYPE_JOB = 1;
12141 const TYPE_LEARNED = 4;
12142
12143
12144
12145
12146
12147
12148 public $ruleById;
12149
12150 protected static $types = array(
12151 255 => 'UNKNOWN',
12152 self::TYPE_PACKAGE => 'PACKAGE',
12153 self::TYPE_JOB => 'JOB',
12154 self::TYPE_LEARNED => 'LEARNED',
12155 );
12156
12157 protected $rules;
12158 protected $nextRuleId;
12159
12160 protected $rulesByHash;
12161
12162 public function __construct()
12163 {
12164 $this->nextRuleId = 0;
12165
12166 foreach ($this->getTypes() as $type) {
12167 $this->rules[$type] = array();
12168 }
12169
12170 $this->rulesByHash = array();
12171 }
12172
12173 public function add(Rule $rule, $type)
12174 {
12175 if (!isset(self::$types[$type])) {
12176 throw new \OutOfBoundsException('Unknown rule type: ' . $type);
12177 }
12178
12179 $hash = $rule->getHash();
12180
12181
12182  if (isset($this->rulesByHash[$hash])) {
12183 $potentialDuplicates = $this->rulesByHash[$hash];
12184 if (is_array($potentialDuplicates)) {
12185 foreach ($potentialDuplicates as $potentialDuplicate) {
12186 if ($rule->equals($potentialDuplicate)) {
12187 return;
12188 }
12189 }
12190 } else {
12191 if ($rule->equals($potentialDuplicates)) {
12192 return;
12193 }
12194 }
12195 }
12196
12197 if (!isset($this->rules[$type])) {
12198 $this->rules[$type] = array();
12199 }
12200
12201 $this->rules[$type][] = $rule;
12202 $this->ruleById[$this->nextRuleId] = $rule;
12203 $rule->setType($type);
12204
12205 $this->nextRuleId++;
12206
12207 if (!isset($this->rulesByHash[$hash])) {
12208 $this->rulesByHash[$hash] = $rule;
12209 } elseif (is_array($this->rulesByHash[$hash])) {
12210 $this->rulesByHash[$hash][] = $rule;
12211 } else {
12212 $originalRule = $this->rulesByHash[$hash];
12213 $this->rulesByHash[$hash] = array($originalRule, $rule);
12214 }
12215 }
12216
12217 public function count()
12218 {
12219 return $this->nextRuleId;
12220 }
12221
12222 public function ruleById($id)
12223 {
12224 return $this->ruleById[$id];
12225 }
12226
12227 public function getRules()
12228 {
12229 return $this->rules;
12230 }
12231
12232 public function getIterator()
12233 {
12234 return new RuleSetIterator($this->getRules());
12235 }
12236
12237 public function getIteratorFor($types)
12238 {
12239 if (!is_array($types)) {
12240 $types = array($types);
12241 }
12242
12243 $allRules = $this->getRules();
12244 $rules = array();
12245
12246 foreach ($types as $type) {
12247 $rules[$type] = $allRules[$type];
12248 }
12249
12250 return new RuleSetIterator($rules);
12251 }
12252
12253 public function getIteratorWithout($types)
12254 {
12255 if (!is_array($types)) {
12256 $types = array($types);
12257 }
12258
12259 $rules = $this->getRules();
12260
12261 foreach ($types as $type) {
12262 unset($rules[$type]);
12263 }
12264
12265 return new RuleSetIterator($rules);
12266 }
12267
12268 public function getTypes()
12269 {
12270 $types = self::$types;
12271 unset($types[255]);
12272
12273 return array_keys($types);
12274 }
12275
12276 public function getPrettyString(Pool $pool = null)
12277 {
12278 $string = "\n";
12279 foreach ($this->rules as $type => $rules) {
12280 $string .= str_pad(self::$types[$type], 8, ' ') . ": ";
12281 foreach ($rules as $rule) {
12282 $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
12283 }
12284 $string .= "\n\n";
12285 }
12286
12287 return $string;
12288 }
12289
12290 public function __toString()
12291 {
12292 return $this->getPrettyString(null);
12293 }
12294 }
12295 <?php
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307 namespace Composer\DependencyResolver;
12308
12309 use Composer\Package\PackageInterface;
12310 use Composer\Package\AliasPackage;
12311 use Composer\Repository\PlatformRepository;
12312
12313
12314
12315
12316 class RuleSetGenerator
12317 {
12318 protected $policy;
12319 protected $pool;
12320 protected $rules;
12321 protected $jobs;
12322 protected $installedMap;
12323 protected $whitelistedMap;
12324 protected $addedMap;
12325
12326 public function __construct(PolicyInterface $policy, Pool $pool)
12327 {
12328 $this->policy = $policy;
12329 $this->pool = $pool;
12330 }
12331
12332
12333
12334
12335
12336
12337
12338
12339
12340
12341
12342
12343
12344
12345
12346 protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
12347 {
12348 $literals = array(-$package->id);
12349
12350 foreach ($providers as $provider) {
12351
12352  if ($provider === $package) {
12353 return null;
12354 }
12355 $literals[] = $provider->id;
12356 }
12357
12358 return new GenericRule($literals, $reason, $reasonData);
12359 }
12360
12361
12362
12363
12364
12365
12366
12367
12368
12369
12370
12371
12372
12373 protected function createInstallOneOfRule(array $packages, $reason, $job)
12374 {
12375 $literals = array();
12376 foreach ($packages as $package) {
12377 $literals[] = $package->id;
12378 }
12379
12380 return new GenericRule($literals, $reason, $job['packageName'], $job);
12381 }
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394 protected function createRemoveRule(PackageInterface $package, $reason, $job)
12395 {
12396 return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
12397 }
12398
12399
12400
12401
12402
12403
12404
12405
12406
12407
12408
12409
12410
12411
12412
12413 protected function createRule2Literals(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
12414 {
12415
12416  if ($issuer === $provider) {
12417 return null;
12418 }
12419
12420 return new Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
12421 }
12422
12423
12424
12425
12426
12427
12428
12429
12430
12431
12432 private function addRule($type, Rule $newRule = null)
12433 {
12434 if (!$newRule) {
12435 return;
12436 }
12437
12438 $this->rules->add($newRule, $type);
12439 }
12440
12441 protected function whitelistFromPackage(PackageInterface $package)
12442 {
12443 $workQueue = new \SplQueue;
12444 $workQueue->enqueue($package);
12445
12446 while (!$workQueue->isEmpty()) {
12447 $package = $workQueue->dequeue();
12448 if (isset($this->whitelistedMap[$package->id])) {
12449 continue;
12450 }
12451
12452 $this->whitelistedMap[$package->id] = true;
12453
12454 foreach ($package->getRequires() as $link) {
12455 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
12456
12457 foreach ($possibleRequires as $require) {
12458 $workQueue->enqueue($require);
12459 }
12460 }
12461
12462 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
12463
12464 foreach ($obsoleteProviders as $provider) {
12465 if ($provider === $package) {
12466 continue;
12467 }
12468
12469 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12470 $workQueue->enqueue($provider);
12471 }
12472 }
12473 }
12474 }
12475
12476 protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
12477 {
12478 $workQueue = new \SplQueue;
12479 $workQueue->enqueue($package);
12480
12481 while (!$workQueue->isEmpty()) {
12482 $package = $workQueue->dequeue();
12483 if (isset($this->addedMap[$package->id])) {
12484 continue;
12485 }
12486
12487 $this->addedMap[$package->id] = true;
12488
12489 foreach ($package->getRequires() as $link) {
12490 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
12491 continue;
12492 }
12493
12494 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12495
12496 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
12497
12498 foreach ($possibleRequires as $require) {
12499 $workQueue->enqueue($require);
12500 }
12501 }
12502
12503 foreach ($package->getConflicts() as $link) {
12504 $possibleConflicts = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12505
12506 foreach ($possibleConflicts as $conflict) {
12507 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $conflict, Rule::RULE_PACKAGE_CONFLICT, $link));
12508 }
12509 }
12510
12511
12512  $isInstalled = (isset($this->installedMap[$package->id]));
12513
12514 foreach ($package->getReplaces() as $link) {
12515 $obsoleteProviders = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12516
12517 foreach ($obsoleteProviders as $provider) {
12518 if ($provider === $package) {
12519 continue;
12520 }
12521
12522 if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12523 $reason = ($isInstalled) ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
12524 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $link));
12525 }
12526 }
12527 }
12528
12529 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null);
12530
12531 foreach ($obsoleteProviders as $provider) {
12532 if ($provider === $package) {
12533 continue;
12534 }
12535
12536 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12537 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
12538 } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12539 $reason = ($package->getName() == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
12540 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRule2Literals($package, $provider, $reason, $package));
12541 }
12542 }
12543 }
12544 }
12545
12546 protected function obsoleteImpossibleForAlias($package, $provider)
12547 {
12548 $packageIsAlias = $package instanceof AliasPackage;
12549 $providerIsAlias = $provider instanceof AliasPackage;
12550
12551 $impossible = (
12552 ($packageIsAlias && $package->getAliasOf() === $provider) ||
12553 ($providerIsAlias && $provider->getAliasOf() === $package) ||
12554 ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
12555 );
12556
12557 return $impossible;
12558 }
12559
12560 protected function whitelistFromJobs()
12561 {
12562 foreach ($this->jobs as $job) {
12563 switch ($job['cmd']) {
12564 case 'install':
12565 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
12566 foreach ($packages as $package) {
12567 $this->whitelistFromPackage($package);
12568 }
12569 break;
12570 }
12571 }
12572 }
12573
12574 protected function addRulesForJobs($ignorePlatformReqs)
12575 {
12576 foreach ($this->jobs as $job) {
12577 switch ($job['cmd']) {
12578 case 'install':
12579 if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
12580 break;
12581 }
12582
12583 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12584 if ($packages) {
12585 foreach ($packages as $package) {
12586 if (!isset($this->installedMap[$package->id])) {
12587 $this->addRulesForPackage($package, $ignorePlatformReqs);
12588 }
12589 }
12590
12591 $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
12592 $this->addRule(RuleSet::TYPE_JOB, $rule);
12593 }
12594 break;
12595 case 'remove':
12596
12597  
12598  $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12599 foreach ($packages as $package) {
12600 $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
12601 $this->addRule(RuleSet::TYPE_JOB, $rule);
12602 }
12603 break;
12604 }
12605 }
12606 }
12607
12608 public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
12609 {
12610 $this->jobs = $jobs;
12611 $this->rules = new RuleSet;
12612 $this->installedMap = $installedMap;
12613
12614 $this->whitelistedMap = array();
12615 foreach ($this->installedMap as $package) {
12616 $this->whitelistFromPackage($package);
12617 }
12618 $this->whitelistFromJobs();
12619
12620 $this->pool->setWhitelist($this->whitelistedMap);
12621
12622 $this->addedMap = array();
12623 foreach ($this->installedMap as $package) {
12624 $this->addRulesForPackage($package, $ignorePlatformReqs);
12625 }
12626
12627 $this->addRulesForJobs($ignorePlatformReqs);
12628
12629 return $this->rules;
12630 }
12631 }
12632 <?php
12633
12634
12635
12636
12637
12638
12639
12640
12641
12642
12643
12644 namespace Composer\DependencyResolver;
12645
12646
12647
12648
12649 class RuleSetIterator implements \Iterator
12650 {
12651 protected $rules;
12652 protected $types;
12653
12654 protected $currentOffset;
12655 protected $currentType;
12656 protected $currentTypeOffset;
12657
12658 public function __construct(array $rules)
12659 {
12660 $this->rules = $rules;
12661 $this->types = array_keys($rules);
12662 sort($this->types);
12663
12664 $this->rewind();
12665 }
12666
12667 public function current()
12668 {
12669 return $this->rules[$this->currentType][$this->currentOffset];
12670 }
12671
12672 public function key()
12673 {
12674 return $this->currentType;
12675 }
12676
12677 public function next()
12678 {
12679 $this->currentOffset++;
12680
12681 if (!isset($this->rules[$this->currentType])) {
12682 return;
12683 }
12684
12685 if ($this->currentOffset >= count($this->rules[$this->currentType])) {
12686 $this->currentOffset = 0;
12687
12688 do {
12689 $this->currentTypeOffset++;
12690
12691 if (!isset($this->types[$this->currentTypeOffset])) {
12692 $this->currentType = -1;
12693 break;
12694 }
12695
12696 $this->currentType = $this->types[$this->currentTypeOffset];
12697 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
12698 }
12699 }
12700
12701 public function rewind()
12702 {
12703 $this->currentOffset = 0;
12704
12705 $this->currentTypeOffset = -1;
12706 $this->currentType = -1;
12707
12708 do {
12709 $this->currentTypeOffset++;
12710
12711 if (!isset($this->types[$this->currentTypeOffset])) {
12712 $this->currentType = -1;
12713 break;
12714 }
12715
12716 $this->currentType = $this->types[$this->currentTypeOffset];
12717 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
12718 }
12719
12720 public function valid()
12721 {
12722 return isset($this->rules[$this->currentType])
12723 && isset($this->rules[$this->currentType][$this->currentOffset]);
12724 }
12725 }
12726 <?php
12727
12728
12729
12730
12731
12732
12733
12734
12735
12736
12737
12738 namespace Composer\DependencyResolver;
12739
12740
12741
12742
12743
12744
12745
12746
12747
12748 class RuleWatchChain extends \SplDoublyLinkedList
12749 {
12750 protected $offset = 0;
12751
12752
12753
12754
12755
12756
12757 public function seek($offset)
12758 {
12759 $this->rewind();
12760 for ($i = 0; $i < $offset; $i++, $this->next());
12761 }
12762
12763
12764
12765
12766
12767
12768
12769
12770
12771 public function remove()
12772 {
12773 $offset = $this->key();
12774 $this->offsetUnset($offset);
12775 $this->seek($offset);
12776 }
12777 }
12778 <?php
12779
12780
12781
12782
12783
12784
12785
12786
12787
12788
12789
12790 namespace Composer\DependencyResolver;
12791
12792
12793
12794
12795
12796
12797
12798
12799
12800
12801
12802 class RuleWatchGraph
12803 {
12804 protected $watchChains = array();
12805
12806
12807
12808
12809
12810
12811
12812
12813
12814
12815
12816
12817
12818 public function insert(RuleWatchNode $node)
12819 {
12820 if ($node->getRule()->isAssertion()) {
12821 return;
12822 }
12823
12824 foreach (array($node->watch1, $node->watch2) as $literal) {
12825 if (!isset($this->watchChains[$literal])) {
12826 $this->watchChains[$literal] = new RuleWatchChain;
12827 }
12828
12829 $this->watchChains[$literal]->unshift($node);
12830 }
12831 }
12832
12833
12834
12835
12836
12837
12838
12839
12840
12841
12842
12843
12844
12845
12846
12847
12848
12849
12850
12851
12852
12853
12854
12855
12856 public function propagateLiteral($decidedLiteral, $level, $decisions)
12857 {
12858
12859  
12860  
12861  $literal = -$decidedLiteral;
12862
12863 if (!isset($this->watchChains[$literal])) {
12864 return null;
12865 }
12866
12867 $chain = $this->watchChains[$literal];
12868
12869 $chain->rewind();
12870 while ($chain->valid()) {
12871 $node = $chain->current();
12872 $otherWatch = $node->getOtherWatch($literal);
12873
12874 if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
12875 $ruleLiterals = $node->getRule()->getLiterals();
12876
12877 $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
12878 return $literal !== $ruleLiteral &&
12879 $otherWatch !== $ruleLiteral &&
12880 !$decisions->conflict($ruleLiteral);
12881 });
12882
12883 if ($alternativeLiterals) {
12884 reset($alternativeLiterals);
12885 $this->moveWatch($literal, current($alternativeLiterals), $node);
12886 continue;
12887 }
12888
12889 if ($decisions->conflict($otherWatch)) {
12890 return $node->getRule();
12891 }
12892
12893 $decisions->decide($otherWatch, $level, $node->getRule());
12894 }
12895
12896 $chain->next();
12897 }
12898
12899 return null;
12900 }
12901
12902
12903
12904
12905
12906
12907
12908
12909
12910
12911 protected function moveWatch($fromLiteral, $toLiteral, $node)
12912 {
12913 if (!isset($this->watchChains[$toLiteral])) {
12914 $this->watchChains[$toLiteral] = new RuleWatchChain;
12915 }
12916
12917 $node->moveWatch($fromLiteral, $toLiteral);
12918 $this->watchChains[$fromLiteral]->remove();
12919 $this->watchChains[$toLiteral]->unshift($node);
12920 }
12921 }
12922 <?php
12923
12924
12925
12926
12927
12928
12929
12930
12931
12932
12933
12934 namespace Composer\DependencyResolver;
12935
12936
12937
12938
12939
12940
12941
12942
12943 class RuleWatchNode
12944 {
12945 public $watch1;
12946 public $watch2;
12947
12948 protected $rule;
12949
12950
12951
12952
12953
12954
12955 public function __construct($rule)
12956 {
12957 $this->rule = $rule;
12958
12959 $literals = $rule->getLiterals();
12960
12961 $this->watch1 = count($literals) > 0 ? $literals[0] : 0;
12962 $this->watch2 = count($literals) > 1 ? $literals[1] : 0;
12963 }
12964
12965
12966
12967
12968
12969
12970
12971
12972
12973 public function watch2OnHighest(Decisions $decisions)
12974 {
12975 $literals = $this->rule->getLiterals();
12976
12977
12978  if (count($literals) < 3) {
12979 return;
12980 }
12981
12982 $watchLevel = 0;
12983
12984 foreach ($literals as $literal) {
12985 $level = $decisions->decisionLevel($literal);
12986
12987 if ($level > $watchLevel) {
12988 $this->watch2 = $literal;
12989 $watchLevel = $level;
12990 }
12991 }
12992 }
12993
12994
12995
12996
12997
12998
12999 public function getRule()
13000 {
13001 return $this->rule;
13002 }
13003
13004
13005
13006
13007
13008
13009
13010 public function getOtherWatch($literal)
13011 {
13012 if ($this->watch1 == $literal) {
13013 return $this->watch2;
13014 }
13015
13016 return $this->watch1;
13017 }
13018
13019
13020
13021
13022
13023
13024
13025 public function moveWatch($from, $to)
13026 {
13027 if ($this->watch1 == $from) {
13028 $this->watch1 = $to;
13029 } else {
13030 $this->watch2 = $to;
13031 }
13032 }
13033 }
13034 <?php
13035
13036
13037
13038
13039
13040
13041
13042
13043
13044
13045
13046 namespace Composer\DependencyResolver;
13047
13048 use Composer\IO\IOInterface;
13049 use Composer\Repository\RepositoryInterface;
13050 use Composer\Repository\PlatformRepository;
13051
13052
13053
13054
13055 class Solver
13056 {
13057 const BRANCH_LITERALS = 0;
13058 const BRANCH_LEVEL = 1;
13059
13060
13061 protected $policy;
13062
13063 protected $pool;
13064
13065 protected $installed;
13066
13067 protected $rules;
13068
13069 protected $ruleSetGenerator;
13070
13071 protected $jobs;
13072
13073
13074 protected $updateMap = array();
13075
13076 protected $watchGraph;
13077
13078 protected $decisions;
13079
13080 protected $installedMap;
13081
13082
13083 protected $propagateIndex;
13084
13085 protected $branches = array();
13086
13087 protected $problems = array();
13088
13089 protected $learnedPool = array();
13090
13091 protected $learnedWhy = array();
13092
13093
13094 protected $io;
13095
13096
13097
13098
13099
13100
13101
13102 public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
13103 {
13104 $this->io = $io;
13105 $this->policy = $policy;
13106 $this->pool = $pool;
13107 $this->installed = $installed;
13108 $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
13109 }
13110
13111
13112
13113
13114 public function getRuleSetSize()
13115 {
13116 return count($this->rules);
13117 }
13118
13119
13120
13121 private function makeAssertionRuleDecisions()
13122 {
13123 $decisionStart = count($this->decisions) - 1;
13124
13125 $rulesCount = count($this->rules);
13126 for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
13127 $rule = $this->rules->ruleById[$ruleIndex];
13128
13129 if (!$rule->isAssertion() || $rule->isDisabled()) {
13130 continue;
13131 }
13132
13133 $literals = $rule->getLiterals();
13134 $literal = $literals[0];
13135
13136 if (!$this->decisions->decided(abs($literal))) {
13137 $this->decisions->decide($literal, 1, $rule);
13138 continue;
13139 }
13140
13141 if ($this->decisions->satisfy($literal)) {
13142 continue;
13143 }
13144
13145
13146  if (RuleSet::TYPE_LEARNED === $rule->getType()) {
13147 $rule->disable();
13148 continue;
13149 }
13150
13151 $conflict = $this->decisions->decisionRule($literal);
13152
13153 if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
13154 $problem = new Problem($this->pool);
13155
13156 $problem->addRule($rule);
13157 $problem->addRule($conflict);
13158 $this->disableProblem($rule);
13159 $this->problems[] = $problem;
13160 continue;
13161 }
13162
13163
13164  $problem = new Problem($this->pool);
13165 $problem->addRule($rule);
13166 $problem->addRule($conflict);
13167
13168
13169  
13170  foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
13171 if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
13172 continue;
13173 }
13174
13175 $assertRuleLiterals = $assertRule->getLiterals();
13176 $assertRuleLiteral = $assertRuleLiterals[0];
13177
13178 if (abs($literal) !== abs($assertRuleLiteral)) {
13179 continue;
13180 }
13181
13182 $problem->addRule($assertRule);
13183 $this->disableProblem($assertRule);
13184 }
13185 $this->problems[] = $problem;
13186
13187 $this->decisions->resetToOffset($decisionStart);
13188 $ruleIndex = -1;
13189 }
13190 }
13191
13192 protected function setupInstalledMap()
13193 {
13194 $this->installedMap = array();
13195 foreach ($this->installed->getPackages() as $package) {
13196 $this->installedMap[$package->id] = $package;
13197 }
13198 }
13199
13200
13201
13202
13203 protected function checkForRootRequireProblems($ignorePlatformReqs)
13204 {
13205 foreach ($this->jobs as $job) {
13206 switch ($job['cmd']) {
13207 case 'update':
13208 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
13209 foreach ($packages as $package) {
13210 if (isset($this->installedMap[$package->id])) {
13211 $this->updateMap[$package->id] = true;
13212 }
13213 }
13214 break;
13215
13216 case 'update-all':
13217 foreach ($this->installedMap as $package) {
13218 $this->updateMap[$package->id] = true;
13219 }
13220 break;
13221
13222 case 'install':
13223 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
13224 break;
13225 }
13226
13227 if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
13228 $problem = new Problem($this->pool);
13229 $problem->addRule(new GenericRule(array(), null, null, $job));
13230 $this->problems[] = $problem;
13231 }
13232 break;
13233 }
13234 }
13235 }
13236
13237
13238
13239
13240
13241
13242 public function solve(Request $request, $ignorePlatformReqs = false)
13243 {
13244 $this->jobs = $request->getJobs();
13245
13246 $this->setupInstalledMap();
13247 $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
13248 $this->checkForRootRequireProblems($ignorePlatformReqs);
13249 $this->decisions = new Decisions($this->pool);
13250 $this->watchGraph = new RuleWatchGraph;
13251
13252 foreach ($this->rules as $rule) {
13253 $this->watchGraph->insert(new RuleWatchNode($rule));
13254 }
13255
13256
13257 $this->makeAssertionRuleDecisions();
13258
13259 $this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
13260 $before = microtime(true);
13261 $this->runSat(true);
13262 $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
13263
13264
13265  foreach ($this->installedMap as $packageId => $void) {
13266 if ($this->decisions->undecided($packageId)) {
13267 $this->decisions->decide(-$packageId, 1, null);
13268 }
13269 }
13270
13271 if ($this->problems) {
13272 throw new SolverProblemsException($this->problems, $this->installedMap);
13273 }
13274
13275 $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
13276
13277 return $transaction->getOperations();
13278 }
13279
13280
13281
13282
13283
13284
13285
13286
13287
13288
13289 protected function propagate($level)
13290 {
13291 while ($this->decisions->validOffset($this->propagateIndex)) {
13292 $decision = $this->decisions->atOffset($this->propagateIndex);
13293
13294 $conflict = $this->watchGraph->propagateLiteral(
13295 $decision[Decisions::DECISION_LITERAL],
13296 $level,
13297 $this->decisions
13298 );
13299
13300 $this->propagateIndex++;
13301
13302 if ($conflict) {
13303 return $conflict;
13304 }
13305 }
13306
13307 return null;
13308 }
13309
13310
13311
13312
13313
13314
13315 private function revert($level)
13316 {
13317 while (!$this->decisions->isEmpty()) {
13318 $literal = $this->decisions->lastLiteral();
13319
13320 if ($this->decisions->undecided($literal)) {
13321 break;
13322 }
13323
13324 $decisionLevel = $this->decisions->decisionLevel($literal);
13325
13326 if ($decisionLevel <= $level) {
13327 break;
13328 }
13329
13330 $this->decisions->revertLast();
13331 $this->propagateIndex = count($this->decisions);
13332 }
13333
13334 while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
13335 array_pop($this->branches);
13336 }
13337 }
13338
13339
13340
13341
13342
13343
13344
13345
13346
13347
13348
13349
13350
13351
13352
13353
13354
13355
13356
13357
13358 private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
13359 {
13360 $level++;
13361
13362 $this->decisions->decide($literal, $level, $rule);
13363
13364 while (true) {
13365 $rule = $this->propagate($level);
13366
13367 if (!$rule) {
13368 break;
13369 }
13370
13371 if ($level == 1) {
13372 return $this->analyzeUnsolvable($rule, $disableRules);
13373 }
13374
13375
13376  list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
13377
13378 if ($newLevel <= 0 || $newLevel >= $level) {
13379 throw new SolverBugException(
13380 "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
13381 );
13382 } elseif (!$newRule) {
13383 throw new SolverBugException(
13384 "No rule was learned from analyzing $rule at level $level."
13385 );
13386 }
13387
13388 $level = $newLevel;
13389
13390 $this->revert($level);
13391
13392 $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
13393
13394 $this->learnedWhy[spl_object_hash($newRule)] = $why;
13395
13396 $ruleNode = new RuleWatchNode($newRule);
13397 $ruleNode->watch2OnHighest($this->decisions);
13398 $this->watchGraph->insert($ruleNode);
13399
13400 $this->decisions->decide($learnLiteral, $level, $newRule);
13401 }
13402
13403 return $level;
13404 }
13405
13406
13407
13408
13409
13410
13411
13412
13413 private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
13414 {
13415
13416  $literals = $this->policy->selectPreferredPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
13417
13418 $selectedLiteral = array_shift($literals);
13419
13420
13421  if (count($literals)) {
13422 $this->branches[] = array($literals, $level);
13423 }
13424
13425 return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
13426 }
13427
13428
13429
13430
13431
13432
13433 protected function analyze($level, Rule $rule)
13434 {
13435 $analyzedRule = $rule;
13436 $ruleLevel = 1;
13437 $num = 0;
13438 $l1num = 0;
13439 $seen = array();
13440 $learnedLiterals = array(null);
13441
13442 $decisionId = count($this->decisions);
13443
13444 $this->learnedPool[] = array();
13445
13446 while (true) {
13447 $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
13448
13449 foreach ($rule->getLiterals() as $literal) {
13450
13451  if ($this->decisions->satisfy($literal)) {
13452 continue;
13453 }
13454
13455 if (isset($seen[abs($literal)])) {
13456 continue;
13457 }
13458 $seen[abs($literal)] = true;
13459
13460 $l = $this->decisions->decisionLevel($literal);
13461
13462 if (1 === $l) {
13463 $l1num++;
13464 } elseif ($level === $l) {
13465 $num++;
13466 } else {
13467
13468  $learnedLiterals[] = $literal;
13469
13470 if ($l > $ruleLevel) {
13471 $ruleLevel = $l;
13472 }
13473 }
13474 }
13475
13476 $l1retry = true;
13477 while ($l1retry) {
13478 $l1retry = false;
13479
13480 if (!$num && !--$l1num) {
13481
13482  break 2;
13483 }
13484
13485 while (true) {
13486 if ($decisionId <= 0) {
13487 throw new SolverBugException(
13488 "Reached invalid decision id $decisionId while looking through $rule for a literal present in the analyzed rule $analyzedRule."
13489 );
13490 }
13491
13492 $decisionId--;
13493
13494 $decision = $this->decisions->atOffset($decisionId);
13495 $literal = $decision[Decisions::DECISION_LITERAL];
13496
13497 if (isset($seen[abs($literal)])) {
13498 break;
13499 }
13500 }
13501
13502 unset($seen[abs($literal)]);
13503
13504 if ($num && 0 === --$num) {
13505 $learnedLiterals[0] = -abs($literal);
13506
13507 if (!$l1num) {
13508 break 2;
13509 }
13510
13511 foreach ($learnedLiterals as $i => $learnedLiteral) {
13512 if ($i !== 0) {
13513 unset($seen[abs($learnedLiteral)]);
13514 }
13515 }
13516
13517  $l1num++;
13518 $l1retry = true;
13519 }
13520 }
13521
13522 $decision = $this->decisions->atOffset($decisionId);
13523 $rule = $decision[Decisions::DECISION_REASON];
13524 }
13525
13526 $why = count($this->learnedPool) - 1;
13527
13528 if (!$learnedLiterals[0]) {
13529 throw new SolverBugException(
13530 "Did not find a learnable literal in analyzed rule $analyzedRule."
13531 );
13532 }
13533
13534 $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why);
13535
13536 return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
13537 }
13538
13539
13540
13541
13542
13543 private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule)
13544 {
13545 $why = spl_object_hash($conflictRule);
13546
13547 if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
13548 $learnedWhy = $this->learnedWhy[$why];
13549 $problemRules = $this->learnedPool[$learnedWhy];
13550
13551 foreach ($problemRules as $problemRule) {
13552 $this->analyzeUnsolvableRule($problem, $problemRule);
13553 }
13554
13555 return;
13556 }
13557
13558 if ($conflictRule->getType() == RuleSet::TYPE_PACKAGE) {
13559
13560  return;
13561 }
13562
13563 $problem->nextSection();
13564 $problem->addRule($conflictRule);
13565 }
13566
13567
13568
13569
13570
13571
13572 private function analyzeUnsolvable(Rule $conflictRule, $disableRules)
13573 {
13574 $problem = new Problem($this->pool);
13575 $problem->addRule($conflictRule);
13576
13577 $this->analyzeUnsolvableRule($problem, $conflictRule);
13578
13579 $this->problems[] = $problem;
13580
13581 $seen = array();
13582 $literals = $conflictRule->getLiterals();
13583
13584 foreach ($literals as $literal) {
13585
13586  if ($this->decisions->satisfy($literal)) {
13587 continue;
13588 }
13589 $seen[abs($literal)] = true;
13590 }
13591
13592 foreach ($this->decisions as $decision) {
13593 $literal = $decision[Decisions::DECISION_LITERAL];
13594
13595
13596  if (!isset($seen[abs($literal)])) {
13597 continue;
13598 }
13599
13600 $why = $decision[Decisions::DECISION_REASON];
13601
13602 $problem->addRule($why);
13603 $this->analyzeUnsolvableRule($problem, $why);
13604
13605 $literals = $why->getLiterals();
13606
13607 foreach ($literals as $literal) {
13608
13609  if ($this->decisions->satisfy($literal)) {
13610 continue;
13611 }
13612 $seen[abs($literal)] = true;
13613 }
13614 }
13615
13616 if ($disableRules) {
13617 foreach ($this->problems[count($this->problems) - 1] as $reason) {
13618 $this->disableProblem($reason['rule']);
13619 }
13620
13621 $this->resetSolver();
13622
13623 return 1;
13624 }
13625
13626 return 0;
13627 }
13628
13629
13630
13631
13632 private function disableProblem(Rule $why)
13633 {
13634 $job = $why->getJob();
13635
13636 if (!$job) {
13637 $why->disable();
13638
13639 return;
13640 }
13641
13642
13643  foreach ($this->rules as $rule) {
13644
13645 if ($job === $rule->getJob()) {
13646 $rule->disable();
13647 }
13648 }
13649 }
13650
13651 private function resetSolver()
13652 {
13653 $this->decisions->reset();
13654
13655 $this->propagateIndex = 0;
13656 $this->branches = array();
13657
13658 $this->enableDisableLearnedRules();
13659 $this->makeAssertionRuleDecisions();
13660 }
13661
13662
13663
13664
13665
13666
13667
13668
13669 private function enableDisableLearnedRules()
13670 {
13671 foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
13672 $why = $this->learnedWhy[spl_object_hash($rule)];
13673 $problemRules = $this->learnedPool[$why];
13674
13675 $foundDisabled = false;
13676 foreach ($problemRules as $problemRule) {
13677 if ($problemRule->isDisabled()) {
13678 $foundDisabled = true;
13679 break;
13680 }
13681 }
13682
13683 if ($foundDisabled && $rule->isEnabled()) {
13684 $rule->disable();
13685 } elseif (!$foundDisabled && $rule->isDisabled()) {
13686 $rule->enable();
13687 }
13688 }
13689 }
13690
13691
13692
13693
13694 private function runSat($disableRules = true)
13695 {
13696 $this->propagateIndex = 0;
13697
13698
13699
13700
13701
13702
13703
13704
13705
13706
13707
13708 $decisionQueue = array();
13709 $decisionSupplementQueue = array();
13710
13711
13712
13713 $disableRules = array();
13714
13715 $level = 1;
13716 $systemLevel = $level + 1;
13717 $installedPos = 0;
13718
13719 while (true) {
13720 if (1 === $level) {
13721 $conflictRule = $this->propagate($level);
13722 if (null !== $conflictRule) {
13723 if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
13724 continue;
13725 }
13726
13727 return;
13728 }
13729 }
13730
13731
13732  if ($level < $systemLevel) {
13733 $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
13734 foreach ($iterator as $rule) {
13735 if ($rule->isEnabled()) {
13736 $decisionQueue = array();
13737 $noneSatisfied = true;
13738
13739 foreach ($rule->getLiterals() as $literal) {
13740 if ($this->decisions->satisfy($literal)) {
13741 $noneSatisfied = false;
13742 break;
13743 }
13744 if ($literal > 0 && $this->decisions->undecided($literal)) {
13745 $decisionQueue[] = $literal;
13746 }
13747 }
13748
13749 if ($noneSatisfied && count($decisionQueue)) {
13750
13751  
13752  if (count($this->installed) != count($this->updateMap)) {
13753 $prunedQueue = array();
13754 foreach ($decisionQueue as $literal) {
13755 if (isset($this->installedMap[abs($literal)])) {
13756 $prunedQueue[] = $literal;
13757 if (isset($this->updateMap[abs($literal)])) {
13758 $prunedQueue = $decisionQueue;
13759 break;
13760 }
13761 }
13762 }
13763 $decisionQueue = $prunedQueue;
13764 }
13765 }
13766
13767 if ($noneSatisfied && count($decisionQueue)) {
13768 $oLevel = $level;
13769 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
13770
13771 if (0 === $level) {
13772 return;
13773 }
13774 if ($level <= $oLevel) {
13775 break;
13776 }
13777 }
13778 }
13779 }
13780
13781 $systemLevel = $level + 1;
13782
13783
13784  $iterator->next();
13785 if ($iterator->valid()) {
13786 continue;
13787 }
13788 }
13789
13790 if ($level < $systemLevel) {
13791 $systemLevel = $level;
13792 }
13793
13794 $rulesCount = count($this->rules);
13795
13796 for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
13797 if ($i == $rulesCount) {
13798 $i = 0;
13799 }
13800
13801 $rule = $this->rules->ruleById[$i];
13802 $literals = $rule->getLiterals();
13803
13804 if ($rule->isDisabled()) {
13805 continue;
13806 }
13807
13808 $decisionQueue = array();
13809
13810
13811  
13812  
13813  
13814  
13815  
13816  foreach ($literals as $literal) {
13817 if ($literal <= 0) {
13818 if (!$this->decisions->decidedInstall(abs($literal))) {
13819 continue 2; 
13820  }
13821 } else {
13822 if ($this->decisions->decidedInstall(abs($literal))) {
13823 continue 2; 
13824  }
13825 if ($this->decisions->undecided(abs($literal))) {
13826 $decisionQueue[] = $literal;
13827 }
13828 }
13829 }
13830
13831
13832  if (count($decisionQueue) < 2) {
13833 continue;
13834 }
13835
13836 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
13837
13838 if (0 === $level) {
13839 return;
13840 }
13841
13842
13843  $rulesCount = count($this->rules);
13844 $n = -1;
13845 }
13846
13847 if ($level < $systemLevel) {
13848 continue;
13849 }
13850
13851
13852  if (count($this->branches)) {
13853 $lastLiteral = null;
13854 $lastLevel = null;
13855 $lastBranchIndex = 0;
13856 $lastBranchOffset = 0;
13857
13858 for ($i = count($this->branches) - 1; $i >= 0; $i--) {
13859 list($literals, $l) = $this->branches[$i];
13860
13861 foreach ($literals as $offset => $literal) {
13862 if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
13863 $lastLiteral = $literal;
13864 $lastBranchIndex = $i;
13865 $lastBranchOffset = $offset;
13866 $lastLevel = $l;
13867 }
13868 }
13869 }
13870
13871 if ($lastLiteral) {
13872 unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
13873
13874 $level = $lastLevel;
13875 $this->revert($level);
13876
13877 $why = $this->decisions->lastReason();
13878
13879 $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
13880
13881 if ($level == 0) {
13882 return;
13883 }
13884
13885 continue;
13886 }
13887 }
13888
13889 break;
13890 }
13891 }
13892 }
13893 <?php
13894
13895
13896
13897
13898
13899
13900
13901
13902
13903
13904
13905 namespace Composer\DependencyResolver;
13906
13907
13908
13909
13910 class SolverBugException extends \RuntimeException
13911 {
13912 public function __construct($message)
13913 {
13914 parent::__construct(
13915 $message."\nThis exception was most likely caused by a bug in Composer.\n".
13916 "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");
13917 }
13918 }
13919 <?php
13920
13921
13922
13923
13924
13925
13926
13927
13928
13929
13930
13931 namespace Composer\DependencyResolver;
13932
13933 use Composer\Util\IniHelper;
13934
13935
13936
13937
13938 class SolverProblemsException extends \RuntimeException
13939 {
13940 protected $problems;
13941 protected $installedMap;
13942
13943 public function __construct(array $problems, array $installedMap)
13944 {
13945 $this->problems = $problems;
13946 $this->installedMap = $installedMap;
13947
13948 parent::__construct($this->createMessage(), 2);
13949 }
13950
13951 protected function createMessage()
13952 {
13953 $text = "\n";
13954 $hasExtensionProblems = false;
13955 foreach ($this->problems as $i => $problem) {
13956 $text .= "  Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
13957
13958 if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
13959 $hasExtensionProblems = true;
13960 }
13961 }
13962
13963 if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
13964 $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.";
13965 }
13966
13967 if ($hasExtensionProblems) {
13968 $text .= $this->createExtensionHint();
13969 }
13970
13971 return $text;
13972 }
13973
13974 public function getProblems()
13975 {
13976 return $this->problems;
13977 }
13978
13979 private function createExtensionHint()
13980 {
13981 $paths = IniHelper::getAll();
13982
13983 if (count($paths) === 1 && empty($paths[0])) {
13984 return '';
13985 }
13986
13987 $text = "\n  To enable extensions, verify that they are enabled in your .ini files:\n    - ";
13988 $text .= implode("\n    - ", $paths);
13989 $text .= "\n  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
13990
13991 return $text;
13992 }
13993
13994 private function hasExtensionProblems(array $reasonSets)
13995 {
13996 foreach ($reasonSets as $reasonSet) {
13997 foreach ($reasonSet as $reason) {
13998 if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
13999 return true;
14000 }
14001 }
14002 }
14003
14004 return false;
14005 }
14006 }
14007 <?php
14008
14009
14010
14011
14012
14013
14014
14015
14016
14017
14018
14019 namespace Composer\DependencyResolver;
14020
14021 use Composer\Package\AliasPackage;
14022
14023
14024
14025
14026 class Transaction
14027 {
14028 protected $policy;
14029 protected $pool;
14030 protected $installedMap;
14031 protected $decisions;
14032 protected $transaction;
14033
14034 public function __construct($policy, $pool, $installedMap, $decisions)
14035 {
14036 $this->policy = $policy;
14037 $this->pool = $pool;
14038 $this->installedMap = $installedMap;
14039 $this->decisions = $decisions;
14040 $this->transaction = array();
14041 }
14042
14043 public function getOperations()
14044 {
14045 $installMeansUpdateMap = $this->findUpdates();
14046
14047 $updateMap = array();
14048 $installMap = array();
14049 $uninstallMap = array();
14050
14051 foreach ($this->decisions as $i => $decision) {
14052 $literal = $decision[Decisions::DECISION_LITERAL];
14053 $reason = $decision[Decisions::DECISION_REASON];
14054
14055 $package = $this->pool->literalToPackage($literal);
14056
14057
14058  if (($literal > 0) == (isset($this->installedMap[$package->id]))) {
14059 continue;
14060 }
14061
14062 if ($literal > 0) {
14063 if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
14064 $source = $installMeansUpdateMap[abs($literal)];
14065
14066 $updateMap[$package->id] = array(
14067 'package' => $package,
14068 'source' => $source,
14069 'reason' => $reason,
14070 );
14071
14072
14073  unset($installMeansUpdateMap[abs($literal)]);
14074 $ignoreRemove[$source->id] = true;
14075 } else {
14076 $installMap[$package->id] = array(
14077 'package' => $package,
14078 'reason' => $reason,
14079 );
14080 }
14081 }
14082 }
14083
14084 foreach ($this->decisions as $i => $decision) {
14085 $literal = $decision[Decisions::DECISION_LITERAL];
14086 $reason = $decision[Decisions::DECISION_REASON];
14087 $package = $this->pool->literalToPackage($literal);
14088
14089 if ($literal <= 0 &&
14090 isset($this->installedMap[$package->id]) &&
14091 !isset($ignoreRemove[$package->id])) {
14092 $uninstallMap[$package->id] = array(
14093 'package' => $package,
14094 'reason' => $reason,
14095 );
14096 }
14097 }
14098
14099 $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
14100
14101 return $this->transaction;
14102 }
14103
14104 protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
14105 {
14106 $queue = array_map(
14107 function ($operation) {
14108 return $operation['package'];
14109 },
14110 $this->findRootPackages($installMap, $updateMap)
14111 );
14112
14113 $visited = array();
14114
14115 while (!empty($queue)) {
14116 $package = array_pop($queue);
14117 $packageId = $package->id;
14118
14119 if (!isset($visited[$packageId])) {
14120 $queue[] = $package;
14121
14122 if ($package instanceof AliasPackage) {
14123 $queue[] = $package->getAliasOf();
14124 } else {
14125 foreach ($package->getRequires() as $link) {
14126 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
14127
14128 foreach ($possibleRequires as $require) {
14129 $queue[] = $require;
14130 }
14131 }
14132 }
14133
14134 $visited[$package->id] = true;
14135 } else {
14136 if (isset($installMap[$packageId])) {
14137 $this->install(
14138 $installMap[$packageId]['package'],
14139 $installMap[$packageId]['reason']
14140 );
14141 unset($installMap[$packageId]);
14142 }
14143 if (isset($updateMap[$packageId])) {
14144 $this->update(
14145 $updateMap[$packageId]['source'],
14146 $updateMap[$packageId]['package'],
14147 $updateMap[$packageId]['reason']
14148 );
14149 unset($updateMap[$packageId]);
14150 }
14151 }
14152 }
14153
14154 foreach ($uninstallMap as $uninstall) {
14155 $this->uninstall($uninstall['package'], $uninstall['reason']);
14156 }
14157 }
14158
14159 protected function findRootPackages($installMap, $updateMap)
14160 {
14161 $packages = $installMap + $updateMap;
14162 $roots = $packages;
14163
14164 foreach ($packages as $packageId => $operation) {
14165 $package = $operation['package'];
14166
14167 if (!isset($roots[$packageId])) {
14168 continue;
14169 }
14170
14171 foreach ($package->getRequires() as $link) {
14172 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
14173
14174 foreach ($possibleRequires as $require) {
14175 if ($require !== $package) {
14176 unset($roots[$require->id]);
14177 }
14178 }
14179 }
14180 }
14181
14182 return $roots;
14183 }
14184
14185 protected function findUpdates()
14186 {
14187 $installMeansUpdateMap = array();
14188
14189 foreach ($this->decisions as $i => $decision) {
14190 $literal = $decision[Decisions::DECISION_LITERAL];
14191 $package = $this->pool->literalToPackage($literal);
14192
14193 if ($package instanceof AliasPackage) {
14194 continue;
14195 }
14196
14197
14198  if ($literal <= 0 && isset($this->installedMap[$package->id])) {
14199 $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
14200
14201 $literals = array($package->id);
14202
14203 foreach ($updates as $update) {
14204 $literals[] = $update->id;
14205 }
14206
14207 foreach ($literals as $updateLiteral) {
14208 if ($updateLiteral !== $literal) {
14209 $installMeansUpdateMap[abs($updateLiteral)] = $package;
14210 }
14211 }
14212 }
14213 }
14214
14215 return $installMeansUpdateMap;
14216 }
14217
14218 protected function install($package, $reason)
14219 {
14220 if ($package instanceof AliasPackage) {
14221 return $this->markAliasInstalled($package, $reason);
14222 }
14223
14224 $this->transaction[] = new Operation\InstallOperation($package, $reason);
14225 }
14226
14227 protected function update($from, $to, $reason)
14228 {
14229 $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
14230 }
14231
14232 protected function uninstall($package, $reason)
14233 {
14234 if ($package instanceof AliasPackage) {
14235 return $this->markAliasUninstalled($package, $reason);
14236 }
14237
14238 $this->transaction[] = new Operation\UninstallOperation($package, $reason);
14239 }
14240
14241 protected function markAliasInstalled($package, $reason)
14242 {
14243 $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
14244 }
14245
14246 protected function markAliasUninstalled($package, $reason)
14247 {
14248 $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
14249 }
14250 }
14251 <?php
14252
14253
14254
14255
14256
14257
14258
14259
14260
14261
14262
14263 namespace Composer\Downloader;
14264
14265 use Composer\Package\PackageInterface;
14266 use Symfony\Component\Finder\Finder;
14267 use Composer\IO\IOInterface;
14268
14269
14270
14271
14272
14273
14274
14275
14276 abstract class ArchiveDownloader extends FileDownloader
14277 {
14278
14279
14280
14281 public function download(PackageInterface $package, $path, $output = true)
14282 {
14283 $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
14284 $retries = 3;
14285 while ($retries--) {
14286 $fileName = parent::download($package, $path, $output);
14287
14288 $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
14289
14290 try {
14291 $this->filesystem->ensureDirectoryExists($temporaryDir);
14292 try {
14293 $this->extract($fileName, $temporaryDir);
14294 } catch (\Exception $e) {
14295
14296  parent::clearLastCacheWrite($package);
14297 throw $e;
14298 }
14299
14300 $this->filesystem->unlink($fileName);
14301
14302 $contentDir = $this->getFolderContent($temporaryDir);
14303
14304
14305  if (1 === count($contentDir) && is_dir(reset($contentDir))) {
14306 $contentDir = $this->getFolderContent((string) reset($contentDir));
14307 }
14308
14309
14310  foreach ($contentDir as $file) {
14311 $file = (string) $file;
14312 $this->filesystem->rename($file, $path . '/' . basename($file));
14313 }
14314
14315 $this->filesystem->removeDirectory($temporaryDir);
14316 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
14317 $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
14318 }
14319 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
14320 $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
14321 }
14322 } catch (\Exception $e) {
14323
14324  $this->filesystem->removeDirectory($path);
14325 $this->filesystem->removeDirectory($temporaryDir);
14326
14327
14328  if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
14329 $this->io->writeError('');
14330 if ($this->io->isDebug()) {
14331 $this->io->writeError('    Invalid zip file ('.$e->getMessage().'), retrying...');
14332 } else {
14333 $this->io->writeError('    Invalid zip file, retrying...');
14334 }
14335 usleep(500000);
14336 continue;
14337 }
14338
14339 throw $e;
14340 }
14341
14342 break;
14343 }
14344 }
14345
14346
14347
14348
14349 protected function getFileName(PackageInterface $package, $path)
14350 {
14351 return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
14352 }
14353
14354
14355
14356
14357
14358
14359
14360
14361
14362 abstract protected function extract($file, $path);
14363
14364
14365
14366
14367
14368
14369
14370 private function getFolderContent($dir)
14371 {
14372 $finder = Finder::create()
14373 ->ignoreVCS(false)
14374 ->ignoreDotFiles(false)
14375 ->notName('.DS_Store')
14376 ->depth(0)
14377 ->in($dir);
14378
14379 return iterator_to_array($finder);
14380 }
14381 }
14382 <?php
14383
14384
14385
14386
14387
14388
14389
14390
14391
14392
14393
14394 namespace Composer\Downloader;
14395
14396 use Composer\Package\PackageInterface;
14397
14398
14399
14400
14401
14402
14403 interface ChangeReportInterface
14404 {
14405
14406
14407
14408
14409
14410
14411
14412 public function getLocalChanges(PackageInterface $package, $path);
14413 }
14414 <?php
14415
14416
14417
14418
14419
14420
14421
14422
14423
14424
14425
14426 namespace Composer\Downloader;
14427
14428 use Composer\Package\PackageInterface;
14429 use Composer\IO\IOInterface;
14430 use Composer\Util\Filesystem;
14431
14432
14433
14434
14435
14436
14437 class DownloadManager
14438 {
14439 private $io;
14440 private $preferDist = false;
14441 private $preferSource = false;
14442 private $packagePreferences = array();
14443 private $filesystem;
14444 private $downloaders = array();
14445
14446
14447
14448
14449
14450
14451
14452
14453 public function __construct(IOInterface $io, $preferSource = false, Filesystem $filesystem = null)
14454 {
14455 $this->io = $io;
14456 $this->preferSource = $preferSource;
14457 $this->filesystem = $filesystem ?: new Filesystem();
14458 }
14459
14460
14461
14462
14463
14464
14465
14466 public function setPreferSource($preferSource)
14467 {
14468 $this->preferSource = $preferSource;
14469
14470 return $this;
14471 }
14472
14473
14474
14475
14476
14477
14478
14479 public function setPreferDist($preferDist)
14480 {
14481 $this->preferDist = $preferDist;
14482
14483 return $this;
14484 }
14485
14486
14487
14488
14489
14490
14491
14492 public function setPreferences(array $preferences)
14493 {
14494 $this->packagePreferences = $preferences;
14495
14496 return $this;
14497 }
14498
14499
14500
14501
14502
14503
14504
14505
14506 public function setOutputProgress($outputProgress)
14507 {
14508 foreach ($this->downloaders as $downloader) {
14509 $downloader->setOutputProgress($outputProgress);
14510 }
14511
14512 return $this;
14513 }
14514
14515
14516
14517
14518
14519
14520
14521
14522 public function setDownloader($type, DownloaderInterface $downloader)
14523 {
14524 $type = strtolower($type);
14525 $this->downloaders[$type] = $downloader;
14526
14527 return $this;
14528 }
14529
14530
14531
14532
14533
14534
14535
14536
14537 public function getDownloader($type)
14538 {
14539 $type = strtolower($type);
14540 if (!isset($this->downloaders[$type])) {
14541 throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
14542 }
14543
14544 return $this->downloaders[$type];
14545 }
14546
14547
14548
14549
14550
14551
14552
14553
14554
14555
14556 public function getDownloaderForInstalledPackage(PackageInterface $package)
14557 {
14558 $installationSource = $package->getInstallationSource();
14559
14560 if ('metapackage' === $package->getType()) {
14561 return;
14562 }
14563
14564 if ('dist' === $installationSource) {
14565 $downloader = $this->getDownloader($package->getDistType());
14566 } elseif ('source' === $installationSource) {
14567 $downloader = $this->getDownloader($package->getSourceType());
14568 } else {
14569 throw new \InvalidArgumentException(
14570 'Package '.$package.' seems not been installed properly'
14571 );
14572 }
14573
14574 if ($installationSource !== $downloader->getInstallationSource()) {
14575 throw new \LogicException(sprintf(
14576 'Downloader "%s" is a %s type downloader and can not be used to download %s',
14577 get_class($downloader), $downloader->getInstallationSource(), $installationSource
14578 ));
14579 }
14580
14581 return $downloader;
14582 }
14583
14584
14585
14586
14587
14588
14589
14590
14591
14592
14593
14594 public function download(PackageInterface $package, $targetDir, $preferSource = null)
14595 {
14596 $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
14597 $sourceType = $package->getSourceType();
14598 $distType = $package->getDistType();
14599
14600 $sources = array();
14601 if ($sourceType) {
14602 $sources[] = 'source';
14603 }
14604 if ($distType) {
14605 $sources[] = 'dist';
14606 }
14607
14608 if (empty($sources)) {
14609 throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
14610 }
14611
14612 if (!$preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
14613 $sources = array_reverse($sources);
14614 }
14615
14616 $this->filesystem->ensureDirectoryExists($targetDir);
14617
14618 foreach ($sources as $i => $source) {
14619 if (isset($e)) {
14620 $this->io->writeError('    <warning>Now trying to download from ' . $source . '</warning>');
14621 }
14622 $package->setInstallationSource($source);
14623 try {
14624 $downloader = $this->getDownloaderForInstalledPackage($package);
14625 if ($downloader) {
14626 $downloader->download($package, $targetDir);
14627 }
14628 break;
14629 } catch (\RuntimeException $e) {
14630 if ($i === count($sources) - 1) {
14631 throw $e;
14632 }
14633
14634 $this->io->writeError(
14635 '    <warning>Failed to download '.
14636 $package->getPrettyName().
14637 ' from ' . $source . ': '.
14638 $e->getMessage().'</warning>'
14639 );
14640 }
14641 }
14642 }
14643
14644
14645
14646
14647
14648
14649
14650
14651
14652
14653 public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
14654 {
14655 $downloader = $this->getDownloaderForInstalledPackage($initial);
14656 if (!$downloader) {
14657 return;
14658 }
14659
14660 $installationSource = $initial->getInstallationSource();
14661
14662 if ('dist' === $installationSource) {
14663 $initialType = $initial->getDistType();
14664 $targetType = $target->getDistType();
14665 } else {
14666 $initialType = $initial->getSourceType();
14667 $targetType = $target->getSourceType();
14668 }
14669
14670
14671  if ($target->isDev() && 'dist' === $installationSource) {
14672 $downloader->remove($initial, $targetDir);
14673 $this->download($target, $targetDir);
14674
14675 return;
14676 }
14677
14678 if ($initialType === $targetType) {
14679 $target->setInstallationSource($installationSource);
14680 try {
14681 $downloader->update($initial, $target, $targetDir);
14682
14683 return;
14684 } catch (\RuntimeException $e) {
14685 if (!$this->io->isInteractive()) {
14686 throw $e;
14687 }
14688 $this->io->writeError('<error>    Update failed ('.$e->getMessage().')</error>');
14689 if (!$this->io->askConfirmation('    Would you like to try reinstalling the package instead [<comment>yes</comment>]? ', true)) {
14690 throw $e;
14691 }
14692 }
14693 }
14694
14695 $downloader->remove($initial, $targetDir);
14696 $this->download($target, $targetDir, 'source' === $installationSource);
14697 }
14698
14699
14700
14701
14702
14703
14704
14705 public function remove(PackageInterface $package, $targetDir)
14706 {
14707 $downloader = $this->getDownloaderForInstalledPackage($package);
14708 if ($downloader) {
14709 $downloader->remove($package, $targetDir);
14710 }
14711 }
14712
14713
14714
14715
14716
14717
14718
14719
14720 protected function resolvePackageInstallPreference(PackageInterface $package)
14721 {
14722 foreach ($this->packagePreferences as $pattern => $preference) {
14723 $pattern = '{^'.str_replace('\\*', '.*', preg_quote($pattern)).'$}i';
14724 if (preg_match($pattern, $package->getName())) {
14725 if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) {
14726 return 'dist';
14727 }
14728
14729 return 'source';
14730 }
14731 }
14732
14733 return $package->isDev() ? 'source' : 'dist';
14734 }
14735 }
14736 <?php
14737
14738
14739
14740
14741
14742
14743
14744
14745
14746
14747
14748 namespace Composer\Downloader;
14749
14750 use Composer\Package\PackageInterface;
14751
14752
14753
14754
14755
14756
14757
14758 interface DownloaderInterface
14759 {
14760
14761
14762
14763
14764
14765 public function getInstallationSource();
14766
14767
14768
14769
14770
14771
14772
14773 public function download(PackageInterface $package, $path);
14774
14775
14776
14777
14778
14779
14780
14781
14782 public function update(PackageInterface $initial, PackageInterface $target, $path);
14783
14784
14785
14786
14787
14788
14789
14790 public function remove(PackageInterface $package, $path);
14791
14792
14793
14794
14795
14796
14797
14798 public function setOutputProgress($outputProgress);
14799 }
14800 <?php
14801
14802
14803
14804
14805
14806
14807
14808
14809
14810
14811
14812 namespace Composer\Downloader;
14813
14814 use Composer\Package\PackageInterface;
14815
14816
14817
14818
14819
14820
14821 interface DvcsDownloaderInterface
14822 {
14823
14824
14825
14826
14827
14828
14829
14830 public function getUnpushedChanges(PackageInterface $package, $path);
14831 }
14832 <?php
14833
14834
14835
14836
14837
14838
14839
14840
14841
14842
14843
14844 namespace Composer\Downloader;
14845
14846 use Composer\Config;
14847 use Composer\Cache;
14848 use Composer\Factory;
14849 use Composer\IO\IOInterface;
14850 use Composer\Package\PackageInterface;
14851 use Composer\Plugin\PluginEvents;
14852 use Composer\Plugin\PreFileDownloadEvent;
14853 use Composer\EventDispatcher\EventDispatcher;
14854 use Composer\Util\Filesystem;
14855 use Composer\Util\RemoteFilesystem;
14856 use Composer\Util\Url as UrlUtil;
14857
14858
14859
14860
14861
14862
14863
14864
14865
14866 class FileDownloader implements DownloaderInterface
14867 {
14868 protected $io;
14869 protected $config;
14870 protected $rfs;
14871 protected $filesystem;
14872 protected $cache;
14873 protected $outputProgress = true;
14874 private $lastCacheWrites = array();
14875 private $eventDispatcher;
14876
14877
14878
14879
14880
14881
14882
14883
14884
14885
14886
14887 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
14888 {
14889 $this->io = $io;
14890 $this->config = $config;
14891 $this->eventDispatcher = $eventDispatcher;
14892 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
14893 $this->filesystem = $filesystem ?: new Filesystem();
14894 $this->cache = $cache;
14895
14896 if ($this->cache && $this->cache->gcIsNecessary()) {
14897 $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
14898 }
14899 }
14900
14901
14902
14903
14904 public function getInstallationSource()
14905 {
14906 return 'dist';
14907 }
14908
14909
14910
14911
14912 public function download(PackageInterface $package, $path, $output = true)
14913 {
14914 if (!$package->getDistUrl()) {
14915 throw new \InvalidArgumentException('The given package is missing url information');
14916 }
14917
14918 if ($output) {
14919 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
14920 }
14921
14922 $urls = $package->getDistUrls();
14923 while ($url = array_shift($urls)) {
14924 try {
14925 $fileName = $this->doDownload($package, $path, $url);
14926 break;
14927 } catch (\Exception $e) {
14928 if ($this->io->isDebug()) {
14929 $this->io->writeError('');
14930 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
14931 } elseif (count($urls)) {
14932 $this->io->writeError('');
14933 $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
14934 }
14935
14936 if (!count($urls)) {
14937 throw $e;
14938 }
14939 }
14940 }
14941
14942 if ($output) {
14943 $this->io->writeError('');
14944 }
14945
14946 return $fileName;
14947 }
14948
14949 protected function doDownload(PackageInterface $package, $path, $url)
14950 {
14951 $this->filesystem->emptyDirectory($path);
14952
14953 $fileName = $this->getFileName($package, $path);
14954
14955 $processedUrl = $this->processUrl($package, $url);
14956 $hostname = parse_url($processedUrl, PHP_URL_HOST);
14957
14958 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
14959 if ($this->eventDispatcher) {
14960 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
14961 }
14962 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
14963
14964 try {
14965 $checksum = $package->getDistSha1Checksum();
14966 $cacheKey = $this->getCacheKey($package, $processedUrl);
14967
14968
14969  if (!$this->cache || ($checksum && $checksum !== $this->cache->sha1($cacheKey)) || !$this->cache->copyTo($cacheKey, $fileName)) {
14970 if (!$this->outputProgress) {
14971 $this->io->writeError('Downloading', false);
14972 }
14973
14974
14975  $retries = 3;
14976 while ($retries--) {
14977 try {
14978 $rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
14979 break;
14980 } catch (TransportException $e) {
14981
14982  if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
14983 throw $e;
14984 }
14985 $this->io->writeError('');
14986 $this->io->writeError('    Download failed, retrying...', true, IOInterface::VERBOSE);
14987 usleep(500000);
14988 }
14989 }
14990
14991 if (!$this->outputProgress) {
14992 $this->io->writeError(' (<comment>100%</comment>)', false);
14993 }
14994
14995 if ($this->cache) {
14996 $this->lastCacheWrites[$package->getName()] = $cacheKey;
14997 $this->cache->copyFrom($cacheKey, $fileName);
14998 }
14999 } else {
15000 $this->io->writeError('Loading from cache', false);
15001 }
15002
15003 if (!file_exists($fileName)) {
15004 throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
15005 .' directory is writable and you have internet connectivity');
15006 }
15007
15008 if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
15009 throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
15010 }
15011 } catch (\Exception $e) {
15012
15013  $this->filesystem->removeDirectory($path);
15014 $this->clearLastCacheWrite($package);
15015 throw $e;
15016 }
15017
15018 return $fileName;
15019 }
15020
15021
15022
15023
15024 public function setOutputProgress($outputProgress)
15025 {
15026 $this->outputProgress = $outputProgress;
15027
15028 return $this;
15029 }
15030
15031 protected function clearLastCacheWrite(PackageInterface $package)
15032 {
15033 if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
15034 $this->cache->remove($this->lastCacheWrites[$package->getName()]);
15035 unset($this->lastCacheWrites[$package->getName()]);
15036 }
15037 }
15038
15039
15040
15041
15042 public function update(PackageInterface $initial, PackageInterface $target, $path)
15043 {
15044 $name = $target->getName();
15045 $from = $initial->getPrettyVersion();
15046 $to = $target->getPrettyVersion();
15047
15048 $this->io->writeError("  - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
15049
15050 $this->remove($initial, $path, false);
15051 $this->download($target, $path, false);
15052
15053 $this->io->writeError('');
15054 }
15055
15056
15057
15058
15059 public function remove(PackageInterface $package, $path, $output = true)
15060 {
15061 if ($output) {
15062 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
15063 }
15064 if (!$this->filesystem->removeDirectory($path)) {
15065 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
15066 }
15067 }
15068
15069
15070
15071
15072
15073
15074
15075
15076 protected function getFileName(PackageInterface $package, $path)
15077 {
15078 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
15079 }
15080
15081
15082
15083
15084
15085
15086
15087
15088
15089 protected function processUrl(PackageInterface $package, $url)
15090 {
15091 if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
15092 throw new \RuntimeException('You must enable the openssl extension to download files via https');
15093 }
15094
15095 if ($package->getDistReference()) {
15096 $url = UrlUtil::updateDistReference($this->config, $url, $package->getDistReference());
15097 }
15098
15099 return $url;
15100 }
15101
15102 private function getCacheKey(PackageInterface $package, $processedUrl)
15103 {
15104
15105  
15106  
15107  
15108  $cacheKey = sha1($processedUrl);
15109
15110 return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
15111 }
15112 }
15113 <?php
15114
15115
15116
15117
15118
15119
15120
15121
15122
15123
15124
15125 namespace Composer\Downloader;
15126
15127
15128
15129
15130
15131
15132 class FilesystemException extends \Exception
15133 {
15134 public function __construct($message = '', $code = 0, \Exception $previous = null)
15135 {
15136 parent::__construct("Filesystem exception: \n".$message, $code, $previous);
15137 }
15138 }
15139 <?php
15140
15141
15142
15143
15144
15145
15146
15147
15148
15149
15150
15151 namespace Composer\Downloader;
15152
15153 use Composer\Package\PackageInterface;
15154 use Composer\Util\ProcessExecutor;
15155
15156
15157
15158
15159 class FossilDownloader extends VcsDownloader
15160 {
15161
15162
15163
15164 public function doDownload(PackageInterface $package, $path, $url)
15165 {
15166
15167  $this->config->prohibitUrlByConfig($url, $this->io);
15168
15169 $url = ProcessExecutor::escape($url);
15170 $ref = ProcessExecutor::escape($package->getSourceReference());
15171 $repoFile = $path . '.fossil';
15172 $this->io->writeError("Cloning ".$package->getSourceReference());
15173 $command = sprintf('fossil clone %s %s', $url, ProcessExecutor::escape($repoFile));
15174 if (0 !== $this->process->execute($command, $ignoredOutput)) {
15175 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15176 }
15177 $command = sprintf('fossil open %s', ProcessExecutor::escape($repoFile));
15178 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15179 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15180 }
15181 $command = sprintf('fossil update %s', $ref);
15182 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15183 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15184 }
15185 }
15186
15187
15188
15189
15190 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15191 {
15192
15193  $this->config->prohibitUrlByConfig($url, $this->io);
15194
15195 $url = ProcessExecutor::escape($url);
15196 $ref = ProcessExecutor::escape($target->getSourceReference());
15197 $this->io->writeError(" Updating to ".$target->getSourceReference());
15198
15199 if (!$this->hasMetadataRepository($path)) {
15200 throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15201 }
15202
15203 $command = sprintf('fossil pull && fossil up %s', $ref);
15204 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15205 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15206 }
15207 }
15208
15209
15210
15211
15212 public function getLocalChanges(PackageInterface $package, $path)
15213 {
15214 if (!$this->hasMetadataRepository($path)) {
15215 return null;
15216 }
15217
15218 $this->process->execute('fossil changes', $output, realpath($path));
15219
15220 return trim($output) ?: null;
15221 }
15222
15223
15224
15225
15226 protected function getCommitLogs($fromReference, $toReference, $path)
15227 {
15228 $command = sprintf('fossil timeline -t ci -W 0 -n 0 before %s', $toReference);
15229
15230 if (0 !== $this->process->execute($command, $output, realpath($path))) {
15231 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15232 }
15233
15234 $log = '';
15235 $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
15236
15237 foreach ($this->process->splitLines($output) as $line) {
15238 if (preg_match($match, $line)) {
15239 break;
15240 }
15241 $log .= $line;
15242 }
15243
15244 return $log;
15245 }
15246
15247
15248
15249
15250 protected function hasMetadataRepository($path)
15251 {
15252 return is_file($path . '/.fslckout') || is_file($path . '/_FOSSIL_');
15253 }
15254 }
15255 <?php
15256
15257
15258
15259
15260
15261
15262
15263
15264
15265
15266
15267 namespace Composer\Downloader;
15268
15269 use Composer\Config;
15270 use Composer\IO\IOInterface;
15271 use Composer\Package\PackageInterface;
15272 use Composer\Util\Filesystem;
15273 use Composer\Util\Git as GitUtil;
15274 use Composer\Util\Platform;
15275 use Composer\Util\ProcessExecutor;
15276
15277
15278
15279
15280 class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
15281 {
15282 private $hasStashedChanges = false;
15283 private $hasDiscardedChanges = false;
15284 private $gitUtil;
15285
15286 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
15287 {
15288 parent::__construct($io, $config, $process, $fs);
15289 $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
15290 }
15291
15292
15293
15294
15295 public function doDownload(PackageInterface $package, $path, $url)
15296 {
15297 GitUtil::cleanEnv();
15298 $path = $this->normalizePath($path);
15299 $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
15300 $ref = $package->getSourceReference();
15301 $flag = Platform::isWindows() ? '/D ' : '';
15302
15303
15304  $gitVersion = $this->gitUtil->getVersion();
15305 $msg = "Cloning ".$this->getShortHash($ref);
15306
15307 $command = 'git clone --no-checkout %url% %path% && cd '.$flag.'%path% && git remote add composer %url% && git fetch composer';
15308 if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=')) {
15309 $this->io->writeError('', true, IOInterface::DEBUG);
15310 $this->io->writeError(sprintf('    Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
15311 try {
15312 $this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref);
15313 if (is_dir($cachePath)) {
15314 $command =
15315 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% '
15316 . '&& cd '.$flag.'%path% '
15317 . '&& git remote set-url origin %url% && git remote add composer %url%';
15318 $msg = "Cloning ".$this->getShortHash($ref).' from cache';
15319 }
15320 } catch (\RuntimeException $e) {
15321 }
15322 }
15323 $this->io->writeError($msg);
15324
15325 $commandCallable = function ($url) use ($path, $command, $cachePath) {
15326 return str_replace(
15327 array('%url%', '%path%', '%cachePath%'),
15328 array(
15329 ProcessExecutor::escape($url),
15330 ProcessExecutor::escape($path),
15331 ProcessExecutor::escape($cachePath),
15332 ),
15333 $command
15334 );
15335 };
15336
15337 $this->gitUtil->runCommand($commandCallable, $url, $path, true);
15338 if ($url !== $package->getSourceUrl()) {
15339 $this->updateOriginUrl($path, $package->getSourceUrl());
15340 } else {
15341 $this->setPushUrl($path, $url);
15342 }
15343
15344 if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
15345 if ($package->getDistReference() === $package->getSourceReference()) {
15346 $package->setDistReference($newRef);
15347 }
15348 $package->setSourceReference($newRef);
15349 }
15350 }
15351
15352
15353
15354
15355 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15356 {
15357 GitUtil::cleanEnv();
15358 if (!$this->hasMetadataRepository($path)) {
15359 throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15360 }
15361
15362 $updateOriginUrl = false;
15363 if (
15364 0 === $this->process->execute('git remote -v', $output, $path)
15365 && preg_match('{^origin\s+(?P<url>\S+)}m', $output, $originMatch)
15366 && preg_match('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)
15367 ) {
15368 if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
15369 $updateOriginUrl = true;
15370 }
15371 }
15372
15373 $ref = $target->getSourceReference();
15374 $this->io->writeError(" Checking out ".$this->getShortHash($ref));
15375 $command = 'git remote set-url composer %s && git rev-parse --quiet --verify %s || (git fetch composer && git fetch --tags composer)';
15376
15377 $commandCallable = function ($url) use ($command, $ref) {
15378 return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($ref.'^{commit}'));
15379 };
15380
15381 $this->gitUtil->runCommand($commandCallable, $url, $path);
15382 if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
15383 if ($target->getDistReference() === $target->getSourceReference()) {
15384 $target->setDistReference($newRef);
15385 }
15386 $target->setSourceReference($newRef);
15387 }
15388
15389 if ($updateOriginUrl) {
15390 $this->updateOriginUrl($path, $target->getSourceUrl());
15391 }
15392 }
15393
15394
15395
15396
15397 public function getLocalChanges(PackageInterface $package, $path)
15398 {
15399 GitUtil::cleanEnv();
15400 if (!$this->hasMetadataRepository($path)) {
15401 return;
15402 }
15403
15404 $command = 'git status --porcelain --untracked-files=no';
15405 if (0 !== $this->process->execute($command, $output, $path)) {
15406 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15407 }
15408
15409 return trim($output) ?: null;
15410 }
15411
15412 public function getUnpushedChanges(PackageInterface $package, $path)
15413 {
15414 GitUtil::cleanEnv();
15415 $path = $this->normalizePath($path);
15416 if (!$this->hasMetadataRepository($path)) {
15417 return;
15418 }
15419
15420 $command = 'git show-ref --head -d';
15421 if (0 !== $this->process->execute($command, $output, $path)) {
15422 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15423 }
15424
15425 $refs = trim($output);
15426 if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
15427
15428  return;
15429 }
15430
15431 $headRef = $match[1];
15432 if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
15433
15434  return;
15435 }
15436
15437
15438  $branch = $matches[1][0];
15439 $unpushedChanges = null;
15440
15441
15442  for ($i = 0; $i <= 1; $i++) {
15443
15444  foreach ($matches[1] as $candidate) {
15445 if (preg_match('{^[a-f0-9]+ refs/remotes/((?:composer|origin)/'.preg_quote($candidate).')$}mi', $refs, $match)) {
15446 $branch = $candidate;
15447 $remoteBranch = $match[1];
15448 break;
15449 }
15450 }
15451
15452
15453  
15454  
15455  if (!isset($remoteBranch)) {
15456 $unpushedChanges = 'Branch ' . $branch . ' could not be found on the origin remote and appears to be unpushed';
15457 } else {
15458 $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
15459 if (0 !== $this->process->execute($command, $output, $path)) {
15460 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15461 }
15462
15463 $unpushedChanges = trim($output) ?: null;
15464 }
15465
15466
15467  
15468  if ($unpushedChanges && $i === 0) {
15469 $this->process->execute('git fetch composer && git fetch origin', $output, $path);
15470 }
15471
15472
15473  if (!$unpushedChanges) {
15474 break;
15475 }
15476 }
15477
15478 return $unpushedChanges;
15479 }
15480
15481
15482
15483
15484 protected function cleanChanges(PackageInterface $package, $path, $update)
15485 {
15486 GitUtil::cleanEnv();
15487 $path = $this->normalizePath($path);
15488
15489 $unpushed = $this->getUnpushedChanges($package, $path);
15490 if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== true)) {
15491 throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: '."\n".$unpushed);
15492 }
15493
15494 if (!$changes = $this->getLocalChanges($package, $path)) {
15495 return;
15496 }
15497
15498 if (!$this->io->isInteractive()) {
15499 $discardChanges = $this->config->get('discard-changes');
15500 if (true === $discardChanges) {
15501 return $this->discardChanges($path);
15502 }
15503 if ('stash' === $discardChanges) {
15504 if (!$update) {
15505 return parent::cleanChanges($package, $path, $update);
15506 }
15507
15508 return $this->stashChanges($path);
15509 }
15510
15511 return parent::cleanChanges($package, $path, $update);
15512 }
15513
15514 $changes = array_map(function ($elem) {
15515 return '    '.$elem;
15516 }, preg_split('{\s*\r?\n\s*}', $changes));
15517 $this->io->writeError('    <error>The package has modified files:</error>');
15518 $this->io->writeError(array_slice($changes, 0, 10));
15519 if (count($changes) > 10) {
15520 $this->io->writeError('    <info>' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list</info>');
15521 }
15522
15523 while (true) {
15524 switch ($this->io->ask('    <info>Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]?</info> ', '?')) {
15525 case 'y':
15526 $this->discardChanges($path);
15527 break 2;
15528
15529 case 's':
15530 if (!$update) {
15531 goto help;
15532 }
15533
15534 $this->stashChanges($path);
15535 break 2;
15536
15537 case 'n':
15538 throw new \RuntimeException('Update aborted');
15539
15540 case 'v':
15541 $this->io->writeError($changes);
15542 break;
15543
15544 case 'd':
15545 $this->viewDiff($path);
15546 break;
15547
15548 case '?':
15549 default:
15550 help:
15551 $this->io->writeError(array(
15552 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
15553 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
15554 '    v - view modified files',
15555 '    d - view local modifications (diff)',
15556 ));
15557 if ($update) {
15558 $this->io->writeError('    s - stash changes and try to reapply them after the update');
15559 }
15560 $this->io->writeError('    ? - print help');
15561 break;
15562 }
15563 }
15564 }
15565
15566
15567
15568
15569 protected function reapplyChanges($path)
15570 {
15571 $path = $this->normalizePath($path);
15572 if ($this->hasStashedChanges) {
15573 $this->hasStashedChanges = false;
15574 $this->io->writeError('    <info>Re-applying stashed changes</info>');
15575 if (0 !== $this->process->execute('git stash pop', $output, $path)) {
15576 throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
15577 }
15578 }
15579
15580 $this->hasDiscardedChanges = false;
15581 }
15582
15583
15584
15585
15586
15587
15588
15589
15590
15591
15592
15593 protected function updateToCommit($path, $reference, $branch, $date)
15594 {
15595 $force = $this->hasDiscardedChanges || $this->hasStashedChanges ? '-f ' : '';
15596
15597
15598  
15599  
15600  
15601  
15602  $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
15603 $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);
15604
15605 $branches = null;
15606 if (0 === $this->process->execute('git branch -r', $output, $path)) {
15607 $branches = $output;
15608 }
15609
15610
15611  $gitRef = $reference;
15612 if (!preg_match('{^[a-f0-9]{40}$}', $reference)
15613 && $branches
15614 && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
15615 ) {
15616 $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
15617 if (0 === $this->process->execute($command, $output, $path)) {
15618 return;
15619 }
15620 }
15621
15622
15623  if (preg_match('{^[a-f0-9]{40}$}', $reference)) {
15624
15625  if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) {
15626 $branch = 'v' . $branch;
15627 }
15628
15629 $command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
15630 $fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
15631 if (0 === $this->process->execute($command, $output, $path)
15632 || 0 === $this->process->execute($fallbackCommand, $output, $path)
15633 ) {
15634 $command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
15635 if (0 === $this->process->execute($command, $output, $path)) {
15636 return;
15637 }
15638 }
15639 }
15640
15641 $command = sprintf($template, ProcessExecutor::escape($gitRef));
15642 if (0 === $this->process->execute($command, $output, $path)) {
15643 return;
15644 }
15645
15646
15647  if (false !== strpos($this->process->getErrorOutput(), $reference)) {
15648 $this->io->writeError('    <warning>'.$reference.' is gone (history was rewritten?)</warning>');
15649 }
15650
15651 throw new \RuntimeException(GitUtil::sanitizeUrl('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
15652 }
15653
15654 protected function updateOriginUrl($path, $url)
15655 {
15656 $this->process->execute(sprintf('git remote set-url origin %s', ProcessExecutor::escape($url)), $output, $path);
15657 $this->setPushUrl($path, $url);
15658 }
15659
15660 protected function setPushUrl($path, $url)
15661 {
15662
15663  if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
15664 $protocols = $this->config->get('github-protocols');
15665 $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git';
15666 if (!in_array('ssh', $protocols, true)) {
15667 $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
15668 }
15669 $cmd = sprintf('git remote set-url --push origin %s', ProcessExecutor::escape($pushUrl));
15670 $this->process->execute($cmd, $ignoredOutput, $path);
15671 }
15672 }
15673
15674
15675
15676
15677 protected function getCommitLogs($fromReference, $toReference, $path)
15678 {
15679 $path = $this->normalizePath($path);
15680 $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', $fromReference, $toReference);
15681
15682 if (0 !== $this->process->execute($command, $output, $path)) {
15683 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15684 }
15685
15686 return $output;
15687 }
15688
15689
15690
15691
15692
15693 protected function discardChanges($path)
15694 {
15695 $path = $this->normalizePath($path);
15696 if (0 !== $this->process->execute('git reset --hard', $output, $path)) {
15697 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
15698 }
15699
15700 $this->hasDiscardedChanges = true;
15701 }
15702
15703
15704
15705
15706
15707 protected function stashChanges($path)
15708 {
15709 $path = $this->normalizePath($path);
15710 if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
15711 throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
15712 }
15713
15714 $this->hasStashedChanges = true;
15715 }
15716
15717
15718
15719
15720
15721 protected function viewDiff($path)
15722 {
15723 $path = $this->normalizePath($path);
15724 if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
15725 throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
15726 }
15727
15728 $this->io->writeError($output);
15729 }
15730
15731 protected function normalizePath($path)
15732 {
15733 if (Platform::isWindows() && strlen($path) > 0) {
15734 $basePath = $path;
15735 $removed = array();
15736
15737 while (!is_dir($basePath) && $basePath !== '\\') {
15738 array_unshift($removed, basename($basePath));
15739 $basePath = dirname($basePath);
15740 }
15741
15742 if ($basePath === '\\') {
15743 return $path;
15744 }
15745
15746 $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
15747 }
15748
15749 return $path;
15750 }
15751
15752
15753
15754
15755 protected function hasMetadataRepository($path)
15756 {
15757 $path = $this->normalizePath($path);
15758
15759 return is_dir($path.'/.git');
15760 }
15761
15762 protected function getShortHash($reference)
15763 {
15764 if (!$this->io->isVerbose() && preg_match('{^[0-9a-f]{40}$}', $reference)) {
15765 return substr($reference, 0, 10);
15766 }
15767
15768 return $reference;
15769 }
15770 }
15771 <?php
15772
15773
15774
15775
15776
15777
15778
15779
15780
15781
15782
15783 namespace Composer\Downloader;
15784
15785 use Composer\Config;
15786 use Composer\Cache;
15787 use Composer\EventDispatcher\EventDispatcher;
15788 use Composer\Package\PackageInterface;
15789 use Composer\Util\Platform;
15790 use Composer\Util\ProcessExecutor;
15791 use Composer\Util\RemoteFilesystem;
15792 use Composer\IO\IOInterface;
15793
15794
15795
15796
15797
15798
15799 class GzipDownloader extends ArchiveDownloader
15800 {
15801 protected $process;
15802
15803 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
15804 {
15805 $this->process = $process ?: new ProcessExecutor($io);
15806 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
15807 }
15808
15809 protected function extract($file, $path)
15810 {
15811 $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
15812
15813
15814  if (!Platform::isWindows()) {
15815 $command = 'gzip -cd ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
15816
15817 if (0 === $this->process->execute($command, $ignoredOutput)) {
15818 return;
15819 }
15820
15821 if (extension_loaded('zlib')) {
15822
15823  $this->extractUsingExt($file, $targetFilepath);
15824
15825 return;
15826 }
15827
15828 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
15829 throw new \RuntimeException($processError);
15830 }
15831
15832
15833  $this->extractUsingExt($file, $targetFilepath);
15834 }
15835
15836
15837
15838
15839 protected function getFileName(PackageInterface $package, $path)
15840 {
15841 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
15842 }
15843
15844 private function extractUsingExt($file, $targetFilepath)
15845 {
15846 $archiveFile = gzopen($file, 'rb');
15847 $targetFile = fopen($targetFilepath, 'wb');
15848 while ($string = gzread($archiveFile, 4096)) {
15849 fwrite($targetFile, $string, Platform::strlen($string));
15850 }
15851 gzclose($archiveFile);
15852 fclose($targetFile);
15853 }
15854 }
15855 <?php
15856
15857
15858
15859
15860
15861
15862
15863
15864
15865
15866
15867 namespace Composer\Downloader;
15868
15869 use Composer\Package\PackageInterface;
15870 use Composer\Util\ProcessExecutor;
15871
15872
15873
15874
15875 class HgDownloader extends VcsDownloader
15876 {
15877
15878
15879
15880 public function doDownload(PackageInterface $package, $path, $url)
15881 {
15882
15883  $this->config->prohibitUrlByConfig($url, $this->io);
15884
15885 $url = ProcessExecutor::escape($url);
15886 $ref = ProcessExecutor::escape($package->getSourceReference());
15887 $this->io->writeError("Cloning ".$package->getSourceReference());
15888 $command = sprintf('hg clone %s %s', $url, ProcessExecutor::escape($path));
15889 if (0 !== $this->process->execute($command, $ignoredOutput)) {
15890 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15891 }
15892 $command = sprintf('hg up %s', $ref);
15893 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15894 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15895 }
15896 }
15897
15898
15899
15900
15901 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15902 {
15903
15904  $this->config->prohibitUrlByConfig($url, $this->io);
15905
15906 $url = ProcessExecutor::escape($url);
15907 $ref = ProcessExecutor::escape($target->getSourceReference());
15908 $this->io->writeError(" Updating to ".$target->getSourceReference());
15909
15910 if (!$this->hasMetadataRepository($path)) {
15911 throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15912 }
15913
15914 $command = sprintf('hg pull %s && hg up %s', $url, $ref);
15915 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15916 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15917 }
15918 }
15919
15920
15921
15922
15923 public function getLocalChanges(PackageInterface $package, $path)
15924 {
15925 if (!is_dir($path.'/.hg')) {
15926 return null;
15927 }
15928
15929 $this->process->execute('hg st', $output, realpath($path));
15930
15931 return trim($output) ?: null;
15932 }
15933
15934
15935
15936
15937 protected function getCommitLogs($fromReference, $toReference, $path)
15938 {
15939 $command = sprintf('hg log -r %s:%s --style compact', $fromReference, $toReference);
15940
15941 if (0 !== $this->process->execute($command, $output, realpath($path))) {
15942 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15943 }
15944
15945 return $output;
15946 }
15947
15948
15949
15950
15951 protected function hasMetadataRepository($path)
15952 {
15953 return is_dir($path . '/.hg');
15954 }
15955 }
15956 <?php
15957
15958
15959
15960
15961
15962
15963
15964
15965
15966
15967
15968 namespace Composer\Downloader;
15969
15970 use Composer\Package\Archiver\ArchivableFilesFinder;
15971 use Composer\Package\Dumper\ArrayDumper;
15972 use Composer\Package\PackageInterface;
15973 use Composer\Package\Version\VersionGuesser;
15974 use Composer\Package\Version\VersionParser;
15975 use Composer\Util\Platform;
15976 use Composer\Util\ProcessExecutor;
15977 use Composer\Util\Filesystem as ComposerFilesystem;
15978 use Symfony\Component\Filesystem\Exception\IOException;
15979 use Symfony\Component\Filesystem\Filesystem;
15980
15981
15982
15983
15984
15985
15986
15987 class PathDownloader extends FileDownloader implements VcsCapableDownloaderInterface
15988 {
15989 const STRATEGY_SYMLINK = 10;
15990 const STRATEGY_MIRROR = 20;
15991
15992
15993
15994
15995 public function download(PackageInterface $package, $path, $output = true)
15996 {
15997 $url = $package->getDistUrl();
15998 $realUrl = realpath($url);
15999 if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
16000 throw new \RuntimeException(sprintf(
16001 'Source path "%s" is not found for package %s', $url, $package->getName()
16002 ));
16003 }
16004
16005 if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
16006
16007  
16008  
16009  
16010  throw new \RuntimeException(sprintf(
16011 'Package %s cannot install to "%s" inside its source at "%s"',
16012 $package->getName(), realpath($path), $realUrl
16013 ));
16014 }
16015
16016
16017  $transportOptions = $package->getTransportOptions() + array('symlink' => null);
16018
16019
16020  $currentStrategy = self::STRATEGY_SYMLINK;
16021 $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
16022
16023 $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
16024 if ($mirrorPathRepos) {
16025 $currentStrategy = self::STRATEGY_MIRROR;
16026 }
16027
16028 if (true === $transportOptions['symlink']) {
16029 $currentStrategy = self::STRATEGY_SYMLINK;
16030 $allowedStrategies = array(self::STRATEGY_SYMLINK);
16031 } elseif (false === $transportOptions['symlink']) {
16032 $currentStrategy = self::STRATEGY_MIRROR;
16033 $allowedStrategies = array(self::STRATEGY_MIRROR);
16034 }
16035
16036 $fileSystem = new Filesystem();
16037 $this->filesystem->removeDirectory($path);
16038
16039 if ($output) {
16040 $this->io->writeError(sprintf(
16041 '  - Installing <info>%s</info> (<comment>%s</comment>): ',
16042 $package->getName(),
16043 $package->getFullPrettyVersion()
16044 ), false);
16045 }
16046
16047 $isFallback = false;
16048 if (self::STRATEGY_SYMLINK == $currentStrategy) {
16049 try {
16050 if (Platform::isWindows()) {
16051
16052  $this->io->writeError(sprintf('Junctioning from %s', $url), false);
16053 $this->filesystem->junction($realUrl, $path);
16054 } else {
16055 $absolutePath = $path;
16056 if (!$this->filesystem->isAbsolutePath($absolutePath)) {
16057 $absolutePath = getcwd() . DIRECTORY_SEPARATOR . $path;
16058 }
16059 $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
16060 $path = rtrim($path, "/");
16061 $this->io->writeError(sprintf('Symlinking from %s', $url), false);
16062 $fileSystem->symlink($shortestPath, $path);
16063 }
16064 } catch (IOException $e) {
16065 if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
16066 $this->io->writeError('');
16067 $this->io->writeError('    <error>Symlink failed, fallback to use mirroring!</error>');
16068 $currentStrategy = self::STRATEGY_MIRROR;
16069 $isFallback = true;
16070 } else {
16071 throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
16072 }
16073 }
16074 }
16075
16076
16077  if (self::STRATEGY_MIRROR == $currentStrategy) {
16078 $fs = new ComposerFilesystem();
16079 $realUrl = $fs->normalizePath($realUrl);
16080
16081 $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? '    ' : '', $url), false);
16082 $iterator = new ArchivableFilesFinder($realUrl, array());
16083 $fileSystem->mirror($realUrl, $path, $iterator);
16084 }
16085
16086 $this->io->writeError('');
16087 }
16088
16089
16090
16091
16092 public function remove(PackageInterface $package, $path, $output = true)
16093 {
16094
16095
16096
16097
16098
16099 if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
16100 if ($output) {
16101 $this->io->writeError("  - Removing junction for <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
16102 }
16103 if (!$this->filesystem->removeJunction($path)) {
16104 $this->io->writeError("    <warn>Could not remove junction at " . $path . " - is another process locking it?</warn>");
16105 throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
16106 }
16107 } else {
16108 parent::remove($package, $path, $output);
16109 }
16110 }
16111
16112
16113
16114
16115 public function getVcsReference(PackageInterface $package, $path)
16116 {
16117 $parser = new VersionParser;
16118 $guesser = new VersionGuesser($this->config, new ProcessExecutor($this->io), $parser);
16119 $dumper = new ArrayDumper;
16120
16121 $packageConfig = $dumper->dump($package);
16122 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
16123 return $packageVersion['commit'];
16124 }
16125 }
16126 }
16127 <?php
16128
16129
16130
16131
16132
16133
16134
16135
16136
16137
16138
16139 namespace Composer\Downloader;
16140
16141 use Composer\Util\Filesystem;
16142
16143
16144
16145
16146
16147
16148
16149
16150
16151
16152 class PearPackageExtractor
16153 {
16154 private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
16155
16156 private $filesystem;
16157 private $file;
16158
16159 public function __construct($file)
16160 {
16161 if (!is_file($file)) {
16162 throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
16163 }
16164
16165 $this->filesystem = new Filesystem();
16166 $this->file = $file;
16167 }
16168
16169
16170
16171
16172
16173
16174
16175
16176
16177
16178 public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
16179 {
16180 $extractionPath = $target.'/tarball';
16181
16182 try {
16183 $archive = new \PharData($this->file);
16184 $archive->extractTo($extractionPath, null, true);
16185
16186 if (!is_file($this->combine($extractionPath, '/package.xml'))) {
16187 throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
16188 }
16189
16190 $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
16191 $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
16192 $this->filesystem->removeDirectory($extractionPath);
16193 } catch (\Exception $exception) {
16194 throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
16195 }
16196 }
16197
16198
16199
16200
16201
16202
16203
16204
16205
16206
16207 private function copyFiles($files, $source, $target, $roles, $vars)
16208 {
16209 foreach ($files as $file) {
16210 $from = $this->combine($source, $file['from']);
16211 $to = $this->combine($target, $roles[$file['role']]);
16212 $to = $this->combine($to, $file['to']);
16213 $tasks = $file['tasks'];
16214 $this->copyFile($from, $to, $tasks, $vars);
16215 }
16216 }
16217
16218 private function copyFile($from, $to, $tasks, $vars)
16219 {
16220 if (!is_file($from)) {
16221 throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
16222 }
16223
16224 $this->filesystem->ensureDirectoryExists(dirname($to));
16225
16226 if (0 == count($tasks)) {
16227 $copied = copy($from, $to);
16228 } else {
16229 $content = file_get_contents($from);
16230 $replacements = array();
16231 foreach ($tasks as $task) {
16232 $pattern = $task['from'];
16233 $varName = $task['to'];
16234 if (isset($vars[$varName])) {
16235 if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
16236 $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
16237 } else {
16238 $replacements[$pattern] = $vars[$varName];
16239 }
16240 }
16241 }
16242 $content = strtr($content, $replacements);
16243
16244 $copied = file_put_contents($to, $content);
16245 }
16246
16247 if (false === $copied) {
16248 throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
16249 }
16250 }
16251
16252
16253
16254
16255
16256
16257
16258
16259
16260
16261
16262 private function buildCopyActions($source, array $roles, $vars)
16263 {
16264
16265 $package = simplexml_load_string(file_get_contents($this->combine($source, 'package.xml')));
16266 if (false === $package) {
16267 throw new \RuntimeException('Package definition file is not valid.');
16268 }
16269
16270 $packageSchemaVersion = $package['version'];
16271 if ('1.0' == $packageSchemaVersion) {
16272 $children = $package->release->filelist->children();
16273 $packageName = (string) $package->name;
16274 $packageVersion = (string) $package->release->version;
16275 $sourceDir = $packageName . '-' . $packageVersion;
16276 $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
16277 } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
16278 $children = $package->contents->children();
16279 $packageName = (string) $package->name;
16280 $packageVersion = (string) $package->version->release;
16281 $sourceDir = $packageName . '-' . $packageVersion;
16282 $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
16283
16284 $namespaces = $package->getNamespaces();
16285 $package->registerXPathNamespace('ns', $namespaces['']);
16286 $releaseNodes = $package->xpath('ns:phprelease');
16287 $this->applyRelease($result, $releaseNodes, $vars);
16288 } else {
16289 throw new \RuntimeException('Unsupported schema version of package definition file.');
16290 }
16291
16292 return $result;
16293 }
16294
16295 private function applyRelease(&$actions, $releaseNodes, $vars)
16296 {
16297 foreach ($releaseNodes as $releaseNode) {
16298 $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
16299 if ($requiredOs && $vars['os'] != $requiredOs) {
16300 continue;
16301 }
16302
16303 if ($releaseNode->filelist) {
16304 foreach ($releaseNode->filelist->children() as $action) {
16305 if ('install' == $action->getName()) {
16306 $name = (string) $action['name'];
16307 $as = (string) $action['as'];
16308 if (isset($actions[$name])) {
16309 $actions[$name]['to'] = $as;
16310 }
16311 } elseif ('ignore' == $action->getName()) {
16312 $name = (string) $action['name'];
16313 unset($actions[$name]);
16314 } else {
16315
16316  }
16317 }
16318 }
16319 break;
16320 }
16321 }
16322
16323 private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
16324 {
16325 $result = array();
16326
16327
16328  foreach ($children as $child) {
16329
16330 if ($child->getName() == 'dir') {
16331 $dirSource = $this->combine($source, (string) $child['name']);
16332 $dirTarget = $child['baseinstalldir'] ?: $target;
16333 $dirRole = $child['role'] ?: $role;
16334 $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16335 $result = array_merge($result, $dirFiles);
16336 } elseif ($child->getName() == 'file') {
16337 $fileRole = (string) $child['role'] ?: $role;
16338 if (isset($targetRoles[$fileRole])) {
16339 $fileName = (string) ($child['name'] ?: $child[0]); 
16340  $fileSource = $this->combine($source, $fileName);
16341 $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
16342 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16343 $fileTarget = $packageName . '/' . $fileTarget;
16344 }
16345 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
16346 }
16347 }
16348 }
16349
16350 return $result;
16351 }
16352
16353 private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
16354 {
16355 $result = array();
16356
16357
16358  foreach ($children as $child) {
16359
16360 if ('dir' == $child->getName()) {
16361 $dirSource = $this->combine($source, $child['name']);
16362 $dirTarget = $child['baseinstalldir'] ?: $target;
16363 $dirRole = $child['role'] ?: $role;
16364 $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16365 $result = array_merge($result, $dirFiles);
16366 } elseif ('file' == $child->getName()) {
16367 $fileRole = (string) $child['role'] ?: $role;
16368 if (isset($targetRoles[$fileRole])) {
16369 $fileSource = $this->combine($source, (string) $child['name']);
16370 $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
16371 $fileTasks = array();
16372 foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
16373 if ('replace' == $taskNode->getName()) {
16374 $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
16375 }
16376 }
16377 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16378 $fileTarget = $packageName . '/' . $fileTarget;
16379 }
16380 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
16381 }
16382 }
16383 }
16384
16385 return $result;
16386 }
16387
16388 private function combine($left, $right)
16389 {
16390 return rtrim($left, '/') . '/' . ltrim($right, '/');
16391 }
16392 }
16393 <?php
16394
16395
16396
16397
16398
16399
16400
16401
16402
16403
16404
16405 namespace Composer\Downloader;
16406
16407 use Composer\Package\PackageInterface;
16408 use Composer\Repository\VcsRepository;
16409 use Composer\Util\Perforce;
16410
16411
16412
16413
16414 class PerforceDownloader extends VcsDownloader
16415 {
16416
16417 protected $perforce;
16418
16419
16420
16421
16422 public function doDownload(PackageInterface $package, $path, $url)
16423 {
16424 $ref = $package->getSourceReference();
16425 $label = $this->getLabelFromSourceReference($ref);
16426
16427 $this->io->writeError('Cloning ' . $ref);
16428 $this->initPerforce($package, $path, $url);
16429 $this->perforce->setStream($ref);
16430 $this->perforce->p4Login();
16431 $this->perforce->writeP4ClientSpec();
16432 $this->perforce->connectClient();
16433 $this->perforce->syncCodeBase($label);
16434 $this->perforce->cleanupClientSpec();
16435 }
16436
16437 private function getLabelFromSourceReference($ref)
16438 {
16439 $pos = strpos($ref, '@');
16440 if (false !== $pos) {
16441 return substr($ref, $pos + 1);
16442 }
16443
16444 return null;
16445 }
16446
16447 public function initPerforce(PackageInterface $package, $path, $url)
16448 {
16449 if (!empty($this->perforce)) {
16450 $this->perforce->initializePath($path);
16451
16452 return;
16453 }
16454
16455 $repository = $package->getRepository();
16456 $repoConfig = null;
16457 if ($repository instanceof VcsRepository) {
16458 $repoConfig = $this->getRepoConfig($repository);
16459 }
16460 $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
16461 }
16462
16463 private function getRepoConfig(VcsRepository $repository)
16464 {
16465 return $repository->getRepoConfig();
16466 }
16467
16468
16469
16470
16471 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16472 {
16473 $this->doDownload($target, $path, $url);
16474 }
16475
16476
16477
16478
16479 public function getLocalChanges(PackageInterface $package, $path)
16480 {
16481 $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
16482
16483 return;
16484 }
16485
16486
16487
16488
16489 protected function getCommitLogs($fromReference, $toReference, $path)
16490 {
16491 return $this->perforce->getCommitLogs($fromReference, $toReference);
16492 }
16493
16494 public function setPerforce($perforce)
16495 {
16496 $this->perforce = $perforce;
16497 }
16498
16499
16500
16501
16502 protected function hasMetadataRepository($path)
16503 {
16504 return true;
16505 }
16506 }
16507 <?php
16508
16509
16510
16511
16512
16513
16514
16515
16516
16517
16518
16519 namespace Composer\Downloader;
16520
16521
16522
16523
16524
16525
16526 class PharDownloader extends ArchiveDownloader
16527 {
16528
16529
16530
16531 protected function extract($file, $path)
16532 {
16533
16534  $archive = new \Phar($file);
16535 $archive->extractTo($path, null, true);
16536
16537
16538
16539
16540
16541 }
16542 }
16543 <?php
16544
16545
16546
16547
16548
16549
16550
16551
16552
16553
16554
16555 namespace Composer\Downloader;
16556
16557 use Composer\Config;
16558 use Composer\Cache;
16559 use Composer\EventDispatcher\EventDispatcher;
16560 use Composer\Util\IniHelper;
16561 use Composer\Util\Platform;
16562 use Composer\Util\ProcessExecutor;
16563 use Composer\Util\RemoteFilesystem;
16564 use Composer\IO\IOInterface;
16565 use RarArchive;
16566
16567
16568
16569
16570
16571
16572
16573
16574 class RarDownloader extends ArchiveDownloader
16575 {
16576 protected $process;
16577
16578 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
16579 {
16580 $this->process = $process ?: new ProcessExecutor($io);
16581 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
16582 }
16583
16584 protected function extract($file, $path)
16585 {
16586 $processError = null;
16587
16588
16589  if (!Platform::isWindows()) {
16590 $command = 'unrar x ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
16591
16592 if (0 === $this->process->execute($command, $ignoredOutput)) {
16593 return;
16594 }
16595
16596 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
16597 }
16598
16599 if (!class_exists('RarArchive')) {
16600
16601  $iniMessage = IniHelper::getMessage();
16602
16603 $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n"
16604 . $iniMessage . "\n" . $processError;
16605
16606 if (!Platform::isWindows()) {
16607 $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
16608 }
16609
16610 throw new \RuntimeException($error);
16611 }
16612
16613 $rarArchive = RarArchive::open($file);
16614
16615 if (false === $rarArchive) {
16616 throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
16617 }
16618
16619 $entries = $rarArchive->getEntries();
16620
16621 if (false === $entries) {
16622 throw new \RuntimeException('Could not retrieve RAR archive entries');
16623 }
16624
16625 foreach ($entries as $entry) {
16626 if (false === $entry->extract($path)) {
16627 throw new \RuntimeException('Could not extract entry');
16628 }
16629 }
16630
16631 $rarArchive->close();
16632 }
16633 }
16634 <?php
16635
16636
16637
16638
16639
16640
16641
16642
16643
16644
16645
16646 namespace Composer\Downloader;
16647
16648 use Composer\Package\PackageInterface;
16649 use Composer\Util\Svn as SvnUtil;
16650 use Composer\Repository\VcsRepository;
16651
16652
16653
16654
16655
16656 class SvnDownloader extends VcsDownloader
16657 {
16658 protected $cacheCredentials = true;
16659
16660
16661
16662
16663 public function doDownload(PackageInterface $package, $path, $url)
16664 {
16665 SvnUtil::cleanEnv();
16666 $ref = $package->getSourceReference();
16667
16668 $repo = $package->getRepository();
16669 if ($repo instanceof VcsRepository) {
16670 $repoConfig = $repo->getRepoConfig();
16671 if (array_key_exists('svn-cache-credentials', $repoConfig)) {
16672 $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials'];
16673 }
16674 }
16675
16676 $this->io->writeError(" Checking out ".$package->getSourceReference());
16677 $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
16678 }
16679
16680
16681
16682
16683 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16684 {
16685 SvnUtil::cleanEnv();
16686 $ref = $target->getSourceReference();
16687
16688 if (!$this->hasMetadataRepository($path)) {
16689 throw new \RuntimeException('The .svn directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16690 }
16691
16692 $flags = "";
16693 if (0 === $this->process->execute('svn --version', $output)) {
16694 if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match) && version_compare($match[1], '1.7.0', '>=')) {
16695 $flags .= ' --ignore-ancestry';
16696 }
16697 }
16698
16699 $this->io->writeError(" Checking out " . $ref);
16700 $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
16701 }
16702
16703
16704
16705
16706 public function getLocalChanges(PackageInterface $package, $path)
16707 {
16708 if (!$this->hasMetadataRepository($path)) {
16709 return null;
16710 }
16711
16712 $this->process->execute('svn status --ignore-externals', $output, $path);
16713
16714 return preg_match('{^ *[^X ] +}m', $output) ? $output : null;
16715 }
16716
16717
16718
16719
16720
16721
16722
16723
16724
16725
16726
16727
16728
16729 protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
16730 {
16731 $util = new SvnUtil($baseUrl, $this->io, $this->config);
16732 $util->setCacheCredentials($this->cacheCredentials);
16733 try {
16734 return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
16735 } catch (\RuntimeException $e) {
16736 throw new \RuntimeException(
16737 'Package could not be downloaded, '.$e->getMessage()
16738 );
16739 }
16740 }
16741
16742
16743
16744
16745 protected function cleanChanges(PackageInterface $package, $path, $update)
16746 {
16747 if (!$changes = $this->getLocalChanges($package, $path)) {
16748 return;
16749 }
16750
16751 if (!$this->io->isInteractive()) {
16752 if (true === $this->config->get('discard-changes')) {
16753 return $this->discardChanges($path);
16754 }
16755
16756 return parent::cleanChanges($package, $path, $update);
16757 }
16758
16759 $changes = array_map(function ($elem) {
16760 return '    '.$elem;
16761 }, preg_split('{\s*\r?\n\s*}', $changes));
16762 $countChanges = count($changes);
16763 $this->io->writeError(sprintf('    <error>The package has modified file%s:</error>', $countChanges === 1 ? '' : 's'));
16764 $this->io->writeError(array_slice($changes, 0, 10));
16765 if ($countChanges > 10) {
16766 $remaingChanges = $countChanges - 10;
16767 $this->io->writeError(
16768 sprintf(
16769 '    <info>'.$remaingChanges.' more file%s modified, choose "v" to view the full list</info>',
16770 $remaingChanges === 1 ? '' : 's'
16771 )
16772 );
16773 }
16774
16775 while (true) {
16776 switch ($this->io->ask('    <info>Discard changes [y,n,v,?]?</info> ', '?')) {
16777 case 'y':
16778 $this->discardChanges($path);
16779 break 2;
16780
16781 case 'n':
16782 throw new \RuntimeException('Update aborted');
16783
16784 case 'v':
16785 $this->io->writeError($changes);
16786 break;
16787
16788 case '?':
16789 default:
16790 $this->io->writeError(array(
16791 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
16792 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
16793 '    v - view modified files',
16794 '    ? - print help',
16795 ));
16796 break;
16797 }
16798 }
16799 }
16800
16801
16802
16803
16804 protected function getCommitLogs($fromReference, $toReference, $path)
16805 {
16806 if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
16807
16808  $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
16809 $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
16810
16811 $command = sprintf('svn log -r%s:%s --incremental', $fromRevision, $toRevision);
16812
16813 if (0 !== $this->process->execute($command, $output, $path)) {
16814 throw new \RuntimeException(
16815 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
16816 );
16817 }
16818 } else {
16819 $output = "Could not retrieve changes between $fromReference and $toReference due to missing revision information";
16820 }
16821
16822 return $output;
16823 }
16824
16825 protected function discardChanges($path)
16826 {
16827 if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
16828 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
16829 }
16830 }
16831
16832
16833
16834
16835 protected function hasMetadataRepository($path)
16836 {
16837 return is_dir($path.'/.svn');
16838 }
16839 }
16840 <?php
16841
16842
16843
16844
16845
16846
16847
16848
16849
16850
16851
16852 namespace Composer\Downloader;
16853
16854
16855
16856
16857
16858
16859 class TarDownloader extends ArchiveDownloader
16860 {
16861
16862
16863
16864 protected function extract($file, $path)
16865 {
16866
16867  $archive = new \PharData($file);
16868 $archive->extractTo($path, null, true);
16869 }
16870 }
16871 <?php
16872
16873
16874
16875
16876
16877
16878
16879
16880
16881
16882
16883 namespace Composer\Downloader;
16884
16885
16886
16887
16888 class TransportException extends \RuntimeException
16889 {
16890 protected $headers;
16891 protected $response;
16892 protected $statusCode;
16893
16894 public function setHeaders($headers)
16895 {
16896 $this->headers = $headers;
16897 }
16898
16899 public function getHeaders()
16900 {
16901 return $this->headers;
16902 }
16903
16904 public function setResponse($response)
16905 {
16906 $this->response = $response;
16907 }
16908
16909 public function getResponse()
16910 {
16911 return $this->response;
16912 }
16913
16914 public function setStatusCode($statusCode)
16915 {
16916 $this->statusCode = $statusCode;
16917 }
16918
16919 public function getStatusCode()
16920 {
16921 return $this->statusCode;
16922 }
16923 }
16924 <?php
16925
16926
16927
16928
16929
16930
16931
16932
16933
16934
16935
16936 namespace Composer\Downloader;
16937
16938 use Composer\Package\PackageInterface;
16939
16940
16941
16942
16943
16944
16945 interface VcsCapableDownloaderInterface
16946 {
16947
16948
16949
16950
16951
16952
16953
16954 public function getVcsReference(PackageInterface $package, $path);
16955 }
16956 <?php
16957
16958
16959
16960
16961
16962
16963
16964
16965
16966
16967
16968 namespace Composer\Downloader;
16969
16970 use Composer\Config;
16971 use Composer\Package\Dumper\ArrayDumper;
16972 use Composer\Package\PackageInterface;
16973 use Composer\Package\Version\VersionGuesser;
16974 use Composer\Package\Version\VersionParser;
16975 use Composer\Util\ProcessExecutor;
16976 use Composer\IO\IOInterface;
16977 use Composer\Util\Filesystem;
16978
16979
16980
16981
16982 abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterface, VcsCapableDownloaderInterface
16983 {
16984
16985 protected $io;
16986
16987 protected $config;
16988
16989 protected $process;
16990
16991 protected $filesystem;
16992
16993 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
16994 {
16995 $this->io = $io;
16996 $this->config = $config;
16997 $this->process = $process ?: new ProcessExecutor($io);
16998 $this->filesystem = $fs ?: new Filesystem($this->process);
16999 }
17000
17001
17002
17003
17004 public function getInstallationSource()
17005 {
17006 return 'source';
17007 }
17008
17009
17010
17011
17012 public function download(PackageInterface $package, $path)
17013 {
17014 if (!$package->getSourceReference()) {
17015 throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
17016 }
17017
17018 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
17019 $this->filesystem->emptyDirectory($path);
17020
17021 $urls = $package->getSourceUrls();
17022 while ($url = array_shift($urls)) {
17023 try {
17024 if (Filesystem::isLocalPath($url)) {
17025
17026  
17027  $needle = 'file://';
17028 $isFileProtocol = false;
17029 if (0 === strpos($url, $needle)) {
17030 $url = substr($url, strlen($needle));
17031 $isFileProtocol = true;
17032 }
17033
17034
17035  if (false !== strpos($url, '%')) {
17036 $url = rawurldecode($url);
17037 }
17038
17039 $url = realpath($url);
17040
17041 if ($isFileProtocol) {
17042 $url = $needle . $url;
17043 }
17044 }
17045 $this->doDownload($package, $path, $url);
17046 break;
17047 } catch (\Exception $e) {
17048
17049  if ($e instanceof \PHPUnit_Framework_Exception) {
17050 throw $e;
17051 }
17052 if ($this->io->isDebug()) {
17053 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
17054 } elseif (count($urls)) {
17055 $this->io->writeError('    Failed, trying the next URL');
17056 }
17057 if (!count($urls)) {
17058 throw $e;
17059 }
17060 }
17061 }
17062 }
17063
17064
17065
17066
17067 public function update(PackageInterface $initial, PackageInterface $target, $path)
17068 {
17069 if (!$target->getSourceReference()) {
17070 throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
17071 }
17072
17073 $name = $target->getName();
17074 if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
17075 if ($target->getSourceType() === 'svn') {
17076 $from = $initial->getSourceReference();
17077 $to = $target->getSourceReference();
17078 } else {
17079 $from = substr($initial->getSourceReference(), 0, 7);
17080 $to = substr($target->getSourceReference(), 0, 7);
17081 }
17082 $name .= ' '.$initial->getPrettyVersion();
17083 } else {
17084 $from = $initial->getFullPrettyVersion();
17085 $to = $target->getFullPrettyVersion();
17086 }
17087
17088 $this->io->writeError("  - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
17089
17090 $this->cleanChanges($initial, $path, true);
17091 $urls = $target->getSourceUrls();
17092
17093 $exception = null;
17094 while ($url = array_shift($urls)) {
17095 try {
17096 if (Filesystem::isLocalPath($url)) {
17097 $url = realpath($url);
17098 }
17099 $this->doUpdate($initial, $target, $path, $url);
17100
17101 $exception = null;
17102 break;
17103 } catch (\Exception $exception) {
17104
17105  if ($exception instanceof \PHPUnit_Framework_Exception) {
17106 throw $exception;
17107 }
17108 if ($this->io->isDebug()) {
17109 $this->io->writeError('Failed: ['.get_class($exception).'] '.$exception->getMessage());
17110 } elseif (count($urls)) {
17111 $this->io->writeError('    Failed, trying the next URL');
17112 }
17113 }
17114 }
17115
17116 $this->reapplyChanges($path);
17117
17118
17119  
17120  if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
17121 $message = 'Pulling in changes:';
17122 $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
17123
17124 if (!trim($logs)) {
17125 $message = 'Rolling back changes:';
17126 $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
17127 }
17128
17129 if (trim($logs)) {
17130 $logs = implode("\n", array_map(function ($line) {
17131 return '      ' . $line;
17132 }, explode("\n", $logs)));
17133
17134
17135  $logs = str_replace('<', '\<', $logs);
17136
17137 $this->io->writeError('    '.$message);
17138 $this->io->writeError($logs);
17139 }
17140 }
17141
17142 if (!$urls && $exception) {
17143 throw $exception;
17144 }
17145 }
17146
17147
17148
17149
17150 public function remove(PackageInterface $package, $path)
17151 {
17152 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
17153 $this->cleanChanges($package, $path, false);
17154 if (!$this->filesystem->removeDirectory($path)) {
17155 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
17156 }
17157 }
17158
17159
17160
17161
17162
17163 public function setOutputProgress($outputProgress)
17164 {
17165 return $this;
17166 }
17167
17168
17169
17170
17171 public function getVcsReference(PackageInterface $package, $path)
17172 {
17173 $parser = new VersionParser;
17174 $guesser = new VersionGuesser($this->config, $this->process, $parser);
17175 $dumper = new ArrayDumper;
17176
17177 $packageConfig = $dumper->dump($package);
17178 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
17179 return $packageVersion['commit'];
17180 }
17181 }
17182
17183
17184
17185
17186
17187
17188
17189
17190
17191
17192 protected function cleanChanges(PackageInterface $package, $path, $update)
17193 {
17194
17195  if (null !== $this->getLocalChanges($package, $path)) {
17196 throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
17197 }
17198 }
17199
17200
17201
17202
17203
17204
17205
17206 protected function reapplyChanges($path)
17207 {
17208 }
17209
17210
17211
17212
17213
17214
17215
17216
17217 abstract protected function doDownload(PackageInterface $package, $path, $url);
17218
17219
17220
17221
17222
17223
17224
17225
17226
17227 abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
17228
17229
17230
17231
17232
17233
17234
17235
17236
17237 abstract protected function getCommitLogs($fromReference, $toReference, $path);
17238
17239
17240
17241
17242
17243
17244
17245
17246 abstract protected function hasMetadataRepository($path);
17247 }
17248 <?php
17249
17250
17251
17252
17253
17254
17255
17256
17257
17258
17259
17260 namespace Composer\Downloader;
17261
17262 use Composer\Config;
17263 use Composer\Cache;
17264 use Composer\EventDispatcher\EventDispatcher;
17265 use Composer\Package\PackageInterface;
17266 use Composer\Util\ProcessExecutor;
17267 use Composer\Util\RemoteFilesystem;
17268 use Composer\IO\IOInterface;
17269
17270
17271
17272
17273
17274
17275
17276 class XzDownloader extends ArchiveDownloader
17277 {
17278 protected $process;
17279
17280 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17281 {
17282 $this->process = $process ?: new ProcessExecutor($io);
17283
17284 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17285 }
17286
17287 protected function extract($file, $path)
17288 {
17289 $command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
17290
17291 if (0 === $this->process->execute($command, $ignoredOutput)) {
17292 return;
17293 }
17294
17295 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
17296
17297 throw new \RuntimeException($processError);
17298 }
17299
17300
17301
17302
17303 protected function getFileName(PackageInterface $package, $path)
17304 {
17305 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
17306 }
17307 }
17308 <?php
17309
17310
17311
17312
17313
17314
17315
17316
17317
17318
17319
17320 namespace Composer\Downloader;
17321
17322 use Composer\Config;
17323 use Composer\Cache;
17324 use Composer\EventDispatcher\EventDispatcher;
17325 use Composer\Package\PackageInterface;
17326 use Composer\Util\IniHelper;
17327 use Composer\Util\Platform;
17328 use Composer\Util\ProcessExecutor;
17329 use Composer\Util\RemoteFilesystem;
17330 use Composer\IO\IOInterface;
17331 use Symfony\Component\Process\ExecutableFinder;
17332 use ZipArchive;
17333
17334
17335
17336
17337 class ZipDownloader extends ArchiveDownloader
17338 {
17339 protected static $hasSystemUnzip;
17340 private static $hasZipArchive;
17341 private static $isWindows;
17342
17343 protected $process;
17344 private $zipArchiveObject;
17345
17346 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17347 {
17348 $this->process = $process ?: new ProcessExecutor($io);
17349 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17350 }
17351
17352
17353
17354
17355 public function download(PackageInterface $package, $path, $output = true)
17356 {
17357 if (null === self::$hasSystemUnzip) {
17358 $finder = new ExecutableFinder;
17359 self::$hasSystemUnzip = (bool) $finder->find('unzip');
17360 }
17361
17362 if (null === self::$hasZipArchive) {
17363 self::$hasZipArchive = class_exists('ZipArchive');
17364 }
17365
17366 if (null === self::$isWindows) {
17367 self::$isWindows = Platform::isWindows();
17368 }
17369
17370 if (!self::$hasZipArchive && !self::$hasSystemUnzip) {
17371
17372  $iniMessage = IniHelper::getMessage();
17373 $error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
17374
17375 throw new \RuntimeException($error);
17376 }
17377
17378 return parent::download($package, $path, $output);
17379 }
17380
17381
17382
17383
17384
17385
17386
17387
17388
17389 protected function extractWithSystemUnzip($file, $path, $isLastChance)
17390 {
17391 if (!self::$hasZipArchive) {
17392
17393  $isLastChance = true;
17394 }
17395
17396 if (!self::$hasSystemUnzip && !$isLastChance) {
17397
17398  
17399  return $this->extractWithZipArchive($file, $path, true);
17400 }
17401
17402 $processError = null;
17403
17404  $overwrite = $isLastChance ? '-o' : '';
17405
17406 $command = 'unzip -qq '.$overwrite.' '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
17407
17408 try {
17409 if (0 === $this->process->execute($command, $ignoredOutput)) {
17410 return true;
17411 }
17412
17413 $processError = new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17414 } catch (\Exception $e) {
17415 $processError = $e;
17416 }
17417
17418 if ($isLastChance) {
17419 throw $processError;
17420 }
17421
17422 $this->io->writeError('    '.$processError->getMessage());
17423 $this->io->writeError('    The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
17424 $this->io->writeError('    Unzip with unzip command failed, falling back to ZipArchive class');
17425
17426 return $this->extractWithZipArchive($file, $path, true);
17427 }
17428
17429
17430
17431
17432
17433
17434
17435
17436
17437 protected function extractWithZipArchive($file, $path, $isLastChance)
17438 {
17439 if (!self::$hasSystemUnzip) {
17440
17441  $isLastChance = true;
17442 }
17443
17444 if (!self::$hasZipArchive && !$isLastChance) {
17445
17446  
17447  return $this->extractWithSystemUnzip($file, $path, true);
17448 }
17449
17450 $processError = null;
17451 $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
17452
17453 try {
17454 if (true === ($retval = $zipArchive->open($file))) {
17455 $extractResult = $zipArchive->extractTo($path);
17456
17457 if (true === $extractResult) {
17458 $zipArchive->close();
17459
17460 return true;
17461 }
17462
17463 $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
17464 } else {
17465 $processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file)."\n"), $retval);
17466 }
17467 } catch (\ErrorException $e) {
17468 $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
17469 } catch (\Exception $e) {
17470 $processError = $e;
17471 }
17472
17473 if ($isLastChance) {
17474 throw $processError;
17475 }
17476
17477 $this->io->writeError('    '.$processError->getMessage());
17478 $this->io->writeError('    Unzip with ZipArchive class failed, falling back to unzip command');
17479
17480 return $this->extractWithSystemUnzip($file, $path, true);
17481 }
17482
17483
17484
17485
17486
17487
17488
17489 public function extract($file, $path)
17490 {
17491
17492  if (self::$isWindows) {
17493 $this->extractWithZipArchive($file, $path, false);
17494 } else {
17495 $this->extractWithSystemUnzip($file, $path, false);
17496 }
17497 }
17498
17499
17500
17501
17502
17503
17504
17505
17506 protected function getErrorMessage($retval, $file)
17507 {
17508 switch ($retval) {
17509 case ZipArchive::ER_EXISTS:
17510 return sprintf("File '%s' already exists.", $file);
17511 case ZipArchive::ER_INCONS:
17512 return sprintf("Zip archive '%s' is inconsistent.", $file);
17513 case ZipArchive::ER_INVAL:
17514 return sprintf("Invalid argument (%s)", $file);
17515 case ZipArchive::ER_MEMORY:
17516 return sprintf("Malloc failure (%s)", $file);
17517 case ZipArchive::ER_NOENT:
17518 return sprintf("No such zip file: '%s'", $file);
17519 case ZipArchive::ER_NOZIP:
17520 return sprintf("'%s' is not a zip archive.", $file);
17521 case ZipArchive::ER_OPEN:
17522 return sprintf("Can't open zip file: %s", $file);
17523 case ZipArchive::ER_READ:
17524 return sprintf("Zip read error (%s)", $file);
17525 case ZipArchive::ER_SEEK:
17526 return sprintf("Zip seek error (%s)", $file);
17527 default:
17528 return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
17529 }
17530 }
17531 }
17532 <?php
17533
17534
17535
17536
17537
17538
17539
17540
17541
17542
17543
17544 namespace Composer\EventDispatcher;
17545
17546
17547
17548
17549
17550
17551 class Event
17552 {
17553
17554
17555
17556 protected $name;
17557
17558
17559
17560
17561 protected $args;
17562
17563
17564
17565
17566 protected $flags;
17567
17568
17569
17570
17571 private $propagationStopped = false;
17572
17573
17574
17575
17576
17577
17578
17579
17580 public function __construct($name, array $args = array(), array $flags = array())
17581 {
17582 $this->name = $name;
17583 $this->args = $args;
17584 $this->flags = $flags;
17585 }
17586
17587
17588
17589
17590
17591
17592 public function getName()
17593 {
17594 return $this->name;
17595 }
17596
17597
17598
17599
17600
17601
17602 public function getArguments()
17603 {
17604 return $this->args;
17605 }
17606
17607
17608
17609
17610
17611
17612 public function getFlags()
17613 {
17614 return $this->flags;
17615 }
17616
17617
17618
17619
17620
17621
17622 public function isPropagationStopped()
17623 {
17624 return $this->propagationStopped;
17625 }
17626
17627
17628
17629
17630 public function stopPropagation()
17631 {
17632 $this->propagationStopped = true;
17633 }
17634 }
17635 <?php
17636
17637
17638
17639
17640
17641
17642
17643
17644
17645
17646
17647 namespace Composer\EventDispatcher;
17648
17649 use Composer\DependencyResolver\PolicyInterface;
17650 use Composer\DependencyResolver\Pool;
17651 use Composer\DependencyResolver\Request;
17652 use Composer\Installer\InstallerEvent;
17653 use Composer\IO\IOInterface;
17654 use Composer\Composer;
17655 use Composer\DependencyResolver\Operation\OperationInterface;
17656 use Composer\Repository\CompositeRepository;
17657 use Composer\Script;
17658 use Composer\Installer\PackageEvent;
17659 use Composer\Installer\BinaryInstaller;
17660 use Composer\Util\ProcessExecutor;
17661 use Composer\Script\Event as ScriptEvent;
17662 use Symfony\Component\Process\PhpExecutableFinder;
17663
17664
17665
17666
17667
17668
17669
17670
17671
17672
17673
17674
17675
17676
17677 class EventDispatcher
17678 {
17679 protected $composer;
17680 protected $io;
17681 protected $loader;
17682 protected $process;
17683 protected $listeners;
17684 private $eventStack;
17685
17686
17687
17688
17689
17690
17691
17692
17693 public function __construct(Composer $composer, IOInterface $io, ProcessExecutor $process = null)
17694 {
17695 $this->composer = $composer;
17696 $this->io = $io;
17697 $this->process = $process ?: new ProcessExecutor($io);
17698 $this->eventStack = array();
17699 }
17700
17701
17702
17703
17704
17705
17706
17707
17708
17709 public function dispatch($eventName, Event $event = null)
17710 {
17711 if (null === $event) {
17712 $event = new Event($eventName);
17713 }
17714
17715 return $this->doDispatch($event);
17716 }
17717
17718
17719
17720
17721
17722
17723
17724
17725
17726
17727
17728 public function dispatchScript($eventName, $devMode = false, $additionalArgs = array(), $flags = array())
17729 {
17730 return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
17731 }
17732
17733
17734
17735
17736
17737
17738
17739
17740
17741
17742
17743
17744
17745
17746
17747
17748 public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
17749 {
17750 return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
17751 }
17752
17753
17754
17755
17756
17757
17758
17759
17760
17761
17762
17763
17764
17765
17766
17767 public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
17768 {
17769 return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
17770 }
17771
17772
17773
17774
17775
17776
17777
17778
17779
17780 protected function doDispatch(Event $event)
17781 {
17782 $pathStr = 'PATH';
17783 if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
17784 $pathStr = 'Path';
17785 }
17786
17787
17788  $binDir = $this->composer->getConfig()->get('bin-dir');
17789 if (is_dir($binDir)) {
17790 $binDir = realpath($binDir);
17791 if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
17792 $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
17793 putenv($pathStr.'='.$_SERVER[$pathStr]);
17794 }
17795 }
17796
17797 $listeners = $this->getListeners($event);
17798
17799 $this->pushEvent($event);
17800
17801 $return = 0;
17802 foreach ($listeners as $callable) {
17803 if (!is_string($callable) && is_callable($callable)) {
17804 $event = $this->checkListenerExpectedEvent($callable, $event);
17805 $return = false === call_user_func($callable, $event) ? 1 : 0;
17806 } elseif ($this->isComposerScript($callable)) {
17807 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
17808 $scriptName = substr($callable, 1);
17809 $args = $event->getArguments();
17810 $flags = $event->getFlags();
17811 if (substr($callable, 0, 10) === '@composer ') {
17812 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
17813 if (0 !== ($exitCode = $this->process->execute($exec))) {
17814 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
17815
17816 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
17817 }
17818 } else {
17819 if (!$this->getListeners(new Event($scriptName))) {
17820 $this->io->writeError(sprintf('<warning>You made a reference to a non-existent script %s</warning>', $callable), true, IOInterface::QUIET);
17821 }
17822
17823 $return = $this->dispatch($scriptName, new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags));
17824 }
17825 } elseif ($this->isPhpScript($callable)) {
17826 $className = substr($callable, 0, strpos($callable, '::'));
17827 $methodName = substr($callable, strpos($callable, '::') + 2);
17828
17829 if (!class_exists($className)) {
17830 $this->io->writeError('<warning>Class '.$className.' is not autoloadable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
17831 continue;
17832 }
17833 if (!is_callable($callable)) {
17834 $this->io->writeError('<warning>Method '.$callable.' is not callable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
17835 continue;
17836 }
17837
17838 try {
17839 $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
17840 } catch (\Exception $e) {
17841 $message = "Script %s handling the %s event terminated with an exception";
17842 $this->io->writeError('<error>'.sprintf($message, $callable, $event->getName()).'</error>', true, IOInterface::QUIET);
17843 throw $e;
17844 }
17845 } else {
17846 $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
17847 $exec = $callable . ($args === '' ? '' : ' '.$args);
17848 if ($this->io->isVerbose()) {
17849 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
17850 } else {
17851 $this->io->writeError(sprintf('> %s', $exec));
17852 }
17853
17854 $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
17855 if ($possibleLocalBinaries) {
17856 foreach ($possibleLocalBinaries as $localExec) {
17857 if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
17858 $caller = BinaryInstaller::determineBinaryCaller($localExec);
17859 $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
17860 break;
17861 }
17862 }
17863 }
17864
17865 if (substr($exec, 0, 5) === '@php ') {
17866 $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
17867 }
17868
17869 if (0 !== ($exitCode = $this->process->execute($exec))) {
17870 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
17871
17872 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
17873 }
17874 }
17875
17876 if ($event->isPropagationStopped()) {
17877 break;
17878 }
17879 }
17880
17881 $this->popEvent();
17882
17883 return $return;
17884 }
17885
17886 protected function getPhpExecCommand()
17887 {
17888 $finder = new PhpExecutableFinder();
17889 $phpPath = $finder->find();
17890 if (!$phpPath) {
17891 throw new \RuntimeException('Failed to locate PHP binary to execute '.$scriptName);
17892 }
17893
17894 $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
17895 $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
17896 $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
17897
17898 return ProcessExecutor::escape($phpPath) . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag;
17899 }
17900
17901
17902
17903
17904
17905
17906 protected function executeEventPhpScript($className, $methodName, Event $event)
17907 {
17908 $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
17909
17910 if ($this->io->isVerbose()) {
17911 $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
17912 } else {
17913 $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
17914 }
17915
17916 return $className::$methodName($event);
17917 }
17918
17919
17920
17921
17922
17923
17924 protected function checkListenerExpectedEvent($target, Event $event)
17925 {
17926 if (in_array($event->getName(), array(
17927 'init',
17928 'command',
17929 'pre-file-download',
17930 ), true)) {
17931 return $event;
17932 }
17933
17934 try {
17935 $reflected = new \ReflectionParameter($target, 0);
17936 } catch (\Exception $e) {
17937 return $event;
17938 }
17939
17940 $typehint = $reflected->getClass();
17941
17942 if (!$typehint instanceof \ReflectionClass) {
17943 return $event;
17944 }
17945
17946 $expected = $typehint->getName();
17947
17948
17949  if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
17950 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);
17951 $event = new \Composer\Script\CommandEvent(
17952 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(), $event->getArguments()
17953 );
17954 }
17955 if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
17956 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);
17957 $event = new \Composer\Script\PackageEvent(
17958 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
17959 $event->getPolicy(), $event->getPool(), $event->getInstalledRepo(), $event->getRequest(),
17960 $event->getOperations(), $event->getOperation()
17961 );
17962 }
17963 if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
17964 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);
17965 $event = new \Composer\Script\Event(
17966 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
17967 $event->getArguments(), $event->getFlags()
17968 );
17969 }
17970
17971 return $event;
17972 }
17973
17974 private function serializeCallback($cb)
17975 {
17976 if (is_array($cb) && count($cb) === 2) {
17977 if (is_object($cb[0])) {
17978 $cb[0] = get_class($cb[0]);
17979 }
17980 if (is_string($cb[0]) && is_string($cb[1])) {
17981 $cb = implode('::', $cb);
17982 }
17983 }
17984 if (is_string($cb)) {
17985 return $cb;
17986 }
17987
17988 return var_export($cb, true);
17989 }
17990
17991
17992
17993
17994
17995
17996
17997
17998 public function addListener($eventName, $listener, $priority = 0)
17999 {
18000 $this->listeners[$eventName][$priority][] = $listener;
18001 }
18002
18003
18004
18005
18006
18007
18008
18009
18010 public function addSubscriber(EventSubscriberInterface $subscriber)
18011 {
18012 foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
18013 if (is_string($params)) {
18014 $this->addListener($eventName, array($subscriber, $params));
18015 } elseif (is_string($params[0])) {
18016 $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
18017 } else {
18018 foreach ($params as $listener) {
18019 $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
18020 }
18021 }
18022 }
18023 }
18024
18025
18026
18027
18028
18029
18030
18031 protected function getListeners(Event $event)
18032 {
18033 $scriptListeners = $this->getScriptListeners($event);
18034
18035 if (!isset($this->listeners[$event->getName()][0])) {
18036 $this->listeners[$event->getName()][0] = array();
18037 }
18038 krsort($this->listeners[$event->getName()]);
18039
18040 $listeners = $this->listeners;
18041 $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
18042
18043 return call_user_func_array('array_merge', $listeners[$event->getName()]);
18044 }
18045
18046
18047
18048
18049
18050
18051
18052 public function hasEventListeners(Event $event)
18053 {
18054 $listeners = $this->getListeners($event);
18055
18056 return count($listeners) > 0;
18057 }
18058
18059
18060
18061
18062
18063
18064
18065 protected function getScriptListeners(Event $event)
18066 {
18067 $package = $this->composer->getPackage();
18068 $scripts = $package->getScripts();
18069
18070 if (empty($scripts[$event->getName()])) {
18071 return array();
18072 }
18073
18074 if ($this->loader) {
18075 $this->loader->unregister();
18076 }
18077
18078 $generator = $this->composer->getAutoloadGenerator();
18079 if ($event instanceof ScriptEvent) {
18080 $generator->setDevMode($event->isDevMode());
18081 }
18082
18083 $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
18084 $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
18085 $map = $generator->parseAutoloads($packageMap, $package);
18086 $this->loader = $generator->createLoader($map);
18087 $this->loader->register();
18088
18089 return $scripts[$event->getName()];
18090 }
18091
18092
18093
18094
18095
18096
18097
18098 protected function isPhpScript($callable)
18099 {
18100 return false === strpos($callable, ' ') && false !== strpos($callable, '::');
18101 }
18102
18103
18104
18105
18106
18107
18108
18109 protected function isComposerScript($callable)
18110 {
18111 return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5);
18112 }
18113
18114
18115
18116
18117
18118
18119
18120
18121 protected function pushEvent(Event $event)
18122 {
18123 $eventName = $event->getName();
18124 if (in_array($eventName, $this->eventStack)) {
18125 throw new \RuntimeException(sprintf("Circular call to script handler '%s' detected", $eventName));
18126 }
18127
18128 return array_push($this->eventStack, $eventName);
18129 }
18130
18131
18132
18133
18134
18135
18136 protected function popEvent()
18137 {
18138 return array_pop($this->eventStack);
18139 }
18140 }
18141 <?php
18142
18143
18144
18145
18146
18147
18148
18149
18150
18151
18152
18153 namespace Composer\EventDispatcher;
18154
18155
18156
18157
18158
18159
18160
18161
18162
18163
18164
18165
18166
18167 interface EventSubscriberInterface
18168 {
18169
18170
18171
18172
18173
18174
18175
18176
18177
18178
18179
18180
18181
18182
18183
18184
18185
18186
18187 public static function getSubscribedEvents();
18188 }
18189 <?php
18190
18191
18192
18193
18194
18195
18196
18197
18198
18199
18200
18201 namespace Composer\EventDispatcher;
18202
18203
18204
18205
18206 class ScriptExecutionException extends \RuntimeException
18207 {
18208 }
18209 <?php
18210
18211
18212
18213
18214
18215
18216
18217
18218
18219
18220
18221 namespace Composer\Exception;
18222
18223
18224
18225
18226 class NoSslException extends \RuntimeException
18227 {
18228 }
18229 <?php
18230
18231
18232
18233
18234
18235
18236
18237
18238
18239
18240
18241 namespace Composer;
18242
18243 use Composer\Config\JsonConfigSource;
18244 use Composer\Json\JsonFile;
18245 use Composer\IO\IOInterface;
18246 use Composer\Package\Archiver;
18247 use Composer\Package\Version\VersionGuesser;
18248 use Composer\Repository\RepositoryManager;
18249 use Composer\Repository\RepositoryFactory;
18250 use Composer\Repository\WritableRepositoryInterface;
18251 use Composer\Util\Filesystem;
18252 use Composer\Util\Platform;
18253 use Composer\Util\ProcessExecutor;
18254 use Composer\Util\RemoteFilesystem;
18255 use Composer\Util\Silencer;
18256 use Composer\Plugin\PluginEvents;
18257 use Composer\EventDispatcher\Event;
18258 use Seld\JsonLint\DuplicateKeyException;
18259 use Symfony\Component\Console\Formatter\OutputFormatter;
18260 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
18261 use Symfony\Component\Console\Output\ConsoleOutput;
18262 use Composer\EventDispatcher\EventDispatcher;
18263 use Composer\Autoload\AutoloadGenerator;
18264 use Composer\Package\Version\VersionParser;
18265 use Composer\Downloader\TransportException;
18266 use Seld\JsonLint\JsonParser;
18267
18268
18269
18270
18271
18272
18273
18274
18275
18276 class Factory
18277 {
18278
18279
18280
18281
18282 protected static function getHomeDir()
18283 {
18284 $home = getenv('COMPOSER_HOME');
18285 if ($home) {
18286 return $home;
18287 }
18288
18289 if (Platform::isWindows()) {
18290 if (!getenv('APPDATA')) {
18291 throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
18292 }
18293
18294 return rtrim(strtr(getenv('APPDATA'), '\\', '/'), '/') . '/Composer';
18295 }
18296
18297 $userDir = self::getUserDir();
18298 if (is_dir($userDir . '/.composer')) {
18299 return $userDir . '/.composer';
18300 }
18301
18302 if (self::useXdg()) {
18303
18304  $xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
18305
18306 return $xdgConfig . '/composer';
18307 }
18308
18309 return $userDir . '/.composer';
18310 }
18311
18312
18313
18314
18315
18316 protected static function getCacheDir($home)
18317 {
18318 $cacheDir = getenv('COMPOSER_CACHE_DIR');
18319 if ($cacheDir) {
18320 return $cacheDir;
18321 }
18322
18323 $homeEnv = getenv('COMPOSER_HOME');
18324 if ($homeEnv) {
18325 return $homeEnv . '/cache';
18326 }
18327
18328 if (Platform::isWindows()) {
18329 if ($cacheDir = getenv('LOCALAPPDATA')) {
18330 $cacheDir .= '/Composer';
18331 } else {
18332 $cacheDir = $home . '/cache';
18333 }
18334
18335 return rtrim(strtr($cacheDir, '\\', '/'), '/');
18336 }
18337
18338 $userDir = self::getUserDir();
18339 if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
18340 return $home . '/cache';
18341 }
18342
18343 if (self::useXdg()) {
18344 $xdgCache = getenv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
18345
18346 return $xdgCache . '/composer';
18347 }
18348
18349 return $home . '/cache';
18350 }
18351
18352
18353
18354
18355
18356 protected static function getDataDir($home)
18357 {
18358 $homeEnv = getenv('COMPOSER_HOME');
18359 if ($homeEnv) {
18360 return $homeEnv;
18361 }
18362
18363 if (Platform::isWindows()) {
18364 return strtr($home, '\\', '/');
18365 }
18366
18367 $userDir = self::getUserDir();
18368 if ($home !== $userDir . '/.composer' && self::useXdg()) {
18369 $xdgData = getenv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
18370
18371 return $xdgData . '/composer';
18372 }
18373
18374 return $home;
18375 }
18376
18377
18378
18379
18380
18381 public static function createConfig(IOInterface $io = null, $cwd = null)
18382 {
18383 $cwd = $cwd ?: getcwd();
18384
18385 $config = new Config(true, $cwd);
18386
18387
18388  $home = self::getHomeDir();
18389 $config->merge(array('config' => array(
18390 'home' => $home,
18391 'cache-dir' => self::getCacheDir($home),
18392 'data-dir' => self::getDataDir($home),
18393 )));
18394
18395 $htaccessProtect = (bool) $config->get('htaccess-protect');
18396 if ($htaccessProtect) {
18397
18398  
18399  
18400  $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
18401 foreach ($dirs as $dir) {
18402 if (!file_exists($dir . '/.htaccess')) {
18403 if (!is_dir($dir)) {
18404 Silencer::call('mkdir', $dir, 0777, true);
18405 }
18406 Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
18407 }
18408 }
18409 }
18410
18411
18412  $file = new JsonFile($config->get('home').'/config.json');
18413 if ($file->exists()) {
18414 if ($io && $io->isDebug()) {
18415 $io->writeError('Loading config file ' . $file->getPath());
18416 }
18417 $config->merge($file->read());
18418 }
18419 $config->setConfigSource(new JsonConfigSource($file));
18420
18421
18422  $file = new JsonFile($config->get('home').'/auth.json');
18423 if ($file->exists()) {
18424 if ($io && $io->isDebug()) {
18425 $io->writeError('Loading config file ' . $file->getPath());
18426 }
18427 $config->merge(array('config' => $file->read()));
18428 }
18429 $config->setAuthConfigSource(new JsonConfigSource($file, true));
18430
18431
18432  if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
18433 $authData = json_decode($composerAuthEnv, true);
18434
18435 if (null === $authData) {
18436 throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
18437 }
18438
18439 if ($io && $io->isDebug()) {
18440 $io->writeError('Loading auth config from COMPOSER_AUTH');
18441 }
18442 $config->merge(array('config' => $authData));
18443 }
18444
18445 return $config;
18446 }
18447
18448 public static function getComposerFile()
18449 {
18450 return trim(getenv('COMPOSER')) ?: './composer.json';
18451 }
18452
18453 public static function createAdditionalStyles()
18454 {
18455 return array(
18456 'highlight' => new OutputFormatterStyle('red'),
18457 'warning' => new OutputFormatterStyle('black', 'yellow'),
18458 );
18459 }
18460
18461
18462
18463
18464
18465
18466 public static function createOutput()
18467 {
18468 $styles = self::createAdditionalStyles();
18469 $formatter = new OutputFormatter(false, $styles);
18470
18471 return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
18472 }
18473
18474
18475
18476
18477 public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
18478 {
18479 return RepositoryFactory::defaultRepos($io, $config, $rm);
18480 }
18481
18482
18483
18484
18485
18486
18487
18488
18489
18490
18491
18492
18493
18494 public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
18495 {
18496 $cwd = $cwd ?: getcwd();
18497
18498
18499  if (null === $localConfig) {
18500 $localConfig = static::getComposerFile();
18501 }
18502
18503 if (is_string($localConfig)) {
18504 $composerFile = $localConfig;
18505
18506 $file = new JsonFile($localConfig, null, $io);
18507
18508 if (!$file->exists()) {
18509 if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
18510 $message = 'Composer could not find a composer.json file in '.$cwd;
18511 } else {
18512 $message = 'Composer could not find the config file: '.$localConfig;
18513 }
18514 $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section';
18515 throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
18516 }
18517
18518 $file->validateSchema(JsonFile::LAX_SCHEMA);
18519 $jsonParser = new JsonParser;
18520 try {
18521 $jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS);
18522 } catch (DuplicateKeyException $e) {
18523 $details = $e->getDetails();
18524 $io->writeError('<warning>Key '.$details['key'].' is a duplicate in '.$localConfig.' at line '.$details['line'].'</warning>');
18525 }
18526
18527 $localConfig = $file->read();
18528 }
18529
18530
18531  $config = static::createConfig($io, $cwd);
18532 $config->merge($localConfig);
18533 if (isset($composerFile)) {
18534 $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
18535 $config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
18536
18537 $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
18538 if ($localAuthFile->exists()) {
18539 $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
18540 $config->merge(array('config' => $localAuthFile->read()));
18541 $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
18542 }
18543 }
18544
18545 $vendorDir = $config->get('vendor-dir');
18546
18547
18548  $composer = new Composer();
18549 $composer->setConfig($config);
18550
18551 if ($fullLoad) {
18552
18553  $io->loadConfiguration($config);
18554 }
18555
18556 $rfs = self::createRemoteFilesystem($io, $config);
18557
18558
18559  $dispatcher = new EventDispatcher($composer, $io);
18560 $composer->setEventDispatcher($dispatcher);
18561
18562
18563  $rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
18564 $composer->setRepositoryManager($rm);
18565
18566
18567  $this->addLocalRepository($io, $rm, $vendorDir);
18568
18569
18570  
18571  if (!$fullLoad && !isset($localConfig['version'])) {
18572 $localConfig['version'] = '1.0.0';
18573 }
18574
18575
18576  $parser = new VersionParser;
18577 $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
18578 $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser);
18579 $package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
18580 $composer->setPackage($package);
18581
18582
18583  $im = $this->createInstallationManager();
18584 $composer->setInstallationManager($im);
18585
18586 if ($fullLoad) {
18587
18588  $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
18589 $composer->setDownloadManager($dm);
18590
18591
18592  $generator = new AutoloadGenerator($dispatcher, $io);
18593 $composer->setAutoloadGenerator($generator);
18594
18595
18596  $am = $this->createArchiveManager($config, $dm);
18597 $composer->setArchiveManager($am);
18598 }
18599
18600
18601  $this->createDefaultInstallers($im, $composer, $io);
18602
18603 if ($fullLoad) {
18604 $globalComposer = null;
18605 if (realpath($config->get('home')) !== $cwd) {
18606 $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
18607 }
18608
18609 $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
18610 $composer->setPluginManager($pm);
18611
18612 $pm->loadInstalledPlugins();
18613 }
18614
18615
18616  if ($fullLoad && isset($composerFile)) {
18617 $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
18618 ? substr($composerFile, 0, -4).'lock'
18619 : $composerFile . '.lock';
18620
18621 $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile));
18622 $composer->setLocker($locker);
18623 }
18624
18625 if ($fullLoad) {
18626 $initEvent = new Event(PluginEvents::INIT);
18627 $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent);
18628
18629
18630  
18631  if ($rm->getLocalRepository()) {
18632 $this->purgePackages($rm->getLocalRepository(), $im);
18633 }
18634 }
18635
18636 return $composer;
18637 }
18638
18639
18640
18641
18642
18643
18644 public static function createGlobal(IOInterface $io, $disablePlugins = false)
18645 {
18646 $factory = new static();
18647
18648 return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, true);
18649 }
18650
18651
18652
18653
18654
18655 protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir)
18656 {
18657 $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io)));
18658 }
18659
18660
18661
18662
18663
18664 protected function createGlobalComposer(IOInterface $io, Config $config, $disablePlugins, $fullLoad = false)
18665 {
18666 $composer = null;
18667 try {
18668 $composer = $this->createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad);
18669 } catch (\Exception $e) {
18670 $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
18671 }
18672
18673 return $composer;
18674 }
18675
18676
18677
18678
18679
18680
18681
18682 public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
18683 {
18684 $cache = null;
18685 if ($config->get('cache-files-ttl') > 0) {
18686 $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
18687 }
18688
18689 $dm = new Downloader\DownloadManager($io);
18690 switch ($preferred = $config->get('preferred-install')) {
18691 case 'dist':
18692 $dm->setPreferDist(true);
18693 break;
18694 case 'source':
18695 $dm->setPreferSource(true);
18696 break;
18697 case 'auto':
18698 default:
18699
18700  break;
18701 }
18702
18703 if (is_array($preferred)) {
18704 $dm->setPreferences($preferred);
18705 }
18706
18707 $executor = new ProcessExecutor($io);
18708 $fs = new Filesystem($executor);
18709
18710 $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs));
18711 $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs));
18712 $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $executor, $fs));
18713 $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs));
18714 $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
18715 $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18716 $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18717 $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18718 $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18719 $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18720 $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18721 $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18722 $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18723
18724 return $dm;
18725 }
18726
18727
18728
18729
18730
18731
18732 public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
18733 {
18734 if (null === $dm) {
18735 $io = new IO\NullIO();
18736 $io->loadConfiguration($config);
18737 $dm = $this->createDownloadManager($io, $config);
18738 }
18739
18740 $am = new Archiver\ArchiveManager($dm);
18741 $am->addArchiver(new Archiver\ZipArchiver);
18742 $am->addArchiver(new Archiver\PharArchiver);
18743
18744 return $am;
18745 }
18746
18747
18748
18749
18750
18751
18752
18753
18754 protected function createPluginManager(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
18755 {
18756 return new Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
18757 }
18758
18759
18760
18761
18762 protected function createInstallationManager()
18763 {
18764 return new Installer\InstallationManager();
18765 }
18766
18767
18768
18769
18770
18771
18772 protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
18773 {
18774 $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
18775 $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
18776 $im->addInstaller(new Installer\PluginInstaller($io, $composer));
18777 $im->addInstaller(new Installer\MetapackageInstaller($io));
18778 }
18779
18780
18781
18782
18783
18784 protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
18785 {
18786 foreach ($repo->getPackages() as $package) {
18787 if (!$im->isPackageInstalled($repo, $package)) {
18788 $repo->removePackage($package);
18789 }
18790 }
18791 }
18792
18793
18794
18795
18796
18797
18798
18799
18800 public static function create(IOInterface $io, $config = null, $disablePlugins = false)
18801 {
18802 $factory = new static();
18803
18804 return $factory->createComposer($io, $config, $disablePlugins);
18805 }
18806
18807
18808
18809
18810
18811
18812
18813 public static function createRemoteFilesystem(IOInterface $io, Config $config = null, $options = array())
18814 {
18815 static $warned = false;
18816 $disableTls = false;
18817 if ($config && $config->get('disable-tls') === true) {
18818 if (!$warned) {
18819 $io->write('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
18820 }
18821 $warned = true;
18822 $disableTls = true;
18823 } elseif (!extension_loaded('openssl')) {
18824 throw new Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. '
18825 . '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.');
18826 }
18827 $remoteFilesystemOptions = array();
18828 if ($disableTls === false) {
18829 if ($config && $config->get('cafile')) {
18830 $remoteFilesystemOptions['ssl']['cafile'] = $config->get('cafile');
18831 }
18832 if ($config && $config->get('capath')) {
18833 $remoteFilesystemOptions['ssl']['capath'] = $config->get('capath');
18834 }
18835 $remoteFilesystemOptions = array_replace_recursive($remoteFilesystemOptions, $options);
18836 }
18837 try {
18838 $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);
18839 } catch (TransportException $e) {
18840 if (false !== strpos($e->getMessage(), 'cafile')) {
18841 $io->write('<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>');
18842 $io->write('<error>A valid CA certificate file is required for SSL/TLS protection.</error>');
18843 if (PHP_VERSION_ID < 50600) {
18844 $io->write('<error>It is recommended you upgrade to PHP 5.6+ which can detect your system CA file automatically.</error>');
18845 }
18846 $io->write('<error>You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.</error>');
18847 }
18848 throw $e;
18849 }
18850
18851 return $remoteFilesystem;
18852 }
18853
18854
18855
18856
18857 private static function useXdg()
18858 {
18859 foreach (array_keys($_SERVER) as $key) {
18860 if (substr($key, 0, 4) === 'XDG_') {
18861 return true;
18862 }
18863 }
18864
18865 return false;
18866 }
18867
18868
18869
18870
18871
18872 private static function getUserDir()
18873 {
18874 $home = getenv('HOME');
18875 if (!$home) {
18876 throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
18877 }
18878
18879 return rtrim(strtr($home, '\\', '/'), '/');
18880 }
18881 }
18882 <?php
18883
18884
18885
18886
18887
18888
18889
18890
18891
18892
18893
18894 namespace Composer\IO;
18895
18896 use Composer\Config;
18897 use Composer\Util\ProcessExecutor;
18898 use Psr\Log\LoggerInterface;
18899 use Psr\Log\LogLevel;
18900
18901 abstract class BaseIO implements IOInterface, LoggerInterface
18902 {
18903 protected $authentications = array();
18904
18905
18906
18907
18908 public function getAuthentications()
18909 {
18910 return $this->authentications;
18911 }
18912
18913
18914
18915
18916 public function hasAuthentication($repositoryName)
18917 {
18918 return isset($this->authentications[$repositoryName]);
18919 }
18920
18921
18922
18923
18924 public function getAuthentication($repositoryName)
18925 {
18926 if (isset($this->authentications[$repositoryName])) {
18927 return $this->authentications[$repositoryName];
18928 }
18929
18930 return array('username' => null, 'password' => null);
18931 }
18932
18933
18934
18935
18936 public function setAuthentication($repositoryName, $username, $password = null)
18937 {
18938 $this->authentications[$repositoryName] = array('username' => $username, 'password' => $password);
18939 }
18940
18941
18942
18943
18944
18945
18946
18947
18948 protected function checkAndSetAuthentication($repositoryName, $username, $password = null)
18949 {
18950 if ($this->hasAuthentication($repositoryName)) {
18951 $auth = $this->getAuthentication($repositoryName);
18952 if ($auth['username'] === $username && $auth['password'] === $password) {
18953 return;
18954 }
18955
18956 $this->writeError(
18957 sprintf(
18958 "<warning>Warning: You should avoid overwriting already defined auth settings for %s.</warning>",
18959 $repositoryName
18960 )
18961 );
18962 }
18963 $this->setAuthentication($repositoryName, $username, $password);
18964 }
18965
18966
18967
18968
18969 public function loadConfiguration(Config $config)
18970 {
18971 $bitbucketOauth = $config->get('bitbucket-oauth') ?: array();
18972 $githubOauth = $config->get('github-oauth') ?: array();
18973 $gitlabOauth = $config->get('gitlab-oauth') ?: array();
18974 $gitlabToken = $config->get('gitlab-token') ?: array();
18975 $httpBasic = $config->get('http-basic') ?: array();
18976
18977
18978
18979 foreach ($bitbucketOauth as $domain => $cred) {
18980 $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']);
18981 }
18982
18983 foreach ($githubOauth as $domain => $token) {
18984 if (!preg_match('{^[.a-z0-9]+$}', $token)) {
18985 throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
18986 }
18987 $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic');
18988 }
18989
18990 foreach ($gitlabOauth as $domain => $token) {
18991 $this->checkAndSetAuthentication($domain, $token, 'oauth2');
18992 }
18993
18994 foreach ($gitlabToken as $domain => $token) {
18995 $this->checkAndSetAuthentication($domain, $token, 'private-token');
18996 }
18997
18998
18999  foreach ($httpBasic as $domain => $cred) {
19000 $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
19001 }
19002
19003
19004  ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
19005 }
19006
19007
19008
19009
19010
19011
19012
19013
19014 public function emergency($message, array $context = array())
19015 {
19016 return $this->log(LogLevel::EMERGENCY, $message, $context);
19017 }
19018
19019
19020
19021
19022
19023
19024
19025
19026
19027
19028
19029 public function alert($message, array $context = array())
19030 {
19031 return $this->log(LogLevel::ALERT, $message, $context);
19032 }
19033
19034
19035
19036
19037
19038
19039
19040
19041
19042
19043 public function critical($message, array $context = array())
19044 {
19045 return $this->log(LogLevel::CRITICAL, $message, $context);
19046 }
19047
19048
19049
19050
19051
19052
19053
19054
19055
19056 public function error($message, array $context = array())
19057 {
19058 return $this->log(LogLevel::ERROR, $message, $context);
19059 }
19060
19061
19062
19063
19064
19065
19066
19067
19068
19069
19070
19071 public function warning($message, array $context = array())
19072 {
19073 return $this->log(LogLevel::WARNING, $message, $context);
19074 }
19075
19076
19077
19078
19079
19080
19081
19082
19083 public function notice($message, array $context = array())
19084 {
19085 return $this->log(LogLevel::NOTICE, $message, $context);
19086 }
19087
19088
19089
19090
19091
19092
19093
19094
19095
19096
19097 public function info($message, array $context = array())
19098 {
19099 return $this->log(LogLevel::INFO, $message, $context);
19100 }
19101
19102
19103
19104
19105
19106
19107
19108
19109 public function debug($message, array $context = array())
19110 {
19111 return $this->log(LogLevel::DEBUG, $message, $context);
19112 }
19113
19114
19115
19116
19117
19118
19119
19120
19121
19122 public function log($level, $message, array $context = array())
19123 {
19124 if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
19125 $this->writeError('<error>'.$message.'</error>', true, self::NORMAL);
19126 } elseif ($level === LogLevel::WARNING) {
19127 $this->writeError('<warning>'.$message.'</warning>', true, self::NORMAL);
19128 } elseif ($level === LogLevel::NOTICE) {
19129 $this->writeError('<info>'.$message.'</info>', true, self::VERBOSE);
19130 } elseif ($level === LogLevel::INFO) {
19131 $this->writeError('<info>'.$message.'</info>', true, self::VERY_VERBOSE);
19132 } else {
19133 $this->writeError($message, true, self::DEBUG);
19134 }
19135 }
19136 }
19137 <?php
19138
19139
19140
19141
19142
19143
19144
19145
19146
19147
19148
19149 namespace Composer\IO;
19150
19151 use Symfony\Component\Console\Output\StreamOutput;
19152 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
19153 use Symfony\Component\Console\Input\StringInput;
19154 use Symfony\Component\Console\Helper\HelperSet;
19155
19156
19157
19158
19159 class BufferIO extends ConsoleIO
19160 {
19161
19162
19163
19164
19165
19166 public function __construct($input = '', $verbosity = StreamOutput::VERBOSITY_NORMAL, OutputFormatterInterface $formatter = null)
19167 {
19168 $input = new StringInput($input);
19169 $input->setInteractive(false);
19170
19171 $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
19172
19173 parent::__construct($input, $output, new HelperSet(array()));
19174 }
19175
19176 public function getOutput()
19177 {
19178 fseek($this->output->getStream(), 0);
19179
19180 $output = stream_get_contents($this->output->getStream());
19181
19182 $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) {
19183 $pre = strip_tags($matches[1]);
19184
19185 if (strlen($pre) === strlen($matches[2])) {
19186 return '';
19187 }
19188
19189
19190  return rtrim($matches[1])."\n";
19191 }, $output);
19192
19193 return $output;
19194 }
19195 }
19196 <?php
19197
19198
19199
19200
19201
19202
19203
19204
19205
19206
19207
19208 namespace Composer\IO;
19209
19210 use Composer\Question\StrictConfirmationQuestion;
19211 use Symfony\Component\Console\Helper\HelperSet;
19212 use Symfony\Component\Console\Input\InputInterface;
19213 use Symfony\Component\Console\Output\ConsoleOutputInterface;
19214 use Symfony\Component\Console\Output\OutputInterface;
19215 use Symfony\Component\Console\Question\ChoiceQuestion;
19216 use Symfony\Component\Console\Question\Question;
19217
19218
19219
19220
19221
19222
19223
19224 class ConsoleIO extends BaseIO
19225 {
19226
19227 protected $input;
19228
19229 protected $output;
19230
19231 protected $helperSet;
19232
19233 protected $lastMessage;
19234
19235 protected $lastMessageErr;
19236
19237
19238 private $startTime;
19239
19240 private $verbosityMap;
19241
19242
19243
19244
19245
19246
19247
19248
19249 public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
19250 {
19251 $this->input = $input;
19252 $this->output = $output;
19253 $this->helperSet = $helperSet;
19254 $this->verbosityMap = array(
19255 self::QUIET => OutputInterface::VERBOSITY_QUIET,
19256 self::NORMAL => OutputInterface::VERBOSITY_NORMAL,
19257 self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
19258 self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
19259 self::DEBUG => OutputInterface::VERBOSITY_DEBUG,
19260 );
19261 }
19262
19263
19264
19265
19266 public function enableDebugging($startTime)
19267 {
19268 $this->startTime = $startTime;
19269 }
19270
19271
19272
19273
19274 public function isInteractive()
19275 {
19276 return $this->input->isInteractive();
19277 }
19278
19279
19280
19281
19282 public function isDecorated()
19283 {
19284 return $this->output->isDecorated();
19285 }
19286
19287
19288
19289
19290 public function isVerbose()
19291 {
19292 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
19293 }
19294
19295
19296
19297
19298 public function isVeryVerbose()
19299 {
19300 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
19301 }
19302
19303
19304
19305
19306 public function isDebug()
19307 {
19308 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
19309 }
19310
19311
19312
19313
19314 public function write($messages, $newline = true, $verbosity = self::NORMAL)
19315 {
19316 $this->doWrite($messages, $newline, false, $verbosity);
19317 }
19318
19319
19320
19321
19322 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
19323 {
19324 $this->doWrite($messages, $newline, true, $verbosity);
19325 }
19326
19327
19328
19329
19330
19331
19332
19333 private function doWrite($messages, $newline, $stderr, $verbosity)
19334 {
19335 $sfVerbosity = $this->verbosityMap[$verbosity];
19336 if ($sfVerbosity > $this->output->getVerbosity()) {
19337 return;
19338 }
19339
19340
19341  
19342  
19343  if (OutputInterface::VERBOSITY_QUIET === 0) {
19344 $sfVerbosity = OutputInterface::OUTPUT_NORMAL;
19345 }
19346
19347 if (null !== $this->startTime) {
19348 $memoryUsage = memory_get_usage() / 1024 / 1024;
19349 $timeSpent = microtime(true) - $this->startTime;
19350 $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
19351 return sprintf('[%.1fMB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
19352 }, (array) $messages);
19353 }
19354
19355 if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
19356 $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
19357 $this->lastMessageErr = implode($newline ? "\n" : '', (array) $messages);
19358
19359 return;
19360 }
19361
19362 $this->output->write($messages, $newline, $sfVerbosity);
19363 $this->lastMessage = implode($newline ? "\n" : '', (array) $messages);
19364 }
19365
19366
19367
19368
19369 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19370 {
19371 $this->doOverwrite($messages, $newline, $size, false, $verbosity);
19372 }
19373
19374
19375
19376
19377 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19378 {
19379 $this->doOverwrite($messages, $newline, $size, true, $verbosity);
19380 }
19381
19382
19383
19384
19385
19386
19387
19388
19389 private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
19390 {
19391
19392  $messages = implode($newline ? "\n" : '', (array) $messages);
19393
19394
19395  if (!isset($size)) {
19396
19397  $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
19398 }
19399
19400  $this->doWrite(str_repeat("\x08", $size), false, $stderr, $verbosity);
19401
19402
19403  $this->doWrite($messages, false, $stderr, $verbosity);
19404
19405
19406  
19407  
19408  $fill = $size - strlen(strip_tags($messages));
19409 if ($fill > 0) {
19410
19411  $this->doWrite(str_repeat(' ', $fill), false, $stderr, $verbosity);
19412
19413  $this->doWrite(str_repeat("\x08", $fill), false, $stderr, $verbosity);
19414 }
19415
19416 if ($newline) {
19417 $this->doWrite('', true, $stderr, $verbosity);
19418 }
19419
19420 if ($stderr) {
19421 $this->lastMessageErr = $messages;
19422 } else {
19423 $this->lastMessage = $messages;
19424 }
19425 }
19426
19427
19428
19429
19430 public function ask($question, $default = null)
19431 {
19432
19433 $helper = $this->helperSet->get('question');
19434 $question = new Question($question, $default);
19435
19436 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19437 }
19438
19439
19440
19441
19442 public function askConfirmation($question, $default = true)
19443 {
19444
19445 $helper = $this->helperSet->get('question');
19446 $question = new StrictConfirmationQuestion($question, $default);
19447
19448 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19449 }
19450
19451
19452
19453
19454 public function askAndValidate($question, $validator, $attempts = null, $default = null)
19455 {
19456
19457 $helper = $this->helperSet->get('question');
19458 $question = new Question($question, $default);
19459 $question->setValidator($validator);
19460 $question->setMaxAttempts($attempts);
19461
19462 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19463 }
19464
19465
19466
19467
19468 public function askAndHideAnswer($question)
19469 {
19470 $this->writeError($question, false);
19471
19472 return \Seld\CliPrompt\CliPrompt::hiddenPrompt(true);
19473 }
19474
19475
19476
19477
19478 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
19479 {
19480
19481 $helper = $this->helperSet->get('question');
19482 $question = new ChoiceQuestion($question, $choices, $default);
19483 $question->setMaxAttempts($attempts ?: null); 
19484  $question->setErrorMessage($errorMessage);
19485 $question->setMultiselect($multiselect);
19486
19487 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19488 }
19489
19490
19491
19492
19493 private function getErrorOutput()
19494 {
19495 if ($this->output instanceof ConsoleOutputInterface) {
19496 return $this->output->getErrorOutput();
19497 }
19498
19499 return $this->output;
19500 }
19501 }
19502 <?php
19503
19504
19505
19506
19507
19508
19509
19510
19511
19512
19513
19514 namespace Composer\IO;
19515
19516 use Composer\Config;
19517
19518
19519
19520
19521
19522
19523 interface IOInterface
19524 {
19525 const QUIET = 1;
19526 const NORMAL = 2;
19527 const VERBOSE = 4;
19528 const VERY_VERBOSE = 8;
19529 const DEBUG = 16;
19530
19531
19532
19533
19534
19535
19536 public function isInteractive();
19537
19538
19539
19540
19541
19542
19543 public function isVerbose();
19544
19545
19546
19547
19548
19549
19550 public function isVeryVerbose();
19551
19552
19553
19554
19555
19556
19557 public function isDebug();
19558
19559
19560
19561
19562
19563
19564 public function isDecorated();
19565
19566
19567
19568
19569
19570
19571
19572
19573 public function write($messages, $newline = true, $verbosity = self::NORMAL);
19574
19575
19576
19577
19578
19579
19580
19581
19582 public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
19583
19584
19585
19586
19587
19588
19589
19590
19591
19592 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
19593
19594
19595
19596
19597
19598
19599
19600
19601
19602 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
19603
19604
19605
19606
19607
19608
19609
19610
19611
19612
19613 public function ask($question, $default = null);
19614
19615
19616
19617
19618
19619
19620
19621
19622
19623
19624
19625 public function askConfirmation($question, $default = true);
19626
19627
19628
19629
19630
19631
19632
19633
19634
19635
19636
19637
19638
19639
19640
19641
19642 public function askAndValidate($question, $validator, $attempts = null, $default = null);
19643
19644
19645
19646
19647
19648
19649
19650
19651 public function askAndHideAnswer($question);
19652
19653
19654
19655
19656
19657
19658
19659
19660
19661
19662
19663
19664
19665
19666 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
19667
19668
19669
19670
19671
19672
19673 public function getAuthentications();
19674
19675
19676
19677
19678
19679
19680
19681
19682 public function hasAuthentication($repositoryName);
19683
19684
19685
19686
19687
19688
19689
19690
19691 public function getAuthentication($repositoryName);
19692
19693
19694
19695
19696
19697
19698
19699
19700 public function setAuthentication($repositoryName, $username, $password = null);
19701
19702
19703
19704
19705
19706
19707 public function loadConfiguration(Config $config);
19708 }
19709 <?php
19710
19711
19712
19713
19714
19715
19716
19717
19718
19719
19720
19721 namespace Composer\IO;
19722
19723
19724
19725
19726
19727
19728 class NullIO extends BaseIO
19729 {
19730
19731
19732
19733 public function isInteractive()
19734 {
19735 return false;
19736 }
19737
19738
19739
19740
19741 public function isVerbose()
19742 {
19743 return false;
19744 }
19745
19746
19747
19748
19749 public function isVeryVerbose()
19750 {
19751 return false;
19752 }
19753
19754
19755
19756
19757 public function isDebug()
19758 {
19759 return false;
19760 }
19761
19762
19763
19764
19765 public function isDecorated()
19766 {
19767 return false;
19768 }
19769
19770
19771
19772
19773 public function write($messages, $newline = true, $verbosity = self::NORMAL)
19774 {
19775 }
19776
19777
19778
19779
19780 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
19781 {
19782 }
19783
19784
19785
19786
19787 public function overwrite($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
19788 {
19789 }
19790
19791
19792
19793
19794 public function overwriteError($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
19795 {
19796 }
19797
19798
19799
19800
19801 public function ask($question, $default = null)
19802 {
19803 return $default;
19804 }
19805
19806
19807
19808
19809 public function askConfirmation($question, $default = true)
19810 {
19811 return $default;
19812 }
19813
19814
19815
19816
19817 public function askAndValidate($question, $validator, $attempts = false, $default = null)
19818 {
19819 return $default;
19820 }
19821
19822
19823
19824
19825 public function askAndHideAnswer($question)
19826 {
19827 return null;
19828 }
19829
19830
19831
19832
19833 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
19834 {
19835 return $default;
19836 }
19837 }
19838 <?php
19839
19840
19841
19842
19843
19844
19845
19846
19847
19848
19849
19850 namespace Composer;
19851
19852 use Composer\Autoload\AutoloadGenerator;
19853 use Composer\DependencyResolver\DefaultPolicy;
19854 use Composer\DependencyResolver\Operation\UpdateOperation;
19855 use Composer\DependencyResolver\Operation\InstallOperation;
19856 use Composer\DependencyResolver\Operation\UninstallOperation;
19857 use Composer\DependencyResolver\Operation\OperationInterface;
19858 use Composer\DependencyResolver\PolicyInterface;
19859 use Composer\DependencyResolver\Pool;
19860 use Composer\DependencyResolver\Request;
19861 use Composer\DependencyResolver\Rule;
19862 use Composer\DependencyResolver\Solver;
19863 use Composer\DependencyResolver\SolverProblemsException;
19864 use Composer\Downloader\DownloadManager;
19865 use Composer\EventDispatcher\EventDispatcher;
19866 use Composer\Installer\InstallationManager;
19867 use Composer\Installer\InstallerEvents;
19868 use Composer\Installer\NoopInstaller;
19869 use Composer\Installer\SuggestedPackagesReporter;
19870 use Composer\IO\IOInterface;
19871 use Composer\Package\AliasPackage;
19872 use Composer\Package\CompletePackage;
19873 use Composer\Package\Link;
19874 use Composer\Package\Loader\ArrayLoader;
19875 use Composer\Package\Dumper\ArrayDumper;
19876 use Composer\Semver\Constraint\Constraint;
19877 use Composer\Package\Locker;
19878 use Composer\Package\PackageInterface;
19879 use Composer\Package\RootPackageInterface;
19880 use Composer\Repository\CompositeRepository;
19881 use Composer\Repository\InstalledArrayRepository;
19882 use Composer\Repository\PlatformRepository;
19883 use Composer\Repository\RepositoryInterface;
19884 use Composer\Repository\RepositoryManager;
19885 use Composer\Repository\WritableRepositoryInterface;
19886 use Composer\Script\ScriptEvents;
19887
19888
19889
19890
19891
19892
19893
19894 class Installer
19895 {
19896
19897
19898
19899 protected $io;
19900
19901
19902
19903
19904 protected $config;
19905
19906
19907
19908
19909 protected $package;
19910
19911
19912
19913
19914 protected $downloadManager;
19915
19916
19917
19918
19919 protected $repositoryManager;
19920
19921
19922
19923
19924 protected $locker;
19925
19926
19927
19928
19929 protected $installationManager;
19930
19931
19932
19933
19934 protected $eventDispatcher;
19935
19936
19937
19938
19939 protected $autoloadGenerator;
19940
19941 protected $preferSource = false;
19942 protected $preferDist = false;
19943 protected $optimizeAutoloader = false;
19944 protected $classMapAuthoritative = false;
19945 protected $apcuAutoloader = false;
19946 protected $devMode = false;
19947 protected $dryRun = false;
19948 protected $verbose = false;
19949 protected $update = false;
19950 protected $dumpAutoloader = true;
19951 protected $runScripts = true;
19952 protected $ignorePlatformReqs = false;
19953 protected $preferStable = false;
19954 protected $preferLowest = false;
19955 protected $skipSuggest = false;
19956 protected $writeLock = true;
19957 protected $executeOperations = true;
19958
19959
19960
19961
19962
19963
19964 protected $updateWhitelist = null;
19965 protected $whitelistDependencies = false; 
19966  protected $whitelistAllDependencies = false;
19967
19968
19969
19970
19971 protected $suggestedPackagesReporter;
19972
19973
19974
19975
19976 protected $additionalInstalledRepository;
19977
19978
19979
19980
19981
19982
19983
19984
19985
19986
19987
19988
19989
19990
19991 public function __construct(IOInterface $io, Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
19992 {
19993 $this->io = $io;
19994 $this->config = $config;
19995 $this->package = $package;
19996 $this->downloadManager = $downloadManager;
19997 $this->repositoryManager = $repositoryManager;
19998 $this->locker = $locker;
19999 $this->installationManager = $installationManager;
20000 $this->eventDispatcher = $eventDispatcher;
20001 $this->autoloadGenerator = $autoloadGenerator;
20002 }
20003
20004
20005
20006
20007
20008
20009
20010 public function run()
20011 {
20012
20013  
20014  
20015  
20016  gc_collect_cycles();
20017 gc_disable();
20018
20019
20020  if (!$this->update && !$this->locker->isLocked()) {
20021 $this->update = true;
20022 }
20023
20024 if ($this->dryRun) {
20025 $this->verbose = true;
20026 $this->runScripts = false;
20027 $this->executeOperations = false;
20028 $this->writeLock = false;
20029 $this->dumpAutoloader = false;
20030 $this->installationManager->addInstaller(new NoopInstaller);
20031 $this->mockLocalRepositories($this->repositoryManager);
20032 }
20033
20034 if ($this->runScripts) {
20035 $devMode = (int) $this->devMode;
20036 putenv("COMPOSER_DEV_MODE=$devMode");
20037
20038
20039  $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
20040 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
20041 }
20042
20043 $this->downloadManager->setPreferSource($this->preferSource);
20044 $this->downloadManager->setPreferDist($this->preferDist);
20045
20046
20047  $localRepo = $this->repositoryManager->getLocalRepository();
20048 if ($this->update) {
20049 $platformOverrides = $this->config->get('platform') ?: array();
20050 } else {
20051 $platformOverrides = $this->locker->getPlatformOverrides();
20052 }
20053 $platformRepo = new PlatformRepository(array(), $platformOverrides);
20054 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
20055
20056 $aliases = $this->getRootAliases();
20057 $this->aliasPlatformPackages($platformRepo, $aliases);
20058
20059 if (!$this->suggestedPackagesReporter) {
20060 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
20061 }
20062
20063 try {
20064 list($res, $devPackages) = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases);
20065 if ($res !== 0) {
20066 return $res;
20067 }
20068 } catch (\Exception $e) {
20069 if ($this->executeOperations) {
20070 $this->installationManager->notifyInstalls($this->io);
20071 }
20072
20073 throw $e;
20074 }
20075 if ($this->executeOperations) {
20076 $this->installationManager->notifyInstalls($this->io);
20077 }
20078
20079
20080  if ($this->devMode && !$this->skipSuggest) {
20081 $this->suggestedPackagesReporter->output($installedRepo);
20082 }
20083
20084
20085  foreach ($localRepo->getPackages() as $package) {
20086 if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
20087 continue;
20088 }
20089
20090 $replacement = (is_string($package->getReplacementPackage()))
20091 ? 'Use ' . $package->getReplacementPackage() . ' instead'
20092 : 'No replacement was suggested';
20093
20094 $this->io->writeError(
20095 sprintf(
20096 "<warning>Package %s is abandoned, you should avoid using it. %s.</warning>",
20097 $package->getPrettyName(),
20098 $replacement
20099 )
20100 );
20101 }
20102
20103
20104  if ($this->update && $this->writeLock) {
20105 $localRepo->reload();
20106
20107 $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
20108 $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires());
20109
20110 $updatedLock = $this->locker->setLockData(
20111 array_diff($localRepo->getCanonicalPackages(), $devPackages),
20112 $devPackages,
20113 $platformReqs,
20114 $platformDevReqs,
20115 $aliases,
20116 $this->package->getMinimumStability(),
20117 $this->package->getStabilityFlags(),
20118 $this->preferStable || $this->package->getPreferStable(),
20119 $this->preferLowest,
20120 $this->config->get('platform') ?: array()
20121 );
20122 if ($updatedLock) {
20123 $this->io->writeError('<info>Writing lock file</info>');
20124 }
20125 }
20126
20127 if ($this->dumpAutoloader) {
20128
20129  if ($this->optimizeAutoloader) {
20130 $this->io->writeError('<info>Generating optimized autoload files</info>');
20131 } else {
20132 $this->io->writeError('<info>Generating autoload files</info>');
20133 }
20134
20135 $this->autoloadGenerator->setDevMode($this->devMode);
20136 $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
20137 $this->autoloadGenerator->setApcu($this->apcuAutoloader);
20138 $this->autoloadGenerator->setRunScripts($this->runScripts);
20139 $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
20140 }
20141
20142 if ($this->executeOperations) {
20143
20144  foreach ($localRepo->getPackages() as $package) {
20145 $this->installationManager->ensureBinariesPresence($package);
20146 }
20147
20148 $vendorDir = $this->config->get('vendor-dir');
20149 if (is_dir($vendorDir)) {
20150
20151  
20152  @touch($vendorDir);
20153 }
20154 }
20155
20156 if ($this->runScripts) {
20157
20158  $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
20159 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
20160 }
20161
20162
20163  if (!defined('HHVM_VERSION')) {
20164 gc_enable();
20165 }
20166
20167 return 0;
20168 }
20169
20170
20171
20172
20173
20174
20175
20176
20177 protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases)
20178 {
20179
20180  $lockedRepository = null;
20181 $repositories = null;
20182
20183
20184  
20185  
20186  if (!$this->update || (!empty($this->updateWhitelist) && $this->locker->isLocked())) {
20187 try {
20188 $lockedRepository = $this->locker->getLockedRepository($this->devMode);
20189 } catch (\RuntimeException $e) {
20190
20191  if ($this->package->getDevRequires()) {
20192 throw $e;
20193 }
20194
20195  $lockedRepository = $this->locker->getLockedRepository();
20196 }
20197 }
20198
20199 $this->whitelistUpdateDependencies(
20200 $lockedRepository ?: $localRepo,
20201 $this->package->getRequires(),
20202 $this->package->getDevRequires()
20203 );
20204
20205 $this->io->writeError('<info>Loading composer repositories with package information</info>');
20206
20207
20208  $policy = $this->createPolicy();
20209 $pool = $this->createPool($this->update ? null : $lockedRepository);
20210 $pool->addRepository($installedRepo, $aliases);
20211 if ($this->update) {
20212 $repositories = $this->repositoryManager->getRepositories();
20213 foreach ($repositories as $repository) {
20214 $pool->addRepository($repository, $aliases);
20215 }
20216 }
20217
20218  
20219  
20220  if ($lockedRepository) {
20221 $pool->addRepository($lockedRepository, $aliases);
20222 }
20223
20224
20225  $request = $this->createRequest($this->package, $platformRepo);
20226
20227 if ($this->update) {
20228
20229  $removedUnstablePackages = array();
20230 foreach ($localRepo->getPackages() as $package) {
20231 if (
20232 !$pool->isPackageAcceptable($package->getNames(), $package->getStability())
20233 && $this->installationManager->isPackageInstalled($localRepo, $package)
20234 ) {
20235 $removedUnstablePackages[$package->getName()] = true;
20236 $request->remove($package->getName(), new Constraint('=', $package->getVersion()));
20237 }
20238 }
20239
20240 $this->io->writeError('<info>Updating dependencies'.($this->devMode ? ' (including require-dev)' : '').'</info>');
20241
20242 $request->updateAll();
20243
20244 $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
20245
20246 foreach ($links as $link) {
20247 $request->install($link->getTarget(), $link->getConstraint());
20248 }
20249
20250
20251  
20252  if ($this->updateWhitelist) {
20253 $currentPackages = $this->getCurrentPackages($installedRepo);
20254
20255
20256  $candidates = array();
20257 foreach ($links as $link) {
20258 $candidates[$link->getTarget()] = true;
20259 $rootRequires[$link->getTarget()] = $link;
20260 }
20261 foreach ($currentPackages as $package) {
20262 $candidates[$package->getName()] = true;
20263 }
20264
20265
20266  foreach ($candidates as $candidate => $dummy) {
20267 foreach ($currentPackages as $curPackage) {
20268 if ($curPackage->getName() === $candidate) {
20269 if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
20270 $constraint = new Constraint('=', $curPackage->getVersion());
20271 $description = $this->locker->isLocked() ? '(locked at' : '(installed at';
20272 $requiredAt = isset($rootRequires[$candidate]) ? ', required as ' . $rootRequires[$candidate]->getPrettyConstraint() : '';
20273 $constraint->setPrettyString($description . ' ' . $curPackage->getPrettyVersion() . $requiredAt . ')');
20274 $request->install($curPackage->getName(), $constraint);
20275 }
20276 break;
20277 }
20278 }
20279 }
20280 }
20281 } else {
20282 $this->io->writeError('<info>Installing dependencies'.($this->devMode ? ' (including require-dev)' : '').' from lock file</info>');
20283
20284 if (!$this->locker->isFresh()) {
20285 $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);
20286 }
20287
20288 foreach ($lockedRepository->getPackages() as $package) {
20289 $version = $package->getVersion();
20290 if (isset($aliases[$package->getName()][$version])) {
20291 $version = $aliases[$package->getName()][$version]['alias_normalized'];
20292 }
20293 $constraint = new Constraint('=', $version);
20294 $constraint->setPrettyString($package->getPrettyVersion());
20295 $request->install($package->getName(), $constraint);
20296 }
20297
20298 foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
20299 $request->install($link->getTarget(), $link->getConstraint());
20300 }
20301 }
20302
20303
20304  $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-links');
20305
20306
20307  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
20308 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
20309 try {
20310 $operations = $solver->solve($request, $this->ignorePlatformReqs);
20311 } catch (SolverProblemsException $e) {
20312 $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
20313 $this->io->writeError($e->getMessage());
20314 if ($this->update && !$this->devMode) {
20315 $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);
20316 }
20317
20318 return array(max(1, $e->getCode()), array());
20319 }
20320
20321
20322  $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-updates', $operations);
20323
20324 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
20325
20326 $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
20327 $this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies", true, IOInterface::VERBOSE);
20328
20329
20330  if (!$operations) {
20331 $this->io->writeError('Nothing to install or update');
20332 }
20333
20334 $operations = $this->movePluginsToFront($operations);
20335 $operations = $this->moveUninstallsToFront($operations);
20336
20337
20338  
20339  if ($this->update) {
20340 $devPackages = $this->extractDevPackages($operations, $localRepo, $platformRepo, $aliases);
20341 if (!$this->devMode) {
20342 $operations = $this->filterDevPackageOperations($devPackages, $operations, $localRepo);
20343 }
20344 } else {
20345 $devPackages = null;
20346 }
20347
20348 if ($operations) {
20349 $installs = $updates = $uninstalls = array();
20350 foreach ($operations as $operation) {
20351 if ($operation instanceof InstallOperation) {
20352 $installs[] = $operation->getPackage()->getPrettyName().':'.$operation->getPackage()->getFullPrettyVersion();
20353 } elseif ($operation instanceof UpdateOperation) {
20354 $updates[] = $operation->getTargetPackage()->getPrettyName().':'.$operation->getTargetPackage()->getFullPrettyVersion();
20355 } elseif ($operation instanceof UninstallOperation) {
20356 $uninstalls[] = $operation->getPackage()->getPrettyName();
20357 }
20358 }
20359
20360 $this->io->writeError(
20361 sprintf("<info>Package operations: %d install%s, %d update%s, %d removal%s</info>",
20362 count($installs),
20363 1 === count($installs) ? '' : 's',
20364 count($updates),
20365 1 === count($updates) ? '' : 's',
20366 count($uninstalls),
20367 1 === count($uninstalls) ? '' : 's')
20368 );
20369 if ($installs) {
20370 $this->io->writeError("Installs: ".implode(', ', $installs), true, IOInterface::VERBOSE);
20371 }
20372 if ($updates) {
20373 $this->io->writeError("Updates: ".implode(', ', $updates), true, IOInterface::VERBOSE);
20374 }
20375 if ($uninstalls) {
20376 $this->io->writeError("Removals: ".implode(', ', $uninstalls), true, IOInterface::VERBOSE);
20377 }
20378 }
20379
20380 foreach ($operations as $operation) {
20381
20382  if ('install' === $operation->getJobType()) {
20383 $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
20384 }
20385
20386
20387  if ($this->update) {
20388 $package = null;
20389 if ('update' === $operation->getJobType()) {
20390 $package = $operation->getTargetPackage();
20391 } elseif ('install' === $operation->getJobType()) {
20392 $package = $operation->getPackage();
20393 }
20394 if ($package && $package->isDev()) {
20395 $references = $this->package->getReferences();
20396 if (isset($references[$package->getName()])) {
20397 $this->updateInstallReferences($package, $references[$package->getName()]);
20398 }
20399 }
20400 if ('update' === $operation->getJobType()
20401 && $operation->getTargetPackage()->isDev()
20402 && $operation->getTargetPackage()->getVersion() === $operation->getInitialPackage()->getVersion()
20403 && (!$operation->getTargetPackage()->getSourceReference() || $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference())
20404 && (!$operation->getTargetPackage()->getDistReference() || $operation->getTargetPackage()->getDistReference() === $operation->getInitialPackage()->getDistReference())
20405 ) {
20406 $this->io->writeError('  - Skipping update of '. $operation->getTargetPackage()->getPrettyName().' to the same reference-locked version', true, IOInterface::DEBUG);
20407 $this->io->writeError('', true, IOInterface::DEBUG);
20408
20409 continue;
20410 }
20411 }
20412
20413 $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($operation->getJobType());
20414 if (defined($event) && $this->runScripts) {
20415 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20416 }
20417
20418
20419  if (!$this->executeOperations && false === strpos($operation->getJobType(), 'Alias')) {
20420 $this->io->writeError('  - ' . $operation);
20421 } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
20422 $this->io->writeError('  - ' . $operation);
20423 }
20424
20425 $this->installationManager->execute($localRepo, $operation);
20426
20427
20428  if ($this->verbose && $this->io->isVeryVerbose() && in_array($operation->getJobType(), array('install', 'update'))) {
20429 $reason = $operation->getReason();
20430 if ($reason instanceof Rule) {
20431 switch ($reason->getReason()) {
20432 case Rule::RULE_JOB_INSTALL:
20433 $this->io->writeError('    REASON: Required by the root package: '.$reason->getPrettyString($pool));
20434 $this->io->writeError('');
20435 break;
20436 case Rule::RULE_PACKAGE_REQUIRES:
20437 $this->io->writeError('    REASON: '.$reason->getPrettyString($pool));
20438 $this->io->writeError('');
20439 break;
20440 }
20441 }
20442 }
20443
20444 $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($operation->getJobType());
20445 if (defined($event) && $this->runScripts) {
20446 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20447 }
20448
20449 if ($this->executeOperations || $this->writeLock) {
20450 $localRepo->write();
20451 }
20452 }
20453
20454 if ($this->executeOperations) {
20455
20456  $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
20457 $localRepo->write();
20458 }
20459
20460 return array(0, $devPackages);
20461 }
20462
20463
20464
20465
20466
20467
20468
20469
20470
20471
20472
20473 private function extractDevPackages(array $operations, RepositoryInterface $localRepo, PlatformRepository $platformRepo, array $aliases)
20474 {
20475 if (!$this->package->getDevRequires()) {
20476 return array();
20477 }
20478
20479
20480  $tempLocalRepo = clone $localRepo;
20481 foreach ($operations as $operation) {
20482 switch ($operation->getJobType()) {
20483 case 'install':
20484 case 'markAliasInstalled':
20485 if (!$tempLocalRepo->hasPackage($operation->getPackage())) {
20486 $tempLocalRepo->addPackage(clone $operation->getPackage());
20487 }
20488 break;
20489
20490 case 'uninstall':
20491 case 'markAliasUninstalled':
20492 $tempLocalRepo->removePackage($operation->getPackage());
20493 break;
20494
20495 case 'update':
20496 $tempLocalRepo->removePackage($operation->getInitialPackage());
20497 if (!$tempLocalRepo->hasPackage($operation->getTargetPackage())) {
20498 $tempLocalRepo->addPackage(clone $operation->getTargetPackage());
20499 }
20500 break;
20501
20502 default:
20503 throw new \LogicException('Unknown type: '.$operation->getJobType());
20504 }
20505 }
20506
20507
20508  
20509  
20510  $localRepo = new InstalledArrayRepository(array());
20511 $loader = new ArrayLoader(null, true);
20512 $dumper = new ArrayDumper();
20513 foreach ($tempLocalRepo->getCanonicalPackages() as $pkg) {
20514 $localRepo->addPackage($loader->load($dumper->dump($pkg)));
20515 }
20516 unset($tempLocalRepo, $loader, $dumper);
20517
20518 $policy = $this->createPolicy();
20519 $pool = $this->createPool();
20520 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
20521 $pool->addRepository($installedRepo, $aliases);
20522
20523
20524  $request = $this->createRequest($this->package, $platformRepo);
20525 $request->updateAll();
20526 foreach ($this->package->getRequires() as $link) {
20527 $request->install($link->getTarget(), $link->getConstraint());
20528 }
20529
20530
20531  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
20532 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
20533 $ops = $solver->solve($request, $this->ignorePlatformReqs);
20534 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
20535
20536 $devPackages = array();
20537 foreach ($ops as $op) {
20538 if ($op->getJobType() === 'uninstall') {
20539 $devPackages[] = $op->getPackage();
20540 }
20541 }
20542
20543 return $devPackages;
20544 }
20545
20546
20547
20548
20549 private function filterDevPackageOperations(array $devPackages, array $operations, RepositoryInterface $localRepo)
20550 {
20551 $finalOps = array();
20552 $packagesToSkip = array();
20553 foreach ($devPackages as $pkg) {
20554 $packagesToSkip[$pkg->getName()] = true;
20555 if ($installedDevPkg = $localRepo->findPackage($pkg->getName(), '*')) {
20556 $finalOps[] = new UninstallOperation($installedDevPkg, 'non-dev install removing it');
20557 }
20558 }
20559
20560
20561  foreach ($operations as $op) {
20562 $package = $op->getJobType() === 'update' ? $op->getTargetPackage() : $op->getPackage();
20563 if (isset($packagesToSkip[$package->getName()])) {
20564 continue;
20565 }
20566
20567 $finalOps[] = $op;
20568 }
20569
20570 return $finalOps;
20571 }
20572
20573
20574
20575
20576
20577
20578
20579
20580
20581
20582
20583
20584
20585
20586 private function movePluginsToFront(array $operations)
20587 {
20588 $pluginsNoDeps = array();
20589 $pluginsWithDeps = array();
20590 $pluginRequires = array();
20591
20592 foreach (array_reverse($operations, true) as $idx => $op) {
20593 if ($op instanceof InstallOperation) {
20594 $package = $op->getPackage();
20595 } elseif ($op instanceof UpdateOperation) {
20596 $package = $op->getTargetPackage();
20597 } else {
20598 continue;
20599 }
20600
20601
20602  $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
20603
20604
20605  if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
20606
20607  $requires = array_filter(array_keys($package->getRequires()), function ($req) {
20608 return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
20609 });
20610
20611
20612  if ($isPlugin && !count($requires)) {
20613
20614  array_unshift($pluginsNoDeps, $op);
20615 } else {
20616
20617  $pluginRequires = array_merge($pluginRequires, $requires);
20618
20619  array_unshift($pluginsWithDeps, $op);
20620 }
20621
20622 unset($operations[$idx]);
20623 }
20624 }
20625
20626 return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
20627 }
20628
20629
20630
20631
20632
20633
20634
20635
20636 private function moveUninstallsToFront(array $operations)
20637 {
20638 $uninstOps = array();
20639 foreach ($operations as $idx => $op) {
20640 if ($op instanceof UninstallOperation) {
20641 $uninstOps[] = $op;
20642 unset($operations[$idx]);
20643 }
20644 }
20645
20646 return array_merge($uninstOps, $operations);
20647 }
20648
20649
20650
20651
20652 private function createInstalledRepo(RepositoryInterface $localRepo, PlatformRepository $platformRepo)
20653 {
20654
20655  
20656  
20657  $installedRootPackage = clone $this->package;
20658 $installedRootPackage->setRequires(array());
20659 $installedRootPackage->setDevRequires(array());
20660
20661 $repos = array(
20662 $localRepo,
20663 new InstalledArrayRepository(array($installedRootPackage)),
20664 $platformRepo,
20665 );
20666 $installedRepo = new CompositeRepository($repos);
20667 if ($this->additionalInstalledRepository) {
20668 $installedRepo->addRepository($this->additionalInstalledRepository);
20669 }
20670
20671 return $installedRepo;
20672 }
20673
20674
20675
20676
20677
20678 private function createPool(RepositoryInterface $lockedRepository = null)
20679 {
20680 if ($this->update) {
20681 $minimumStability = $this->package->getMinimumStability();
20682 $stabilityFlags = $this->package->getStabilityFlags();
20683
20684 $requires = array_merge($this->package->getRequires(), $this->package->getDevRequires());
20685 } else {
20686 $minimumStability = $this->locker->getMinimumStability();
20687 $stabilityFlags = $this->locker->getStabilityFlags();
20688
20689 $requires = array();
20690 foreach ($lockedRepository->getPackages() as $package) {
20691 $constraint = new Constraint('=', $package->getVersion());
20692 $constraint->setPrettyString($package->getPrettyVersion());
20693 $requires[$package->getName()] = $constraint;
20694 }
20695 }
20696
20697 $rootConstraints = array();
20698 foreach ($requires as $req => $constraint) {
20699
20700  if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
20701 continue;
20702 }
20703 if ($constraint instanceof Link) {
20704 $rootConstraints[$req] = $constraint->getConstraint();
20705 } else {
20706 $rootConstraints[$req] = $constraint;
20707 }
20708 }
20709
20710 return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
20711 }
20712
20713
20714
20715
20716 private function createPolicy()
20717 {
20718 $preferStable = null;
20719 $preferLowest = null;
20720 if (!$this->update) {
20721 $preferStable = $this->locker->getPreferStable();
20722 $preferLowest = $this->locker->getPreferLowest();
20723 }
20724
20725  
20726  if (null === $preferStable) {
20727 $preferStable = $this->preferStable || $this->package->getPreferStable();
20728 }
20729 if (null === $preferLowest) {
20730 $preferLowest = $this->preferLowest;
20731 }
20732
20733 return new DefaultPolicy($preferStable, $preferLowest);
20734 }
20735
20736
20737
20738
20739
20740
20741 private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
20742 {
20743 $request = new Request();
20744
20745 $constraint = new Constraint('=', $rootPackage->getVersion());
20746 $constraint->setPrettyString($rootPackage->getPrettyVersion());
20747 $request->install($rootPackage->getName(), $constraint);
20748
20749 $fixedPackages = $platformRepo->getPackages();
20750 if ($this->additionalInstalledRepository) {
20751 $additionalFixedPackages = $this->additionalInstalledRepository->getPackages();
20752 $fixedPackages = array_merge($fixedPackages, $additionalFixedPackages);
20753 }
20754
20755
20756  
20757  $provided = $rootPackage->getProvides();
20758 foreach ($fixedPackages as $package) {
20759 $constraint = new Constraint('=', $package->getVersion());
20760 $constraint->setPrettyString($package->getPrettyVersion());
20761
20762
20763  if ($package->getRepository() !== $platformRepo
20764 || !isset($provided[$package->getName()])
20765 || !$provided[$package->getName()]->getConstraint()->matches($constraint)
20766 ) {
20767 $request->fix($package->getName(), $constraint);
20768 }
20769 }
20770
20771 return $request;
20772 }
20773
20774
20775
20776
20777
20778
20779
20780
20781
20782
20783
20784
20785 private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $task, array $operations = null)
20786 {
20787 if ($task === 'force-updates' && null === $operations) {
20788 throw new \InvalidArgumentException('Missing operations argument');
20789 }
20790 if ($task === 'force-links') {
20791 $operations = array();
20792 }
20793
20794 if ($this->update && $this->updateWhitelist) {
20795 $currentPackages = $this->getCurrentPackages($installedRepo);
20796 }
20797
20798 foreach ($localRepo->getCanonicalPackages() as $package) {
20799
20800  if (!$package->isDev()) {
20801 continue;
20802 }
20803
20804
20805  foreach ($operations as $operation) {
20806 if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
20807 || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
20808 ) {
20809 continue 2;
20810 }
20811 }
20812
20813 if ($this->update) {
20814
20815  if ($this->updateWhitelist && !$this->isUpdateable($package)) {
20816
20817  foreach ($currentPackages as $curPackage) {
20818 if ($curPackage->isDev() && $curPackage->getName() === $package->getName() && $curPackage->getVersion() === $package->getVersion()) {
20819 if ($task === 'force-links') {
20820 $package->setRequires($curPackage->getRequires());
20821 $package->setConflicts($curPackage->getConflicts());
20822 $package->setProvides($curPackage->getProvides());
20823 $package->setReplaces($curPackage->getReplaces());
20824 } elseif ($task === 'force-updates') {
20825 if (($curPackage->getSourceReference() && $curPackage->getSourceReference() !== $package->getSourceReference())
20826 || ($curPackage->getDistReference() && $curPackage->getDistReference() !== $package->getDistReference())
20827 ) {
20828 $operations[] = new UpdateOperation($package, $curPackage);
20829 }
20830 }
20831
20832 break;
20833 }
20834 }
20835
20836 continue;
20837 }
20838
20839
20840  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
20841 foreach ($matches as $index => $match) {
20842
20843  if (!in_array($match->getRepository(), $repositories, true)) {
20844 unset($matches[$index]);
20845 continue;
20846 }
20847
20848
20849  if ($match->getName() !== $package->getName()) {
20850 unset($matches[$index]);
20851 continue;
20852 }
20853
20854 $matches[$index] = $match->getId();
20855 }
20856
20857
20858  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
20859 $newPackage = $pool->literalToPackage($matches[0]);
20860
20861 if ($task === 'force-links' && $newPackage) {
20862 $package->setRequires($newPackage->getRequires());
20863 $package->setConflicts($newPackage->getConflicts());
20864 $package->setProvides($newPackage->getProvides());
20865 $package->setReplaces($newPackage->getReplaces());
20866 }
20867
20868 if ($task === 'force-updates' && $newPackage && (
20869 (($newPackage->getSourceReference() && $newPackage->getSourceReference() !== $package->getSourceReference())
20870 || ($newPackage->getDistReference() && $newPackage->getDistReference() !== $package->getDistReference())
20871 )
20872 )) {
20873 $operations[] = new UpdateOperation($package, $newPackage);
20874
20875 continue;
20876 }
20877 }
20878
20879 if ($task === 'force-updates') {
20880
20881  $references = $this->package->getReferences();
20882
20883 if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
20884
20885  $operations[] = new UpdateOperation($package, clone $package);
20886 }
20887 }
20888 } else {
20889
20890  foreach ($lockedRepository->findPackages($package->getName()) as $lockedPackage) {
20891 if ($lockedPackage->isDev() && $lockedPackage->getVersion() === $package->getVersion()) {
20892 if ($task === 'force-links') {
20893 $package->setRequires($lockedPackage->getRequires());
20894 $package->setConflicts($lockedPackage->getConflicts());
20895 $package->setProvides($lockedPackage->getProvides());
20896 $package->setReplaces($lockedPackage->getReplaces());
20897 } elseif ($task === 'force-updates') {
20898 if (($lockedPackage->getSourceReference() && $lockedPackage->getSourceReference() !== $package->getSourceReference())
20899 || ($lockedPackage->getDistReference() && $lockedPackage->getDistReference() !== $package->getDistReference())
20900 ) {
20901 $operations[] = new UpdateOperation($package, $lockedPackage);
20902 }
20903 }
20904
20905 break;
20906 }
20907 }
20908 }
20909 }
20910
20911 return $operations;
20912 }
20913
20914
20915
20916
20917
20918
20919 private function getCurrentPackages($installedRepo)
20920 {
20921 if ($this->locker->isLocked()) {
20922 try {
20923 return $this->locker->getLockedRepository(true)->getPackages();
20924 } catch (\RuntimeException $e) {
20925
20926  return $this->locker->getLockedRepository()->getPackages();
20927 }
20928 }
20929
20930 return $installedRepo->getPackages();
20931 }
20932
20933
20934
20935
20936 private function getRootAliases()
20937 {
20938 if ($this->update) {
20939 $aliases = $this->package->getAliases();
20940 } else {
20941 $aliases = $this->locker->getAliases();
20942 }
20943
20944 $normalizedAliases = array();
20945
20946 foreach ($aliases as $alias) {
20947 $normalizedAliases[$alias['package']][$alias['version']] = array(
20948 'alias' => $alias['alias'],
20949 'alias_normalized' => $alias['alias_normalized'],
20950 );
20951 }
20952
20953 return $normalizedAliases;
20954 }
20955
20956
20957
20958
20959
20960
20961
20962 private function processPackageUrls($pool, $policy, $localRepo, $repositories)
20963 {
20964 if (!$this->update) {
20965 return;
20966 }
20967
20968 $rootRefs = $this->package->getReferences();
20969
20970 foreach ($localRepo->getCanonicalPackages() as $package) {
20971
20972  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
20973 foreach ($matches as $index => $match) {
20974
20975  if (!in_array($match->getRepository(), $repositories, true)) {
20976 unset($matches[$index]);
20977 continue;
20978 }
20979
20980
20981  if ($match->getName() !== $package->getName()) {
20982 unset($matches[$index]);
20983 continue;
20984 }
20985
20986 $matches[$index] = $match->getId();
20987 }
20988
20989
20990  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
20991 $newPackage = $pool->literalToPackage($matches[0]);
20992
20993
20994  $sourceUrl = $package->getSourceUrl();
20995 $newSourceUrl = $newPackage->getSourceUrl();
20996 $newReference = $newPackage->getSourceReference();
20997
20998 if ($package->isDev() && isset($rootRefs[$package->getName()]) && $package->getSourceReference() === $rootRefs[$package->getName()]) {
20999 $newReference = $rootRefs[$package->getName()];
21000 }
21001
21002 $this->updatePackageUrl($package, $newSourceUrl, $newPackage->getSourceType(), $newReference, $newPackage->getDistUrl());
21003
21004 if ($package instanceof CompletePackage && $newPackage instanceof CompletePackage) {
21005 $package->setAbandoned($newPackage->getReplacementPackage() ?: $newPackage->isAbandoned());
21006 }
21007
21008 $package->setDistMirrors($newPackage->getDistMirrors());
21009 $package->setSourceMirrors($newPackage->getSourceMirrors());
21010 }
21011 }
21012 }
21013
21014 private function updatePackageUrl(PackageInterface $package, $sourceUrl, $sourceType, $sourceReference, $distUrl)
21015 {
21016 $oldSourceRef = $package->getSourceReference();
21017
21018 if ($package->getSourceUrl() !== $sourceUrl) {
21019 $package->setSourceType($sourceType);
21020 $package->setSourceUrl($sourceUrl);
21021 $package->setSourceReference($sourceReference);
21022 }
21023
21024
21025  
21026  if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $distUrl)) {
21027 $package->setDistUrl($distUrl);
21028 $this->updateInstallReferences($package, $sourceReference);
21029 }
21030
21031 if ($this->updateWhitelist && !$this->isUpdateable($package)) {
21032 $this->updateInstallReferences($package, $oldSourceRef);
21033 }
21034 }
21035
21036 private function updateInstallReferences(PackageInterface $package, $reference)
21037 {
21038 if (!$reference) {
21039 return;
21040 }
21041
21042 $package->setSourceReference($reference);
21043
21044 if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $package->getDistUrl())) {
21045 $package->setDistReference($reference);
21046 $package->setDistUrl(preg_replace('{(?<=/)[a-f0-9]{40}(?=/|$)}i', $reference, $package->getDistUrl()));
21047 } elseif ($package->getDistReference()) { 
21048  $package->setDistReference($reference);
21049 }
21050 }
21051
21052
21053
21054
21055
21056 private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
21057 {
21058 foreach ($aliases as $package => $versions) {
21059 foreach ($versions as $version => $alias) {
21060 $packages = $platformRepo->findPackages($package, $version);
21061 foreach ($packages as $package) {
21062 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
21063 $aliasPackage->setRootPackageAlias(true);
21064 $platformRepo->addPackage($aliasPackage);
21065 }
21066 }
21067 }
21068 }
21069
21070
21071
21072
21073
21074 private function isUpdateable(PackageInterface $package)
21075 {
21076 if (!$this->updateWhitelist) {
21077 throw new \LogicException('isUpdateable should only be called when a whitelist is present');
21078 }
21079
21080 foreach ($this->updateWhitelist as $whiteListedPattern => $void) {
21081 $patternRegexp = $this->packageNameToRegexp($whiteListedPattern);
21082 if (preg_match($patternRegexp, $package->getName())) {
21083 return true;
21084 }
21085 }
21086
21087 return false;
21088 }
21089
21090
21091
21092
21093
21094
21095
21096 private function packageNameToRegexp($whiteListedPattern)
21097 {
21098 $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern));
21099
21100 return "{^" . $cleanedWhiteListedPattern . "$}i";
21101 }
21102
21103
21104
21105
21106
21107 private function extractPlatformRequirements($links)
21108 {
21109 $platformReqs = array();
21110 foreach ($links as $link) {
21111 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
21112 $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
21113 }
21114 }
21115
21116 return $platformReqs;
21117 }
21118
21119
21120
21121
21122
21123
21124
21125
21126
21127
21128
21129
21130
21131
21132 private function whitelistUpdateDependencies($localOrLockRepo, array $rootRequires, array $rootDevRequires)
21133 {
21134 if (!$this->updateWhitelist) {
21135 return;
21136 }
21137
21138 $rootRequires = array_merge($rootRequires, $rootDevRequires);
21139
21140 $requiredPackageNames = array();
21141 foreach ($rootRequires as $require) {
21142 $requiredPackageNames[] = $require->getTarget();
21143 }
21144
21145 $skipPackages = array();
21146 if (!$this->whitelistAllDependencies) {
21147 foreach ($rootRequires as $require) {
21148 $skipPackages[$require->getTarget()] = true;
21149 }
21150 }
21151
21152 $pool = new Pool('dev');
21153 $pool->addRepository($localOrLockRepo);
21154
21155 $seen = array();
21156
21157 $rootRequiredPackageNames = array_keys($rootRequires);
21158
21159 foreach ($this->updateWhitelist as $packageName => $void) {
21160 $packageQueue = new \SplQueue;
21161
21162 $depPackages = $pool->whatProvides($packageName);
21163
21164 $nameMatchesRequiredPackage = in_array($packageName, $requiredPackageNames, true);
21165
21166
21167  if (!$nameMatchesRequiredPackage) {
21168 $whitelistPatternRegexp = $this->packageNameToRegexp($packageName);
21169 foreach ($rootRequiredPackageNames as $rootRequiredPackageName) {
21170 if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) {
21171 $nameMatchesRequiredPackage = true;
21172 break;
21173 }
21174 }
21175 }
21176
21177 if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) {
21178 $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
21179 }
21180
21181 foreach ($depPackages as $depPackage) {
21182 $packageQueue->enqueue($depPackage);
21183 }
21184
21185 while (!$packageQueue->isEmpty()) {
21186 $package = $packageQueue->dequeue();
21187 if (isset($seen[$package->getId()])) {
21188 continue;
21189 }
21190
21191 $seen[$package->getId()] = true;
21192 $this->updateWhitelist[$package->getName()] = true;
21193
21194 if (!$this->whitelistDependencies && !$this->whitelistAllDependencies) {
21195 continue;
21196 }
21197
21198 $requires = $package->getRequires();
21199
21200 foreach ($requires as $require) {
21201 $requirePackages = $pool->whatProvides($require->getTarget());
21202
21203 foreach ($requirePackages as $requirePackage) {
21204 if (isset($this->updateWhitelist[$requirePackage->getName()])) {
21205 continue;
21206 }
21207
21208 if (isset($skipPackages[$requirePackage->getName()])) {
21209 $this->io->writeError('<warning>Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.</warning>');
21210 continue;
21211 }
21212
21213 $packageQueue->enqueue($requirePackage);
21214 }
21215 }
21216 }
21217 }
21218 }
21219
21220
21221
21222
21223
21224
21225
21226
21227 private function mockLocalRepositories(RepositoryManager $rm)
21228 {
21229 $packages = array();
21230 foreach ($rm->getLocalRepository()->getPackages() as $package) {
21231 $packages[(string) $package] = clone $package;
21232 }
21233 foreach ($packages as $key => $package) {
21234 if ($package instanceof AliasPackage) {
21235 $alias = (string) $package->getAliasOf();
21236 $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
21237 }
21238 }
21239 $rm->setLocalRepository(
21240 new InstalledArrayRepository($packages)
21241 );
21242 }
21243
21244
21245
21246
21247
21248
21249
21250
21251 public static function create(IOInterface $io, Composer $composer)
21252 {
21253 return new static(
21254 $io,
21255 $composer->getConfig(),
21256 $composer->getPackage(),
21257 $composer->getDownloadManager(),
21258 $composer->getRepositoryManager(),
21259 $composer->getLocker(),
21260 $composer->getInstallationManager(),
21261 $composer->getEventDispatcher(),
21262 $composer->getAutoloadGenerator()
21263 );
21264 }
21265
21266
21267
21268
21269
21270 public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
21271 {
21272 $this->additionalInstalledRepository = $additionalInstalledRepository;
21273
21274 return $this;
21275 }
21276
21277
21278
21279
21280
21281
21282
21283 public function setDryRun($dryRun = true)
21284 {
21285 $this->dryRun = (bool) $dryRun;
21286
21287 return $this;
21288 }
21289
21290
21291
21292
21293
21294
21295 public function isDryRun()
21296 {
21297 return $this->dryRun;
21298 }
21299
21300
21301
21302
21303
21304
21305
21306 public function setPreferSource($preferSource = true)
21307 {
21308 $this->preferSource = (bool) $preferSource;
21309
21310 return $this;
21311 }
21312
21313
21314
21315
21316
21317
21318
21319 public function setPreferDist($preferDist = true)
21320 {
21321 $this->preferDist = (bool) $preferDist;
21322
21323 return $this;
21324 }
21325
21326
21327
21328
21329
21330
21331
21332 public function setOptimizeAutoloader($optimizeAutoloader = false)
21333 {
21334 $this->optimizeAutoloader = (bool) $optimizeAutoloader;
21335 if (!$this->optimizeAutoloader) {
21336
21337  
21338  $this->setClassMapAuthoritative(false);
21339 }
21340
21341 return $this;
21342 }
21343
21344
21345
21346
21347
21348
21349
21350
21351 public function setClassMapAuthoritative($classMapAuthoritative = false)
21352 {
21353 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
21354 if ($this->classMapAuthoritative) {
21355
21356  $this->setOptimizeAutoloader(true);
21357 }
21358
21359 return $this;
21360 }
21361
21362
21363
21364
21365
21366
21367
21368 public function setApcuAutoloader($apcuAutoloader = false)
21369 {
21370 $this->apcuAutoloader = (bool) $apcuAutoloader;
21371
21372 return $this;
21373 }
21374
21375
21376
21377
21378
21379
21380
21381 public function setUpdate($update = true)
21382 {
21383 $this->update = (bool) $update;
21384
21385 return $this;
21386 }
21387
21388
21389
21390
21391
21392
21393
21394 public function setDevMode($devMode = true)
21395 {
21396 $this->devMode = (bool) $devMode;
21397
21398 return $this;
21399 }
21400
21401
21402
21403
21404
21405
21406
21407
21408
21409 public function setDumpAutoloader($dumpAutoloader = true)
21410 {
21411 $this->dumpAutoloader = (bool) $dumpAutoloader;
21412
21413 return $this;
21414 }
21415
21416
21417
21418
21419
21420
21421
21422
21423
21424 public function setRunScripts($runScripts = true)
21425 {
21426 $this->runScripts = (bool) $runScripts;
21427
21428 return $this;
21429 }
21430
21431
21432
21433
21434
21435
21436
21437 public function setConfig(Config $config)
21438 {
21439 $this->config = $config;
21440
21441 return $this;
21442 }
21443
21444
21445
21446
21447
21448
21449
21450 public function setVerbose($verbose = true)
21451 {
21452 $this->verbose = (bool) $verbose;
21453
21454 return $this;
21455 }
21456
21457
21458
21459
21460
21461
21462 public function isVerbose()
21463 {
21464 return $this->verbose;
21465 }
21466
21467
21468
21469
21470
21471
21472
21473 public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
21474 {
21475 $this->ignorePlatformReqs = (bool) $ignorePlatformReqs;
21476
21477 return $this;
21478 }
21479
21480
21481
21482
21483
21484
21485
21486
21487 public function setUpdateWhitelist(array $packages)
21488 {
21489 $this->updateWhitelist = array_flip(array_map('strtolower', $packages));
21490
21491 return $this;
21492 }
21493
21494
21495
21496
21497 public function setWhitelistDependencies($updateDependencies = true)
21498 {
21499 return $this->setWhitelistTransitiveDependencies($updateDependencies);
21500 }
21501
21502
21503
21504
21505
21506
21507
21508
21509
21510
21511 public function setWhitelistTransitiveDependencies($updateTransitiveDependencies = true)
21512 {
21513 $this->whitelistDependencies = (bool) $updateTransitiveDependencies;
21514
21515 return $this;
21516 }
21517
21518
21519
21520
21521
21522
21523
21524
21525
21526
21527 public function setWhitelistAllDependencies($updateAllDependencies = true)
21528 {
21529 $this->whitelistAllDependencies = (bool) $updateAllDependencies;
21530
21531 return $this;
21532 }
21533
21534
21535
21536
21537
21538
21539
21540 public function setPreferStable($preferStable = true)
21541 {
21542 $this->preferStable = (bool) $preferStable;
21543
21544 return $this;
21545 }
21546
21547
21548
21549
21550
21551
21552
21553 public function setPreferLowest($preferLowest = true)
21554 {
21555 $this->preferLowest = (bool) $preferLowest;
21556
21557 return $this;
21558 }
21559
21560
21561
21562
21563
21564
21565
21566
21567
21568 public function setWriteLock($writeLock = true)
21569 {
21570 $this->writeLock = (bool) $writeLock;
21571
21572 return $this;
21573 }
21574
21575
21576
21577
21578
21579
21580
21581
21582
21583 public function setExecuteOperations($executeOperations = true)
21584 {
21585 $this->executeOperations = (bool) $executeOperations;
21586
21587 return $this;
21588 }
21589
21590
21591
21592
21593
21594
21595
21596 public function setSkipSuggest($skipSuggest = true)
21597 {
21598 $this->skipSuggest = (bool) $skipSuggest;
21599
21600 return $this;
21601 }
21602
21603
21604
21605
21606
21607
21608
21609
21610
21611
21612 public function disablePlugins()
21613 {
21614 $this->installationManager->disablePlugins();
21615
21616 return $this;
21617 }
21618
21619
21620
21621
21622
21623 public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter)
21624 {
21625 $this->suggestedPackagesReporter = $suggestedPackagesReporter;
21626
21627 return $this;
21628 }
21629 }
21630 <?php
21631
21632
21633
21634
21635
21636
21637
21638
21639
21640
21641
21642 namespace Composer\Installer;
21643
21644 use Composer\IO\IOInterface;
21645 use Composer\Package\PackageInterface;
21646 use Composer\Util\Filesystem;
21647 use Composer\Util\Platform;
21648 use Composer\Util\ProcessExecutor;
21649 use Composer\Util\Silencer;
21650
21651
21652
21653
21654
21655
21656
21657
21658 class BinaryInstaller
21659 {
21660 protected $binDir;
21661 protected $binCompat;
21662 protected $io;
21663 protected $filesystem;
21664
21665
21666
21667
21668
21669
21670
21671 public function __construct(IOInterface $io, $binDir, $binCompat, Filesystem $filesystem = null)
21672 {
21673 $this->binDir = $binDir;
21674 $this->binCompat = $binCompat;
21675 $this->io = $io;
21676 $this->filesystem = $filesystem ?: new Filesystem();
21677 }
21678
21679 public function installBinaries(PackageInterface $package, $installPath, $warnOnOverwrite = true)
21680 {
21681 $binaries = $this->getBinaries($package);
21682 if (!$binaries) {
21683 return;
21684 }
21685 foreach ($binaries as $bin) {
21686 $binPath = $installPath.'/'.$bin;
21687 if (!file_exists($binPath)) {
21688 $this->io->writeError('    <warning>Skipped installation of bin '.$bin.' for package '.$package->getName().': file not found in package</warning>');
21689 continue;
21690 }
21691
21692
21693  
21694  
21695  
21696  $binPath = realpath($binPath);
21697
21698 $this->initializeBinDir();
21699 $link = $this->binDir.'/'.basename($bin);
21700 if (file_exists($link)) {
21701 if (is_link($link)) {
21702
21703  
21704  
21705  Silencer::call('chmod', $link, 0777 & ~umask());
21706 }
21707 if ($warnOnOverwrite) {
21708 $this->io->writeError('    Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
21709 }
21710 continue;
21711 }
21712
21713 if ($this->binCompat === "auto") {
21714 if (Platform::isWindows()) {
21715 $this->installFullBinaries($binPath, $link, $bin, $package);
21716 } else {
21717 $this->installSymlinkBinaries($binPath, $link);
21718 }
21719 } elseif ($this->binCompat === "full") {
21720 $this->installFullBinaries($binPath, $link, $bin, $package);
21721 }
21722 Silencer::call('chmod', $link, 0777 & ~umask());
21723 }
21724 }
21725
21726 public function removeBinaries(PackageInterface $package)
21727 {
21728 $this->initializeBinDir();
21729
21730 $binaries = $this->getBinaries($package);
21731 if (!$binaries) {
21732 return;
21733 }
21734 foreach ($binaries as $bin) {
21735 $link = $this->binDir.'/'.basename($bin);
21736 if (is_link($link) || file_exists($link)) {
21737 $this->filesystem->unlink($link);
21738 }
21739 if (file_exists($link.'.bat')) {
21740 $this->filesystem->unlink($link.'.bat');
21741 }
21742 }
21743
21744
21745  if ((is_dir($this->binDir)) && ($this->filesystem->isDirEmpty($this->binDir))) {
21746 Silencer::call('rmdir', $this->binDir);
21747 }
21748 }
21749
21750 public static function determineBinaryCaller($bin)
21751 {
21752 if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
21753 return 'call';
21754 }
21755
21756 $handle = fopen($bin, 'r');
21757 $line = fgets($handle);
21758 fclose($handle);
21759 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
21760 return trim($match[1]);
21761 }
21762
21763 return 'php';
21764 }
21765
21766 protected function getBinaries(PackageInterface $package)
21767 {
21768 return $package->getBinaries();
21769 }
21770
21771 protected function installFullBinaries($binPath, $link, $bin, PackageInterface $package)
21772 {
21773
21774  if ('.bat' !== substr($binPath, -4)) {
21775 $this->installUnixyProxyBinaries($binPath, $link);
21776 @chmod($link, 0777 & ~umask());
21777 $link .= '.bat';
21778 if (file_exists($link)) {
21779 $this->io->writeError('    Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
21780 }
21781 }
21782 if (!file_exists($link)) {
21783 file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
21784 }
21785 }
21786
21787 protected function installSymlinkBinaries($binPath, $link)
21788 {
21789 if (!$this->filesystem->relativeSymlink($binPath, $link)) {
21790 $this->installUnixyProxyBinaries($binPath, $link);
21791 }
21792 }
21793
21794 protected function installUnixyProxyBinaries($binPath, $link)
21795 {
21796 file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
21797 }
21798
21799 protected function initializeBinDir()
21800 {
21801 $this->filesystem->ensureDirectoryExists($this->binDir);
21802 $this->binDir = realpath($this->binDir);
21803 }
21804
21805 protected function generateWindowsProxyCode($bin, $link)
21806 {
21807 $binPath = $this->filesystem->findShortestPath($link, $bin);
21808 $caller = self::determineBinaryCaller($bin);
21809
21810 return "@ECHO OFF\r\n".
21811 "setlocal DISABLEDELAYEDEXPANSION\r\n".
21812 "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"\'')."\r\n".
21813 "{$caller} \"%BIN_TARGET%\" %*\r\n";
21814 }
21815
21816 protected function generateUnixyProxyCode($bin, $link)
21817 {
21818 $binPath = $this->filesystem->findShortestPath($link, $bin);
21819
21820 $binDir = ProcessExecutor::escape(dirname($binPath));
21821 $binFile = basename($binPath);
21822
21823 $proxyCode = <<<PROXY
21824 #!/usr/bin/env sh
21825
21826 dir=\$(cd "\${0%[/\\\\]*}" > /dev/null; cd $binDir && pwd)
21827
21828 if [ -d /proc/cygdrive ] && [[ \$(which php) == \$(readlink -n /proc/cygdrive)/* ]]; then
21829    # We are in Cgywin using Windows php, so the path must be translated
21830    dir=\$(cygpath -m "\$dir");
21831 fi
21832
21833 "\${dir}/$binFile" "\$@"
21834
21835 PROXY;
21836
21837 return $proxyCode;
21838 }
21839 }
21840 <?php
21841
21842
21843
21844
21845
21846
21847
21848
21849
21850
21851
21852 namespace Composer\Installer;
21853
21854 use Composer\Package\PackageInterface;
21855
21856
21857
21858
21859
21860
21861 interface BinaryPresenceInterface
21862 {
21863
21864
21865
21866
21867
21868 public function ensureBinariesPresence(PackageInterface $package);
21869 }
21870 <?php
21871
21872
21873
21874
21875
21876
21877
21878
21879
21880
21881
21882 namespace Composer\Installer;
21883
21884 use Composer\IO\IOInterface;
21885 use Composer\Package\PackageInterface;
21886 use Composer\Package\AliasPackage;
21887 use Composer\Repository\RepositoryInterface;
21888 use Composer\Repository\InstalledRepositoryInterface;
21889 use Composer\DependencyResolver\Operation\OperationInterface;
21890 use Composer\DependencyResolver\Operation\InstallOperation;
21891 use Composer\DependencyResolver\Operation\UpdateOperation;
21892 use Composer\DependencyResolver\Operation\UninstallOperation;
21893 use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
21894 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
21895 use Composer\Util\StreamContextFactory;
21896
21897
21898
21899
21900
21901
21902
21903
21904 class InstallationManager
21905 {
21906 private $installers = array();
21907 private $cache = array();
21908 private $notifiablePackages = array();
21909
21910 public function reset()
21911 {
21912 $this->notifiablePackages = array();
21913 }
21914
21915
21916
21917
21918
21919
21920 public function addInstaller(InstallerInterface $installer)
21921 {
21922 array_unshift($this->installers, $installer);
21923 $this->cache = array();
21924 }
21925
21926
21927
21928
21929
21930
21931 public function removeInstaller(InstallerInterface $installer)
21932 {
21933 if (false !== ($key = array_search($installer, $this->installers, true))) {
21934 array_splice($this->installers, $key, 1);
21935 $this->cache = array();
21936 }
21937 }
21938
21939
21940
21941
21942
21943
21944
21945
21946 public function disablePlugins()
21947 {
21948 foreach ($this->installers as $i => $installer) {
21949 if (!$installer instanceof PluginInstaller) {
21950 continue;
21951 }
21952
21953 unset($this->installers[$i]);
21954 }
21955 }
21956
21957
21958
21959
21960
21961
21962
21963
21964
21965 public function getInstaller($type)
21966 {
21967 $type = strtolower($type);
21968
21969 if (isset($this->cache[$type])) {
21970 return $this->cache[$type];
21971 }
21972
21973 foreach ($this->installers as $installer) {
21974 if ($installer->supports($type)) {
21975 return $this->cache[$type] = $installer;
21976 }
21977 }
21978
21979 throw new \InvalidArgumentException('Unknown installer type: '.$type);
21980 }
21981
21982
21983
21984
21985
21986
21987
21988
21989
21990 public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
21991 {
21992 if ($package instanceof AliasPackage) {
21993 return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
21994 }
21995
21996 return $this->getInstaller($package->getType())->isInstalled($repo, $package);
21997 }
21998
21999
22000
22001
22002
22003
22004
22005 public function ensureBinariesPresence(PackageInterface $package)
22006 {
22007 try {
22008 $installer = $this->getInstaller($package->getType());
22009 } catch (\InvalidArgumentException $e) {
22010
22011  return;
22012 }
22013
22014
22015  if ($installer instanceof BinaryPresenceInterface) {
22016 $installer->ensureBinariesPresence($package);
22017 }
22018 }
22019
22020
22021
22022
22023
22024
22025
22026 public function execute(RepositoryInterface $repo, OperationInterface $operation)
22027 {
22028 $method = $operation->getJobType();
22029 $this->$method($repo, $operation);
22030 }
22031
22032
22033
22034
22035
22036
22037
22038 public function install(RepositoryInterface $repo, InstallOperation $operation)
22039 {
22040 $package = $operation->getPackage();
22041 $installer = $this->getInstaller($package->getType());
22042 $installer->install($repo, $package);
22043 $this->markForNotification($package);
22044 }
22045
22046
22047
22048
22049
22050
22051
22052 public function update(RepositoryInterface $repo, UpdateOperation $operation)
22053 {
22054 $initial = $operation->getInitialPackage();
22055 $target = $operation->getTargetPackage();
22056
22057 $initialType = $initial->getType();
22058 $targetType = $target->getType();
22059
22060 if ($initialType === $targetType) {
22061 $installer = $this->getInstaller($initialType);
22062 $installer->update($repo, $initial, $target);
22063 $this->markForNotification($target);
22064 } else {
22065 $this->getInstaller($initialType)->uninstall($repo, $initial);
22066 $this->getInstaller($targetType)->install($repo, $target);
22067 }
22068 }
22069
22070
22071
22072
22073
22074
22075
22076 public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
22077 {
22078 $package = $operation->getPackage();
22079 $installer = $this->getInstaller($package->getType());
22080 $installer->uninstall($repo, $package);
22081 }
22082
22083
22084
22085
22086
22087
22088
22089 public function markAliasInstalled(RepositoryInterface $repo, MarkAliasInstalledOperation $operation)
22090 {
22091 $package = $operation->getPackage();
22092
22093 if (!$repo->hasPackage($package)) {
22094 $repo->addPackage(clone $package);
22095 }
22096 }
22097
22098
22099
22100
22101
22102
22103
22104 public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
22105 {
22106 $package = $operation->getPackage();
22107
22108 $repo->removePackage($package);
22109 }
22110
22111
22112
22113
22114
22115
22116
22117 public function getInstallPath(PackageInterface $package)
22118 {
22119 $installer = $this->getInstaller($package->getType());
22120
22121 return $installer->getInstallPath($package);
22122 }
22123
22124 public function notifyInstalls(IOInterface $io)
22125 {
22126 foreach ($this->notifiablePackages as $repoUrl => $packages) {
22127 $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
22128 if ($io->hasAuthentication($repositoryName)) {
22129 $auth = $io->getAuthentication($repositoryName);
22130 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
22131 $authHeader = 'Authorization: Basic '.$authStr;
22132 }
22133
22134
22135  if (strpos($repoUrl, '%package%')) {
22136 foreach ($packages as $package) {
22137 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
22138
22139 $params = array(
22140 'version' => $package->getPrettyVersion(),
22141 'version_normalized' => $package->getVersion(),
22142 );
22143 $opts = array('http' =>
22144 array(
22145 'method' => 'POST',
22146 'header' => array('Content-type: application/x-www-form-urlencoded'),
22147 'content' => http_build_query($params, '', '&'),
22148 'timeout' => 3,
22149 ),
22150 );
22151 if (isset($authHeader)) {
22152 $opts['http']['header'][] = $authHeader;
22153 }
22154
22155 $context = StreamContextFactory::getContext($url, $opts);
22156 @file_get_contents($url, false, $context);
22157 }
22158
22159 continue;
22160 }
22161
22162 $postData = array('downloads' => array());
22163 foreach ($packages as $package) {
22164 $postData['downloads'][] = array(
22165 'name' => $package->getPrettyName(),
22166 'version' => $package->getVersion(),
22167 );
22168 }
22169
22170 $opts = array('http' =>
22171 array(
22172 'method' => 'POST',
22173 'header' => array('Content-Type: application/json'),
22174 'content' => json_encode($postData),
22175 'timeout' => 6,
22176 ),
22177 );
22178 if (isset($authHeader)) {
22179 $opts['http']['header'][] = $authHeader;
22180 }
22181
22182 $context = StreamContextFactory::getContext($repoUrl, $opts);
22183 @file_get_contents($repoUrl, false, $context);
22184 }
22185
22186 $this->reset();
22187 }
22188
22189 private function markForNotification(PackageInterface $package)
22190 {
22191 if ($package->getNotificationUrl()) {
22192 $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
22193 }
22194 }
22195 }
22196 <?php
22197
22198
22199
22200
22201
22202
22203
22204
22205
22206
22207
22208 namespace Composer\Installer;
22209
22210 use Composer\Composer;
22211 use Composer\DependencyResolver\PolicyInterface;
22212 use Composer\DependencyResolver\Operation\OperationInterface;
22213 use Composer\DependencyResolver\Pool;
22214 use Composer\DependencyResolver\Request;
22215 use Composer\EventDispatcher\Event;
22216 use Composer\IO\IOInterface;
22217 use Composer\Repository\CompositeRepository;
22218
22219
22220
22221
22222
22223
22224 class InstallerEvent extends Event
22225 {
22226
22227
22228
22229 private $composer;
22230
22231
22232
22233
22234 private $io;
22235
22236
22237
22238
22239 private $devMode;
22240
22241
22242
22243
22244 private $policy;
22245
22246
22247
22248
22249 private $pool;
22250
22251
22252
22253
22254 private $installedRepo;
22255
22256
22257
22258
22259 private $request;
22260
22261
22262
22263
22264 private $operations;
22265
22266
22267
22268
22269
22270
22271
22272
22273
22274
22275
22276
22277
22278
22279 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
22280 {
22281 parent::__construct($eventName);
22282
22283 $this->composer = $composer;
22284 $this->io = $io;
22285 $this->devMode = $devMode;
22286 $this->policy = $policy;
22287 $this->pool = $pool;
22288 $this->installedRepo = $installedRepo;
22289 $this->request = $request;
22290 $this->operations = $operations;
22291 }
22292
22293
22294
22295
22296 public function getComposer()
22297 {
22298 return $this->composer;
22299 }
22300
22301
22302
22303
22304 public function getIO()
22305 {
22306 return $this->io;
22307 }
22308
22309
22310
22311
22312 public function isDevMode()
22313 {
22314 return $this->devMode;
22315 }
22316
22317
22318
22319
22320 public function getPolicy()
22321 {
22322 return $this->policy;
22323 }
22324
22325
22326
22327
22328 public function getPool()
22329 {
22330 return $this->pool;
22331 }
22332
22333
22334
22335
22336 public function getInstalledRepo()
22337 {
22338 return $this->installedRepo;
22339 }
22340
22341
22342
22343
22344 public function getRequest()
22345 {
22346 return $this->request;
22347 }
22348
22349
22350
22351
22352 public function getOperations()
22353 {
22354 return $this->operations;
22355 }
22356 }
22357 <?php
22358
22359
22360
22361
22362
22363
22364
22365
22366
22367
22368
22369 namespace Composer\Installer;
22370
22371
22372
22373
22374
22375
22376 class InstallerEvents
22377 {
22378
22379
22380
22381
22382
22383
22384
22385
22386
22387 const PRE_DEPENDENCIES_SOLVING = 'pre-dependencies-solving';
22388
22389
22390
22391
22392
22393
22394
22395
22396
22397
22398 const POST_DEPENDENCIES_SOLVING = 'post-dependencies-solving';
22399 }
22400 <?php
22401
22402
22403
22404
22405
22406
22407
22408
22409
22410
22411
22412 namespace Composer\Installer;
22413
22414 use Composer\Package\PackageInterface;
22415 use Composer\Repository\InstalledRepositoryInterface;
22416 use InvalidArgumentException;
22417
22418
22419
22420
22421
22422
22423
22424 interface InstallerInterface
22425 {
22426
22427
22428
22429
22430
22431
22432 public function supports($packageType);
22433
22434
22435
22436
22437
22438
22439
22440
22441
22442 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
22443
22444
22445
22446
22447
22448
22449
22450 public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
22451
22452
22453
22454
22455
22456
22457
22458
22459
22460
22461 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
22462
22463
22464
22465
22466
22467
22468
22469 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
22470
22471
22472
22473
22474
22475
22476
22477 public function getInstallPath(PackageInterface $package);
22478 }
22479 <?php
22480
22481
22482
22483
22484
22485
22486
22487
22488
22489
22490
22491 namespace Composer\Installer;
22492
22493 use Composer\Composer;
22494 use Composer\IO\IOInterface;
22495 use Composer\Repository\InstalledRepositoryInterface;
22496 use Composer\Package\PackageInterface;
22497 use Composer\Util\Filesystem;
22498 use Composer\Util\Silencer;
22499
22500
22501
22502
22503
22504
22505
22506 class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
22507 {
22508 protected $composer;
22509 protected $vendorDir;
22510 protected $binDir;
22511 protected $downloadManager;
22512 protected $io;
22513 protected $type;
22514 protected $filesystem;
22515 protected $binCompat;
22516 protected $binaryInstaller;
22517
22518
22519
22520
22521
22522
22523
22524
22525
22526
22527 public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null, BinaryInstaller $binaryInstaller = null)
22528 {
22529 $this->composer = $composer;
22530 $this->downloadManager = $composer->getDownloadManager();
22531 $this->io = $io;
22532 $this->type = $type;
22533
22534 $this->filesystem = $filesystem ?: new Filesystem();
22535 $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
22536 $this->binaryInstaller = $binaryInstaller ?: new BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem);
22537 }
22538
22539
22540
22541
22542 public function supports($packageType)
22543 {
22544 return $packageType === $this->type || null === $this->type;
22545 }
22546
22547
22548
22549
22550 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22551 {
22552 return $repo->hasPackage($package) && is_readable($this->getInstallPath($package));
22553 }
22554
22555
22556
22557
22558 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22559 {
22560 $this->initializeVendorDir();
22561 $downloadPath = $this->getInstallPath($package);
22562
22563
22564  if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
22565 $this->binaryInstaller->removeBinaries($package);
22566 }
22567
22568 $this->installCode($package);
22569 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package));
22570 if (!$repo->hasPackage($package)) {
22571 $repo->addPackage(clone $package);
22572 }
22573 }
22574
22575
22576
22577
22578 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22579 {
22580 if (!$repo->hasPackage($initial)) {
22581 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22582 }
22583
22584 $this->initializeVendorDir();
22585
22586 $this->binaryInstaller->removeBinaries($initial);
22587 $this->updateCode($initial, $target);
22588 $this->binaryInstaller->installBinaries($target, $this->getInstallPath($target));
22589 $repo->removePackage($initial);
22590 if (!$repo->hasPackage($target)) {
22591 $repo->addPackage(clone $target);
22592 }
22593 }
22594
22595
22596
22597
22598 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22599 {
22600 if (!$repo->hasPackage($package)) {
22601 throw new \InvalidArgumentException('Package is not installed: '.$package);
22602 }
22603
22604 $this->removeCode($package);
22605 $this->binaryInstaller->removeBinaries($package);
22606 $repo->removePackage($package);
22607
22608 $downloadPath = $this->getPackageBasePath($package);
22609 if (strpos($package->getName(), '/')) {
22610 $packageVendorDir = dirname($downloadPath);
22611 if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
22612 Silencer::call('rmdir', $packageVendorDir);
22613 }
22614 }
22615 }
22616
22617
22618
22619
22620 public function getInstallPath(PackageInterface $package)
22621 {
22622 $this->initializeVendorDir();
22623
22624 $basePath = ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
22625 $targetDir = $package->getTargetDir();
22626
22627 return $basePath . ($targetDir ? '/'.$targetDir : '');
22628 }
22629
22630
22631
22632
22633
22634
22635 public function ensureBinariesPresence(PackageInterface $package)
22636 {
22637 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), false);
22638 }
22639
22640
22641
22642
22643
22644
22645
22646
22647
22648
22649 protected function getPackageBasePath(PackageInterface $package)
22650 {
22651 $installPath = $this->getInstallPath($package);
22652 $targetDir = $package->getTargetDir();
22653
22654 if ($targetDir) {
22655 return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath);
22656 }
22657
22658 return $installPath;
22659 }
22660
22661 protected function installCode(PackageInterface $package)
22662 {
22663 $downloadPath = $this->getInstallPath($package);
22664 $this->downloadManager->download($package, $downloadPath);
22665 }
22666
22667 protected function updateCode(PackageInterface $initial, PackageInterface $target)
22668 {
22669 $initialDownloadPath = $this->getInstallPath($initial);
22670 $targetDownloadPath = $this->getInstallPath($target);
22671 if ($targetDownloadPath !== $initialDownloadPath) {
22672
22673  
22674  if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
22675 || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
22676 ) {
22677 $this->removeCode($initial);
22678 $this->installCode($target);
22679
22680 return;
22681 }
22682
22683 $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
22684 }
22685 $this->downloadManager->update($initial, $target, $targetDownloadPath);
22686 }
22687
22688 protected function removeCode(PackageInterface $package)
22689 {
22690 $downloadPath = $this->getPackageBasePath($package);
22691 $this->downloadManager->remove($package, $downloadPath);
22692 }
22693
22694 protected function initializeVendorDir()
22695 {
22696 $this->filesystem->ensureDirectoryExists($this->vendorDir);
22697 $this->vendorDir = realpath($this->vendorDir);
22698 }
22699 }
22700 <?php
22701
22702
22703
22704
22705
22706
22707
22708
22709
22710
22711
22712 namespace Composer\Installer;
22713
22714 use Composer\Repository\InstalledRepositoryInterface;
22715 use Composer\Package\PackageInterface;
22716
22717
22718
22719
22720
22721
22722 class MetapackageInstaller implements InstallerInterface
22723 {
22724
22725
22726
22727 public function supports($packageType)
22728 {
22729 return $packageType === 'metapackage';
22730 }
22731
22732
22733
22734
22735 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22736 {
22737 return $repo->hasPackage($package);
22738 }
22739
22740
22741
22742
22743 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22744 {
22745 $repo->addPackage(clone $package);
22746 }
22747
22748
22749
22750
22751 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22752 {
22753 if (!$repo->hasPackage($initial)) {
22754 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22755 }
22756
22757 $repo->removePackage($initial);
22758 $repo->addPackage(clone $target);
22759 }
22760
22761
22762
22763
22764 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22765 {
22766 if (!$repo->hasPackage($package)) {
22767 throw new \InvalidArgumentException('Package is not installed: '.$package);
22768 }
22769
22770 $repo->removePackage($package);
22771 }
22772
22773
22774
22775
22776 public function getInstallPath(PackageInterface $package)
22777 {
22778 return '';
22779 }
22780 }
22781 <?php
22782
22783
22784
22785
22786
22787
22788
22789
22790
22791
22792
22793 namespace Composer\Installer;
22794
22795 use Composer\Repository\InstalledRepositoryInterface;
22796 use Composer\Package\PackageInterface;
22797
22798
22799
22800
22801
22802
22803
22804
22805 class NoopInstaller implements InstallerInterface
22806 {
22807
22808
22809
22810 public function supports($packageType)
22811 {
22812 return true;
22813 }
22814
22815
22816
22817
22818 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22819 {
22820 return $repo->hasPackage($package);
22821 }
22822
22823
22824
22825
22826 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22827 {
22828 if (!$repo->hasPackage($package)) {
22829 $repo->addPackage(clone $package);
22830 }
22831 }
22832
22833
22834
22835
22836 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22837 {
22838 if (!$repo->hasPackage($initial)) {
22839 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22840 }
22841
22842 $repo->removePackage($initial);
22843 if (!$repo->hasPackage($target)) {
22844 $repo->addPackage(clone $target);
22845 }
22846 }
22847
22848
22849
22850
22851 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22852 {
22853 if (!$repo->hasPackage($package)) {
22854 throw new \InvalidArgumentException('Package is not installed: '.$package);
22855 }
22856 $repo->removePackage($package);
22857 }
22858
22859
22860
22861
22862 public function getInstallPath(PackageInterface $package)
22863 {
22864 $targetDir = $package->getTargetDir();
22865
22866 return $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
22867 }
22868 }
22869 <?php
22870
22871
22872
22873
22874
22875
22876
22877
22878
22879
22880
22881 namespace Composer\Installer;
22882
22883 use Composer\Composer;
22884 use Composer\IO\IOInterface;
22885 use Composer\DependencyResolver\Operation\OperationInterface;
22886 use Composer\DependencyResolver\PolicyInterface;
22887 use Composer\DependencyResolver\Pool;
22888 use Composer\DependencyResolver\Request;
22889 use Composer\Repository\CompositeRepository;
22890
22891
22892
22893
22894
22895
22896 class PackageEvent extends InstallerEvent
22897 {
22898
22899
22900
22901 private $operation;
22902
22903
22904
22905
22906
22907
22908
22909
22910
22911
22912
22913
22914
22915
22916
22917 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
22918 {
22919 parent::__construct($eventName, $composer, $io, $devMode, $policy, $pool, $installedRepo, $request, $operations);
22920
22921 $this->operation = $operation;
22922 }
22923
22924
22925
22926
22927
22928
22929 public function getOperation()
22930 {
22931 return $this->operation;
22932 }
22933 }
22934 <?php
22935
22936
22937
22938
22939
22940
22941
22942
22943
22944
22945
22946 namespace Composer\Installer;
22947
22948
22949
22950
22951
22952
22953 class PackageEvents
22954 {
22955
22956
22957
22958
22959
22960
22961
22962 const PRE_PACKAGE_INSTALL = 'pre-package-install';
22963
22964
22965
22966
22967
22968
22969
22970
22971 const POST_PACKAGE_INSTALL = 'post-package-install';
22972
22973
22974
22975
22976
22977
22978
22979
22980 const PRE_PACKAGE_UPDATE = 'pre-package-update';
22981
22982
22983
22984
22985
22986
22987
22988
22989 const POST_PACKAGE_UPDATE = 'post-package-update';
22990
22991
22992
22993
22994
22995
22996
22997
22998 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
22999
23000
23001
23002
23003
23004
23005
23006
23007 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
23008 }
23009 <?php
23010
23011
23012
23013
23014
23015
23016
23017
23018
23019
23020
23021 namespace Composer\Installer;
23022
23023 use Composer\IO\IOInterface;
23024 use Composer\Package\PackageInterface;
23025 use Composer\Util\Filesystem;
23026 use Composer\Util\ProcessExecutor;
23027
23028
23029
23030
23031
23032
23033 class PearBinaryInstaller extends BinaryInstaller
23034 {
23035 private $installer;
23036 private $vendorDir;
23037
23038
23039
23040
23041
23042
23043
23044
23045
23046 public function __construct(IOInterface $io, $binDir, $vendorDir, $binCompat, Filesystem $filesystem, PearInstaller $installer)
23047 {
23048 parent::__construct($io, $binDir, $binCompat, $filesystem);
23049 $this->installer = $installer;
23050 $this->vendorDir = $vendorDir;
23051 }
23052
23053 protected function getBinaries(PackageInterface $package)
23054 {
23055 $binariesPath = $this->installer->getInstallPath($package) . '/bin/';
23056 $binaries = array();
23057 if (file_exists($binariesPath)) {
23058 foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::CURRENT_AS_FILEINFO) as $fileName => $value) {
23059 if (!$value->isDir()) {
23060 $binaries[] = 'bin/'.$fileName;
23061 }
23062 }
23063 }
23064
23065 return $binaries;
23066 }
23067
23068 protected function initializeBinDir()
23069 {
23070 parent::initializeBinDir();
23071 file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode());
23072 @chmod($this->binDir.'/composer-php', 0777);
23073 file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode());
23074 @chmod($this->binDir.'/composer-php.bat', 0777);
23075 }
23076
23077 protected function generateWindowsProxyCode($bin, $link)
23078 {
23079 $binPath = $this->filesystem->findShortestPath($link, $bin);
23080 if ('.bat' === substr($bin, -4)) {
23081 $caller = 'call';
23082 } else {
23083 $handle = fopen($bin, 'r');
23084 $line = fgets($handle);
23085 fclose($handle);
23086 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
23087 $caller = trim($match[1]);
23088 } else {
23089 $caller = 'php';
23090 }
23091
23092 if ($caller === 'php') {
23093 return "@echo off\r\n".
23094 "pushd .\r\n".
23095 "cd %~dp0\r\n".
23096 "set PHP_PROXY=%CD%\\composer-php.bat\r\n".
23097 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
23098 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
23099 "popd\r\n".
23100 "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n";
23101 }
23102 }
23103
23104 return "@echo off\r\n".
23105 "pushd .\r\n".
23106 "cd %~dp0\r\n".
23107 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
23108 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
23109 "popd\r\n".
23110 $caller." \"%BIN_TARGET%\" %*\r\n";
23111 }
23112
23113 private function generateWindowsPhpProxyCode()
23114 {
23115 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
23116
23117 return
23118 "@echo off\r\n" .
23119 "setlocal enabledelayedexpansion\r\n" .
23120 "set BIN_DIR=%~dp0\r\n" .
23121 "set VENDOR_DIR=%BIN_DIR%\\".$binToVendor."\r\n" .
23122 "set DIRS=.\r\n" .
23123 "FOR /D %%V IN (%VENDOR_DIR%\\*) DO (\r\n" .
23124 "    FOR /D %%P IN (%%V\\*) DO (\r\n" .
23125 "        set DIRS=!DIRS!;%%~fP\r\n" .
23126 "    )\r\n" .
23127 ")\r\n" .
23128 "php.exe -d include_path=!DIRS! %*\r\n";
23129 }
23130
23131 private function generateUnixyPhpProxyCode()
23132 {
23133 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
23134
23135 return
23136 "#!/usr/bin/env sh\n".
23137 "SRC_DIR=`pwd`\n".
23138 "BIN_DIR=`dirname $0`\n".
23139 "VENDOR_DIR=\$BIN_DIR/".escapeshellarg($binToVendor)."\n".
23140 "DIRS=\"\"\n".
23141 "for vendor in \$VENDOR_DIR/*; do\n".
23142 "    if [ -d \"\$vendor\" ]; then\n".
23143 "        for package in \$vendor/*; do\n".
23144 "            if [ -d \"\$package\" ]; then\n".
23145 "                DIRS=\"\${DIRS}:\${package}\"\n".
23146 "            fi\n".
23147 "        done\n".
23148 "    fi\n".
23149 "done\n".
23150 "php -d include_path=\".\$DIRS\" $@\n";
23151 }
23152 }
23153 <?php
23154
23155
23156
23157
23158
23159
23160
23161
23162
23163
23164
23165 namespace Composer\Installer;
23166
23167 use Composer\IO\IOInterface;
23168 use Composer\Composer;
23169 use Composer\Downloader\PearPackageExtractor;
23170 use Composer\Repository\InstalledRepositoryInterface;
23171 use Composer\Package\PackageInterface;
23172 use Composer\Util\Platform;
23173 use Composer\Util\Filesystem;
23174
23175
23176
23177
23178
23179
23180
23181 class PearInstaller extends LibraryInstaller
23182 {
23183
23184
23185
23186
23187
23188
23189
23190 public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
23191 {
23192 $filesystem = new Filesystem();
23193 $binaryInstaller = new PearBinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), rtrim($composer->getConfig()->get('vendor-dir'), '/'), $composer->getConfig()->get('bin-compat'), $filesystem, $this);
23194
23195 parent::__construct($io, $composer, $type, $filesystem, $binaryInstaller);
23196 }
23197
23198
23199
23200
23201 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23202 {
23203 $this->uninstall($repo, $initial);
23204 $this->install($repo, $target);
23205 }
23206
23207 protected function installCode(PackageInterface $package)
23208 {
23209 parent::installCode($package);
23210
23211 $isWindows = Platform::isWindows();
23212 $php_bin = $this->binDir . ($isWindows ? '/composer-php.bat' : '/composer-php');
23213
23214 if (!$isWindows) {
23215 $php_bin = '/usr/bin/env ' . $php_bin;
23216 }
23217
23218 $installPath = $this->getInstallPath($package);
23219 $vars = array(
23220 'os' => $isWindows ? 'windows' : 'linux',
23221 'php_bin' => $php_bin,
23222 'pear_php' => $installPath,
23223 'php_dir' => $installPath,
23224 'bin_dir' => $installPath . '/bin',
23225 'data_dir' => $installPath . '/data',
23226 'version' => $package->getPrettyVersion(),
23227 );
23228
23229 $packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
23230 $pearExtractor = new PearPackageExtractor($packageArchive);
23231 $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
23232
23233 $this->io->writeError('    Cleaning up', true, IOInterface::VERBOSE);
23234 $this->filesystem->unlink($packageArchive);
23235 }
23236 }
23237 <?php
23238
23239
23240
23241
23242
23243
23244
23245
23246
23247
23248
23249 namespace Composer\Installer;
23250
23251 use Composer\Composer;
23252 use Composer\IO\IOInterface;
23253 use Composer\Repository\InstalledRepositoryInterface;
23254 use Composer\Package\PackageInterface;
23255
23256
23257
23258
23259
23260
23261
23262 class PluginInstaller extends LibraryInstaller
23263 {
23264 private $installationManager;
23265
23266
23267
23268
23269
23270
23271
23272
23273 public function __construct(IOInterface $io, Composer $composer, $type = 'library')
23274 {
23275 parent::__construct($io, $composer, 'composer-plugin');
23276 $this->installationManager = $composer->getInstallationManager();
23277 }
23278
23279
23280
23281
23282 public function supports($packageType)
23283 {
23284 return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
23285 }
23286
23287
23288
23289
23290 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23291 {
23292 $extra = $package->getExtra();
23293 if (empty($extra['class'])) {
23294 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
23295 }
23296
23297 parent::install($repo, $package);
23298 try {
23299 $this->composer->getPluginManager()->registerPackage($package, true);
23300 } catch (\Exception $e) {
23301
23302  $this->io->writeError('Plugin installation failed, rolling back');
23303 parent::uninstall($repo, $package);
23304 throw $e;
23305 }
23306 }
23307
23308
23309
23310
23311 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23312 {
23313 $extra = $target->getExtra();
23314 if (empty($extra['class'])) {
23315 throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
23316 }
23317
23318 parent::update($repo, $initial, $target);
23319 $this->composer->getPluginManager()->registerPackage($target, true);
23320 }
23321 }
23322 <?php
23323
23324
23325
23326
23327
23328
23329
23330
23331
23332
23333
23334 namespace Composer\Installer;
23335
23336 use Composer\Package\PackageInterface;
23337 use Composer\Downloader\DownloadManager;
23338 use Composer\Repository\InstalledRepositoryInterface;
23339 use Composer\Util\Filesystem;
23340
23341
23342
23343
23344
23345
23346
23347 class ProjectInstaller implements InstallerInterface
23348 {
23349 private $installPath;
23350 private $downloadManager;
23351 private $filesystem;
23352
23353 public function __construct($installPath, DownloadManager $dm)
23354 {
23355 $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/';
23356 $this->downloadManager = $dm;
23357 $this->filesystem = new Filesystem;
23358 }
23359
23360
23361
23362
23363
23364
23365
23366 public function supports($packageType)
23367 {
23368 return true;
23369 }
23370
23371
23372
23373
23374 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23375 {
23376 return false;
23377 }
23378
23379
23380
23381
23382 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23383 {
23384 $installPath = $this->installPath;
23385 if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
23386 throw new \InvalidArgumentException("Project directory $installPath is not empty.");
23387 }
23388 if (!is_dir($installPath)) {
23389 mkdir($installPath, 0777, true);
23390 }
23391 $this->downloadManager->download($package, $installPath);
23392 }
23393
23394
23395
23396
23397 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23398 {
23399 throw new \InvalidArgumentException("not supported");
23400 }
23401
23402
23403
23404
23405 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23406 {
23407 throw new \InvalidArgumentException("not supported");
23408 }
23409
23410
23411
23412
23413
23414
23415
23416 public function getInstallPath(PackageInterface $package)
23417 {
23418 return $this->installPath;
23419 }
23420 }
23421 <?php
23422
23423
23424
23425
23426
23427
23428
23429
23430
23431
23432
23433 namespace Composer\Installer;
23434
23435 use Composer\IO\IOInterface;
23436 use Composer\Package\PackageInterface;
23437 use Composer\Repository\RepositoryInterface;
23438 use Symfony\Component\Console\Formatter\OutputFormatter;
23439
23440
23441
23442
23443
23444
23445 class SuggestedPackagesReporter
23446 {
23447
23448
23449
23450 protected $suggestedPackages = array();
23451
23452
23453
23454
23455 private $io;
23456
23457 public function __construct(IOInterface $io)
23458 {
23459 $this->io = $io;
23460 }
23461
23462
23463
23464
23465 public function getPackages()
23466 {
23467 return $this->suggestedPackages;
23468 }
23469
23470
23471
23472
23473
23474
23475
23476
23477
23478
23479
23480
23481 public function addPackage($source, $target, $reason)
23482 {
23483 $this->suggestedPackages[] = array(
23484 'source' => $source,
23485 'target' => $target,
23486 'reason' => $reason,
23487 );
23488
23489 return $this;
23490 }
23491
23492
23493
23494
23495
23496
23497
23498 public function addSuggestionsFromPackage(PackageInterface $package)
23499 {
23500 $source = $package->getPrettyName();
23501 foreach ($package->getSuggests() as $target => $reason) {
23502 $this->addPackage(
23503 $source,
23504 $target,
23505 $reason
23506 );
23507 }
23508
23509 return $this;
23510 }
23511
23512
23513
23514
23515
23516
23517
23518
23519 public function output(RepositoryInterface $installedRepo = null)
23520 {
23521 $suggestedPackages = $this->getPackages();
23522 $installedPackages = array();
23523 if (null !== $installedRepo && ! empty($suggestedPackages)) {
23524 foreach ($installedRepo->getPackages() as $package) {
23525 $installedPackages = array_merge(
23526 $installedPackages,
23527 $package->getNames()
23528 );
23529 }
23530 }
23531
23532 foreach ($suggestedPackages as $suggestion) {
23533 if (in_array($suggestion['target'], $installedPackages)) {
23534 continue;
23535 }
23536
23537 $this->io->writeError(sprintf(
23538 '%s suggests installing %s (%s)',
23539 $suggestion['source'],
23540 $this->escapeOutput($suggestion['target']),
23541 $this->escapeOutput($suggestion['reason'])
23542 ));
23543 }
23544
23545 return $this;
23546 }
23547
23548
23549
23550
23551
23552 private function escapeOutput($string)
23553 {
23554 return OutputFormatter::escape(
23555 $this->removeControlCharacters($string)
23556 );
23557 }
23558
23559
23560
23561
23562
23563 private function removeControlCharacters($string)
23564 {
23565 return preg_replace(
23566 '/[[:cntrl:]]/',
23567 '',
23568 str_replace("\n", ' ', $string)
23569 );
23570 }
23571 }
23572 <?php
23573
23574
23575
23576
23577
23578
23579
23580
23581
23582
23583
23584 namespace Composer\Json;
23585
23586 use JsonSchema\Validator;
23587 use Seld\JsonLint\JsonParser;
23588 use Seld\JsonLint\ParsingException;
23589 use Composer\Util\RemoteFilesystem;
23590 use Composer\IO\IOInterface;
23591 use Composer\Downloader\TransportException;
23592
23593
23594
23595
23596
23597
23598
23599 class JsonFile
23600 {
23601 const LAX_SCHEMA = 1;
23602 const STRICT_SCHEMA = 2;
23603
23604 const JSON_UNESCAPED_SLASHES = 64;
23605 const JSON_PRETTY_PRINT = 128;
23606 const JSON_UNESCAPED_UNICODE = 256;
23607
23608 private $path;
23609 private $rfs;
23610 private $io;
23611
23612
23613
23614
23615
23616
23617
23618
23619
23620 public function __construct($path, RemoteFilesystem $rfs = null, IOInterface $io = null)
23621 {
23622 $this->path = $path;
23623
23624 if (null === $rfs && preg_match('{^https?://}i', $path)) {
23625 throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed');
23626 }
23627 $this->rfs = $rfs;
23628 $this->io = $io;
23629 }
23630
23631
23632
23633
23634 public function getPath()
23635 {
23636 return $this->path;
23637 }
23638
23639
23640
23641
23642
23643
23644 public function exists()
23645 {
23646 return is_file($this->path);
23647 }
23648
23649
23650
23651
23652
23653
23654
23655 public function read()
23656 {
23657 try {
23658 if ($this->rfs) {
23659 $json = $this->rfs->getContents($this->path, $this->path, false);
23660 } else {
23661 if ($this->io && $this->io->isDebug()) {
23662 $this->io->writeError('Reading ' . $this->path);
23663 }
23664 $json = file_get_contents($this->path);
23665 }
23666 } catch (TransportException $e) {
23667 throw new \RuntimeException($e->getMessage(), 0, $e);
23668 } catch (\Exception $e) {
23669 throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
23670 }
23671
23672 return static::parseJson($json, $this->path);
23673 }
23674
23675
23676
23677
23678
23679
23680
23681
23682 public function write(array $hash, $options = 448)
23683 {
23684 $dir = dirname($this->path);
23685 if (!is_dir($dir)) {
23686 if (file_exists($dir)) {
23687 throw new \UnexpectedValueException(
23688 $dir.' exists and is not a directory.'
23689 );
23690 }
23691 if (!@mkdir($dir, 0777, true)) {
23692 throw new \UnexpectedValueException(
23693 $dir.' does not exist and could not be created.'
23694 );
23695 }
23696 }
23697
23698 $retries = 3;
23699 while ($retries--) {
23700 try {
23701 file_put_contents($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : ''));
23702 break;
23703 } catch (\Exception $e) {
23704 if ($retries) {
23705 usleep(500000);
23706 continue;
23707 }
23708
23709 throw $e;
23710 }
23711 }
23712 }
23713
23714
23715
23716
23717
23718
23719
23720
23721 public function validateSchema($schema = self::STRICT_SCHEMA)
23722 {
23723 $content = file_get_contents($this->path);
23724 $data = json_decode($content);
23725
23726 if (null === $data && 'null' !== $content) {
23727 self::validateSyntax($content, $this->path);
23728 }
23729
23730 $schemaFile = __DIR__ . '/../../../res/composer-schema.json';
23731
23732
23733  if (false === strpos($schemaFile, '://')) {
23734 $schemaFile = 'file://' . $schemaFile;
23735 }
23736
23737 $schemaData = (object) array('$ref' => $schemaFile);
23738
23739 if ($schema === self::LAX_SCHEMA) {
23740 $schemaData->additionalProperties = true;
23741 $schemaData->required = array();
23742 }
23743
23744 $validator = new Validator();
23745 $validator->check($data, $schemaData);
23746
23747
23748
23749 if (!$validator->isValid()) {
23750 $errors = array();
23751 foreach ((array) $validator->getErrors() as $error) {
23752 $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
23753 }
23754 throw new JsonValidationException('"'.$this->path.'" does not match the expected JSON schema', $errors);
23755 }
23756
23757 return true;
23758 }
23759
23760
23761
23762
23763
23764
23765
23766
23767 public static function encode($data, $options = 448)
23768 {
23769 if (PHP_VERSION_ID >= 50400) {
23770 $json = json_encode($data, $options);
23771 if (false === $json) {
23772 self::throwEncodeError(json_last_error());
23773 }
23774
23775
23776  if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
23777 $json = preg_replace('/\[\s+\]/', '[]', $json);
23778 $json = preg_replace('/\{\s+\}/', '{}', $json);
23779 }
23780
23781 return $json;
23782 }
23783
23784 $json = json_encode($data);
23785 if (false === $json) {
23786 self::throwEncodeError(json_last_error());
23787 }
23788
23789 $prettyPrint = (bool) ($options & self::JSON_PRETTY_PRINT);
23790 $unescapeUnicode = (bool) ($options & self::JSON_UNESCAPED_UNICODE);
23791 $unescapeSlashes = (bool) ($options & self::JSON_UNESCAPED_SLASHES);
23792
23793 if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes) {
23794 return $json;
23795 }
23796
23797 return JsonFormatter::format($json, $unescapeUnicode, $unescapeSlashes);
23798 }
23799
23800
23801
23802
23803
23804
23805
23806 private static function throwEncodeError($code)
23807 {
23808 switch ($code) {
23809 case JSON_ERROR_DEPTH:
23810 $msg = 'Maximum stack depth exceeded';
23811 break;
23812 case JSON_ERROR_STATE_MISMATCH:
23813 $msg = 'Underflow or the modes mismatch';
23814 break;
23815 case JSON_ERROR_CTRL_CHAR:
23816 $msg = 'Unexpected control character found';
23817 break;
23818 case JSON_ERROR_UTF8:
23819 $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
23820 break;
23821 default:
23822 $msg = 'Unknown error';
23823 }
23824
23825 throw new \RuntimeException('JSON encoding failed: '.$msg);
23826 }
23827
23828
23829
23830
23831
23832
23833
23834
23835
23836 public static function parseJson($json, $file = null)
23837 {
23838 if (null === $json) {
23839 return;
23840 }
23841 $data = json_decode($json, true);
23842 if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
23843 self::validateSyntax($json, $file);
23844 }
23845
23846 return $data;
23847 }
23848
23849
23850
23851
23852
23853
23854
23855
23856
23857
23858
23859 protected static function validateSyntax($json, $file = null)
23860 {
23861 $parser = new JsonParser();
23862 $result = $parser->lint($json);
23863 if (null === $result) {
23864 if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
23865 throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
23866 }
23867
23868 return true;
23869 }
23870
23871 throw new ParsingException('"'.$file.'" does not contain valid JSON'."\n".$result->getMessage(), $result->getDetails());
23872 }
23873 }
23874 <?php
23875
23876
23877
23878
23879
23880
23881
23882
23883
23884
23885
23886 namespace Composer\Json;
23887
23888
23889
23890
23891
23892
23893
23894
23895
23896 class JsonFormatter
23897 {
23898
23899
23900
23901
23902
23903
23904
23905
23906
23907
23908
23909
23910 public static function format($json, $unescapeUnicode, $unescapeSlashes)
23911 {
23912 $result = '';
23913 $pos = 0;
23914 $strLen = strlen($json);
23915 $indentStr = '    ';
23916 $newLine = "\n";
23917 $outOfQuotes = true;
23918 $buffer = '';
23919 $noescape = true;
23920
23921 for ($i = 0; $i < $strLen; $i++) {
23922
23923  $char = substr($json, $i, 1);
23924
23925
23926  if ('"' === $char && $noescape) {
23927 $outOfQuotes = !$outOfQuotes;
23928 }
23929
23930 if (!$outOfQuotes) {
23931 $buffer .= $char;
23932 $noescape = '\\' === $char ? !$noescape : true;
23933 continue;
23934 } elseif ('' !== $buffer) {
23935 if ($unescapeSlashes) {
23936 $buffer = str_replace('\\/', '/', $buffer);
23937 }
23938
23939 if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
23940
23941  $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) {
23942 $l = strlen($match[1]);
23943
23944 if ($l % 2) {
23945 return str_repeat('\\', $l - 1) . mb_convert_encoding(
23946 pack('H*', $match[2]),
23947 'UTF-8',
23948 'UCS-2BE'
23949 );
23950 }
23951
23952 return $match[0];
23953 }, $buffer);
23954 }
23955
23956 $result .= $buffer.$char;
23957 $buffer = '';
23958 continue;
23959 }
23960
23961 if (':' === $char) {
23962
23963  $char .= ' ';
23964 } elseif (('}' === $char || ']' === $char)) {
23965 $pos--;
23966 $prevChar = substr($json, $i - 1, 1);
23967
23968 if ('{' !== $prevChar && '[' !== $prevChar) {
23969
23970  
23971  $result .= $newLine;
23972 for ($j = 0; $j < $pos; $j++) {
23973 $result .= $indentStr;
23974 }
23975 } else {
23976
23977  $result = rtrim($result);
23978 }
23979 }
23980
23981 $result .= $char;
23982
23983
23984  
23985  if (',' === $char || '{' === $char || '[' === $char) {
23986 $result .= $newLine;
23987
23988 if ('{' === $char || '[' === $char) {
23989 $pos++;
23990 }
23991
23992 for ($j = 0; $j < $pos; $j++) {
23993 $result .= $indentStr;
23994 }
23995 }
23996 }
23997
23998 return $result;
23999 }
24000 }
24001 <?php
24002
24003
24004
24005
24006
24007
24008
24009
24010
24011
24012
24013 namespace Composer\Json;
24014
24015 use Composer\Repository\PlatformRepository;
24016
24017
24018
24019
24020 class JsonManipulator
24021 {
24022 private static $DEFINES = '(?(DEFINE)
24023        (?<number>   -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
24024        (?<boolean>   true | false | null )
24025        (?<string>    " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
24026        (?<array>     \[  (?:  (?&json) \s* (?: , (?&json) \s* )*  )?  \s* \] )
24027        (?<pair>      \s* (?&string) \s* : (?&json) \s* )
24028        (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
24029        (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
24030     )';
24031
24032 private $contents;
24033 private $newline;
24034 private $indent;
24035
24036 public function __construct($contents)
24037 {
24038 $contents = trim($contents);
24039 if ($contents === '') {
24040 $contents = '{}';
24041 }
24042 if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) {
24043 throw new \InvalidArgumentException('The json file must be an object ({})');
24044 }
24045 $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
24046 $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
24047 $this->detectIndenting();
24048 }
24049
24050 public function getContents()
24051 {
24052 return $this->contents . $this->newline;
24053 }
24054
24055 public function addLink($type, $package, $constraint, $sortPackages = false)
24056 {
24057 $decoded = JsonFile::parseJson($this->contents);
24058
24059
24060  if (!isset($decoded[$type])) {
24061 return $this->addMainKey($type, array($package => $constraint));
24062 }
24063
24064 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24065 '(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
24066 if (!$this->pregMatch($regex, $this->contents, $matches)) {
24067 return false;
24068 }
24069
24070 $links = $matches['value'];
24071
24072
24073  $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
24074 $regex = '{'.self::$DEFINES.'"(?P<package>'.$packageRegex.')"(\s*:\s*)(?&string)}ix';
24075 if ($this->pregMatch($regex, $links, $packageMatches)) {
24076
24077  $existingPackage = $packageMatches['package'];
24078 $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage));
24079 $links = preg_replace_callback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P<separator>\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) {
24080 return JsonFile::encode(str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"';
24081 }, $links);
24082 } else {
24083 if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
24084
24085  $links = preg_replace(
24086 '{'.preg_quote($match[1]).'$}',
24087
24088  addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
24089 $links
24090 );
24091 } else {
24092
24093  $links = '{' . $this->newline .
24094 $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
24095 $this->indent . '}';
24096 }
24097 }
24098
24099 if (true === $sortPackages) {
24100 $requirements = json_decode($links, true);
24101 $this->sortPackages($requirements);
24102 $links = $this->format($requirements);
24103 }
24104
24105 $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end'];
24106
24107 return true;
24108 }
24109
24110
24111
24112
24113
24114
24115
24116
24117 private function sortPackages(array &$packages = array())
24118 {
24119 $prefix = function ($requirement) {
24120 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) {
24121 return preg_replace(
24122 array(
24123 '/^php/',
24124 '/^hhvm/',
24125 '/^ext/',
24126 '/^lib/',
24127 '/^\D/',
24128 ),
24129 array(
24130 '0-$0',
24131 '1-$0',
24132 '2-$0',
24133 '3-$0',
24134 '4-$0',
24135 ),
24136 $requirement
24137 );
24138 }
24139
24140 return '5-'.$requirement;
24141 };
24142
24143 uksort($packages, function ($a, $b) use ($prefix) {
24144 return strnatcmp($prefix($a), $prefix($b));
24145 });
24146 }
24147
24148 public function addRepository($name, $config)
24149 {
24150 return $this->addSubNode('repositories', $name, $config);
24151 }
24152
24153 public function removeRepository($name)
24154 {
24155 return $this->removeSubNode('repositories', $name);
24156 }
24157
24158 public function addConfigSetting($name, $value)
24159 {
24160 return $this->addSubNode('config', $name, $value);
24161 }
24162
24163 public function removeConfigSetting($name)
24164 {
24165 return $this->removeSubNode('config', $name);
24166 }
24167
24168 public function addProperty($name, $value)
24169 {
24170 if (substr($name, 0, 6) === 'extra.') {
24171 return $this->addSubNode('extra', substr($name, 6), $value);
24172 }
24173
24174 return $this->addMainKey($name, $value);
24175 }
24176
24177 public function removeProperty($name)
24178 {
24179 if (substr($name, 0, 6) === 'extra.') {
24180 return $this->removeSubNode('extra', substr($name, 6));
24181 }
24182
24183 return $this->removeMainKey($name);
24184 }
24185
24186 public function addSubNode($mainNode, $name, $value)
24187 {
24188 $decoded = JsonFile::parseJson($this->contents);
24189
24190 $subName = null;
24191 if (in_array($mainNode, array('config', 'extra')) && false !== strpos($name, '.')) {
24192 list($name, $subName) = explode('.', $name, 2);
24193 }
24194
24195
24196  if (!isset($decoded[$mainNode])) {
24197 if ($subName !== null) {
24198 $this->addMainKey($mainNode, array($name => array($subName => $value)));
24199 } else {
24200 $this->addMainKey($mainNode, array($name => $value));
24201 }
24202
24203 return true;
24204 }
24205
24206
24207  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
24208 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
24209
24210 try {
24211 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
24212 return false;
24213 }
24214 } catch (\RuntimeException $e) {
24215 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
24216 return false;
24217 }
24218 throw $e;
24219 }
24220
24221 $children = $match['content'];
24222
24223  if (!@json_decode($children)) {
24224 return false;
24225 }
24226
24227 $that = $this;
24228
24229
24230  $childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
24231 if ($this->pregMatch($childRegex, $children, $matches)) {
24232 $children = preg_replace_callback($childRegex, function ($matches) use ($name, $subName, $value, $that) {
24233 if ($subName !== null) {
24234 $curVal = json_decode($matches['content'], true);
24235 if (!is_array($curVal)) {
24236 $curVal = array();
24237 }
24238 $curVal[$subName] = $value;
24239 $value = $curVal;
24240 }
24241
24242 return $matches['start'] . $that->format($value, 1) . $matches['end'];
24243 }, $children);
24244 } else {
24245 $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
24246
24247 $whitespace = '';
24248 if (!empty($match['trailingspace'])) {
24249 $whitespace = $match['trailingspace'];
24250 }
24251
24252 if (!empty($match['content'])) {
24253 if ($subName !== null) {
24254 $value = array($subName => $value);
24255 }
24256
24257
24258  $children = preg_replace(
24259 '#'.$whitespace.'}$#',
24260 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}', '\\$'),
24261 $children
24262 );
24263 } else {
24264 if ($subName !== null) {
24265 $value = array($subName => $value);
24266 }
24267
24268
24269  $children = '{' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}';
24270 }
24271 }
24272
24273 $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) {
24274 return $m['start'] . $children . $m['end'];
24275 }, $this->contents);
24276
24277 return true;
24278 }
24279
24280 public function removeSubNode($mainNode, $name)
24281 {
24282 $decoded = JsonFile::parseJson($this->contents);
24283
24284
24285  if (empty($decoded[$mainNode])) {
24286 return true;
24287 }
24288
24289
24290  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
24291 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
24292 try {
24293 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
24294 return false;
24295 }
24296 } catch (\RuntimeException $e) {
24297 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
24298 return false;
24299 }
24300 throw $e;
24301 }
24302
24303 $children = $match['content'];
24304
24305
24306  if (!@json_decode($children, true)) {
24307 return false;
24308 }
24309
24310 $subName = null;
24311 if (in_array($mainNode, array('config', 'extra')) && false !== strpos($name, '.')) {
24312 list($name, $subName) = explode('.', $name, 2);
24313 }
24314
24315
24316  if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
24317 return true;
24318 }
24319
24320
24321  if ($this->pregMatch('{"'.preg_quote($name).'"\s*:}i', $children)) {
24322
24323  if (preg_match_all('{'.self::$DEFINES.'"'.preg_quote($name).'"\s*:\s*(?:(?&json))}x', $children, $matches)) {
24324 $bestMatch = '';
24325 foreach ($matches[0] as $match) {
24326 if (strlen($bestMatch) < strlen($match)) {
24327 $bestMatch = $match;
24328 }
24329 }
24330 $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count);
24331 if (1 !== $count) {
24332 $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count);
24333 if (1 !== $count) {
24334 return false;
24335 }
24336 }
24337 }
24338 } else {
24339 $childrenClean = $children;
24340 }
24341
24342
24343  $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $childrenClean, $match);
24344 if (empty($match['content'])) {
24345 $newline = $this->newline;
24346 $indent = $this->indent;
24347
24348 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($indent, $newline) {
24349 return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
24350 }, $this->contents);
24351
24352
24353  if ($subName !== null) {
24354 $curVal = json_decode($children, true);
24355 unset($curVal[$name][$subName]);
24356 $this->addSubNode($mainNode, $name, $curVal[$name]);
24357 }
24358
24359 return true;
24360 }
24361
24362 $that = $this;
24363 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
24364 if ($subName !== null) {
24365 $curVal = json_decode($matches['content'], true);
24366 unset($curVal[$name][$subName]);
24367 $childrenClean = $that->format($curVal, 0);
24368 }
24369
24370 return $matches['start'] . $childrenClean . $matches['end'];
24371 }, $this->contents);
24372
24373 return true;
24374 }
24375
24376 public function addMainKey($key, $content)
24377 {
24378 $decoded = JsonFile::parseJson($this->contents);
24379 $content = $this->format($content);
24380
24381
24382  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24383 '(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}sx';
24384 if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
24385
24386  if (!@json_decode('{'.$matches['key'].'}')) {
24387 return false;
24388 }
24389
24390 $this->contents = $matches['start'] . JsonFile::encode($key).': '.$content . $matches['end'];
24391
24392 return true;
24393 }
24394
24395
24396  if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
24397 $this->contents = preg_replace(
24398 '#'.$match[1].'\}$#',
24399 addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'),
24400 $this->contents
24401 );
24402
24403 return true;
24404 }
24405
24406
24407  $this->contents = preg_replace(
24408 '#\}$#',
24409 addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'),
24410 $this->contents
24411 );
24412
24413 return true;
24414 }
24415
24416 public function removeMainKey($key)
24417 {
24418 $decoded = JsonFile::parseJson($this->contents);
24419
24420 if (!array_key_exists($key, $decoded)) {
24421 return true;
24422 }
24423
24424
24425  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24426 '(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
24427 if ($this->pregMatch($regex, $this->contents, $matches)) {
24428
24429  if (!@json_decode('{'.$matches['removal'].'}')) {
24430 return false;
24431 }
24432
24433
24434  if (preg_match('#,\s*$#', $matches['start']) && preg_match('#^\}$#', $matches['end'])) {
24435 $matches['start'] = rtrim(preg_replace('#,(\s*)$#', '$1', $matches['start']), $this->indent);
24436 }
24437
24438 $this->contents = $matches['start'] . $matches['end'];
24439 if (preg_match('#^\{\s*\}\s*$#', $this->contents)) {
24440 $this->contents = "{\n}";
24441 }
24442
24443 return true;
24444 }
24445
24446 return false;
24447 }
24448
24449 public function format($data, $depth = 0)
24450 {
24451 if (is_array($data)) {
24452 reset($data);
24453
24454 if (is_numeric(key($data))) {
24455 foreach ($data as $key => $val) {
24456 $data[$key] = $this->format($val, $depth + 1);
24457 }
24458
24459 return '['.implode(', ', $data).']';
24460 }
24461
24462 $out = '{' . $this->newline;
24463 $elems = array();
24464 foreach ($data as $key => $val) {
24465 $elems[] = str_repeat($this->indent, $depth + 2) . JsonFile::encode($key). ': '.$this->format($val, $depth + 1);
24466 }
24467
24468 return $out . implode(','.$this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
24469 }
24470
24471 return JsonFile::encode($data);
24472 }
24473
24474 protected function detectIndenting()
24475 {
24476 if ($this->pregMatch('{^([ \t]+)"}m', $this->contents, $match)) {
24477 $this->indent = $match[1];
24478 } else {
24479 $this->indent = '    ';
24480 }
24481 }
24482
24483 protected function pregMatch($re, $str, &$matches = array())
24484 {
24485 $count = preg_match($re, $str, $matches);
24486
24487 if ($count === false) {
24488 switch (preg_last_error()) {
24489 case PREG_NO_ERROR:
24490 throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR);
24491 case PREG_INTERNAL_ERROR:
24492 throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR);
24493 case PREG_BACKTRACK_LIMIT_ERROR:
24494 throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR);
24495 case PREG_RECURSION_LIMIT_ERROR:
24496 throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR);
24497 case PREG_BAD_UTF8_ERROR:
24498 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR);
24499 case PREG_BAD_UTF8_OFFSET_ERROR:
24500 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR);
24501 case 6: 
24502  if (PHP_VERSION_ID > 70000) {
24503 throw new \RuntimeException('Failed to execute regex: PREG_JIT_STACKLIMIT_ERROR', 6);
24504 }
24505
24506
24507 default:
24508 throw new \RuntimeException('Failed to execute regex: Unknown error');
24509 }
24510 }
24511
24512 return $count;
24513 }
24514 }
24515 <?php
24516
24517
24518
24519
24520
24521
24522
24523
24524
24525
24526
24527 namespace Composer\Json;
24528
24529 use Exception;
24530
24531
24532
24533
24534 class JsonValidationException extends Exception
24535 {
24536 protected $errors;
24537
24538 public function __construct($message, $errors = array(), Exception $previous = null)
24539 {
24540 $this->errors = $errors;
24541 parent::__construct($message, 0, $previous);
24542 }
24543
24544 public function getErrors()
24545 {
24546 return $this->errors;
24547 }
24548 }
24549 <?php
24550
24551
24552
24553
24554
24555
24556
24557
24558
24559
24560
24561 namespace Composer\Package;
24562
24563 use Composer\Semver\Constraint\Constraint;
24564 use Composer\Package\Version\VersionParser;
24565
24566
24567
24568
24569 class AliasPackage extends BasePackage implements CompletePackageInterface
24570 {
24571 protected $version;
24572 protected $prettyVersion;
24573 protected $dev;
24574 protected $rootPackageAlias = false;
24575 protected $stability;
24576
24577
24578 protected $aliasOf;
24579
24580 protected $requires;
24581
24582 protected $devRequires;
24583
24584 protected $conflicts;
24585
24586 protected $provides;
24587
24588 protected $replaces;
24589
24590
24591
24592
24593
24594
24595
24596
24597 public function __construct(PackageInterface $aliasOf, $version, $prettyVersion)
24598 {
24599 parent::__construct($aliasOf->getName());
24600
24601 $this->version = $version;
24602 $this->prettyVersion = $prettyVersion;
24603 $this->aliasOf = $aliasOf;
24604 $this->stability = VersionParser::parseStability($version);
24605 $this->dev = $this->stability === 'dev';
24606
24607 foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) {
24608 $links = $aliasOf->{'get' . ucfirst($type)}();
24609 $this->$type = $this->replaceSelfVersionDependencies($links, $type);
24610 }
24611 }
24612
24613
24614
24615
24616 public function getAliasOf()
24617 {
24618 return $this->aliasOf;
24619 }
24620
24621
24622
24623
24624 public function getVersion()
24625 {
24626 return $this->version;
24627 }
24628
24629
24630
24631
24632 public function getStability()
24633 {
24634 return $this->stability;
24635 }
24636
24637
24638
24639
24640 public function getPrettyVersion()
24641 {
24642 return $this->prettyVersion;
24643 }
24644
24645
24646
24647
24648 public function isDev()
24649 {
24650 return $this->dev;
24651 }
24652
24653
24654
24655
24656 public function getRequires()
24657 {
24658 return $this->requires;
24659 }
24660
24661
24662
24663
24664 public function getConflicts()
24665 {
24666 return $this->conflicts;
24667 }
24668
24669
24670
24671
24672 public function getProvides()
24673 {
24674 return $this->provides;
24675 }
24676
24677
24678
24679
24680 public function getReplaces()
24681 {
24682 return $this->replaces;
24683 }
24684
24685
24686
24687
24688 public function getDevRequires()
24689 {
24690 return $this->devRequires;
24691 }
24692
24693
24694
24695
24696
24697
24698
24699
24700
24701
24702 public function setRootPackageAlias($value)
24703 {
24704 return $this->rootPackageAlias = $value;
24705 }
24706
24707
24708
24709
24710
24711 public function isRootPackageAlias()
24712 {
24713 return $this->rootPackageAlias;
24714 }
24715
24716
24717
24718
24719
24720
24721
24722 protected function replaceSelfVersionDependencies(array $links, $linkType)
24723 {
24724 if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
24725 $newLinks = array();
24726 foreach ($links as $link) {
24727
24728  if ('self.version' === $link->getPrettyConstraint()) {
24729 $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
24730 }
24731 }
24732 $links = array_merge($links, $newLinks);
24733 } else {
24734 foreach ($links as $index => $link) {
24735 if ('self.version' === $link->getPrettyConstraint()) {
24736 $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
24737 }
24738 }
24739 }
24740
24741 return $links;
24742 }
24743
24744
24745
24746
24747
24748 public function getType()
24749 {
24750 return $this->aliasOf->getType();
24751 }
24752
24753 public function getTargetDir()
24754 {
24755 return $this->aliasOf->getTargetDir();
24756 }
24757
24758 public function getExtra()
24759 {
24760 return $this->aliasOf->getExtra();
24761 }
24762
24763 public function setInstallationSource($type)
24764 {
24765 $this->aliasOf->setInstallationSource($type);
24766 }
24767
24768 public function getInstallationSource()
24769 {
24770 return $this->aliasOf->getInstallationSource();
24771 }
24772
24773 public function getSourceType()
24774 {
24775 return $this->aliasOf->getSourceType();
24776 }
24777
24778 public function getSourceUrl()
24779 {
24780 return $this->aliasOf->getSourceUrl();
24781 }
24782
24783 public function getSourceUrls()
24784 {
24785 return $this->aliasOf->getSourceUrls();
24786 }
24787
24788 public function getSourceReference()
24789 {
24790 return $this->aliasOf->getSourceReference();
24791 }
24792
24793 public function setSourceReference($reference)
24794 {
24795 return $this->aliasOf->setSourceReference($reference);
24796 }
24797
24798 public function setSourceMirrors($mirrors)
24799 {
24800 return $this->aliasOf->setSourceMirrors($mirrors);
24801 }
24802
24803 public function getSourceMirrors()
24804 {
24805 return $this->aliasOf->getSourceMirrors();
24806 }
24807
24808 public function getDistType()
24809 {
24810 return $this->aliasOf->getDistType();
24811 }
24812
24813 public function getDistUrl()
24814 {
24815 return $this->aliasOf->getDistUrl();
24816 }
24817
24818 public function getDistUrls()
24819 {
24820 return $this->aliasOf->getDistUrls();
24821 }
24822
24823 public function getDistReference()
24824 {
24825 return $this->aliasOf->getDistReference();
24826 }
24827
24828 public function setDistReference($reference)
24829 {
24830 return $this->aliasOf->setDistReference($reference);
24831 }
24832
24833 public function getDistSha1Checksum()
24834 {
24835 return $this->aliasOf->getDistSha1Checksum();
24836 }
24837
24838 public function setTransportOptions(array $options)
24839 {
24840 return $this->aliasOf->setTransportOptions($options);
24841 }
24842
24843 public function getTransportOptions()
24844 {
24845 return $this->aliasOf->getTransportOptions();
24846 }
24847
24848 public function setDistMirrors($mirrors)
24849 {
24850 return $this->aliasOf->setDistMirrors($mirrors);
24851 }
24852
24853 public function getDistMirrors()
24854 {
24855 return $this->aliasOf->getDistMirrors();
24856 }
24857
24858 public function getScripts()
24859 {
24860 return $this->aliasOf->getScripts();
24861 }
24862
24863 public function getLicense()
24864 {
24865 return $this->aliasOf->getLicense();
24866 }
24867
24868 public function getAutoload()
24869 {
24870 return $this->aliasOf->getAutoload();
24871 }
24872
24873 public function getDevAutoload()
24874 {
24875 return $this->aliasOf->getDevAutoload();
24876 }
24877
24878 public function getIncludePaths()
24879 {
24880 return $this->aliasOf->getIncludePaths();
24881 }
24882
24883 public function getRepositories()
24884 {
24885 return $this->aliasOf->getRepositories();
24886 }
24887
24888 public function getReleaseDate()
24889 {
24890 return $this->aliasOf->getReleaseDate();
24891 }
24892
24893 public function getBinaries()
24894 {
24895 return $this->aliasOf->getBinaries();
24896 }
24897
24898 public function getKeywords()
24899 {
24900 return $this->aliasOf->getKeywords();
24901 }
24902
24903 public function getDescription()
24904 {
24905 return $this->aliasOf->getDescription();
24906 }
24907
24908 public function getHomepage()
24909 {
24910 return $this->aliasOf->getHomepage();
24911 }
24912
24913 public function getSuggests()
24914 {
24915 return $this->aliasOf->getSuggests();
24916 }
24917
24918 public function getAuthors()
24919 {
24920 return $this->aliasOf->getAuthors();
24921 }
24922
24923 public function getSupport()
24924 {
24925 return $this->aliasOf->getSupport();
24926 }
24927
24928 public function getNotificationUrl()
24929 {
24930 return $this->aliasOf->getNotificationUrl();
24931 }
24932
24933 public function getArchiveExcludes()
24934 {
24935 return $this->aliasOf->getArchiveExcludes();
24936 }
24937
24938 public function isAbandoned()
24939 {
24940 return $this->aliasOf->isAbandoned();
24941 }
24942
24943 public function getReplacementPackage()
24944 {
24945 return $this->aliasOf->getReplacementPackage();
24946 }
24947
24948 public function __toString()
24949 {
24950 return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
24951 }
24952 }
24953 <?php
24954
24955
24956
24957
24958
24959
24960
24961
24962
24963
24964
24965 namespace Composer\Package\Archiver;
24966
24967 use FilterIterator;
24968 use PharData;
24969
24970 class ArchivableFilesFilter extends FilterIterator
24971 {
24972 private $dirs = array();
24973
24974
24975
24976
24977 public function accept()
24978 {
24979 $file = $this->getInnerIterator()->current();
24980 if ($file->isDir()) {
24981 $this->dirs[] = (string) $file;
24982
24983 return false;
24984 }
24985
24986 return true;
24987 }
24988
24989 public function addEmptyDir(PharData $phar, $sources)
24990 {
24991 foreach ($this->dirs as $filepath) {
24992 $localname = str_replace($sources . "/", '', $filepath);
24993 $phar->addEmptyDir($localname);
24994 }
24995 }
24996 }
24997 <?php
24998
24999
25000
25001
25002
25003
25004
25005
25006
25007
25008
25009 namespace Composer\Package\Archiver;
25010
25011 use Composer\Util\Filesystem;
25012 use FilesystemIterator;
25013 use Symfony\Component\Finder\Finder;
25014 use Symfony\Component\Finder\SplFileInfo;
25015
25016
25017
25018
25019
25020
25021
25022
25023
25024 class ArchivableFilesFinder extends \FilterIterator
25025 {
25026
25027
25028
25029 protected $finder;
25030
25031
25032
25033
25034
25035
25036
25037
25038 public function __construct($sources, array $excludes, $ignoreFilters = false)
25039 {
25040 $fs = new Filesystem();
25041
25042 $sources = $fs->normalizePath($sources);
25043
25044 if ($ignoreFilters) {
25045 $filters = array();
25046 } else {
25047 $filters = array(
25048 new HgExcludeFilter($sources),
25049 new GitExcludeFilter($sources),
25050 new ComposerExcludeFilter($sources, $excludes),
25051 );
25052 }
25053
25054 $this->finder = new Finder();
25055
25056 $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
25057 if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) {
25058 return false;
25059 }
25060
25061 $relativePath = preg_replace(
25062 '#^'.preg_quote($sources, '#').'#',
25063 '',
25064 $fs->normalizePath($file->getRealPath())
25065 );
25066
25067 $exclude = false;
25068 foreach ($filters as $filter) {
25069 $exclude = $filter->filter($relativePath, $exclude);
25070 }
25071
25072 return !$exclude;
25073 };
25074
25075 if (method_exists($filter, 'bindTo')) {
25076 $filter = $filter->bindTo(null);
25077 }
25078
25079 $this->finder
25080 ->in($sources)
25081 ->filter($filter)
25082 ->ignoreVCS(true)
25083 ->ignoreDotFiles(false);
25084
25085 parent::__construct($this->finder->getIterator());
25086 }
25087
25088 public function accept()
25089 {
25090
25091 $current = $this->getInnerIterator()->current();
25092
25093 if (!$current->isDir()) {
25094 return true;
25095 }
25096
25097 $iterator = new FilesystemIterator($current, FilesystemIterator::SKIP_DOTS);
25098
25099 return !$iterator->valid();
25100 }
25101 }
25102 <?php
25103
25104
25105
25106
25107
25108
25109
25110
25111
25112
25113
25114 namespace Composer\Package\Archiver;
25115
25116 use Composer\Downloader\DownloadManager;
25117 use Composer\Package\PackageInterface;
25118 use Composer\Package\RootPackageInterface;
25119 use Composer\Util\Filesystem;
25120 use Composer\Json\JsonFile;
25121
25122
25123
25124
25125
25126 class ArchiveManager
25127 {
25128 protected $downloadManager;
25129
25130 protected $archivers = array();
25131
25132
25133
25134
25135 protected $overwriteFiles = true;
25136
25137
25138
25139
25140 public function __construct(DownloadManager $downloadManager)
25141 {
25142 $this->downloadManager = $downloadManager;
25143 }
25144
25145
25146
25147
25148 public function addArchiver(ArchiverInterface $archiver)
25149 {
25150 $this->archivers[] = $archiver;
25151 }
25152
25153
25154
25155
25156
25157
25158
25159
25160 public function setOverwriteFiles($overwriteFiles)
25161 {
25162 $this->overwriteFiles = $overwriteFiles;
25163
25164 return $this;
25165 }
25166
25167
25168
25169
25170
25171
25172
25173
25174 public function getPackageFilename(PackageInterface $package)
25175 {
25176 $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
25177
25178 if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
25179 $nameParts = array_merge($nameParts, array($package->getDistReference(), $package->getDistType()));
25180 } else {
25181 $nameParts = array_merge($nameParts, array($package->getPrettyVersion(), $package->getDistReference()));
25182 }
25183
25184 if ($package->getSourceReference()) {
25185 $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
25186 }
25187
25188 $name = implode('-', array_filter($nameParts, function ($p) {
25189 return !empty($p);
25190 }));
25191
25192 return str_replace('/', '-', $name);
25193 }
25194
25195
25196
25197
25198
25199
25200
25201
25202
25203
25204
25205
25206
25207
25208 public function archive(PackageInterface $package, $format, $targetDir, $fileName = null, $ignoreFilters = false)
25209 {
25210 if (empty($format)) {
25211 throw new \InvalidArgumentException('Format must be specified');
25212 }
25213
25214
25215  $usableArchiver = null;
25216 foreach ($this->archivers as $archiver) {
25217 if ($archiver->supports($format, $package->getSourceType())) {
25218 $usableArchiver = $archiver;
25219 break;
25220 }
25221 }
25222
25223
25224  if (null === $usableArchiver) {
25225 throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
25226 }
25227
25228 $filesystem = new Filesystem();
25229 if (null === $fileName) {
25230 $packageName = $this->getPackageFilename($package);
25231 } else {
25232 $packageName = $fileName;
25233 }
25234
25235
25236  $filesystem->ensureDirectoryExists($targetDir);
25237 $target = realpath($targetDir).'/'.$packageName.'.'.$format;
25238 $filesystem->ensureDirectoryExists(dirname($target));
25239
25240 if (!$this->overwriteFiles && file_exists($target)) {
25241 return $target;
25242 }
25243
25244 if ($package instanceof RootPackageInterface) {
25245 $sourcePath = realpath('.');
25246 } else {
25247
25248  $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
25249 $filesystem->ensureDirectoryExists($sourcePath);
25250
25251
25252  $this->downloadManager->download($package, $sourcePath);
25253
25254
25255  if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
25256 $jsonFile = new JsonFile($composerJsonPath);
25257 $jsonData = $jsonFile->read();
25258 if (!empty($jsonData['archive']['exclude'])) {
25259 $package->setArchiveExcludes($jsonData['archive']['exclude']);
25260 }
25261 }
25262 }
25263
25264
25265  $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
25266 $filesystem->ensureDirectoryExists(dirname($tempTarget));
25267
25268 $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes(), $ignoreFilters);
25269 $filesystem->rename($archivePath, $target);
25270
25271
25272  if (!$package instanceof RootPackageInterface) {
25273 $filesystem->removeDirectory($sourcePath);
25274 }
25275 $filesystem->remove($tempTarget);
25276
25277 return $target;
25278 }
25279 }
25280 <?php
25281
25282
25283
25284
25285
25286
25287
25288
25289
25290
25291
25292 namespace Composer\Package\Archiver;
25293
25294
25295
25296
25297
25298
25299 interface ArchiverInterface
25300 {
25301
25302
25303
25304
25305
25306
25307
25308
25309
25310
25311 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false);
25312
25313
25314
25315
25316
25317
25318
25319
25320
25321 public function supports($format, $sourceType);
25322 }
25323 <?php
25324
25325
25326
25327
25328
25329
25330
25331
25332
25333
25334
25335 namespace Composer\Package\Archiver;
25336
25337 use Symfony\Component\Finder;
25338
25339
25340
25341
25342 abstract class BaseExcludeFilter
25343 {
25344
25345
25346
25347 protected $sourcePath;
25348
25349
25350
25351
25352 protected $excludePatterns;
25353
25354
25355
25356
25357 public function __construct($sourcePath)
25358 {
25359 $this->sourcePath = $sourcePath;
25360 $this->excludePatterns = array();
25361 }
25362
25363
25364
25365
25366
25367
25368
25369
25370
25371
25372
25373 public function filter($relativePath, $exclude)
25374 {
25375 foreach ($this->excludePatterns as $patternData) {
25376 list($pattern, $negate, $stripLeadingSlash) = $patternData;
25377
25378 if ($stripLeadingSlash) {
25379 $path = substr($relativePath, 1);
25380 } else {
25381 $path = $relativePath;
25382 }
25383
25384 if (preg_match($pattern, $path)) {
25385 $exclude = !$negate;
25386 }
25387 }
25388
25389 return $exclude;
25390 }
25391
25392
25393
25394
25395
25396
25397
25398
25399
25400 protected function parseLines(array $lines, $lineParser)
25401 {
25402 return array_filter(
25403 array_map(
25404 function ($line) use ($lineParser) {
25405 $line = trim($line);
25406
25407 if (!$line || 0 === strpos($line, '#')) {
25408 return null;
25409 }
25410
25411 return call_user_func($lineParser, $line);
25412 },
25413 $lines
25414 ),
25415 function ($pattern) {
25416 return $pattern !== null;
25417 }
25418 );
25419 }
25420
25421
25422
25423
25424
25425
25426
25427
25428 protected function generatePatterns($rules)
25429 {
25430 $patterns = array();
25431 foreach ($rules as $rule) {
25432 $patterns[] = $this->generatePattern($rule);
25433 }
25434
25435 return $patterns;
25436 }
25437
25438
25439
25440
25441
25442
25443
25444
25445 protected function generatePattern($rule)
25446 {
25447 $negate = false;
25448 $pattern = '{';
25449
25450 if (strlen($rule) && $rule[0] === '!') {
25451 $negate = true;
25452 $rule = substr($rule, 1);
25453 }
25454
25455 if (strlen($rule) && $rule[0] === '/') {
25456 $pattern .= '^/';
25457 $rule = substr($rule, 1);
25458 } elseif (strlen($rule) - 1 === strpos($rule, '/')) {
25459 $pattern .= '/';
25460 $rule = substr($rule, 0, -1);
25461 } elseif (false === strpos($rule, '/')) {
25462 $pattern .= '/';
25463 }
25464
25465
25466  $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
25467
25468 return array($pattern . '}', $negate, false);
25469 }
25470 }
25471 <?php
25472
25473
25474
25475
25476
25477
25478
25479
25480
25481
25482
25483 namespace Composer\Package\Archiver;
25484
25485
25486
25487
25488
25489
25490 class ComposerExcludeFilter extends BaseExcludeFilter
25491 {
25492
25493
25494
25495
25496 public function __construct($sourcePath, array $excludeRules)
25497 {
25498 parent::__construct($sourcePath);
25499 $this->excludePatterns = $this->generatePatterns($excludeRules);
25500 }
25501 }
25502 <?php
25503
25504
25505
25506
25507
25508
25509
25510
25511
25512
25513
25514 namespace Composer\Package\Archiver;
25515
25516
25517
25518
25519
25520
25521
25522
25523 class GitExcludeFilter extends BaseExcludeFilter
25524 {
25525
25526
25527
25528
25529
25530 public function __construct($sourcePath)
25531 {
25532 parent::__construct($sourcePath);
25533
25534 if (file_exists($sourcePath.'/.gitignore')) {
25535 $this->excludePatterns = $this->parseLines(
25536 file($sourcePath.'/.gitignore'),
25537 array($this, 'parseGitIgnoreLine')
25538 );
25539 }
25540 if (file_exists($sourcePath.'/.gitattributes')) {
25541 $this->excludePatterns = array_merge(
25542 $this->excludePatterns,
25543 $this->parseLines(
25544 file($sourcePath.'/.gitattributes'),
25545 array($this, 'parseGitAttributesLine')
25546 ));
25547 }
25548 }
25549
25550
25551
25552
25553
25554
25555
25556
25557 public function parseGitIgnoreLine($line)
25558 {
25559 return $this->generatePattern($line);
25560 }
25561
25562
25563
25564
25565
25566
25567
25568
25569 public function parseGitAttributesLine($line)
25570 {
25571 $parts = preg_split('#\s+#', $line);
25572
25573 if (count($parts) == 2 && $parts[1] === 'export-ignore') {
25574 return $this->generatePattern($parts[0]);
25575 }
25576
25577 return null;
25578 }
25579 }
25580 <?php
25581
25582
25583
25584
25585
25586
25587
25588
25589
25590
25591
25592 namespace Composer\Package\Archiver;
25593
25594 use Symfony\Component\Finder;
25595
25596
25597
25598
25599
25600
25601 class HgExcludeFilter extends BaseExcludeFilter
25602 {
25603 const HG_IGNORE_REGEX = 1;
25604 const HG_IGNORE_GLOB = 2;
25605
25606
25607
25608
25609
25610 protected $patternMode;
25611
25612
25613
25614
25615
25616
25617 public function __construct($sourcePath)
25618 {
25619 parent::__construct($sourcePath);
25620
25621 $this->patternMode = self::HG_IGNORE_REGEX;
25622
25623 if (file_exists($sourcePath.'/.hgignore')) {
25624 $this->excludePatterns = $this->parseLines(
25625 file($sourcePath.'/.hgignore'),
25626 array($this, 'parseHgIgnoreLine')
25627 );
25628 }
25629 }
25630
25631
25632
25633
25634
25635
25636
25637
25638 public function parseHgIgnoreLine($line)
25639 {
25640 if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) {
25641 if ($matches[1] === 'glob') {
25642 $this->patternMode = self::HG_IGNORE_GLOB;
25643 } else {
25644 $this->patternMode = self::HG_IGNORE_REGEX;
25645 }
25646
25647 return null;
25648 }
25649
25650 if ($this->patternMode == self::HG_IGNORE_GLOB) {
25651 return $this->patternFromGlob($line);
25652 }
25653
25654 return $this->patternFromRegex($line);
25655 }
25656
25657
25658
25659
25660
25661
25662
25663
25664 protected function patternFromGlob($line)
25665 {
25666 $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#';
25667 $pattern = str_replace('[^/]*', '.*', $pattern);
25668
25669 return array($pattern, false, true);
25670 }
25671
25672
25673
25674
25675
25676
25677
25678
25679 public function patternFromRegex($line)
25680 {
25681
25682  $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#';
25683
25684 return array($pattern, false, true);
25685 }
25686 }
25687 <?php
25688
25689
25690
25691
25692
25693
25694
25695
25696
25697
25698
25699 namespace Composer\Package\Archiver;
25700
25701
25702
25703
25704
25705
25706 class PharArchiver implements ArchiverInterface
25707 {
25708 protected static $formats = array(
25709 'zip' => \Phar::ZIP,
25710 'tar' => \Phar::TAR,
25711 'tar.gz' => \Phar::TAR,
25712 'tar.bz2' => \Phar::TAR,
25713 );
25714
25715 protected static $compressFormats = array(
25716 'tar.gz' => \Phar::GZ,
25717 'tar.bz2' => \Phar::BZ2,
25718 );
25719
25720
25721
25722
25723 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
25724 {
25725 $sources = realpath($sources);
25726
25727
25728  if (file_exists($target)) {
25729 unlink($target);
25730 }
25731
25732 try {
25733 $filename = substr($target, 0, strrpos($target, $format) - 1);
25734
25735
25736  if (isset(static::$compressFormats[$format])) {
25737
25738  $target = $filename . '.tar';
25739 }
25740
25741 $phar = new \PharData($target, null, null, static::$formats[$format]);
25742 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
25743 $filesOnly = new ArchivableFilesFilter($files);
25744 $phar->buildFromIterator($filesOnly, $sources);
25745 $filesOnly->addEmptyDir($phar, $sources);
25746
25747 if (isset(static::$compressFormats[$format])) {
25748
25749  if (!$phar->canCompress(static::$compressFormats[$format])) {
25750 throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
25751 }
25752
25753
25754  unlink($target);
25755
25756
25757  $phar->compress(static::$compressFormats[$format]);
25758
25759
25760  $target = $filename . '.' . $format;
25761 }
25762
25763 return $target;
25764 } catch (\UnexpectedValueException $e) {
25765 $message = sprintf("Could not create archive '%s' from '%s': %s",
25766 $target,
25767 $sources,
25768 $e->getMessage()
25769 );
25770
25771 throw new \RuntimeException($message, $e->getCode(), $e);
25772 }
25773 }
25774
25775
25776
25777
25778 public function supports($format, $sourceType)
25779 {
25780 return isset(static::$formats[$format]);
25781 }
25782 }
25783 <?php
25784
25785
25786
25787
25788
25789
25790
25791
25792
25793
25794
25795 namespace Composer\Package\Archiver;
25796
25797 use ZipArchive;
25798 use Composer\Util\Filesystem;
25799
25800
25801
25802
25803 class ZipArchiver implements ArchiverInterface
25804 {
25805 protected static $formats = array(
25806 'zip' => 1,
25807 );
25808
25809
25810
25811
25812 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
25813 {
25814 $fs = new Filesystem();
25815 $sources = $fs->normalizePath($sources);
25816
25817 $zip = new ZipArchive();
25818 $res = $zip->open($target, ZipArchive::CREATE);
25819 if ($res === true) {
25820 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
25821 foreach ($files as $file) {
25822
25823 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
25824 $localname = str_replace($sources.'/', '', $filepath);
25825 if ($file->isDir()) {
25826 $zip->addEmptyDir($localname);
25827 } else {
25828 $zip->addFile($filepath, $localname);
25829 }
25830 }
25831 if ($zip->close()) {
25832 return $target;
25833 }
25834 }
25835 $message = sprintf("Could not create archive '%s' from '%s': %s",
25836 $target,
25837 $sources,
25838 $zip->getStatusString()
25839 );
25840 throw new \RuntimeException($message);
25841 }
25842
25843
25844
25845
25846 public function supports($format, $sourceType)
25847 {
25848 return isset(static::$formats[$format]) && $this->compressionAvailable();
25849 }
25850
25851 private function compressionAvailable()
25852 {
25853 return class_exists('ZipArchive');
25854 }
25855 }
25856 <?php
25857
25858
25859
25860
25861
25862
25863
25864
25865
25866
25867
25868 namespace Composer\Package;
25869
25870 use Composer\Repository\RepositoryInterface;
25871 use Composer\Repository\PlatformRepository;
25872
25873
25874
25875
25876
25877
25878 abstract class BasePackage implements PackageInterface
25879 {
25880 public static $supportedLinkTypes = array(
25881 'require' => array('description' => 'requires', 'method' => 'requires'),
25882 'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
25883 'provide' => array('description' => 'provides', 'method' => 'provides'),
25884 'replace' => array('description' => 'replaces', 'method' => 'replaces'),
25885 'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
25886 );
25887
25888 const STABILITY_STABLE = 0;
25889 const STABILITY_RC = 5;
25890 const STABILITY_BETA = 10;
25891 const STABILITY_ALPHA = 15;
25892 const STABILITY_DEV = 20;
25893
25894 public static $stabilities = array(
25895 'stable' => self::STABILITY_STABLE,
25896 'RC' => self::STABILITY_RC,
25897 'beta' => self::STABILITY_BETA,
25898 'alpha' => self::STABILITY_ALPHA,
25899 'dev' => self::STABILITY_DEV,
25900 );
25901
25902
25903
25904
25905
25906 public $id;
25907
25908 protected $name;
25909
25910 protected $prettyName;
25911
25912 protected $repository;
25913
25914 protected $transportOptions = array();
25915
25916
25917
25918
25919
25920
25921 public function __construct($name)
25922 {
25923 $this->prettyName = $name;
25924 $this->name = strtolower($name);
25925 $this->id = -1;
25926 }
25927
25928
25929
25930
25931 public function getName()
25932 {
25933 return $this->name;
25934 }
25935
25936
25937
25938
25939 public function getPrettyName()
25940 {
25941 return $this->prettyName;
25942 }
25943
25944
25945
25946
25947 public function getNames()
25948 {
25949 $names = array(
25950 $this->getName() => true,
25951 );
25952
25953 foreach ($this->getProvides() as $link) {
25954 $names[$link->getTarget()] = true;
25955 }
25956
25957 foreach ($this->getReplaces() as $link) {
25958 $names[$link->getTarget()] = true;
25959 }
25960
25961 return array_keys($names);
25962 }
25963
25964
25965
25966
25967 public function setId($id)
25968 {
25969 $this->id = $id;
25970 }
25971
25972
25973
25974
25975 public function getId()
25976 {
25977 return $this->id;
25978 }
25979
25980
25981
25982
25983 public function setRepository(RepositoryInterface $repository)
25984 {
25985 if ($this->repository && $repository !== $this->repository) {
25986 throw new \LogicException('A package can only be added to one repository');
25987 }
25988 $this->repository = $repository;
25989 }
25990
25991
25992
25993
25994 public function getRepository()
25995 {
25996 return $this->repository;
25997 }
25998
25999
26000
26001
26002 public function getTransportOptions()
26003 {
26004 return $this->transportOptions;
26005 }
26006
26007
26008
26009
26010
26011
26012 public function setTransportOptions(array $options)
26013 {
26014 $this->transportOptions = $options;
26015 }
26016
26017
26018
26019
26020
26021
26022 public function isPlatform()
26023 {
26024 return $this->getRepository() instanceof PlatformRepository;
26025 }
26026
26027
26028
26029
26030
26031
26032 public function getUniqueName()
26033 {
26034 return $this->getName().'-'.$this->getVersion();
26035 }
26036
26037 public function equals(PackageInterface $package)
26038 {
26039 $self = $this;
26040 if ($this instanceof AliasPackage) {
26041 $self = $this->getAliasOf();
26042 }
26043 if ($package instanceof AliasPackage) {
26044 $package = $package->getAliasOf();
26045 }
26046
26047 return $package === $self;
26048 }
26049
26050
26051
26052
26053
26054
26055 public function __toString()
26056 {
26057 return $this->getUniqueName();
26058 }
26059
26060 public function getPrettyString()
26061 {
26062 return $this->getPrettyName().' '.$this->getPrettyVersion();
26063 }
26064
26065
26066
26067
26068 public function getFullPrettyVersion($truncate = true)
26069 {
26070 if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
26071 return $this->getPrettyVersion();
26072 }
26073
26074
26075  if ($truncate && strlen($this->getSourceReference()) === 40) {
26076 return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
26077 }
26078
26079 return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
26080 }
26081
26082 public function getStabilityPriority()
26083 {
26084 return self::$stabilities[$this->getStability()];
26085 }
26086
26087 public function __clone()
26088 {
26089 $this->repository = null;
26090 $this->id = -1;
26091 }
26092 }
26093 <?php
26094
26095
26096
26097
26098
26099
26100
26101
26102
26103
26104
26105 namespace Composer\Package;
26106
26107
26108
26109
26110
26111
26112 class CompletePackage extends Package implements CompletePackageInterface
26113 {
26114 protected $repositories;
26115 protected $license = array();
26116 protected $keywords;
26117 protected $authors;
26118 protected $description;
26119 protected $homepage;
26120 protected $scripts = array();
26121 protected $support = array();
26122 protected $abandoned = false;
26123
26124
26125
26126
26127 public function setScripts(array $scripts)
26128 {
26129 $this->scripts = $scripts;
26130 }
26131
26132
26133
26134
26135 public function getScripts()
26136 {
26137 return $this->scripts;
26138 }
26139
26140
26141
26142
26143
26144
26145 public function setRepositories($repositories)
26146 {
26147 $this->repositories = $repositories;
26148 }
26149
26150
26151
26152
26153 public function getRepositories()
26154 {
26155 return $this->repositories;
26156 }
26157
26158
26159
26160
26161
26162
26163 public function setLicense(array $license)
26164 {
26165 $this->license = $license;
26166 }
26167
26168
26169
26170
26171 public function getLicense()
26172 {
26173 return $this->license;
26174 }
26175
26176
26177
26178
26179
26180
26181 public function setKeywords(array $keywords)
26182 {
26183 $this->keywords = $keywords;
26184 }
26185
26186
26187
26188
26189 public function getKeywords()
26190 {
26191 return $this->keywords;
26192 }
26193
26194
26195
26196
26197
26198
26199 public function setAuthors(array $authors)
26200 {
26201 $this->authors = $authors;
26202 }
26203
26204
26205
26206
26207 public function getAuthors()
26208 {
26209 return $this->authors;
26210 }
26211
26212
26213
26214
26215
26216
26217 public function setDescription($description)
26218 {
26219 $this->description = $description;
26220 }
26221
26222
26223
26224
26225 public function getDescription()
26226 {
26227 return $this->description;
26228 }
26229
26230
26231
26232
26233
26234
26235 public function setHomepage($homepage)
26236 {
26237 $this->homepage = $homepage;
26238 }
26239
26240
26241
26242
26243 public function getHomepage()
26244 {
26245 return $this->homepage;
26246 }
26247
26248
26249
26250
26251
26252
26253 public function setSupport(array $support)
26254 {
26255 $this->support = $support;
26256 }
26257
26258
26259
26260
26261 public function getSupport()
26262 {
26263 return $this->support;
26264 }
26265
26266
26267
26268
26269 public function isAbandoned()
26270 {
26271 return (bool) $this->abandoned;
26272 }
26273
26274
26275
26276
26277 public function setAbandoned($abandoned)
26278 {
26279 $this->abandoned = $abandoned;
26280 }
26281
26282
26283
26284
26285
26286
26287 public function getReplacementPackage()
26288 {
26289 return is_string($this->abandoned) ? $this->abandoned : null;
26290 }
26291 }
26292 <?php
26293
26294
26295
26296
26297
26298
26299
26300
26301
26302
26303
26304 namespace Composer\Package;
26305
26306
26307
26308
26309
26310
26311 interface CompletePackageInterface extends PackageInterface
26312 {
26313
26314
26315
26316
26317
26318 public function getScripts();
26319
26320
26321
26322
26323
26324
26325
26326
26327 public function getRepositories();
26328
26329
26330
26331
26332
26333
26334 public function getLicense();
26335
26336
26337
26338
26339
26340
26341 public function getKeywords();
26342
26343
26344
26345
26346
26347
26348 public function getDescription();
26349
26350
26351
26352
26353
26354
26355 public function getHomepage();
26356
26357
26358
26359
26360
26361
26362
26363
26364 public function getAuthors();
26365
26366
26367
26368
26369
26370
26371 public function getSupport();
26372
26373
26374
26375
26376
26377
26378 public function isAbandoned();
26379
26380
26381
26382
26383
26384
26385 public function getReplacementPackage();
26386 }
26387 <?php
26388
26389
26390
26391
26392
26393
26394
26395
26396
26397
26398
26399 namespace Composer\Package\Dumper;
26400
26401 use Composer\Package\BasePackage;
26402 use Composer\Package\PackageInterface;
26403 use Composer\Package\CompletePackageInterface;
26404 use Composer\Package\RootPackageInterface;
26405
26406
26407
26408
26409
26410 class ArrayDumper
26411 {
26412 public function dump(PackageInterface $package)
26413 {
26414 $keys = array(
26415 'binaries' => 'bin',
26416 'type',
26417 'extra',
26418 'installationSource' => 'installation-source',
26419 'autoload',
26420 'devAutoload' => 'autoload-dev',
26421 'notificationUrl' => 'notification-url',
26422 'includePaths' => 'include-path',
26423 );
26424
26425 $data = array();
26426 $data['name'] = $package->getPrettyName();
26427 $data['version'] = $package->getPrettyVersion();
26428 $data['version_normalized'] = $package->getVersion();
26429
26430 if ($package->getTargetDir()) {
26431 $data['target-dir'] = $package->getTargetDir();
26432 }
26433
26434 if ($package->getSourceType()) {
26435 $data['source']['type'] = $package->getSourceType();
26436 $data['source']['url'] = $package->getSourceUrl();
26437 $data['source']['reference'] = $package->getSourceReference();
26438 if ($mirrors = $package->getSourceMirrors()) {
26439 $data['source']['mirrors'] = $mirrors;
26440 }
26441 }
26442
26443 if ($package->getDistType()) {
26444 $data['dist']['type'] = $package->getDistType();
26445 $data['dist']['url'] = $package->getDistUrl();
26446 $data['dist']['reference'] = $package->getDistReference();
26447 $data['dist']['shasum'] = $package->getDistSha1Checksum();
26448 if ($mirrors = $package->getDistMirrors()) {
26449 $data['dist']['mirrors'] = $mirrors;
26450 }
26451 }
26452
26453 if ($package->getArchiveExcludes()) {
26454 $data['archive']['exclude'] = $package->getArchiveExcludes();
26455 }
26456
26457 foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
26458 if ($links = $package->{'get'.ucfirst($opts['method'])}()) {
26459 foreach ($links as $link) {
26460 $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
26461 }
26462 ksort($data[$type]);
26463 }
26464 }
26465
26466 if ($packages = $package->getSuggests()) {
26467 ksort($packages);
26468 $data['suggest'] = $packages;
26469 }
26470
26471 if ($package->getReleaseDate()) {
26472 $data['time'] = $package->getReleaseDate()->format(DATE_RFC3339);
26473 }
26474
26475 $data = $this->dumpValues($package, $keys, $data);
26476
26477 if ($package instanceof CompletePackageInterface) {
26478 $keys = array(
26479 'scripts',
26480 'license',
26481 'authors',
26482 'description',
26483 'homepage',
26484 'keywords',
26485 'repositories',
26486 'support',
26487 );
26488
26489 $data = $this->dumpValues($package, $keys, $data);
26490
26491 if (isset($data['keywords']) && is_array($data['keywords'])) {
26492 sort($data['keywords']);
26493 }
26494
26495 if ($package->isAbandoned()) {
26496 $data['abandoned'] = $package->getReplacementPackage() ?: true;
26497 }
26498 }
26499
26500 if ($package instanceof RootPackageInterface) {
26501 $minimumStability = $package->getMinimumStability();
26502 if ($minimumStability) {
26503 $data['minimum-stability'] = $minimumStability;
26504 }
26505 }
26506
26507 if (count($package->getTransportOptions()) > 0) {
26508 $data['transport-options'] = $package->getTransportOptions();
26509 }
26510
26511 return $data;
26512 }
26513
26514 private function dumpValues(PackageInterface $package, array $keys, array $data)
26515 {
26516 foreach ($keys as $method => $key) {
26517 if (is_numeric($method)) {
26518 $method = $key;
26519 }
26520
26521 $getter = 'get'.ucfirst($method);
26522 $value = $package->$getter();
26523
26524 if (null !== $value && !(is_array($value) && 0 === count($value))) {
26525 $data[$key] = $value;
26526 }
26527 }
26528
26529 return $data;
26530 }
26531 }
26532 <?php
26533
26534
26535
26536
26537
26538
26539
26540
26541
26542
26543
26544 namespace Composer\Package;
26545
26546 use Composer\Semver\Constraint\ConstraintInterface;
26547
26548
26549
26550
26551
26552
26553 class Link
26554 {
26555
26556
26557
26558 protected $source;
26559
26560
26561
26562
26563 protected $target;
26564
26565
26566
26567
26568 protected $constraint;
26569
26570
26571
26572
26573 protected $description;
26574
26575
26576
26577
26578 protected $prettyConstraint;
26579
26580
26581
26582
26583
26584
26585
26586
26587
26588
26589 public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
26590 {
26591 $this->source = strtolower($source);
26592 $this->target = strtolower($target);
26593 $this->constraint = $constraint;
26594 $this->description = $description;
26595 $this->prettyConstraint = $prettyConstraint;
26596 }
26597
26598
26599
26600
26601 public function getDescription()
26602 {
26603 return $this->description;
26604 }
26605
26606
26607
26608
26609 public function getSource()
26610 {
26611 return $this->source;
26612 }
26613
26614
26615
26616
26617 public function getTarget()
26618 {
26619 return $this->target;
26620 }
26621
26622
26623
26624
26625 public function getConstraint()
26626 {
26627 return $this->constraint;
26628 }
26629
26630
26631
26632
26633
26634 public function getPrettyConstraint()
26635 {
26636 if (null === $this->prettyConstraint) {
26637 throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
26638 }
26639
26640 return $this->prettyConstraint;
26641 }
26642
26643
26644
26645
26646 public function __toString()
26647 {
26648 return $this->source.' '.$this->description.' '.$this->target.' ('.$this->constraint.')';
26649 }
26650
26651
26652
26653
26654
26655 public function getPrettyString(PackageInterface $sourcePackage)
26656 {
26657 return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
26658 }
26659 }
26660 <?php
26661
26662
26663
26664
26665
26666
26667
26668
26669
26670
26671
26672 namespace Composer\Package\LinkConstraint;
26673
26674 use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint;
26675
26676 trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
26677
26678
26679
26680
26681 class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
26682 {
26683 }
26684 <?php
26685
26686
26687
26688
26689
26690
26691
26692
26693
26694
26695
26696 namespace Composer\Package\LinkConstraint;
26697
26698 use Composer\Semver\Constraint\ConstraintInterface;
26699
26700 trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
26701
26702
26703
26704
26705 interface LinkConstraintInterface extends ConstraintInterface
26706 {
26707 }
26708 <?php
26709
26710
26711
26712
26713
26714
26715
26716
26717
26718
26719
26720 namespace Composer\Package\LinkConstraint;
26721
26722 use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint;
26723
26724 trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
26725
26726
26727
26728
26729 class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface
26730 {
26731 }
26732 <?php
26733
26734
26735
26736
26737
26738
26739
26740
26741
26742
26743
26744 namespace Composer\Package\LinkConstraint;
26745
26746 use Composer\Semver\Constraint\AbstractConstraint;
26747
26748 trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, there is no replacement for it.', E_USER_DEPRECATED);
26749
26750
26751
26752
26753 abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
26754 {
26755 }
26756 <?php
26757
26758
26759
26760
26761
26762
26763
26764
26765
26766
26767
26768 namespace Composer\Package\LinkConstraint;
26769
26770 use Composer\Semver\Constraint\Constraint;
26771
26772 trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
26773
26774
26775
26776
26777 class VersionConstraint extends Constraint implements LinkConstraintInterface
26778 {
26779 }
26780 <?php
26781
26782
26783
26784
26785
26786
26787
26788
26789
26790
26791
26792 namespace Composer\Package\Loader;
26793
26794 use Composer\Package;
26795 use Composer\Package\AliasPackage;
26796 use Composer\Package\Link;
26797 use Composer\Package\RootAliasPackage;
26798 use Composer\Package\RootPackageInterface;
26799 use Composer\Package\Version\VersionParser;
26800 use Composer\Semver\VersionParser as SemverVersionParser;
26801
26802
26803
26804
26805
26806 class ArrayLoader implements LoaderInterface
26807 {
26808 protected $versionParser;
26809 protected $loadOptions;
26810
26811 public function __construct(SemverVersionParser $parser = null, $loadOptions = false)
26812 {
26813 if (!$parser) {
26814 $parser = new VersionParser;
26815 }
26816 $this->versionParser = $parser;
26817 $this->loadOptions = $loadOptions;
26818 }
26819
26820 public function load(array $config, $class = 'Composer\Package\CompletePackage')
26821 {
26822 if (!isset($config['name'])) {
26823 throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
26824 }
26825 if (!isset($config['version'])) {
26826 throw new \UnexpectedValueException('Package '.$config['name'].' has no version defined.');
26827 }
26828
26829
26830  if (isset($config['version_normalized'])) {
26831 $version = $config['version_normalized'];
26832 } else {
26833 $version = $this->versionParser->normalize($config['version']);
26834 }
26835 $package = new $class($config['name'], $version, $config['version']);
26836 $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
26837
26838 if (isset($config['target-dir'])) {
26839 $package->setTargetDir($config['target-dir']);
26840 }
26841
26842 if (isset($config['extra']) && is_array($config['extra'])) {
26843 $package->setExtra($config['extra']);
26844 }
26845
26846 if (isset($config['bin'])) {
26847 foreach ((array) $config['bin'] as $key => $bin) {
26848 $config['bin'][$key] = ltrim($bin, '/');
26849 }
26850 $package->setBinaries((array) $config['bin']);
26851 }
26852
26853 if (isset($config['installation-source'])) {
26854 $package->setInstallationSource($config['installation-source']);
26855 }
26856
26857 if (isset($config['source'])) {
26858 if (!isset($config['source']['type']) || !isset($config['source']['url']) || !isset($config['source']['reference'])) {
26859 throw new \UnexpectedValueException(sprintf(
26860 "Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.",
26861 $config['name'],
26862 json_encode($config['source'])
26863 ));
26864 }
26865 $package->setSourceType($config['source']['type']);
26866 $package->setSourceUrl($config['source']['url']);
26867 $package->setSourceReference($config['source']['reference']);
26868 if (isset($config['source']['mirrors'])) {
26869 $package->setSourceMirrors($config['source']['mirrors']);
26870 }
26871 }
26872
26873 if (isset($config['dist'])) {
26874 if (!isset($config['dist']['type'])
26875 || !isset($config['dist']['url'])) {
26876 throw new \UnexpectedValueException(sprintf(
26877 "Package %s's dist key should be specified as ".
26878 "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.",
26879 $config['name'],
26880 json_encode($config['dist'])
26881 ));
26882 }
26883 $package->setDistType($config['dist']['type']);
26884 $package->setDistUrl($config['dist']['url']);
26885 $package->setDistReference(isset($config['dist']['reference']) ? $config['dist']['reference'] : null);
26886 $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
26887 if (isset($config['dist']['mirrors'])) {
26888 $package->setDistMirrors($config['dist']['mirrors']);
26889 }
26890 }
26891
26892 foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
26893 if (isset($config[$type])) {
26894 $method = 'set'.ucfirst($opts['method']);
26895 $package->{$method}(
26896 $this->parseLinks(
26897 $package->getName(),
26898 $package->getPrettyVersion(),
26899 $opts['description'],
26900 $config[$type]
26901 )
26902 );
26903 }
26904 }
26905
26906 if (isset($config['suggest']) && is_array($config['suggest'])) {
26907 foreach ($config['suggest'] as $target => $reason) {
26908 if ('self.version' === trim($reason)) {
26909 $config['suggest'][$target] = $package->getPrettyVersion();
26910 }
26911 }
26912 $package->setSuggests($config['suggest']);
26913 }
26914
26915 if (isset($config['autoload'])) {
26916 $package->setAutoload($config['autoload']);
26917 }
26918
26919 if (isset($config['autoload-dev'])) {
26920 $package->setDevAutoload($config['autoload-dev']);
26921 }
26922
26923 if (isset($config['include-path'])) {
26924 $package->setIncludePaths($config['include-path']);
26925 }
26926
26927 if (!empty($config['time'])) {
26928 $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
26929
26930 try {
26931 $date = new \DateTime($time, new \DateTimeZone('UTC'));
26932 $package->setReleaseDate($date);
26933 } catch (\Exception $e) {
26934 }
26935 }
26936
26937 if (!empty($config['notification-url'])) {
26938 $package->setNotificationUrl($config['notification-url']);
26939 }
26940
26941 if (!empty($config['archive']['exclude'])) {
26942 $package->setArchiveExcludes($config['archive']['exclude']);
26943 }
26944
26945 if ($package instanceof Package\CompletePackageInterface) {
26946 if (isset($config['scripts']) && is_array($config['scripts'])) {
26947 foreach ($config['scripts'] as $event => $listeners) {
26948 $config['scripts'][$event] = (array) $listeners;
26949 }
26950 if (isset($config['scripts']['composer'])) {
26951 trigger_error('The `composer` script name is reserved for internal use, please avoid defining it', E_USER_DEPRECATED);
26952 }
26953 $package->setScripts($config['scripts']);
26954 }
26955
26956 if (!empty($config['description']) && is_string($config['description'])) {
26957 $package->setDescription($config['description']);
26958 }
26959
26960 if (!empty($config['homepage']) && is_string($config['homepage'])) {
26961 $package->setHomepage($config['homepage']);
26962 }
26963
26964 if (!empty($config['keywords']) && is_array($config['keywords'])) {
26965 $package->setKeywords($config['keywords']);
26966 }
26967
26968 if (!empty($config['license'])) {
26969 $package->setLicense(is_array($config['license']) ? $config['license'] : array($config['license']));
26970 }
26971
26972 if (!empty($config['authors']) && is_array($config['authors'])) {
26973 $package->setAuthors($config['authors']);
26974 }
26975
26976 if (isset($config['support'])) {
26977 $package->setSupport($config['support']);
26978 }
26979
26980 if (isset($config['abandoned'])) {
26981 $package->setAbandoned($config['abandoned']);
26982 }
26983 }
26984
26985 if ($aliasNormalized = $this->getBranchAlias($config)) {
26986 if ($package instanceof RootPackageInterface) {
26987 $package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
26988 } else {
26989 $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
26990 }
26991 }
26992
26993 if ($this->loadOptions && isset($config['transport-options'])) {
26994 $package->setTransportOptions($config['transport-options']);
26995 }
26996
26997 return $package;
26998 }
26999
27000
27001
27002
27003
27004
27005
27006
27007 public function parseLinks($source, $sourceVersion, $description, $links)
27008 {
27009 $res = array();
27010 foreach ($links as $target => $constraint) {
27011 if (!is_string($constraint)) {
27012 throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($constraint) . ' (' . var_export($constraint, true) . ')');
27013 }
27014 if ('self.version' === $constraint) {
27015 $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
27016 } else {
27017 $parsedConstraint = $this->versionParser->parseConstraints($constraint);
27018 }
27019
27020 $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
27021 }
27022
27023 return $res;
27024 }
27025
27026
27027
27028
27029
27030
27031
27032 public function getBranchAlias(array $config)
27033 {
27034 if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
27035 || !isset($config['extra']['branch-alias'])
27036 || !is_array($config['extra']['branch-alias'])
27037 ) {
27038 return;
27039 }
27040
27041 foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
27042
27043  if ('-dev' !== substr($targetBranch, -4)) {
27044 continue;
27045 }
27046
27047
27048  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
27049 if ('-dev' !== substr($validatedTargetBranch, -4)) {
27050 continue;
27051 }
27052
27053
27054  if (strtolower($config['version']) !== strtolower($sourceBranch)) {
27055 continue;
27056 }
27057
27058
27059  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
27060 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
27061 && (stripos($targetPrefix, $sourcePrefix) !== 0)
27062 ) {
27063 continue;
27064 }
27065
27066 return $validatedTargetBranch;
27067 }
27068 }
27069 }
27070 <?php
27071
27072
27073
27074
27075
27076
27077
27078
27079
27080
27081
27082 namespace Composer\Package\Loader;
27083
27084
27085
27086
27087 class InvalidPackageException extends \Exception
27088 {
27089 private $errors;
27090 private $warnings;
27091 private $data;
27092
27093 public function __construct(array $errors, array $warnings, array $data)
27094 {
27095 $this->errors = $errors;
27096 $this->warnings = $warnings;
27097 $this->data = $data;
27098 parent::__construct("Invalid package information: \n".implode("\n", array_merge($errors, $warnings)));
27099 }
27100
27101 public function getData()
27102 {
27103 return $this->data;
27104 }
27105
27106 public function getErrors()
27107 {
27108 return $this->errors;
27109 }
27110
27111 public function getWarnings()
27112 {
27113 return $this->warnings;
27114 }
27115 }
27116 <?php
27117
27118
27119
27120
27121
27122
27123
27124
27125
27126
27127
27128 namespace Composer\Package\Loader;
27129
27130 use Composer\Json\JsonFile;
27131
27132
27133
27134
27135 class JsonLoader
27136 {
27137 private $loader;
27138
27139 public function __construct(LoaderInterface $loader)
27140 {
27141 $this->loader = $loader;
27142 }
27143
27144
27145
27146
27147
27148 public function load($json)
27149 {
27150 if ($json instanceof JsonFile) {
27151 $config = $json->read();
27152 } elseif (file_exists($json)) {
27153 $config = JsonFile::parseJson(file_get_contents($json), $json);
27154 } elseif (is_string($json)) {
27155 $config = JsonFile::parseJson($json);
27156 }
27157
27158 return $this->loader->load($config);
27159 }
27160 }
27161 <?php
27162
27163
27164
27165
27166
27167
27168
27169
27170
27171
27172
27173 namespace Composer\Package\Loader;
27174
27175
27176
27177
27178
27179
27180 interface LoaderInterface
27181 {
27182
27183
27184
27185
27186
27187
27188
27189 public function load(array $package, $class = 'Composer\Package\CompletePackage');
27190 }
27191 <?php
27192
27193
27194
27195
27196
27197
27198
27199
27200
27201
27202
27203 namespace Composer\Package\Loader;
27204
27205 use Composer\Package\BasePackage;
27206 use Composer\Package\AliasPackage;
27207 use Composer\Config;
27208 use Composer\Package\RootPackageInterface;
27209 use Composer\Repository\RepositoryFactory;
27210 use Composer\Package\Version\VersionGuesser;
27211 use Composer\Package\Version\VersionParser;
27212 use Composer\Repository\RepositoryManager;
27213 use Composer\Util\ProcessExecutor;
27214
27215
27216
27217
27218
27219
27220
27221
27222 class RootPackageLoader extends ArrayLoader
27223 {
27224
27225
27226
27227 private $manager;
27228
27229
27230
27231
27232 private $config;
27233
27234
27235
27236
27237 private $versionGuesser;
27238
27239 public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null)
27240 {
27241 parent::__construct($parser);
27242
27243 $this->manager = $manager;
27244 $this->config = $config;
27245 $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
27246 }
27247
27248
27249
27250
27251
27252
27253
27254 public function load(array $config, $class = 'Composer\Package\RootPackage', $cwd = null)
27255 {
27256 if (!isset($config['name'])) {
27257 $config['name'] = '__root__';
27258 }
27259 $autoVersioned = false;
27260 if (!isset($config['version'])) {
27261 $commit = null;
27262
27263
27264  if (getenv('COMPOSER_ROOT_VERSION')) {
27265 $config['version'] = getenv('COMPOSER_ROOT_VERSION');
27266 } else {
27267 $versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
27268 if ($versionData) {
27269 $config['version'] = $versionData['pretty_version'];
27270 $config['version_normalized'] = $versionData['version'];
27271 $commit = $versionData['commit'];
27272 }
27273 }
27274
27275 if (!isset($config['version'])) {
27276 $config['version'] = '1.0.0';
27277 $autoVersioned = true;
27278 }
27279
27280 if ($commit) {
27281 $config['source'] = array(
27282 'type' => '',
27283 'url' => '',
27284 'reference' => $commit,
27285 );
27286 $config['dist'] = array(
27287 'type' => '',
27288 'url' => '',
27289 'reference' => $commit,
27290 );
27291 }
27292 }
27293
27294 $realPackage = $package = parent::load($config, $class);
27295 if ($realPackage instanceof AliasPackage) {
27296 $realPackage = $package->getAliasOf();
27297 }
27298
27299 if ($autoVersioned) {
27300 $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
27301 }
27302
27303 if (isset($config['minimum-stability'])) {
27304 $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
27305 }
27306
27307 $aliases = array();
27308 $stabilityFlags = array();
27309 $references = array();
27310 foreach (array('require', 'require-dev') as $linkType) {
27311 if (isset($config[$linkType])) {
27312 $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
27313 $method = 'get'.ucfirst($linkInfo['method']);
27314 $links = array();
27315 foreach ($realPackage->$method() as $link) {
27316 $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
27317 }
27318 $aliases = $this->extractAliases($links, $aliases);
27319 $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
27320 $references = $this->extractReferences($links, $references);
27321 }
27322 }
27323
27324 if (isset($links[$config['name']])) {
27325 throw new \InvalidArgumentException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL .
27326 'Did you accidentally name your root package after an external package?', $config['name']));
27327 }
27328
27329 $realPackage->setAliases($aliases);
27330 $realPackage->setStabilityFlags($stabilityFlags);
27331 $realPackage->setReferences($references);
27332
27333 if (isset($config['prefer-stable'])) {
27334 $realPackage->setPreferStable((bool) $config['prefer-stable']);
27335 }
27336
27337 if (isset($config['config'])) {
27338 $realPackage->setConfig($config['config']);
27339 }
27340
27341 $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
27342 foreach ($repos as $repo) {
27343 $this->manager->addRepository($repo);
27344 }
27345 $realPackage->setRepositories($this->config->getRepositories());
27346
27347 return $package;
27348 }
27349
27350 private function extractAliases(array $requires, array $aliases)
27351 {
27352 foreach ($requires as $reqName => $reqVersion) {
27353 if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
27354 $aliases[] = array(
27355 'package' => strtolower($reqName),
27356 'version' => $this->versionParser->normalize($match[1], $reqVersion),
27357 'alias' => $match[2],
27358 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
27359 );
27360 }
27361 }
27362
27363 return $aliases;
27364 }
27365
27366 private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
27367 {
27368 $stabilities = BasePackage::$stabilities;
27369 $minimumStability = $stabilities[$minimumStability];
27370 foreach ($requires as $reqName => $reqVersion) {
27371 $constraints = array();
27372
27373
27374  $orSplit = preg_split('{\s*\|\|?\s*}', trim($reqVersion));
27375 foreach ($orSplit as $orConstraint) {
27376 $andSplit = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
27377 foreach ($andSplit as $andConstraint) {
27378 $constraints[] = $andConstraint;
27379 }
27380 }
27381
27382
27383  $match = false;
27384 foreach ($constraints as $constraint) {
27385 if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
27386 $name = strtolower($reqName);
27387 $stability = $stabilities[VersionParser::normalizeStability($match[1])];
27388
27389 if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
27390 continue;
27391 }
27392 $stabilityFlags[$name] = $stability;
27393 $match = true;
27394 }
27395 }
27396
27397 if ($match) {
27398 continue;
27399 }
27400
27401 foreach ($constraints as $constraint) {
27402
27403  
27404  $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
27405 if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
27406 $name = strtolower($reqName);
27407 $stability = $stabilities[$stabilityName];
27408 if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
27409 continue;
27410 }
27411 $stabilityFlags[$name] = $stability;
27412 }
27413 }
27414 }
27415
27416 return $stabilityFlags;
27417 }
27418
27419 private function extractReferences(array $requires, array $references)
27420 {
27421 foreach ($requires as $reqName => $reqVersion) {
27422 $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
27423 if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === ($stabilityName = VersionParser::parseStability($reqVersion))) {
27424 $name = strtolower($reqName);
27425 $references[$name] = $match[1];
27426 }
27427 }
27428
27429 return $references;
27430 }
27431 }
27432 <?php
27433
27434
27435
27436
27437
27438
27439
27440
27441
27442
27443
27444 namespace Composer\Package\Loader;
27445
27446 use Composer\Package;
27447 use Composer\Package\BasePackage;
27448 use Composer\Semver\Constraint\Constraint;
27449 use Composer\Package\Version\VersionParser;
27450 use Composer\Repository\PlatformRepository;
27451 use Composer\Spdx\SpdxLicenses;
27452
27453
27454
27455
27456 class ValidatingArrayLoader implements LoaderInterface
27457 {
27458 const CHECK_ALL = 3;
27459 const CHECK_UNBOUND_CONSTRAINTS = 1;
27460 const CHECK_STRICT_CONSTRAINTS = 2;
27461
27462 private $loader;
27463 private $versionParser;
27464 private $errors;
27465 private $warnings;
27466 private $config;
27467 private $strictName;
27468 private $flags;
27469
27470 public function __construct(LoaderInterface $loader, $strictName = true, VersionParser $parser = null, $flags = 0)
27471 {
27472 $this->loader = $loader;
27473 $this->versionParser = $parser ?: new VersionParser();
27474 $this->strictName = $strictName;
27475 $this->flags = $flags;
27476 }
27477
27478 public function load(array $config, $class = 'Composer\Package\CompletePackage')
27479 {
27480 $this->errors = array();
27481 $this->warnings = array();
27482 $this->config = $config;
27483
27484 if ($this->strictName) {
27485 $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
27486 } else {
27487 $this->validateString('name', true);
27488 }
27489
27490 if (!empty($this->config['version'])) {
27491 try {
27492 $this->versionParser->normalize($this->config['version']);
27493 } catch (\Exception $e) {
27494 $this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
27495 unset($this->config['version']);
27496 }
27497 }
27498
27499 if (!empty($this->config['config']['platform'])) {
27500 foreach ((array) $this->config['config']['platform'] as $key => $platform) {
27501 try {
27502 $this->versionParser->normalize($platform);
27503 } catch (\Exception $e) {
27504 $this->errors[] = 'config.platform.' . $key . ' : invalid value ('.$platform.'): '.$e->getMessage();
27505 }
27506 }
27507 }
27508
27509 $this->validateRegex('type', '[A-Za-z0-9-]+');
27510 $this->validateString('target-dir');
27511 $this->validateArray('extra');
27512
27513 if (isset($this->config['bin'])) {
27514 if (is_string($this->config['bin'])) {
27515 $this->validateString('bin');
27516 } else {
27517 $this->validateFlatArray('bin');
27518 }
27519 }
27520
27521 $this->validateArray('scripts'); 
27522  $this->validateString('description');
27523 $this->validateUrl('homepage');
27524 $this->validateFlatArray('keywords', '[\p{N}\p{L} ._-]+');
27525
27526 if (isset($this->config['license'])) {
27527 if (is_string($this->config['license'])) {
27528 $this->validateRegex('license', '[A-Za-z0-9+. ()-]+');
27529 } else {
27530 $this->validateFlatArray('license', '[A-Za-z0-9+. ()-]+');
27531 }
27532
27533 if (is_array($this->config['license']) || is_string($this->config['license'])) {
27534 $licenses = (array) $this->config['license'];
27535
27536
27537  foreach ($licenses as $key => $license) {
27538 if ('proprietary' === $license) {
27539 unset($licenses[$key]);
27540 }
27541 }
27542
27543 $licenseValidator = new SpdxLicenses();
27544 if (count($licenses) === 1 && !$licenseValidator->validate($licenses) && $licenseValidator->validate(trim($licenses[0]))) {
27545 $this->warnings[] = sprintf(
27546 'License %s must not contain extra spaces, make sure to trim it.',
27547 json_encode($this->config['license'])
27548 );
27549 } elseif (array() !== $licenses && !$licenseValidator->validate($licenses)) {
27550 $this->warnings[] = sprintf(
27551 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.' . PHP_EOL .
27552 'If the software is closed-source, you may use "proprietary" as license.',
27553 json_encode($this->config['license'])
27554 );
27555 } else {
27556 foreach ($licenses as $license) {
27557 $spdxLicense = $licenseValidator->getLicenseByIdentifier($license);
27558 if ($spdxLicense && $spdxLicense[3]) {
27559 if (preg_match('{^[AL]?GPL-[123](\.[01])?\+?$}i', $license)) {
27560 $this->warnings[] = sprintf(
27561 'License "%s" is a deprecated SPDX license identifier, use "'.$license.'-only" or "'.$license.'-or-later" instead',
27562 $license
27563 );
27564 } else {
27565 $this->warnings[] = sprintf(
27566 'License "%s" is a deprecated SPDX license identifier, see https://spdx.org/licenses/',
27567 $license
27568 );
27569 }
27570 }
27571 }
27572 }
27573 }
27574 }
27575
27576 $this->validateString('time');
27577 if (!empty($this->config['time'])) {
27578 try {
27579 $date = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
27580 } catch (\Exception $e) {
27581 $this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
27582 unset($this->config['time']);
27583 }
27584 }
27585
27586 if ($this->validateArray('authors') && !empty($this->config['authors'])) {
27587 foreach ($this->config['authors'] as $key => $author) {
27588 if (!is_array($author)) {
27589 $this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
27590 unset($this->config['authors'][$key]);
27591 continue;
27592 }
27593 foreach (array('homepage', 'email', 'name', 'role') as $authorData) {
27594 if (isset($author[$authorData]) && !is_string($author[$authorData])) {
27595 $this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
27596 unset($this->config['authors'][$key][$authorData]);
27597 }
27598 }
27599 if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
27600 $this->warnings[] = 'authors.'.$key.'.homepage : invalid value ('.$author['homepage'].'), must be an http/https URL';
27601 unset($this->config['authors'][$key]['homepage']);
27602 }
27603 if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
27604 $this->warnings[] = 'authors.'.$key.'.email : invalid value ('.$author['email'].'), must be a valid email address';
27605 unset($this->config['authors'][$key]['email']);
27606 }
27607 if (empty($this->config['authors'][$key])) {
27608 unset($this->config['authors'][$key]);
27609 }
27610 }
27611 if (empty($this->config['authors'])) {
27612 unset($this->config['authors']);
27613 }
27614 }
27615
27616 if ($this->validateArray('support') && !empty($this->config['support'])) {
27617 foreach (array('issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss') as $key) {
27618 if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
27619 $this->errors[] = 'support.'.$key.' : invalid value, must be a string';
27620 unset($this->config['support'][$key]);
27621 }
27622 }
27623
27624 if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], FILTER_VALIDATE_EMAIL)) {
27625 $this->warnings[] = 'support.email : invalid value ('.$this->config['support']['email'].'), must be a valid email address';
27626 unset($this->config['support']['email']);
27627 }
27628
27629 if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) {
27630 $this->warnings[] = 'support.irc : invalid value ('.$this->config['support']['irc'].'), must be a irc://<server>/<channel> URL';
27631 unset($this->config['support']['irc']);
27632 }
27633
27634 foreach (array('issues', 'forum', 'wiki', 'source', 'docs') as $key) {
27635 if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
27636 $this->warnings[] = 'support.'.$key.' : invalid value ('.$this->config['support'][$key].'), must be an http/https URL';
27637 unset($this->config['support'][$key]);
27638 }
27639 }
27640 if (empty($this->config['support'])) {
27641 unset($this->config['support']);
27642 }
27643 }
27644
27645 $unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master'));
27646 $stableConstraint = new Constraint('=', '1.0.0');
27647
27648 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
27649 if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
27650 foreach ($this->config[$linkType] as $package => $constraint) {
27651 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
27652 $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
27653 }
27654 if (!is_string($constraint)) {
27655 $this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
27656 unset($this->config[$linkType][$package]);
27657 } elseif ('self.version' !== $constraint) {
27658 try {
27659 $linkConstraint = $this->versionParser->parseConstraints($constraint);
27660 } catch (\Exception $e) {
27661 $this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
27662 unset($this->config[$linkType][$package]);
27663 continue;
27664 }
27665
27666
27667  if (
27668 ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS)
27669 && 'require' === $linkType
27670 && $linkConstraint->matches($unboundConstraint)
27671 && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $package)
27672 ) {
27673 $this->warnings[] = $linkType.'.'.$package.' : unbound version constraints ('.$constraint.') should be avoided';
27674 } elseif (
27675
27676  ($this->flags & self::CHECK_STRICT_CONSTRAINTS)
27677 && 'require' === $linkType
27678 && substr($linkConstraint, 0, 1) === '='
27679 && $stableConstraint->versionCompare($stableConstraint, $linkConstraint, '<=')
27680 ) {
27681 $this->warnings[] = $linkType.'.'.$package.' : exact version constraints ('.$constraint.') should be avoided if the package follows semantic versioning';
27682 }
27683 }
27684 }
27685 }
27686 }
27687
27688 if ($this->validateArray('suggest') && !empty($this->config['suggest'])) {
27689 foreach ($this->config['suggest'] as $package => $description) {
27690 if (!is_string($description)) {
27691 $this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
27692 unset($this->config['suggest'][$package]);
27693 }
27694 }
27695 }
27696
27697 if ($this->validateString('minimum-stability') && !empty($this->config['minimum-stability'])) {
27698 if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
27699 $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
27700 unset($this->config['minimum-stability']);
27701 }
27702 }
27703
27704 if ($this->validateArray('autoload') && !empty($this->config['autoload'])) {
27705 $types = array('psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap');
27706 foreach ($this->config['autoload'] as $type => $typeConfig) {
27707 if (!in_array($type, $types)) {
27708 $this->errors[] = 'autoload : invalid value ('.$type.'), must be one of '.implode(', ', $types);
27709 unset($this->config['autoload'][$type]);
27710 }
27711 if ($type === 'psr-4') {
27712 foreach ($typeConfig as $namespace => $dirs) {
27713 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
27714 $this->errors[] = 'autoload.psr-4 : invalid value ('.$namespace.'), namespaces must end with a namespace separator, should be '.$namespace.'\\\\';
27715 }
27716 }
27717 }
27718 }
27719 }
27720
27721 if (!empty($this->config['autoload']['psr-4']) && !empty($this->config['target-dir'])) {
27722 $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
27723
27724  
27725  unset($this->config['autoload']['psr-4']);
27726 }
27727
27728
27729  
27730
27731
27732  
27733
27734 $this->validateFlatArray('include-path');
27735 $this->validateArray('transport-options');
27736
27737
27738  if (isset($this->config['extra']['branch-alias'])) {
27739 if (!is_array($this->config['extra']['branch-alias'])) {
27740 $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
27741 } else {
27742 foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
27743
27744  if ('-dev' !== substr($targetBranch, -4)) {
27745 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must end in -dev';
27746 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27747
27748 continue;
27749 }
27750
27751
27752  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
27753 if ('-dev' !== substr($validatedTargetBranch, -4)) {
27754 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
27755 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27756
27757 continue;
27758 }
27759
27760
27761  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
27762 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
27763 && (stripos($targetPrefix, $sourcePrefix) !== 0)
27764 ) {
27765 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
27766 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27767 }
27768 }
27769 }
27770 }
27771
27772 if ($this->errors) {
27773 throw new InvalidPackageException($this->errors, $this->warnings, $config);
27774 }
27775
27776 $package = $this->loader->load($this->config, $class);
27777 $this->config = null;
27778
27779 return $package;
27780 }
27781
27782 public function getWarnings()
27783 {
27784 return $this->warnings;
27785 }
27786
27787 public function getErrors()
27788 {
27789 return $this->errors;
27790 }
27791
27792 private function validateRegex($property, $regex, $mandatory = false)
27793 {
27794 if (!$this->validateString($property, $mandatory)) {
27795 return false;
27796 }
27797
27798 if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) {
27799 $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex;
27800 if ($mandatory) {
27801 $this->errors[] = $message;
27802 } else {
27803 $this->warnings[] = $message;
27804 }
27805 unset($this->config[$property]);
27806
27807 return false;
27808 }
27809
27810 return true;
27811 }
27812
27813 private function validateString($property, $mandatory = false)
27814 {
27815 if (isset($this->config[$property]) && !is_string($this->config[$property])) {
27816 $this->errors[] = $property.' : should be a string, '.gettype($this->config[$property]).' given';
27817 unset($this->config[$property]);
27818
27819 return false;
27820 }
27821
27822 if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
27823 if ($mandatory) {
27824 $this->errors[] = $property.' : must be present';
27825 }
27826 unset($this->config[$property]);
27827
27828 return false;
27829 }
27830
27831 return true;
27832 }
27833
27834 private function validateArray($property, $mandatory = false)
27835 {
27836 if (isset($this->config[$property]) && !is_array($this->config[$property])) {
27837 $this->errors[] = $property.' : should be an array, '.gettype($this->config[$property]).' given';
27838 unset($this->config[$property]);
27839
27840 return false;
27841 }
27842
27843 if (!isset($this->config[$property]) || !count($this->config[$property])) {
27844 if ($mandatory) {
27845 $this->errors[] = $property.' : must be present and contain at least one element';
27846 }
27847 unset($this->config[$property]);
27848
27849 return false;
27850 }
27851
27852 return true;
27853 }
27854
27855 private function validateFlatArray($property, $regex = null, $mandatory = false)
27856 {
27857 if (!$this->validateArray($property, $mandatory)) {
27858 return false;
27859 }
27860
27861 $pass = true;
27862 foreach ($this->config[$property] as $key => $value) {
27863 if (!is_string($value) && !is_numeric($value)) {
27864 $this->errors[] = $property.'.'.$key.' : must be a string or int, '.gettype($value).' given';
27865 unset($this->config[$property][$key]);
27866 $pass = false;
27867
27868 continue;
27869 }
27870
27871 if ($regex && !preg_match('{^'.$regex.'$}u', $value)) {
27872 $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex;
27873 unset($this->config[$property][$key]);
27874 $pass = false;
27875 }
27876 }
27877
27878 return $pass;
27879 }
27880
27881 private function validateUrl($property, $mandatory = false)
27882 {
27883 if (!$this->validateString($property, $mandatory)) {
27884 return false;
27885 }
27886
27887 if (!$this->filterUrl($this->config[$property])) {
27888 $this->warnings[] = $property.' : invalid value ('.$this->config[$property].'), must be an http/https URL';
27889 unset($this->config[$property]);
27890
27891 return false;
27892 }
27893
27894 return true;
27895 }
27896
27897 private function filterUrl($value, array $schemes = array('http', 'https'))
27898 {
27899 if ($value === '') {
27900 return true;
27901 }
27902
27903 $bits = parse_url($value);
27904 if (empty($bits['scheme']) || empty($bits['host'])) {
27905 return false;
27906 }
27907
27908 if (!in_array($bits['scheme'], $schemes, true)) {
27909 return false;
27910 }
27911
27912 return true;
27913 }
27914 }
27915 <?php
27916
27917
27918
27919
27920
27921
27922
27923
27924
27925
27926
27927 namespace Composer\Package;
27928
27929 use Composer\Json\JsonFile;
27930 use Composer\Installer\InstallationManager;
27931 use Composer\Repository\RepositoryManager;
27932 use Composer\Util\ProcessExecutor;
27933 use Composer\Repository\ArrayRepository;
27934 use Composer\Package\Dumper\ArrayDumper;
27935 use Composer\Package\Loader\ArrayLoader;
27936 use Composer\Util\Git as GitUtil;
27937 use Composer\IO\IOInterface;
27938 use Seld\JsonLint\ParsingException;
27939
27940
27941
27942
27943
27944
27945
27946 class Locker
27947 {
27948 private $lockFile;
27949 private $repositoryManager;
27950 private $installationManager;
27951 private $hash;
27952 private $contentHash;
27953 private $loader;
27954 private $dumper;
27955 private $process;
27956 private $lockDataCache;
27957
27958
27959
27960
27961
27962
27963
27964
27965
27966
27967 public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
27968 {
27969 $this->lockFile = $lockFile;
27970 $this->repositoryManager = $repositoryManager;
27971 $this->installationManager = $installationManager;
27972 $this->hash = md5($composerFileContents);
27973 $this->contentHash = self::getContentHash($composerFileContents);
27974 $this->loader = new ArrayLoader(null, true);
27975 $this->dumper = new ArrayDumper();
27976 $this->process = new ProcessExecutor($io);
27977 }
27978
27979
27980
27981
27982
27983
27984
27985
27986 public static function getContentHash($composerFileContents)
27987 {
27988 $content = json_decode($composerFileContents, true);
27989
27990 $relevantKeys = array(
27991 'name',
27992 'version',
27993 'require',
27994 'require-dev',
27995 'conflict',
27996 'replace',
27997 'provide',
27998 'minimum-stability',
27999 'prefer-stable',
28000 'repositories',
28001 'extra',
28002 );
28003
28004 $relevantContent = array();
28005
28006 foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
28007 $relevantContent[$key] = $content[$key];
28008 }
28009 if (isset($content['config']['platform'])) {
28010 $relevantContent['config']['platform'] = $content['config']['platform'];
28011 }
28012
28013 ksort($relevantContent);
28014
28015 return md5(json_encode($relevantContent));
28016 }
28017
28018
28019
28020
28021
28022
28023 public function isLocked()
28024 {
28025 if (!$this->lockFile->exists()) {
28026 return false;
28027 }
28028
28029 $data = $this->getLockData();
28030
28031 return isset($data['packages']);
28032 }
28033
28034
28035
28036
28037
28038
28039 public function isFresh()
28040 {
28041 $lock = $this->lockFile->read();
28042
28043 if (!empty($lock['content-hash'])) {
28044
28045  return $this->contentHash === $lock['content-hash'];
28046 }
28047
28048
28049  if (!empty($lock['hash'])) {
28050 return $this->hash === $lock['hash'];
28051 }
28052
28053
28054  return false;
28055 }
28056
28057
28058
28059
28060
28061
28062
28063
28064 public function getLockedRepository($withDevReqs = false)
28065 {
28066 $lockData = $this->getLockData();
28067 $packages = new ArrayRepository();
28068
28069 $lockedPackages = $lockData['packages'];
28070 if ($withDevReqs) {
28071 if (isset($lockData['packages-dev'])) {
28072 $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
28073 } else {
28074 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.');
28075 }
28076 }
28077
28078 if (empty($lockedPackages)) {
28079 return $packages;
28080 }
28081
28082 if (isset($lockedPackages[0]['name'])) {
28083 foreach ($lockedPackages as $info) {
28084 $packages->addPackage($this->loader->load($info));
28085 }
28086
28087 return $packages;
28088 }
28089
28090 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.');
28091 }
28092
28093
28094
28095
28096
28097
28098
28099 public function getPlatformRequirements($withDevReqs = false)
28100 {
28101 $lockData = $this->getLockData();
28102 $requirements = array();
28103
28104 if (!empty($lockData['platform'])) {
28105 $requirements = $this->loader->parseLinks(
28106 '__ROOT__',
28107 '1.0.0',
28108 'requires',
28109 isset($lockData['platform']) ? $lockData['platform'] : array()
28110 );
28111 }
28112
28113 if ($withDevReqs && !empty($lockData['platform-dev'])) {
28114 $devRequirements = $this->loader->parseLinks(
28115 '__ROOT__',
28116 '1.0.0',
28117 'requires',
28118 isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
28119 );
28120
28121 $requirements = array_merge($requirements, $devRequirements);
28122 }
28123
28124 return $requirements;
28125 }
28126
28127 public function getMinimumStability()
28128 {
28129 $lockData = $this->getLockData();
28130
28131 return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'stable';
28132 }
28133
28134 public function getStabilityFlags()
28135 {
28136 $lockData = $this->getLockData();
28137
28138 return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
28139 }
28140
28141 public function getPreferStable()
28142 {
28143 $lockData = $this->getLockData();
28144
28145
28146  
28147  return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null;
28148 }
28149
28150 public function getPreferLowest()
28151 {
28152 $lockData = $this->getLockData();
28153
28154
28155  
28156  return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
28157 }
28158
28159 public function getPlatformOverrides()
28160 {
28161 $lockData = $this->getLockData();
28162
28163 return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
28164 }
28165
28166 public function getAliases()
28167 {
28168 $lockData = $this->getLockData();
28169
28170 return isset($lockData['aliases']) ? $lockData['aliases'] : array();
28171 }
28172
28173 public function getLockData()
28174 {
28175 if (null !== $this->lockDataCache) {
28176 return $this->lockDataCache;
28177 }
28178
28179 if (!$this->lockFile->exists()) {
28180 throw new \LogicException('No lockfile found. Unable to read locked packages');
28181 }
28182
28183 return $this->lockDataCache = $this->lockFile->read();
28184 }
28185
28186
28187
28188
28189
28190
28191
28192
28193
28194
28195
28196
28197
28198
28199
28200
28201
28202 public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest, array $platformOverrides)
28203 {
28204 $lock = array(
28205 '_readme' => array('This file locks the dependencies of your project to a known state',
28206 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file',
28207 'This file is @gener'.'ated automatically', ),
28208 'content-hash' => $this->contentHash,
28209 'packages' => null,
28210 'packages-dev' => null,
28211 'aliases' => array(),
28212 'minimum-stability' => $minimumStability,
28213 'stability-flags' => $stabilityFlags,
28214 'prefer-stable' => $preferStable,
28215 'prefer-lowest' => $preferLowest,
28216 );
28217
28218 foreach ($aliases as $package => $versions) {
28219 foreach ($versions as $version => $alias) {
28220 $lock['aliases'][] = array(
28221 'alias' => $alias['alias'],
28222 'alias_normalized' => $alias['alias_normalized'],
28223 'version' => $version,
28224 'package' => $package,
28225 );
28226 }
28227 }
28228
28229 $lock['packages'] = $this->lockPackages($packages);
28230 if (null !== $devPackages) {
28231 $lock['packages-dev'] = $this->lockPackages($devPackages);
28232 }
28233
28234 $lock['platform'] = $platformReqs;
28235 $lock['platform-dev'] = $platformDevReqs;
28236 if ($platformOverrides) {
28237 $lock['platform-overrides'] = $platformOverrides;
28238 }
28239
28240 if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
28241 if ($this->lockFile->exists()) {
28242 unlink($this->lockFile->getPath());
28243 }
28244
28245 return false;
28246 }
28247
28248 try {
28249 $isLocked = $this->isLocked();
28250 } catch (ParsingException $e) {
28251 $isLocked = false;
28252 }
28253 if (!$isLocked || $lock !== $this->getLockData()) {
28254 $this->lockFile->write($lock);
28255 $this->lockDataCache = null;
28256
28257 return true;
28258 }
28259
28260 return false;
28261 }
28262
28263 private function lockPackages(array $packages)
28264 {
28265 $locked = array();
28266
28267 foreach ($packages as $package) {
28268 if ($package instanceof AliasPackage) {
28269 continue;
28270 }
28271
28272 $name = $package->getPrettyName();
28273 $version = $package->getPrettyVersion();
28274
28275 if (!$name || !$version) {
28276 throw new \LogicException(sprintf(
28277 'Package "%s" has no version or name and can not be locked', $package
28278 ));
28279 }
28280
28281 $spec = $this->dumper->dump($package);
28282 unset($spec['version_normalized']);
28283
28284
28285  $time = isset($spec['time']) ? $spec['time'] : null;
28286 unset($spec['time']);
28287 if ($package->isDev() && $package->getInstallationSource() === 'source') {
28288
28289  $time = $this->getPackageTime($package) ?: $time;
28290 }
28291 if (null !== $time) {
28292 $spec['time'] = $time;
28293 }
28294
28295 unset($spec['installation-source']);
28296
28297 $locked[] = $spec;
28298 }
28299
28300 usort($locked, function ($a, $b) {
28301 $comparison = strcmp($a['name'], $b['name']);
28302
28303 if (0 !== $comparison) {
28304 return $comparison;
28305 }
28306
28307
28308  return strcmp($a['version'], $b['version']);
28309 });
28310
28311 return $locked;
28312 }
28313
28314
28315
28316
28317
28318
28319
28320 private function getPackageTime(PackageInterface $package)
28321 {
28322 if (!function_exists('proc_open')) {
28323 return null;
28324 }
28325
28326 $path = realpath($this->installationManager->getInstallPath($package));
28327 $sourceType = $package->getSourceType();
28328 $datetime = null;
28329
28330 if ($path && in_array($sourceType, array('git', 'hg'))) {
28331 $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
28332 switch ($sourceType) {
28333 case 'git':
28334 GitUtil::cleanEnv();
28335
28336 if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
28337 $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
28338 }
28339 break;
28340
28341 case 'hg':
28342 if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
28343 $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
28344 }
28345 break;
28346 }
28347 }
28348
28349 return $datetime ? $datetime->format(DATE_RFC3339) : null;
28350 }
28351 }
28352 <?php
28353
28354
28355
28356
28357
28358
28359
28360
28361
28362
28363
28364 namespace Composer\Package;
28365
28366 use Composer\Package\Version\VersionParser;
28367 use Composer\Util\ComposerMirror;
28368
28369
28370
28371
28372
28373
28374 class Package extends BasePackage
28375 {
28376 protected $type;
28377 protected $targetDir;
28378 protected $installationSource;
28379 protected $sourceType;
28380 protected $sourceUrl;
28381 protected $sourceReference;
28382 protected $sourceMirrors;
28383 protected $distType;
28384 protected $distUrl;
28385 protected $distReference;
28386 protected $distSha1Checksum;
28387 protected $distMirrors;
28388 protected $version;
28389 protected $prettyVersion;
28390 protected $releaseDate;
28391 protected $extra = array();
28392 protected $binaries = array();
28393 protected $dev;
28394 protected $stability;
28395 protected $notificationUrl;
28396
28397
28398 protected $requires = array();
28399
28400 protected $conflicts = array();
28401
28402 protected $provides = array();
28403
28404 protected $replaces = array();
28405
28406 protected $devRequires = array();
28407 protected $suggests = array();
28408 protected $autoload = array();
28409 protected $devAutoload = array();
28410 protected $includePaths = array();
28411 protected $archiveExcludes = array();
28412
28413
28414
28415
28416
28417
28418
28419
28420 public function __construct($name, $version, $prettyVersion)
28421 {
28422 parent::__construct($name);
28423
28424 $this->version = $version;
28425 $this->prettyVersion = $prettyVersion;
28426
28427 $this->stability = VersionParser::parseStability($version);
28428 $this->dev = $this->stability === 'dev';
28429 }
28430
28431
28432
28433
28434 public function isDev()
28435 {
28436 return $this->dev;
28437 }
28438
28439
28440
28441
28442 public function setType($type)
28443 {
28444 $this->type = $type;
28445 }
28446
28447
28448
28449
28450 public function getType()
28451 {
28452 return $this->type ?: 'library';
28453 }
28454
28455
28456
28457
28458 public function getStability()
28459 {
28460 return $this->stability;
28461 }
28462
28463
28464
28465
28466 public function setTargetDir($targetDir)
28467 {
28468 $this->targetDir = $targetDir;
28469 }
28470
28471
28472
28473
28474 public function getTargetDir()
28475 {
28476 if (null === $this->targetDir) {
28477 return;
28478 }
28479
28480 return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
28481 }
28482
28483
28484
28485
28486 public function setExtra(array $extra)
28487 {
28488 $this->extra = $extra;
28489 }
28490
28491
28492
28493
28494 public function getExtra()
28495 {
28496 return $this->extra;
28497 }
28498
28499
28500
28501
28502 public function setBinaries(array $binaries)
28503 {
28504 $this->binaries = $binaries;
28505 }
28506
28507
28508
28509
28510 public function getBinaries()
28511 {
28512 return $this->binaries;
28513 }
28514
28515
28516
28517
28518 public function setInstallationSource($type)
28519 {
28520 $this->installationSource = $type;
28521 }
28522
28523
28524
28525
28526 public function getInstallationSource()
28527 {
28528 return $this->installationSource;
28529 }
28530
28531
28532
28533
28534 public function setSourceType($type)
28535 {
28536 $this->sourceType = $type;
28537 }
28538
28539
28540
28541
28542 public function getSourceType()
28543 {
28544 return $this->sourceType;
28545 }
28546
28547
28548
28549
28550 public function setSourceUrl($url)
28551 {
28552 $this->sourceUrl = $url;
28553 }
28554
28555
28556
28557
28558 public function getSourceUrl()
28559 {
28560 return $this->sourceUrl;
28561 }
28562
28563
28564
28565
28566 public function setSourceReference($reference)
28567 {
28568 $this->sourceReference = $reference;
28569 }
28570
28571
28572
28573
28574 public function getSourceReference()
28575 {
28576 return $this->sourceReference;
28577 }
28578
28579
28580
28581
28582 public function setSourceMirrors($mirrors)
28583 {
28584 $this->sourceMirrors = $mirrors;
28585 }
28586
28587
28588
28589
28590 public function getSourceMirrors()
28591 {
28592 return $this->sourceMirrors;
28593 }
28594
28595
28596
28597
28598 public function getSourceUrls()
28599 {
28600 return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
28601 }
28602
28603
28604
28605
28606 public function setDistType($type)
28607 {
28608 $this->distType = $type;
28609 }
28610
28611
28612
28613
28614 public function getDistType()
28615 {
28616 return $this->distType;
28617 }
28618
28619
28620
28621
28622 public function setDistUrl($url)
28623 {
28624 $this->distUrl = $url;
28625 }
28626
28627
28628
28629
28630 public function getDistUrl()
28631 {
28632 return $this->distUrl;
28633 }
28634
28635
28636
28637
28638 public function setDistReference($reference)
28639 {
28640 $this->distReference = $reference;
28641 }
28642
28643
28644
28645
28646 public function getDistReference()
28647 {
28648 return $this->distReference;
28649 }
28650
28651
28652
28653
28654 public function setDistSha1Checksum($sha1checksum)
28655 {
28656 $this->distSha1Checksum = $sha1checksum;
28657 }
28658
28659
28660
28661
28662 public function getDistSha1Checksum()
28663 {
28664 return $this->distSha1Checksum;
28665 }
28666
28667
28668
28669
28670 public function setDistMirrors($mirrors)
28671 {
28672 $this->distMirrors = $mirrors;
28673 }
28674
28675
28676
28677
28678 public function getDistMirrors()
28679 {
28680 return $this->distMirrors;
28681 }
28682
28683
28684
28685
28686 public function getDistUrls()
28687 {
28688 return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
28689 }
28690
28691
28692
28693
28694 public function getVersion()
28695 {
28696 return $this->version;
28697 }
28698
28699
28700
28701
28702 public function getPrettyVersion()
28703 {
28704 return $this->prettyVersion;
28705 }
28706
28707
28708
28709
28710
28711
28712 public function setReleaseDate(\DateTime $releaseDate)
28713 {
28714 $this->releaseDate = $releaseDate;
28715 }
28716
28717
28718
28719
28720 public function getReleaseDate()
28721 {
28722 return $this->releaseDate;
28723 }
28724
28725
28726
28727
28728
28729
28730 public function setRequires(array $requires)
28731 {
28732 $this->requires = $requires;
28733 }
28734
28735
28736
28737
28738 public function getRequires()
28739 {
28740 return $this->requires;
28741 }
28742
28743
28744
28745
28746
28747
28748 public function setConflicts(array $conflicts)
28749 {
28750 $this->conflicts = $conflicts;
28751 }
28752
28753
28754
28755
28756 public function getConflicts()
28757 {
28758 return $this->conflicts;
28759 }
28760
28761
28762
28763
28764
28765
28766 public function setProvides(array $provides)
28767 {
28768 $this->provides = $provides;
28769 }
28770
28771
28772
28773
28774 public function getProvides()
28775 {
28776 return $this->provides;
28777 }
28778
28779
28780
28781
28782
28783
28784 public function setReplaces(array $replaces)
28785 {
28786 $this->replaces = $replaces;
28787 }
28788
28789
28790
28791
28792 public function getReplaces()
28793 {
28794 return $this->replaces;
28795 }
28796
28797
28798
28799
28800
28801
28802 public function setDevRequires(array $devRequires)
28803 {
28804 $this->devRequires = $devRequires;
28805 }
28806
28807
28808
28809
28810 public function getDevRequires()
28811 {
28812 return $this->devRequires;
28813 }
28814
28815
28816
28817
28818
28819
28820 public function setSuggests(array $suggests)
28821 {
28822 $this->suggests = $suggests;
28823 }
28824
28825
28826
28827
28828 public function getSuggests()
28829 {
28830 return $this->suggests;
28831 }
28832
28833
28834
28835
28836
28837
28838 public function setAutoload(array $autoload)
28839 {
28840 $this->autoload = $autoload;
28841 }
28842
28843
28844
28845
28846 public function getAutoload()
28847 {
28848 return $this->autoload;
28849 }
28850
28851
28852
28853
28854
28855
28856 public function setDevAutoload(array $devAutoload)
28857 {
28858 $this->devAutoload = $devAutoload;
28859 }
28860
28861
28862
28863
28864 public function getDevAutoload()
28865 {
28866 return $this->devAutoload;
28867 }
28868
28869
28870
28871
28872
28873
28874 public function setIncludePaths(array $includePaths)
28875 {
28876 $this->includePaths = $includePaths;
28877 }
28878
28879
28880
28881
28882 public function getIncludePaths()
28883 {
28884 return $this->includePaths;
28885 }
28886
28887
28888
28889
28890
28891
28892 public function setNotificationUrl($notificationUrl)
28893 {
28894 $this->notificationUrl = $notificationUrl;
28895 }
28896
28897
28898
28899
28900 public function getNotificationUrl()
28901 {
28902 return $this->notificationUrl;
28903 }
28904
28905
28906
28907
28908
28909
28910 public function setArchiveExcludes(array $excludes)
28911 {
28912 $this->archiveExcludes = $excludes;
28913 }
28914
28915
28916
28917
28918 public function getArchiveExcludes()
28919 {
28920 return $this->archiveExcludes;
28921 }
28922
28923
28924
28925
28926
28927
28928
28929
28930 public function replaceVersion($version, $prettyVersion)
28931 {
28932 $this->version = $version;
28933 $this->prettyVersion = $prettyVersion;
28934
28935 $this->stability = VersionParser::parseStability($version);
28936 $this->dev = $this->stability === 'dev';
28937 }
28938
28939 protected function getUrls($url, $mirrors, $ref, $type, $urlType)
28940 {
28941 if (!$url) {
28942 return array();
28943 }
28944 $urls = array($url);
28945 if ($mirrors) {
28946 foreach ($mirrors as $mirror) {
28947 if ($urlType === 'dist') {
28948 $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type);
28949 } elseif ($urlType === 'source' && $type === 'git') {
28950 $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
28951 } elseif ($urlType === 'source' && $type === 'hg') {
28952 $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
28953 }
28954 if (!in_array($mirrorUrl, $urls)) {
28955 $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
28956 $func($urls, $mirrorUrl);
28957 }
28958 }
28959 }
28960
28961 return $urls;
28962 }
28963 }
28964 <?php
28965
28966
28967
28968
28969
28970
28971
28972
28973
28974
28975
28976 namespace Composer\Package;
28977
28978 use Composer\Repository\RepositoryInterface;
28979
28980
28981
28982
28983
28984
28985 interface PackageInterface
28986 {
28987
28988
28989
28990
28991
28992 public function getName();
28993
28994
28995
28996
28997
28998
28999 public function getPrettyName();
29000
29001
29002
29003
29004
29005
29006
29007
29008
29009 public function getNames();
29010
29011
29012
29013
29014
29015
29016 public function setId($id);
29017
29018
29019
29020
29021
29022
29023 public function getId();
29024
29025
29026
29027
29028
29029
29030 public function isDev();
29031
29032
29033
29034
29035
29036
29037 public function getType();
29038
29039
29040
29041
29042
29043
29044 public function getTargetDir();
29045
29046
29047
29048
29049
29050
29051 public function getExtra();
29052
29053
29054
29055
29056
29057
29058 public function setInstallationSource($type);
29059
29060
29061
29062
29063
29064
29065 public function getInstallationSource();
29066
29067
29068
29069
29070
29071
29072 public function getSourceType();
29073
29074
29075
29076
29077
29078
29079 public function getSourceUrl();
29080
29081
29082
29083
29084
29085
29086 public function getSourceUrls();
29087
29088
29089
29090
29091
29092
29093 public function getSourceReference();
29094
29095
29096
29097
29098
29099
29100 public function getSourceMirrors();
29101
29102
29103
29104
29105
29106
29107 public function getDistType();
29108
29109
29110
29111
29112
29113
29114 public function getDistUrl();
29115
29116
29117
29118
29119
29120
29121 public function getDistUrls();
29122
29123
29124
29125
29126
29127
29128 public function getDistReference();
29129
29130
29131
29132
29133
29134
29135 public function getDistSha1Checksum();
29136
29137
29138
29139
29140
29141
29142 public function getDistMirrors();
29143
29144
29145
29146
29147
29148
29149 public function getVersion();
29150
29151
29152
29153
29154
29155
29156 public function getPrettyVersion();
29157
29158
29159
29160
29161
29162
29163
29164
29165
29166 public function getFullPrettyVersion($truncate = true);
29167
29168
29169
29170
29171
29172
29173 public function getReleaseDate();
29174
29175
29176
29177
29178
29179
29180 public function getStability();
29181
29182
29183
29184
29185
29186
29187
29188 public function getRequires();
29189
29190
29191
29192
29193
29194
29195
29196 public function getConflicts();
29197
29198
29199
29200
29201
29202
29203
29204 public function getProvides();
29205
29206
29207
29208
29209
29210
29211
29212 public function getReplaces();
29213
29214
29215
29216
29217
29218
29219
29220 public function getDevRequires();
29221
29222
29223
29224
29225
29226
29227
29228 public function getSuggests();
29229
29230
29231
29232
29233
29234
29235
29236
29237
29238
29239
29240 public function getAutoload();
29241
29242
29243
29244
29245
29246
29247
29248
29249
29250
29251
29252 public function getDevAutoload();
29253
29254
29255
29256
29257
29258
29259
29260 public function getIncludePaths();
29261
29262
29263
29264
29265
29266
29267 public function setRepository(RepositoryInterface $repository);
29268
29269
29270
29271
29272
29273
29274 public function getRepository();
29275
29276
29277
29278
29279
29280
29281 public function getBinaries();
29282
29283
29284
29285
29286
29287
29288 public function getUniqueName();
29289
29290
29291
29292
29293
29294
29295 public function getNotificationUrl();
29296
29297
29298
29299
29300
29301
29302 public function __toString();
29303
29304
29305
29306
29307
29308
29309 public function getPrettyString();
29310
29311
29312
29313
29314
29315
29316 public function getArchiveExcludes();
29317
29318
29319
29320
29321
29322
29323 public function getTransportOptions();
29324 }
29325 <?php
29326
29327
29328
29329
29330
29331
29332
29333
29334
29335
29336
29337 namespace Composer\Package;
29338
29339
29340
29341
29342 class RootAliasPackage extends AliasPackage implements RootPackageInterface
29343 {
29344 public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
29345 {
29346 parent::__construct($aliasOf, $version, $prettyVersion);
29347 }
29348
29349
29350
29351
29352 public function getAliases()
29353 {
29354 return $this->aliasOf->getAliases();
29355 }
29356
29357
29358
29359
29360 public function getMinimumStability()
29361 {
29362 return $this->aliasOf->getMinimumStability();
29363 }
29364
29365
29366
29367
29368 public function getStabilityFlags()
29369 {
29370 return $this->aliasOf->getStabilityFlags();
29371 }
29372
29373
29374
29375
29376 public function getReferences()
29377 {
29378 return $this->aliasOf->getReferences();
29379 }
29380
29381
29382
29383
29384 public function getPreferStable()
29385 {
29386 return $this->aliasOf->getPreferStable();
29387 }
29388
29389
29390
29391
29392 public function getConfig()
29393 {
29394 return $this->aliasOf->getConfig();
29395 }
29396
29397
29398
29399
29400 public function setRequires(array $require)
29401 {
29402 $this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
29403
29404 $this->aliasOf->setRequires($require);
29405 }
29406
29407
29408
29409
29410 public function setDevRequires(array $devRequire)
29411 {
29412 $this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
29413
29414 $this->aliasOf->setDevRequires($devRequire);
29415 }
29416
29417
29418
29419
29420 public function setConflicts(array $conflicts)
29421 {
29422 $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, 'conflicts');
29423 $this->aliasOf->setConflicts($conflicts);
29424 }
29425
29426
29427
29428
29429 public function setProvides(array $provides)
29430 {
29431 $this->provides = $this->replaceSelfVersionDependencies($provides, 'provides');
29432 $this->aliasOf->setProvides($provides);
29433 }
29434
29435
29436
29437
29438 public function setReplaces(array $replaces)
29439 {
29440 $this->replaces = $this->replaceSelfVersionDependencies($replaces, 'replaces');
29441 $this->aliasOf->setReplaces($replaces);
29442 }
29443
29444
29445
29446
29447 public function setRepositories($repositories)
29448 {
29449 $this->aliasOf->setRepositories($repositories);
29450 }
29451
29452
29453
29454
29455 public function setAutoload(array $autoload)
29456 {
29457 $this->aliasOf->setAutoload($autoload);
29458 }
29459
29460
29461
29462
29463 public function setDevAutoload(array $devAutoload)
29464 {
29465 $this->aliasOf->setDevAutoload($devAutoload);
29466 }
29467
29468
29469
29470
29471 public function setStabilityFlags(array $stabilityFlags)
29472 {
29473 $this->aliasOf->setStabilityFlags($stabilityFlags);
29474 }
29475
29476
29477
29478
29479 public function setSuggests(array $suggests)
29480 {
29481 $this->aliasOf->setSuggests($suggests);
29482 }
29483
29484
29485
29486
29487 public function setExtra(array $extra)
29488 {
29489 $this->aliasOf->setExtra($extra);
29490 }
29491
29492 public function __clone()
29493 {
29494 parent::__clone();
29495 $this->aliasOf = clone $this->aliasOf;
29496 }
29497 }
29498 <?php
29499
29500
29501
29502
29503
29504
29505
29506
29507
29508
29509
29510 namespace Composer\Package;
29511
29512
29513
29514
29515
29516
29517 class RootPackage extends CompletePackage implements RootPackageInterface
29518 {
29519 protected $minimumStability = 'stable';
29520 protected $preferStable = false;
29521 protected $stabilityFlags = array();
29522 protected $config = array();
29523 protected $references = array();
29524 protected $aliases = array();
29525
29526
29527
29528
29529
29530
29531 public function setMinimumStability($minimumStability)
29532 {
29533 $this->minimumStability = $minimumStability;
29534 }
29535
29536
29537
29538
29539 public function getMinimumStability()
29540 {
29541 return $this->minimumStability;
29542 }
29543
29544
29545
29546
29547
29548
29549 public function setStabilityFlags(array $stabilityFlags)
29550 {
29551 $this->stabilityFlags = $stabilityFlags;
29552 }
29553
29554
29555
29556
29557 public function getStabilityFlags()
29558 {
29559 return $this->stabilityFlags;
29560 }
29561
29562
29563
29564
29565
29566
29567 public function setPreferStable($preferStable)
29568 {
29569 $this->preferStable = $preferStable;
29570 }
29571
29572
29573
29574
29575 public function getPreferStable()
29576 {
29577 return $this->preferStable;
29578 }
29579
29580
29581
29582
29583
29584
29585 public function setConfig(array $config)
29586 {
29587 $this->config = $config;
29588 }
29589
29590
29591
29592
29593 public function getConfig()
29594 {
29595 return $this->config;
29596 }
29597
29598
29599
29600
29601
29602
29603 public function setReferences(array $references)
29604 {
29605 $this->references = $references;
29606 }
29607
29608
29609
29610
29611 public function getReferences()
29612 {
29613 return $this->references;
29614 }
29615
29616
29617
29618
29619
29620
29621 public function setAliases(array $aliases)
29622 {
29623 $this->aliases = $aliases;
29624 }
29625
29626
29627
29628
29629 public function getAliases()
29630 {
29631 return $this->aliases;
29632 }
29633 }
29634 <?php
29635
29636
29637
29638
29639
29640
29641
29642
29643
29644
29645
29646 namespace Composer\Package;
29647
29648
29649
29650
29651
29652
29653 interface RootPackageInterface extends CompletePackageInterface
29654 {
29655
29656
29657
29658
29659
29660 public function getAliases();
29661
29662
29663
29664
29665
29666
29667 public function getMinimumStability();
29668
29669
29670
29671
29672
29673
29674
29675
29676 public function getStabilityFlags();
29677
29678
29679
29680
29681
29682
29683
29684
29685 public function getReferences();
29686
29687
29688
29689
29690
29691
29692 public function getPreferStable();
29693
29694
29695
29696
29697
29698
29699 public function getConfig();
29700
29701
29702
29703
29704
29705
29706 public function setRequires(array $requires);
29707
29708
29709
29710
29711
29712
29713 public function setDevRequires(array $devRequires);
29714
29715
29716
29717
29718
29719
29720 public function setConflicts(array $conflicts);
29721
29722
29723
29724
29725
29726
29727 public function setProvides(array $provides);
29728
29729
29730
29731
29732
29733
29734 public function setReplaces(array $replaces);
29735
29736
29737
29738
29739
29740
29741 public function setRepositories($repositories);
29742
29743
29744
29745
29746
29747
29748 public function setAutoload(array $autoload);
29749
29750
29751
29752
29753
29754
29755 public function setDevAutoload(array $devAutoload);
29756
29757
29758
29759
29760
29761
29762 public function setStabilityFlags(array $stabilityFlags);
29763
29764
29765
29766
29767
29768
29769 public function setSuggests(array $suggests);
29770
29771
29772
29773
29774 public function setExtra(array $extra);
29775 }
29776 <?php
29777
29778
29779
29780
29781
29782
29783
29784
29785
29786
29787
29788 namespace Composer\Package\Version;
29789
29790 use Composer\Config;
29791 use Composer\Repository\Vcs\HgDriver;
29792 use Composer\IO\NullIO;
29793 use Composer\Semver\VersionParser as SemverVersionParser;
29794 use Composer\Util\Git as GitUtil;
29795 use Composer\Util\ProcessExecutor;
29796 use Composer\Util\Svn as SvnUtil;
29797
29798
29799
29800
29801
29802
29803
29804 class VersionGuesser
29805 {
29806
29807
29808
29809 private $config;
29810
29811
29812
29813
29814 private $process;
29815
29816
29817
29818
29819 private $versionParser;
29820
29821
29822
29823
29824
29825
29826 public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
29827 {
29828 $this->config = $config;
29829 $this->process = $process;
29830 $this->versionParser = $versionParser;
29831 }
29832
29833
29834
29835
29836
29837
29838
29839 public function guessVersion(array $packageConfig, $path)
29840 {
29841 if (function_exists('proc_open')) {
29842 $versionData = $this->guessGitVersion($packageConfig, $path);
29843 if (null !== $versionData && null !== $versionData['version']) {
29844 return $this->postprocess($versionData);
29845 }
29846
29847 $versionData = $this->guessHgVersion($packageConfig, $path);
29848 if (null !== $versionData && null !== $versionData['version']) {
29849 return $this->postprocess($versionData);
29850 }
29851
29852 $versionData = $this->guessFossilVersion($packageConfig, $path);
29853 if (null !== $versionData && null !== $versionData['version']) {
29854 return $this->postprocess($versionData);
29855 }
29856
29857 $versionData = $this->guessSvnVersion($packageConfig, $path);
29858 if (null !== $versionData && null !== $versionData['version']) {
29859 return $this->postprocess($versionData);
29860 }
29861 }
29862 }
29863
29864 private function postprocess(array $versionData)
29865 {
29866 if ('-dev' === substr($versionData['version'], -4)) {
29867 $versionData['pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['version']);
29868 }
29869
29870 return $versionData;
29871 }
29872
29873 private function guessGitVersion(array $packageConfig, $path)
29874 {
29875 GitUtil::cleanEnv();
29876 $commit = null;
29877 $version = null;
29878 $prettyVersion = null;
29879 $isDetached = false;
29880
29881
29882  if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
29883 $branches = array();
29884 $isFeatureBranch = false;
29885
29886
29887  foreach ($this->process->splitLines($output) as $branch) {
29888 if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
29889 if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ' || substr($match[1], 0, 17) === '(HEAD detached at') {
29890 $version = 'dev-' . $match[2];
29891 $prettyVersion = $version;
29892 $isFeatureBranch = true;
29893 $isDetached = true;
29894 } else {
29895 $version = $this->versionParser->normalizeBranch($match[1]);
29896 $prettyVersion = 'dev-' . $match[1];
29897 $isFeatureBranch = 0 === strpos($version, 'dev-');
29898 if ('9999999-dev' === $version) {
29899 $version = $prettyVersion;
29900 }
29901 }
29902
29903 if ($match[2]) {
29904 $commit = $match[2];
29905 }
29906 }
29907
29908 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
29909 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
29910 $branches[] = $match[1];
29911 }
29912 }
29913 }
29914
29915 if ($isFeatureBranch) {
29916
29917  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
29918 $version = $result['version'];
29919 $prettyVersion = $result['pretty_version'];
29920 }
29921 }
29922
29923 if (!$version || $isDetached) {
29924 $result = $this->versionFromGitTags($path);
29925 if ($result) {
29926 $version = $result['version'];
29927 $prettyVersion = $result['pretty_version'];
29928 }
29929 }
29930
29931 if (!$commit) {
29932 $command = 'git log --pretty="%H" -n1 HEAD';
29933 if (0 === $this->process->execute($command, $output, $path)) {
29934 $commit = trim($output) ?: null;
29935 }
29936 }
29937
29938 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion);
29939 }
29940
29941 private function versionFromGitTags($path)
29942 {
29943
29944  if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
29945 try {
29946 $version = $this->versionParser->normalize(trim($output));
29947
29948 return array('version' => $version, 'pretty_version' => trim($output));
29949 } catch (\Exception $e) {
29950 }
29951 }
29952
29953 return null;
29954 }
29955
29956 private function guessHgVersion(array $packageConfig, $path)
29957 {
29958
29959  if (0 === $this->process->execute('hg branch', $output, $path)) {
29960 $branch = trim($output);
29961 $version = $this->versionParser->normalizeBranch($branch);
29962 $isFeatureBranch = 0 === strpos($version, 'dev-');
29963
29964 if ('9999999-dev' === $version) {
29965 $version = 'dev-' . $branch;
29966 }
29967
29968 if (!$isFeatureBranch) {
29969 return array('version' => $version, 'commit' => null, 'pretty_version' => $version);
29970 }
29971
29972
29973  $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process);
29974 $branches = array_keys($driver->getBranches());
29975
29976
29977  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
29978 $result['commit'] = '';
29979
29980 return $result;
29981 }
29982 }
29983
29984 private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path)
29985 {
29986 $prettyVersion = $version;
29987
29988
29989  
29990  if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version]))
29991 || strpos(json_encode($packageConfig), '"self.version"')
29992 ) {
29993 $branch = preg_replace('{^dev-}', '', $version);
29994 $length = PHP_INT_MAX;
29995
29996 $nonFeatureBranches = '';
29997 if (!empty($packageConfig['non-feature-branches'])) {
29998 $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
29999 }
30000
30001 foreach ($branches as $candidate) {
30002
30003  if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
30004 break;
30005 }
30006
30007
30008  if ($candidate === $branch || !preg_match('{^(' . $nonFeatureBranches . '|master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
30009 continue;
30010 }
30011
30012 $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
30013 if (0 !== $this->process->execute($cmdLine, $output, $path)) {
30014 continue;
30015 }
30016
30017 if (strlen($output) < $length) {
30018 $length = strlen($output);
30019 $version = $this->versionParser->normalizeBranch($candidate);
30020 $prettyVersion = 'dev-' . $match[1];
30021 if ('9999999-dev' === $version) {
30022 $version = $prettyVersion;
30023 }
30024 }
30025 }
30026 }
30027
30028 return array('version' => $version, 'pretty_version' => $prettyVersion);
30029 }
30030
30031 private function guessFossilVersion(array $packageConfig, $path)
30032 {
30033 $version = null;
30034 $prettyVersion = null;
30035
30036
30037  if (0 === $this->process->execute('fossil branch list', $output, $path)) {
30038 $branch = trim($output);
30039 $version = $this->versionParser->normalizeBranch($branch);
30040 $prettyVersion = 'dev-' . $branch;
30041
30042 if ('9999999-dev' === $version) {
30043 $version = $prettyVersion;
30044 }
30045 }
30046
30047
30048  if (0 === $this->process->execute('fossil tag list', $output, $path)) {
30049 try {
30050 $version = $this->versionParser->normalize(trim($output));
30051 $prettyVersion = trim($output);
30052 } catch (\Exception $e) {
30053 }
30054 }
30055
30056 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
30057 }
30058
30059 private function guessSvnVersion(array $packageConfig, $path)
30060 {
30061 SvnUtil::cleanEnv();
30062
30063
30064  if (0 === $this->process->execute('svn info --xml', $output, $path)) {
30065 $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
30066 $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
30067 $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
30068
30069 $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
30070
30071 if (preg_match($urlPattern, $output, $matches)) {
30072 if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
30073
30074  $version = $this->versionParser->normalizeBranch($matches[3]);
30075 $prettyVersion = 'dev-' . $matches[3];
30076 if ('9999999-dev' === $version) {
30077 $version = $prettyVersion;
30078 }
30079
30080 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
30081 }
30082
30083 $prettyVersion = trim($matches[1]);
30084 $version = $this->versionParser->normalize($prettyVersion);
30085
30086 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
30087 }
30088 }
30089 }
30090 }
30091 <?php
30092
30093
30094
30095
30096
30097
30098
30099
30100
30101
30102
30103 namespace Composer\Package\Version;
30104
30105 use Composer\Repository\PlatformRepository;
30106 use Composer\Semver\VersionParser as SemverVersionParser;
30107
30108 class VersionParser extends SemverVersionParser
30109 {
30110 private static $constraints = array();
30111
30112
30113
30114
30115 public function parseConstraints($constraints)
30116 {
30117 if (!isset(self::$constraints[$constraints])) {
30118 self::$constraints[$constraints] = parent::parseConstraints($constraints);
30119 }
30120
30121 return self::$constraints[$constraints];
30122 }
30123
30124
30125
30126
30127
30128
30129
30130
30131
30132
30133
30134 public function parseNameVersionPairs(array $pairs)
30135 {
30136 $pairs = array_values($pairs);
30137 $result = array();
30138
30139 for ($i = 0, $count = count($pairs); $i < $count; $i++) {
30140 $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
30141 if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/') && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $pairs[$i + 1])) {
30142 $pair .= ' '.$pairs[$i + 1];
30143 $i++;
30144 }
30145
30146 if (strpos($pair, ' ')) {
30147 list($name, $version) = explode(' ', $pair, 2);
30148 $result[] = array('name' => $name, 'version' => $version);
30149 } else {
30150 $result[] = array('name' => $pair);
30151 }
30152 }
30153
30154 return $result;
30155 }
30156 }
30157 <?php
30158
30159
30160
30161
30162
30163
30164
30165
30166
30167
30168
30169 namespace Composer\Package\Version;
30170
30171 use Composer\DependencyResolver\Pool;
30172 use Composer\Package\BasePackage;
30173 use Composer\Package\PackageInterface;
30174 use Composer\Package\Loader\ArrayLoader;
30175 use Composer\Package\Dumper\ArrayDumper;
30176 use Composer\Semver\Constraint\Constraint;
30177
30178
30179
30180
30181
30182
30183
30184 class VersionSelector
30185 {
30186 private $pool;
30187
30188 private $parser;
30189
30190 public function __construct(Pool $pool)
30191 {
30192 $this->pool = $pool;
30193 }
30194
30195
30196
30197
30198
30199
30200
30201
30202
30203
30204
30205 public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
30206 {
30207 $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
30208 $candidates = $this->pool->whatProvides(strtolower($packageName), $constraint, true);
30209
30210 if ($targetPhpVersion) {
30211 $phpConstraint = new Constraint('==', $this->getParser()->normalize($targetPhpVersion));
30212 $candidates = array_filter($candidates, function ($pkg) use ($phpConstraint) {
30213 $reqs = $pkg->getRequires();
30214
30215 return !isset($reqs['php']) || $reqs['php']->getConstraint()->matches($phpConstraint);
30216 });
30217 }
30218
30219 if (!$candidates) {
30220 return false;
30221 }
30222
30223
30224  $package = reset($candidates);
30225 $minPriority = BasePackage::$stabilities[$preferredStability];
30226 foreach ($candidates as $candidate) {
30227 $candidatePriority = $candidate->getStabilityPriority();
30228 $currentPriority = $package->getStabilityPriority();
30229
30230
30231  
30232  if ($minPriority < $candidatePriority && $currentPriority < $candidatePriority) {
30233 continue;
30234 }
30235
30236
30237  
30238  if ($minPriority < $candidatePriority && $candidatePriority < $currentPriority) {
30239 $package = $candidate;
30240 continue;
30241 }
30242
30243
30244  
30245  if ($minPriority >= $candidatePriority && $minPriority < $currentPriority) {
30246 $package = $candidate;
30247 continue;
30248 }
30249
30250
30251  if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) {
30252 $package = $candidate;
30253 }
30254 }
30255
30256 return $package;
30257 }
30258
30259
30260
30261
30262
30263
30264
30265
30266
30267
30268
30269
30270
30271
30272
30273
30274 public function findRecommendedRequireVersion(PackageInterface $package)
30275 {
30276 $version = $package->getVersion();
30277 if (!$package->isDev()) {
30278 return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
30279 }
30280
30281 $loader = new ArrayLoader($this->getParser());
30282 $dumper = new ArrayDumper();
30283 $extra = $loader->getBranchAlias($dumper->dump($package));
30284 if ($extra) {
30285 $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
30286 if ($count) {
30287 $extra = str_replace('.9999999', '.0', $extra);
30288
30289 return $this->transformVersion($extra, $extra, 'dev');
30290 }
30291 }
30292
30293 return $package->getPrettyVersion();
30294 }
30295
30296 private function transformVersion($version, $prettyVersion, $stability)
30297 {
30298
30299  
30300  $semanticVersionParts = explode('.', $version);
30301
30302
30303  if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
30304
30305  if ($semanticVersionParts[0] === '0') {
30306 unset($semanticVersionParts[3]);
30307 } else {
30308 unset($semanticVersionParts[2], $semanticVersionParts[3]);
30309 }
30310 $version = implode('.', $semanticVersionParts);
30311 } else {
30312 return $prettyVersion;
30313 }
30314
30315
30316  if ($stability != 'stable') {
30317 $version .= '@'.$stability;
30318 }
30319
30320
30321  return '^' . $version;
30322 }
30323
30324 private function getParser()
30325 {
30326 if ($this->parser === null) {
30327 $this->parser = new VersionParser();
30328 }
30329
30330 return $this->parser;
30331 }
30332 }
30333 <?php
30334
30335
30336
30337
30338
30339
30340
30341
30342
30343
30344
30345 namespace Composer\Plugin\Capability;
30346
30347
30348
30349
30350
30351
30352
30353 interface Capability
30354 {
30355 }
30356 <?php
30357
30358
30359
30360
30361
30362
30363
30364
30365
30366
30367
30368 namespace Composer\Plugin\Capability;
30369
30370
30371
30372
30373
30374
30375
30376
30377
30378
30379
30380 interface CommandProvider extends Capability
30381 {
30382
30383
30384
30385
30386
30387 public function getCommands();
30388 }
30389 <?php
30390
30391
30392
30393
30394
30395
30396
30397
30398
30399
30400
30401 namespace Composer\Plugin;
30402
30403
30404
30405
30406
30407
30408
30409
30410 interface Capable
30411 {
30412
30413
30414
30415
30416
30417
30418
30419
30420
30421
30422
30423
30424
30425
30426
30427
30428
30429
30430 public function getCapabilities();
30431 }
30432 <?php
30433
30434
30435
30436
30437
30438
30439
30440
30441
30442
30443
30444 namespace Composer\Plugin;
30445
30446 use Composer\EventDispatcher\Event;
30447 use Symfony\Component\Console\Input\InputInterface;
30448 use Symfony\Component\Console\Output\OutputInterface;
30449
30450
30451
30452
30453
30454
30455 class CommandEvent extends Event
30456 {
30457
30458
30459
30460 private $commandName;
30461
30462
30463
30464
30465 private $input;
30466
30467
30468
30469
30470 private $output;
30471
30472
30473
30474
30475
30476
30477
30478
30479
30480
30481
30482 public function __construct($name, $commandName, $input, $output, array $args = array(), array $flags = array())
30483 {
30484 parent::__construct($name, $args, $flags);
30485 $this->commandName = $commandName;
30486 $this->input = $input;
30487 $this->output = $output;
30488 }
30489
30490
30491
30492
30493
30494
30495 public function getInput()
30496 {
30497 return $this->input;
30498 }
30499
30500
30501
30502
30503
30504
30505 public function getOutput()
30506 {
30507 return $this->output;
30508 }
30509
30510
30511
30512
30513
30514
30515 public function getCommandName()
30516 {
30517 return $this->commandName;
30518 }
30519 }
30520 <?php
30521
30522
30523
30524
30525
30526
30527
30528
30529
30530
30531
30532 namespace Composer\Plugin;
30533
30534
30535
30536
30537
30538
30539 class PluginEvents
30540 {
30541
30542
30543
30544
30545
30546
30547
30548
30549 const INIT = 'init';
30550
30551
30552
30553
30554
30555
30556
30557
30558
30559 const COMMAND = 'command';
30560
30561
30562
30563
30564
30565
30566
30567
30568
30569 const PRE_FILE_DOWNLOAD = 'pre-file-download';
30570 }
30571 <?php
30572
30573
30574
30575
30576
30577
30578
30579
30580
30581
30582
30583 namespace Composer\Plugin;
30584
30585 use Composer\Composer;
30586 use Composer\IO\IOInterface;
30587
30588
30589
30590
30591
30592
30593 interface PluginInterface
30594 {
30595
30596
30597
30598
30599
30600 const PLUGIN_API_VERSION = '1.1.0';
30601
30602
30603
30604
30605
30606
30607
30608 public function activate(Composer $composer, IOInterface $io);
30609 }
30610 <?php
30611
30612
30613
30614
30615
30616
30617
30618
30619
30620
30621
30622 namespace Composer\Plugin;
30623
30624 use Composer\Composer;
30625 use Composer\EventDispatcher\EventSubscriberInterface;
30626 use Composer\IO\IOInterface;
30627 use Composer\Package\Package;
30628 use Composer\Package\Version\VersionParser;
30629 use Composer\Repository\RepositoryInterface;
30630 use Composer\Package\AliasPackage;
30631 use Composer\Package\PackageInterface;
30632 use Composer\Package\Link;
30633 use Composer\Semver\Constraint\Constraint;
30634 use Composer\DependencyResolver\Pool;
30635 use Composer\Plugin\Capability\Capability;
30636
30637
30638
30639
30640
30641
30642
30643 class PluginManager
30644 {
30645 protected $composer;
30646 protected $io;
30647 protected $globalComposer;
30648 protected $versionParser;
30649 protected $disablePlugins = false;
30650
30651 protected $plugins = array();
30652 protected $registeredPlugins = array();
30653
30654 private static $classCounter = 0;
30655
30656
30657
30658
30659
30660
30661
30662
30663
30664 public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
30665 {
30666 $this->io = $io;
30667 $this->composer = $composer;
30668 $this->globalComposer = $globalComposer;
30669 $this->versionParser = new VersionParser();
30670 $this->disablePlugins = $disablePlugins;
30671 }
30672
30673
30674
30675
30676 public function loadInstalledPlugins()
30677 {
30678 if ($this->disablePlugins) {
30679 return;
30680 }
30681
30682 $repo = $this->composer->getRepositoryManager()->getLocalRepository();
30683 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
30684 if ($repo) {
30685 $this->loadRepository($repo);
30686 }
30687 if ($globalRepo) {
30688 $this->loadRepository($globalRepo);
30689 }
30690 }
30691
30692
30693
30694
30695
30696
30697 public function getPlugins()
30698 {
30699 return $this->plugins;
30700 }
30701
30702
30703
30704
30705
30706
30707 public function getGlobalComposer()
30708 {
30709 return $this->globalComposer;
30710 }
30711
30712
30713
30714
30715
30716
30717
30718
30719
30720
30721
30722
30723 public function registerPackage(PackageInterface $package, $failOnMissingClasses = false)
30724 {
30725 if ($this->disablePlugins) {
30726 return;
30727 }
30728
30729 if ($package->getType() === 'composer-plugin') {
30730 $requiresComposer = null;
30731 foreach ($package->getRequires() as $link) { 
30732 if ('composer-plugin-api' === $link->getTarget()) {
30733 $requiresComposer = $link->getConstraint();
30734 break;
30735 }
30736 }
30737
30738 if (!$requiresComposer) {
30739 throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
30740 }
30741
30742 $currentPluginApiVersion = $this->getPluginApiVersion();
30743 $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
30744
30745 if ($requiresComposer->getPrettyString() === '1.0.0' && $this->getPluginApiVersion() === '1.0.0') {
30746 $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>');
30747 } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) {
30748 $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>');
30749
30750 return;
30751 }
30752 }
30753
30754 $oldInstallerPlugin = ($package->getType() === 'composer-installer');
30755
30756 if (in_array($package->getName(), $this->registeredPlugins)) {
30757 return;
30758 }
30759
30760 $extra = $package->getExtra();
30761 if (empty($extra['class'])) {
30762 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
30763 }
30764 $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
30765
30766 $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
30767 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
30768
30769 $pool = new Pool('dev');
30770 $pool->addRepository($localRepo);
30771 if ($globalRepo) {
30772 $pool->addRepository($globalRepo);
30773 }
30774
30775 $autoloadPackages = array($package->getName() => $package);
30776 $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package);
30777
30778 $generator = $this->composer->getAutoloadGenerator();
30779 $autoloads = array();
30780 foreach ($autoloadPackages as $autoloadPackage) {
30781 $downloadPath = $this->getInstallPath($autoloadPackage, ($globalRepo && $globalRepo->hasPackage($autoloadPackage)));
30782 $autoloads[] = array($autoloadPackage, $downloadPath);
30783 }
30784
30785 $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0'));
30786 $classLoader = $generator->createLoader($map);
30787 $classLoader->register();
30788
30789 foreach ($classes as $class) {
30790 if (class_exists($class, false)) {
30791 $class = trim($class, '\\');
30792 $path = $classLoader->findFile($class);
30793 $code = file_get_contents($path);
30794 $separatorPos = strrpos($class, '\\');
30795 $className = $class;
30796 if ($separatorPos) {
30797 $className = substr($class, $separatorPos + 1);
30798 }
30799 $code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
30800 $code = str_replace('__FILE__', var_export($path, true), $code);
30801 $code = str_replace('__DIR__', var_export(dirname($path), true), $code);
30802 $code = str_replace('__CLASS__', var_export($class, true), $code);
30803 $code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
30804 eval($code);
30805 $class .= '_composer_tmp'.self::$classCounter;
30806 self::$classCounter++;
30807 }
30808
30809 if ($oldInstallerPlugin) {
30810 $installer = new $class($this->io, $this->composer);
30811 $this->composer->getInstallationManager()->addInstaller($installer);
30812 } elseif (class_exists($class)) {
30813 $plugin = new $class();
30814 $this->addPlugin($plugin);
30815 $this->registeredPlugins[] = $package->getName();
30816 } elseif ($failOnMissingClasses) {
30817 throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
30818 }
30819 }
30820 }
30821
30822
30823
30824
30825
30826
30827 protected function getPluginApiVersion()
30828 {
30829 return PluginInterface::PLUGIN_API_VERSION;
30830 }
30831
30832
30833
30834
30835
30836
30837
30838
30839
30840
30841 public function addPlugin(PluginInterface $plugin)
30842 {
30843 $this->io->writeError('Loading plugin '.get_class($plugin), true, IOInterface::DEBUG);
30844 $this->plugins[] = $plugin;
30845 $plugin->activate($this->composer, $this->io);
30846
30847 if ($plugin instanceof EventSubscriberInterface) {
30848 $this->composer->getEventDispatcher()->addSubscriber($plugin);
30849 }
30850 }
30851
30852
30853
30854
30855
30856
30857
30858
30859
30860
30861
30862
30863 private function loadRepository(RepositoryInterface $repo)
30864 {
30865 foreach ($repo->getPackages() as $package) { 
30866 if ($package instanceof AliasPackage) {
30867 continue;
30868 }
30869 if ('composer-plugin' === $package->getType()) {
30870 $this->registerPackage($package);
30871
30872  } elseif ('composer-installer' === $package->getType()) {
30873 $this->registerPackage($package);
30874 }
30875 }
30876 }
30877
30878
30879
30880
30881
30882
30883
30884
30885
30886
30887 private function collectDependencies(Pool $pool, array $collected, PackageInterface $package)
30888 {
30889 $requires = array_merge(
30890 $package->getRequires(),
30891 $package->getDevRequires()
30892 );
30893
30894 foreach ($requires as $requireLink) {
30895 $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink);
30896 if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) {
30897 $collected[$requiredPackage->getName()] = $requiredPackage;
30898 $collected = $this->collectDependencies($pool, $collected, $requiredPackage);
30899 }
30900 }
30901
30902 return $collected;
30903 }
30904
30905
30906
30907
30908
30909
30910
30911
30912
30913
30914
30915 private function lookupInstalledPackage(Pool $pool, Link $link)
30916 {
30917 $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint());
30918
30919 return (!empty($packages)) ? $packages[0] : null;
30920 }
30921
30922
30923
30924
30925
30926
30927
30928
30929
30930 private function getInstallPath(PackageInterface $package, $global = false)
30931 {
30932 if (!$global) {
30933 return $this->composer->getInstallationManager()->getInstallPath($package);
30934 }
30935
30936 return $this->globalComposer->getInstallationManager()->getInstallPath($package);
30937 }
30938
30939
30940
30941
30942
30943
30944
30945 protected function getCapabilityImplementationClassName(PluginInterface $plugin, $capability)
30946 {
30947 if (!($plugin instanceof Capable)) {
30948 return null;
30949 }
30950
30951 $capabilities = (array) $plugin->getCapabilities();
30952
30953 if (!empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability])) {
30954 return trim($capabilities[$capability]);
30955 }
30956
30957 if (
30958 array_key_exists($capability, $capabilities)
30959 && (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))
30960 ) {
30961 throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], 1));
30962 }
30963 }
30964
30965
30966
30967
30968
30969
30970
30971
30972
30973 public function getPluginCapability(PluginInterface $plugin, $capabilityClassName, array $ctorArgs = array())
30974 {
30975 if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) {
30976 if (!class_exists($capabilityClass)) {
30977 throw new \RuntimeException("Cannot instantiate Capability, as class $capabilityClass from plugin ".get_class($plugin)." does not exist.");
30978 }
30979
30980 $ctorArgs['plugin'] = $plugin;
30981 $capabilityObj = new $capabilityClass($ctorArgs);
30982
30983
30984  if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) {
30985 throw new \RuntimeException(
30986 'Class ' . $capabilityClass . ' must implement both Composer\Plugin\Capability\Capability and '. $capabilityClassName . '.'
30987 );
30988 }
30989
30990 return $capabilityObj;
30991 }
30992 }
30993
30994
30995
30996
30997
30998
30999
31000
31001 public function getPluginCapabilities($capabilityClassName, array $ctorArgs = array())
31002 {
31003 $capabilities = array();
31004 foreach ($this->getPlugins() as $plugin) {
31005 if ($capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs)) {
31006 $capabilities[] = $capability;
31007 }
31008 }
31009
31010 return $capabilities;
31011 }
31012 }
31013 <?php
31014
31015
31016
31017
31018
31019
31020
31021
31022
31023
31024
31025 namespace Composer\Plugin;
31026
31027 use Composer\EventDispatcher\Event;
31028 use Composer\Util\RemoteFilesystem;
31029
31030
31031
31032
31033
31034
31035 class PreFileDownloadEvent extends Event
31036 {
31037
31038
31039
31040 private $rfs;
31041
31042
31043
31044
31045 private $processedUrl;
31046
31047
31048
31049
31050
31051
31052
31053
31054 public function __construct($name, RemoteFilesystem $rfs, $processedUrl)
31055 {
31056 parent::__construct($name);
31057 $this->rfs = $rfs;
31058 $this->processedUrl = $processedUrl;
31059 }
31060
31061
31062
31063
31064
31065
31066 public function getRemoteFilesystem()
31067 {
31068 return $this->rfs;
31069 }
31070
31071
31072
31073
31074
31075
31076 public function setRemoteFilesystem(RemoteFilesystem $rfs)
31077 {
31078 $this->rfs = $rfs;
31079 }
31080
31081
31082
31083
31084
31085
31086 public function getProcessedUrl()
31087 {
31088 return $this->processedUrl;
31089 }
31090 }
31091 <?php
31092
31093
31094
31095
31096
31097
31098
31099
31100
31101
31102
31103 namespace Composer\Question;
31104
31105 use Symfony\Component\Console\Exception\InvalidArgumentException;
31106 use Symfony\Component\Console\Question\Question;
31107
31108
31109
31110
31111
31112
31113
31114
31115 class StrictConfirmationQuestion extends Question
31116 {
31117 private $trueAnswerRegex;
31118 private $falseAnswerRegex;
31119
31120
31121
31122
31123
31124
31125
31126
31127
31128 public function __construct($question, $default = true, $trueAnswerRegex = '/^y(?:es)?$/i', $falseAnswerRegex = '/^no?$/i')
31129 {
31130 parent::__construct($question, (bool) $default);
31131
31132 $this->trueAnswerRegex = $trueAnswerRegex;
31133 $this->falseAnswerRegex = $falseAnswerRegex;
31134 $this->setNormalizer($this->getDefaultNormalizer());
31135 $this->setValidator($this->getDefaultValidator());
31136 }
31137
31138
31139
31140
31141
31142
31143 private function getDefaultNormalizer()
31144 {
31145 $default = $this->getDefault();
31146 $trueRegex = $this->trueAnswerRegex;
31147 $falseRegex = $this->falseAnswerRegex;
31148
31149 return function ($answer) use ($default, $trueRegex, $falseRegex) {
31150 if (is_bool($answer)) {
31151 return $answer;
31152 }
31153 if (empty($answer) && !empty($default)) {
31154 return $default;
31155 }
31156
31157 if (preg_match($trueRegex, $answer)) {
31158 return true;
31159 }
31160
31161 if (preg_match($falseRegex, $answer)) {
31162 return false;
31163 }
31164
31165 return null;
31166 };
31167 }
31168
31169
31170
31171
31172
31173
31174 private function getDefaultValidator()
31175 {
31176 return function ($answer) {
31177 if (!is_bool($answer)) {
31178 throw new InvalidArgumentException('Please answer yes, y, no, or n.');
31179 }
31180
31181 return $answer;
31182 };
31183 }
31184 }
31185 <?php
31186
31187
31188
31189
31190
31191
31192
31193
31194
31195
31196
31197 namespace Composer\Repository;
31198
31199 use Composer\Package\AliasPackage;
31200 use Composer\Package\PackageInterface;
31201 use Composer\Package\CompletePackageInterface;
31202 use Composer\Package\Version\VersionParser;
31203 use Composer\Semver\Constraint\ConstraintInterface;
31204 use Composer\Semver\Constraint\Constraint;
31205
31206
31207
31208
31209
31210
31211 class ArrayRepository extends BaseRepository
31212 {
31213
31214 protected $packages;
31215
31216 public function __construct(array $packages = array())
31217 {
31218 foreach ($packages as $package) {
31219 $this->addPackage($package);
31220 }
31221 }
31222
31223
31224
31225
31226 public function findPackage($name, $constraint)
31227 {
31228 $name = strtolower($name);
31229
31230 if (!$constraint instanceof ConstraintInterface) {
31231 $versionParser = new VersionParser();
31232 $constraint = $versionParser->parseConstraints($constraint);
31233 }
31234
31235 foreach ($this->getPackages() as $package) {
31236 if ($name === $package->getName()) {
31237 $pkgConstraint = new Constraint('==', $package->getVersion());
31238 if ($constraint->matches($pkgConstraint)) {
31239 return $package;
31240 }
31241 }
31242 }
31243
31244 return null;
31245 }
31246
31247
31248
31249
31250 public function findPackages($name, $constraint = null)
31251 {
31252
31253  $name = strtolower($name);
31254 $packages = array();
31255
31256 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
31257 $versionParser = new VersionParser();
31258 $constraint = $versionParser->parseConstraints($constraint);
31259 }
31260
31261 foreach ($this->getPackages() as $package) {
31262 if ($name === $package->getName()) {
31263 $pkgConstraint = new Constraint('==', $package->getVersion());
31264 if (null === $constraint || $constraint->matches($pkgConstraint)) {
31265 $packages[] = $package;
31266 }
31267 }
31268 }
31269
31270 return $packages;
31271 }
31272
31273
31274
31275
31276 public function search($query, $mode = 0, $type = null)
31277 {
31278 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
31279
31280 $matches = array();
31281 foreach ($this->getPackages() as $package) {
31282 $name = $package->getName();
31283 if (isset($matches[$name])) {
31284 continue;
31285 }
31286 if (preg_match($regex, $name)
31287 || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
31288 ) {
31289 if (null !== $type && $package->getType() !== $type) {
31290 continue;
31291 }
31292
31293 $matches[$name] = array(
31294 'name' => $package->getPrettyName(),
31295 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null,
31296 );
31297 }
31298 }
31299
31300 return array_values($matches);
31301 }
31302
31303
31304
31305
31306 public function hasPackage(PackageInterface $package)
31307 {
31308 $packageId = $package->getUniqueName();
31309
31310 foreach ($this->getPackages() as $repoPackage) {
31311 if ($packageId === $repoPackage->getUniqueName()) {
31312 return true;
31313 }
31314 }
31315
31316 return false;
31317 }
31318
31319
31320
31321
31322
31323
31324 public function addPackage(PackageInterface $package)
31325 {
31326 if (null === $this->packages) {
31327 $this->initialize();
31328 }
31329 $package->setRepository($this);
31330 $this->packages[] = $package;
31331
31332 if ($package instanceof AliasPackage) {
31333 $aliasedPackage = $package->getAliasOf();
31334 if (null === $aliasedPackage->getRepository()) {
31335 $this->addPackage($aliasedPackage);
31336 }
31337 }
31338 }
31339
31340 protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
31341 {
31342 return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
31343 }
31344
31345
31346
31347
31348
31349
31350 public function removePackage(PackageInterface $package)
31351 {
31352 $packageId = $package->getUniqueName();
31353
31354 foreach ($this->getPackages() as $key => $repoPackage) {
31355 if ($packageId === $repoPackage->getUniqueName()) {
31356 array_splice($this->packages, $key, 1);
31357
31358 return;
31359 }
31360 }
31361 }
31362
31363
31364
31365
31366 public function getPackages()
31367 {
31368 if (null === $this->packages) {
31369 $this->initialize();
31370 }
31371
31372 return $this->packages;
31373 }
31374
31375
31376
31377
31378
31379
31380 public function count()
31381 {
31382 return count($this->packages);
31383 }
31384
31385
31386
31387
31388 protected function initialize()
31389 {
31390 $this->packages = array();
31391 }
31392 }
31393 <?php
31394
31395
31396
31397
31398
31399
31400
31401
31402
31403
31404
31405 namespace Composer\Repository;
31406
31407 use Composer\IO\IOInterface;
31408 use Composer\Json\JsonFile;
31409 use Composer\Package\Loader\ArrayLoader;
31410 use Composer\Package\Loader\LoaderInterface;
31411
31412
31413
31414
31415 class ArtifactRepository extends ArrayRepository implements ConfigurableRepositoryInterface
31416 {
31417
31418 protected $loader;
31419
31420 protected $lookup;
31421 protected $repoConfig;
31422 private $io;
31423
31424 public function __construct(array $repoConfig, IOInterface $io)
31425 {
31426 parent::__construct();
31427 if (!extension_loaded('zip')) {
31428 throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
31429 }
31430
31431 $this->loader = new ArrayLoader();
31432 $this->lookup = $repoConfig['url'];
31433 $this->io = $io;
31434 $this->repoConfig = $repoConfig;
31435 }
31436
31437 public function getRepoConfig()
31438 {
31439 return $this->repoConfig;
31440 }
31441
31442 protected function initialize()
31443 {
31444 parent::initialize();
31445
31446 $this->scanDirectory($this->lookup);
31447 }
31448
31449 private function scanDirectory($path)
31450 {
31451 $io = $this->io;
31452
31453 $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
31454 $iterator = new \RecursiveIteratorIterator($directory);
31455 $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i');
31456 foreach ($regex as $file) {
31457
31458 if (!$file->isFile()) {
31459 continue;
31460 }
31461
31462 $package = $this->getComposerInformation($file);
31463 if (!$package) {
31464 $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", true, IOInterface::VERBOSE);
31465 continue;
31466 }
31467
31468 $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
31469 $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), true, IOInterface::VERBOSE);
31470
31471 $this->addPackage($package);
31472 }
31473 }
31474
31475
31476
31477
31478
31479
31480
31481
31482 private function locateFile(\ZipArchive $zip, $filename)
31483 {
31484 $indexOfShortestMatch = false;
31485 $lengthOfShortestMatch = -1;
31486
31487 for ($i = 0; $i < $zip->numFiles; $i++) {
31488 $stat = $zip->statIndex($i);
31489 if (strcmp(basename($stat['name']), $filename) === 0) {
31490 $directoryName = dirname($stat['name']);
31491 if ($directoryName == '.') {
31492
31493  
31494  return $i;
31495 }
31496
31497 if (strpos($directoryName, '\\') !== false ||
31498 strpos($directoryName, '/') !== false) {
31499
31500  continue;
31501 }
31502
31503 $length = strlen($stat['name']);
31504 if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) {
31505
31506  $contents = $zip->getFromIndex($i);
31507 if ($contents !== false) {
31508 $indexOfShortestMatch = $i;
31509 $lengthOfShortestMatch = $length;
31510 }
31511 }
31512 }
31513 }
31514
31515 return $indexOfShortestMatch;
31516 }
31517
31518 private function getComposerInformation(\SplFileInfo $file)
31519 {
31520 $zip = new \ZipArchive();
31521 $zip->open($file->getPathname());
31522
31523 if (0 == $zip->numFiles) {
31524 return false;
31525 }
31526
31527 $foundFileIndex = $this->locateFile($zip, 'composer.json');
31528 if (false === $foundFileIndex) {
31529 return false;
31530 }
31531
31532 $configurationFileName = $zip->getNameIndex($foundFileIndex);
31533
31534 $composerFile = "zip://{$file->getPathname()}#$configurationFileName";
31535 $json = file_get_contents($composerFile);
31536
31537 $package = JsonFile::parseJson($json, $composerFile);
31538 $package['dist'] = array(
31539 'type' => 'zip',
31540 'url' => strtr($file->getPathname(), '\\', '/'),
31541 'shasum' => sha1_file($file->getRealPath()),
31542 );
31543
31544 try {
31545 $package = $this->loader->load($package);
31546 } catch (\UnexpectedValueException $e) {
31547 throw new \UnexpectedValueException('Failed loading package in '.$file.': '.$e->getMessage(), 0, $e);
31548 }
31549
31550 return $package;
31551 }
31552 }
31553 <?php
31554
31555
31556
31557
31558
31559
31560
31561
31562
31563
31564
31565 namespace Composer\Repository;
31566
31567 use Composer\Package\RootPackageInterface;
31568 use Composer\Semver\Constraint\ConstraintInterface;
31569 use Composer\Semver\Constraint\Constraint;
31570 use Composer\Package\Link;
31571
31572
31573
31574
31575
31576
31577 abstract class BaseRepository implements RepositoryInterface
31578 {
31579
31580
31581
31582
31583
31584
31585
31586
31587
31588
31589
31590
31591
31592 public function getDependents($needle, $constraint = null, $invert = false, $recurse = true, $packagesFound = null)
31593 {
31594 $needles = (array) $needle;
31595 $results = array();
31596
31597
31598  if (null === $packagesFound) {
31599 $packagesFound = $needles;
31600 }
31601
31602
31603  $rootPackage = null;
31604 foreach ($this->getPackages() as $package) {
31605 if ($package instanceof RootPackageInterface) {
31606 $rootPackage = $package;
31607 break;
31608 }
31609 }
31610
31611
31612  foreach ($this->getPackages() as $package) {
31613 $links = $package->getRequires();
31614
31615
31616  
31617  $packagesInTree = $packagesFound;
31618
31619
31620  if (!$invert) {
31621 $links += $package->getReplaces();
31622 }
31623
31624
31625  if ($package instanceof RootPackageInterface) {
31626 $links += $package->getDevRequires();
31627 }
31628
31629
31630  foreach ($links as $link) {
31631 foreach ($needles as $needle) {
31632 if ($link->getTarget() === $needle) {
31633 if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
31634
31635  if (in_array($link->getSource(), $packagesInTree)) {
31636 $results[$link->getSource()] = array($package, $link, false);
31637 continue;
31638 }
31639 $packagesInTree[] = $link->getSource();
31640 $dependents = $recurse ? $this->getDependents($link->getSource(), null, false, true, $packagesInTree) : array();
31641 $results[$link->getSource()] = array($package, $link, $dependents);
31642 }
31643 }
31644 }
31645 }
31646
31647
31648  if ($invert && in_array($package->getName(), $needles)) {
31649 foreach ($package->getConflicts() as $link) {
31650 foreach ($this->findPackages($link->getTarget()) as $pkg) {
31651 $version = new Constraint('=', $pkg->getVersion());
31652 if ($link->getConstraint()->matches($version) === $invert) {
31653 $results[] = array($package, $link, false);
31654 }
31655 }
31656 }
31657 }
31658
31659
31660  if ($invert && $constraint && in_array($package->getName(), $needles) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
31661 foreach ($package->getRequires() as $link) {
31662 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
31663 if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
31664 continue;
31665 }
31666
31667 $platformPkg = $this->findPackage($link->getTarget(), '*');
31668 $description = $platformPkg ? 'but '.$platformPkg->getPrettyVersion().' is installed' : 'but it is missing';
31669 $results[] = array($package, new Link($package->getName(), $link->getTarget(), null, 'requires', $link->getPrettyConstraint().' '.$description), false);
31670
31671 continue;
31672 }
31673
31674 foreach ($this->getPackages() as $pkg) {
31675 if (!in_array($link->getTarget(), $pkg->getNames())) {
31676 continue;
31677 }
31678
31679 $version = new Constraint('=', $pkg->getVersion());
31680 if (!$link->getConstraint()->matches($version)) {
31681
31682  
31683  if ($rootPackage) {
31684 foreach (array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) {
31685 if (in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) {
31686 $results[] = array($package, $link, false);
31687 $results[] = array($rootPackage, $rootReq, false);
31688 continue 3;
31689 }
31690 }
31691 $results[] = array($package, $link, false);
31692 $results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), null, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
31693 } else {
31694
31695  $results[] = array($package, $link, false);
31696 }
31697 }
31698
31699 continue 2;
31700 }
31701 }
31702 }
31703 }
31704
31705 ksort($results);
31706
31707 return $results;
31708 }
31709 }
31710 <?php
31711
31712
31713
31714
31715
31716
31717
31718
31719
31720
31721
31722 namespace Composer\Repository;
31723
31724 use Composer\Package\Loader\ArrayLoader;
31725 use Composer\Package\PackageInterface;
31726 use Composer\Package\AliasPackage;
31727 use Composer\Package\Version\VersionParser;
31728 use Composer\DependencyResolver\Pool;
31729 use Composer\Json\JsonFile;
31730 use Composer\Cache;
31731 use Composer\Config;
31732 use Composer\Factory;
31733 use Composer\IO\IOInterface;
31734 use Composer\Util\RemoteFilesystem;
31735 use Composer\Plugin\PluginEvents;
31736 use Composer\Plugin\PreFileDownloadEvent;
31737 use Composer\EventDispatcher\EventDispatcher;
31738 use Composer\Downloader\TransportException;
31739 use Composer\Semver\Constraint\ConstraintInterface;
31740 use Composer\Semver\Constraint\Constraint;
31741
31742
31743
31744
31745 class ComposerRepository extends ArrayRepository implements ConfigurableRepositoryInterface
31746 {
31747 protected $config;
31748 protected $repoConfig;
31749 protected $options;
31750 protected $url;
31751 protected $baseUrl;
31752 protected $io;
31753 protected $rfs;
31754 protected $cache;
31755 protected $notifyUrl;
31756 protected $searchUrl;
31757 protected $hasProviders = false;
31758 protected $providersUrl;
31759 protected $lazyProvidersUrl;
31760 protected $providerListing;
31761 protected $providers = array();
31762 protected $providersByUid = array();
31763 protected $loader;
31764 protected $rootAliases;
31765 protected $allowSslDowngrade = false;
31766 protected $eventDispatcher;
31767 protected $sourceMirrors;
31768 protected $distMirrors;
31769 private $degradedMode = false;
31770 private $rootData;
31771 private $hasPartialPackages;
31772 private $partialPackagesByName;
31773
31774 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
31775 {
31776 parent::__construct();
31777 if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) {
31778
31779  $repoConfig['url'] = 'http://'.$repoConfig['url'];
31780 }
31781 $repoConfig['url'] = rtrim($repoConfig['url'], '/');
31782
31783 if ('https?' === substr($repoConfig['url'], 0, 6)) {
31784 $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
31785 }
31786
31787 $urlBits = parse_url($repoConfig['url']);
31788 if ($urlBits === false || empty($urlBits['scheme'])) {
31789 throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
31790 }
31791
31792 if (!isset($repoConfig['options'])) {
31793 $repoConfig['options'] = array();
31794 }
31795 if (isset($repoConfig['allow_ssl_downgrade']) && true === $repoConfig['allow_ssl_downgrade']) {
31796 $this->allowSslDowngrade = true;
31797 }
31798
31799 $this->config = $config;
31800 $this->options = $repoConfig['options'];
31801 $this->url = $repoConfig['url'];
31802 $this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
31803 $this->io = $io;
31804 $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
31805 $this->loader = new ArrayLoader();
31806 if ($rfs && $this->options) {
31807 $rfs = clone $rfs;
31808 $rfs->setOptions($this->options);
31809 }
31810 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $this->config, $this->options);
31811 $this->eventDispatcher = $eventDispatcher;
31812 $this->repoConfig = $repoConfig;
31813 }
31814
31815 public function getRepoConfig()
31816 {
31817 return $this->repoConfig;
31818 }
31819
31820 public function setRootAliases(array $rootAliases)
31821 {
31822 $this->rootAliases = $rootAliases;
31823 }
31824
31825
31826
31827
31828 public function findPackage($name, $constraint)
31829 {
31830 if (!$this->hasProviders()) {
31831 return parent::findPackage($name, $constraint);
31832 }
31833
31834 $name = strtolower($name);
31835 if (!$constraint instanceof ConstraintInterface) {
31836 $versionParser = new VersionParser();
31837 $constraint = $versionParser->parseConstraints($constraint);
31838 }
31839
31840 foreach ($this->getProviderNames() as $providerName) {
31841 if ($name === $providerName) {
31842 $packages = $this->whatProvides(new Pool('dev'), $providerName);
31843 foreach ($packages as $package) {
31844 if ($name === $package->getName()) {
31845 $pkgConstraint = new Constraint('==', $package->getVersion());
31846 if ($constraint->matches($pkgConstraint)) {
31847 return $package;
31848 }
31849 }
31850 }
31851 break;
31852 }
31853 }
31854 }
31855
31856
31857
31858
31859 public function findPackages($name, $constraint = null)
31860 {
31861 if (!$this->hasProviders()) {
31862 return parent::findPackages($name, $constraint);
31863 }
31864
31865  $name = strtolower($name);
31866
31867 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
31868 $versionParser = new VersionParser();
31869 $constraint = $versionParser->parseConstraints($constraint);
31870 }
31871
31872 $packages = array();
31873
31874 foreach ($this->getProviderNames() as $providerName) {
31875 if ($name === $providerName) {
31876 $candidates = $this->whatProvides(new Pool('dev'), $providerName);
31877 foreach ($candidates as $package) {
31878 if ($name === $package->getName()) {
31879 $pkgConstraint = new Constraint('==', $package->getVersion());
31880 if (null === $constraint || $constraint->matches($pkgConstraint)) {
31881 $packages[] = $package;
31882 }
31883 }
31884 }
31885 break;
31886 }
31887 }
31888
31889 return $packages;
31890 }
31891
31892 public function getPackages()
31893 {
31894 if ($this->hasProviders()) {
31895 throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.');
31896 }
31897
31898 return parent::getPackages();
31899 }
31900
31901
31902
31903
31904 public function search($query, $mode = 0, $type = null)
31905 {
31906 $this->loadRootServerFile();
31907
31908 if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
31909 $url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl);
31910
31911 $hostname = parse_url($url, PHP_URL_HOST) ?: $url;
31912 $json = $this->rfs->getContents($hostname, $url, false);
31913 $results = JsonFile::parseJson($json, $url);
31914
31915 return $results['results'];
31916 }
31917
31918 if ($this->hasProviders()) {
31919 $results = array();
31920 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
31921
31922 foreach ($this->getProviderNames() as $name) {
31923 if (preg_match($regex, $name)) {
31924 $results[] = array('name' => $name);
31925 }
31926 }
31927
31928 return $results;
31929 }
31930
31931 return parent::search($query, $mode);
31932 }
31933
31934 public function getProviderNames()
31935 {
31936 $this->loadRootServerFile();
31937
31938 if (null === $this->providerListing) {
31939 $this->loadProviderListings($this->loadRootServerFile());
31940 }
31941
31942 if ($this->lazyProvidersUrl) {
31943
31944  return array();
31945 }
31946
31947 if ($this->providersUrl) {
31948 return array_keys($this->providerListing);
31949 }
31950
31951 return array();
31952 }
31953
31954 protected function configurePackageTransportOptions(PackageInterface $package)
31955 {
31956 foreach ($package->getDistUrls() as $url) {
31957 if (strpos($url, $this->baseUrl) === 0) {
31958 $package->setTransportOptions($this->options);
31959
31960 return;
31961 }
31962 }
31963 }
31964
31965 public function hasProviders()
31966 {
31967 $this->loadRootServerFile();
31968
31969 return $this->hasProviders;
31970 }
31971
31972 public function resetPackageIds()
31973 {
31974 foreach ($this->providersByUid as $package) {
31975 if ($package instanceof AliasPackage) {
31976 $package->getAliasOf()->setId(-1);
31977 }
31978 $package->setId(-1);
31979 }
31980 }
31981
31982
31983
31984
31985
31986
31987
31988 public function whatProvides(Pool $pool, $name, $bypassFilters = false)
31989 {
31990 if (isset($this->providers[$name]) && !$bypassFilters) {
31991 return $this->providers[$name];
31992 }
31993
31994 if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
31995 $this->initializePartialPackages();
31996 }
31997
31998 if (!$this->hasPartialPackages || !isset($this->partialPackagesByName[$name])) {
31999
32000  if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) {
32001 return array();
32002 }
32003
32004 if (null === $this->providerListing) {
32005 $this->loadProviderListings($this->loadRootServerFile());
32006 }
32007
32008 $useLastModifiedCheck = false;
32009 if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
32010 $hash = null;
32011 $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
32012 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
32013 $useLastModifiedCheck = true;
32014 } elseif ($this->providersUrl) {
32015
32016  if (!isset($this->providerListing[$name])) {
32017 return array();
32018 }
32019
32020 $hash = $this->providerListing[$name]['sha256'];
32021 $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
32022 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
32023 } else {
32024 return array();
32025 }
32026
32027 $packages = null;
32028 if ($cacheKey) {
32029 if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) {
32030 $packages = json_decode($this->cache->read($cacheKey), true);
32031 } elseif ($useLastModifiedCheck) {
32032 if ($contents = $this->cache->read($cacheKey)) {
32033 $contents = json_decode($contents, true);
32034 if (isset($contents['last-modified'])) {
32035 $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']);
32036 if (true === $response) {
32037 $packages = $contents;
32038 } elseif ($response) {
32039 $packages = $response;
32040 }
32041 }
32042 }
32043 }
32044 }
32045
32046 if (!$packages) {
32047 try {
32048 $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck);
32049 } catch (TransportException $e) {
32050
32051  if ($e->getStatusCode() === 404 && $this->lazyProvidersUrl) {
32052 $packages = array('packages' => array());
32053 } else {
32054 throw $e;
32055 }
32056 }
32057 }
32058
32059 $loadingPartialPackage = false;
32060 } else {
32061 $packages = array('packages' => array('versions' => $this->partialPackagesByName[$name]));
32062 $loadingPartialPackage = true;
32063 }
32064
32065 $this->providers[$name] = array();
32066 foreach ($packages['packages'] as $versions) {
32067 foreach ($versions as $version) {
32068 if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
32069 continue;
32070 }
32071
32072
32073  if (isset($this->providersByUid[$version['uid']])) {
32074
32075  if (!isset($this->providers[$name][$version['uid']])) {
32076
32077  if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
32078 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
32079 $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
32080 } else {
32081 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
32082 }
32083
32084  if (isset($this->providersByUid[$version['uid'].'-root'])) {
32085 $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
32086 }
32087 }
32088 } else {
32089 if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
32090 continue;
32091 }
32092
32093
32094  $package = $this->createPackage($version, 'Composer\Package\CompletePackage');
32095 $package->setRepository($this);
32096
32097 if ($package instanceof AliasPackage) {
32098 $aliased = $package->getAliasOf();
32099 $aliased->setRepository($this);
32100
32101 $this->providers[$name][$version['uid']] = $aliased;
32102 $this->providers[$name][$version['uid'].'-alias'] = $package;
32103
32104
32105  $this->providersByUid[$version['uid']] = $package;
32106 } else {
32107 $this->providers[$name][$version['uid']] = $package;
32108 $this->providersByUid[$version['uid']] = $package;
32109 }
32110
32111
32112  unset($rootAliasData);
32113
32114 if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
32115 $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
32116 } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
32117 $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
32118 }
32119
32120 if (isset($rootAliasData)) {
32121 $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
32122 $alias->setRepository($this);
32123
32124 $this->providers[$name][$version['uid'].'-root'] = $alias;
32125 $this->providersByUid[$version['uid'].'-root'] = $alias;
32126 }
32127 }
32128 }
32129 }
32130
32131 $result = $this->providers[$name];
32132
32133
32134  
32135  if ($bypassFilters) {
32136 foreach ($this->providers[$name] as $uid => $provider) {
32137 unset($this->providersByUid[$uid]);
32138 }
32139 unset($this->providers[$name]);
32140 }
32141
32142 return $result;
32143 }
32144
32145
32146
32147
32148 protected function initialize()
32149 {
32150 parent::initialize();
32151
32152 $repoData = $this->loadDataFromServer();
32153
32154 foreach ($repoData as $package) {
32155 $this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
32156 }
32157 }
32158
32159
32160
32161
32162
32163
32164 public function addPackage(PackageInterface $package)
32165 {
32166 parent::addPackage($package);
32167 $this->configurePackageTransportOptions($package);
32168 }
32169
32170 protected function loadRootServerFile()
32171 {
32172 if (null !== $this->rootData) {
32173 return $this->rootData;
32174 }
32175
32176 if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
32177 throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
32178 }
32179
32180 $jsonUrlParts = parse_url($this->url);
32181
32182 if (isset($jsonUrlParts['path']) && false !== strpos($jsonUrlParts['path'], '.json')) {
32183 $jsonUrl = $this->url;
32184 } else {
32185 $jsonUrl = $this->url . '/packages.json';
32186 }
32187
32188 $data = $this->fetchFile($jsonUrl, 'packages.json');
32189
32190 if (!empty($data['notify-batch'])) {
32191 $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
32192 } elseif (!empty($data['notify'])) {
32193 $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
32194 }
32195
32196 if (!empty($data['search'])) {
32197 $this->searchUrl = $this->canonicalizeUrl($data['search']);
32198 }
32199
32200 if (!empty($data['mirrors'])) {
32201 foreach ($data['mirrors'] as $mirror) {
32202 if (!empty($mirror['git-url'])) {
32203 $this->sourceMirrors['git'][] = array('url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred']));
32204 }
32205 if (!empty($mirror['hg-url'])) {
32206 $this->sourceMirrors['hg'][] = array('url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred']));
32207 }
32208 if (!empty($mirror['dist-url'])) {
32209 $this->distMirrors[] = array(
32210 'url' => $this->canonicalizeUrl($mirror['dist-url']),
32211 'preferred' => !empty($mirror['preferred']),
32212 );
32213 }
32214 }
32215 }
32216
32217 if (!empty($data['providers-lazy-url'])) {
32218 $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
32219 $this->hasProviders = true;
32220
32221 $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
32222 }
32223
32224 if ($this->allowSslDowngrade) {
32225 $this->url = str_replace('https://', 'http://', $this->url);
32226 $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
32227 }
32228
32229 if (!empty($data['providers-url'])) {
32230 $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
32231 $this->hasProviders = true;
32232 }
32233
32234 if (!empty($data['providers']) || !empty($data['providers-includes'])) {
32235 $this->hasProviders = true;
32236 }
32237
32238
32239  if (preg_match('{^https?://packagist.org/?$}i', $this->url) && !empty($this->repoConfig['force-lazy-providers'])) {
32240 $this->url = 'https://packagist.org';
32241 $this->baseUrl = 'https://packagist.org';
32242 $this->lazyProvidersUrl = $this->canonicalizeUrl('https://packagist.org/p/%package%.json');
32243 $this->providersUrl = null;
32244 } elseif (!empty($this->repoConfig['force-lazy-providers'])) {
32245 $this->lazyProvidersUrl = $this->canonicalizeUrl('/p/%package%.json');
32246 $this->providersUrl = null;
32247 }
32248
32249 return $this->rootData = $data;
32250 }
32251
32252 protected function canonicalizeUrl($url)
32253 {
32254 if ('/' === $url[0]) {
32255 return preg_replace('{(https?://[^/]+).*}i', '$1' . $url, $this->url);
32256 }
32257
32258 return $url;
32259 }
32260
32261 protected function loadDataFromServer()
32262 {
32263 $data = $this->loadRootServerFile();
32264
32265 return $this->loadIncludes($data);
32266 }
32267
32268 protected function loadProviderListings($data)
32269 {
32270 if (isset($data['providers'])) {
32271 if (!is_array($this->providerListing)) {
32272 $this->providerListing = array();
32273 }
32274 $this->providerListing = array_merge($this->providerListing, $data['providers']);
32275 }
32276
32277 if ($this->providersUrl && isset($data['provider-includes'])) {
32278 $includes = $data['provider-includes'];
32279 foreach ($includes as $include => $metadata) {
32280 $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
32281 $cacheKey = str_replace(array('%hash%','$'), '', $include);
32282 if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
32283 $includedData = json_decode($this->cache->read($cacheKey), true);
32284 } else {
32285 $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
32286 }
32287
32288 $this->loadProviderListings($includedData);
32289 }
32290 }
32291 }
32292
32293 protected function loadIncludes($data)
32294 {
32295 $packages = array();
32296
32297
32298  if (!isset($data['packages']) && !isset($data['includes'])) {
32299 foreach ($data as $pkg) {
32300 foreach ($pkg['versions'] as $metadata) {
32301 $packages[] = $metadata;
32302 }
32303 }
32304
32305 return $packages;
32306 }
32307
32308 if (isset($data['packages'])) {
32309 foreach ($data['packages'] as $package => $versions) {
32310 foreach ($versions as $version => $metadata) {
32311 $packages[] = $metadata;
32312 }
32313 }
32314 }
32315
32316 if (isset($data['includes'])) {
32317 foreach ($data['includes'] as $include => $metadata) {
32318 if ($this->cache->sha1($include) === $metadata['sha1']) {
32319 $includedData = json_decode($this->cache->read($include), true);
32320 } else {
32321 $includedData = $this->fetchFile($include);
32322 }
32323 $packages = array_merge($packages, $this->loadIncludes($includedData));
32324 }
32325 }
32326
32327 return $packages;
32328 }
32329
32330 protected function createPackage(array $data, $class = 'Composer\Package\CompletePackage')
32331 {
32332 try {
32333 if (!isset($data['notification-url'])) {
32334 $data['notification-url'] = $this->notifyUrl;
32335 }
32336
32337 $package = $this->loader->load($data, $class);
32338 if (isset($this->sourceMirrors[$package->getSourceType()])) {
32339 $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
32340 }
32341 $package->setDistMirrors($this->distMirrors);
32342 $this->configurePackageTransportOptions($package);
32343
32344 return $package;
32345 } catch (\Exception $e) {
32346 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);
32347 }
32348 }
32349
32350 protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)
32351 {
32352 if (null === $cacheKey) {
32353 $cacheKey = $filename;
32354 $filename = $this->baseUrl.'/'.$filename;
32355 }
32356
32357
32358  if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) {
32359 $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
32360 }
32361
32362 $retries = 3;
32363 while ($retries--) {
32364 try {
32365 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
32366 if ($this->eventDispatcher) {
32367 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
32368 }
32369
32370 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
32371 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
32372
32373 $json = $rfs->getContents($hostname, $filename, false);
32374 if ($sha256 && $sha256 !== hash('sha256', $json)) {
32375
32376  if ($this->allowSslDowngrade) {
32377 $this->url = str_replace('http://', 'https://', $this->url);
32378 $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
32379 $filename = str_replace('http://', 'https://', $filename);
32380 }
32381
32382 if ($retries) {
32383 usleep(100000);
32384
32385 continue;
32386 }
32387
32388
32389  throw new RepositorySecurityException('The contents of '.$filename.' do not match its signature. This could indicate a man-in-the-middle attack. Try running composer again and report this if you think it is a mistake.');
32390 }
32391
32392 $data = JsonFile::parseJson($json, $filename);
32393 if (!empty($data['warning'])) {
32394 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
32395 }
32396 if (!empty($data['info'])) {
32397 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
32398 }
32399
32400 if ($cacheKey) {
32401 if ($storeLastModifiedTime) {
32402 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
32403 if ($lastModifiedDate) {
32404 $data['last-modified'] = $lastModifiedDate;
32405 $json = json_encode($data);
32406 }
32407 }
32408 $this->cache->write($cacheKey, $json);
32409 }
32410
32411 break;
32412 } catch (\Exception $e) {
32413 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
32414 throw $e;
32415 }
32416
32417 if ($retries) {
32418 usleep(100000);
32419 continue;
32420 }
32421
32422 if ($e instanceof RepositorySecurityException) {
32423 throw $e;
32424 }
32425
32426 if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
32427 if (!$this->degradedMode) {
32428 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
32429 $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>');
32430 }
32431 $this->degradedMode = true;
32432 $data = JsonFile::parseJson($contents, $this->cache->getRoot().$cacheKey);
32433
32434 break;
32435 }
32436
32437 throw $e;
32438 }
32439 }
32440
32441 return $data;
32442 }
32443
32444 protected function fetchFileIfLastModified($filename, $cacheKey, $lastModifiedTime)
32445 {
32446 $retries = 3;
32447 while ($retries--) {
32448 try {
32449 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
32450 if ($this->eventDispatcher) {
32451 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
32452 }
32453
32454 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
32455 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
32456 $options = array('http' => array('header' => array('If-Modified-Since: '.$lastModifiedTime)));
32457 $json = $rfs->getContents($hostname, $filename, false, $options);
32458 if ($json === '' && $rfs->findStatusCode($rfs->getLastHeaders()) === 304) {
32459 return true;
32460 }
32461
32462 $data = JsonFile::parseJson($json, $filename);
32463 if (!empty($data['warning'])) {
32464 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
32465 }
32466 if (!empty($data['info'])) {
32467 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
32468 }
32469
32470 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
32471 if ($lastModifiedDate) {
32472 $data['last-modified'] = $lastModifiedDate;
32473 $json = json_encode($data);
32474 }
32475 $this->cache->write($cacheKey, $json);
32476
32477 return $data;
32478 } catch (\Exception $e) {
32479 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
32480 throw $e;
32481 }
32482
32483 if ($retries) {
32484 usleep(100000);
32485 continue;
32486 }
32487
32488 if (!$this->degradedMode) {
32489 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
32490 $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>');
32491 }
32492 $this->degradedMode = true;
32493
32494 return true;
32495 }
32496 }
32497 }
32498
32499
32500
32501
32502
32503
32504 private function initializePartialPackages()
32505 {
32506 $rootData = $this->loadRootServerFile();
32507
32508 $this->partialPackagesByName = array();
32509 foreach ($rootData['packages'] as $package => $versions) {
32510 $package = strtolower($package);
32511 foreach ($versions as $version) {
32512 $this->partialPackagesByName[$package][] = $version;
32513 if (!empty($version['provide']) && is_array($version['provide'])) {
32514 foreach ($version['provide'] as $provided => $providedVersion) {
32515 $this->partialPackagesByName[strtolower($provided)][] = $version;
32516 }
32517 }
32518 if (!empty($version['replace']) && is_array($version['replace'])) {
32519 foreach ($version['replace'] as $provided => $providedVersion) {
32520 $this->partialPackagesByName[strtolower($provided)][] = $version;
32521 }
32522 }
32523 }
32524 }
32525
32526
32527  $this->rootData = true;
32528 }
32529 }
32530 <?php
32531
32532
32533
32534
32535
32536
32537
32538
32539
32540
32541
32542 namespace Composer\Repository;
32543
32544 use Composer\Package\PackageInterface;
32545
32546
32547
32548
32549
32550
32551 class CompositeRepository extends BaseRepository
32552 {
32553
32554
32555
32556
32557 private $repositories;
32558
32559
32560
32561
32562
32563 public function __construct(array $repositories)
32564 {
32565 $this->repositories = array();
32566 foreach ($repositories as $repo) {
32567 $this->addRepository($repo);
32568 }
32569 }
32570
32571
32572
32573
32574
32575
32576 public function getRepositories()
32577 {
32578 return $this->repositories;
32579 }
32580
32581
32582
32583
32584 public function hasPackage(PackageInterface $package)
32585 {
32586 foreach ($this->repositories as $repository) {
32587
32588 if ($repository->hasPackage($package)) {
32589 return true;
32590 }
32591 }
32592
32593 return false;
32594 }
32595
32596
32597
32598
32599 public function findPackage($name, $constraint)
32600 {
32601 foreach ($this->repositories as $repository) {
32602
32603 $package = $repository->findPackage($name, $constraint);
32604 if (null !== $package) {
32605 return $package;
32606 }
32607 }
32608
32609 return null;
32610 }
32611
32612
32613
32614
32615 public function findPackages($name, $constraint = null)
32616 {
32617 $packages = array();
32618 foreach ($this->repositories as $repository) {
32619
32620 $packages[] = $repository->findPackages($name, $constraint);
32621 }
32622
32623 return $packages ? call_user_func_array('array_merge', $packages) : array();
32624 }
32625
32626
32627
32628
32629 public function search($query, $mode = 0, $type = null)
32630 {
32631 $matches = array();
32632 foreach ($this->repositories as $repository) {
32633
32634 $matches[] = $repository->search($query, $mode, $type);
32635 }
32636
32637 return $matches ? call_user_func_array('array_merge', $matches) : array();
32638 }
32639
32640
32641
32642
32643 public function getPackages()
32644 {
32645 $packages = array();
32646 foreach ($this->repositories as $repository) {
32647
32648 $packages[] = $repository->getPackages();
32649 }
32650
32651 return $packages ? call_user_func_array('array_merge', $packages) : array();
32652 }
32653
32654
32655
32656
32657 public function removePackage(PackageInterface $package)
32658 {
32659 foreach ($this->repositories as $repository) {
32660
32661 $repository->removePackage($package);
32662 }
32663 }
32664
32665
32666
32667
32668 public function count()
32669 {
32670 $total = 0;
32671 foreach ($this->repositories as $repository) {
32672
32673 $total += $repository->count();
32674 }
32675
32676 return $total;
32677 }
32678
32679
32680
32681
32682
32683 public function addRepository(RepositoryInterface $repository)
32684 {
32685 if ($repository instanceof self) {
32686 foreach ($repository->getRepositories() as $repo) {
32687 $this->addRepository($repo);
32688 }
32689 } else {
32690 $this->repositories[] = $repository;
32691 }
32692 }
32693 }
32694 <?php
32695
32696
32697
32698
32699
32700
32701
32702
32703
32704
32705
32706 namespace Composer\Repository;
32707
32708
32709
32710
32711
32712
32713 interface ConfigurableRepositoryInterface
32714 {
32715 public function getRepoConfig();
32716 }
32717 <?php
32718
32719
32720
32721
32722
32723
32724
32725
32726
32727
32728
32729 namespace Composer\Repository;
32730
32731 use Composer\Json\JsonFile;
32732 use Composer\Package\Loader\ArrayLoader;
32733 use Composer\Package\Dumper\ArrayDumper;
32734
32735
32736
32737
32738
32739
32740
32741 class FilesystemRepository extends WritableArrayRepository
32742 {
32743 private $file;
32744
32745
32746
32747
32748
32749
32750 public function __construct(JsonFile $repositoryFile)
32751 {
32752 parent::__construct();
32753 $this->file = $repositoryFile;
32754 }
32755
32756
32757
32758
32759 protected function initialize()
32760 {
32761 parent::initialize();
32762
32763 if (!$this->file->exists()) {
32764 return;
32765 }
32766
32767 try {
32768 $packages = $this->file->read();
32769
32770 if (!is_array($packages)) {
32771 throw new \UnexpectedValueException('Could not parse package list from the repository');
32772 }
32773 } catch (\Exception $e) {
32774 throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.get_class($e).'] '.$e->getMessage());
32775 }
32776
32777 $loader = new ArrayLoader(null, true);
32778 foreach ($packages as $packageData) {
32779 $package = $loader->load($packageData);
32780 $this->addPackage($package);
32781 }
32782 }
32783
32784 public function reload()
32785 {
32786 $this->packages = null;
32787 $this->initialize();
32788 }
32789
32790
32791
32792
32793 public function write()
32794 {
32795 $data = array();
32796 $dumper = new ArrayDumper();
32797
32798 foreach ($this->getCanonicalPackages() as $package) {
32799 $data[] = $dumper->dump($package);
32800 }
32801
32802 usort($data, function ($a, $b) {
32803 return strcmp($a['name'], $b['name']);
32804 });
32805
32806 $this->file->write($data);
32807 }
32808 }
32809 <?php
32810
32811
32812
32813
32814
32815
32816
32817
32818
32819
32820
32821 namespace Composer\Repository;
32822
32823
32824
32825
32826
32827
32828
32829
32830 class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
32831 {
32832 }
32833 <?php
32834
32835
32836
32837
32838
32839
32840
32841
32842
32843
32844
32845 namespace Composer\Repository;
32846
32847
32848
32849
32850
32851
32852 class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
32853 {
32854 }
32855 <?php
32856
32857
32858
32859
32860
32861
32862
32863
32864
32865
32866
32867 namespace Composer\Repository;
32868
32869
32870
32871
32872
32873
32874
32875
32876 interface InstalledRepositoryInterface extends WritableRepositoryInterface
32877 {
32878 }
32879 <?php
32880
32881
32882
32883
32884
32885
32886
32887
32888
32889
32890
32891 namespace Composer\Repository;
32892
32893
32894
32895
32896
32897
32898 class InvalidRepositoryException extends \Exception
32899 {
32900 }
32901 <?php
32902
32903
32904
32905
32906
32907
32908
32909
32910
32911
32912
32913 namespace Composer\Repository;
32914
32915 use Composer\Package\Loader\ArrayLoader;
32916 use Composer\Package\Loader\ValidatingArrayLoader;
32917
32918
32919
32920
32921
32922
32923 class PackageRepository extends ArrayRepository
32924 {
32925 private $config;
32926
32927
32928
32929
32930
32931
32932 public function __construct(array $config)
32933 {
32934 parent::__construct();
32935 $this->config = $config['package'];
32936
32937
32938  if (!is_numeric(key($this->config))) {
32939 $this->config = array($this->config);
32940 }
32941 }
32942
32943
32944
32945
32946 protected function initialize()
32947 {
32948 parent::initialize();
32949
32950 $loader = new ValidatingArrayLoader(new ArrayLoader(null, true), false);
32951 foreach ($this->config as $package) {
32952 try {
32953 $package = $loader->load($package);
32954 } catch (\Exception $e) {
32955 throw new InvalidRepositoryException('A repository of type "package" contains an invalid package definition: '.$e->getMessage()."\n\nInvalid package definition:\n".json_encode($package));
32956 }
32957
32958 $this->addPackage($package);
32959 }
32960 }
32961 }
32962 <?php
32963
32964
32965
32966
32967
32968
32969
32970
32971
32972
32973
32974 namespace Composer\Repository;
32975
32976 use Composer\Config;
32977 use Composer\IO\IOInterface;
32978 use Composer\Json\JsonFile;
32979 use Composer\Package\Loader\ArrayLoader;
32980 use Composer\Package\Version\VersionGuesser;
32981 use Composer\Package\Version\VersionParser;
32982 use Composer\Util\Platform;
32983 use Composer\Util\ProcessExecutor;
32984
32985
32986
32987
32988
32989
32990
32991
32992
32993
32994
32995
32996
32997
32998
32999
33000
33001
33002
33003
33004
33005
33006
33007
33008
33009
33010
33011
33012
33013
33014
33015
33016
33017
33018
33019
33020 class PathRepository extends ArrayRepository implements ConfigurableRepositoryInterface
33021 {
33022
33023
33024
33025 private $loader;
33026
33027
33028
33029
33030 private $versionGuesser;
33031
33032
33033
33034
33035 private $url;
33036
33037
33038
33039
33040 private $repoConfig;
33041
33042
33043
33044
33045 private $process;
33046
33047
33048
33049
33050 private $options;
33051
33052
33053
33054
33055
33056
33057
33058
33059 public function __construct(array $repoConfig, IOInterface $io, Config $config)
33060 {
33061 if (!isset($repoConfig['url'])) {
33062 throw new \RuntimeException('You must specify the `url` configuration for the path repository');
33063 }
33064
33065 $this->loader = new ArrayLoader(null, true);
33066 $this->url = Platform::expandPath($repoConfig['url']);
33067 $this->process = new ProcessExecutor($io);
33068 $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
33069 $this->repoConfig = $repoConfig;
33070 $this->options = isset($repoConfig['options']) ? $repoConfig['options'] : array();
33071
33072 parent::__construct();
33073 }
33074
33075 public function getRepoConfig()
33076 {
33077 return $this->repoConfig;
33078 }
33079
33080
33081
33082
33083
33084
33085 protected function initialize()
33086 {
33087 parent::initialize();
33088
33089 foreach ($this->getUrlMatches() as $url) {
33090 $path = realpath($url) . DIRECTORY_SEPARATOR;
33091 $composerFilePath = $path.'composer.json';
33092
33093 if (!file_exists($composerFilePath)) {
33094 continue;
33095 }
33096
33097 $json = file_get_contents($composerFilePath);
33098 $package = JsonFile::parseJson($json, $composerFilePath);
33099 $package['dist'] = array(
33100 'type' => 'path',
33101 'url' => $url,
33102 'reference' => sha1($json . serialize($this->options)),
33103 );
33104 $package['transport-options'] = $this->options;
33105
33106
33107  if (!isset($package['version']) && ($rootVersion = getenv('COMPOSER_ROOT_VERSION'))) {
33108 if (
33109 0 === $this->process->execute('git rev-parse HEAD', $ref1, $path)
33110 && 0 === $this->process->execute('git rev-parse HEAD', $ref2)
33111 && $ref1 === $ref2
33112 ) {
33113 $package['version'] = $rootVersion;
33114 }
33115 }
33116
33117 if (!isset($package['version'])) {
33118 $versionData = $this->versionGuesser->guessVersion($package, $path);
33119 $package['version'] = $versionData['version'] ?: 'dev-master';
33120 }
33121
33122 $output = '';
33123 if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
33124 $package['dist']['reference'] = trim($output);
33125 }
33126 $package = $this->loader->load($package);
33127 $this->addPackage($package);
33128 }
33129 }
33130
33131
33132
33133
33134
33135
33136 private function getUrlMatches()
33137 {
33138
33139  return array_map(function ($val) {
33140 return rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $val), '/');
33141 }, glob($this->url, GLOB_MARK | GLOB_ONLYDIR));
33142 }
33143 }
33144 <?php
33145
33146
33147
33148
33149
33150
33151
33152
33153
33154
33155
33156 namespace Composer\Repository\Pear;
33157
33158 use Composer\Util\RemoteFilesystem;
33159
33160
33161
33162
33163
33164
33165
33166
33167 abstract class BaseChannelReader
33168 {
33169
33170
33171
33172 const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
33173 const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
33174 const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
33175 const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
33176 const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
33177 const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
33178
33179
33180 private $rfs;
33181
33182 protected function __construct(RemoteFilesystem $rfs)
33183 {
33184 $this->rfs = $rfs;
33185 }
33186
33187
33188
33189
33190
33191
33192
33193
33194
33195 protected function requestContent($origin, $path)
33196 {
33197 $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
33198 $content = $this->rfs->getContents($origin, $url, false);
33199 if (!$content) {
33200 throw new \UnexpectedValueException('The PEAR channel at ' . $url . ' did not respond.');
33201 }
33202
33203 return str_replace('http://pear.php.net/rest/', 'https://pear.php.net/rest/', $content);
33204 }
33205
33206
33207
33208
33209
33210
33211
33212
33213
33214 protected function requestXml($origin, $path)
33215 {
33216
33217  $xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
33218
33219 if (false === $xml) {
33220 throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
33221 }
33222
33223 return $xml;
33224 }
33225 }
33226 <?php
33227
33228
33229
33230
33231
33232
33233
33234
33235
33236
33237
33238 namespace Composer\Repository\Pear;
33239
33240
33241
33242
33243
33244
33245 class ChannelInfo
33246 {
33247 private $name;
33248 private $alias;
33249 private $packages;
33250
33251
33252
33253
33254
33255
33256 public function __construct($name, $alias, array $packages)
33257 {
33258 $this->name = $name;
33259 $this->alias = $alias;
33260 $this->packages = $packages;
33261 }
33262
33263
33264
33265
33266
33267
33268 public function getName()
33269 {
33270 return $this->name;
33271 }
33272
33273
33274
33275
33276
33277
33278 public function getAlias()
33279 {
33280 return $this->alias;
33281 }
33282
33283
33284
33285
33286
33287
33288 public function getPackages()
33289 {
33290 return $this->packages;
33291 }
33292 }
33293 <?php
33294
33295
33296
33297
33298
33299
33300
33301
33302
33303
33304
33305 namespace Composer\Repository\Pear;
33306
33307 use Composer\Util\RemoteFilesystem;
33308
33309
33310
33311
33312
33313
33314
33315
33316 class ChannelReader extends BaseChannelReader
33317 {
33318
33319 private $readerMap;
33320
33321 public function __construct(RemoteFilesystem $rfs)
33322 {
33323 parent::__construct($rfs);
33324
33325 $rest10reader = new ChannelRest10Reader($rfs);
33326 $rest11reader = new ChannelRest11Reader($rfs);
33327
33328 $this->readerMap = array(
33329 'REST1.3' => $rest11reader,
33330 'REST1.2' => $rest11reader,
33331 'REST1.1' => $rest11reader,
33332 'REST1.0' => $rest10reader,
33333 );
33334 }
33335
33336
33337
33338
33339
33340
33341
33342
33343 public function read($url)
33344 {
33345 $xml = $this->requestXml($url, "/channel.xml");
33346
33347 $channelName = (string) $xml->name;
33348 $channelAlias = (string) $xml->suggestedalias;
33349
33350 $supportedVersions = array_keys($this->readerMap);
33351 $selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
33352 if (!$selectedRestVersion) {
33353 throw new \UnexpectedValueException(sprintf('PEAR repository %s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
33354 }
33355
33356 $reader = $this->readerMap[$selectedRestVersion['version']];
33357 $packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
33358
33359 return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
33360 }
33361
33362
33363
33364
33365
33366
33367
33368
33369 private function selectRestVersion($channelXml, $supportedVersions)
33370 {
33371 $channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
33372
33373 foreach ($supportedVersions as $version) {
33374 $xpathTest = "ns:servers/ns:*/ns:rest/ns:baseurl[@type='{$version}']";
33375 $testResult = $channelXml->xpath($xpathTest);
33376
33377 foreach ($testResult as $result) {
33378
33379  $result = (string) $result;
33380 if (preg_match('{^https://}i', $result)) {
33381 return array('version' => $version, 'baseUrl' => $result);
33382 }
33383 }
33384
33385
33386  if (count($testResult) > 0) {
33387 return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
33388 }
33389 }
33390
33391 return null;
33392 }
33393 }
33394 <?php
33395
33396
33397
33398
33399
33400
33401
33402
33403
33404
33405
33406 namespace Composer\Repository\Pear;
33407
33408 use Composer\Downloader\TransportException;
33409
33410
33411
33412
33413
33414
33415
33416
33417
33418
33419
33420
33421 class ChannelRest10Reader extends BaseChannelReader
33422 {
33423 private $dependencyReader;
33424
33425 public function __construct($rfs)
33426 {
33427 parent::__construct($rfs);
33428
33429 $this->dependencyReader = new PackageDependencyParser();
33430 }
33431
33432
33433
33434
33435
33436
33437
33438
33439 public function read($baseUrl)
33440 {
33441 return $this->readPackages($baseUrl);
33442 }
33443
33444
33445
33446
33447
33448
33449
33450
33451 private function readPackages($baseUrl)
33452 {
33453 $result = array();
33454
33455 $xmlPath = '/p/packages.xml';
33456 $xml = $this->requestXml($baseUrl, $xmlPath);
33457 $xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
33458 foreach ($xml->xpath('ns:p') as $node) {
33459 $packageName = (string) $node;
33460 $packageInfo = $this->readPackage($baseUrl, $packageName);
33461 $result[] = $packageInfo;
33462 }
33463
33464 return $result;
33465 }
33466
33467
33468
33469
33470
33471
33472
33473
33474
33475 private function readPackage($baseUrl, $packageName)
33476 {
33477 $xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
33478 $xml = $this->requestXml($baseUrl, $xmlPath);
33479 $xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
33480
33481 $channelName = (string) $xml->c;
33482 $packageName = (string) $xml->n;
33483 $license = (string) $xml->l;
33484 $shortDescription = (string) $xml->s;
33485 $description = (string) $xml->d;
33486
33487 return new PackageInfo(
33488 $channelName,
33489 $packageName,
33490 $license,
33491 $shortDescription,
33492 $description,
33493 $this->readPackageReleases($baseUrl, $packageName)
33494 );
33495 }
33496
33497
33498
33499
33500
33501
33502
33503
33504
33505
33506 private function readPackageReleases($baseUrl, $packageName)
33507 {
33508 $result = array();
33509
33510 try {
33511 $xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
33512 $xml = $this->requestXml($baseUrl, $xmlPath);
33513 $xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
33514 foreach ($xml->xpath('ns:r') as $node) {
33515 $releaseVersion = (string) $node->v;
33516 $releaseStability = (string) $node->s;
33517
33518 try {
33519 $result[$releaseVersion] = new ReleaseInfo(
33520 $releaseStability,
33521 $this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
33522 );
33523 } catch (TransportException $exception) {
33524 if ($exception->getCode() != 404) {
33525 throw $exception;
33526 }
33527 }
33528 }
33529 } catch (TransportException $exception) {
33530 if ($exception->getCode() != 404) {
33531 throw $exception;
33532 }
33533 }
33534
33535 return $result;
33536 }
33537
33538
33539
33540
33541
33542
33543
33544
33545
33546
33547 private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
33548 {
33549 $dependencyReader = new PackageDependencyParser();
33550
33551 $depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
33552 $content = $this->requestContent($baseUrl, $depthPath);
33553 $dependencyArray = unserialize($content);
33554
33555 return $dependencyReader->buildDependencyInfo($dependencyArray);
33556 }
33557 }
33558 <?php
33559
33560
33561
33562
33563
33564
33565
33566
33567
33568
33569
33570 namespace Composer\Repository\Pear;
33571
33572
33573
33574
33575
33576
33577
33578
33579
33580
33581 class ChannelRest11Reader extends BaseChannelReader
33582 {
33583 private $dependencyReader;
33584
33585 public function __construct($rfs)
33586 {
33587 parent::__construct($rfs);
33588
33589 $this->dependencyReader = new PackageDependencyParser();
33590 }
33591
33592
33593
33594
33595
33596
33597
33598
33599 public function read($baseUrl)
33600 {
33601 return $this->readChannelPackages($baseUrl);
33602 }
33603
33604
33605
33606
33607
33608
33609
33610
33611 private function readChannelPackages($baseUrl)
33612 {
33613 $result = array();
33614
33615 $xml = $this->requestXml($baseUrl, "/c/categories.xml");
33616 $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
33617 foreach ($xml->xpath('ns:c') as $node) {
33618 $categoryName = (string) $node;
33619 $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
33620 $result = array_merge($result, $categoryPackages);
33621 }
33622
33623 return $result;
33624 }
33625
33626
33627
33628
33629
33630
33631
33632
33633
33634 private function readCategoryPackages($baseUrl, $categoryName)
33635 {
33636 $result = array();
33637
33638 $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
33639 $xml = $this->requestXml($baseUrl, $categoryPath);
33640 $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
33641 foreach ($xml->xpath('ns:pi') as $node) {
33642 $packageInfo = $this->parsePackage($node);
33643 $result[] = $packageInfo;
33644 }
33645
33646 return $result;
33647 }
33648
33649
33650
33651
33652
33653
33654
33655 private function parsePackage($packageInfo)
33656 {
33657 $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
33658 $channelName = (string) $packageInfo->p->c;
33659 $packageName = (string) $packageInfo->p->n;
33660 $license = (string) $packageInfo->p->l;
33661 $shortDescription = (string) $packageInfo->p->s;
33662 $description = (string) $packageInfo->p->d;
33663
33664 $dependencies = array();
33665 foreach ($packageInfo->xpath('ns:deps') as $node) {
33666 $dependencyVersion = (string) $node->v;
33667 $dependencyArray = unserialize((string) $node->d);
33668
33669 $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
33670
33671 $dependencies[$dependencyVersion] = $dependencyInfo;
33672 }
33673
33674 $releases = array();
33675 $releasesInfo = $packageInfo->xpath('ns:a/ns:r');
33676 if ($releasesInfo) {
33677 foreach ($releasesInfo as $node) {
33678 $releaseVersion = (string) $node->v;
33679 $releaseStability = (string) $node->s;
33680 $releases[$releaseVersion] = new ReleaseInfo(
33681 $releaseStability,
33682 isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
33683 );
33684 }
33685 }
33686
33687 return new PackageInfo(
33688 $channelName,
33689 $packageName,
33690 $license,
33691 $shortDescription,
33692 $description,
33693 $releases
33694 );
33695 }
33696 }
33697 <?php
33698
33699
33700
33701
33702
33703
33704
33705
33706
33707
33708
33709 namespace Composer\Repository\Pear;
33710
33711
33712
33713
33714
33715
33716 class DependencyConstraint
33717 {
33718 private $type;
33719 private $constraint;
33720 private $channelName;
33721 private $packageName;
33722
33723
33724
33725
33726
33727
33728
33729 public function __construct($type, $constraint, $channelName, $packageName)
33730 {
33731 $this->type = $type;
33732 $this->constraint = $constraint;
33733 $this->channelName = $channelName;
33734 $this->packageName = $packageName;
33735 }
33736
33737 public function getChannelName()
33738 {
33739 return $this->channelName;
33740 }
33741
33742 public function getConstraint()
33743 {
33744 return $this->constraint;
33745 }
33746
33747 public function getPackageName()
33748 {
33749 return $this->packageName;
33750 }
33751
33752 public function getType()
33753 {
33754 return $this->type;
33755 }
33756 }
33757 <?php
33758
33759
33760
33761
33762
33763
33764
33765
33766
33767
33768
33769 namespace Composer\Repository\Pear;
33770
33771
33772
33773
33774
33775
33776 class DependencyInfo
33777 {
33778 private $requires;
33779 private $optionals;
33780
33781
33782
33783
33784
33785 public function __construct($requires, $optionals)
33786 {
33787 $this->requires = $requires;
33788 $this->optionals = $optionals;
33789 }
33790
33791
33792
33793
33794 public function getRequires()
33795 {
33796 return $this->requires;
33797 }
33798
33799
33800
33801
33802 public function getOptionals()
33803 {
33804 return $this->optionals;
33805 }
33806 }
33807 <?php
33808
33809
33810
33811
33812
33813
33814
33815
33816
33817
33818
33819 namespace Composer\Repository\Pear;
33820
33821
33822
33823
33824
33825
33826 class PackageDependencyParser
33827 {
33828
33829
33830
33831
33832
33833
33834 public function buildDependencyInfo($depArray)
33835 {
33836 if (!is_array($depArray)) {
33837 return new DependencyInfo(array(), array());
33838 }
33839 if (!$this->isHash($depArray)) {
33840 return new DependencyInfo($this->buildDependency10Info($depArray), array());
33841 }
33842
33843 return $this->buildDependency20Info($depArray);
33844 }
33845
33846
33847
33848
33849
33850
33851
33852
33853
33854
33855
33856
33857
33858 private function buildDependency10Info($depArray)
33859 {
33860 static $dep10toOperatorMap = array('has' => '==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
33861
33862 $result = array();
33863
33864 foreach ($depArray as $depItem) {
33865 if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
33866
33867  continue;
33868 }
33869
33870 $depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
33871 ? 'optional'
33872 : 'required';
33873 $depType = 'not' == $depItem['rel']
33874 ? 'conflicts'
33875 : $depType;
33876
33877 $depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
33878
33879
33880  $depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
33881 ? '*'
33882 : $dep10toOperatorMap[$depItem['rel']] . $depVersion;
33883
33884 switch ($depItem['type']) {
33885 case 'php':
33886 $depChannelName = 'php';
33887 $depPackageName = '';
33888 break;
33889 case 'pkg':
33890 $depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
33891 $depPackageName = $depItem['name'];
33892 break;
33893 case 'ext':
33894 $depChannelName = 'ext';
33895 $depPackageName = $depItem['name'];
33896 break;
33897 case 'os':
33898 case 'sapi':
33899 $depChannelName = '';
33900 $depPackageName = '';
33901 break;
33902 default:
33903 $depChannelName = '';
33904 $depPackageName = '';
33905 break;
33906 }
33907
33908 if ('' != $depChannelName) {
33909 $result[] = new DependencyConstraint(
33910 $depType,
33911 $depVersionConstraint,
33912 $depChannelName,
33913 $depPackageName
33914 );
33915 }
33916 }
33917
33918 return $result;
33919 }
33920
33921
33922
33923
33924
33925
33926
33927 private function buildDependency20Info($depArray)
33928 {
33929 $result = array();
33930 $optionals = array();
33931 $defaultOptionals = array();
33932 foreach ($depArray as $depType => $depTypeGroup) {
33933 if (!is_array($depTypeGroup)) {
33934 continue;
33935 }
33936 if ('required' == $depType || 'optional' == $depType) {
33937 foreach ($depTypeGroup as $depItemType => $depItem) {
33938 switch ($depItemType) {
33939 case 'php':
33940 $result[] = new DependencyConstraint(
33941 $depType,
33942 $this->parse20VersionConstraint($depItem),
33943 'php',
33944 ''
33945 );
33946 break;
33947 case 'package':
33948 $deps = $this->buildDepPackageConstraints($depItem, $depType);
33949 $result = array_merge($result, $deps);
33950 break;
33951 case 'extension':
33952 $deps = $this->buildDepExtensionConstraints($depItem, $depType);
33953 $result = array_merge($result, $deps);
33954 break;
33955 case 'subpackage':
33956 $deps = $this->buildDepPackageConstraints($depItem, 'replaces');
33957 $defaultOptionals += $deps;
33958 break;
33959 case 'os':
33960 case 'pearinstaller':
33961 break;
33962 default:
33963 break;
33964 }
33965 }
33966 } elseif ('group' == $depType) {
33967 if ($this->isHash($depTypeGroup)) {
33968 $depTypeGroup = array($depTypeGroup);
33969 }
33970
33971 foreach ($depTypeGroup as $depItem) {
33972 $groupName = $depItem['attribs']['name'];
33973 if (!isset($optionals[$groupName])) {
33974 $optionals[$groupName] = array();
33975 }
33976
33977 if (isset($depItem['subpackage'])) {
33978 $optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
33979 } else {
33980 $result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
33981 }
33982 }
33983 }
33984 }
33985
33986 if (count($defaultOptionals) > 0) {
33987 $optionals['*'] = $defaultOptionals;
33988 }
33989
33990 return new DependencyInfo($result, $optionals);
33991 }
33992
33993
33994
33995
33996
33997
33998
33999
34000 private function buildDepExtensionConstraints($depItem, $depType)
34001 {
34002 if ($this->isHash($depItem)) {
34003 $depItem = array($depItem);
34004 }
34005
34006 $result = array();
34007 foreach ($depItem as $subDepItem) {
34008 $depChannelName = 'ext';
34009 $depPackageName = $subDepItem['name'];
34010 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
34011
34012 $result[] = new DependencyConstraint(
34013 $depType,
34014 $depVersionConstraint,
34015 $depChannelName,
34016 $depPackageName
34017 );
34018 }
34019
34020 return $result;
34021 }
34022
34023
34024
34025
34026
34027
34028
34029
34030 private function buildDepPackageConstraints($depItem, $depType)
34031 {
34032 if ($this->isHash($depItem)) {
34033 $depItem = array($depItem);
34034 }
34035
34036 $result = array();
34037 foreach ($depItem as $subDepItem) {
34038 if (!array_key_exists('channel', $subDepItem)) {
34039 $subDepItem['channel'] = $subDepItem['uri'];
34040 }
34041 $depChannelName = $subDepItem['channel'];
34042 $depPackageName = $subDepItem['name'];
34043 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
34044 if (isset($subDepItem['conflicts'])) {
34045 $depType = 'conflicts';
34046 }
34047
34048 $result[] = new DependencyConstraint(
34049 $depType,
34050 $depVersionConstraint,
34051 $depChannelName,
34052 $depPackageName
34053 );
34054 }
34055
34056 return $result;
34057 }
34058
34059
34060
34061
34062
34063
34064
34065 private function parse20VersionConstraint(array $data)
34066 {
34067 static $dep20toOperatorMap = array('has' => '==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
34068
34069 $versions = array();
34070 $values = array_intersect_key($data, $dep20toOperatorMap);
34071 if (0 == count($values)) {
34072 return '*';
34073 }
34074 if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
34075 $versions[] = '>' . $this->parseVersion($values['min']);
34076 } elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
34077 $versions[] = '<' . $this->parseVersion($values['max']);
34078 } else {
34079 foreach ($values as $op => $version) {
34080 if ('exclude' == $op && is_array($version)) {
34081 foreach ($version as $versionPart) {
34082 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
34083 }
34084 } else {
34085 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
34086 }
34087 }
34088 }
34089
34090 return implode(',', $versions);
34091 }
34092
34093
34094
34095
34096
34097
34098
34099 private function parseVersion($version)
34100 {
34101 if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
34102 $version = $matches[1]
34103 .(!empty($matches[2]) ? $matches[2] : '.0')
34104 .(!empty($matches[3]) ? $matches[3] : '.0')
34105 .(!empty($matches[4]) ? $matches[4] : '.0');
34106
34107 return $version;
34108 }
34109
34110 return null;
34111 }
34112
34113
34114
34115
34116
34117
34118
34119 private function isHash(array $array)
34120 {
34121 return !array_key_exists(1, $array) && !array_key_exists(0, $array);
34122 }
34123 }
34124 <?php
34125
34126
34127
34128
34129
34130
34131
34132
34133
34134
34135
34136 namespace Composer\Repository\Pear;
34137
34138
34139
34140
34141
34142
34143 class PackageInfo
34144 {
34145 private $channelName;
34146 private $packageName;
34147 private $license;
34148 private $shortDescription;
34149 private $description;
34150 private $releases;
34151
34152
34153
34154
34155
34156
34157
34158
34159
34160 public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
34161 {
34162 $this->channelName = $channelName;
34163 $this->packageName = $packageName;
34164 $this->license = $license;
34165 $this->shortDescription = $shortDescription;
34166 $this->description = $description;
34167 $this->releases = $releases;
34168 }
34169
34170
34171
34172
34173 public function getChannelName()
34174 {
34175 return $this->channelName;
34176 }
34177
34178
34179
34180
34181 public function getPackageName()
34182 {
34183 return $this->packageName;
34184 }
34185
34186
34187
34188
34189 public function getDescription()
34190 {
34191 return $this->description;
34192 }
34193
34194
34195
34196
34197 public function getShortDescription()
34198 {
34199 return $this->shortDescription;
34200 }
34201
34202
34203
34204
34205 public function getLicense()
34206 {
34207 return $this->license;
34208 }
34209
34210
34211
34212
34213 public function getReleases()
34214 {
34215 return $this->releases;
34216 }
34217 }
34218 <?php
34219
34220
34221
34222
34223
34224
34225
34226
34227
34228
34229
34230 namespace Composer\Repository\Pear;
34231
34232
34233
34234
34235
34236
34237 class ReleaseInfo
34238 {
34239 private $stability;
34240 private $dependencyInfo;
34241
34242
34243
34244
34245
34246 public function __construct($stability, $dependencyInfo)
34247 {
34248 $this->stability = $stability;
34249 $this->dependencyInfo = $dependencyInfo;
34250 }
34251
34252
34253
34254
34255 public function getDependencyInfo()
34256 {
34257 return $this->dependencyInfo;
34258 }
34259
34260
34261
34262
34263 public function getStability()
34264 {
34265 return $this->stability;
34266 }
34267 }
34268 <?php
34269
34270
34271
34272
34273
34274
34275
34276
34277
34278
34279
34280 namespace Composer\Repository;
34281
34282 use Composer\IO\IOInterface;
34283 use Composer\Semver\VersionParser as SemverVersionParser;
34284 use Composer\Package\Version\VersionParser;
34285 use Composer\Repository\Pear\ChannelReader;
34286 use Composer\Package\CompletePackage;
34287 use Composer\Repository\Pear\ChannelInfo;
34288 use Composer\EventDispatcher\EventDispatcher;
34289 use Composer\Package\Link;
34290 use Composer\Semver\Constraint\Constraint;
34291 use Composer\Util\RemoteFilesystem;
34292 use Composer\Config;
34293 use Composer\Factory;
34294
34295
34296
34297
34298
34299
34300
34301
34302
34303
34304 class PearRepository extends ArrayRepository implements ConfigurableRepositoryInterface
34305 {
34306 private $url;
34307 private $io;
34308 private $rfs;
34309 private $versionParser;
34310 private $repoConfig;
34311
34312
34313
34314
34315 private $vendorAlias;
34316
34317 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null)
34318 {
34319 parent::__construct();
34320 if (!preg_match('{^https?://}', $repoConfig['url'])) {
34321 $repoConfig['url'] = 'http://'.$repoConfig['url'];
34322 }
34323
34324 $urlBits = parse_url($repoConfig['url']);
34325 if (empty($urlBits['scheme']) || empty($urlBits['host'])) {
34326 throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']);
34327 }
34328
34329 $this->url = rtrim($repoConfig['url'], '/');
34330 $this->io = $io;
34331 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
34332 $this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
34333 $this->versionParser = new VersionParser();
34334 $this->repoConfig = $repoConfig;
34335 }
34336
34337 public function getRepoConfig()
34338 {
34339 return $this->repoConfig;
34340 }
34341
34342 protected function initialize()
34343 {
34344 parent::initialize();
34345
34346 $this->io->writeError('Initializing PEAR repository '.$this->url);
34347
34348 $reader = new ChannelReader($this->rfs);
34349 try {
34350 $channelInfo = $reader->read($this->url);
34351 } catch (\Exception $e) {
34352 $this->io->writeError('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
34353
34354 return;
34355 }
34356 $packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
34357 foreach ($packages as $package) {
34358 $this->addPackage($package);
34359 }
34360 }
34361
34362
34363
34364
34365
34366
34367
34368
34369 private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
34370 {
34371 $result = array();
34372 foreach ($channelInfo->getPackages() as $packageDefinition) {
34373 foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
34374 try {
34375 $normalizedVersion = $versionParser->normalize($version);
34376 } catch (\UnexpectedValueException $e) {
34377 $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage(), true, IOInterface::VERBOSE);
34378 continue;
34379 }
34380
34381 $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
34382
34383
34384  
34385  $urlBits = parse_url($this->url);
34386 $scheme = (isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl')) ? 'https' : 'http';
34387 $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
34388
34389 $requires = array();
34390 $suggests = array();
34391 $conflicts = array();
34392 $replaces = array();
34393
34394
34395  
34396  if ($channelInfo->getName() == $packageDefinition->getChannelName()) {
34397 $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
34398 $aliasConstraint = new Constraint('==', $normalizedVersion);
34399 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
34400 }
34401
34402
34403  if (!empty($this->vendorAlias)
34404 && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())
34405 ) {
34406 $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
34407 $aliasConstraint = new Constraint('==', $normalizedVersion);
34408 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
34409 }
34410
34411 foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) {
34412 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
34413 $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
34414 $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
34415 switch ($dependencyConstraint->getType()) {
34416 case 'required':
34417 $requires[] = $link;
34418 break;
34419 case 'conflicts':
34420 $conflicts[] = $link;
34421 break;
34422 case 'replaces':
34423 $replaces[] = $link;
34424 break;
34425 }
34426 }
34427
34428 foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
34429 foreach ($dependencyConstraints as $dependencyConstraint) {
34430 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
34431 $suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
34432 }
34433 }
34434
34435 $package = new CompletePackage($composerPackageName, $normalizedVersion, $version);
34436 $package->setType('pear-library');
34437 $package->setDescription($packageDefinition->getDescription());
34438 $package->setLicense(array($packageDefinition->getLicense()));
34439 $package->setDistType('file');
34440 $package->setDistUrl($distUrl);
34441 $package->setAutoload(array('classmap' => array('')));
34442 $package->setIncludePaths(array('/'));
34443 $package->setRequires($requires);
34444 $package->setConflicts($conflicts);
34445 $package->setSuggests($suggests);
34446 $package->setReplaces($replaces);
34447 $result[] = $package;
34448 }
34449 }
34450
34451 return $result;
34452 }
34453
34454 private function buildComposerPackageName($channelName, $packageName)
34455 {
34456 if ('php' === $channelName) {
34457 return "php";
34458 }
34459 if ('ext' === $channelName) {
34460 return "ext-{$packageName}";
34461 }
34462
34463 return "pear-{$channelName}/{$packageName}";
34464 }
34465 }
34466 <?php
34467
34468
34469
34470
34471
34472
34473
34474
34475
34476
34477
34478 namespace Composer\Repository;
34479
34480 use Composer\XdebugHandler;
34481 use Composer\Package\CompletePackage;
34482 use Composer\Package\PackageInterface;
34483 use Composer\Package\Version\VersionParser;
34484 use Composer\Plugin\PluginInterface;
34485 use Composer\Util\Silencer;
34486
34487
34488
34489
34490 class PlatformRepository extends ArrayRepository
34491 {
34492 const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[^/]+)$}i';
34493
34494 private $versionParser;
34495
34496
34497
34498
34499
34500
34501
34502
34503 private $overrides = array();
34504
34505 public function __construct(array $packages = array(), array $overrides = array())
34506 {
34507 foreach ($overrides as $name => $version) {
34508 $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
34509 }
34510 parent::__construct($packages);
34511 }
34512
34513 protected function initialize()
34514 {
34515 parent::initialize();
34516
34517 $this->versionParser = new VersionParser();
34518
34519
34520  
34521  foreach ($this->overrides as $override) {
34522
34523  if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
34524 throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
34525 }
34526
34527 $this->addOverriddenPackage($override);
34528 }
34529
34530 $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
34531 $version = $this->versionParser->normalize($prettyVersion);
34532 $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
34533 $composerPluginApi->setDescription('The Composer Plugin API');
34534 $this->addPackage($composerPluginApi);
34535
34536 try {
34537 $prettyVersion = PHP_VERSION;
34538 $version = $this->versionParser->normalize($prettyVersion);
34539 } catch (\UnexpectedValueException $e) {
34540 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
34541 $version = $this->versionParser->normalize($prettyVersion);
34542 }
34543
34544 $php = new CompletePackage('php', $version, $prettyVersion);
34545 $php->setDescription('The PHP interpreter');
34546 $this->addPackage($php);
34547
34548 if (PHP_DEBUG) {
34549 $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion);
34550 $phpdebug->setDescription('The PHP interpreter, with debugging symbols');
34551 $this->addPackage($phpdebug);
34552 }
34553
34554 if (defined('PHP_ZTS') && PHP_ZTS) {
34555 $phpzts = new CompletePackage('php-zts', $version, $prettyVersion);
34556 $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety');
34557 $this->addPackage($phpzts);
34558 }
34559
34560 if (PHP_INT_SIZE === 8) {
34561 $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
34562 $php64->setDescription('The PHP interpreter, 64bit');
34563 $this->addPackage($php64);
34564 }
34565
34566
34567  
34568  if (defined('AF_INET6') || Silencer::call('inet_pton', '::') !== false) {
34569 $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion);
34570 $phpIpv6->setDescription('The PHP interpreter, with IPv6 support');
34571 $this->addPackage($phpIpv6);
34572 }
34573
34574 $loadedExtensions = get_loaded_extensions();
34575
34576
34577  foreach ($loadedExtensions as $name) {
34578 if (in_array($name, array('standard', 'Core'))) {
34579 continue;
34580 }
34581
34582 $reflExt = new \ReflectionExtension($name);
34583 $prettyVersion = $reflExt->getVersion();
34584 $this->addExtension($name, $prettyVersion);
34585 }
34586
34587
34588  if (!in_array('xdebug', $loadedExtensions, true) && ($prettyVersion = strval(getenv(XdebugHandler::ENV_VERSION)))) {
34589 $this->addExtension('xdebug', $prettyVersion);
34590 }
34591
34592
34593  
34594  
34595  foreach ($loadedExtensions as $name) {
34596 $prettyVersion = null;
34597 $description = 'The '.$name.' PHP library';
34598 switch ($name) {
34599 case 'curl':
34600 $curlVersion = curl_version();
34601 $prettyVersion = $curlVersion['version'];
34602 break;
34603
34604 case 'iconv':
34605 $prettyVersion = ICONV_VERSION;
34606 break;
34607
34608 case 'intl':
34609 $name = 'ICU';
34610 if (defined('INTL_ICU_VERSION')) {
34611 $prettyVersion = INTL_ICU_VERSION;
34612 } else {
34613 $reflector = new \ReflectionExtension('intl');
34614
34615 ob_start();
34616 $reflector->info();
34617 $output = ob_get_clean();
34618
34619 preg_match('/^ICU version => (.*)$/m', $output, $matches);
34620 $prettyVersion = $matches[1];
34621 }
34622
34623 break;
34624
34625 case 'libxml':
34626 $prettyVersion = LIBXML_DOTTED_VERSION;
34627 break;
34628
34629 case 'openssl':
34630 $prettyVersion = preg_replace_callback('{^(?:OpenSSL|LibreSSL)?\s*([0-9.]+)([a-z]*).*}i', function ($match) {
34631 if (empty($match[2])) {
34632 return $match[1];
34633 }
34634
34635
34636  
34637
34638 if (!preg_match('{^z*[a-z]$}', $match[2])) {
34639
34640  return 0;
34641 }
34642
34643 $len = strlen($match[2]);
34644 $patchVersion = ($len - 1) * 26; 
34645  $patchVersion += ord($match[2][$len - 1]) - 96;
34646
34647 return $match[1].'.'.$patchVersion;
34648 }, OPENSSL_VERSION_TEXT);
34649
34650 $description = OPENSSL_VERSION_TEXT;
34651 break;
34652
34653 case 'pcre':
34654 $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION);
34655 break;
34656
34657 case 'uuid':
34658 $prettyVersion = phpversion('uuid');
34659 break;
34660
34661 case 'xsl':
34662 $prettyVersion = LIBXSLT_DOTTED_VERSION;
34663 break;
34664
34665 default:
34666
34667  continue 2;
34668 }
34669
34670 try {
34671 $version = $this->versionParser->normalize($prettyVersion);
34672 } catch (\UnexpectedValueException $e) {
34673 continue;
34674 }
34675
34676 $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
34677 $lib->setDescription($description);
34678 $this->addPackage($lib);
34679 }
34680
34681 if (defined('HHVM_VERSION')) {
34682 try {
34683 $prettyVersion = HHVM_VERSION;
34684 $version = $this->versionParser->normalize($prettyVersion);
34685 } catch (\UnexpectedValueException $e) {
34686 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION);
34687 $version = $this->versionParser->normalize($prettyVersion);
34688 }
34689
34690 $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
34691 $hhvm->setDescription('The HHVM Runtime (64bit)');
34692 $this->addPackage($hhvm);
34693 }
34694 }
34695
34696
34697
34698
34699 public function addPackage(PackageInterface $package)
34700 {
34701
34702  if (isset($this->overrides[$package->getName()])) {
34703 $overrider = $this->findPackage($package->getName(), '*');
34704 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
34705
34706 return;
34707 }
34708
34709
34710  if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
34711 $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
34712 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
34713
34714 return;
34715 }
34716
34717 parent::addPackage($package);
34718 }
34719
34720 private function addOverriddenPackage(array $override, $name = null)
34721 {
34722 $version = $this->versionParser->normalize($override['version']);
34723 $package = new CompletePackage($name ?: $override['name'], $version, $override['version']);
34724 $package->setDescription('Package overridden via config.platform');
34725 $package->setExtra(array('config.platform' => true));
34726 parent::addPackage($package);
34727
34728 return $package;
34729 }
34730
34731
34732
34733
34734
34735
34736
34737 private function addExtension($name, $prettyVersion)
34738 {
34739 $extraDescription = null;
34740
34741 try {
34742 $version = $this->versionParser->normalize($prettyVersion);
34743 } catch (\UnexpectedValueException $e) {
34744 $extraDescription = ' (actual version: '.$prettyVersion.')';
34745 if (preg_match('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) {
34746 $prettyVersion = $match[1];
34747 } else {
34748 $prettyVersion = '0';
34749 }
34750 $version = $this->versionParser->normalize($prettyVersion);
34751 }
34752
34753 $packageName = $this->buildPackageName($name);
34754 $ext = new CompletePackage($packageName, $version, $prettyVersion);
34755 $ext->setDescription('The '.$name.' PHP extension'.$extraDescription);
34756 $this->addPackage($ext);
34757 }
34758
34759 private function buildPackageName($name)
34760 {
34761 return 'ext-' . str_replace(' ', '-', $name);
34762 }
34763 }
34764 <?php
34765
34766
34767
34768
34769
34770
34771
34772
34773
34774
34775
34776 namespace Composer\Repository;
34777
34778 use Composer\Factory;
34779 use Composer\IO\IOInterface;
34780 use Composer\Config;
34781 use Composer\EventDispatcher\EventDispatcher;
34782 use Composer\Util\RemoteFilesystem;
34783 use Composer\Json\JsonFile;
34784
34785
34786
34787
34788 class RepositoryFactory
34789 {
34790
34791
34792
34793
34794
34795
34796
34797 public static function configFromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
34798 {
34799 if (0 === strpos($repository, 'http')) {
34800 $repoConfig = array('type' => 'composer', 'url' => $repository);
34801 } elseif ("json" === pathinfo($repository, PATHINFO_EXTENSION)) {
34802 $json = new JsonFile($repository, Factory::createRemoteFilesystem($io, $config));
34803 $data = $json->read();
34804 if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
34805 $repoConfig = array('type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/'));
34806 } elseif ($allowFilesystem) {
34807 $repoConfig = array('type' => 'filesystem', 'json' => $json);
34808 } else {
34809 throw new \InvalidArgumentException("Invalid repository URL ($repository) given. This file does not contain a valid composer repository.");
34810 }
34811 } elseif ('{' === substr($repository, 0, 1)) {
34812
34813  $repoConfig = JsonFile::parseJson($repository);
34814 } else {
34815 throw new \InvalidArgumentException("Invalid repository url ($repository) given. Has to be a .json file, an http url or a JSON object.");
34816 }
34817
34818 return $repoConfig;
34819 }
34820
34821
34822
34823
34824
34825
34826
34827
34828 public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
34829 {
34830 $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
34831
34832 return static::createRepo($io, $config, $repoConfig);
34833 }
34834
34835
34836
34837
34838
34839
34840
34841 public static function createRepo(IOInterface $io, Config $config, array $repoConfig)
34842 {
34843 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
34844 $repos = static::createRepos($rm, array($repoConfig));
34845
34846 return reset($repos);
34847 }
34848
34849
34850
34851
34852
34853
34854
34855 public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
34856 {
34857 if (!$config) {
34858 $config = Factory::createConfig($io);
34859 }
34860 if (!$rm) {
34861 if (!$io) {
34862 throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
34863 }
34864 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
34865 }
34866
34867 return static::createRepos($rm, $config->getRepositories());
34868 }
34869
34870
34871
34872
34873
34874
34875
34876
34877 public static function manager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
34878 {
34879 $rm = new RepositoryManager($io, $config, $eventDispatcher, $rfs);
34880 $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
34881 $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
34882 $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
34883 $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
34884 $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
34885 $rm->setRepositoryClass('github', 'Composer\Repository\VcsRepository');
34886 $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
34887 $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
34888 $rm->setRepositoryClass('fossil', 'Composer\Repository\VcsRepository');
34889 $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
34890 $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
34891 $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
34892 $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
34893
34894 return $rm;
34895 }
34896
34897
34898
34899
34900 private static function createRepos(RepositoryManager $rm, array $repoConfigs)
34901 {
34902 $repos = array();
34903
34904 foreach ($repoConfigs as $index => $repo) {
34905 if (is_string($repo)) {
34906 throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
34907 }
34908 if (!is_array($repo)) {
34909 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') should be an array, '.gettype($repo).' given');
34910 }
34911 if (!isset($repo['type'])) {
34912 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') must have a type defined');
34913 }
34914 $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
34915 while (isset($repos[$name])) {
34916 $name .= '2';
34917 }
34918 if ($repo['type'] === 'filesystem') {
34919 $repos[$name] = new FilesystemRepository($repo['json']);
34920 } else {
34921 $repos[$name] = $rm->createRepository($repo['type'], $repo, $index);
34922 }
34923 }
34924
34925 return $repos;
34926 }
34927 }
34928 <?php
34929
34930
34931
34932
34933
34934
34935
34936
34937
34938
34939
34940 namespace Composer\Repository;
34941
34942 use Composer\Package\PackageInterface;
34943
34944
34945
34946
34947
34948
34949
34950
34951 interface RepositoryInterface extends \Countable
34952 {
34953 const SEARCH_FULLTEXT = 0;
34954 const SEARCH_NAME = 1;
34955
34956
34957
34958
34959
34960
34961
34962
34963 public function hasPackage(PackageInterface $package);
34964
34965
34966
34967
34968
34969
34970
34971
34972
34973 public function findPackage($name, $constraint);
34974
34975
34976
34977
34978
34979
34980
34981
34982
34983 public function findPackages($name, $constraint = null);
34984
34985
34986
34987
34988
34989
34990 public function getPackages();
34991
34992
34993
34994
34995
34996
34997
34998
34999
35000 public function search($query, $mode = 0);
35001 }
35002 <?php
35003
35004
35005
35006
35007
35008
35009
35010
35011
35012
35013
35014 namespace Composer\Repository;
35015
35016 use Composer\IO\IOInterface;
35017 use Composer\Config;
35018 use Composer\EventDispatcher\EventDispatcher;
35019 use Composer\Package\PackageInterface;
35020 use Composer\Util\RemoteFilesystem;
35021
35022
35023
35024
35025
35026
35027
35028
35029 class RepositoryManager
35030 {
35031 private $localRepository;
35032 private $repositories = array();
35033 private $repositoryClasses = array();
35034 private $io;
35035 private $config;
35036 private $eventDispatcher;
35037 private $rfs;
35038
35039 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
35040 {
35041 $this->io = $io;
35042 $this->config = $config;
35043 $this->eventDispatcher = $eventDispatcher;
35044 $this->rfs = $rfs;
35045 }
35046
35047
35048
35049
35050
35051
35052
35053
35054
35055 public function findPackage($name, $constraint)
35056 {
35057 foreach ($this->repositories as $repository) {
35058 if ($package = $repository->findPackage($name, $constraint)) {
35059 return $package;
35060 }
35061 }
35062
35063 return null;
35064 }
35065
35066
35067
35068
35069
35070
35071
35072
35073
35074 public function findPackages($name, $constraint)
35075 {
35076 $packages = array();
35077
35078 foreach ($this->repositories as $repository) {
35079 $packages = array_merge($packages, $repository->findPackages($name, $constraint));
35080 }
35081
35082 return $packages;
35083 }
35084
35085
35086
35087
35088
35089
35090 public function addRepository(RepositoryInterface $repository)
35091 {
35092 $this->repositories[] = $repository;
35093 }
35094
35095
35096
35097
35098
35099
35100
35101
35102 public function prependRepository(RepositoryInterface $repository)
35103 {
35104 array_unshift($this->repositories, $repository);
35105 }
35106
35107
35108
35109
35110
35111
35112
35113
35114
35115
35116 public function createRepository($type, $config, $name = null)
35117 {
35118 if (!isset($this->repositoryClasses[$type])) {
35119 throw new \InvalidArgumentException('Repository type is not registered: '.$type);
35120 }
35121
35122 if (isset($config['packagist']) && false === $config['packagist']) {
35123 $this->io->writeError('<warning>Repository "'.$name.'" ('.json_encode($config).') has a packagist key which should be in its own repository definition</warning>');
35124 }
35125
35126 $class = $this->repositoryClasses[$type];
35127
35128 $reflMethod = new \ReflectionMethod($class, '__construct');
35129 $params = $reflMethod->getParameters();
35130 if (isset($params[4]) && $params[4]->getClass() && $params[4]->getClass()->getName() === 'Composer\Util\RemoteFilesystem') {
35131 return new $class($config, $this->io, $this->config, $this->eventDispatcher, $this->rfs);
35132 }
35133
35134 return new $class($config, $this->io, $this->config, $this->eventDispatcher);
35135 }
35136
35137
35138
35139
35140
35141
35142
35143 public function setRepositoryClass($type, $class)
35144 {
35145 $this->repositoryClasses[$type] = $class;
35146 }
35147
35148
35149
35150
35151
35152
35153 public function getRepositories()
35154 {
35155 return $this->repositories;
35156 }
35157
35158
35159
35160
35161
35162
35163 public function setLocalRepository(WritableRepositoryInterface $repository)
35164 {
35165 $this->localRepository = $repository;
35166 }
35167
35168
35169
35170
35171
35172
35173 public function getLocalRepository()
35174 {
35175 return $this->localRepository;
35176 }
35177 }
35178 <?php
35179
35180
35181
35182
35183
35184
35185
35186
35187
35188
35189
35190 namespace Composer\Repository;
35191
35192
35193
35194
35195
35196
35197 class RepositorySecurityException extends \Exception
35198 {
35199 }
35200 <?php
35201
35202
35203
35204
35205
35206
35207
35208
35209
35210
35211
35212 namespace Composer\Repository\Vcs;
35213
35214 use Composer\Cache;
35215 use Composer\Downloader\TransportException;
35216 use Composer\Json\JsonFile;
35217 use Composer\Util\Bitbucket;
35218
35219 abstract class BitbucketDriver extends VcsDriver
35220 {
35221
35222 protected $cache;
35223 protected $owner;
35224 protected $repository;
35225 protected $hasIssues;
35226 protected $rootIdentifier;
35227 protected $tags;
35228 protected $branches;
35229 protected $infoCache = array();
35230 protected $branchesUrl = '';
35231 protected $tagsUrl = '';
35232 protected $homeUrl = '';
35233 protected $website = '';
35234 protected $cloneHttpsUrl = '';
35235
35236
35237
35238
35239 protected $fallbackDriver;
35240
35241 protected $vcsType;
35242
35243
35244
35245
35246 public function initialize()
35247 {
35248 preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#', $this->url, $match);
35249 $this->owner = $match[1];
35250 $this->repository = $match[2];
35251 $this->originUrl = 'bitbucket.org';
35252 $this->cache = new Cache(
35253 $this->io,
35254 implode('/', array(
35255 $this->config->get('cache-repo-dir'),
35256 $this->originUrl,
35257 $this->owner,
35258 $this->repository,
35259 ))
35260 );
35261 }
35262
35263
35264
35265
35266 public function getUrl()
35267 {
35268 if ($this->fallbackDriver) {
35269 return $this->fallbackDriver->getUrl();
35270 }
35271
35272 return $this->cloneHttpsUrl;
35273 }
35274
35275
35276
35277
35278
35279
35280
35281 protected function getRepoData()
35282 {
35283 $resource = sprintf(
35284 'https://api.bitbucket.org/2.0/repositories/%s/%s?%s',
35285 $this->owner,
35286 $this->repository,
35287 http_build_query(
35288 array('fields' => '-project,-owner'),
35289 null,
35290 '&'
35291 )
35292 );
35293
35294 $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource);
35295 if ($this->fallbackDriver) {
35296 return false;
35297 }
35298 $this->parseCloneUrls($repoData['links']['clone']);
35299
35300 $this->hasIssues = !empty($repoData['has_issues']);
35301 $this->branchesUrl = $repoData['links']['branches']['href'];
35302 $this->tagsUrl = $repoData['links']['tags']['href'];
35303 $this->homeUrl = $repoData['links']['html']['href'];
35304 $this->website = $repoData['website'];
35305 $this->vcsType = $repoData['scm'];
35306
35307 return true;
35308 }
35309
35310
35311
35312
35313 public function getComposerInformation($identifier)
35314 {
35315 if ($this->fallbackDriver) {
35316 return $this->fallbackDriver->getComposerInformation($identifier);
35317 }
35318
35319 if (!isset($this->infoCache[$identifier])) {
35320 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
35321 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
35322 }
35323
35324 $composer = $this->getBaseComposerInformation($identifier);
35325
35326
35327  if (!isset($composer['support']['source'])) {
35328 $label = array_search(
35329 $identifier,
35330 $this->getTags()
35331 ) ?: array_search(
35332 $identifier,
35333 $this->getBranches()
35334 ) ?: $identifier;
35335
35336 if (array_key_exists($label, $tags = $this->getTags())) {
35337 $hash = $tags[$label];
35338 } elseif (array_key_exists($label, $branches = $this->getBranches())) {
35339 $hash = $branches[$label];
35340 }
35341
35342 if (! isset($hash)) {
35343 $composer['support']['source'] = sprintf(
35344 'https://%s/%s/%s/src',
35345 $this->originUrl,
35346 $this->owner,
35347 $this->repository
35348 );
35349 } else {
35350 $composer['support']['source'] = sprintf(
35351 'https://%s/%s/%s/src/%s/?at=%s',
35352 $this->originUrl,
35353 $this->owner,
35354 $this->repository,
35355 $hash,
35356 $label
35357 );
35358 }
35359 }
35360 if (!isset($composer['support']['issues']) && $this->hasIssues) {
35361 $composer['support']['issues'] = sprintf(
35362 'https://%s/%s/%s/issues',
35363 $this->originUrl,
35364 $this->owner,
35365 $this->repository
35366 );
35367 }
35368 if (!isset($composer['homepage'])) {
35369 $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
35370 }
35371
35372 $this->infoCache[$identifier] = $composer;
35373
35374 if ($this->shouldCache($identifier)) {
35375 $this->cache->write($identifier, json_encode($composer));
35376 }
35377 }
35378
35379 return $this->infoCache[$identifier];
35380 }
35381
35382
35383
35384
35385 public function getFileContent($file, $identifier)
35386 {
35387 if ($this->fallbackDriver) {
35388 return $this->fallbackDriver->getFileContent($file, $identifier);
35389 }
35390
35391 $resource = sprintf(
35392 'https://api.bitbucket.org/1.0/repositories/%s/%s/raw/%s/%s',
35393 $this->owner,
35394 $this->repository,
35395 $identifier,
35396 $file
35397 );
35398
35399 return $this->getContentsWithOAuthCredentials($resource);
35400 }
35401
35402
35403
35404
35405 public function getChangeDate($identifier)
35406 {
35407 if ($this->fallbackDriver) {
35408 return $this->fallbackDriver->getChangeDate($identifier);
35409 }
35410
35411 $resource = sprintf(
35412 'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
35413 $this->owner,
35414 $this->repository,
35415 $identifier
35416 );
35417 $commit = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35418
35419 return new \DateTime($commit['date']);
35420 }
35421
35422
35423
35424
35425 public function getSource($identifier)
35426 {
35427 if ($this->fallbackDriver) {
35428 return $this->fallbackDriver->getSource($identifier);
35429 }
35430
35431 return array('type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier);
35432 }
35433
35434
35435
35436
35437 public function getDist($identifier)
35438 {
35439 if ($this->fallbackDriver) {
35440 return $this->fallbackDriver->getDist($identifier);
35441 }
35442
35443 $url = sprintf(
35444 'https://bitbucket.org/%s/%s/get/%s.zip',
35445 $this->owner,
35446 $this->repository,
35447 $identifier
35448 );
35449
35450 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
35451 }
35452
35453
35454
35455
35456 public function getTags()
35457 {
35458 if ($this->fallbackDriver) {
35459 return $this->fallbackDriver->getTags();
35460 }
35461
35462 if (null === $this->tags) {
35463 $this->tags = array();
35464 $resource = sprintf(
35465 '%s?%s',
35466 $this->tagsUrl,
35467 http_build_query(
35468 array(
35469 'pagelen' => 100,
35470 'fields' => 'values.name,values.target.hash,next',
35471 'sort' => '-target.date',
35472 ),
35473 null,
35474 '&'
35475 )
35476 );
35477 $hasNext = true;
35478 while ($hasNext) {
35479 $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35480 foreach ($tagsData['values'] as $data) {
35481 $this->tags[$data['name']] = $data['target']['hash'];
35482 }
35483 if (empty($tagsData['next'])) {
35484 $hasNext = false;
35485 } else {
35486 $resource = $tagsData['next'];
35487 }
35488 }
35489 if ($this->vcsType === 'hg') {
35490 unset($this->tags['tip']);
35491 }
35492 }
35493
35494 return $this->tags;
35495 }
35496
35497
35498
35499
35500 public function getBranches()
35501 {
35502 if ($this->fallbackDriver) {
35503 return $this->fallbackDriver->getBranches();
35504 }
35505
35506 if (null === $this->branches) {
35507 $this->branches = array();
35508 $resource = sprintf(
35509 '%s?%s',
35510 $this->branchesUrl,
35511 http_build_query(
35512 array(
35513 'pagelen' => 100,
35514 'fields' => 'values.name,values.target.hash,values.heads,next',
35515 'sort' => '-target.date',
35516 ),
35517 null,
35518 '&'
35519 )
35520 );
35521 $hasNext = true;
35522 while ($hasNext) {
35523 $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35524 foreach ($branchData['values'] as $data) {
35525
35526  if ($this->vcsType === 'hg' && empty($data['heads'])) {
35527 continue;
35528 }
35529
35530 $this->branches[$data['name']] = $data['target']['hash'];
35531 }
35532 if (empty($branchData['next'])) {
35533 $hasNext = false;
35534 } else {
35535 $resource = $branchData['next'];
35536 }
35537 }
35538 }
35539
35540 return $this->branches;
35541 }
35542
35543
35544
35545
35546
35547
35548
35549
35550
35551 protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false)
35552 {
35553 try {
35554 return parent::getContents($url);
35555 } catch (TransportException $e) {
35556 $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem);
35557
35558 if (403 === $e->getCode() || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) {
35559 if (!$this->io->hasAuthentication($this->originUrl)
35560 && $bitbucketUtil->authorizeOAuth($this->originUrl)
35561 ) {
35562 return parent::getContents($url);
35563 }
35564
35565 if (!$this->io->isInteractive() && $fetchingRepoData) {
35566 return $this->attemptCloneFallback();
35567 }
35568 }
35569
35570 throw $e;
35571 }
35572 }
35573
35574
35575
35576
35577
35578
35579 abstract protected function generateSshUrl();
35580
35581 protected function attemptCloneFallback()
35582 {
35583 try {
35584 $this->setupFallbackDriver($this->generateSshUrl());
35585 } catch (\RuntimeException $e) {
35586 $this->fallbackDriver = null;
35587
35588 $this->io->writeError(
35589 '<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode'
35590 . ' so that you can enter your Bitbucket OAuth consumer credentials</error>'
35591 );
35592 throw $e;
35593 }
35594 }
35595
35596
35597
35598
35599
35600 abstract protected function setupFallbackDriver($url);
35601
35602
35603
35604
35605
35606 protected function parseCloneUrls(array $cloneLinks)
35607 {
35608 foreach ($cloneLinks as $cloneLink) {
35609 if ($cloneLink['name'] === 'https') {
35610
35611  
35612  $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']);
35613 }
35614 }
35615 }
35616
35617
35618
35619
35620 protected function getMainBranchData()
35621 {
35622 $resource = sprintf(
35623 'https://api.bitbucket.org/1.0/repositories/%s/%s/main-branch',
35624 $this->owner,
35625 $this->repository
35626 );
35627
35628 return JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35629 }
35630 }
35631 <?php
35632
35633
35634
35635
35636
35637
35638
35639
35640
35641
35642
35643 namespace Composer\Repository\Vcs;
35644
35645 use Composer\Config;
35646 use Composer\Util\ProcessExecutor;
35647 use Composer\Util\Filesystem;
35648 use Composer\IO\IOInterface;
35649
35650
35651
35652
35653 class FossilDriver extends VcsDriver
35654 {
35655 protected $tags;
35656 protected $branches;
35657 protected $rootIdentifier;
35658 protected $repoFile;
35659 protected $checkoutDir;
35660 protected $infoCache = array();
35661
35662
35663
35664
35665 public function initialize()
35666 {
35667
35668  $this->checkFossil();
35669
35670
35671  $this->config->prohibitUrlByConfig($this->url, $this->io);
35672
35673
35674  
35675  if (Filesystem::isLocalPath($this->url) && is_dir($this->url)) {
35676 $this->checkoutDir = $this->url;
35677 } else {
35678 $localName = preg_replace('{[^a-z0-9]}i', '-', $this->url);
35679 $this->repoFile = $this->config->get('cache-repo-dir') . '/' . $localName . '.fossil';
35680 $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . $localName . '/';
35681
35682 $this->updateLocalRepo();
35683 }
35684
35685 $this->getTags();
35686 $this->getBranches();
35687 }
35688
35689
35690
35691
35692 protected function checkFossil()
35693 {
35694 if (0 !== $this->process->execute('fossil version', $ignoredOutput)) {
35695 throw new \RuntimeException("fossil was not found, check that it is installed and in your PATH env.\n\n" . $this->process->getErrorOutput());
35696 }
35697 }
35698
35699
35700
35701
35702 protected function updateLocalRepo()
35703 {
35704 $fs = new Filesystem();
35705 $fs->ensureDirectoryExists($this->checkoutDir);
35706
35707 if (!is_writable(dirname($this->checkoutDir))) {
35708 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.');
35709 }
35710
35711
35712  if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) {
35713 if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) {
35714 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
35715 }
35716 } else {
35717
35718  $fs->removeDirectory($this->checkoutDir);
35719 $fs->remove($this->repoFile);
35720
35721 $fs->ensureDirectoryExists($this->checkoutDir);
35722
35723 if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
35724 $output = $this->process->getErrorOutput();
35725
35726 throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output);
35727 }
35728
35729 if (0 !== $this->process->execute(sprintf('fossil open %s', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
35730 $output = $this->process->getErrorOutput();
35731
35732 throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output);
35733 }
35734 }
35735 }
35736
35737
35738
35739
35740 public function getRootIdentifier()
35741 {
35742 if (null === $this->rootIdentifier) {
35743 $this->rootIdentifier = 'trunk';
35744 }
35745
35746 return $this->rootIdentifier;
35747 }
35748
35749
35750
35751
35752 public function getUrl()
35753 {
35754 return $this->url;
35755 }
35756
35757
35758
35759
35760 public function getSource($identifier)
35761 {
35762 return array('type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier);
35763 }
35764
35765
35766
35767
35768 public function getDist($identifier)
35769 {
35770 return null;
35771 }
35772
35773
35774
35775
35776 public function getFileContent($file, $identifier)
35777 {
35778 $command = sprintf('fossil cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
35779 $this->process->execute($command, $content, $this->checkoutDir);
35780
35781 if (!trim($content)) {
35782 return null;
35783 }
35784
35785 return $content;
35786 }
35787
35788
35789
35790
35791 public function getChangeDate($identifier)
35792 {
35793 $this->process->execute('fossil finfo -b -n 1 composer.json', $output, $this->checkoutDir);
35794 list($ckout, $date, $message) = explode(' ', trim($output), 3);
35795
35796 return new \DateTime($date, new \DateTimeZone('UTC'));
35797 }
35798
35799
35800
35801
35802 public function getTags()
35803 {
35804 if (null === $this->tags) {
35805 $tags = array();
35806
35807 $this->process->execute('fossil tag list', $output, $this->checkoutDir);
35808 foreach ($this->process->splitLines($output) as $tag) {
35809 $tags[$tag] = $tag;
35810 }
35811
35812 $this->tags = $tags;
35813 }
35814
35815 return $this->tags;
35816 }
35817
35818
35819
35820
35821 public function getBranches()
35822 {
35823 if (null === $this->branches) {
35824 $branches = array();
35825 $bookmarks = array();
35826
35827 $this->process->execute('fossil branch list', $output, $this->checkoutDir);
35828 foreach ($this->process->splitLines($output) as $branch) {
35829 $branch = trim(preg_replace('/^\*/', '', trim($branch)));
35830 $branches[$branch] = $branch;
35831 }
35832
35833 $this->branches = $branches;
35834 }
35835
35836 return $this->branches;
35837 }
35838
35839
35840
35841
35842 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35843 {
35844 if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) {
35845 return true;
35846 }
35847
35848 if (preg_match('!/fossil/|\.fossil!', $url)) {
35849 return true;
35850 }
35851
35852
35853  if (Filesystem::isLocalPath($url)) {
35854 $url = Filesystem::getPlatformPath($url);
35855 if (!is_dir($url)) {
35856 return false;
35857 }
35858
35859 $process = new ProcessExecutor();
35860
35861  if ($process->execute('fossil info', $output, $url) === 0) {
35862 return true;
35863 }
35864 }
35865
35866 return false;
35867 }
35868 }
35869 <?php
35870
35871
35872
35873
35874
35875
35876
35877
35878
35879
35880
35881 namespace Composer\Repository\Vcs;
35882
35883 use Composer\Config;
35884 use Composer\IO\IOInterface;
35885
35886
35887
35888
35889 class GitBitbucketDriver extends BitbucketDriver
35890 {
35891
35892
35893
35894 public function getRootIdentifier()
35895 {
35896 if ($this->fallbackDriver) {
35897 return $this->fallbackDriver->getRootIdentifier();
35898 }
35899
35900 if (null === $this->rootIdentifier) {
35901 if (! $this->getRepoData()) {
35902 return $this->fallbackDriver->getRootIdentifier();
35903 }
35904
35905 if ($this->vcsType !== 'git') {
35906 throw new \RuntimeException(
35907 $this->url.' does not appear to be a git repository, use '.
35908 $this->cloneHttpsUrl.' if this is a mercurial bitbucket repository'
35909 );
35910 }
35911
35912 $mainBranchData = $this->getMainBranchData();
35913 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'master';
35914 }
35915
35916 return $this->rootIdentifier;
35917 }
35918
35919
35920
35921
35922 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35923 {
35924 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url)) {
35925 return false;
35926 }
35927
35928 if (!extension_loaded('openssl')) {
35929 $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
35930
35931 return false;
35932 }
35933
35934 return true;
35935 }
35936
35937
35938
35939
35940 protected function setupFallbackDriver($url)
35941 {
35942 $this->fallbackDriver = new GitDriver(
35943 array('url' => $url),
35944 $this->io,
35945 $this->config,
35946 $this->process,
35947 $this->remoteFilesystem
35948 );
35949 $this->fallbackDriver->initialize();
35950 }
35951
35952
35953
35954
35955 protected function generateSshUrl()
35956 {
35957 return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git';
35958 }
35959 }
35960 <?php
35961
35962
35963
35964
35965
35966
35967
35968
35969
35970
35971
35972 namespace Composer\Repository\Vcs;
35973
35974 use Composer\Util\ProcessExecutor;
35975 use Composer\Util\Filesystem;
35976 use Composer\Util\Git as GitUtil;
35977 use Composer\IO\IOInterface;
35978 use Composer\Cache;
35979 use Composer\Config;
35980
35981
35982
35983
35984 class GitDriver extends VcsDriver
35985 {
35986 protected $cache;
35987 protected $tags;
35988 protected $branches;
35989 protected $rootIdentifier;
35990 protected $repoDir;
35991 protected $infoCache = array();
35992
35993
35994
35995
35996 public function initialize()
35997 {
35998 if (Filesystem::isLocalPath($this->url)) {
35999 $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
36000 $this->repoDir = $this->url;
36001 $cacheUrl = realpath($this->url);
36002 } else {
36003 $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
36004
36005 GitUtil::cleanEnv();
36006
36007 $fs = new Filesystem();
36008 $fs->ensureDirectoryExists(dirname($this->repoDir));
36009
36010 if (!is_writable(dirname($this->repoDir))) {
36011 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
36012 }
36013
36014 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
36015 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.');
36016 }
36017
36018 $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
36019 if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
36020 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
36021 }
36022
36023 $cacheUrl = $this->url;
36024 }
36025
36026 $this->getTags();
36027 $this->getBranches();
36028
36029 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
36030 }
36031
36032
36033
36034
36035 public function getRootIdentifier()
36036 {
36037 if (null === $this->rootIdentifier) {
36038 $this->rootIdentifier = 'master';
36039
36040
36041  $this->process->execute('git branch --no-color', $output, $this->repoDir);
36042 $branches = $this->process->splitLines($output);
36043 if (!in_array('* master', $branches)) {
36044 foreach ($branches as $branch) {
36045 if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) {
36046 $this->rootIdentifier = $match[1];
36047 break;
36048 }
36049 }
36050 }
36051 }
36052
36053 return $this->rootIdentifier;
36054 }
36055
36056
36057
36058
36059 public function getUrl()
36060 {
36061 return $this->url;
36062 }
36063
36064
36065
36066
36067 public function getSource($identifier)
36068 {
36069 return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
36070 }
36071
36072
36073
36074
36075 public function getDist($identifier)
36076 {
36077 return null;
36078 }
36079
36080
36081
36082
36083 public function getFileContent($file, $identifier)
36084 {
36085 $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
36086 $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir);
36087
36088 if (!trim($content)) {
36089 return null;
36090 }
36091
36092 return $content;
36093 }
36094
36095
36096
36097
36098 public function getChangeDate($identifier)
36099 {
36100 $this->process->execute(sprintf(
36101 'git log -1 --format=%%at %s',
36102 ProcessExecutor::escape($identifier)
36103 ), $output, $this->repoDir);
36104
36105 return new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
36106 }
36107
36108
36109
36110
36111 public function getTags()
36112 {
36113 if (null === $this->tags) {
36114 $this->tags = array();
36115
36116 $this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir);
36117 foreach ($output = $this->process->splitLines($output) as $tag) {
36118 if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
36119 $this->tags[$match[2]] = $match[1];
36120 }
36121 }
36122 }
36123
36124 return $this->tags;
36125 }
36126
36127
36128
36129
36130 public function getBranches()
36131 {
36132 if (null === $this->branches) {
36133 $branches = array();
36134
36135 $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
36136 foreach ($this->process->splitLines($output) as $branch) {
36137 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
36138 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) {
36139 $branches[$match[1]] = $match[2];
36140 }
36141 }
36142 }
36143
36144 $this->branches = $branches;
36145 }
36146
36147 return $this->branches;
36148 }
36149
36150
36151
36152
36153 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36154 {
36155 if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
36156 return true;
36157 }
36158
36159
36160  if (Filesystem::isLocalPath($url)) {
36161 $url = Filesystem::getPlatformPath($url);
36162 if (!is_dir($url)) {
36163 return false;
36164 }
36165
36166 $process = new ProcessExecutor($io);
36167
36168  if ($process->execute('git tag', $output, $url) === 0) {
36169 return true;
36170 }
36171 }
36172
36173 if (!$deep) {
36174 return false;
36175 }
36176
36177 $process = new ProcessExecutor($io);
36178
36179 return $process->execute('git ls-remote --heads ' . ProcessExecutor::escape($url), $output) === 0;
36180 }
36181 }
36182 <?php
36183
36184
36185
36186
36187
36188
36189
36190
36191
36192
36193
36194 namespace Composer\Repository\Vcs;
36195
36196 use Composer\Config;
36197 use Composer\Downloader\TransportException;
36198 use Composer\Json\JsonFile;
36199 use Composer\Cache;
36200 use Composer\IO\IOInterface;
36201 use Composer\Util\GitHub;
36202
36203
36204
36205
36206 class GitHubDriver extends VcsDriver
36207 {
36208 protected $cache;
36209 protected $owner;
36210 protected $repository;
36211 protected $tags;
36212 protected $branches;
36213 protected $rootIdentifier;
36214 protected $repoData;
36215 protected $hasIssues;
36216 protected $infoCache = array();
36217 protected $isPrivate = false;
36218
36219
36220
36221
36222
36223
36224 protected $gitDriver;
36225
36226
36227
36228
36229 public function initialize()
36230 {
36231 preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
36232 $this->owner = $match[3];
36233 $this->repository = $match[4];
36234 $this->originUrl = !empty($match[1]) ? $match[1] : $match[2];
36235 if ($this->originUrl === 'www.github.com') {
36236 $this->originUrl = 'github.com';
36237 }
36238 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
36239
36240 if (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api']) {
36241 $this->setupGitDriver($this->url);
36242
36243 return;
36244 }
36245
36246 $this->fetchRootIdentifier();
36247 }
36248
36249 public function getRepositoryUrl()
36250 {
36251 return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
36252 }
36253
36254
36255
36256
36257 public function getRootIdentifier()
36258 {
36259 if ($this->gitDriver) {
36260 return $this->gitDriver->getRootIdentifier();
36261 }
36262
36263 return $this->rootIdentifier;
36264 }
36265
36266
36267
36268
36269 public function getUrl()
36270 {
36271 if ($this->gitDriver) {
36272 return $this->gitDriver->getUrl();
36273 }
36274
36275 return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
36276 }
36277
36278
36279
36280
36281 protected function getApiUrl()
36282 {
36283 if ('github.com' === $this->originUrl) {
36284 $apiUrl = 'api.github.com';
36285 } else {
36286 $apiUrl = $this->originUrl . '/api/v3';
36287 }
36288
36289 return 'https://' . $apiUrl;
36290 }
36291
36292
36293
36294
36295 public function getSource($identifier)
36296 {
36297 if ($this->gitDriver) {
36298 return $this->gitDriver->getSource($identifier);
36299 }
36300 if ($this->isPrivate) {
36301
36302  
36303  $url = $this->generateSshUrl();
36304 } else {
36305 $url = $this->getUrl();
36306 }
36307
36308 return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
36309 }
36310
36311
36312
36313
36314 public function getDist($identifier)
36315 {
36316 $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
36317
36318 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
36319 }
36320
36321
36322
36323
36324 public function getComposerInformation($identifier)
36325 {
36326 if ($this->gitDriver) {
36327 return $this->gitDriver->getComposerInformation($identifier);
36328 }
36329
36330 if (!isset($this->infoCache[$identifier])) {
36331 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
36332 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
36333 }
36334
36335 $composer = $this->getBaseComposerInformation($identifier);
36336 if ($composer) {
36337
36338
36339  if (!isset($composer['support']['source'])) {
36340 $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
36341 $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
36342 }
36343 if (!isset($composer['support']['issues']) && $this->hasIssues) {
36344 $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
36345 }
36346 }
36347
36348 if ($this->shouldCache($identifier)) {
36349 $this->cache->write($identifier, json_encode($composer));
36350 }
36351
36352 $this->infoCache[$identifier] = $composer;
36353 }
36354
36355 return $this->infoCache[$identifier];
36356 }
36357
36358
36359
36360
36361 public function getFileContent($file, $identifier)
36362 {
36363 if ($this->gitDriver) {
36364 return $this->gitDriver->getFileContent($file, $identifier);
36365 }
36366
36367 $notFoundRetries = 2;
36368 while ($notFoundRetries) {
36369 try {
36370 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
36371 $resource = JsonFile::parseJson($this->getContents($resource));
36372 if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
36373 throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
36374 }
36375
36376 return $content;
36377 } catch (TransportException $e) {
36378 if (404 !== $e->getCode()) {
36379 throw $e;
36380 }
36381
36382
36383  
36384  $notFoundRetries--;
36385
36386 return null;
36387 }
36388 }
36389
36390 return null;
36391 }
36392
36393
36394
36395
36396 public function getChangeDate($identifier)
36397 {
36398 if ($this->gitDriver) {
36399 return $this->gitDriver->getChangeDate($identifier);
36400 }
36401
36402 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
36403 $commit = JsonFile::parseJson($this->getContents($resource), $resource);
36404
36405 return new \DateTime($commit['commit']['committer']['date']);
36406 }
36407
36408
36409
36410
36411 public function getTags()
36412 {
36413 if ($this->gitDriver) {
36414 return $this->gitDriver->getTags();
36415 }
36416 if (null === $this->tags) {
36417 $this->tags = array();
36418 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
36419
36420 do {
36421 $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
36422 foreach ($tagsData as $tag) {
36423 $this->tags[$tag['name']] = $tag['commit']['sha'];
36424 }
36425
36426 $resource = $this->getNextPage();
36427 } while ($resource);
36428 }
36429
36430 return $this->tags;
36431 }
36432
36433
36434
36435
36436 public function getBranches()
36437 {
36438 if ($this->gitDriver) {
36439 return $this->gitDriver->getBranches();
36440 }
36441 if (null === $this->branches) {
36442 $this->branches = array();
36443 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
36444
36445 $branchBlacklist = array('gh-pages');
36446
36447 do {
36448 $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
36449 foreach ($branchData as $branch) {
36450 $name = substr($branch['ref'], 11);
36451 if (!in_array($name, $branchBlacklist)) {
36452 $this->branches[$name] = $branch['object']['sha'];
36453 }
36454 }
36455
36456 $resource = $this->getNextPage();
36457 } while ($resource);
36458 }
36459
36460 return $this->branches;
36461 }
36462
36463
36464
36465
36466 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36467 {
36468 if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
36469 return false;
36470 }
36471
36472 $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
36473 if (!in_array(preg_replace('{^www\.}i', '', $originUrl), $config->get('github-domains'))) {
36474 return false;
36475 }
36476
36477 if (!extension_loaded('openssl')) {
36478 $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36479
36480 return false;
36481 }
36482
36483 return true;
36484 }
36485
36486
36487
36488
36489
36490
36491 public function getRepoData()
36492 {
36493 $this->fetchRootIdentifier();
36494
36495 return $this->repoData;
36496 }
36497
36498
36499
36500
36501
36502
36503 protected function generateSshUrl()
36504 {
36505 return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
36506 }
36507
36508
36509
36510
36511 protected function getContents($url, $fetchingRepoData = false)
36512 {
36513 try {
36514 return parent::getContents($url);
36515 } catch (TransportException $e) {
36516 $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
36517
36518 switch ($e->getCode()) {
36519 case 401:
36520 case 404:
36521
36522  if (!$fetchingRepoData) {
36523 throw $e;
36524 }
36525
36526 if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
36527 return parent::getContents($url);
36528 }
36529
36530 if (!$this->io->isInteractive()) {
36531 return $this->attemptCloneFallback();
36532 }
36533
36534 $scopesIssued = array();
36535 $scopesNeeded = array();
36536 if ($headers = $e->getHeaders()) {
36537 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-OAuth-Scopes')) {
36538 $scopesIssued = explode(' ', $scopes);
36539 }
36540 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
36541 $scopesNeeded = explode(' ', $scopes);
36542 }
36543 }
36544 $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
36545 if (!$headers || count($scopesFailed)) {
36546 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
36547 }
36548
36549 return parent::getContents($url);
36550
36551 case 403:
36552 if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
36553 return parent::getContents($url);
36554 }
36555
36556 if (!$this->io->isInteractive() && $fetchingRepoData) {
36557 return $this->attemptCloneFallback();
36558 }
36559
36560 $rateLimited = false;
36561 foreach ($e->getHeaders() as $header) {
36562 if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
36563 $rateLimited = true;
36564 }
36565 }
36566
36567 if (!$this->io->hasAuthentication($this->originUrl)) {
36568 if (!$this->io->isInteractive()) {
36569 $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>');
36570 throw $e;
36571 }
36572
36573 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>'.$this->url.'</info>)');
36574
36575 return parent::getContents($url);
36576 }
36577
36578 if ($rateLimited) {
36579 $rateLimit = $this->getRateLimit($e->getHeaders());
36580 $this->io->writeError(sprintf(
36581 '<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>',
36582 $rateLimit['limit'],
36583 $rateLimit['reset']
36584 ));
36585 }
36586
36587 throw $e;
36588
36589 default:
36590 throw $e;
36591 }
36592 }
36593 }
36594
36595
36596
36597
36598
36599
36600
36601
36602 protected function getRateLimit(array $headers)
36603 {
36604 $rateLimit = array(
36605 'limit' => '?',
36606 'reset' => '?',
36607 );
36608
36609 foreach ($headers as $header) {
36610 $header = trim($header);
36611 if (false === strpos($header, 'X-RateLimit-')) {
36612 continue;
36613 }
36614 list($type, $value) = explode(':', $header, 2);
36615 switch ($type) {
36616 case 'X-RateLimit-Limit':
36617 $rateLimit['limit'] = (int) trim($value);
36618 break;
36619 case 'X-RateLimit-Reset':
36620 $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
36621 break;
36622 }
36623 }
36624
36625 return $rateLimit;
36626 }
36627
36628
36629
36630
36631
36632
36633 protected function fetchRootIdentifier()
36634 {
36635 if ($this->repoData) {
36636 return;
36637 }
36638
36639 $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
36640
36641 $this->repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
36642 if (null === $this->repoData && null !== $this->gitDriver) {
36643 return;
36644 }
36645
36646 $this->owner = $this->repoData['owner']['login'];
36647 $this->repository = $this->repoData['name'];
36648
36649 $this->isPrivate = !empty($this->repoData['private']);
36650 if (isset($this->repoData['default_branch'])) {
36651 $this->rootIdentifier = $this->repoData['default_branch'];
36652 } elseif (isset($this->repoData['master_branch'])) {
36653 $this->rootIdentifier = $this->repoData['master_branch'];
36654 } else {
36655 $this->rootIdentifier = 'master';
36656 }
36657 $this->hasIssues = !empty($this->repoData['has_issues']);
36658 }
36659
36660 protected function attemptCloneFallback()
36661 {
36662 $this->isPrivate = true;
36663
36664 try {
36665
36666  
36667  
36668  
36669  $this->setupGitDriver($this->generateSshUrl());
36670
36671 return;
36672 } catch (\RuntimeException $e) {
36673 $this->gitDriver = null;
36674
36675 $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>');
36676 throw $e;
36677 }
36678 }
36679
36680 protected function setupGitDriver($url)
36681 {
36682 $this->gitDriver = new GitDriver(
36683 array('url' => $url),
36684 $this->io,
36685 $this->config,
36686 $this->process,
36687 $this->remoteFilesystem
36688 );
36689 $this->gitDriver->initialize();
36690 }
36691
36692 protected function getNextPage()
36693 {
36694 $headers = $this->remoteFilesystem->getLastHeaders();
36695 foreach ($headers as $header) {
36696 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
36697 $links = explode(',', $match[1]);
36698 foreach ($links as $link) {
36699 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
36700 return $match[1];
36701 }
36702 }
36703 }
36704 }
36705 }
36706 }
36707 <?php
36708
36709
36710
36711
36712
36713
36714
36715
36716
36717
36718
36719 namespace Composer\Repository\Vcs;
36720
36721 use Composer\Config;
36722 use Composer\Cache;
36723 use Composer\IO\IOInterface;
36724 use Composer\Json\JsonFile;
36725 use Composer\Downloader\TransportException;
36726 use Composer\Util\RemoteFilesystem;
36727 use Composer\Util\GitLab;
36728
36729
36730
36731
36732
36733
36734
36735 class GitLabDriver extends VcsDriver
36736 {
36737 private $scheme;
36738 private $namespace;
36739 private $repository;
36740
36741
36742
36743
36744 private $project;
36745
36746
36747
36748
36749 private $commits = array();
36750
36751
36752
36753
36754 private $tags;
36755
36756
36757
36758
36759 private $branches;
36760
36761
36762
36763
36764
36765
36766 protected $gitDriver;
36767
36768
36769
36770
36771
36772
36773 private $isPrivate = true;
36774
36775
36776
36777
36778 protected $portNumber;
36779
36780 const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)(?::(?P<port>[0-9]+))?/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
36781
36782
36783
36784
36785
36786
36787
36788
36789 public function initialize()
36790 {
36791 if (!preg_match(self::URL_REGEX, $this->url, $match)) {
36792 throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
36793 }
36794
36795 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
36796 $configuredDomains = $this->config->get('gitlab-domains');
36797 $urlParts = explode('/', $match['parts']);
36798
36799 $this->scheme = !empty($match['scheme'])
36800 ? $match['scheme']
36801 : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https')
36802 ;
36803 $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts);
36804
36805 if (!empty($match['port']) && true === is_numeric($match['port'])) {
36806
36807  $this->portNumber = (int) $match['port'];
36808 }
36809
36810 $this->namespace = implode('/', $urlParts);
36811 $this->repository = preg_replace('#(\.git)$#', '', $match['repo']);
36812
36813 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository);
36814
36815 $this->fetchProject();
36816 }
36817
36818
36819
36820
36821
36822
36823
36824 public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
36825 {
36826 $this->remoteFilesystem = $remoteFilesystem;
36827 }
36828
36829
36830
36831
36832 public function getFileContent($file, $identifier)
36833 {
36834 if ($this->gitDriver) {
36835 return $this->gitDriver->getFileContent($file, $identifier);
36836 }
36837
36838
36839  if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
36840 $branches = $this->getBranches();
36841 if (isset($branches[$identifier])) {
36842 $identifier = $branches[$identifier];
36843 }
36844 }
36845
36846 $resource = $this->getApiUrl().'/repository/files/'.$this->urlEncodeAll($file).'/raw?ref='.$identifier;
36847
36848 try {
36849 $content = $this->getContents($resource);
36850 } catch (TransportException $e) {
36851 if ($e->getCode() !== 404) {
36852 throw $e;
36853 }
36854
36855 return null;
36856 }
36857
36858 return $content;
36859 }
36860
36861
36862
36863
36864 public function getChangeDate($identifier)
36865 {
36866 if ($this->gitDriver) {
36867 return $this->gitDriver->getChangeDate($identifier);
36868 }
36869
36870 if (isset($this->commits[$identifier])) {
36871 return new \DateTime($this->commits[$identifier]['committed_date']);
36872 }
36873
36874 return new \DateTime();
36875 }
36876
36877
36878
36879
36880 public function getRepositoryUrl()
36881 {
36882 return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
36883 }
36884
36885
36886
36887
36888 public function getUrl()
36889 {
36890 if ($this->gitDriver) {
36891 return $this->gitDriver->getUrl();
36892 }
36893
36894 return $this->project['web_url'];
36895 }
36896
36897
36898
36899
36900 public function getDist($identifier)
36901 {
36902 $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
36903
36904 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
36905 }
36906
36907
36908
36909
36910 public function getSource($identifier)
36911 {
36912 if ($this->gitDriver) {
36913 return $this->gitDriver->getSource($identifier);
36914 }
36915
36916 return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
36917 }
36918
36919
36920
36921
36922 public function getRootIdentifier()
36923 {
36924 if ($this->gitDriver) {
36925 return $this->gitDriver->getRootIdentifier();
36926 }
36927
36928 return $this->project['default_branch'];
36929 }
36930
36931
36932
36933
36934 public function getBranches()
36935 {
36936 if ($this->gitDriver) {
36937 return $this->gitDriver->getBranches();
36938 }
36939
36940 if (!$this->branches) {
36941 $this->branches = $this->getReferences('branches');
36942 }
36943
36944 return $this->branches;
36945 }
36946
36947
36948
36949
36950 public function getTags()
36951 {
36952 if ($this->gitDriver) {
36953 return $this->gitDriver->getTags();
36954 }
36955
36956 if (!$this->tags) {
36957 $this->tags = $this->getReferences('tags');
36958 }
36959
36960 return $this->tags;
36961 }
36962
36963
36964
36965
36966 public function getApiUrl()
36967 {
36968 $domainName = $this->originUrl;
36969 $portNumber = (true === is_numeric($this->portNumber)) ? sprintf(':%s', $this->portNumber) : '';
36970
36971 return $this->scheme.'://'.$domainName.$portNumber.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository);
36972 }
36973
36974
36975
36976
36977
36978
36979
36980 private function urlEncodeAll($string)
36981 {
36982 $encoded = '';
36983 for ($i = 0; isset($string[$i]); $i++) {
36984 $character = $string[$i];
36985 if (!ctype_alnum($character) && !in_array($character, array('-', '_'), true)) {
36986 $character = '%' . sprintf('%02X', ord($character));
36987 }
36988 $encoded .= $character;
36989 }
36990
36991 return $encoded;
36992 }
36993
36994
36995
36996
36997
36998
36999 protected function getReferences($type)
37000 {
37001 $perPage = 100;
37002 $resource = $this->getApiUrl().'/repository/'.$type.'?per_page='.$perPage;
37003
37004 $references = array();
37005 do {
37006 $data = JsonFile::parseJson($this->getContents($resource), $resource);
37007
37008 foreach ($data as $datum) {
37009 $references[$datum['name']] = $datum['commit']['id'];
37010
37011
37012  
37013  $this->commits[$datum['commit']['id']] = $datum['commit'];
37014 }
37015
37016 if (count($data) >= $perPage) {
37017 $resource = $this->getNextPage();
37018 } else {
37019 $resource = false;
37020 }
37021 } while ($resource);
37022
37023 return $references;
37024 }
37025
37026 protected function fetchProject()
37027 {
37028
37029  $resource = $this->getApiUrl();
37030 $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
37031 if (isset($this->project['visibility'])) {
37032 $this->isPrivate = $this->project['visibility'] !== 'public';
37033 } else {
37034
37035  $this->isPrivate = false;
37036 }
37037 }
37038
37039 protected function attemptCloneFallback()
37040 {
37041 try {
37042 if ($this->isPrivate === false) {
37043 $url = $this->generatePublicUrl();
37044 } else {
37045 $url = $this->generateSshUrl();
37046 }
37047
37048
37049  
37050  
37051  $this->setupGitDriver($url);
37052
37053 return;
37054 } catch (\RuntimeException $e) {
37055 $this->gitDriver = null;
37056
37057 $this->io->writeError('<error>Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials</error>');
37058 throw $e;
37059 }
37060 }
37061
37062
37063
37064
37065
37066
37067 protected function generateSshUrl()
37068 {
37069 return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git';
37070 }
37071
37072 protected function generatePublicUrl()
37073 {
37074 return $this->scheme . '://' . $this->originUrl . '/'.$this->namespace.'/'.$this->repository.'.git';
37075 }
37076
37077 protected function setupGitDriver($url)
37078 {
37079 $this->gitDriver = new GitDriver(
37080 array('url' => $url),
37081 $this->io,
37082 $this->config,
37083 $this->process,
37084 $this->remoteFilesystem
37085 );
37086 $this->gitDriver->initialize();
37087 }
37088
37089
37090
37091
37092 protected function getContents($url, $fetchingRepoData = false)
37093 {
37094 try {
37095 $res = parent::getContents($url);
37096
37097 if ($fetchingRepoData) {
37098 $json = JsonFile::parseJson($res, $url);
37099
37100
37101  if (!isset($json['default_branch'])) {
37102 if (!empty($json['id'])) {
37103 $this->isPrivate = false;
37104 }
37105
37106 throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
37107 }
37108 }
37109
37110 return $res;
37111 } catch (TransportException $e) {
37112 $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);
37113
37114 switch ($e->getCode()) {
37115 case 401:
37116 case 404:
37117
37118  if (!$fetchingRepoData) {
37119 throw $e;
37120 }
37121
37122 if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
37123 return parent::getContents($url);
37124 }
37125
37126 if (!$this->io->isInteractive()) {
37127 return $this->attemptCloneFallback();
37128 }
37129 $this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
37130 $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
37131
37132 return parent::getContents($url);
37133
37134 case 403:
37135 if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
37136 return parent::getContents($url);
37137 }
37138
37139 if (!$this->io->isInteractive() && $fetchingRepoData) {
37140 return $this->attemptCloneFallback();
37141 }
37142
37143 throw $e;
37144
37145 default:
37146 throw $e;
37147 }
37148 }
37149 }
37150
37151
37152
37153
37154
37155
37156
37157 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37158 {
37159 if (!preg_match(self::URL_REGEX, $url, $match)) {
37160 return false;
37161 }
37162
37163 $scheme = !empty($match['scheme']) ? $match['scheme'] : null;
37164 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
37165 $urlParts = explode('/', $match['parts']);
37166
37167 if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts)) {
37168 return false;
37169 }
37170
37171 if ('https' === $scheme && !extension_loaded('openssl')) {
37172 $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
37173
37174 return false;
37175 }
37176
37177 return true;
37178 }
37179
37180 private function getNextPage()
37181 {
37182 $headers = $this->remoteFilesystem->getLastHeaders();
37183 foreach ($headers as $header) {
37184 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
37185 $links = explode(',', $match[1]);
37186 foreach ($links as $link) {
37187 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
37188 return $match[1];
37189 }
37190 }
37191 }
37192 }
37193 }
37194
37195
37196
37197
37198
37199
37200
37201 private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts)
37202 {
37203 if (in_array($guessedDomain, $configuredDomains)) {
37204 return $guessedDomain;
37205 }
37206
37207 while (null !== ($part = array_shift($urlParts))) {
37208 $guessedDomain .= '/' . $part;
37209
37210 if (in_array($guessedDomain, $configuredDomains)) {
37211 return $guessedDomain;
37212 }
37213 }
37214
37215 return false;
37216 }
37217 }
37218 <?php
37219
37220
37221
37222
37223
37224
37225
37226
37227
37228
37229
37230 namespace Composer\Repository\Vcs;
37231
37232 use Composer\Config;
37233 use Composer\IO\IOInterface;
37234
37235
37236
37237
37238 class HgBitbucketDriver extends BitbucketDriver
37239 {
37240
37241
37242
37243 public function getRootIdentifier()
37244 {
37245 if ($this->fallbackDriver) {
37246 return $this->fallbackDriver->getRootIdentifier();
37247 }
37248
37249 if (null === $this->rootIdentifier) {
37250 if (! $this->getRepoData()) {
37251 return $this->fallbackDriver->getRootIdentifier();
37252 }
37253
37254 if ($this->vcsType !== 'hg') {
37255 throw new \RuntimeException(
37256 $this->url.' does not appear to be a mercurial repository, use '.
37257 $this->cloneHttpsUrl.' if this is a git bitbucket repository'
37258 );
37259 }
37260
37261 $mainBranchData = $this->getMainBranchData();
37262 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'default';
37263 }
37264
37265 return $this->rootIdentifier;
37266 }
37267
37268
37269
37270
37271 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37272 {
37273 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url)) {
37274 return false;
37275 }
37276
37277 if (!extension_loaded('openssl')) {
37278 $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
37279
37280 return false;
37281 }
37282
37283 return true;
37284 }
37285
37286
37287
37288
37289 protected function setupFallbackDriver($url)
37290 {
37291 $this->fallbackDriver = new HgDriver(
37292 array('url' => $url),
37293 $this->io,
37294 $this->config,
37295 $this->process,
37296 $this->remoteFilesystem
37297 );
37298 $this->fallbackDriver->initialize();
37299 }
37300
37301
37302
37303
37304 protected function generateSshUrl()
37305 {
37306 return 'ssh://hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository;
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\Util\ProcessExecutor;
37325 use Composer\Util\Filesystem;
37326 use Composer\IO\IOInterface;
37327
37328
37329
37330
37331 class HgDriver extends VcsDriver
37332 {
37333 protected $tags;
37334 protected $branches;
37335 protected $rootIdentifier;
37336 protected $repoDir;
37337 protected $infoCache = array();
37338
37339
37340
37341
37342 public function initialize()
37343 {
37344 if (Filesystem::isLocalPath($this->url)) {
37345 $this->repoDir = $this->url;
37346 } else {
37347 $cacheDir = $this->config->get('cache-vcs-dir');
37348 $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
37349
37350 $fs = new Filesystem();
37351 $fs->ensureDirectoryExists($cacheDir);
37352
37353 if (!is_writable(dirname($this->repoDir))) {
37354 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.');
37355 }
37356
37357
37358  $this->config->prohibitUrlByConfig($this->url, $this->io);
37359
37360
37361  if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) {
37362 if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) {
37363 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
37364 }
37365 } else {
37366
37367  $fs->removeDirectory($this->repoDir);
37368
37369 if (0 !== $this->process->execute(sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoDir)), $output, $cacheDir)) {
37370 $output = $this->process->getErrorOutput();
37371
37372 if (0 !== $this->process->execute('hg --version', $ignoredOutput)) {
37373 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());
37374 }
37375
37376 throw new \RuntimeException('Failed to clone '.$this->url.', could not read packages from it' . "\n\n" .$output);
37377 }
37378 }
37379 }
37380
37381 $this->getTags();
37382 $this->getBranches();
37383 }
37384
37385
37386
37387
37388 public function getRootIdentifier()
37389 {
37390 if (null === $this->rootIdentifier) {
37391 $this->process->execute(sprintf('hg tip --template "{node}"'), $output, $this->repoDir);
37392 $output = $this->process->splitLines($output);
37393 $this->rootIdentifier = $output[0];
37394 }
37395
37396 return $this->rootIdentifier;
37397 }
37398
37399
37400
37401
37402 public function getUrl()
37403 {
37404 return $this->url;
37405 }
37406
37407
37408
37409
37410 public function getSource($identifier)
37411 {
37412 return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
37413 }
37414
37415
37416
37417
37418 public function getDist($identifier)
37419 {
37420 return null;
37421 }
37422
37423
37424
37425
37426 public function getFileContent($file, $identifier)
37427 {
37428 $resource = sprintf('hg cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
37429 $this->process->execute($resource, $content, $this->repoDir);
37430
37431 if (!trim($content)) {
37432 return;
37433 }
37434
37435 return $content;
37436 }
37437
37438
37439
37440
37441 public function getChangeDate($identifier)
37442 {
37443 $this->process->execute(
37444 sprintf(
37445 'hg log --template "{date|rfc3339date}" -r %s',
37446 ProcessExecutor::escape($identifier)
37447 ),
37448 $output,
37449 $this->repoDir
37450 );
37451
37452 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
37453 }
37454
37455
37456
37457
37458 public function getTags()
37459 {
37460 if (null === $this->tags) {
37461 $tags = array();
37462
37463 $this->process->execute('hg tags', $output, $this->repoDir);
37464 foreach ($this->process->splitLines($output) as $tag) {
37465 if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
37466 $tags[$match[1]] = $match[2];
37467 }
37468 }
37469 unset($tags['tip']);
37470
37471 $this->tags = $tags;
37472 }
37473
37474 return $this->tags;
37475 }
37476
37477
37478
37479
37480 public function getBranches()
37481 {
37482 if (null === $this->branches) {
37483 $branches = array();
37484 $bookmarks = array();
37485
37486 $this->process->execute('hg branches', $output, $this->repoDir);
37487 foreach ($this->process->splitLines($output) as $branch) {
37488 if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) {
37489 $branches[$match[1]] = $match[2];
37490 }
37491 }
37492
37493 $this->process->execute('hg bookmarks', $output, $this->repoDir);
37494 foreach ($this->process->splitLines($output) as $branch) {
37495 if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) {
37496 $bookmarks[$match[1]] = $match[2];
37497 }
37498 }
37499
37500
37501  $this->branches = array_merge($bookmarks, $branches);
37502 }
37503
37504 return $this->branches;
37505 }
37506
37507
37508
37509
37510 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37511 {
37512 if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
37513 return true;
37514 }
37515
37516
37517  if (Filesystem::isLocalPath($url)) {
37518 $url = Filesystem::getPlatformPath($url);
37519 if (!is_dir($url)) {
37520 return false;
37521 }
37522
37523 $process = new ProcessExecutor();
37524
37525  if ($process->execute('hg summary', $output, $url) === 0) {
37526 return true;
37527 }
37528 }
37529
37530 if (!$deep) {
37531 return false;
37532 }
37533
37534 $processExecutor = new ProcessExecutor();
37535 $exit = $processExecutor->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);
37536
37537 return $exit === 0;
37538 }
37539 }
37540 <?php
37541
37542
37543
37544
37545
37546
37547
37548
37549
37550
37551
37552 namespace Composer\Repository\Vcs;
37553
37554 use Composer\Config;
37555 use Composer\IO\IOInterface;
37556 use Composer\Util\ProcessExecutor;
37557 use Composer\Util\Perforce;
37558
37559
37560
37561
37562 class PerforceDriver extends VcsDriver
37563 {
37564 protected $depot;
37565 protected $branch;
37566
37567 protected $perforce;
37568
37569
37570
37571
37572 public function initialize()
37573 {
37574 $this->depot = $this->repoConfig['depot'];
37575 $this->branch = '';
37576 if (!empty($this->repoConfig['branch'])) {
37577 $this->branch = $this->repoConfig['branch'];
37578 }
37579
37580 $this->initPerforce($this->repoConfig);
37581 $this->perforce->p4Login();
37582 $this->perforce->checkStream();
37583
37584 $this->perforce->writeP4ClientSpec();
37585 $this->perforce->connectClient();
37586
37587 return true;
37588 }
37589
37590 private function initPerforce($repoConfig)
37591 {
37592 if (!empty($this->perforce)) {
37593 return;
37594 }
37595
37596 $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
37597 $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
37598 }
37599
37600
37601
37602
37603 public function getFileContent($file, $identifier)
37604 {
37605 return $this->perforce->getFileContent($file, $identifier);
37606 }
37607
37608
37609
37610
37611 public function getChangeDate($identifier)
37612 {
37613 return null;
37614 }
37615
37616
37617
37618
37619 public function getRootIdentifier()
37620 {
37621 return $this->branch;
37622 }
37623
37624
37625
37626
37627 public function getBranches()
37628 {
37629 return $this->perforce->getBranches();
37630 }
37631
37632
37633
37634
37635 public function getTags()
37636 {
37637 return $this->perforce->getTags();
37638 }
37639
37640
37641
37642
37643 public function getDist($identifier)
37644 {
37645 return null;
37646 }
37647
37648
37649
37650
37651 public function getSource($identifier)
37652 {
37653 $source = array(
37654 'type' => 'perforce',
37655 'url' => $this->repoConfig['url'],
37656 'reference' => $identifier,
37657 'p4user' => $this->perforce->getUser(),
37658 );
37659
37660 return $source;
37661 }
37662
37663
37664
37665
37666 public function getUrl()
37667 {
37668 return $this->url;
37669 }
37670
37671
37672
37673
37674 public function hasComposerFile($identifier)
37675 {
37676 $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
37677 $composerInfoIdentifier = $identifier;
37678
37679 return !empty($composerInfo);
37680 }
37681
37682
37683
37684
37685 public function getContents($url)
37686 {
37687 return false;
37688 }
37689
37690
37691
37692
37693 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37694 {
37695 if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) {
37696 return Perforce::checkServerExists($url, new ProcessExecutor($io));
37697 }
37698
37699 return false;
37700 }
37701
37702
37703
37704
37705 public function cleanup()
37706 {
37707 $this->perforce->cleanupClientSpec();
37708 $this->perforce = null;
37709 }
37710
37711 public function getDepot()
37712 {
37713 return $this->depot;
37714 }
37715
37716 public function getBranch()
37717 {
37718 return $this->branch;
37719 }
37720 }
37721 <?php
37722
37723
37724
37725
37726
37727
37728
37729
37730
37731
37732
37733 namespace Composer\Repository\Vcs;
37734
37735 use Composer\Cache;
37736 use Composer\Config;
37737 use Composer\Json\JsonFile;
37738 use Composer\Util\ProcessExecutor;
37739 use Composer\Util\Filesystem;
37740 use Composer\Util\Svn as SvnUtil;
37741 use Composer\IO\IOInterface;
37742 use Composer\Downloader\TransportException;
37743
37744
37745
37746
37747
37748 class SvnDriver extends VcsDriver
37749 {
37750
37751
37752
37753 protected $cache;
37754 protected $baseUrl;
37755 protected $tags;
37756 protected $branches;
37757 protected $rootIdentifier;
37758 protected $infoCache = array();
37759
37760 protected $trunkPath = 'trunk';
37761 protected $branchesPath = 'branches';
37762 protected $tagsPath = 'tags';
37763 protected $packagePath = '';
37764 protected $cacheCredentials = true;
37765
37766
37767
37768
37769 private $util;
37770
37771
37772
37773
37774 public function initialize()
37775 {
37776 $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
37777
37778 SvnUtil::cleanEnv();
37779
37780 if (isset($this->repoConfig['trunk-path'])) {
37781 $this->trunkPath = $this->repoConfig['trunk-path'];
37782 }
37783 if (isset($this->repoConfig['branches-path'])) {
37784 $this->branchesPath = $this->repoConfig['branches-path'];
37785 }
37786 if (isset($this->repoConfig['tags-path'])) {
37787 $this->tagsPath = $this->repoConfig['tags-path'];
37788 }
37789 if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
37790 $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
37791 }
37792 if (isset($this->repoConfig['package-path'])) {
37793 $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
37794 }
37795
37796 if (false !== ($pos = strrpos($this->url, '/' . $this->trunkPath))) {
37797 $this->baseUrl = substr($this->url, 0, $pos);
37798 }
37799
37800 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl));
37801
37802 $this->getBranches();
37803 $this->getTags();
37804 }
37805
37806
37807
37808
37809 public function getRootIdentifier()
37810 {
37811 return $this->rootIdentifier ?: $this->trunkPath;
37812 }
37813
37814
37815
37816
37817 public function getUrl()
37818 {
37819 return $this->url;
37820 }
37821
37822
37823
37824
37825 public function getSource($identifier)
37826 {
37827 return array('type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier);
37828 }
37829
37830
37831
37832
37833 public function getDist($identifier)
37834 {
37835 return null;
37836 }
37837
37838
37839
37840
37841 public function getComposerInformation($identifier)
37842 {
37843 if (!isset($this->infoCache[$identifier])) {
37844 if ($res = $this->cache->read($identifier.'.json')) {
37845 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37846 }
37847
37848 $composer = $this->getBaseComposerInformation($identifier);
37849
37850 $this->cache->write($identifier.'.json', json_encode($composer));
37851
37852 $this->infoCache[$identifier] = $composer;
37853 }
37854
37855 return $this->infoCache[$identifier];
37856 }
37857
37858
37859
37860
37861
37862 public function getFileContent($file, $identifier)
37863 {
37864 $identifier = '/' . trim($identifier, '/') . '/';
37865
37866 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
37867 if (!empty($match[2])) {
37868 $path = $match[1];
37869 $rev = $match[2];
37870 } else {
37871 $path = $identifier;
37872 $rev = '';
37873 }
37874
37875 try {
37876 $resource = $path.$file;
37877 $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
37878 if (!trim($output)) {
37879 return null;
37880 }
37881 } catch (\RuntimeException $e) {
37882 throw new TransportException($e->getMessage());
37883 }
37884
37885 return $output;
37886 }
37887
37888
37889
37890
37891 public function getChangeDate($identifier)
37892 {
37893 $identifier = '/' . trim($identifier, '/') . '/';
37894
37895 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
37896 if (!empty($match[2])) {
37897 $path = $match[1];
37898 $rev = $match[2];
37899 } else {
37900 $path = $identifier;
37901 $rev = '';
37902 }
37903
37904 $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
37905 foreach ($this->process->splitLines($output) as $line) {
37906 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
37907 return new \DateTime($match[1], new \DateTimeZone('UTC'));
37908 }
37909 }
37910
37911 return null;
37912 }
37913
37914
37915
37916
37917 public function getTags()
37918 {
37919 if (null === $this->tags) {
37920 $this->tags = array();
37921
37922 if ($this->tagsPath !== false) {
37923 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
37924 if ($output) {
37925 foreach ($this->process->splitLines($output) as $line) {
37926 $line = trim($line);
37927 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37928 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
37929 $this->tags[rtrim($match[2], '/')] = $this->buildIdentifier(
37930 '/' . $this->tagsPath . '/' . $match[2],
37931 $match[1]
37932 );
37933 }
37934 }
37935 }
37936 }
37937 }
37938 }
37939
37940 return $this->tags;
37941 }
37942
37943
37944
37945
37946 public function getBranches()
37947 {
37948 if (null === $this->branches) {
37949 $this->branches = array();
37950
37951 if (false === $this->trunkPath) {
37952 $trunkParent = $this->baseUrl . '/';
37953 } else {
37954 $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
37955 }
37956
37957 $output = $this->execute('svn ls --verbose', $trunkParent);
37958 if ($output) {
37959 foreach ($this->process->splitLines($output) as $line) {
37960 $line = trim($line);
37961 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37962 if (isset($match[1]) && isset($match[2]) && $match[2] === './') {
37963 $this->branches['trunk'] = $this->buildIdentifier(
37964 '/' . $this->trunkPath,
37965 $match[1]
37966 );
37967 $this->rootIdentifier = $this->branches['trunk'];
37968 break;
37969 }
37970 }
37971 }
37972 }
37973 unset($output);
37974
37975 if ($this->branchesPath !== false) {
37976 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
37977 if ($output) {
37978 foreach ($this->process->splitLines(trim($output)) as $line) {
37979 $line = trim($line);
37980 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37981 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
37982 $this->branches[rtrim($match[2], '/')] = $this->buildIdentifier(
37983 '/' . $this->branchesPath . '/' . $match[2],
37984 $match[1]
37985 );
37986 }
37987 }
37988 }
37989 }
37990 }
37991 }
37992
37993 return $this->branches;
37994 }
37995
37996
37997
37998
37999 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38000 {
38001 $url = self::normalizeUrl($url);
38002 if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
38003 return true;
38004 }
38005
38006
38007  if (!$deep && !Filesystem::isLocalPath($url)) {
38008 return false;
38009 }
38010
38011 $processExecutor = new ProcessExecutor();
38012
38013 $exit = $processExecutor->execute(
38014 "svn info --non-interactive {$url}",
38015 $ignoredOutput
38016 );
38017
38018 if ($exit === 0) {
38019
38020  return true;
38021 }
38022
38023
38024  if (false !== stripos($processExecutor->getErrorOutput(), 'authorization failed:')) {
38025
38026  
38027  return true;
38028 }
38029
38030
38031  if (false !== stripos($processExecutor->getErrorOutput(), 'Authentication failed')) {
38032
38033  
38034  return true;
38035 }
38036
38037 return false;
38038 }
38039
38040
38041
38042
38043
38044
38045
38046
38047 protected static function normalizeUrl($url)
38048 {
38049 $fs = new Filesystem();
38050 if ($fs->isAbsolutePath($url)) {
38051 return 'file://' . strtr($url, '\\', '/');
38052 }
38053
38054 return $url;
38055 }
38056
38057
38058
38059
38060
38061
38062
38063
38064
38065
38066 protected function execute($command, $url)
38067 {
38068 if (null === $this->util) {
38069 $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
38070 $this->util->setCacheCredentials($this->cacheCredentials);
38071 }
38072
38073 try {
38074 return $this->util->execute($command, $url);
38075 } catch (\RuntimeException $e) {
38076 if (0 !== $this->process->execute('svn --version', $ignoredOutput)) {
38077 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());
38078 }
38079
38080 throw new \RuntimeException(
38081 'Repository '.$this->url.' could not be processed, '.$e->getMessage()
38082 );
38083 }
38084 }
38085
38086
38087
38088
38089
38090
38091
38092
38093
38094 protected function buildIdentifier($baseDir, $revision)
38095 {
38096 return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
38097 }
38098 }
38099 <?php
38100
38101
38102
38103
38104
38105
38106
38107
38108
38109
38110
38111 namespace Composer\Repository\Vcs;
38112
38113 use Composer\Cache;
38114 use Composer\Downloader\TransportException;
38115 use Composer\Config;
38116 use Composer\Factory;
38117 use Composer\IO\IOInterface;
38118 use Composer\Json\JsonFile;
38119 use Composer\Util\ProcessExecutor;
38120 use Composer\Util\RemoteFilesystem;
38121 use Composer\Util\Filesystem;
38122
38123
38124
38125
38126
38127
38128 abstract class VcsDriver implements VcsDriverInterface
38129 {
38130
38131 protected $url;
38132
38133 protected $originUrl;
38134
38135 protected $repoConfig;
38136
38137 protected $io;
38138
38139 protected $config;
38140
38141 protected $process;
38142
38143 protected $remoteFilesystem;
38144
38145 protected $infoCache = array();
38146
38147 protected $cache;
38148
38149
38150
38151
38152
38153
38154
38155
38156
38157
38158 final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
38159 {
38160 if (Filesystem::isLocalPath($repoConfig['url'])) {
38161 $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
38162 }
38163
38164 $this->url = $repoConfig['url'];
38165 $this->originUrl = $repoConfig['url'];
38166 $this->repoConfig = $repoConfig;
38167 $this->io = $io;
38168 $this->config = $config;
38169 $this->process = $process ?: new ProcessExecutor($io);
38170 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
38171 }
38172
38173
38174
38175
38176
38177
38178
38179 protected function shouldCache($identifier)
38180 {
38181 return $this->cache && preg_match('{[a-f0-9]{40}}i', $identifier);
38182 }
38183
38184
38185
38186
38187 public function getComposerInformation($identifier)
38188 {
38189 if (!isset($this->infoCache[$identifier])) {
38190 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
38191 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
38192 }
38193
38194 $composer = $this->getBaseComposerInformation($identifier);
38195
38196 if ($this->shouldCache($identifier)) {
38197 $this->cache->write($identifier, json_encode($composer));
38198 }
38199
38200 $this->infoCache[$identifier] = $composer;
38201 }
38202
38203 return $this->infoCache[$identifier];
38204 }
38205
38206 protected function getBaseComposerInformation($identifier)
38207 {
38208 $composerFileContent = $this->getFileContent('composer.json', $identifier);
38209
38210 if (!$composerFileContent) {
38211 return null;
38212 }
38213
38214 $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json');
38215
38216 if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) {
38217 $composer['time'] = $changeDate->format(DATE_RFC3339);
38218 }
38219
38220 return $composer;
38221 }
38222
38223
38224
38225
38226 public function hasComposerFile($identifier)
38227 {
38228 try {
38229 return (bool) $this->getComposerInformation($identifier);
38230 } catch (TransportException $e) {
38231 }
38232
38233 return false;
38234 }
38235
38236
38237
38238
38239
38240
38241
38242
38243 protected function getScheme()
38244 {
38245 if (extension_loaded('openssl')) {
38246 return 'https';
38247 }
38248
38249 return 'http';
38250 }
38251
38252
38253
38254
38255
38256
38257
38258
38259 protected function getContents($url)
38260 {
38261 $options = isset($this->repoConfig['options']) ? $this->repoConfig['options'] : array();
38262
38263 return $this->remoteFilesystem->getContents($this->originUrl, $url, false, $options);
38264 }
38265
38266
38267
38268
38269 public function cleanup()
38270 {
38271 return;
38272 }
38273 }
38274 <?php
38275
38276
38277
38278
38279
38280
38281
38282
38283
38284
38285
38286 namespace Composer\Repository\Vcs;
38287
38288 use Composer\Config;
38289 use Composer\IO\IOInterface;
38290
38291
38292
38293
38294 interface VcsDriverInterface
38295 {
38296
38297
38298
38299 public function initialize();
38300
38301
38302
38303
38304
38305
38306
38307 public function getComposerInformation($identifier);
38308
38309
38310
38311
38312
38313
38314
38315
38316 public function getFileContent($file, $identifier);
38317
38318
38319
38320
38321
38322
38323
38324 public function getChangeDate($identifier);
38325
38326
38327
38328
38329
38330
38331 public function getRootIdentifier();
38332
38333
38334
38335
38336
38337
38338 public function getBranches();
38339
38340
38341
38342
38343
38344
38345 public function getTags();
38346
38347
38348
38349
38350
38351 public function getDist($identifier);
38352
38353
38354
38355
38356
38357 public function getSource($identifier);
38358
38359
38360
38361
38362
38363
38364 public function getUrl();
38365
38366
38367
38368
38369
38370
38371
38372
38373 public function hasComposerFile($identifier);
38374
38375
38376
38377
38378 public function cleanup();
38379
38380
38381
38382
38383
38384
38385
38386
38387
38388
38389 public static function supports(IOInterface $io, Config $config, $url, $deep = false);
38390 }
38391 <?php
38392
38393
38394
38395
38396
38397
38398
38399
38400
38401
38402
38403 namespace Composer\Repository;
38404
38405 use Composer\Downloader\TransportException;
38406 use Composer\Repository\Vcs\VcsDriverInterface;
38407 use Composer\Package\Version\VersionParser;
38408 use Composer\Package\Loader\ArrayLoader;
38409 use Composer\Package\Loader\ValidatingArrayLoader;
38410 use Composer\Package\Loader\InvalidPackageException;
38411 use Composer\Package\Loader\LoaderInterface;
38412 use Composer\EventDispatcher\EventDispatcher;
38413 use Composer\IO\IOInterface;
38414 use Composer\Config;
38415
38416
38417
38418
38419 class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInterface
38420 {
38421 protected $url;
38422 protected $packageName;
38423 protected $verbose;
38424 protected $io;
38425 protected $config;
38426 protected $versionParser;
38427 protected $type;
38428 protected $loader;
38429 protected $repoConfig;
38430 protected $branchErrorOccurred = false;
38431 private $drivers;
38432
38433 private $driver;
38434
38435 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null)
38436 {
38437 parent::__construct();
38438 $this->drivers = $drivers ?: array(
38439 'github' => 'Composer\Repository\Vcs\GitHubDriver',
38440 'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
38441 'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
38442 'git' => 'Composer\Repository\Vcs\GitDriver',
38443 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver',
38444 'hg' => 'Composer\Repository\Vcs\HgDriver',
38445 'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
38446 'fossil' => 'Composer\Repository\Vcs\FossilDriver',
38447
38448  'svn' => 'Composer\Repository\Vcs\SvnDriver',
38449 );
38450
38451 $this->url = $repoConfig['url'];
38452 $this->io = $io;
38453 $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
38454 $this->verbose = $io->isVeryVerbose();
38455 $this->config = $config;
38456 $this->repoConfig = $repoConfig;
38457 }
38458
38459 public function getRepoConfig()
38460 {
38461 return $this->repoConfig;
38462 }
38463
38464 public function setLoader(LoaderInterface $loader)
38465 {
38466 $this->loader = $loader;
38467 }
38468
38469 public function getDriver()
38470 {
38471 if ($this->driver) {
38472 return $this->driver;
38473 }
38474
38475 if (isset($this->drivers[$this->type])) {
38476 $class = $this->drivers[$this->type];
38477 $this->driver = new $class($this->repoConfig, $this->io, $this->config);
38478 $this->driver->initialize();
38479
38480 return $this->driver;
38481 }
38482
38483 foreach ($this->drivers as $driver) {
38484 if ($driver::supports($this->io, $this->config, $this->url)) {
38485 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
38486 $this->driver->initialize();
38487
38488 return $this->driver;
38489 }
38490 }
38491
38492 foreach ($this->drivers as $driver) {
38493 if ($driver::supports($this->io, $this->config, $this->url, true)) {
38494 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
38495 $this->driver->initialize();
38496
38497 return $this->driver;
38498 }
38499 }
38500 }
38501
38502 public function hadInvalidBranches()
38503 {
38504 return $this->branchErrorOccurred;
38505 }
38506
38507 protected function initialize()
38508 {
38509 parent::initialize();
38510
38511 $verbose = $this->verbose;
38512
38513 $driver = $this->getDriver();
38514 if (!$driver) {
38515 throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url);
38516 }
38517
38518 $this->versionParser = new VersionParser;
38519 if (!$this->loader) {
38520 $this->loader = new ArrayLoader($this->versionParser);
38521 }
38522
38523 try {
38524 if ($driver->hasComposerFile($driver->getRootIdentifier())) {
38525 $data = $driver->getComposerInformation($driver->getRootIdentifier());
38526 $this->packageName = !empty($data['name']) ? $data['name'] : null;
38527 }
38528 } catch (\Exception $e) {
38529 if ($verbose) {
38530 $this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
38531 }
38532 }
38533
38534 foreach ($driver->getTags() as $tag => $identifier) {
38535 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
38536 if ($verbose) {
38537 $this->io->writeError($msg);
38538 } else {
38539 $this->io->overwriteError($msg, false);
38540 }
38541
38542
38543  $tag = str_replace('release-', '', $tag);
38544
38545 if (!$parsedTag = $this->validateTag($tag)) {
38546 if ($verbose) {
38547 $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
38548 }
38549 continue;
38550 }
38551
38552 try {
38553 if (!$data = $driver->getComposerInformation($identifier)) {
38554 if ($verbose) {
38555 $this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
38556 }
38557 continue;
38558 }
38559
38560
38561  if (isset($data['version'])) {
38562 $data['version_normalized'] = $this->versionParser->normalize($data['version']);
38563 } else {
38564
38565  $data['version'] = $tag;
38566 $data['version_normalized'] = $parsedTag;
38567 }
38568
38569
38570  $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']);
38571 $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
38572
38573
38574  if ($data['version_normalized'] !== $parsedTag) {
38575 if ($verbose) {
38576 $this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
38577 }
38578 continue;
38579 }
38580
38581 if ($verbose) {
38582 $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
38583 }
38584
38585 $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
38586 } catch (\Exception $e) {
38587 if ($verbose) {
38588 $this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
38589 }
38590 continue;
38591 }
38592 }
38593
38594 if (!$verbose) {
38595 $this->io->overwriteError('', false);
38596 }
38597
38598 foreach ($driver->getBranches() as $branch => $identifier) {
38599 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
38600 if ($verbose) {
38601 $this->io->writeError($msg);
38602 } else {
38603 $this->io->overwriteError($msg, false);
38604 }
38605
38606 if (!$parsedBranch = $this->validateBranch($branch)) {
38607 if ($verbose) {
38608 $this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
38609 }
38610 continue;
38611 }
38612
38613 try {
38614 if (!$data = $driver->getComposerInformation($identifier)) {
38615 if ($verbose) {
38616 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
38617 }
38618 continue;
38619 }
38620
38621
38622  $data['version'] = $branch;
38623 $data['version_normalized'] = $parsedBranch;
38624
38625
38626  if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
38627 $data['version'] = 'dev-' . $data['version'];
38628 } else {
38629 $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
38630 $data['version'] = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
38631 }
38632
38633 if ($verbose) {
38634 $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
38635 }
38636
38637 $packageData = $this->preProcess($driver, $data, $identifier);
38638 $package = $this->loader->load($packageData);
38639 if ($this->loader instanceof ValidatingArrayLoader && $this->loader->getWarnings()) {
38640 throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
38641 }
38642 $this->addPackage($package);
38643 } catch (TransportException $e) {
38644 if ($verbose) {
38645 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
38646 }
38647 continue;
38648 } catch (\Exception $e) {
38649 if (!$verbose) {
38650 $this->io->writeError('');
38651 }
38652 $this->branchErrorOccurred = true;
38653 $this->io->writeError('<error>Skipped branch '.$branch.', '.$e->getMessage().'</error>');
38654 $this->io->writeError('');
38655 continue;
38656 }
38657 }
38658 $driver->cleanup();
38659
38660 if (!$verbose) {
38661 $this->io->overwriteError('', false);
38662 }
38663
38664 if (!$this->getPackages()) {
38665 throw new InvalidRepositoryException('No valid composer.json was found in any branch or tag of '.$this->url.', could not load a package from it.');
38666 }
38667 }
38668
38669 protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
38670 {
38671
38672  $data['name'] = $this->packageName ?: $data['name'];
38673
38674 if (!isset($data['dist'])) {
38675 $data['dist'] = $driver->getDist($identifier);
38676 }
38677 if (!isset($data['source'])) {
38678 $data['source'] = $driver->getSource($identifier);
38679 }
38680
38681 return $data;
38682 }
38683
38684 private function validateBranch($branch)
38685 {
38686 try {
38687 return $this->versionParser->normalizeBranch($branch);
38688 } catch (\Exception $e) {
38689 }
38690
38691 return false;
38692 }
38693
38694 private function validateTag($version)
38695 {
38696 try {
38697 return $this->versionParser->normalize($version);
38698 } catch (\Exception $e) {
38699 }
38700
38701 return false;
38702 }
38703 }
38704 <?php
38705
38706
38707
38708
38709
38710
38711
38712
38713
38714
38715
38716 namespace Composer\Repository;
38717
38718 use Composer\Package\AliasPackage;
38719
38720
38721
38722
38723
38724
38725 class WritableArrayRepository extends ArrayRepository implements WritableRepositoryInterface
38726 {
38727
38728
38729
38730 public function write()
38731 {
38732 }
38733
38734
38735
38736
38737 public function reload()
38738 {
38739 }
38740
38741
38742
38743
38744 public function getCanonicalPackages()
38745 {
38746 $packages = $this->getPackages();
38747
38748
38749  $packagesByName = array();
38750 foreach ($packages as $package) {
38751 if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
38752 $packagesByName[$package->getName()] = $package;
38753 }
38754 }
38755
38756 $canonicalPackages = array();
38757
38758
38759  foreach ($packagesByName as $package) {
38760 while ($package instanceof AliasPackage) {
38761 $package = $package->getAliasOf();
38762 }
38763
38764 $canonicalPackages[] = $package;
38765 }
38766
38767 return $canonicalPackages;
38768 }
38769 }
38770 <?php
38771
38772
38773
38774
38775
38776
38777
38778
38779
38780
38781
38782 namespace Composer\Repository;
38783
38784 use Composer\Package\PackageInterface;
38785
38786
38787
38788
38789
38790
38791 interface WritableRepositoryInterface extends RepositoryInterface
38792 {
38793
38794
38795
38796 public function write();
38797
38798
38799
38800
38801
38802
38803 public function addPackage(PackageInterface $package);
38804
38805
38806
38807
38808
38809
38810 public function removePackage(PackageInterface $package);
38811
38812
38813
38814
38815
38816
38817 public function getCanonicalPackages();
38818
38819
38820
38821
38822 public function reload();
38823 }
38824 <?php
38825
38826
38827
38828
38829
38830
38831
38832
38833
38834
38835
38836 namespace Composer\Script;
38837
38838
38839
38840
38841
38842
38843 class CommandEvent extends Event
38844 {
38845 }
38846 <?php
38847
38848
38849
38850
38851
38852
38853
38854
38855
38856
38857
38858 namespace Composer\Script;
38859
38860 use Composer\Composer;
38861 use Composer\IO\IOInterface;
38862 use Composer\EventDispatcher\Event as BaseEvent;
38863
38864
38865
38866
38867
38868
38869
38870 class Event extends BaseEvent
38871 {
38872
38873
38874
38875 private $composer;
38876
38877
38878
38879
38880 private $io;
38881
38882
38883
38884
38885 private $devMode;
38886
38887
38888
38889
38890
38891
38892
38893
38894
38895
38896
38897 public function __construct($name, Composer $composer, IOInterface $io, $devMode = false, array $args = array(), array $flags = array())
38898 {
38899 parent::__construct($name, $args, $flags);
38900 $this->composer = $composer;
38901 $this->io = $io;
38902 $this->devMode = $devMode;
38903 }
38904
38905
38906
38907
38908
38909
38910 public function getComposer()
38911 {
38912 return $this->composer;
38913 }
38914
38915
38916
38917
38918
38919
38920 public function getIO()
38921 {
38922 return $this->io;
38923 }
38924
38925
38926
38927
38928
38929
38930 public function isDevMode()
38931 {
38932 return $this->devMode;
38933 }
38934 }
38935 <?php
38936
38937
38938
38939
38940
38941
38942
38943
38944
38945
38946
38947 namespace Composer\Script;
38948
38949 use Composer\Installer\PackageEvent as BasePackageEvent;
38950
38951
38952
38953
38954
38955
38956 class PackageEvent extends BasePackageEvent
38957 {
38958 }
38959 <?php
38960
38961
38962
38963
38964
38965
38966
38967
38968
38969
38970
38971 namespace Composer\Script;
38972
38973
38974
38975
38976
38977
38978
38979 class ScriptEvents
38980 {
38981
38982
38983
38984
38985
38986
38987
38988 const PRE_INSTALL_CMD = 'pre-install-cmd';
38989
38990
38991
38992
38993
38994
38995
38996
38997 const POST_INSTALL_CMD = 'post-install-cmd';
38998
38999
39000
39001
39002
39003
39004
39005
39006 const PRE_UPDATE_CMD = 'pre-update-cmd';
39007
39008
39009
39010
39011
39012
39013
39014
39015 const POST_UPDATE_CMD = 'post-update-cmd';
39016
39017
39018
39019
39020
39021
39022
39023
39024 const PRE_STATUS_CMD = 'pre-status-cmd';
39025
39026
39027
39028
39029
39030
39031
39032
39033 const POST_STATUS_CMD = 'post-status-cmd';
39034
39035
39036
39037
39038
39039
39040
39041
39042 const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
39043
39044
39045
39046
39047
39048
39049
39050
39051 const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
39052
39053
39054
39055
39056
39057
39058
39059
39060 const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
39061
39062
39063
39064
39065
39066
39067
39068
39069
39070 const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
39071
39072
39073
39074
39075
39076
39077
39078
39079 const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
39080
39081
39082
39083
39084
39085
39086
39087
39088 const POST_ARCHIVE_CMD = 'post-archive-cmd';
39089
39090
39091
39092
39093
39094
39095
39096
39097
39098
39099
39100 const PRE_PACKAGE_INSTALL = 'pre-package-install';
39101
39102
39103
39104
39105
39106
39107
39108
39109
39110 const POST_PACKAGE_INSTALL = 'post-package-install';
39111
39112
39113
39114
39115
39116
39117
39118
39119
39120 const PRE_PACKAGE_UPDATE = 'pre-package-update';
39121
39122
39123
39124
39125
39126
39127
39128
39129
39130 const POST_PACKAGE_UPDATE = 'post-package-update';
39131
39132
39133
39134
39135
39136
39137
39138
39139
39140 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
39141
39142
39143
39144
39145
39146
39147
39148
39149
39150 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
39151 }
39152 <?php
39153
39154
39155
39156
39157
39158
39159
39160
39161
39162
39163
39164 namespace Composer\SelfUpdate;
39165
39166
39167
39168
39169 class Keys
39170 {
39171 public static function fingerprint($path)
39172 {
39173 $hash = strtoupper(hash('sha256', preg_replace('{\s}', '', file_get_contents($path))));
39174
39175 return implode(' ', array(
39176 substr($hash, 0, 8),
39177 substr($hash, 8, 8),
39178 substr($hash, 16, 8),
39179 substr($hash, 24, 8),
39180 '', 
39181  substr($hash, 32, 8),
39182 substr($hash, 40, 8),
39183 substr($hash, 48, 8),
39184 substr($hash, 56, 8),
39185 ));
39186 }
39187 }
39188 <?php
39189
39190
39191
39192
39193
39194
39195
39196
39197
39198
39199
39200 namespace Composer\SelfUpdate;
39201
39202 use Composer\Util\RemoteFilesystem;
39203 use Composer\Config;
39204 use Composer\Json\JsonFile;
39205
39206
39207
39208
39209 class Versions
39210 {
39211 private $rfs;
39212 private $config;
39213 private $channel;
39214
39215 public function __construct(Config $config, RemoteFilesystem $rfs)
39216 {
39217 $this->rfs = $rfs;
39218 $this->config = $config;
39219 }
39220
39221 public function getChannel()
39222 {
39223 if ($this->channel) {
39224 return $this->channel;
39225 }
39226
39227 $channelFile = $this->config->get('home').'/update-channel';
39228 if (file_exists($channelFile)) {
39229 $channel = trim(file_get_contents($channelFile));
39230 if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
39231 return $this->channel = $channel;
39232 }
39233 }
39234
39235 return $this->channel = 'stable';
39236 }
39237
39238 public function setChannel($channel)
39239 {
39240 if (!in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
39241 throw new \InvalidArgumentException('Invalid channel '.$channel.', must be one of: stable, preview, snapshot');
39242 }
39243
39244 $channelFile = $this->config->get('home').'/update-channel';
39245 $this->channel = $channel;
39246 file_put_contents($channelFile, $channel.PHP_EOL);
39247 }
39248
39249 public function getLatest()
39250 {
39251 $protocol = extension_loaded('openssl') ? 'https' : 'http';
39252 $versions = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false));
39253
39254 foreach ($versions[$this->getChannel()] as $version) {
39255 if ($version['min-php'] <= PHP_VERSION_ID) {
39256 return $version;
39257 }
39258 }
39259
39260 throw new \LogicException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')');
39261 }
39262 }
39263 <?php
39264
39265
39266
39267
39268
39269
39270
39271
39272
39273
39274
39275 namespace Composer\Util;
39276
39277 use Composer\Config;
39278 use Composer\IO\IOInterface;
39279
39280
39281
39282
39283 class AuthHelper
39284 {
39285 protected $io;
39286 protected $config;
39287
39288 public function __construct(IOInterface $io, Config $config)
39289 {
39290 $this->io = $io;
39291 $this->config = $config;
39292 }
39293
39294 public function storeAuth($originUrl, $storeAuth)
39295 {
39296 $store = false;
39297 $configSource = $this->config->getAuthConfigSource();
39298 if ($storeAuth === true) {
39299 $store = $configSource;
39300 } elseif ($storeAuth === 'prompt') {
39301 $answer = $this->io->askAndValidate(
39302 'Do you want to store credentials for '.$originUrl.' in '.$configSource->getName().' ? [Yn] ',
39303 function ($value) {
39304 $input = strtolower(substr(trim($value), 0, 1));
39305 if (in_array($input, array('y','n'))) {
39306 return $input;
39307 }
39308 throw new \RuntimeException('Please answer (y)es or (n)o');
39309 },
39310 null,
39311 'y'
39312 );
39313
39314 if ($answer === 'y') {
39315 $store = $configSource;
39316 }
39317 }
39318 if ($store) {
39319 $store->addConfigSetting(
39320 'http-basic.'.$originUrl,
39321 $this->io->getAuthentication($originUrl)
39322 );
39323 }
39324 }
39325 }
39326 <?php
39327
39328
39329
39330
39331
39332
39333
39334
39335
39336
39337
39338 namespace Composer\Util;
39339
39340 use Composer\Factory;
39341 use Composer\IO\IOInterface;
39342 use Composer\Config;
39343 use Composer\Downloader\TransportException;
39344
39345
39346
39347
39348 class Bitbucket
39349 {
39350 private $io;
39351 private $config;
39352 private $process;
39353 private $remoteFilesystem;
39354 private $token = array();
39355 private $time;
39356
39357 const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
39358
39359
39360
39361
39362
39363
39364
39365
39366
39367
39368 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null, $time = null)
39369 {
39370 $this->io = $io;
39371 $this->config = $config;
39372 $this->process = $process ?: new ProcessExecutor;
39373 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
39374 $this->time = $time;
39375 }
39376
39377
39378
39379
39380 public function getToken()
39381 {
39382 if (!isset($this->token['access_token'])) {
39383 return '';
39384 }
39385
39386 return $this->token['access_token'];
39387 }
39388
39389
39390
39391
39392
39393
39394
39395 public function authorizeOAuth($originUrl)
39396 {
39397 if ($originUrl !== 'bitbucket.org') {
39398 return false;
39399 }
39400
39401
39402  if (0 === $this->process->execute('git config bitbucket.accesstoken', $output)) {
39403 $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));
39404
39405 return true;
39406 }
39407
39408 return false;
39409 }
39410
39411
39412
39413
39414
39415 private function requestAccessToken($originUrl)
39416 {
39417 try {
39418 $json = $this->remoteFilesystem->getContents($originUrl, self::OAUTH2_ACCESS_TOKEN_URL, false, array(
39419 'retry-auth-failure' => false,
39420 'http' => array(
39421 'method' => 'POST',
39422 'content' => 'grant_type=client_credentials',
39423 ),
39424 ));
39425
39426 $this->token = json_decode($json, true);
39427 } catch (TransportException $e) {
39428 if ($e->getCode() === 400) {
39429 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
39430 $this->io->writeError('This can have two reasons:');
39431 $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
39432 $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
39433
39434 return false;
39435 } elseif (in_array($e->getCode(), array(403, 401))) {
39436 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
39437 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39438
39439 return false;
39440 }
39441
39442 throw $e;
39443 }
39444
39445 return true;
39446 }
39447
39448
39449
39450
39451
39452
39453
39454
39455
39456
39457 public function authorizeOAuthInteractively($originUrl, $message = null)
39458 {
39459 if ($message) {
39460 $this->io->writeError($message);
39461 }
39462
39463 $url = 'https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html';
39464 $this->io->writeError(sprintf('Follow the instructions on %s', $url));
39465 $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
39466 $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)');
39467
39468 $consumerKey = trim($this->io->askAndHideAnswer('Consumer Key (hidden): '));
39469
39470 if (!$consumerKey) {
39471 $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
39472 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39473
39474 return false;
39475 }
39476
39477 $consumerSecret = trim($this->io->askAndHideAnswer('Consumer Secret (hidden): '));
39478
39479 if (!$consumerSecret) {
39480 $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
39481 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39482
39483 return false;
39484 }
39485
39486 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
39487
39488 if (!$this->requestAccessToken($originUrl)) {
39489 return false;
39490 }
39491
39492
39493  $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
39494
39495
39496  $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
39497
39498 $this->io->writeError('<info>Consumer stored successfully.</info>');
39499
39500 return true;
39501 }
39502
39503
39504
39505
39506
39507
39508
39509
39510
39511 public function requestToken($originUrl, $consumerKey, $consumerSecret)
39512 {
39513 if (!empty($this->token) || $this->getTokenFromConfig($originUrl)) {
39514 return $this->token['access_token'];
39515 }
39516
39517 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
39518 if (!$this->requestAccessToken($originUrl)) {
39519 return '';
39520 }
39521
39522 $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
39523
39524 return $this->token['access_token'];
39525 }
39526
39527
39528
39529
39530
39531
39532
39533 private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret)
39534 {
39535 $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
39536
39537 $time = null === $this->time ? time() : $this->time;
39538 $consumer = array(
39539 "consumer-key" => $consumerKey,
39540 "consumer-secret" => $consumerSecret,
39541 "access-token" => $this->token['access_token'],
39542 "access-token-expiration" => $time + $this->token['expires_in'],
39543 );
39544
39545 $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.'.$originUrl, $consumer);
39546 }
39547
39548
39549
39550
39551
39552 private function getTokenFromConfig($originUrl)
39553 {
39554 $authConfig = $this->config->get('bitbucket-oauth');
39555
39556 if (
39557 !isset($authConfig[$originUrl]['access-token'])
39558 || !isset($authConfig[$originUrl]['access-token-expiration'])
39559 || time() > $authConfig[$originUrl]['access-token-expiration']
39560 ) {
39561 return false;
39562 }
39563
39564 $this->token = array(
39565 'access_token' => $authConfig[$originUrl]['access-token'],
39566 );
39567
39568 return true;
39569 }
39570 }
39571 <?php
39572
39573
39574
39575
39576
39577
39578
39579
39580
39581
39582
39583 namespace Composer\Util;
39584
39585
39586
39587
39588
39589
39590 class ComposerMirror
39591 {
39592 public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type)
39593 {
39594 if ($reference) {
39595 $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference);
39596 }
39597 $version = strpos($version, '/') === false ? $version : md5($version);
39598
39599 return str_replace(
39600 array('%package%', '%version%', '%reference%', '%type%'),
39601 array($packageName, $version, $reference, $type),
39602 $mirrorUrl
39603 );
39604 }
39605
39606 public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
39607 {
39608 if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
39609 $url = 'gh-'.$match[1].'/'.$match[2];
39610 } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
39611 $url = 'bb-'.$match[1].'/'.$match[2];
39612 } else {
39613 $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
39614 }
39615
39616 return str_replace(
39617 array('%package%', '%normalizedUrl%', '%type%'),
39618 array($packageName, $url, $type),
39619 $mirrorUrl
39620 );
39621 }
39622
39623 public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
39624 {
39625 return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
39626 }
39627 }
39628 <?php
39629
39630
39631
39632
39633
39634
39635
39636
39637
39638
39639
39640 namespace Composer\Util;
39641
39642 use Composer\Package\Loader\ArrayLoader;
39643 use Composer\Package\Loader\ValidatingArrayLoader;
39644 use Composer\Package\Loader\InvalidPackageException;
39645 use Composer\Json\JsonValidationException;
39646 use Composer\IO\IOInterface;
39647 use Composer\Json\JsonFile;
39648
39649
39650
39651
39652
39653
39654
39655 class ConfigValidator
39656 {
39657 private $io;
39658
39659 public function __construct(IOInterface $io)
39660 {
39661 $this->io = $io;
39662 }
39663
39664
39665
39666
39667
39668
39669
39670
39671
39672 public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL)
39673 {
39674 $errors = array();
39675 $publishErrors = array();
39676 $warnings = array();
39677
39678
39679  $laxValid = false;
39680 try {
39681 $json = new JsonFile($file, null, $this->io);
39682 $manifest = $json->read();
39683
39684 $json->validateSchema(JsonFile::LAX_SCHEMA);
39685 $laxValid = true;
39686 $json->validateSchema();
39687 } catch (JsonValidationException $e) {
39688 foreach ($e->getErrors() as $message) {
39689 if ($laxValid) {
39690 $publishErrors[] = $message;
39691 } else {
39692 $errors[] = $message;
39693 }
39694 }
39695 } catch (\Exception $e) {
39696 $errors[] = $e->getMessage();
39697
39698 return array($errors, $publishErrors, $warnings);
39699 }
39700
39701
39702  if (empty($manifest['license'])) {
39703 $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
39704 }
39705
39706 if (isset($manifest['version'])) {
39707 $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
39708 }
39709
39710 if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) {
39711 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']);
39712 $suggestName = strtolower($suggestName);
39713
39714 $publishErrors[] = sprintf(
39715 '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.',
39716 $manifest['name'],
39717 $suggestName
39718 );
39719 }
39720
39721 if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') {
39722 $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.";
39723 }
39724
39725
39726  if (isset($manifest['require']) && isset($manifest['require-dev'])) {
39727 $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
39728
39729 if (!empty($requireOverrides)) {
39730 $plural = (count($requireOverrides) > 1) ? 'are' : 'is';
39731 $warnings[] = implode(', ', array_keys($requireOverrides)). " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
39732 }
39733 }
39734
39735
39736  $require = isset($manifest['require']) ? $manifest['require'] : array();
39737 $requireDev = isset($manifest['require-dev']) ? $manifest['require-dev'] : array();
39738 $packages = array_merge($require, $requireDev);
39739 foreach ($packages as $package => $version) {
39740 if (preg_match('/#/', $version) === 1) {
39741 $warnings[] = sprintf(
39742 'The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.',
39743 $package
39744 );
39745 }
39746 }
39747
39748
39749  if (isset($manifest['autoload']['psr-0'][''])) {
39750 $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
39751 }
39752 if (isset($manifest['autoload']['psr-4'][''])) {
39753 $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
39754 }
39755
39756 try {
39757 $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags);
39758 if (!isset($manifest['version'])) {
39759 $manifest['version'] = '1.0.0';
39760 }
39761 if (!isset($manifest['name'])) {
39762 $manifest['name'] = 'dummy/dummy';
39763 }
39764 $loader->load($manifest);
39765 } catch (InvalidPackageException $e) {
39766 $errors = array_merge($errors, $e->getErrors());
39767 }
39768
39769 $warnings = array_merge($warnings, $loader->getWarnings());
39770
39771 return array($errors, $publishErrors, $warnings);
39772 }
39773 }
39774 <?php
39775
39776
39777
39778
39779
39780
39781
39782
39783
39784
39785
39786 namespace Composer\Util;
39787
39788 use Composer\IO\IOInterface;
39789
39790
39791
39792
39793
39794
39795 class ErrorHandler
39796 {
39797 private static $io;
39798
39799
39800
39801
39802
39803
39804
39805
39806
39807
39808
39809
39810 public static function handle($level, $message, $file, $line)
39811 {
39812
39813  if (!(error_reporting() & $level)) {
39814 return;
39815 }
39816
39817 if (ini_get('xdebug.scream')) {
39818 $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
39819 "\na legitimately suppressed error that you were not supposed to see.";
39820 }
39821
39822 if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
39823 throw new \ErrorException($message, 0, $level, $file, $line);
39824 }
39825
39826 if (self::$io) {
39827 self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
39828 if (self::$io->isVerbose()) {
39829 self::$io->writeError('<warning>Stack trace:</warning>');
39830 self::$io->writeError(array_filter(array_map(function ($a) {
39831 if (isset($a['line'], $a['file'])) {
39832 return '<warning> '.$a['file'].':'.$a['line'].'</warning>';
39833 }
39834
39835 return null;
39836 }, array_slice(debug_backtrace(), 2))));
39837 }
39838 }
39839 }
39840
39841
39842
39843
39844
39845
39846 public static function register(IOInterface $io = null)
39847 {
39848 set_error_handler(array(__CLASS__, 'handle'));
39849 error_reporting(E_ALL | E_STRICT);
39850 self::$io = $io;
39851 }
39852 }
39853 <?php
39854
39855
39856
39857
39858
39859
39860
39861
39862
39863
39864
39865 namespace Composer\Util;
39866
39867 use RecursiveDirectoryIterator;
39868 use RecursiveIteratorIterator;
39869 use Symfony\Component\Filesystem\Exception\IOException;
39870 use Symfony\Component\Finder\Finder;
39871
39872
39873
39874
39875
39876 class Filesystem
39877 {
39878 private $processExecutor;
39879
39880 public function __construct(ProcessExecutor $executor = null)
39881 {
39882 $this->processExecutor = $executor ?: new ProcessExecutor();
39883 }
39884
39885 public function remove($file)
39886 {
39887 if (is_dir($file)) {
39888 return $this->removeDirectory($file);
39889 }
39890
39891 if (file_exists($file)) {
39892 return $this->unlink($file);
39893 }
39894
39895 return false;
39896 }
39897
39898
39899
39900
39901
39902
39903
39904 public function isDirEmpty($dir)
39905 {
39906 $finder = Finder::create()
39907 ->ignoreVCS(false)
39908 ->ignoreDotFiles(false)
39909 ->depth(0)
39910 ->in($dir);
39911
39912 return count($finder) === 0;
39913 }
39914
39915 public function emptyDirectory($dir, $ensureDirectoryExists = true)
39916 {
39917 if (file_exists($dir) && is_link($dir)) {
39918 $this->unlink($dir);
39919 }
39920
39921 if ($ensureDirectoryExists) {
39922 $this->ensureDirectoryExists($dir);
39923 }
39924
39925 if (is_dir($dir)) {
39926 $finder = Finder::create()
39927 ->ignoreVCS(false)
39928 ->ignoreDotFiles(false)
39929 ->depth(0)
39930 ->in($dir);
39931
39932 foreach ($finder as $path) {
39933 $this->remove((string) $path);
39934 }
39935 }
39936 }
39937
39938
39939
39940
39941
39942
39943
39944
39945
39946
39947
39948 public function removeDirectory($directory)
39949 {
39950 if ($this->isSymlinkedDirectory($directory)) {
39951 return $this->unlinkSymlinkedDirectory($directory);
39952 }
39953
39954 if ($this->isJunction($directory)) {
39955 return $this->removeJunction($directory);
39956 }
39957
39958 if (!file_exists($directory) || !is_dir($directory)) {
39959 return true;
39960 }
39961
39962 if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
39963 throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.');
39964 }
39965
39966 if (!function_exists('proc_open')) {
39967 return $this->removeDirectoryPhp($directory);
39968 }
39969
39970 if (Platform::isWindows()) {
39971 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape(realpath($directory)));
39972 } else {
39973 $cmd = sprintf('rm -rf %s', ProcessExecutor::escape($directory));
39974 }
39975
39976 $result = $this->getProcess()->execute($cmd, $output) === 0;
39977
39978
39979  clearstatcache();
39980
39981 if ($result && !file_exists($directory)) {
39982 return true;
39983 }
39984
39985 return $this->removeDirectoryPhp($directory);
39986 }
39987
39988
39989
39990
39991
39992
39993
39994
39995
39996
39997
39998 public function removeDirectoryPhp($directory)
39999 {
40000 try {
40001 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
40002 } catch (\UnexpectedValueException $e) {
40003
40004  
40005  clearstatcache();
40006 usleep(100000);
40007 if (!is_dir($directory)) {
40008 return true;
40009 }
40010 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
40011 }
40012 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
40013
40014 foreach ($ri as $file) {
40015 if ($file->isDir()) {
40016 $this->rmdir($file->getPathname());
40017 } else {
40018 $this->unlink($file->getPathname());
40019 }
40020 }
40021
40022 return $this->rmdir($directory);
40023 }
40024
40025 public function ensureDirectoryExists($directory)
40026 {
40027 if (!is_dir($directory)) {
40028 if (file_exists($directory)) {
40029 throw new \RuntimeException(
40030 $directory.' exists and is not a directory.'
40031 );
40032 }
40033 if (!@mkdir($directory, 0777, true)) {
40034 throw new \RuntimeException(
40035 $directory.' does not exist and could not be created.'
40036 );
40037 }
40038 }
40039 }
40040
40041
40042
40043
40044
40045
40046
40047
40048 public function unlink($path)
40049 {
40050 if (!@$this->unlinkImplementation($path)) {
40051
40052  if (!Platform::isWindows() || (usleep(350000) && !@$this->unlinkImplementation($path))) {
40053 $error = error_get_last();
40054 $message = 'Could not delete '.$path.': ' . @$error['message'];
40055 if (Platform::isWindows()) {
40056 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
40057 }
40058
40059 throw new \RuntimeException($message);
40060 }
40061 }
40062
40063 return true;
40064 }
40065
40066
40067
40068
40069
40070
40071
40072
40073 public function rmdir($path)
40074 {
40075 if (!@rmdir($path)) {
40076
40077  if (!Platform::isWindows() || (usleep(350000) && !@rmdir($path))) {
40078 $error = error_get_last();
40079 $message = 'Could not delete '.$path.': ' . @$error['message'];
40080 if (Platform::isWindows()) {
40081 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
40082 }
40083
40084 throw new \RuntimeException($message);
40085 }
40086 }
40087
40088 return true;
40089 }
40090
40091
40092
40093
40094
40095
40096
40097
40098
40099
40100 public function copyThenRemove($source, $target)
40101 {
40102 $this->copy($source, $target);
40103 if (!is_dir($source)) {
40104 $this->unlink($source);
40105
40106 return;
40107 }
40108
40109 $this->removeDirectoryPhp($source);
40110 }
40111
40112
40113
40114
40115
40116
40117
40118
40119 public function copy($source, $target)
40120 {
40121 if (!is_dir($source)) {
40122 return copy($source, $target);
40123 }
40124
40125 $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
40126 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
40127 $this->ensureDirectoryExists($target);
40128
40129 $result = true;
40130 foreach ($ri as $file) {
40131 $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
40132 if ($file->isDir()) {
40133 $this->ensureDirectoryExists($targetPath);
40134 } else {
40135 $result = $result && copy($file->getPathname(), $targetPath);
40136 }
40137 }
40138
40139 return $result;
40140 }
40141
40142 public function rename($source, $target)
40143 {
40144 if (true === @rename($source, $target)) {
40145 return;
40146 }
40147
40148 if (!function_exists('proc_open')) {
40149 return $this->copyThenRemove($source, $target);
40150 }
40151
40152 if (Platform::isWindows()) {
40153
40154  $command = sprintf('xcopy %s %s /E /I /Q /Y', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
40155 $result = $this->processExecutor->execute($command, $output);
40156
40157
40158  clearstatcache();
40159
40160 if (0 === $result) {
40161 $this->remove($source);
40162
40163 return;
40164 }
40165 } else {
40166
40167  
40168  $command = sprintf('mv %s %s', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
40169 $result = $this->processExecutor->execute($command, $output);
40170
40171
40172  clearstatcache();
40173
40174 if (0 === $result) {
40175 return;
40176 }
40177 }
40178
40179 return $this->copyThenRemove($source, $target);
40180 }
40181
40182
40183
40184
40185
40186
40187
40188
40189
40190
40191 public function findShortestPath($from, $to, $directories = false)
40192 {
40193 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
40194 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
40195 }
40196
40197 $from = lcfirst($this->normalizePath($from));
40198 $to = lcfirst($this->normalizePath($to));
40199
40200 if ($directories) {
40201 $from = rtrim($from, '/') . '/dummy_file';
40202 }
40203
40204 if (dirname($from) === dirname($to)) {
40205 return './'.basename($to);
40206 }
40207
40208 $commonPath = $to;
40209 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) {
40210 $commonPath = strtr(dirname($commonPath), '\\', '/');
40211 }
40212
40213 if (0 !== strpos($from, $commonPath) || '/' === $commonPath) {
40214 return $to;
40215 }
40216
40217 $commonPath = rtrim($commonPath, '/') . '/';
40218 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/');
40219 $commonPathCode = str_repeat('../', $sourcePathDepth);
40220
40221 return ($commonPathCode . substr($to, strlen($commonPath))) ?: './';
40222 }
40223
40224
40225
40226
40227
40228
40229
40230
40231
40232
40233
40234 public function findShortestPathCode($from, $to, $directories = false, $staticCode = false)
40235 {
40236 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
40237 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
40238 }
40239
40240 $from = lcfirst($this->normalizePath($from));
40241 $to = lcfirst($this->normalizePath($to));
40242
40243 if ($from === $to) {
40244 return $directories ? '__DIR__' : '__FILE__';
40245 }
40246
40247 $commonPath = $to;
40248 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) {
40249 $commonPath = strtr(dirname($commonPath), '\\', '/');
40250 }
40251
40252 if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) {
40253 return var_export($to, true);
40254 }
40255
40256 $commonPath = rtrim($commonPath, '/') . '/';
40257 if (strpos($to, $from.'/') === 0) {
40258 return '__DIR__ . '.var_export(substr($to, strlen($from)), true);
40259 }
40260 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/') + $directories;
40261 if ($staticCode) {
40262 $commonPathCode = "__DIR__ . '".str_repeat('/..', $sourcePathDepth)."'";
40263 } else {
40264 $commonPathCode = str_repeat('dirname(', $sourcePathDepth).'__DIR__'.str_repeat(')', $sourcePathDepth);
40265 }
40266 $relTarget = substr($to, strlen($commonPath));
40267
40268 return $commonPathCode . (strlen($relTarget) ? '.' . var_export('/' . $relTarget, true) : '');
40269 }
40270
40271
40272
40273
40274
40275
40276
40277 public function isAbsolutePath($path)
40278 {
40279 return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':';
40280 }
40281
40282
40283
40284
40285
40286
40287
40288
40289
40290 public function size($path)
40291 {
40292 if (!file_exists($path)) {
40293 throw new \RuntimeException("$path does not exist.");
40294 }
40295 if (is_dir($path)) {
40296 return $this->directorySize($path);
40297 }
40298
40299 return filesize($path);
40300 }
40301
40302
40303
40304
40305
40306
40307
40308
40309 public function normalizePath($path)
40310 {
40311 $parts = array();
40312 $path = strtr($path, '\\', '/');
40313 $prefix = '';
40314 $absolute = false;
40315
40316
40317  if (preg_match('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
40318 $prefix = $match[1];
40319 $path = substr($path, strlen($prefix));
40320 }
40321
40322 if (substr($path, 0, 1) === '/') {
40323 $absolute = true;
40324 $path = substr($path, 1);
40325 }
40326
40327 $up = false;
40328 foreach (explode('/', $path) as $chunk) {
40329 if ('..' === $chunk && ($absolute || $up)) {
40330 array_pop($parts);
40331 $up = !(empty($parts) || '..' === end($parts));
40332 } elseif ('.' !== $chunk && '' !== $chunk) {
40333 $parts[] = $chunk;
40334 $up = '..' !== $chunk;
40335 }
40336 }
40337
40338 return $prefix.($absolute ? '/' : '').implode('/', $parts);
40339 }
40340
40341
40342
40343
40344
40345
40346
40347 public static function isLocalPath($path)
40348 {
40349 return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
40350 }
40351
40352 public static function getPlatformPath($path)
40353 {
40354 if (Platform::isWindows()) {
40355 $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
40356 }
40357
40358 return preg_replace('{^file://}i', '', $path);
40359 }
40360
40361 protected function directorySize($directory)
40362 {
40363 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
40364 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
40365
40366 $size = 0;
40367 foreach ($ri as $file) {
40368 if ($file->isFile()) {
40369 $size += $file->getSize();
40370 }
40371 }
40372
40373 return $size;
40374 }
40375
40376 protected function getProcess()
40377 {
40378 return new ProcessExecutor;
40379 }
40380
40381
40382
40383
40384
40385
40386
40387
40388
40389
40390 private function unlinkImplementation($path)
40391 {
40392 if (Platform::isWindows() && is_dir($path) && is_link($path)) {
40393 return rmdir($path);
40394 }
40395
40396 return unlink($path);
40397 }
40398
40399
40400
40401
40402
40403
40404
40405
40406 public function relativeSymlink($target, $link)
40407 {
40408 $cwd = getcwd();
40409
40410 $relativePath = $this->findShortestPath($link, $target);
40411 chdir(dirname($link));
40412 $result = @symlink($relativePath, $link);
40413
40414 chdir($cwd);
40415
40416 return (bool) $result;
40417 }
40418
40419
40420
40421
40422
40423
40424
40425
40426 public function isSymlinkedDirectory($directory)
40427 {
40428 if (!is_dir($directory)) {
40429 return false;
40430 }
40431
40432 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
40433
40434 return is_link($resolved);
40435 }
40436
40437
40438
40439
40440
40441
40442 private function unlinkSymlinkedDirectory($directory)
40443 {
40444 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
40445
40446 return $this->unlink($resolved);
40447 }
40448
40449
40450
40451
40452
40453
40454
40455
40456 private function resolveSymlinkedDirectorySymlink($pathname)
40457 {
40458 if (!is_dir($pathname)) {
40459 return $pathname;
40460 }
40461
40462 $resolved = rtrim($pathname, '/');
40463
40464 if (!strlen($resolved)) {
40465 return $pathname;
40466 }
40467
40468 return $resolved;
40469 }
40470
40471
40472
40473
40474
40475
40476
40477 public function junction($target, $junction)
40478 {
40479 if (!Platform::isWindows()) {
40480 throw new \LogicException(sprintf('Function %s is not available on non-Windows platform', __CLASS__));
40481 }
40482 if (!is_dir($target)) {
40483 throw new IOException(sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target);
40484 }
40485 $cmd = sprintf('mklink /J %s %s',
40486 ProcessExecutor::escape(str_replace('/', DIRECTORY_SEPARATOR, $junction)),
40487 ProcessExecutor::escape(realpath($target)));
40488 if ($this->getProcess()->execute($cmd, $output) !== 0) {
40489 throw new IOException(sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target);
40490 }
40491 clearstatcache(true, $junction);
40492 }
40493
40494
40495
40496
40497
40498
40499
40500 public function isJunction($junction)
40501 {
40502 if (!Platform::isWindows()) {
40503 return false;
40504 }
40505 if (!is_dir($junction) || is_link($junction)) {
40506 return false;
40507 }
40508
40509
40510
40511
40512
40513
40514
40515
40516
40517
40518
40519 clearstatcache(true, $junction);
40520 $stat = lstat($junction);
40521
40522 return !($stat['mode'] & 0xC000);
40523 }
40524
40525
40526
40527
40528
40529
40530
40531 public function removeJunction($junction)
40532 {
40533 if (!Platform::isWindows()) {
40534 return false;
40535 }
40536 $junction = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $junction), DIRECTORY_SEPARATOR);
40537 if (!$this->isJunction($junction)) {
40538 throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
40539 }
40540 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape($junction));
40541 clearstatcache(true, $junction);
40542
40543 return ($this->getProcess()->execute($cmd, $output) === 0);
40544 }
40545 }
40546 <?php
40547
40548
40549
40550
40551
40552
40553
40554
40555
40556
40557
40558 namespace Composer\Util;
40559
40560 use Composer\Config;
40561 use Composer\IO\IOInterface;
40562
40563
40564
40565
40566 class Git
40567 {
40568 private static $version;
40569
40570
40571 protected $io;
40572
40573 protected $config;
40574
40575 protected $process;
40576
40577 protected $filesystem;
40578
40579 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process, Filesystem $fs)
40580 {
40581 $this->io = $io;
40582 $this->config = $config;
40583 $this->process = $process;
40584 $this->filesystem = $fs;
40585 }
40586
40587 public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
40588 {
40589
40590  $this->config->prohibitUrlByConfig($url, $this->io);
40591
40592 if ($initialClone) {
40593 $origCwd = $cwd;
40594 $cwd = null;
40595 }
40596
40597 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
40598 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.');
40599 }
40600
40601 if (!$initialClone) {
40602
40603  $this->process->execute('git remote -v', $output, $cwd);
40604 if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match)) {
40605 $this->io->setAuthentication($match[3], urldecode($match[1]), urldecode($match[2]));
40606 }
40607 }
40608
40609 $protocols = $this->config->get('github-protocols');
40610 if (!is_array($protocols)) {
40611 throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols));
40612 }
40613
40614  if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
40615 $messages = array();
40616 foreach ($protocols as $protocol) {
40617 if ('ssh' === $protocol) {
40618 $protoUrl = "git@" . $match[1] . ":" . $match[2];
40619 } else {
40620 $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
40621 }
40622
40623 if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) {
40624 return;
40625 }
40626 $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', '  ', $this->process->getErrorOutput());
40627 if ($initialClone) {
40628 $this->filesystem->removeDirectory($origCwd);
40629 }
40630 }
40631
40632
40633  $this->throwException('Failed to clone ' . $url . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
40634 }
40635
40636
40637  $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
40638
40639 $command = call_user_func($commandCallable, $url);
40640
40641 $auth = null;
40642 if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
40643
40644  if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)) {
40645 if (!$this->io->hasAuthentication($match[1])) {
40646 $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
40647 $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
40648
40649 if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
40650 $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
40651 }
40652 }
40653
40654 if ($this->io->hasAuthentication($match[1])) {
40655 $auth = $this->io->getAuthentication($match[1]);
40656 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
40657 $command = call_user_func($commandCallable, $authUrl);
40658 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40659 return;
40660 }
40661 }
40662 } elseif (preg_match('{^https://(bitbucket\.org)/(.*)(\.git)?$}U', $url, $match)) { 
40663  $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process);
40664
40665 if (!$this->io->hasAuthentication($match[1])) {
40666 $message = 'Enter your Bitbucket credentials to access private repos';
40667
40668 if (!$bitbucketUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
40669 $bitbucketUtil->authorizeOAuthInteractively($match[1], $message);
40670 $accessToken = $bitbucketUtil->getToken();
40671 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
40672 }
40673 } else { 
40674  $auth = $this->io->getAuthentication($match[1]);
40675
40676
40677  if ($auth['username'] !== 'x-token-auth') {
40678 $accessToken = $bitbucketUtil->requestToken($match[1], $auth['username'], $auth['password']);
40679 if (! empty($accessToken)) {
40680 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
40681 }
40682 }
40683 }
40684
40685 if ($this->io->hasAuthentication($match[1])) {
40686 $auth = $this->io->getAuthentication($match[1]);
40687 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
40688
40689 $command = call_user_func($commandCallable, $authUrl);
40690 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40691 return;
40692 }
40693 } else { 
40694  $sshUrl = 'git@bitbucket.org:' . $match[2] . '.git';
40695 $this->io->writeError('    No bitbucket authentication configured. Falling back to ssh.');
40696 $command = call_user_func($commandCallable, $sshUrl);
40697 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40698 return;
40699 }
40700 }
40701 } elseif ($this->isAuthenticationFailure($url, $match)) { 
40702  if (strpos($match[2], '@')) {
40703 list($authParts, $match[2]) = explode('@', $match[2], 2);
40704 }
40705
40706 $storeAuth = false;
40707 if ($this->io->hasAuthentication($match[2])) {
40708 $auth = $this->io->getAuthentication($match[2]);
40709 } elseif ($this->io->isInteractive()) {
40710 $defaultUsername = null;
40711 if (isset($authParts) && $authParts) {
40712 if (false !== strpos($authParts, ':')) {
40713 list($defaultUsername, ) = explode(':', $authParts, 2);
40714 } else {
40715 $defaultUsername = $authParts;
40716 }
40717 }
40718
40719 $this->io->writeError('    Authentication required (<info>' . parse_url($url, PHP_URL_HOST) . '</info>):');
40720 $auth = array(
40721 'username' => $this->io->ask('      Username: ', $defaultUsername),
40722 'password' => $this->io->askAndHideAnswer('      Password: '),
40723 );
40724 $storeAuth = $this->config->get('store-auths');
40725 }
40726
40727 if ($auth) {
40728 $authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
40729
40730 $command = call_user_func($commandCallable, $authUrl);
40731 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40732 $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
40733 $authHelper = new AuthHelper($this->io, $this->config);
40734 $authHelper->storeAuth($match[2], $storeAuth);
40735
40736 return;
40737 }
40738 }
40739 }
40740
40741 if ($initialClone) {
40742 $this->filesystem->removeDirectory($origCwd);
40743 }
40744 $this->throwException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput(), $url);
40745 }
40746 }
40747
40748 public function syncMirror($url, $dir)
40749 {
40750
40751  if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
40752 try {
40753 $commandCallable = function ($url) {
40754 return sprintf('git remote set-url origin %s && git remote update --prune origin', ProcessExecutor::escape($url));
40755 };
40756 $this->runCommand($commandCallable, $url, $dir);
40757 } catch (\Exception $e) {
40758 return false;
40759 }
40760
40761 return true;
40762 }
40763
40764
40765  $this->filesystem->removeDirectory($dir);
40766
40767 $commandCallable = function ($url) use ($dir) {
40768 return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
40769 };
40770
40771 $this->runCommand($commandCallable, $url, $dir, true);
40772
40773 return true;
40774 }
40775
40776 public function fetchRefOrSyncMirror($url, $dir, $ref)
40777 {
40778 if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
40779 $escapedRef = ProcessExecutor::escape($ref.'^{commit}');
40780 $exitCode = $this->process->execute(sprintf('git rev-parse --quiet --verify %s', $escapedRef), $output, $dir);
40781 if ($exitCode === 0) {
40782 return true;
40783 }
40784 }
40785
40786 $this->syncMirror($url, $dir);
40787
40788 return false;
40789 }
40790
40791 private function isAuthenticationFailure($url, &$match)
40792 {
40793 if (!preg_match('{(https?://)([^/]+)(.*)$}i', $url, $match)) {
40794 return false;
40795 }
40796
40797 $authFailures = array(
40798 'fatal: Authentication failed',
40799 'remote error: Invalid username or password.',
40800 'error: 401 Unauthorized',
40801 'fatal: unable to access',
40802 );
40803
40804 foreach ($authFailures as $authFailure) {
40805 if (strpos($this->process->getErrorOutput(), $authFailure) !== false) {
40806 return true;
40807 }
40808 }
40809
40810 return false;
40811 }
40812
40813 public static function cleanEnv()
40814 {
40815 if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
40816 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');
40817 }
40818
40819
40820  if (getenv('GIT_ASKPASS') !== 'echo') {
40821 putenv('GIT_ASKPASS=echo');
40822 unset($_SERVER['GIT_ASKPASS']);
40823 }
40824
40825
40826  if (getenv('GIT_DIR')) {
40827 putenv('GIT_DIR');
40828 unset($_SERVER['GIT_DIR']);
40829 }
40830 if (getenv('GIT_WORK_TREE')) {
40831 putenv('GIT_WORK_TREE');
40832 unset($_SERVER['GIT_WORK_TREE']);
40833 }
40834
40835
40836  if (getenv('LANGUAGE') !== 'C') {
40837 putenv('LANGUAGE=C');
40838 }
40839
40840
40841  putenv("DYLD_LIBRARY_PATH");
40842 unset($_SERVER['DYLD_LIBRARY_PATH']);
40843 }
40844
40845 public static function getGitHubDomainsRegex(Config $config)
40846 {
40847 return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
40848 }
40849
40850 public static function sanitizeUrl($message)
40851 {
40852 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
40853 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
40854 return '://***:***@';
40855 }
40856
40857 return '://' . $m[1] . ':***@';
40858 }, $message);
40859 }
40860
40861 private function throwException($message, $url)
40862 {
40863
40864  clearstatcache();
40865
40866 if (0 !== $this->process->execute('git --version', $ignoredOutput)) {
40867 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()));
40868 }
40869
40870 throw new \RuntimeException(self::sanitizeUrl($message));
40871 }
40872
40873
40874
40875
40876
40877
40878 public function getVersion()
40879 {
40880 if (isset(self::$version)) {
40881 return self::$version;
40882 }
40883 if (0 !== $this->process->execute('git --version', $output)) {
40884 return;
40885 }
40886 if (preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
40887 return self::$version = $matches[1];
40888 }
40889 }
40890 }
40891 <?php
40892
40893
40894
40895
40896
40897
40898
40899
40900
40901
40902
40903 namespace Composer\Util;
40904
40905 use Composer\Factory;
40906 use Composer\IO\IOInterface;
40907 use Composer\Config;
40908 use Composer\Downloader\TransportException;
40909
40910
40911
40912
40913 class GitHub
40914 {
40915 protected $io;
40916 protected $config;
40917 protected $process;
40918 protected $remoteFilesystem;
40919
40920
40921
40922
40923
40924
40925
40926
40927
40928 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
40929 {
40930 $this->io = $io;
40931 $this->config = $config;
40932 $this->process = $process ?: new ProcessExecutor;
40933 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
40934 }
40935
40936
40937
40938
40939
40940
40941
40942 public function authorizeOAuth($originUrl)
40943 {
40944 if (!in_array($originUrl, $this->config->get('github-domains'))) {
40945 return false;
40946 }
40947
40948
40949  if (0 === $this->process->execute('git config github.accesstoken', $output)) {
40950 $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
40951
40952 return true;
40953 }
40954
40955 return false;
40956 }
40957
40958
40959
40960
40961
40962
40963
40964
40965
40966
40967 public function authorizeOAuthInteractively($originUrl, $message = null)
40968 {
40969 if ($message) {
40970 $this->io->writeError($message);
40971 }
40972
40973 $note = 'Composer';
40974 if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
40975 $note .= ' on ' . trim($output);
40976 }
40977 $note .= ' ' . date('Y-m-d Hi');
40978
40979 $url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
40980 $this->io->writeError(sprintf('Head to %s', $url));
40981 $this->io->writeError(sprintf('to retrieve a token. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
40982
40983 $token = trim($this->io->askAndHideAnswer('Token (hidden): '));
40984
40985 if (!$token) {
40986 $this->io->writeError('<warning>No token given, aborting.</warning>');
40987 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
40988
40989 return false;
40990 }
40991
40992 $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
40993
40994 try {
40995 $apiUrl = ('github.com' === $originUrl) ? 'api.github.com/' : $originUrl . '/api/v3/';
40996
40997 $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl, false, array(
40998 'retry-auth-failure' => false,
40999 ));
41000 } catch (TransportException $e) {
41001 if (in_array($e->getCode(), array(403, 401))) {
41002 $this->io->writeError('<error>Invalid token provided.</error>');
41003 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
41004
41005 return false;
41006 }
41007
41008 throw $e;
41009 }
41010
41011
41012  $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
41013 $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
41014
41015 $this->io->writeError('<info>Token stored successfully.</info>');
41016
41017 return true;
41018 }
41019 }
41020 <?php
41021
41022
41023
41024
41025
41026
41027
41028
41029
41030
41031
41032 namespace Composer\Util;
41033
41034 use Composer\IO\IOInterface;
41035 use Composer\Config;
41036 use Composer\Factory;
41037 use Composer\Downloader\TransportException;
41038 use Composer\Json\JsonFile;
41039
41040
41041
41042
41043 class GitLab
41044 {
41045 protected $io;
41046 protected $config;
41047 protected $process;
41048 protected $remoteFilesystem;
41049
41050
41051
41052
41053
41054
41055
41056
41057
41058 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
41059 {
41060 $this->io = $io;
41061 $this->config = $config;
41062 $this->process = $process ?: new ProcessExecutor();
41063 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
41064 }
41065
41066
41067
41068
41069
41070
41071
41072
41073 public function authorizeOAuth($originUrl)
41074 {
41075 if (!in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
41076 return false;
41077 }
41078
41079
41080  if (0 === $this->process->execute('git config gitlab.accesstoken', $output)) {
41081 $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
41082
41083 return true;
41084 }
41085
41086
41087  $authTokens = $this->config->get('gitlab-token');
41088
41089 if (isset($authTokens[$originUrl])) {
41090 $this->io->setAuthentication($originUrl, $authTokens[$originUrl], 'private-token');
41091
41092 return true;
41093 }
41094
41095 return false;
41096 }
41097
41098
41099
41100
41101
41102
41103
41104
41105
41106
41107
41108
41109
41110 public function authorizeOAuthInteractively($scheme, $originUrl, $message = null)
41111 {
41112 if ($message) {
41113 $this->io->writeError($message);
41114 }
41115
41116 $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
41117 $this->io->writeError('To revoke access to this token you can visit '.$originUrl.'/profile/applications');
41118
41119 $attemptCounter = 0;
41120
41121 while ($attemptCounter++ < 5) {
41122 try {
41123 $response = $this->createToken($scheme, $originUrl);
41124 } catch (TransportException $e) {
41125
41126  
41127  if (in_array($e->getCode(), array(403, 401))) {
41128 if (401 === $e->getCode()) {
41129 $this->io->writeError('Bad credentials.');
41130 } else {
41131 $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
41132 }
41133
41134 $this->io->writeError('You can also manually create a personal token at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
41135 $this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
41136
41137 continue;
41138 }
41139
41140 throw $e;
41141 }
41142
41143 $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
41144
41145
41146  $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
41147
41148 return true;
41149 }
41150
41151 throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
41152 }
41153
41154 private function createToken($scheme, $originUrl)
41155 {
41156 $username = $this->io->ask('Username: ');
41157 $password = $this->io->askAndHideAnswer('Password: ');
41158
41159 $headers = array('Content-Type: application/x-www-form-urlencoded');
41160
41161 $apiUrl = $originUrl;
41162 $data = http_build_query(array(
41163 'username' => $username,
41164 'password' => $password,
41165 'grant_type' => 'password',
41166 ), null, '&');
41167 $options = array(
41168 'retry-auth-failure' => false,
41169 'http' => array(
41170 'method' => 'POST',
41171 'header' => $headers,
41172 'content' => $data,
41173 ),
41174 );
41175
41176 $json = $this->remoteFilesystem->getContents($originUrl, $scheme.'://'.$apiUrl.'/oauth/token', false, $options);
41177
41178 $this->io->writeError('Token successfully created');
41179
41180 return JsonFile::parseJson($json);
41181 }
41182 }
41183 <?php
41184
41185
41186
41187
41188
41189
41190
41191
41192
41193
41194
41195 namespace Composer\Util;
41196
41197
41198
41199
41200
41201
41202
41203
41204 class IniHelper
41205 {
41206 const ENV_ORIGINAL = 'COMPOSER_ORIGINAL_INIS';
41207
41208
41209
41210
41211
41212
41213
41214
41215
41216 public static function getAll()
41217 {
41218 $env = getenv(self::ENV_ORIGINAL);
41219
41220 if (false !== $env) {
41221 return explode(PATH_SEPARATOR, $env);
41222 }
41223
41224 $paths = array(strval(php_ini_loaded_file()));
41225
41226 if ($scanned = php_ini_scanned_files()) {
41227 $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
41228 }
41229
41230 return $paths;
41231 }
41232
41233
41234
41235
41236
41237
41238 public static function getMessage()
41239 {
41240 $paths = self::getAll();
41241
41242 if (empty($paths[0])) {
41243 array_shift($paths);
41244 }
41245
41246 $ini = array_shift($paths);
41247
41248 if (empty($ini)) {
41249 return 'A php.ini file does not exist. You will have to create one.';
41250 }
41251
41252 if (!empty($paths)) {
41253 return 'Your command-line PHP is using multiple ini files. Run `php --ini` to show them.';
41254 }
41255
41256 return 'The php.ini used by your command-line PHP is: '.$ini;
41257 }
41258 }
41259 <?php
41260
41261
41262
41263
41264
41265
41266
41267
41268
41269
41270
41271 namespace Composer\Util;
41272
41273
41274
41275
41276 class NoProxyPattern
41277 {
41278
41279
41280
41281 protected $rules = array();
41282
41283
41284
41285
41286 public function __construct($pattern)
41287 {
41288 $this->rules = preg_split("/[\s,]+/", $pattern);
41289 }
41290
41291
41292
41293
41294
41295
41296
41297
41298 public function test($url)
41299 {
41300 $host = parse_url($url, PHP_URL_HOST);
41301 $port = parse_url($url, PHP_URL_PORT);
41302
41303 if (empty($port)) {
41304 switch (parse_url($url, PHP_URL_SCHEME)) {
41305 case 'http':
41306 $port = 80;
41307 break;
41308 case 'https':
41309 $port = 443;
41310 break;
41311 }
41312 }
41313
41314 foreach ($this->rules as $rule) {
41315 if ($rule == '*') {
41316 return true;
41317 }
41318
41319 $match = false;
41320
41321 list($ruleHost) = explode(':', $rule);
41322 list($base) = explode('/', $ruleHost);
41323
41324 if (filter_var($base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
41325
41326
41327 if (!isset($ip)) {
41328 $ip = gethostbyname($host);
41329 }
41330
41331 if (strpos($ruleHost, '/') === false) {
41332 $match = $ip === $ruleHost;
41333 } else {
41334
41335  
41336  if ($ip === $host) {
41337 $match = false;
41338 } else {
41339
41340  $match = self::inCIDRBlock($ruleHost, $ip);
41341 }
41342 }
41343 } else {
41344
41345
41346 $haystack = '.' . trim($host, '.') . '.';
41347 $needle = '.'. trim($ruleHost, '.') .'.';
41348 $match = stripos(strrev($haystack), strrev($needle)) === 0;
41349 }
41350
41351
41352  if ($match && strpos($rule, ':') !== false) {
41353 list(, $rulePort) = explode(':', $rule);
41354 if (!empty($rulePort) && $port != $rulePort) {
41355 $match = false;
41356 }
41357 }
41358
41359 if ($match) {
41360 return true;
41361 }
41362 }
41363
41364 return false;
41365 }
41366
41367
41368
41369
41370
41371
41372
41373
41374
41375
41376
41377 private static function inCIDRBlock($cidr, $ip)
41378 {
41379
41380  list($base, $bits) = explode('/', $cidr);
41381
41382
41383  list($a, $b, $c, $d) = explode('.', $base);
41384
41385
41386  $i = ($a << 24) + ($b << 16) + ($c << 8) + $d;
41387 $mask = $bits == 0 ? 0 : (~0 << (32 - $bits));
41388
41389
41390  $low = $i & $mask;
41391
41392
41393  $high = $i | (~$mask & 0xFFFFFFFF);
41394
41395
41396  list($a, $b, $c, $d) = explode('.', $ip);
41397
41398
41399  $check = ($a << 24) + ($b << 16) + ($c << 8) + $d;
41400
41401
41402  
41403  return $check >= $low && $check <= $high;
41404 }
41405 }
41406 <?php
41407
41408
41409
41410
41411
41412
41413
41414
41415
41416
41417
41418 namespace Composer\Util;
41419
41420 use Composer\IO\IOInterface;
41421 use Symfony\Component\Process\Process;
41422
41423
41424
41425
41426 class Perforce
41427 {
41428 protected $path;
41429 protected $p4Depot;
41430 protected $p4Client;
41431 protected $p4User;
41432 protected $p4Password;
41433 protected $p4Port;
41434 protected $p4Stream;
41435 protected $p4ClientSpec;
41436 protected $p4DepotType;
41437 protected $p4Branch;
41438 protected $process;
41439 protected $uniquePerforceClientName;
41440 protected $windowsFlag;
41441 protected $commandResult;
41442
41443 protected $io;
41444
41445 protected $filesystem;
41446
41447 public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
41448 {
41449 $this->windowsFlag = $isWindows;
41450 $this->p4Port = $port;
41451 $this->initializePath($path);
41452 $this->process = $process;
41453 $this->initialize($repoConfig);
41454 $this->io = $io;
41455 }
41456
41457 public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
41458 {
41459 return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io);
41460 }
41461
41462 public static function checkServerExists($url, ProcessExecutor $processExecutor)
41463 {
41464 $output = null;
41465
41466 return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s', $output);
41467 }
41468
41469 public function initialize($repoConfig)
41470 {
41471 $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
41472 if (!$repoConfig) {
41473 return;
41474 }
41475 if (isset($repoConfig['unique_perforce_client_name'])) {
41476 $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
41477 }
41478
41479 if (isset($repoConfig['depot'])) {
41480 $this->p4Depot = $repoConfig['depot'];
41481 }
41482 if (isset($repoConfig['branch'])) {
41483 $this->p4Branch = $repoConfig['branch'];
41484 }
41485 if (isset($repoConfig['p4user'])) {
41486 $this->p4User = $repoConfig['p4user'];
41487 } else {
41488 $this->p4User = $this->getP4variable('P4USER');
41489 }
41490 if (isset($repoConfig['p4password'])) {
41491 $this->p4Password = $repoConfig['p4password'];
41492 }
41493 }
41494
41495 public function initializeDepotAndBranch($depot, $branch)
41496 {
41497 if (isset($depot)) {
41498 $this->p4Depot = $depot;
41499 }
41500 if (isset($branch)) {
41501 $this->p4Branch = $branch;
41502 }
41503 }
41504
41505 public function generateUniquePerforceClientName()
41506 {
41507 return gethostname() . "_" . time();
41508 }
41509
41510 public function cleanupClientSpec()
41511 {
41512 $client = $this->getClient();
41513 $task = 'client -d ' . $client;
41514 $useP4Client = false;
41515 $command = $this->generateP4Command($task, $useP4Client);
41516 $this->executeCommand($command);
41517 $clientSpec = $this->getP4ClientSpec();
41518 $fileSystem = $this->getFilesystem();
41519 $fileSystem->remove($clientSpec);
41520 }
41521
41522 protected function executeCommand($command)
41523 {
41524 $this->commandResult = '';
41525
41526 return $this->process->execute($command, $this->commandResult);
41527 }
41528
41529 public function getClient()
41530 {
41531 if (!isset($this->p4Client)) {
41532 $cleanStreamName = str_replace(array('//', '/', '@'), array('', '_', ''), $this->getStream());
41533 $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
41534 }
41535
41536 return $this->p4Client;
41537 }
41538
41539 protected function getPath()
41540 {
41541 return $this->path;
41542 }
41543
41544 public function initializePath($path)
41545 {
41546 $this->path = $path;
41547 $fs = $this->getFilesystem();
41548 $fs->ensureDirectoryExists($path);
41549 }
41550
41551 protected function getPort()
41552 {
41553 return $this->p4Port;
41554 }
41555
41556 public function setStream($stream)
41557 {
41558 $this->p4Stream = $stream;
41559 $index = strrpos($stream, '/');
41560
41561  if ($index > 2) {
41562 $this->p4DepotType = 'stream';
41563 }
41564 }
41565
41566 public function isStream()
41567 {
41568 return (strcmp($this->p4DepotType, 'stream') === 0);
41569 }
41570
41571 public function getStream()
41572 {
41573 if (!isset($this->p4Stream)) {
41574 if ($this->isStream()) {
41575 $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
41576 } else {
41577 $this->p4Stream = '//' . $this->p4Depot;
41578 }
41579 }
41580
41581 return $this->p4Stream;
41582 }
41583
41584 public function getStreamWithoutLabel($stream)
41585 {
41586 $index = strpos($stream, '@');
41587 if ($index === false) {
41588 return $stream;
41589 }
41590
41591 return substr($stream, 0, $index);
41592 }
41593
41594 public function getP4ClientSpec()
41595 {
41596 return $this->path . '/' . $this->getClient() . '.p4.spec';
41597 }
41598
41599 public function getUser()
41600 {
41601 return $this->p4User;
41602 }
41603
41604 public function setUser($user)
41605 {
41606 $this->p4User = $user;
41607 }
41608
41609 public function queryP4User()
41610 {
41611 $this->getUser();
41612 if (strlen($this->p4User) > 0) {
41613 return;
41614 }
41615 $this->p4User = $this->getP4variable('P4USER');
41616 if (strlen($this->p4User) > 0) {
41617 return;
41618 }
41619 $this->p4User = $this->io->ask('Enter P4 User:');
41620 if ($this->windowsFlag) {
41621 $command = 'p4 set P4USER=' . $this->p4User;
41622 } else {
41623 $command = 'export P4USER=' . $this->p4User;
41624 }
41625 $this->executeCommand($command);
41626 }
41627
41628 protected function getP4variable($name)
41629 {
41630 if ($this->windowsFlag) {
41631 $command = 'p4 set';
41632 $this->executeCommand($command);
41633 $result = trim($this->commandResult);
41634 $resArray = explode(PHP_EOL, $result);
41635 foreach ($resArray as $line) {
41636 $fields = explode('=', $line);
41637 if (strcmp($name, $fields[0]) == 0) {
41638 $index = strpos($fields[1], ' ');
41639 if ($index === false) {
41640 $value = $fields[1];
41641 } else {
41642 $value = substr($fields[1], 0, $index);
41643 }
41644 $value = trim($value);
41645
41646 return $value;
41647 }
41648 }
41649
41650 return null;
41651 }
41652
41653 $command = 'echo $' . $name;
41654 $this->executeCommand($command);
41655 $result = trim($this->commandResult);
41656
41657 return $result;
41658 }
41659
41660 public function queryP4Password()
41661 {
41662 if (isset($this->p4Password)) {
41663 return $this->p4Password;
41664 }
41665 $password = $this->getP4variable('P4PASSWD');
41666 if (strlen($password) <= 0) {
41667 $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
41668 }
41669 $this->p4Password = $password;
41670
41671 return $password;
41672 }
41673
41674 public function generateP4Command($command, $useClient = true)
41675 {
41676 $p4Command = 'p4 ';
41677 $p4Command = $p4Command . '-u ' . $this->getUser() . ' ';
41678 if ($useClient) {
41679 $p4Command = $p4Command . '-c ' . $this->getClient() . ' ';
41680 }
41681 $p4Command = $p4Command . '-p ' . $this->getPort() . ' ' . $command;
41682
41683 return $p4Command;
41684 }
41685
41686 public function isLoggedIn()
41687 {
41688 $command = $this->generateP4Command('login -s', false);
41689 $exitCode = $this->executeCommand($command);
41690 if ($exitCode) {
41691 $errorOutput = $this->process->getErrorOutput();
41692 $index = strpos($errorOutput, $this->getUser());
41693 if ($index === false) {
41694 $index = strpos($errorOutput, 'p4');
41695 if ($index === false) {
41696 return false;
41697 }
41698 throw new \Exception('p4 command not found in path: ' . $errorOutput);
41699 }
41700 throw new \Exception('Invalid user name: ' . $this->getUser());
41701 }
41702
41703 return true;
41704 }
41705
41706 public function connectClient()
41707 {
41708 $p4CreateClientCommand = $this->generateP4Command(
41709 'client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())
41710 );
41711 $this->executeCommand($p4CreateClientCommand);
41712 }
41713
41714 public function syncCodeBase($sourceReference)
41715 {
41716 $prevDir = getcwd();
41717 chdir($this->path);
41718 $p4SyncCommand = $this->generateP4Command('sync -f ');
41719 if (null !== $sourceReference) {
41720 $p4SyncCommand = $p4SyncCommand . '@' . $sourceReference;
41721 }
41722 $this->executeCommand($p4SyncCommand);
41723 chdir($prevDir);
41724 }
41725
41726 public function writeClientSpecToFile($spec)
41727 {
41728 fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
41729 fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL);
41730 fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL);
41731 fwrite($spec, 'Owner:  ' . $this->getUser() . PHP_EOL . PHP_EOL);
41732 fwrite($spec, 'Description:' . PHP_EOL);
41733 fwrite($spec, '  Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL);
41734 fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL);
41735 fwrite($spec, 'Options:  noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL);
41736 fwrite($spec, 'SubmitOptions:  revertunchanged' . PHP_EOL . PHP_EOL);
41737 fwrite($spec, 'LineEnd:  local' . PHP_EOL . PHP_EOL);
41738 if ($this->isStream()) {
41739 fwrite($spec, 'Stream:' . PHP_EOL);
41740 fwrite($spec, '  ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL);
41741 } else {
41742 fwrite(
41743 $spec,
41744 'View:  ' . $this->getStream() . '/...  //' . $this->getClient() . '/... ' . PHP_EOL
41745 );
41746 }
41747 }
41748
41749 public function writeP4ClientSpec()
41750 {
41751 $clientSpec = $this->getP4ClientSpec();
41752 $spec = fopen($clientSpec, 'w');
41753 try {
41754 $this->writeClientSpecToFile($spec);
41755 } catch (\Exception $e) {
41756 fclose($spec);
41757 throw $e;
41758 }
41759 fclose($spec);
41760 }
41761
41762 protected function read($pipe, $name)
41763 {
41764 if (feof($pipe)) {
41765 return;
41766 }
41767 $line = fgets($pipe);
41768 while ($line !== false) {
41769 $line = fgets($pipe);
41770 }
41771
41772 return;
41773 }
41774
41775 public function windowsLogin($password)
41776 {
41777 $command = $this->generateP4Command(' login -a');
41778 $process = new Process($command, null, null, $password);
41779
41780 return $process->run();
41781 }
41782
41783 public function p4Login()
41784 {
41785 $this->queryP4User();
41786 if (!$this->isLoggedIn()) {
41787 $password = $this->queryP4Password();
41788 if ($this->windowsFlag) {
41789 $this->windowsLogin($password);
41790 } else {
41791 $command = 'echo ' . $password . ' | ' . $this->generateP4Command(' login -a', false);
41792 $exitCode = $this->executeCommand($command);
41793 $result = trim($this->commandResult);
41794 if ($exitCode) {
41795 throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
41796 }
41797 }
41798 }
41799 }
41800
41801 public function getComposerInformation($identifier)
41802 {
41803 $composerFileContent = $this->getFileContent('composer.json', $identifier);
41804
41805 if (!$composerFileContent) {
41806 return;
41807 }
41808
41809 return json_decode($composerFileContent, true);
41810 }
41811
41812 public function getFileContent($file, $identifier)
41813 {
41814 $path = $this->getFilePath($file, $identifier);
41815
41816 $command = $this->generateP4Command(' print ' . $path);
41817 $this->executeCommand($command);
41818 $result = $this->commandResult;
41819
41820 if (!trim($result)) {
41821 return null;
41822 }
41823
41824 return $result;
41825 }
41826
41827 public function getFilePath($file, $identifier)
41828 {
41829 $index = strpos($identifier, '@');
41830 if ($index === false) {
41831 $path = $identifier. '/' . $file;
41832
41833 return $path;
41834 }
41835
41836 $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index);
41837 $command = $this->generateP4Command(' files ' . $path, false);
41838 $this->executeCommand($command);
41839 $result = $this->commandResult;
41840 $index2 = strpos($result, 'no such file(s).');
41841 if ($index2 === false) {
41842 $index3 = strpos($result, 'change');
41843 if ($index3 !== false) {
41844 $phrase = trim(substr($result, $index3));
41845 $fields = explode(' ', $phrase);
41846
41847 return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1];
41848 }
41849 }
41850
41851 return null;
41852 }
41853
41854 public function getBranches()
41855 {
41856 $possibleBranches = array();
41857 if (!$this->isStream()) {
41858 $possibleBranches[$this->p4Branch] = $this->getStream();
41859 } else {
41860 $command = $this->generateP4Command('streams //' . $this->p4Depot . '/...');
41861 $this->executeCommand($command);
41862 $result = $this->commandResult;
41863 $resArray = explode(PHP_EOL, $result);
41864 foreach ($resArray as $line) {
41865 $resBits = explode(' ', $line);
41866 if (count($resBits) > 4) {
41867 $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
41868 $possibleBranches[$branch] = $resBits[1];
41869 }
41870 }
41871 }
41872 $command = $this->generateP4Command('changes '. $this->getStream() . '/...', false);
41873 $this->executeCommand($command);
41874 $result = $this->commandResult;
41875 $resArray = explode(PHP_EOL, $result);
41876 $lastCommit = $resArray[0];
41877 $lastCommitArr = explode(' ', $lastCommit);
41878 $lastCommitNum = $lastCommitArr[1];
41879
41880 $branches = array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
41881
41882 return $branches;
41883 }
41884
41885 public function getTags()
41886 {
41887 $command = $this->generateP4Command('labels');
41888 $this->executeCommand($command);
41889 $result = $this->commandResult;
41890 $resArray = explode(PHP_EOL, $result);
41891 $tags = array();
41892 foreach ($resArray as $line) {
41893 $index = strpos($line, 'Label');
41894 if (!($index === false)) {
41895 $fields = explode(' ', $line);
41896 $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
41897 }
41898 }
41899
41900 return $tags;
41901 }
41902
41903 public function checkStream()
41904 {
41905 $command = $this->generateP4Command('depots', false);
41906 $this->executeCommand($command);
41907 $result = $this->commandResult;
41908 $resArray = explode(PHP_EOL, $result);
41909 foreach ($resArray as $line) {
41910 $index = strpos($line, 'Depot');
41911 if (!($index === false)) {
41912 $fields = explode(' ', $line);
41913 if (strcmp($this->p4Depot, $fields[1]) === 0) {
41914 $this->p4DepotType = $fields[3];
41915
41916 return $this->isStream();
41917 }
41918 }
41919 }
41920
41921 return false;
41922 }
41923
41924
41925
41926
41927
41928 protected function getChangeList($reference)
41929 {
41930 $index = strpos($reference, '@');
41931 if ($index === false) {
41932 return null;
41933 }
41934 $label = substr($reference, $index);
41935 $command = $this->generateP4Command(' changes -m1 ' . $label);
41936 $this->executeCommand($command);
41937 $changes = $this->commandResult;
41938 if (strpos($changes, 'Change') !== 0) {
41939 return null;
41940 }
41941 $fields = explode(' ', $changes);
41942
41943 return $fields[1];
41944 }
41945
41946
41947
41948
41949
41950
41951 public function getCommitLogs($fromReference, $toReference)
41952 {
41953 $fromChangeList = $this->getChangeList($fromReference);
41954 if ($fromChangeList === null) {
41955 return null;
41956 }
41957 $toChangeList = $this->getChangeList($toReference);
41958 if ($toChangeList === null) {
41959 return null;
41960 }
41961 $index = strpos($fromReference, '@');
41962 $main = substr($fromReference, 0, $index) . '/...';
41963 $command = $this->generateP4Command('filelog ' . $main . '@' . $fromChangeList. ',' . $toChangeList);
41964 $this->executeCommand($command);
41965
41966 return $this->commandResult;
41967 }
41968
41969 public function getFilesystem()
41970 {
41971 if (empty($this->filesystem)) {
41972 $this->filesystem = new Filesystem($this->process);
41973 }
41974
41975 return $this->filesystem;
41976 }
41977
41978 public function setFilesystem(Filesystem $fs)
41979 {
41980 $this->filesystem = $fs;
41981 }
41982 }
41983 <?php
41984
41985
41986
41987
41988
41989
41990
41991
41992
41993
41994
41995 namespace Composer\Util;
41996
41997
41998
41999
42000
42001
42002 class Platform
42003 {
42004
42005
42006
42007
42008
42009
42010 public static function expandPath($path)
42011 {
42012 if (preg_match('#^~[\\/]#', $path)) {
42013 return self::getUserDirectory() . substr($path, 1);
42014 }
42015
42016 return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
42017
42018  if (Platform::isWindows() && $matches['var'] == 'HOME') {
42019 return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches['path'];
42020 }
42021
42022 return getenv($matches['var']) . $matches['path'];
42023 }, $path);
42024 }
42025
42026
42027
42028
42029
42030 public static function getUserDirectory()
42031 {
42032 if (false !== ($home = getenv('HOME'))) {
42033 return $home;
42034 }
42035
42036 if (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) {
42037 return $home;
42038 }
42039
42040 if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
42041 $info = posix_getpwuid(posix_getuid());
42042
42043 return $info['dir'];
42044 }
42045
42046 throw new \RuntimeException('Could not determine user directory');
42047 }
42048
42049
42050
42051
42052 public static function isWindows()
42053 {
42054 return defined('PHP_WINDOWS_VERSION_BUILD');
42055 }
42056
42057
42058
42059
42060
42061 public static function strlen($str)
42062 {
42063 static $useMbString = null;
42064 if (null === $useMbString) {
42065 $useMbString = function_exists('mb_strlen') && ini_get('mbstring.func_overload');
42066 }
42067
42068 if ($useMbString) {
42069 return mb_strlen($str, '8bit');
42070 }
42071
42072 return strlen($str);
42073 }
42074 }
42075 <?php
42076
42077
42078
42079
42080
42081
42082
42083
42084
42085
42086
42087 namespace Composer\Util;
42088
42089 use Composer\IO\IOInterface;
42090 use Symfony\Component\Process\Process;
42091 use Symfony\Component\Process\ProcessUtils;
42092
42093
42094
42095
42096 class ProcessExecutor
42097 {
42098 protected static $timeout = 300;
42099
42100 protected $captureOutput;
42101 protected $errorOutput;
42102 protected $io;
42103
42104 public function __construct(IOInterface $io = null)
42105 {
42106 $this->io = $io;
42107 }
42108
42109
42110
42111
42112
42113
42114
42115
42116
42117
42118 public function execute($command, &$output = null, $cwd = null)
42119 {
42120 if ($this->io && $this->io->isDebug()) {
42121 $safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
42122 if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) {
42123 return '://***:***@';
42124 }
42125
42126 return '://'.$m['user'].':***@';
42127 }, $command);
42128 $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
42129 }
42130
42131
42132  
42133  if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) {
42134 $cwd = realpath(getcwd());
42135 }
42136
42137 $this->captureOutput = count(func_get_args()) > 1;
42138 $this->errorOutput = null;
42139 $process = new Process($command, $cwd, null, null, static::getTimeout());
42140
42141 $callback = is_callable($output) ? $output : array($this, 'outputHandler');
42142 $process->run($callback);
42143
42144 if ($this->captureOutput && !is_callable($output)) {
42145 $output = $process->getOutput();
42146 }
42147
42148 $this->errorOutput = $process->getErrorOutput();
42149
42150 return $process->getExitCode();
42151 }
42152
42153 public function splitLines($output)
42154 {
42155 $output = trim($output);
42156
42157 return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output);
42158 }
42159
42160
42161
42162
42163
42164
42165 public function getErrorOutput()
42166 {
42167 return $this->errorOutput;
42168 }
42169
42170 public function outputHandler($type, $buffer)
42171 {
42172 if ($this->captureOutput) {
42173 return;
42174 }
42175
42176 if (null === $this->io) {
42177 echo $buffer;
42178
42179 return;
42180 }
42181
42182 if (Process::ERR === $type) {
42183 $this->io->writeError($buffer, false);
42184 } else {
42185 $this->io->write($buffer, false);
42186 }
42187 }
42188
42189 public static function getTimeout()
42190 {
42191 return static::$timeout;
42192 }
42193
42194 public static function setTimeout($timeout)
42195 {
42196 static::$timeout = $timeout;
42197 }
42198
42199
42200
42201
42202
42203
42204
42205
42206 public static function escape($argument)
42207 {
42208 if (method_exists('Symfony\Component\Process\ProcessUtils', 'escapeArgument')) {
42209 return ProcessUtils::escapeArgument($argument);
42210 }
42211
42212 return self::escapeArgument($argument);
42213 }
42214
42215
42216
42217
42218
42219
42220
42221
42222 private static function escapeArgument($argument)
42223 {
42224
42225  
42226  
42227  
42228  if ('\\' === DIRECTORY_SEPARATOR) {
42229 if ('' === $argument) {
42230 return escapeshellarg($argument);
42231 }
42232
42233 $escapedArgument = '';
42234 $quote = false;
42235 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
42236 if ('"' === $part) {
42237 $escapedArgument .= '\\"';
42238 } elseif (self::isSurroundedBy($part, '%')) {
42239
42240  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
42241 } else {
42242
42243  if ('\\' === substr($part, -1)) {
42244 $part .= '\\';
42245 }
42246 $quote = true;
42247 $escapedArgument .= $part;
42248 }
42249 }
42250 if ($quote) {
42251 $escapedArgument = '"'.$escapedArgument.'"';
42252 }
42253
42254 return $escapedArgument;
42255 }
42256
42257 return "'".str_replace("'", "'\\''", $argument)."'";
42258 }
42259
42260 private static function isSurroundedBy($arg, $char)
42261 {
42262 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
42263 }
42264 }
42265 <?php
42266
42267
42268
42269
42270
42271
42272
42273
42274
42275
42276
42277 namespace Composer\Util;
42278
42279 use Composer\Config;
42280 use Composer\IO\IOInterface;
42281 use Composer\Downloader\TransportException;
42282 use Composer\CaBundle\CaBundle;
42283 use Psr\Log\LoggerInterface;
42284
42285
42286
42287
42288
42289
42290 class RemoteFilesystem
42291 {
42292 private $io;
42293 private $config;
42294 private $scheme;
42295 private $bytesMax;
42296 private $originUrl;
42297 private $fileUrl;
42298 private $fileName;
42299 private $retry;
42300 private $progress;
42301 private $lastProgress;
42302 private $options = array();
42303 private $peerCertificateMap = array();
42304 private $disableTls = false;
42305 private $retryAuthFailure;
42306 private $lastHeaders;
42307 private $storeAuth;
42308 private $degradedMode = false;
42309 private $redirects;
42310 private $maxRedirects = 20;
42311
42312
42313
42314
42315
42316
42317
42318
42319
42320 public function __construct(IOInterface $io, Config $config = null, array $options = array(), $disableTls = false)
42321 {
42322 $this->io = $io;
42323
42324
42325  
42326  if ($disableTls === false) {
42327 $this->options = $this->getTlsDefaults($options);
42328 } else {
42329 $this->disableTls = true;
42330 }
42331
42332
42333  $this->options = array_replace_recursive($this->options, $options);
42334 $this->config = $config;
42335 }
42336
42337
42338
42339
42340
42341
42342
42343
42344
42345
42346
42347
42348 public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array())
42349 {
42350 return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
42351 }
42352
42353
42354
42355
42356
42357
42358
42359
42360
42361
42362
42363 public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
42364 {
42365 return $this->get($originUrl, $fileUrl, $options, null, $progress);
42366 }
42367
42368
42369
42370
42371
42372
42373 public function getOptions()
42374 {
42375 return $this->options;
42376 }
42377
42378
42379
42380
42381
42382
42383 public function setOptions(array $options)
42384 {
42385 $this->options = array_replace_recursive($this->options, $options);
42386 }
42387
42388 public function isTlsDisabled()
42389 {
42390 return $this->disableTls === true;
42391 }
42392
42393
42394
42395
42396
42397
42398 public function getLastHeaders()
42399 {
42400 return $this->lastHeaders;
42401 }
42402
42403
42404
42405
42406
42407
42408 public function findHeaderValue(array $headers, $name)
42409 {
42410 $value = null;
42411 foreach ($headers as $header) {
42412 if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
42413 $value = $match[1];
42414 } elseif (preg_match('{^HTTP/}i', $header)) {
42415
42416  
42417  $value = null;
42418 }
42419 }
42420
42421 return $value;
42422 }
42423
42424
42425
42426
42427
42428 public function findStatusCode(array $headers)
42429 {
42430 $value = null;
42431 foreach ($headers as $header) {
42432 if (preg_match('{^HTTP/\S+ (\d+)}i', $header, $match)) {
42433
42434  
42435  $value = (int) $match[1];
42436 }
42437 }
42438
42439 return $value;
42440 }
42441
42442
42443
42444
42445
42446
42447
42448
42449
42450
42451
42452
42453
42454
42455
42456 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
42457 {
42458 if (strpos($originUrl, '.github.com') === (strlen($originUrl) - 11)) {
42459 $originUrl = 'github.com';
42460 }
42461
42462
42463  
42464  if (
42465 $this->config
42466 && is_array($this->config->get('gitlab-domains'))
42467 && false === strpos($originUrl, '/')
42468 && !in_array($originUrl, $this->config->get('gitlab-domains'))
42469 ) {
42470 foreach ($this->config->get('gitlab-domains') as $gitlabDomain) {
42471 if (0 === strpos($gitlabDomain, $originUrl)) {
42472 $originUrl = $gitlabDomain;
42473 break;
42474 }
42475 }
42476 unset($gitlabDomain);
42477 }
42478
42479 $this->scheme = parse_url($fileUrl, PHP_URL_SCHEME);
42480 $this->bytesMax = 0;
42481 $this->originUrl = $originUrl;
42482 $this->fileUrl = $fileUrl;
42483 $this->fileName = $fileName;
42484 $this->progress = $progress;
42485 $this->lastProgress = null;
42486 $this->retryAuthFailure = true;
42487 $this->lastHeaders = array();
42488 $this->redirects = 1; 
42489
42490
42491  if (preg_match('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $fileUrl, $match)) {
42492 $this->io->setAuthentication($originUrl, urldecode($match[1]), urldecode($match[2]));
42493 }
42494
42495 $tempAdditionalOptions = $additionalOptions;
42496 if (isset($tempAdditionalOptions['retry-auth-failure'])) {
42497 $this->retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure'];
42498
42499 unset($tempAdditionalOptions['retry-auth-failure']);
42500 }
42501
42502 $isRedirect = false;
42503 if (isset($tempAdditionalOptions['redirects'])) {
42504 $this->redirects = $tempAdditionalOptions['redirects'];
42505 $isRedirect = true;
42506
42507 unset($tempAdditionalOptions['redirects']);
42508 }
42509
42510 $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions);
42511 unset($tempAdditionalOptions);
42512
42513 $origFileUrl = $fileUrl;
42514
42515 if (isset($options['github-token'])) {
42516
42517  if (preg_match('{^https?://([a-z0-9-]+\.)*github\.com/}', $fileUrl)) {
42518 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['github-token'];
42519 }
42520 unset($options['github-token']);
42521 }
42522
42523 if (isset($options['gitlab-token'])) {
42524 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['gitlab-token'];
42525 unset($options['gitlab-token']);
42526 }
42527
42528 if (isset($options['http'])) {
42529 $options['http']['ignore_errors'] = true;
42530 }
42531
42532 if ($this->degradedMode && substr($fileUrl, 0, 21) === 'http://packagist.org/') {
42533
42534  $fileUrl = 'http://' . gethostbyname('packagist.org') . substr($fileUrl, 20);
42535 $degradedPackagist = true;
42536 }
42537
42538 $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
42539
42540 $actualContextOptions = stream_context_get_options($ctx);
42541 $usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : '';
42542 $this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $origFileUrl . $usingProxy, true, IOInterface::DEBUG);
42543 unset($origFileUrl, $actualContextOptions);
42544
42545
42546  if ((substr($fileUrl, 0, 23) !== 'http://packagist.org/p/' || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist) && $this->config) {
42547 $this->config->prohibitUrlByConfig($fileUrl, $this->io);
42548 }
42549
42550 if ($this->progress && !$isRedirect) {
42551 $this->io->writeError("Downloading (<comment>connecting...</comment>)", false);
42552 }
42553
42554 $errorMessage = '';
42555 $errorCode = 0;
42556 $result = false;
42557 set_error_handler(function ($code, $msg) use (&$errorMessage) {
42558 if ($errorMessage) {
42559 $errorMessage .= "\n";
42560 }
42561 $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg);
42562 });
42563 try {
42564 $result = file_get_contents($fileUrl, false, $ctx);
42565
42566 $contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
42567 if ($contentLength && Platform::strlen($result) < $contentLength) {
42568
42569  $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength);
42570 $e->setHeaders($http_response_header);
42571 $e->setStatusCode($this->findStatusCode($http_response_header));
42572 $e->setResponse($result);
42573 $this->io->writeError('Content-Length mismatch, received '.Platform::strlen($result).' out of '.$contentLength.' bytes: (' . base64_encode($result).')', true, IOInterface::DEBUG);
42574
42575 throw $e;
42576 }
42577
42578 if (PHP_VERSION_ID < 50600 && !empty($options['ssl']['peer_fingerprint'])) {
42579
42580  $params = stream_context_get_params($ctx);
42581 $expectedPeerFingerprint = $options['ssl']['peer_fingerprint'];
42582 $peerFingerprint = TlsHelper::getCertificateFingerprint($params['options']['ssl']['peer_certificate']);
42583
42584
42585  if ($expectedPeerFingerprint !== $peerFingerprint) {
42586 throw new TransportException('Peer fingerprint did not match');
42587 }
42588 }
42589 } catch (\Exception $e) {
42590 if ($e instanceof TransportException && !empty($http_response_header[0])) {
42591 $e->setHeaders($http_response_header);
42592 $e->setStatusCode($this->findStatusCode($http_response_header));
42593 }
42594 if ($e instanceof TransportException && $result !== false) {
42595 $e->setResponse($result);
42596 }
42597 $result = false;
42598 }
42599 if ($errorMessage && !ini_get('allow_url_fopen')) {
42600 $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
42601 }
42602 restore_error_handler();
42603 if (isset($e) && !$this->retry) {
42604 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
42605 $this->degradedMode = true;
42606 $this->io->writeError('');
42607 $this->io->writeError(array(
42608 '<error>'.$e->getMessage().'</error>',
42609 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42610 ));
42611
42612 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42613 }
42614
42615 throw $e;
42616 }
42617
42618 $statusCode = null;
42619 $contentType = null;
42620 if (!empty($http_response_header[0])) {
42621 $statusCode = $this->findStatusCode($http_response_header);
42622 $contentType = $this->findHeaderValue($http_response_header, 'content-type');
42623 }
42624
42625
42626  if ($originUrl === 'bitbucket.org'
42627 && !$this->isPublicBitBucketDownload($fileUrl)
42628 && substr($fileUrl, -4) === '.zip'
42629 && $contentType && preg_match('{^text/html\b}i', $contentType)
42630 ) {
42631 $result = false;
42632 if ($this->retryAuthFailure) {
42633 $this->promptAuthAndRetry(401);
42634 }
42635 }
42636
42637
42638  if ($statusCode === 404
42639 && $this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)
42640 && false !== strpos($fileUrl, 'archive.zip')
42641 ) {
42642 $result = false;
42643 if ($this->retryAuthFailure) {
42644 $this->promptAuthAndRetry(401);
42645 }
42646 }
42647
42648
42649  $hasFollowedRedirect = false;
42650 if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
42651 $hasFollowedRedirect = true;
42652 $result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
42653 }
42654
42655
42656  if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
42657 if (!$this->retry) {
42658 if ($this->progress && !$this->retry && !$isRedirect) {
42659 $this->io->overwriteError("Downloading (<error>failed</error>)", false);
42660 }
42661
42662 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $statusCode);
42663 $e->setHeaders($http_response_header);
42664 $e->setResponse($result);
42665 $e->setStatusCode($statusCode);
42666 throw $e;
42667 }
42668 $result = false;
42669 }
42670
42671 if ($this->progress && !$this->retry && !$isRedirect) {
42672 $this->io->overwriteError("Downloading (".($result === false ? '<error>failed</error>' : '<comment>100%</comment>').")", false);
42673 }
42674
42675
42676  if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) {
42677 $contentEncoding = $this->findHeaderValue($http_response_header, 'content-encoding');
42678 $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
42679
42680 if ($decode) {
42681 try {
42682 if (PHP_VERSION_ID >= 50400) {
42683 $result = zlib_decode($result);
42684 } else {
42685
42686  $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
42687 }
42688
42689 if (!$result) {
42690 throw new TransportException('Failed to decode zlib stream');
42691 }
42692 } catch (\Exception $e) {
42693 if ($this->degradedMode) {
42694 throw $e;
42695 }
42696
42697 $this->degradedMode = true;
42698 $this->io->writeError(array(
42699 '',
42700 '<error>Failed to decode response: '.$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 }
42708
42709
42710  if (false !== $result && null !== $fileName && !$isRedirect) {
42711 if ('' === $result) {
42712 throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
42713 }
42714
42715 $errorMessage = '';
42716 set_error_handler(function ($code, $msg) use (&$errorMessage) {
42717 if ($errorMessage) {
42718 $errorMessage .= "\n";
42719 }
42720 $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg);
42721 });
42722 $result = (bool) file_put_contents($fileName, $result);
42723 restore_error_handler();
42724 if (false === $result) {
42725 throw new TransportException('The "'.$this->fileUrl.'" file could not be written to '.$fileName.': '.$errorMessage);
42726 }
42727 }
42728
42729
42730  if (false === $result && false !== strpos($errorMessage, 'Peer certificate') && PHP_VERSION_ID < 50600) {
42731
42732  
42733  
42734  
42735  
42736  
42737  
42738  
42739  
42740  
42741  
42742  
42743  
42744  
42745  
42746  
42747  if (CaBundle::isOpensslParseSafe()) {
42748 $certDetails = $this->getCertificateCnAndFp($this->fileUrl, $options);
42749
42750 if ($certDetails) {
42751 $this->peerCertificateMap[$this->getUrlAuthority($this->fileUrl)] = $certDetails;
42752
42753 $this->retry = true;
42754 }
42755 } else {
42756 $this->io->writeError('');
42757 $this->io->writeError(sprintf(
42758 '<error>Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.</error>',
42759 PHP_VERSION
42760 ));
42761 }
42762 }
42763
42764 if ($this->retry) {
42765 $this->retry = false;
42766
42767 $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42768
42769 if ($this->storeAuth && $this->config) {
42770 $authHelper = new AuthHelper($this->io, $this->config);
42771 $authHelper->storeAuth($this->originUrl, $this->storeAuth);
42772 $this->storeAuth = false;
42773 }
42774
42775 return $result;
42776 }
42777
42778 if (false === $result) {
42779 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded: '.$errorMessage, $errorCode);
42780 if (!empty($http_response_header[0])) {
42781 $e->setHeaders($http_response_header);
42782 }
42783
42784 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
42785 $this->degradedMode = true;
42786 $this->io->writeError('');
42787 $this->io->writeError(array(
42788 '<error>'.$e->getMessage().'</error>',
42789 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42790 ));
42791
42792 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42793 }
42794
42795 throw $e;
42796 }
42797
42798 if (!empty($http_response_header[0])) {
42799 $this->lastHeaders = $http_response_header;
42800 }
42801
42802 return $result;
42803 }
42804
42805
42806
42807
42808
42809
42810
42811
42812
42813
42814
42815
42816 protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
42817 {
42818 switch ($notificationCode) {
42819 case STREAM_NOTIFY_FAILURE:
42820 if (400 === $messageCode) {
42821
42822  
42823  throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
42824 }
42825
42826  
42827
42828 case STREAM_NOTIFY_AUTH_REQUIRED:
42829 if (401 === $messageCode) {
42830
42831  if (!$this->retryAuthFailure) {
42832 break;
42833 }
42834
42835 $this->promptAuthAndRetry($messageCode);
42836 }
42837 break;
42838
42839 case STREAM_NOTIFY_AUTH_RESULT:
42840 if (403 === $messageCode) {
42841
42842  if (!$this->retryAuthFailure) {
42843 break;
42844 }
42845
42846 $this->promptAuthAndRetry($messageCode, $message);
42847 }
42848 break;
42849
42850 case STREAM_NOTIFY_FILE_SIZE_IS:
42851 $this->bytesMax = $bytesMax;
42852 break;
42853
42854 case STREAM_NOTIFY_PROGRESS:
42855 if ($this->bytesMax > 0 && $this->progress) {
42856 $progression = min(100, round($bytesTransferred / $this->bytesMax * 100));
42857
42858 if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) {
42859 $this->lastProgress = $progression;
42860 $this->io->overwriteError("Downloading (<comment>$progression%</comment>)", false);
42861 }
42862 }
42863 break;
42864
42865 default:
42866 break;
42867 }
42868 }
42869
42870 protected function promptAuthAndRetry($httpStatus, $reason = null)
42871 {
42872 if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
42873 $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');
42874 $gitHubUtil = new GitHub($this->io, $this->config, null);
42875 if (!$gitHubUtil->authorizeOAuth($this->originUrl)
42876 && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($this->originUrl, $message))
42877 ) {
42878 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
42879 }
42880 } elseif ($this->config && in_array($this->originUrl, $this->config->get('gitlab-domains'), true)) {
42881 $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');
42882 $gitLabUtil = new GitLab($this->io, $this->config, null);
42883
42884 if ($this->io->hasAuthentication($this->originUrl) && ($auth = $this->io->getAuthentication($this->originUrl)) && $auth['password'] === 'private-token') {
42885 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
42886 }
42887
42888 if (!$gitLabUtil->authorizeOAuth($this->originUrl)
42889 && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, $message))
42890 ) {
42891 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
42892 }
42893 } elseif ($this->config && $this->originUrl === 'bitbucket.org') {
42894 $askForOAuthToken = true;
42895 if ($this->io->hasAuthentication($this->originUrl)) {
42896 $auth = $this->io->getAuthentication($this->originUrl);
42897 if ($auth['username'] !== 'x-token-auth') {
42898 $bitbucketUtil = new Bitbucket($this->io, $this->config);
42899 $accessToken = $bitbucketUtil->requestToken($this->originUrl, $auth['username'], $auth['password']);
42900 if (!empty($accessToken)) {
42901 $this->io->setAuthentication($this->originUrl, 'x-token-auth', $accessToken);
42902 $askForOAuthToken = false;
42903 }
42904 } else {
42905 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
42906 }
42907 }
42908
42909 if ($askForOAuthToken) {
42910 $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');
42911 $bitBucketUtil = new Bitbucket($this->io, $this->config);
42912 if (! $bitBucketUtil->authorizeOAuth($this->originUrl)
42913 && (! $this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($this->originUrl, $message))
42914 ) {
42915 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
42916 }
42917 }
42918 } else {
42919
42920  if ($httpStatus === 404) {
42921 return;
42922 }
42923
42924
42925  if (!$this->io->isInteractive()) {
42926 if ($httpStatus === 401) {
42927 $message = "The '" . $this->fileUrl . "' URL required authentication.\nYou must be using the interactive console to authenticate";
42928 }
42929 if ($httpStatus === 403) {
42930 $message = "The '" . $this->fileUrl . "' URL could not be accessed: " . $reason;
42931 }
42932
42933 throw new TransportException($message, $httpStatus);
42934 }
42935
42936  if ($this->io->hasAuthentication($this->originUrl)) {
42937 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
42938 }
42939
42940 $this->io->overwriteError('');
42941 $this->io->writeError('    Authentication required (<info>'.parse_url($this->fileUrl, PHP_URL_HOST).'</info>):');
42942 $username = $this->io->ask('      Username: ');
42943 $password = $this->io->askAndHideAnswer('      Password: ');
42944 $this->io->setAuthentication($this->originUrl, $username, $password);
42945 $this->storeAuth = $this->config->get('store-auths');
42946 }
42947
42948 $this->retry = true;
42949 throw new TransportException('RETRY');
42950 }
42951
42952 protected function getOptionsForUrl($originUrl, $additionalOptions)
42953 {
42954 $tlsOptions = array();
42955
42956
42957  if ($this->disableTls === false && PHP_VERSION_ID < 50600 && !stream_is_local($this->fileUrl)) {
42958 $host = parse_url($this->fileUrl, PHP_URL_HOST);
42959
42960 if (PHP_VERSION_ID < 50304) {
42961
42962  
42963  
42964  
42965
42966 if ($host === 'github.com' || $host === 'api.github.com') {
42967 $host = '*.github.com';
42968 }
42969 }
42970
42971 $tlsOptions['ssl']['CN_match'] = $host;
42972 $tlsOptions['ssl']['SNI_server_name'] = $host;
42973
42974 $urlAuthority = $this->getUrlAuthority($this->fileUrl);
42975
42976 if (isset($this->peerCertificateMap[$urlAuthority])) {
42977
42978  $certMap = $this->peerCertificateMap[$urlAuthority];
42979
42980 $this->io->writeError('', true, IOInterface::DEBUG);
42981 $this->io->writeError(sprintf(
42982 'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
42983 $certMap['cn'],
42984 $urlAuthority
42985 ), true, IOInterface::DEBUG);
42986
42987 $tlsOptions['ssl']['CN_match'] = $certMap['cn'];
42988 $tlsOptions['ssl']['peer_fingerprint'] = $certMap['fp'];
42989 }
42990 }
42991
42992 $headers = array();
42993
42994 if (extension_loaded('zlib')) {
42995 $headers[] = 'Accept-Encoding: gzip';
42996 }
42997
42998 $options = array_replace_recursive($this->options, $tlsOptions, $additionalOptions);
42999 if (!$this->degradedMode) {
43000
43001  
43002  $options['http']['protocol_version'] = 1.1;
43003 $headers[] = 'Connection: close';
43004 }
43005
43006 if ($this->io->hasAuthentication($originUrl)) {
43007 $auth = $this->io->getAuthentication($originUrl);
43008 if ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
43009 $options['github-token'] = $auth['username'];
43010 } elseif ($this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
43011 if ($auth['password'] === 'oauth2') {
43012 $headers[] = 'Authorization: Bearer '.$auth['username'];
43013 } elseif ($auth['password'] === 'private-token') {
43014 $headers[] = 'PRIVATE-TOKEN: '.$auth['username'];
43015 }
43016 } elseif ('bitbucket.org' === $originUrl
43017 && $this->fileUrl !== Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']
43018 ) {
43019 if (!$this->isPublicBitBucketDownload($this->fileUrl)) {
43020 $headers[] = 'Authorization: Bearer ' . $auth['password'];
43021 }
43022 } else {
43023 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
43024 $headers[] = 'Authorization: Basic '.$authStr;
43025 }
43026 }
43027
43028 $options['http']['follow_location'] = 0;
43029
43030 if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
43031 $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
43032 }
43033 foreach ($headers as $header) {
43034 $options['http']['header'][] = $header;
43035 }
43036
43037 return $options;
43038 }
43039
43040 private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
43041 {
43042 if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
43043 if (parse_url($locationHeader, PHP_URL_SCHEME)) {
43044
43045  $targetUrl = $locationHeader;
43046 } elseif (parse_url($locationHeader, PHP_URL_HOST)) {
43047
43048  $targetUrl = $this->scheme.':'.$locationHeader;
43049 } elseif ('/' === $locationHeader[0]) {
43050
43051  $urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
43052
43053
43054  $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
43055 } else {
43056
43057  
43058  $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
43059 }
43060 }
43061
43062 if (!empty($targetUrl)) {
43063 $this->redirects++;
43064
43065 $this->io->writeError('', true, IOInterface::DEBUG);
43066 $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $targetUrl), true, IOInterface::DEBUG);
43067
43068 $additionalOptions['redirects'] = $this->redirects;
43069
43070 return $this->get(parse_url($targetUrl, PHP_URL_HOST), $targetUrl, $additionalOptions, $this->fileName, $this->progress);
43071 }
43072
43073 if (!$this->retry) {
43074 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
43075 $e->setHeaders($http_response_header);
43076 $e->setResponse($result);
43077
43078 throw $e;
43079 }
43080
43081 return false;
43082 }
43083
43084
43085
43086
43087
43088
43089 private function getTlsDefaults(array $options)
43090 {
43091 $ciphers = implode(':', array(
43092 'ECDHE-RSA-AES128-GCM-SHA256',
43093 'ECDHE-ECDSA-AES128-GCM-SHA256',
43094 'ECDHE-RSA-AES256-GCM-SHA384',
43095 'ECDHE-ECDSA-AES256-GCM-SHA384',
43096 'DHE-RSA-AES128-GCM-SHA256',
43097 'DHE-DSS-AES128-GCM-SHA256',
43098 'kEDH+AESGCM',
43099 'ECDHE-RSA-AES128-SHA256',
43100 'ECDHE-ECDSA-AES128-SHA256',
43101 'ECDHE-RSA-AES128-SHA',
43102 'ECDHE-ECDSA-AES128-SHA',
43103 'ECDHE-RSA-AES256-SHA384',
43104 'ECDHE-ECDSA-AES256-SHA384',
43105 'ECDHE-RSA-AES256-SHA',
43106 'ECDHE-ECDSA-AES256-SHA',
43107 'DHE-RSA-AES128-SHA256',
43108 'DHE-RSA-AES128-SHA',
43109 'DHE-DSS-AES128-SHA256',
43110 'DHE-RSA-AES256-SHA256',
43111 'DHE-DSS-AES256-SHA',
43112 'DHE-RSA-AES256-SHA',
43113 'AES128-GCM-SHA256',
43114 'AES256-GCM-SHA384',
43115 'AES128-SHA256',
43116 'AES256-SHA256',
43117 'AES128-SHA',
43118 'AES256-SHA',
43119 'AES',
43120 'CAMELLIA',
43121 'DES-CBC3-SHA',
43122 '!aNULL',
43123 '!eNULL',
43124 '!EXPORT',
43125 '!DES',
43126 '!RC4',
43127 '!MD5',
43128 '!PSK',
43129 '!aECDH',
43130 '!EDH-DSS-DES-CBC3-SHA',
43131 '!EDH-RSA-DES-CBC3-SHA',
43132 '!KRB5-DES-CBC3-SHA',
43133 ));
43134
43135
43136
43137
43138
43139
43140
43141 $defaults = array(
43142 'ssl' => array(
43143 'ciphers' => $ciphers,
43144 'verify_peer' => true,
43145 'verify_depth' => 7,
43146 'SNI_enabled' => true,
43147 'capture_peer_cert' => true,
43148 ),
43149 );
43150
43151 if (isset($options['ssl'])) {
43152 $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
43153 }
43154
43155 $caBundleLogger = $this->io instanceof LoggerInterface ? $this->io : null;
43156
43157
43158
43159
43160
43161 if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
43162 $result = CaBundle::getSystemCaRootBundlePath($caBundleLogger);
43163
43164 if (is_dir($result)) {
43165 $defaults['ssl']['capath'] = $result;
43166 } else {
43167 $defaults['ssl']['cafile'] = $result;
43168 }
43169 }
43170
43171 if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $caBundleLogger))) {
43172 throw new TransportException('The configured cafile was not valid or could not be read.');
43173 }
43174
43175 if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !is_readable($defaults['ssl']['capath']))) {
43176 throw new TransportException('The configured capath was not valid or could not be read.');
43177 }
43178
43179
43180
43181
43182 if (PHP_VERSION_ID >= 50413) {
43183 $defaults['ssl']['disable_compression'] = true;
43184 }
43185
43186 return $defaults;
43187 }
43188
43189
43190
43191
43192
43193
43194 private function getCertificateCnAndFp($url, $options)
43195 {
43196 if (PHP_VERSION_ID >= 50600) {
43197 throw new \BadMethodCallException(sprintf(
43198 '%s must not be used on PHP >= 5.6',
43199 __METHOD__
43200 ));
43201 }
43202
43203 $context = StreamContextFactory::getContext($url, $options, array('options' => array(
43204 'ssl' => array(
43205 'capture_peer_cert' => true,
43206 'verify_peer' => false, 
43207  ), ),
43208 ));
43209
43210
43211  
43212  if (false === $handle = @fopen($url, 'rb', false, $context)) {
43213 return;
43214 }
43215
43216
43217  fclose($handle);
43218 $handle = null;
43219
43220 $params = stream_context_get_params($context);
43221
43222 if (!empty($params['options']['ssl']['peer_certificate'])) {
43223 $peerCertificate = $params['options']['ssl']['peer_certificate'];
43224
43225 if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) {
43226 return array(
43227 'cn' => $commonName,
43228 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate),
43229 );
43230 }
43231 }
43232 }
43233
43234 private function getUrlAuthority($url)
43235 {
43236 $defaultPorts = array(
43237 'ftp' => 21,
43238 'http' => 80,
43239 'https' => 443,
43240 'ssh2.sftp' => 22,
43241 'ssh2.scp' => 22,
43242 );
43243
43244 $scheme = parse_url($url, PHP_URL_SCHEME);
43245
43246 if (!isset($defaultPorts[$scheme])) {
43247 throw new \InvalidArgumentException(sprintf(
43248 'Could not get default port for unknown scheme: %s',
43249 $scheme
43250 ));
43251 }
43252
43253 $defaultPort = $defaultPorts[$scheme];
43254 $port = parse_url($url, PHP_URL_PORT) ?: $defaultPort;
43255
43256 return parse_url($url, PHP_URL_HOST).':'.$port;
43257 }
43258
43259
43260
43261
43262
43263
43264
43265
43266 private function isPublicBitBucketDownload($urlToBitBucketFile)
43267 {
43268 $domain = parse_url($urlToBitBucketFile, PHP_URL_HOST);
43269 if (strpos($domain, 'bitbucket.org') === false) {
43270
43271  
43272  return true;
43273 }
43274
43275 $path = parse_url($urlToBitBucketFile, PHP_URL_PATH);
43276
43277
43278  
43279  $pathParts = explode('/', $path);
43280
43281 return count($pathParts) >= 4 && $pathParts[3] == 'downloads';
43282 }
43283 }
43284 <?php
43285
43286
43287
43288
43289
43290
43291
43292
43293
43294
43295
43296 namespace Composer\Util;
43297
43298
43299
43300
43301
43302
43303 class Silencer
43304 {
43305
43306
43307
43308 private static $stack = array();
43309
43310
43311
43312
43313
43314
43315
43316 public static function suppress($mask = null)
43317 {
43318 if (!isset($mask)) {
43319 $mask = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT;
43320 }
43321 $old = error_reporting();
43322 self::$stack[] = $old;
43323 error_reporting($old & ~$mask);
43324
43325 return $old;
43326 }
43327
43328
43329
43330
43331 public static function restore()
43332 {
43333 if (!empty(self::$stack)) {
43334 error_reporting(array_pop(self::$stack));
43335 }
43336 }
43337
43338
43339
43340
43341
43342
43343
43344
43345
43346
43347 public static function call($callable )
43348 {
43349 try {
43350 self::suppress();
43351 $result = call_user_func_array($callable, array_slice(func_get_args(), 1));
43352 self::restore();
43353
43354 return $result;
43355 } catch (\Exception $e) {
43356
43357  self::restore();
43358 throw $e;
43359 }
43360 }
43361 }
43362 <?php
43363
43364
43365
43366
43367
43368
43369
43370
43371
43372
43373
43374 namespace Composer\Util;
43375
43376 use Composer\Spdx\SpdxLicenses;
43377
43378 trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED);
43379
43380
43381
43382
43383 class SpdxLicense extends SpdxLicenses
43384 {
43385 }
43386 <?php
43387
43388
43389
43390
43391
43392
43393
43394
43395
43396
43397
43398 namespace Composer\Util;
43399
43400 use Composer\Composer;
43401
43402
43403
43404
43405
43406
43407
43408 final class StreamContextFactory
43409 {
43410
43411
43412
43413
43414
43415
43416
43417
43418
43419 public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
43420 {
43421 $options = array('http' => array(
43422
43423  'follow_location' => 1,
43424 'max_redirects' => 20,
43425 ));
43426
43427
43428  if (PHP_SAPI === 'cli' && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) {
43429 $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
43430 }
43431
43432
43433  if (!empty($_SERVER['CGI_HTTP_PROXY'])) {
43434 $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']);
43435 }
43436
43437
43438  if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
43439 $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
43440 }
43441
43442
43443  if (!empty($_SERVER['NO_PROXY']) || !empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
43444 $pattern = new NoProxyPattern(!empty($_SERVER['no_proxy']) ? $_SERVER['no_proxy'] : $_SERVER['NO_PROXY']);
43445 if ($pattern->test($url)) {
43446 unset($proxy);
43447 }
43448 }
43449
43450 if (!empty($proxy)) {
43451 $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
43452 $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
43453
43454 if (isset($proxy['port'])) {
43455 $proxyURL .= ":" . $proxy['port'];
43456 } elseif ('http://' == substr($proxyURL, 0, 7)) {
43457 $proxyURL .= ":80";
43458 } elseif ('https://' == substr($proxyURL, 0, 8)) {
43459 $proxyURL .= ":443";
43460 }
43461
43462
43463  $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
43464
43465 if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) {
43466 throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
43467 }
43468
43469 $options['http']['proxy'] = $proxyURL;
43470
43471
43472  switch (parse_url($url, PHP_URL_SCHEME)) {
43473 case 'http': 
43474  $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
43475 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
43476 $options['http']['request_fulluri'] = true;
43477 }
43478 break;
43479 case 'https': 
43480  $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
43481 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
43482 $options['http']['request_fulluri'] = true;
43483 }
43484 break;
43485 }
43486
43487
43488  if ('https' === parse_url($url, PHP_URL_SCHEME)) {
43489 $options['ssl']['SNI_enabled'] = true;
43490 if (PHP_VERSION_ID < 50600) {
43491 $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST);
43492 }
43493 }
43494
43495
43496  if (isset($proxy['user'])) {
43497 $auth = urldecode($proxy['user']);
43498 if (isset($proxy['pass'])) {
43499 $auth .= ':' . urldecode($proxy['pass']);
43500 }
43501 $auth = base64_encode($auth);
43502
43503
43504  if (isset($defaultOptions['http']['header'])) {
43505 if (is_string($defaultOptions['http']['header'])) {
43506 $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
43507 }
43508 $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
43509 } else {
43510 $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
43511 }
43512 }
43513 }
43514
43515 $options = array_replace_recursive($options, $defaultOptions);
43516
43517 if (isset($options['http']['header'])) {
43518 $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
43519 }
43520
43521 if (defined('HHVM_VERSION')) {
43522 $phpVersion = 'HHVM ' . HHVM_VERSION;
43523 } else {
43524 $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
43525 }
43526
43527 if (!isset($options['http']['header']) || false === stripos(implode('', $options['http']['header']), 'user-agent')) {
43528 $options['http']['header'][] = sprintf(
43529 'User-Agent: Composer/%s (%s; %s; %s%s)',
43530 Composer::VERSION === '@package_version@' ? 'source' : Composer::VERSION,
43531 function_exists('php_uname') ? php_uname('s') : 'Unknown',
43532 function_exists('php_uname') ? php_uname('r') : 'Unknown',
43533 $phpVersion,
43534 getenv('CI') ? '; CI' : ''
43535 );
43536 }
43537
43538 return stream_context_create($options, $defaultParams);
43539 }
43540
43541
43542
43543
43544
43545
43546
43547
43548
43549
43550
43551 private static function fixHttpHeaderField($header)
43552 {
43553 if (!is_array($header)) {
43554 $header = explode("\r\n", $header);
43555 }
43556 uasort($header, function ($el) {
43557 return preg_match('{^content-type}i', $el) ? 1 : -1;
43558 });
43559
43560 return $header;
43561 }
43562 }
43563 <?php
43564
43565
43566
43567
43568
43569
43570
43571
43572
43573
43574
43575 namespace Composer\Util;
43576
43577 use Composer\Config;
43578 use Composer\IO\IOInterface;
43579
43580
43581
43582
43583
43584 class Svn
43585 {
43586 const MAX_QTY_AUTH_TRIES = 5;
43587
43588
43589
43590
43591 protected $credentials;
43592
43593
43594
43595
43596 protected $hasAuth;
43597
43598
43599
43600
43601 protected $io;
43602
43603
43604
43605
43606 protected $url;
43607
43608
43609
43610
43611 protected $cacheCredentials = true;
43612
43613
43614
43615
43616 protected $process;
43617
43618
43619
43620
43621 protected $qtyAuthTries = 0;
43622
43623
43624
43625
43626 protected $config;
43627
43628
43629
43630
43631
43632
43633
43634 public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null)
43635 {
43636 $this->url = $url;
43637 $this->io = $io;
43638 $this->config = $config;
43639 $this->process = $process ?: new ProcessExecutor;
43640 }
43641
43642 public static function cleanEnv()
43643 {
43644
43645  putenv("DYLD_LIBRARY_PATH");
43646 unset($_SERVER['DYLD_LIBRARY_PATH']);
43647 }
43648
43649
43650
43651
43652
43653
43654
43655
43656
43657
43658
43659
43660
43661
43662 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
43663 {
43664
43665  $this->config->prohibitUrlByConfig($url, $this->io);
43666
43667 $svnCommand = $this->getCommand($command, $url, $path);
43668 $output = null;
43669 $io = $this->io;
43670 $handler = function ($type, $buffer) use (&$output, $io, $verbose) {
43671 if ($type !== 'out') {
43672 return;
43673 }
43674 if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
43675 return;
43676 }
43677 $output .= $buffer;
43678 if ($verbose) {
43679 $io->writeError($buffer, false);
43680 }
43681 };
43682 $status = $this->process->execute($svnCommand, $handler, $cwd);
43683 if (0 === $status) {
43684 return $output;
43685 }
43686
43687 $errorOutput = $this->process->getErrorOutput();
43688 $fullOutput = implode("\n", array($output, $errorOutput));
43689
43690
43691  if (false === stripos($fullOutput, 'Could not authenticate to server:')
43692 && false === stripos($fullOutput, 'authorization failed')
43693 && false === stripos($fullOutput, 'svn: E170001:')
43694 && false === stripos($fullOutput, 'svn: E215004:')) {
43695 throw new \RuntimeException($fullOutput);
43696 }
43697
43698 if (!$this->hasAuth()) {
43699 $this->doAuthDance();
43700 }
43701
43702
43703  if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
43704
43705  return $this->execute($command, $url, $cwd, $path, $verbose);
43706 }
43707
43708 throw new \RuntimeException(
43709 'wrong credentials provided ('.$fullOutput.')'
43710 );
43711 }
43712
43713
43714
43715
43716 public function setCacheCredentials($cacheCredentials)
43717 {
43718 $this->cacheCredentials = $cacheCredentials;
43719 }
43720
43721
43722
43723
43724
43725
43726
43727 protected function doAuthDance()
43728 {
43729
43730  if (!$this->io->isInteractive()) {
43731 throw new \RuntimeException(
43732 'can not ask for authentication in non interactive mode'
43733 );
43734 }
43735
43736 $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
43737
43738 $this->hasAuth = true;
43739 $this->credentials['username'] = $this->io->ask("Username: ");
43740 $this->credentials['password'] = $this->io->askAndHideAnswer("Password: ");
43741
43742 $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ", true);
43743
43744 return $this;
43745 }
43746
43747
43748
43749
43750
43751
43752
43753
43754
43755
43756 protected function getCommand($cmd, $url, $path = null)
43757 {
43758 $cmd = sprintf('%s %s%s %s',
43759 $cmd,
43760 '--non-interactive ',
43761 $this->getCredentialString(),
43762 ProcessExecutor::escape($url)
43763 );
43764
43765 if ($path) {
43766 $cmd .= ' ' . ProcessExecutor::escape($path);
43767 }
43768
43769 return $cmd;
43770 }
43771
43772
43773
43774
43775
43776
43777
43778
43779 protected function getCredentialString()
43780 {
43781 if (!$this->hasAuth()) {
43782 return '';
43783 }
43784
43785 return sprintf(
43786 ' %s--username %s --password %s ',
43787 $this->getAuthCache(),
43788 ProcessExecutor::escape($this->getUsername()),
43789 ProcessExecutor::escape($this->getPassword())
43790 );
43791 }
43792
43793
43794
43795
43796
43797
43798
43799 protected function getPassword()
43800 {
43801 if ($this->credentials === null) {
43802 throw new \LogicException("No svn auth detected.");
43803 }
43804
43805 return isset($this->credentials['password']) ? $this->credentials['password'] : '';
43806 }
43807
43808
43809
43810
43811
43812
43813
43814 protected function getUsername()
43815 {
43816 if ($this->credentials === null) {
43817 throw new \LogicException("No svn auth detected.");
43818 }
43819
43820 return $this->credentials['username'];
43821 }
43822
43823
43824
43825
43826
43827
43828 protected function hasAuth()
43829 {
43830 if (null !== $this->hasAuth) {
43831 return $this->hasAuth;
43832 }
43833
43834 if (false === $this->createAuthFromConfig()) {
43835 $this->createAuthFromUrl();
43836 }
43837
43838 return $this->hasAuth;
43839 }
43840
43841
43842
43843
43844
43845
43846 protected function getAuthCache()
43847 {
43848 return $this->cacheCredentials ? '' : '--no-auth-cache ';
43849 }
43850
43851
43852
43853
43854
43855
43856 private function createAuthFromConfig()
43857 {
43858 if (!$this->config->has('http-basic')) {
43859 return $this->hasAuth = false;
43860 }
43861
43862 $authConfig = $this->config->get('http-basic');
43863
43864 $host = parse_url($this->url, PHP_URL_HOST);
43865 if (isset($authConfig[$host])) {
43866 $this->credentials['username'] = $authConfig[$host]['username'];
43867 $this->credentials['password'] = $authConfig[$host]['password'];
43868
43869 return $this->hasAuth = true;
43870 }
43871
43872 return $this->hasAuth = false;
43873 }
43874
43875
43876
43877
43878
43879
43880 private function createAuthFromUrl()
43881 {
43882 $uri = parse_url($this->url);
43883 if (empty($uri['user'])) {
43884 return $this->hasAuth = false;
43885 }
43886
43887 $this->credentials['username'] = $uri['user'];
43888 if (!empty($uri['pass'])) {
43889 $this->credentials['password'] = $uri['pass'];
43890 }
43891
43892 return $this->hasAuth = true;
43893 }
43894 }
43895 <?php
43896
43897
43898
43899
43900
43901
43902
43903
43904
43905
43906
43907 namespace Composer\Util;
43908
43909 use Composer\CaBundle\CaBundle;
43910
43911
43912
43913
43914 final class TlsHelper
43915 {
43916 private static $useOpensslParse;
43917
43918
43919
43920
43921
43922
43923
43924
43925
43926
43927 public static function checkCertificateHost($certificate, $hostname, &$cn = null)
43928 {
43929 $names = self::getCertificateNames($certificate);
43930
43931 if (empty($names)) {
43932 return false;
43933 }
43934
43935 $combinedNames = array_merge($names['san'], array($names['cn']));
43936 $hostname = strtolower($hostname);
43937
43938 foreach ($combinedNames as $certName) {
43939 $matcher = self::certNameMatcher($certName);
43940
43941 if ($matcher && $matcher($hostname)) {
43942 $cn = $names['cn'];
43943
43944 return true;
43945 }
43946 }
43947
43948 return false;
43949 }
43950
43951
43952
43953
43954
43955
43956
43957
43958 public static function getCertificateNames($certificate)
43959 {
43960 if (is_array($certificate)) {
43961 $info = $certificate;
43962 } elseif (CaBundle::isOpensslParseSafe()) {
43963 $info = openssl_x509_parse($certificate, false);
43964 }
43965
43966 if (!isset($info['subject']['commonName'])) {
43967 return null;
43968 }
43969
43970 $commonName = strtolower($info['subject']['commonName']);
43971 $subjectAltNames = array();
43972
43973 if (isset($info['extensions']['subjectAltName'])) {
43974 $subjectAltNames = preg_split('{\s*,\s*}', $info['extensions']['subjectAltName']);
43975 $subjectAltNames = array_filter(array_map(function ($name) {
43976 if (0 === strpos($name, 'DNS:')) {
43977 return strtolower(ltrim(substr($name, 4)));
43978 }
43979
43980 return null;
43981 }, $subjectAltNames));
43982 $subjectAltNames = array_values($subjectAltNames);
43983 }
43984
43985 return array(
43986 'cn' => $commonName,
43987 'san' => $subjectAltNames,
43988 );
43989 }
43990
43991
43992
43993
43994
43995
43996
43997
43998
43999
44000
44001
44002
44003
44004
44005
44006
44007
44008
44009
44010
44011
44012
44013
44014
44015
44016
44017
44018
44019
44020
44021
44022
44023
44024
44025
44026
44027
44028
44029
44030 public static function getCertificateFingerprint($certificate)
44031 {
44032 $pubkeydetails = openssl_pkey_get_details(openssl_get_publickey($certificate));
44033 $pubkeypem = $pubkeydetails['key'];
44034
44035  $start = '-----BEGIN PUBLIC KEY-----';
44036 $end = '-----END PUBLIC KEY-----';
44037 $pemtrim = substr($pubkeypem, (strpos($pubkeypem, $start) + strlen($start)), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
44038 $der = base64_decode($pemtrim);
44039
44040 return sha1($der);
44041 }
44042
44043
44044
44045
44046
44047
44048
44049
44050
44051 public static function isOpensslParseSafe()
44052 {
44053 return CaBundle::isOpensslParseSafe();
44054 }
44055
44056
44057
44058
44059
44060
44061
44062
44063 private static function certNameMatcher($certName)
44064 {
44065 $wildcards = substr_count($certName, '*');
44066
44067 if (0 === $wildcards) {
44068
44069  return function ($hostname) use ($certName) {
44070 return $hostname === $certName;
44071 };
44072 }
44073
44074 if (1 === $wildcards) {
44075 $components = explode('.', $certName);
44076
44077 if (3 > count($components)) {
44078
44079  return;
44080 }
44081
44082 $firstComponent = $components[0];
44083
44084
44085  if ('*' !== $firstComponent[strlen($firstComponent) - 1]) {
44086 return;
44087 }
44088
44089 $wildcardRegex = preg_quote($certName);
44090 $wildcardRegex = str_replace('\\*', '[a-z0-9-]+', $wildcardRegex);
44091 $wildcardRegex = "{^{$wildcardRegex}$}";
44092
44093 return function ($hostname) use ($wildcardRegex) {
44094 return 1 === preg_match($wildcardRegex, $hostname);
44095 };
44096 }
44097 }
44098 }
44099 <?php
44100
44101
44102
44103
44104
44105
44106
44107
44108
44109
44110
44111 namespace Composer\Util;
44112
44113 use Composer\Config;
44114 use Composer\IO\IOInterface;
44115
44116
44117
44118
44119 class Url
44120 {
44121 public static function updateDistReference(Config $config, $url, $ref)
44122 {
44123 $host = parse_url($url, PHP_URL_HOST);
44124
44125 if ($host === 'api.github.com' || $host === 'github.com' || $host === 'www.github.com') {
44126 if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
44127
44128  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
44129 } elseif (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
44130
44131  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
44132 } elseif (preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
44133
44134  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
44135 }
44136 } elseif ($host === 'bitbucket.org' || $host === 'www.bitbucket.org') {
44137 if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
44138
44139  $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $ref . '.' . $match[4];
44140 }
44141 } elseif ($host === 'gitlab.com' || $host === 'www.gitlab.com') {
44142 if (preg_match('{^https?://(?:www\.)?gitlab\.com/api/v[34]/projects/([^/]+)/repository/archive\.(zip|tar\.gz|tar\.bz2|tar)\?sha=.+$}i', $url, $match)) {
44143
44144  $url = 'https://gitlab.com/api/v4/projects/' . $match[1] . '/repository/archive.' . $match[2] . '?sha=' . $ref;
44145 }
44146 } elseif (in_array($host, $config->get('github-domains'), true)) {
44147 $url = preg_replace('{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i', '$1/'.$ref, $url);
44148 } elseif (in_array($host, $config->get('gitlab-domains'), true)) {
44149 $url = preg_replace('{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i', '$1'.$ref, $url);
44150 }
44151
44152 return $url;
44153 }
44154 }
44155 <?php
44156
44157
44158
44159
44160
44161
44162
44163
44164
44165
44166
44167 namespace Composer;
44168
44169 use Composer\Util\IniHelper;
44170 use Symfony\Component\Console\Output\OutputInterface;
44171
44172
44173
44174
44175 class XdebugHandler
44176 {
44177 const ENV_ALLOW = 'COMPOSER_ALLOW_XDEBUG';
44178 const ENV_VERSION = 'COMPOSER_XDEBUG_VERSION';
44179 const RESTART_ID = 'internal';
44180
44181 private $output;
44182 private $loaded;
44183 private $envScanDir;
44184 private $version;
44185 private $tmpIni;
44186
44187
44188
44189
44190 public function __construct(OutputInterface $output)
44191 {
44192 $this->output = $output;
44193 $this->loaded = extension_loaded('xdebug');
44194 $this->envScanDir = getenv('PHP_INI_SCAN_DIR');
44195
44196 if ($this->loaded) {
44197 $ext = new \ReflectionExtension('xdebug');
44198 $this->version = strval($ext->getVersion());
44199 }
44200 }
44201
44202
44203
44204
44205
44206
44207
44208
44209
44210
44211
44212
44213
44214
44215 public function check()
44216 {
44217 $args = explode('|', strval(getenv(self::ENV_ALLOW)), 2);
44218
44219 if ($this->needsRestart($args[0])) {
44220 if ($this->prepareRestart()) {
44221 $command = $this->getCommand();
44222 $this->restart($command);
44223 }
44224
44225 return;
44226 }
44227
44228
44229  if (self::RESTART_ID === $args[0]) {
44230 putenv(self::ENV_ALLOW);
44231
44232 if (false !== $this->envScanDir) {
44233
44234  if (isset($args[1])) {
44235 putenv('PHP_INI_SCAN_DIR='.$args[1]);
44236 } else {
44237 putenv('PHP_INI_SCAN_DIR');
44238 }
44239 }
44240
44241
44242  if ($this->loaded) {
44243 putenv(self::ENV_VERSION);
44244 }
44245 }
44246 }
44247
44248
44249
44250
44251
44252
44253 protected function restart($command)
44254 {
44255 passthru($command, $exitCode);
44256
44257 if (!empty($this->tmpIni)) {
44258 @unlink($this->tmpIni);
44259 }
44260
44261 exit($exitCode);
44262 }
44263
44264
44265
44266
44267
44268
44269
44270
44271 private function needsRestart($allow)
44272 {
44273 if (PHP_SAPI !== 'cli' || !defined('PHP_BINARY')) {
44274 return false;
44275 }
44276
44277 return empty($allow) && $this->loaded;
44278 }
44279
44280
44281
44282
44283
44284
44285
44286
44287
44288
44289
44290 private function prepareRestart()
44291 {
44292 $this->tmpIni = '';
44293 $iniPaths = IniHelper::getAll();
44294 $additional = count($iniPaths) > 1;
44295
44296 if ($this->writeTmpIni($iniPaths)) {
44297 return $this->setEnvironment($additional, $iniPaths);
44298 }
44299
44300 return false;
44301 }
44302
44303
44304
44305
44306
44307
44308
44309
44310
44311
44312 private function writeTmpIni(array $iniPaths)
44313 {
44314 if (!$this->tmpIni = tempnam(sys_get_temp_dir(), '')) {
44315 return false;
44316 }
44317
44318
44319  if (empty($iniPaths[0])) {
44320 array_shift($iniPaths);
44321 }
44322
44323 $content = '';
44324 $regex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
44325
44326 foreach ($iniPaths as $file) {
44327 $data = preg_replace($regex, ';$1', file_get_contents($file));
44328 $content .= $data.PHP_EOL;
44329 }
44330
44331 $content .= 'allow_url_fopen='.ini_get('allow_url_fopen').PHP_EOL;
44332 $content .= 'disable_functions="'.ini_get('disable_functions').'"'.PHP_EOL;
44333 $content .= 'memory_limit='.ini_get('memory_limit').PHP_EOL;
44334
44335 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
44336
44337  $content .= 'opcache.enable_cli=0'.PHP_EOL;
44338 }
44339
44340 return @file_put_contents($this->tmpIni, $content);
44341 }
44342
44343
44344
44345
44346
44347
44348 private function getCommand()
44349 {
44350 $phpArgs = array(PHP_BINARY, '-c', $this->tmpIni);
44351 $params = array_merge($phpArgs, $this->getScriptArgs($_SERVER['argv']));
44352
44353 return implode(' ', array_map(array($this, 'escape'), $params));
44354 }
44355
44356
44357
44358
44359
44360
44361
44362
44363
44364 private function setEnvironment($additional, array $iniPaths)
44365 {
44366
44367  if ($additional && !putenv('PHP_INI_SCAN_DIR=')) {
44368 return false;
44369 }
44370
44371
44372  if (!putenv(IniHelper::ENV_ORIGINAL.'='.implode(PATH_SEPARATOR, $iniPaths))) {
44373 return false;
44374 }
44375
44376
44377  if (!putenv(self::ENV_VERSION.'='.$this->version)) {
44378 return false;
44379 }
44380
44381
44382  $args = array(self::RESTART_ID);
44383
44384 if (false !== $this->envScanDir) {
44385
44386  $args[] = $this->envScanDir;
44387 }
44388
44389 return putenv(self::ENV_ALLOW.'='.implode('|', $args));
44390 }
44391
44392
44393
44394
44395
44396
44397
44398
44399
44400
44401
44402 private function getScriptArgs(array $args)
44403 {
44404 if (in_array('--no-ansi', $args) || in_array('--ansi', $args)) {
44405 return $args;
44406 }
44407
44408 if ($this->output->isDecorated()) {
44409 $offset = count($args) > 1 ? 2 : 1;
44410 array_splice($args, $offset, 0, '--ansi');
44411 }
44412
44413 return $args;
44414 }
44415
44416
44417
44418
44419
44420
44421
44422
44423
44424
44425
44426
44427 private function escape($arg, $meta = true)
44428 {
44429 if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
44430 return escapeshellarg($arg);
44431 }
44432
44433 $quote = strpbrk($arg, " \t") !== false || $arg === '';
44434 $arg = preg_replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes);
44435
44436 if ($meta) {
44437 $meta = $dquotes || preg_match('/%[^%]+%/', $arg);
44438
44439 if (!$meta && !$quote) {
44440 $quote = strpbrk($arg, '^&|<>()') !== false;
44441 }
44442 }
44443
44444 if ($quote) {
44445 $arg = preg_replace('/(\\\\*)$/', '$1$1', $arg);
44446 $arg = '"'.$arg.'"';
44447 }
44448
44449 if ($meta) {
44450 $arg = preg_replace('/(["^&|<>()%])/', '^$1', $arg);
44451 }
44452
44453 return $arg;
44454 }
44455 }
44456 <?php
44457
44458
44459
44460
44461
44462
44463
44464
44465
44466
44467
44468 function includeIfExists($file)
44469 {
44470 return file_exists($file) ? include $file : false;
44471 }
44472
44473 if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
44474 echo 'You must set up the project dependencies using `composer install`'.PHP_EOL.
44475 'See https://getcomposer.org/download/ for instructions on installing Composer'.PHP_EOL;
44476 exit(1);
44477 }
44478
44479 return $loader;
44480 <?php
44481
44482 /*
44483  * This file is part of Composer.
44484  *
44485  * (c) Nils Adermann <naderman@naderman.de>
44486  *     Jordi Boggiano <j.boggiano@seld.be>
44487  *
44488  * For the full copyright and license information, please view the LICENSE
44489  * file that was distributed with this source code.
44490  */
44491
44492 namespace Composer\Autoload;
44493
44494 /**
44495  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
44496  *
44497  *     $loader = new \Composer\Autoload\ClassLoader();
44498  *
44499  *     // register classes with namespaces
44500  *     $loader->add('Symfony\Component', __DIR__.'/component');
44501  *     $loader->add('Symfony',           __DIR__.'/framework');
44502  *
44503  *     // activate the autoloader
44504  *     $loader->register();
44505  *
44506  *     // to enable searching the include path (eg. for PEAR packages)
44507  *     $loader->setUseIncludePath(true);
44508  *
44509  * In this example, if you try to use a class in the Symfony\Component
44510  * namespace or one of its children (Symfony\Component\Console for instance),
44511  * the autoloader will first look for the class under the component/
44512  * directory, and it will then fallback to the framework/ directory if not
44513  * found before giving up.
44514  *
44515  * This class is loosely based on the Symfony UniversalClassLoader.
44516  *
44517  * @author Fabien Potencier <fabien@symfony.com>
44518  * @author Jordi Boggiano <j.boggiano@seld.be>
44519  * @see    http://www.php-fig.org/psr/psr-0/
44520  * @see    http://www.php-fig.org/psr/psr-4/
44521  */
44522 class ClassLoader
44523 {
44524     // PSR-4
44525     private $prefixLengthsPsr4 = array();
44526     private $prefixDirsPsr4 = array();
44527     private $fallbackDirsPsr4 = array();
44528
44529     // PSR-0
44530     private $prefixesPsr0 = array();
44531     private $fallbackDirsPsr0 = array();
44532
44533     private $useIncludePath = false;
44534     private $classMap = array();
44535     private $classMapAuthoritative = false;
44536     private $missingClasses = array();
44537     private $apcuPrefix;
44538
44539     public function getPrefixes()
44540     {
44541         if (!empty($this->prefixesPsr0)) {
44542             return call_user_func_array('array_merge', $this->prefixesPsr0);
44543         }
44544
44545         return array();
44546     }
44547
44548     public function getPrefixesPsr4()
44549     {
44550         return $this->prefixDirsPsr4;
44551     }
44552
44553     public function getFallbackDirs()
44554     {
44555         return $this->fallbackDirsPsr0;
44556     }
44557
44558     public function getFallbackDirsPsr4()
44559     {
44560         return $this->fallbackDirsPsr4;
44561     }
44562
44563     public function getClassMap()
44564     {
44565         return $this->classMap;
44566     }
44567
44568     /**
44569      * @param array $classMap Class to filename map
44570      */
44571     public function addClassMap(array $classMap)
44572     {
44573         if ($this->classMap) {
44574             $this->classMap = array_merge($this->classMap, $classMap);
44575         } else {
44576             $this->classMap = $classMap;
44577         }
44578     }
44579
44580     /**
44581      * Registers a set of PSR-0 directories for a given prefix, either
44582      * appending or prepending to the ones previously set for this prefix.
44583      *
44584      * @param string       $prefix  The prefix
44585      * @param array|string $paths   The PSR-0 root directories
44586      * @param bool         $prepend Whether to prepend the directories
44587      */
44588     public function add($prefix, $paths, $prepend = false)
44589     {
44590         if (!$prefix) {
44591             if ($prepend) {
44592                 $this->fallbackDirsPsr0 = array_merge(
44593                     (array) $paths,
44594                     $this->fallbackDirsPsr0
44595                 );
44596             } else {
44597                 $this->fallbackDirsPsr0 = array_merge(
44598                     $this->fallbackDirsPsr0,
44599                     (array) $paths
44600                 );
44601             }
44602
44603             return;
44604         }
44605
44606         $first = $prefix[0];
44607         if (!isset($this->prefixesPsr0[$first][$prefix])) {
44608             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
44609
44610             return;
44611         }
44612         if ($prepend) {
44613             $this->prefixesPsr0[$first][$prefix] = array_merge(
44614                 (array) $paths,
44615                 $this->prefixesPsr0[$first][$prefix]
44616             );
44617         } else {
44618             $this->prefixesPsr0[$first][$prefix] = array_merge(
44619                 $this->prefixesPsr0[$first][$prefix],
44620                 (array) $paths
44621             );
44622         }
44623     }
44624
44625     /**
44626      * Registers a set of PSR-4 directories for a given namespace, either
44627      * appending or prepending to the ones previously set for this namespace.
44628      *
44629      * @param string       $prefix  The prefix/namespace, with trailing '\\'
44630      * @param array|string $paths   The PSR-4 base directories
44631      * @param bool         $prepend Whether to prepend the directories
44632      *
44633      * @throws \InvalidArgumentException
44634      */
44635     public function addPsr4($prefix, $paths, $prepend = false)
44636     {
44637         if (!$prefix) {
44638             // Register directories for the root namespace.
44639             if ($prepend) {
44640                 $this->fallbackDirsPsr4 = array_merge(
44641                     (array) $paths,
44642                     $this->fallbackDirsPsr4
44643                 );
44644             } else {
44645                 $this->fallbackDirsPsr4 = array_merge(
44646                     $this->fallbackDirsPsr4,
44647                     (array) $paths
44648                 );
44649             }
44650         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
44651             // Register directories for a new namespace.
44652             $length = strlen($prefix);
44653             if ('\\' !== $prefix[$length - 1]) {
44654                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
44655             }
44656             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
44657             $this->prefixDirsPsr4[$prefix] = (array) $paths;
44658         } elseif ($prepend) {
44659             // Prepend directories for an already registered namespace.
44660             $this->prefixDirsPsr4[$prefix] = array_merge(
44661                 (array) $paths,
44662                 $this->prefixDirsPsr4[$prefix]
44663             );
44664         } else {
44665             // Append directories for an already registered namespace.
44666             $this->prefixDirsPsr4[$prefix] = array_merge(
44667                 $this->prefixDirsPsr4[$prefix],
44668                 (array) $paths
44669             );
44670         }
44671     }
44672
44673     /**
44674      * Registers a set of PSR-0 directories for a given prefix,
44675      * replacing any others previously set for this prefix.
44676      *
44677      * @param string       $prefix The prefix
44678      * @param array|string $paths  The PSR-0 base directories
44679      */
44680     public function set($prefix, $paths)
44681     {
44682         if (!$prefix) {
44683             $this->fallbackDirsPsr0 = (array) $paths;
44684         } else {
44685             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
44686         }
44687     }
44688
44689     /**
44690      * Registers a set of PSR-4 directories for a given namespace,
44691      * replacing any others previously set for this namespace.
44692      *
44693      * @param string       $prefix The prefix/namespace, with trailing '\\'
44694      * @param array|string $paths  The PSR-4 base directories
44695      *
44696      * @throws \InvalidArgumentException
44697      */
44698     public function setPsr4($prefix, $paths)
44699     {
44700         if (!$prefix) {
44701             $this->fallbackDirsPsr4 = (array) $paths;
44702         } else {
44703             $length = strlen($prefix);
44704             if ('\\' !== $prefix[$length - 1]) {
44705                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
44706             }
44707             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
44708             $this->prefixDirsPsr4[$prefix] = (array) $paths;
44709         }
44710     }
44711
44712     /**
44713      * Turns on searching the include path for class files.
44714      *
44715      * @param bool $useIncludePath
44716      */
44717     public function setUseIncludePath($useIncludePath)
44718     {
44719         $this->useIncludePath = $useIncludePath;
44720     }
44721
44722     /**
44723      * Can be used to check if the autoloader uses the include path to check
44724      * for classes.
44725      *
44726      * @return bool
44727      */
44728     public function getUseIncludePath()
44729     {
44730         return $this->useIncludePath;
44731     }
44732
44733     /**
44734      * Turns off searching the prefix and fallback directories for classes
44735      * that have not been registered with the class map.
44736      *
44737      * @param bool $classMapAuthoritative
44738      */
44739     public function setClassMapAuthoritative($classMapAuthoritative)
44740     {
44741         $this->classMapAuthoritative = $classMapAuthoritative;
44742     }
44743
44744     /**
44745      * Should class lookup fail if not found in the current class map?
44746      *
44747      * @return bool
44748      */
44749     public function isClassMapAuthoritative()
44750     {
44751         return $this->classMapAuthoritative;
44752     }
44753
44754     /**
44755      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
44756      *
44757      * @param string|null $apcuPrefix
44758      */
44759     public function setApcuPrefix($apcuPrefix)
44760     {
44761         $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
44762     }
44763
44764     /**
44765      * The APCu prefix in use, or null if APCu caching is not enabled.
44766      *
44767      * @return string|null
44768      */
44769     public function getApcuPrefix()
44770     {
44771         return $this->apcuPrefix;
44772     }
44773
44774     /**
44775      * Registers this instance as an autoloader.
44776      *
44777      * @param bool $prepend Whether to prepend the autoloader or not
44778      */
44779     public function register($prepend = false)
44780     {
44781         spl_autoload_register(array($this, 'loadClass'), true, $prepend);
44782     }
44783
44784     /**
44785      * Unregisters this instance as an autoloader.
44786      */
44787     public function unregister()
44788     {
44789         spl_autoload_unregister(array($this, 'loadClass'));
44790     }
44791
44792     /**
44793      * Loads the given class or interface.
44794      *
44795      * @param  string    $class The name of the class
44796      * @return bool|null True if loaded, null otherwise
44797      */
44798     public function loadClass($class)
44799     {
44800         if ($file = $this->findFile($class)) {
44801             includeFile($file);
44802
44803             return true;
44804         }
44805     }
44806
44807     /**
44808      * Finds the path to the file where the class is defined.
44809      *
44810      * @param string $class The name of the class
44811      *
44812      * @return string|false The path if found, false otherwise
44813      */
44814     public function findFile($class)
44815     {
44816         // class map lookup
44817         if (isset($this->classMap[$class])) {
44818             return $this->classMap[$class];
44819         }
44820         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
44821             return false;
44822         }
44823         if (null !== $this->apcuPrefix) {
44824             $file = apcu_fetch($this->apcuPrefix.$class, $hit);
44825             if ($hit) {
44826                 return $file;
44827             }
44828         }
44829
44830         $file = $this->findFileWithExtension($class, '.php');
44831
44832         // Search for Hack files if we are running on HHVM
44833         if (false === $file && defined('HHVM_VERSION')) {
44834             $file = $this->findFileWithExtension($class, '.hh');
44835         }
44836
44837         if (null !== $this->apcuPrefix) {
44838             apcu_add($this->apcuPrefix.$class, $file);
44839         }
44840
44841         if (false === $file) {
44842             // Remember that this class does not exist.
44843             $this->missingClasses[$class] = true;
44844         }
44845
44846         return $file;
44847     }
44848
44849     private function findFileWithExtension($class, $ext)
44850     {
44851         // PSR-4 lookup
44852         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
44853
44854         $first = $class[0];
44855         if (isset($this->prefixLengthsPsr4[$first])) {
44856             $subPath = $class;
44857             while (false !== $lastPos = strrpos($subPath, '\\')) {
44858                 $subPath = substr($subPath, 0, $lastPos);
44859                 $search = $subPath.'\\';
44860                 if (isset($this->prefixDirsPsr4[$search])) {
44861                     $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
44862                     foreach ($this->prefixDirsPsr4[$search] as $dir) {
44863                         if (file_exists($file = $dir . $pathEnd)) {
44864                             return $file;
44865                         }
44866                     }
44867                 }
44868             }
44869         }
44870
44871         // PSR-4 fallback dirs
44872         foreach ($this->fallbackDirsPsr4 as $dir) {
44873             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
44874                 return $file;
44875             }
44876         }
44877
44878         // PSR-0 lookup
44879         if (false !== $pos = strrpos($class, '\\')) {
44880             // namespaced class name
44881             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
44882                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
44883         } else {
44884             // PEAR-like class name
44885             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
44886         }
44887
44888         if (isset($this->prefixesPsr0[$first])) {
44889             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
44890                 if (0 === strpos($class, $prefix)) {
44891                     foreach ($dirs as $dir) {
44892                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
44893                             return $file;
44894                         }
44895                     }
44896                 }
44897             }
44898         }
44899
44900         // PSR-0 fallback dirs
44901         foreach ($this->fallbackDirsPsr0 as $dir) {
44902             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
44903                 return $file;
44904             }
44905         }
44906
44907         // PSR-0 include paths.
44908         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
44909             return $file;
44910         }
44911
44912         return false;
44913     }
44914 }
44915
44916 /**
44917  * Scope isolated include.
44918  *
44919  * Prevents access to $this/self from included files.
44920  */
44921 function includeFile($file)
44922 {
44923     include $file;
44924 }
44925 {
44926     "$schema": "http://json-schema.org/draft-04/schema#",
44927     "description": "A representation of packages metadata.",
44928     "type": "object",
44929     "oneOf": [
44930         { "required": [ "packages" ] },
44931         { "required": [ "providers" ] },
44932         { "required": [ "provider-includes", "providers-url" ] }
44933     ],
44934     "properties": {
44935         "packages": {
44936             "type": ["object", "array"],
44937             "description": "A hashmap of package names in the form of <vendor>/<name>.",
44938             "additionalProperties": { "$ref": "#/definitions/versions" }
44939         },
44940         "providers-url": {
44941             "type": "string",
44942             "description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
44943         },
44944         "provider-includes": {
44945             "type": "object",
44946             "description": "A hashmap of provider listings.",
44947             "additionalProperties": { "$ref": "#/definitions/provider" }
44948         },
44949         "providers": {
44950             "type": "object",
44951             "description": "A hashmap of package names in the form of <vendor>/<name>.",
44952             "additionalProperties": { "$ref": "#/definitions/provider" }
44953         },
44954         "notify-batch": {
44955             "type": "string",
44956             "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
44957         },
44958         "search": {
44959             "type": "string",
44960             "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
44961         },
44962         "warning": {
44963             "type": "string",
44964             "description": "A message that will be output by Composer as a warning when this source is consulted."
44965         }
44966     },
44967     "definitions": {
44968         "versions": {
44969             "type": "object",
44970             "description": "A hashmap of versions and their metadata.",
44971             "additionalProperties": { "$ref": "#/definitions/version" }
44972         },
44973         "version": {
44974             "type": "object",
44975             "oneOf": [
44976                 { "$ref": "#/definitions/package" },
44977                 { "$ref": "#/definitions/metapackage" }
44978             ]
44979         },
44980         "package-base": {
44981             "properties": {
44982                 "name": { "type": "string" },
44983                 "type": { "type": "string" },
44984                 "version": { "type": "string" },
44985                 "version_normalized": {
44986                     "type": "string",
44987                     "description": "Normalized version, optional but can save computational time on client side."
44988                 },
44989                 "autoload": { "type": "object" },
44990                 "require": { "type": "object" },
44991                 "replace": { "type": "object" },
44992                 "conflict": { "type": "object" },
44993                 "provide": { "type": "object" },
44994                 "time": { "type": "string" }
44995             },
44996             "additionalProperties": true
44997         },
44998         "package": {
44999             "allOf": [
45000                 { "$ref": "#/definitions/package-base" },
45001                 {
45002                     "properties": {
45003                         "dist": { "type": "object" },
45004                         "source": { "type": "object" }
45005                     }
45006                 },
45007                 { "oneOf": [
45008                     { "required": [ "name", "version", "source" ] },
45009                     { "required": [ "name", "version", "dist" ] }
45010                 ] }
45011             ]
45012         },
45013         "metapackage": {
45014             "allOf": [
45015                 { "$ref": "#/definitions/package-base" },
45016                 {
45017                     "properties": {
45018                         "type": { "type": "string", "enum": [ "metapackage" ] }
45019                     },
45020                     "required": [ "name", "version", "type" ]
45021                 }
45022             ]
45023         },
45024         "provider": {
45025             "type": "object",
45026             "properties": {
45027                 "sha256": {
45028                     "type": "string",
45029                     "description": "Hash value that can be used to validate the resource."
45030                 }
45031             }
45032         }
45033     }
45034 }
45035 {
45036     "$schema": "http://json-schema.org/draft-04/schema#",
45037     "name": "Package",
45038     "type": "object",
45039     "additionalProperties": false,
45040     "required": [ "name", "description" ],
45041     "properties": {
45042         "name": {
45043             "type": "string",
45044             "description": "Package name, including 'vendor-name/' prefix."
45045         },
45046         "type": {
45047             "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.",
45048             "type": "string"
45049         },
45050         "target-dir": {
45051             "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.",
45052             "type": "string"
45053         },
45054         "description": {
45055             "type": "string",
45056             "description": "Short package description."
45057         },
45058         "keywords": {
45059             "type": "array",
45060             "items": {
45061                 "type": "string",
45062                 "description": "A tag/keyword that this package relates to."
45063             }
45064         },
45065         "homepage": {
45066             "type": "string",
45067             "description": "Homepage URL for the project.",
45068             "format": "uri"
45069         },
45070         "version": {
45071             "type": "string",
45072             "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes."
45073         },
45074         "time": {
45075             "type": "string",
45076             "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
45077         },
45078         "license": {
45079             "type": ["string", "array"],
45080             "description": "License name. Or an array of license names."
45081         },
45082         "authors": {
45083             "$ref": "#/definitions/authors"
45084         },
45085         "require": {
45086             "type": "object",
45087             "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
45088             "additionalProperties": {
45089                 "type": "string"
45090             }
45091         },
45092         "replace": {
45093             "type": "object",
45094             "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
45095             "additionalProperties": {
45096                 "type": "string"
45097             }
45098         },
45099         "conflict": {
45100             "type": "object",
45101             "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
45102             "additionalProperties": {
45103                 "type": "string"
45104             }
45105         },
45106         "provide": {
45107             "type": "object",
45108             "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
45109             "additionalProperties": {
45110                 "type": "string"
45111             }
45112         },
45113         "require-dev": {
45114             "type": "object",
45115             "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
45116             "additionalProperties": {
45117                 "type": "string"
45118             }
45119         },
45120         "suggest": {
45121             "type": "object",
45122             "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).",
45123             "additionalProperties": {
45124                 "type": "string"
45125             }
45126         },
45127         "config": {
45128             "type": "object",
45129             "description": "Composer options.",
45130             "properties": {
45131                 "process-timeout": {
45132                     "type": "integer",
45133                     "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
45134                 },
45135                 "use-include-path": {
45136                     "type": "boolean",
45137                     "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
45138                 },
45139                 "preferred-install": {
45140                     "type": ["string", "object"],
45141                     "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\"}."
45142                 },
45143                 "notify-on-install": {
45144                     "type": "boolean",
45145                     "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."
45146                 },
45147                 "github-protocols": {
45148                     "type": "array",
45149                     "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].",
45150                     "items": {
45151                         "type": "string"
45152                     }
45153                 },
45154                 "github-oauth": {
45155                     "type": "object",
45156                     "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
45157                     "additionalProperties": {
45158                         "type": "string"
45159                     }
45160                 },
45161                 "gitlab-oauth": {
45162                     "type": "object",
45163                     "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"<token>\"}.",
45164                     "additionalProperties": {
45165                         "type": "string"
45166                     }
45167                 },
45168                 "gitlab-token": {
45169                     "type": "object",
45170                     "description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}.",
45171                     "additionalProperties": true
45172                 },
45173                 "disable-tls": {
45174                     "type": "boolean",
45175                     "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."
45176                 },
45177                 "secure-http": {
45178                     "type": "boolean",
45179                     "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."
45180                 },
45181                 "cafile": {
45182                     "type": "string",
45183                     "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."
45184                 },
45185                 "capath": {
45186                     "type": "string",
45187                     "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."
45188                 },
45189                 "http-basic": {
45190                     "type": "object",
45191                     "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
45192                     "additionalProperties": {
45193                         "type": "object",
45194                         "required": ["username", "password"],
45195                         "properties": {
45196                             "username": {
45197                                 "type": "string",
45198                                 "description": "The username used for HTTP Basic authentication"
45199                             },
45200                             "password": {
45201                                 "type": "string",
45202                                 "description": "The password used for HTTP Basic authentication"
45203                             }
45204                         }
45205                     }
45206                 },
45207                 "store-auths": {
45208                     "type": ["string", "boolean"],
45209                     "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
45210                 },
45211                 "platform": {
45212                     "type": "object",
45213                     "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
45214                     "additionalProperties": {
45215                         "type": "string"
45216                     }
45217                 },
45218                 "vendor-dir": {
45219                     "type": "string",
45220                     "description": "The location where all packages are installed, defaults to \"vendor\"."
45221                 },
45222                 "bin-dir": {
45223                     "type": "string",
45224                     "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
45225                 },
45226                 "data-dir": {
45227                     "type": "string",
45228                     "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes."
45229                 },
45230                 "cache-dir": {
45231                     "type": "string",
45232                     "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
45233                 },
45234                 "cache-files-dir": {
45235                     "type": "string",
45236                     "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
45237                 },
45238                 "cache-repo-dir": {
45239                     "type": "string",
45240                     "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
45241                 },
45242                 "cache-vcs-dir": {
45243                     "type": "string",
45244                     "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
45245                 },
45246                 "cache-ttl": {
45247                     "type": "integer",
45248                     "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
45249                 },
45250                 "cache-files-ttl": {
45251                     "type": "integer",
45252                     "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
45253                 },
45254                 "cache-files-maxsize": {
45255                     "type": ["string", "integer"],
45256                     "description": "The cache max size for the files cache, defaults to \"300MiB\"."
45257                 },
45258                 "bin-compat": {
45259                     "enum": ["auto", "full"],
45260                     "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)."
45261                 },
45262                 "discard-changes": {
45263                     "type": ["string", "boolean"],
45264                     "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
45265                 },
45266                 "autoloader-suffix": {
45267                     "type": "string",
45268                     "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
45269                 },
45270                 "optimize-autoloader": {
45271                     "type": "boolean",
45272                     "description": "Always optimize when dumping the autoloader."
45273                 },
45274                 "prepend-autoloader": {
45275                     "type": "boolean",
45276                     "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
45277                 },
45278                 "classmap-authoritative": {
45279                     "type": "boolean",
45280                     "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
45281                 },
45282                 "apcu-autoloader": {
45283                     "type": "boolean",
45284                     "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."
45285                 },
45286                 "github-domains": {
45287                     "type": "array",
45288                     "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
45289                     "items": {
45290                         "type": "string"
45291                     }
45292                 },
45293                 "github-expose-hostname": {
45294                     "type": "boolean",
45295                     "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."
45296                 },
45297                 "gitlab-domains": {
45298                     "type": "array",
45299                     "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].",
45300                     "items": {
45301                         "type": "string"
45302                     }
45303                 },
45304                 "archive-format": {
45305                     "type": "string",
45306                     "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
45307                 },
45308                 "archive-dir": {
45309                     "type": "string",
45310                     "description": "The default archive path when not provided on cli, defaults to \".\"."
45311                 },
45312                 "htaccess-protect": {
45313                     "type": "boolean",
45314                     "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
45315                 },
45316                 "sort-packages": {
45317                     "type": "boolean",
45318                     "description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency."
45319                 }
45320             }
45321         },
45322         "extra": {
45323             "type": ["object", "array"],
45324             "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.",
45325             "additionalProperties": true
45326         },
45327         "autoload": {
45328             "$ref": "#/definitions/autoload"
45329         },
45330         "autoload-dev": {
45331             "type": "object",
45332             "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
45333             "properties": {
45334                 "psr-0": {
45335                     "type": "object",
45336                     "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.",
45337                     "additionalProperties": {
45338                         "type": ["string", "array"],
45339                         "items": {
45340                             "type": "string"
45341                         }
45342                     }
45343                 },
45344                 "psr-4": {
45345                     "type": "object",
45346                     "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.",
45347                     "additionalProperties": {
45348                         "type": ["string", "array"],
45349                         "items": {
45350                             "type": "string"
45351                         }
45352                     }
45353                 },
45354                 "classmap": {
45355                     "type": "array",
45356                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
45357                 },
45358                 "files": {
45359                     "type": "array",
45360                     "description": "This is an array of files that are always required on every request."
45361                 }
45362             }
45363         },
45364         "archive": {
45365             "type": ["object"],
45366             "description": "Options for creating package archives for distribution.",
45367             "properties": {
45368                 "exclude": {
45369                     "type": "array",
45370                     "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
45371                 }
45372             }
45373         },
45374         "repositories": {
45375             "type": ["object", "array"],
45376             "description": "A set of additional repositories where packages can be found.",
45377             "additionalProperties": {
45378                 "oneOf": [
45379                     { "$ref": "#/definitions/repository" },
45380                     { "type": "boolean", "enum": [false] }
45381                 ]
45382             },
45383             "items": {
45384                 "oneOf": [
45385                     { "$ref": "#/definitions/repository" },
45386                     {
45387                         "type": "object",
45388                         "additionalProperties": { "type": "boolean", "enum": [false] },
45389                         "minProperties": 1,
45390                         "maxProperties": 1
45391                     }
45392                 ]
45393             }
45394         },
45395         "minimum-stability": {
45396             "type": ["string"],
45397             "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
45398             "pattern": "^dev|alpha|beta|rc|RC|stable$"
45399         },
45400         "prefer-stable": {
45401             "type": ["boolean"],
45402             "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages."
45403         },
45404         "bin": {
45405             "type": ["string", "array"],
45406             "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
45407             "items": {
45408                 "type": "string"
45409             }
45410         },
45411         "include-path": {
45412             "type": ["array"],
45413             "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.",
45414             "items": {
45415                 "type": "string"
45416             }
45417         },
45418         "scripts": {
45419             "type": ["object"],
45420             "description": "Script listeners that will be executed before/after some events.",
45421             "properties": {
45422                 "pre-install-cmd": {
45423                     "type": ["array", "string"],
45424                     "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
45425                 },
45426                 "post-install-cmd": {
45427                     "type": ["array", "string"],
45428                     "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
45429                 },
45430                 "pre-update-cmd": {
45431                     "type": ["array", "string"],
45432                     "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
45433                 },
45434                 "post-update-cmd": {
45435                     "type": ["array", "string"],
45436                     "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
45437                 },
45438                 "pre-status-cmd": {
45439                     "type": ["array", "string"],
45440                     "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
45441                 },
45442                 "post-status-cmd": {
45443                     "type": ["array", "string"],
45444                     "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
45445                 },
45446                 "pre-package-install": {
45447                     "type": ["array", "string"],
45448                     "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
45449                 },
45450                 "post-package-install": {
45451                     "type": ["array", "string"],
45452                     "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
45453                 },
45454                 "pre-package-update": {
45455                     "type": ["array", "string"],
45456                     "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
45457                 },
45458                 "post-package-update": {
45459                     "type": ["array", "string"],
45460                     "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
45461                 },
45462                 "pre-package-uninstall": {
45463                     "type": ["array", "string"],
45464                     "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
45465                 },
45466                 "post-package-uninstall": {
45467                     "type": ["array", "string"],
45468                     "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
45469                 },
45470                 "pre-autoload-dump": {
45471                     "type": ["array", "string"],
45472                     "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
45473                 },
45474                 "post-autoload-dump": {
45475                     "type": ["array", "string"],
45476                     "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
45477                 },
45478                 "post-root-package-install": {
45479                     "type": ["array", "string"],
45480                     "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
45481                 },
45482                 "post-create-project-cmd": {
45483                     "type": ["array", "string"],
45484                     "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
45485                 }
45486             }
45487         },
45488         "scripts-descriptions": {
45489             "type": ["object"],
45490             "description": "Descriptions for custom commands, shown in console help.",
45491             "additionalProperties": {
45492                 "type": "string"
45493             }
45494         },
45495         "support": {
45496             "type": "object",
45497             "properties": {
45498                 "email": {
45499                     "type": "string",
45500                     "description": "Email address for support.",
45501                     "format": "email"
45502                 },
45503                 "issues": {
45504                     "type": "string",
45505                     "description": "URL to the issue tracker.",
45506                     "format": "uri"
45507                 },
45508                 "forum": {
45509                     "type": "string",
45510                     "description": "URL to the forum.",
45511                     "format": "uri"
45512                 },
45513                 "wiki": {
45514                     "type": "string",
45515                     "description": "URL to the wiki.",
45516                     "format": "uri"
45517                 },
45518                 "irc": {
45519                     "type": "string",
45520                     "description": "IRC channel for support, as irc://server/channel.",
45521                     "format": "uri"
45522                 },
45523                 "source": {
45524                     "type": "string",
45525                     "description": "URL to browse or download the sources.",
45526                     "format": "uri"
45527                 },
45528                 "docs": {
45529                     "type": "string",
45530                     "description": "URL to the documentation.",
45531                     "format": "uri"
45532                 },
45533                 "rss": {
45534                     "type": "string",
45535                     "description": "URL to the RSS feed.",
45536                     "format": "uri"
45537                 }
45538             }
45539         },
45540         "non-feature-branches": {
45541             "type": ["array"],
45542             "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
45543             "items": {
45544                 "type": "string"
45545             }
45546         },
45547         "abandoned": {
45548             "type": ["boolean", "string"],
45549             "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."
45550         },
45551         "_comment": {
45552             "type": ["array", "string"],
45553             "description": "A key to store comments in"
45554         }
45555     },
45556     "definitions": {
45557         "authors": {
45558             "type": "array",
45559             "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
45560             "items": {
45561                 "type": "object",
45562                 "additionalProperties": false,
45563                 "required": [ "name"],
45564                 "properties": {
45565                     "name": {
45566                         "type": "string",
45567                         "description": "Full name of the author."
45568                     },
45569                     "email": {
45570                         "type": "string",
45571                         "description": "Email address of the author.",
45572                         "format": "email"
45573                     },
45574                     "homepage": {
45575                         "type": "string",
45576                         "description": "Homepage URL for the author.",
45577                         "format": "uri"
45578                     },
45579                     "role": {
45580                         "type": "string",
45581                         "description": "Author's role in the project."
45582                     }
45583                 }
45584             }
45585         },
45586         "autoload": {
45587             "type": "object",
45588             "description": "Description of how the package can be autoloaded.",
45589             "properties": {
45590                 "psr-0": {
45591                     "type": "object",
45592                     "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.",
45593                     "additionalProperties": {
45594                         "type": ["string", "array"],
45595                         "items": {
45596                             "type": "string"
45597                         }
45598                     }
45599                 },
45600                 "psr-4": {
45601                     "type": "object",
45602                     "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.",
45603                     "additionalProperties": {
45604                         "type": ["string", "array"],
45605                         "items": {
45606                             "type": "string"
45607                         }
45608                     }
45609                 },
45610                 "classmap": {
45611                     "type": "array",
45612                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
45613                 },
45614                 "files": {
45615                     "type": "array",
45616                     "description": "This is an array of files that are always required on every request."
45617                 },
45618                 "exclude-from-classmap": {
45619                     "type": "array",
45620                     "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
45621                 }
45622             }
45623         },
45624         "repository": {
45625             "type": "object",
45626             "oneOf": [
45627                 { "$ref": "#/definitions/composer-repository" },
45628                 { "$ref": "#/definitions/vcs-repository" },
45629                 { "$ref": "#/definitions/path-repository" },
45630                 { "$ref": "#/definitions/artifact-repository" },
45631                 { "$ref": "#/definitions/pear-repository" },
45632                 { "$ref": "#/definitions/package-repository" }
45633             ]
45634         },
45635         "composer-repository": {
45636             "type": "object",
45637             "required": ["type", "url"],
45638             "properties": {
45639                 "type": { "type": "string", "enum": ["composer"] },
45640                 "url": { "type": "string" },
45641                 "options": {
45642                     "type": "object",
45643                     "additionalProperties": true
45644                 },
45645                 "allow_ssl_downgrade": { "type": "boolean" },
45646                 "force-lazy-providers": { "type": "boolean" }
45647             }
45648         },
45649         "vcs-repository": {
45650             "type": "object",
45651             "required": ["type", "url"],
45652             "properties": {
45653                 "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] },
45654                 "url": { "type": "string" },
45655                 "no-api": { "type": "boolean" },
45656                 "secure-http": { "type": "boolean" },
45657                 "svn-cache-credentials": { "type": "boolean" },
45658                 "trunk-path": { "type": ["string", "boolean"] },
45659                 "branches-path": { "type": ["string", "boolean"] },
45660                 "tags-path": { "type": ["string", "boolean"] },
45661                 "package-path": { "type": "string" },
45662                 "depot": { "type": "string" },
45663                 "branch": { "type": "string" },
45664                 "unique_perforce_client_name": { "type": "string" },
45665                 "p4user": { "type": "string" },
45666                 "p4password": { "type": "string" }
45667             }
45668         },
45669         "path-repository": {
45670             "type": "object",
45671             "required": ["type", "url"],
45672             "properties": {
45673                 "type": { "type": "string", "enum": ["path"] },
45674                 "url": { "type": "string" },
45675                 "options": {
45676                     "type": "object",
45677                     "properties": {
45678                         "symlink": { "type": ["boolean", "null"] }
45679                     },
45680                     "additionalProperties": true
45681                 }
45682             }
45683         },
45684         "artifact-repository": {
45685             "type": "object",
45686             "required": ["type", "url"],
45687             "properties": {
45688                 "type": { "type": "string", "enum": ["artifact"] },
45689                 "url": { "type": "string" }
45690             }
45691         },
45692         "pear-repository": {
45693             "type": "object",
45694             "required": ["type", "url"],
45695             "properties": {
45696                 "type": { "type": "string", "enum": ["pear"] },
45697                 "url": { "type": "string" },
45698                 "vendor-alias": { "type": "string" }
45699             }
45700         },
45701         "package-repository": {
45702             "type": "object",
45703             "required": ["type", "package"],
45704             "properties": {
45705                 "type": { "type": "string", "enum": ["package"] },
45706                 "package": {
45707                     "oneOf": [
45708                         { "$ref": "#/definitions/inline-package" },
45709                         {
45710                             "type": "array",
45711                             "items": {
45712                                 "type": { "$ref": "#/definitions/inline-package" }
45713                             }
45714                         }
45715                     ]
45716                 }
45717             }
45718         },
45719         "inline-package": {
45720             "required": ["name", "version"],
45721             "properties": {
45722                 "name": {
45723                     "type": "string",
45724                     "description": "Package name, including 'vendor-name/' prefix."
45725                 },
45726                 "type": {
45727                     "type": "string"
45728                 },
45729                 "target-dir": {
45730                     "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.",
45731                     "type": "string"
45732                 },
45733                 "description": {
45734                     "type": "string"
45735                 },
45736                 "keywords": {
45737                     "type": "array",
45738                     "items": {
45739                         "type": "string"
45740                     }
45741                 },
45742                 "homepage": {
45743                     "type": "string",
45744                     "format": "uri"
45745                 },
45746                 "version": {
45747                     "type": "string"
45748                 },
45749                 "time": {
45750                     "type": "string"
45751                 },
45752                 "license": {
45753                     "type": [
45754                         "string",
45755                         "array"
45756                     ]
45757                 },
45758                 "authors": {
45759                     "$ref": "#/definitions/authors"
45760                 },
45761                 "require": {
45762                     "type": "object",
45763                     "additionalProperties": {
45764                         "type": "string"
45765                     }
45766                 },
45767                 "replace": {
45768                     "type": "object",
45769                     "additionalProperties": {
45770                         "type": "string"
45771                     }
45772                 },
45773                 "conflict": {
45774                     "type": "object",
45775                     "additionalProperties": {
45776                         "type": "string"
45777                     }
45778                 },
45779                 "provide": {
45780                     "type": "object",
45781                     "additionalProperties": {
45782                         "type": "string"
45783                     }
45784                 },
45785                 "require-dev": {
45786                     "type": "object",
45787                     "additionalProperties": {
45788                         "type": "string"
45789                     }
45790                 },
45791                 "suggest": {
45792                     "type": "object",
45793                     "additionalProperties": {
45794                         "type": "string"
45795                     }
45796                 },
45797                 "extra": {
45798                     "type": ["object", "array"],
45799                     "additionalProperties": true
45800                 },
45801                 "autoload": {
45802                     "$ref": "#/definitions/autoload"
45803                 },
45804                 "archive": {
45805                     "type": ["object"],
45806                     "properties": {
45807                         "exclude": {
45808                             "type": "array"
45809                         }
45810                     }
45811                 },
45812                 "bin": {
45813                     "type": ["string", "array"],
45814                     "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
45815                     "items": {
45816                         "type": "string"
45817                     }
45818                 },
45819                 "include-path": {
45820                     "type": ["array"],
45821                     "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.",
45822                     "items": {
45823                         "type": "string"
45824                     }
45825                 },
45826                 "source": {
45827                     "type": "object",
45828                     "required": ["type", "url", "reference"],
45829                     "properties": {
45830                         "type": {
45831                             "type": "string"
45832                         },
45833                         "url": {
45834                             "type": "string"
45835                         },
45836                         "reference": {
45837                             "type": "string"
45838                         },
45839                         "mirrors": {
45840                             "type": "array"
45841                         }
45842                     }
45843                 },
45844                 "dist": {
45845                     "type": "object",
45846                     "required": ["type", "url"],
45847                     "properties": {
45848                         "type": {
45849                             "type": "string"
45850                         },
45851                         "url": {
45852                             "type": "string"
45853                         },
45854                         "reference": {
45855                             "type": "string"
45856                         },
45857                         "shasum": {
45858                             "type": "string"
45859                         },
45860                         "mirrors": {
45861                             "type": "array"
45862                         }
45863                     }
45864                 }
45865             },
45866             "additionalProperties": true
45867         }
45868     }
45869 }
45870 {
45871     "389-exception": [
45872         "389 Directory Server Exception"
45873     ],
45874     "Autoconf-exception-2.0": [
45875         "Autoconf exception 2.0"
45876     ],
45877     "Autoconf-exception-3.0": [
45878         "Autoconf exception 3.0"
45879     ],
45880     "Bison-exception-2.2": [
45881         "Bison exception 2.2"
45882     ],
45883     "Bootloader-exception": [
45884         "Bootloader Distribution Exception"
45885     ],
45886     "Classpath-exception-2.0": [
45887         "Classpath exception 2.0"
45888     ],
45889     "CLISP-exception-2.0": [
45890         "CLISP exception 2.0"
45891     ],
45892     "DigiRule-FOSS-exception": [
45893         "DigiRule FOSS License Exception"
45894     ],
45895     "eCos-exception-2.0": [
45896         "eCos exception 2.0"
45897     ],
45898     "Fawkes-Runtime-exception": [
45899         "Fawkes Runtime Exception"
45900     ],
45901     "FLTK-exception": [
45902         "FLTK exception"
45903     ],
45904     "Font-exception-2.0": [
45905         "Font exception 2.0"
45906     ],
45907     "freertos-exception-2.0": [
45908         "FreeRTOS Exception 2.0"
45909     ],
45910     "GCC-exception-2.0": [
45911         "GCC Runtime Library exception 2.0"
45912     ],
45913     "GCC-exception-3.1": [
45914         "GCC Runtime Library exception 3.1"
45915     ],
45916     "gnu-javamail-exception": [
45917         "GNU JavaMail exception"
45918     ],
45919     "i2p-gpl-java-exception": [
45920         "i2p GPL+Java Exception"
45921     ],
45922     "Libtool-exception": [
45923         "Libtool Exception"
45924     ],
45925     "Linux-syscall-note": [
45926         "Linux Syscall Note"
45927     ],
45928     "LZMA-exception": [
45929         "LZMA exception"
45930     ],
45931     "mif-exception": [
45932         "Macros and Inline Functions Exception"
45933     ],
45934     "Nokia-Qt-exception-1.1": [
45935         "Nokia Qt LGPL exception 1.1"
45936     ],
45937     "OCCT-exception-1.0": [
45938         "Open CASCADE Exception 1.0"
45939     ],
45940     "openvpn-openssl-exception": [
45941         "OpenVPN OpenSSL Exception"
45942     ],
45943     "Qwt-exception-1.0": [
45944         "Qwt exception 1.0"
45945     ],
45946     "u-boot-exception-2.0": [
45947         "U-Boot exception 2.0"
45948     ],
45949     "WxWindows-exception-3.1": [
45950         "WxWindows Library Exception 3.1"
45951     ]
45952 }{
45953     "0BSD": [
45954         "BSD Zero Clause License",
45955         false,
45956         false
45957     ],
45958     "AAL": [
45959         "Attribution Assurance License",
45960         true,
45961         false
45962     ],
45963     "Abstyles": [
45964         "Abstyles License",
45965         false,
45966         false
45967     ],
45968     "Adobe-2006": [
45969         "Adobe Systems Incorporated Source Code License Agreement",
45970         false,
45971         false
45972     ],
45973     "Adobe-Glyph": [
45974         "Adobe Glyph List License",
45975         false,
45976         false
45977     ],
45978     "ADSL": [
45979         "Amazon Digital Services License",
45980         false,
45981         false
45982     ],
45983     "AFL-1.1": [
45984         "Academic Free License v1.1",
45985         true,
45986         false
45987     ],
45988     "AFL-1.2": [
45989         "Academic Free License v1.2",
45990         true,
45991         false
45992     ],
45993     "AFL-2.0": [
45994         "Academic Free License v2.0",
45995         true,
45996         false
45997     ],
45998     "AFL-2.1": [
45999         "Academic Free License v2.1",
46000         true,
46001         false
46002     ],
46003     "AFL-3.0": [
46004         "Academic Free License v3.0",
46005         true,
46006         false
46007     ],
46008     "Afmparse": [
46009         "Afmparse License",
46010         false,
46011         false
46012     ],
46013     "AGPL-1.0": [
46014         "Affero General Public License v1.0",
46015         false,
46016         false
46017     ],
46018     "AGPL-3.0": [
46019         "GNU Affero General Public License v3.0",
46020         true,
46021         true
46022     ],
46023     "AGPL-3.0-only": [
46024         "GNU Affero General Public License v3.0 only",
46025         true,
46026         false
46027     ],
46028     "AGPL-3.0-or-later": [
46029         "GNU Affero General Public License v3.0 or later",
46030         true,
46031         false
46032     ],
46033     "Aladdin": [
46034         "Aladdin Free Public License",
46035         false,
46036         false
46037     ],
46038     "AMDPLPA": [
46039         "AMD's plpa_map.c License",
46040         false,
46041         false
46042     ],
46043     "AML": [
46044         "Apple MIT License",
46045         false,
46046         false
46047     ],
46048     "AMPAS": [
46049         "Academy of Motion Picture Arts and Sciences BSD",
46050         false,
46051         false
46052     ],
46053     "ANTLR-PD": [
46054         "ANTLR Software Rights Notice",
46055         false,
46056         false
46057     ],
46058     "Apache-1.0": [
46059         "Apache License 1.0",
46060         false,
46061         false
46062     ],
46063     "Apache-1.1": [
46064         "Apache License 1.1",
46065         true,
46066         false
46067     ],
46068     "Apache-2.0": [
46069         "Apache License 2.0",
46070         true,
46071         false
46072     ],
46073     "APAFML": [
46074         "Adobe Postscript AFM License",
46075         false,
46076         false
46077     ],
46078     "APL-1.0": [
46079         "Adaptive Public License 1.0",
46080         true,
46081         false
46082     ],
46083     "APSL-1.0": [
46084         "Apple Public Source License 1.0",
46085         true,
46086         false
46087     ],
46088     "APSL-1.1": [
46089         "Apple Public Source License 1.1",
46090         true,
46091         false
46092     ],
46093     "APSL-1.2": [
46094         "Apple Public Source License 1.2",
46095         true,
46096         false
46097     ],
46098     "APSL-2.0": [
46099         "Apple Public Source License 2.0",
46100         true,
46101         false
46102     ],
46103     "Artistic-1.0": [
46104         "Artistic License 1.0",
46105         true,
46106         false
46107     ],
46108     "Artistic-1.0-cl8": [
46109         "Artistic License 1.0 w/clause 8",
46110         true,
46111         false
46112     ],
46113     "Artistic-1.0-Perl": [
46114         "Artistic License 1.0 (Perl)",
46115         true,
46116         false
46117     ],
46118     "Artistic-2.0": [
46119         "Artistic License 2.0",
46120         true,
46121         false
46122     ],
46123     "Bahyph": [
46124         "Bahyph License",
46125         false,
46126         false
46127     ],
46128     "Barr": [
46129         "Barr License",
46130         false,
46131         false
46132     ],
46133     "Beerware": [
46134         "Beerware License",
46135         false,
46136         false
46137     ],
46138     "BitTorrent-1.0": [
46139         "BitTorrent Open Source License v1.0",
46140         false,
46141         false
46142     ],
46143     "BitTorrent-1.1": [
46144         "BitTorrent Open Source License v1.1",
46145         false,
46146         false
46147     ],
46148     "Borceux": [
46149         "Borceux license",
46150         false,
46151         false
46152     ],
46153     "BSD-1-Clause": [
46154         "BSD 1-Clause License",
46155         false,
46156         false
46157     ],
46158     "BSD-2-Clause": [
46159         "BSD 2-Clause \"Simplified\" License",
46160         true,
46161         false
46162     ],
46163     "BSD-2-Clause-FreeBSD": [
46164         "BSD 2-Clause FreeBSD License",
46165         false,
46166         false
46167     ],
46168     "BSD-2-Clause-NetBSD": [
46169         "BSD 2-Clause NetBSD License",
46170         false,
46171         false
46172     ],
46173     "BSD-2-Clause-Patent": [
46174         "BSD-2-Clause Plus Patent License",
46175         true,
46176         false
46177     ],
46178     "BSD-3-Clause": [
46179         "BSD 3-Clause \"New\" or \"Revised\" License",
46180         true,
46181         false
46182     ],
46183     "BSD-3-Clause-Attribution": [
46184         "BSD with attribution",
46185         false,
46186         false
46187     ],
46188     "BSD-3-Clause-Clear": [
46189         "BSD 3-Clause Clear License",
46190         false,
46191         false
46192     ],
46193     "BSD-3-Clause-LBNL": [
46194         "Lawrence Berkeley National Labs BSD variant license",
46195         false,
46196         false
46197     ],
46198     "BSD-3-Clause-No-Nuclear-License": [
46199         "BSD 3-Clause No Nuclear License",
46200         false,
46201         false
46202     ],
46203     "BSD-3-Clause-No-Nuclear-License-2014": [
46204         "BSD 3-Clause No Nuclear License 2014",
46205         false,
46206         false
46207     ],
46208     "BSD-3-Clause-No-Nuclear-Warranty": [
46209         "BSD 3-Clause No Nuclear Warranty",
46210         false,
46211         false
46212     ],
46213     "BSD-4-Clause": [
46214         "BSD 4-Clause \"Original\" or \"Old\" License",
46215         false,
46216         false
46217     ],
46218     "BSD-4-Clause-UC": [
46219         "BSD-4-Clause (University of California-Specific)",
46220         false,
46221         false
46222     ],
46223     "BSD-Protection": [
46224         "BSD Protection License",
46225         false,
46226         false
46227     ],
46228     "BSD-Source-Code": [
46229         "BSD Source Code Attribution",
46230         false,
46231         false
46232     ],
46233     "BSL-1.0": [
46234         "Boost Software License 1.0",
46235         true,
46236         false
46237     ],
46238     "bzip2-1.0.5": [
46239         "bzip2 and libbzip2 License v1.0.5",
46240         false,
46241         false
46242     ],
46243     "bzip2-1.0.6": [
46244         "bzip2 and libbzip2 License v1.0.6",
46245         false,
46246         false
46247     ],
46248     "Caldera": [
46249         "Caldera License",
46250         false,
46251         false
46252     ],
46253     "CATOSL-1.1": [
46254         "Computer Associates Trusted Open Source License 1.1",
46255         true,
46256         false
46257     ],
46258     "CC-BY-1.0": [
46259         "Creative Commons Attribution 1.0",
46260         false,
46261         false
46262     ],
46263     "CC-BY-2.0": [
46264         "Creative Commons Attribution 2.0",
46265         false,
46266         false
46267     ],
46268     "CC-BY-2.5": [
46269         "Creative Commons Attribution 2.5",
46270         false,
46271         false
46272     ],
46273     "CC-BY-3.0": [
46274         "Creative Commons Attribution 3.0",
46275         false,
46276         false
46277     ],
46278     "CC-BY-4.0": [
46279         "Creative Commons Attribution 4.0",
46280         false,
46281         false
46282     ],
46283     "CC-BY-NC-1.0": [
46284         "Creative Commons Attribution Non Commercial 1.0",
46285         false,
46286         false
46287     ],
46288     "CC-BY-NC-2.0": [
46289         "Creative Commons Attribution Non Commercial 2.0",
46290         false,
46291         false
46292     ],
46293     "CC-BY-NC-2.5": [
46294         "Creative Commons Attribution Non Commercial 2.5",
46295         false,
46296         false
46297     ],
46298     "CC-BY-NC-3.0": [
46299         "Creative Commons Attribution Non Commercial 3.0",
46300         false,
46301         false
46302     ],
46303     "CC-BY-NC-4.0": [
46304         "Creative Commons Attribution Non Commercial 4.0",
46305         false,
46306         false
46307     ],
46308     "CC-BY-NC-ND-1.0": [
46309         "Creative Commons Attribution Non Commercial No Derivatives 1.0",
46310         false,
46311         false
46312     ],
46313     "CC-BY-NC-ND-2.0": [
46314         "Creative Commons Attribution Non Commercial No Derivatives 2.0",
46315         false,
46316         false
46317     ],
46318     "CC-BY-NC-ND-2.5": [
46319         "Creative Commons Attribution Non Commercial No Derivatives 2.5",
46320         false,
46321         false
46322     ],
46323     "CC-BY-NC-ND-3.0": [
46324         "Creative Commons Attribution Non Commercial No Derivatives 3.0",
46325         false,
46326         false
46327     ],
46328     "CC-BY-NC-ND-4.0": [
46329         "Creative Commons Attribution Non Commercial No Derivatives 4.0",
46330         false,
46331         false
46332     ],
46333     "CC-BY-NC-SA-1.0": [
46334         "Creative Commons Attribution Non Commercial Share Alike 1.0",
46335         false,
46336         false
46337     ],
46338     "CC-BY-NC-SA-2.0": [
46339         "Creative Commons Attribution Non Commercial Share Alike 2.0",
46340         false,
46341         false
46342     ],
46343     "CC-BY-NC-SA-2.5": [
46344         "Creative Commons Attribution Non Commercial Share Alike 2.5",
46345         false,
46346         false
46347     ],
46348     "CC-BY-NC-SA-3.0": [
46349         "Creative Commons Attribution Non Commercial Share Alike 3.0",
46350         false,
46351         false
46352     ],
46353     "CC-BY-NC-SA-4.0": [
46354         "Creative Commons Attribution Non Commercial Share Alike 4.0",
46355         false,
46356         false
46357     ],
46358     "CC-BY-ND-1.0": [
46359         "Creative Commons Attribution No Derivatives 1.0",
46360         false,
46361         false
46362     ],
46363     "CC-BY-ND-2.0": [
46364         "Creative Commons Attribution No Derivatives 2.0",
46365         false,
46366         false
46367     ],
46368     "CC-BY-ND-2.5": [
46369         "Creative Commons Attribution No Derivatives 2.5",
46370         false,
46371         false
46372     ],
46373     "CC-BY-ND-3.0": [
46374         "Creative Commons Attribution No Derivatives 3.0",
46375         false,
46376         false
46377     ],
46378     "CC-BY-ND-4.0": [
46379         "Creative Commons Attribution No Derivatives 4.0",
46380         false,
46381         false
46382     ],
46383     "CC-BY-SA-1.0": [
46384         "Creative Commons Attribution Share Alike 1.0",
46385         false,
46386         false
46387     ],
46388     "CC-BY-SA-2.0": [
46389         "Creative Commons Attribution Share Alike 2.0",
46390         false,
46391         false
46392     ],
46393     "CC-BY-SA-2.5": [
46394         "Creative Commons Attribution Share Alike 2.5",
46395         false,
46396         false
46397     ],
46398     "CC-BY-SA-3.0": [
46399         "Creative Commons Attribution Share Alike 3.0",
46400         false,
46401         false
46402     ],
46403     "CC-BY-SA-4.0": [
46404         "Creative Commons Attribution Share Alike 4.0",
46405         false,
46406         false
46407     ],
46408     "CC0-1.0": [
46409         "Creative Commons Zero v1.0 Universal",
46410         false,
46411         false
46412     ],
46413     "CDDL-1.0": [
46414         "Common Development and Distribution License 1.0",
46415         true,
46416         false
46417     ],
46418     "CDDL-1.1": [
46419         "Common Development and Distribution License 1.1",
46420         false,
46421         false
46422     ],
46423     "CDLA-Permissive-1.0": [
46424         "Community Data License Agreement Permissive 1.0",
46425         false,
46426         false
46427     ],
46428     "CDLA-Sharing-1.0": [
46429         "Community Data License Agreement Sharing 1.0",
46430         false,
46431         false
46432     ],
46433     "CECILL-1.0": [
46434         "CeCILL Free Software License Agreement v1.0",
46435         false,
46436         false
46437     ],
46438     "CECILL-1.1": [
46439         "CeCILL Free Software License Agreement v1.1",
46440         false,
46441         false
46442     ],
46443     "CECILL-2.0": [
46444         "CeCILL Free Software License Agreement v2.0",
46445         false,
46446         false
46447     ],
46448     "CECILL-2.1": [
46449         "CeCILL Free Software License Agreement v2.1",
46450         true,
46451         false
46452     ],
46453     "CECILL-B": [
46454         "CeCILL-B Free Software License Agreement",
46455         false,
46456         false
46457     ],
46458     "CECILL-C": [
46459         "CeCILL-C Free Software License Agreement",
46460         false,
46461         false
46462     ],
46463     "ClArtistic": [
46464         "Clarified Artistic License",
46465         false,
46466         false
46467     ],
46468     "CNRI-Jython": [
46469         "CNRI Jython License",
46470         false,
46471         false
46472     ],
46473     "CNRI-Python": [
46474         "CNRI Python License",
46475         true,
46476         false
46477     ],
46478     "CNRI-Python-GPL-Compatible": [
46479         "CNRI Python Open Source GPL Compatible License Agreement",
46480         false,
46481         false
46482     ],
46483     "Condor-1.1": [
46484         "Condor Public License v1.1",
46485         false,
46486         false
46487     ],
46488     "CPAL-1.0": [
46489         "Common Public Attribution License 1.0",
46490         true,
46491         false
46492     ],
46493     "CPL-1.0": [
46494         "Common Public License 1.0",
46495         true,
46496         false
46497     ],
46498     "CPOL-1.02": [
46499         "Code Project Open License 1.02",
46500         false,
46501         false
46502     ],
46503     "Crossword": [
46504         "Crossword License",
46505         false,
46506         false
46507     ],
46508     "CrystalStacker": [
46509         "CrystalStacker License",
46510         false,
46511         false
46512     ],
46513     "CUA-OPL-1.0": [
46514         "CUA Office Public License v1.0",
46515         true,
46516         false
46517     ],
46518     "Cube": [
46519         "Cube License",
46520         false,
46521         false
46522     ],
46523     "curl": [
46524         "curl License",
46525         false,
46526         false
46527     ],
46528     "D-FSL-1.0": [
46529         "Deutsche Freie Software Lizenz",
46530         false,
46531         false
46532     ],
46533     "diffmark": [
46534         "diffmark license",
46535         false,
46536         false
46537     ],
46538     "DOC": [
46539         "DOC License",
46540         false,
46541         false
46542     ],
46543     "Dotseqn": [
46544         "Dotseqn License",
46545         false,
46546         false
46547     ],
46548     "DSDP": [
46549         "DSDP License",
46550         false,
46551         false
46552     ],
46553     "dvipdfm": [
46554         "dvipdfm License",
46555         false,
46556         false
46557     ],
46558     "ECL-1.0": [
46559         "Educational Community License v1.0",
46560         true,
46561         false
46562     ],
46563     "ECL-2.0": [
46564         "Educational Community License v2.0",
46565         true,
46566         false
46567     ],
46568     "eCos-2.0": [
46569         "eCos license version 2.0",
46570         false,
46571         true
46572     ],
46573     "EFL-1.0": [
46574         "Eiffel Forum License v1.0",
46575         true,
46576         false
46577     ],
46578     "EFL-2.0": [
46579         "Eiffel Forum License v2.0",
46580         true,
46581         false
46582     ],
46583     "eGenix": [
46584         "eGenix.com Public License 1.1.0",
46585         false,
46586         false
46587     ],
46588     "Entessa": [
46589         "Entessa Public License v1.0",
46590         true,
46591         false
46592     ],
46593     "EPL-1.0": [
46594         "Eclipse Public License 1.0",
46595         true,
46596         false
46597     ],
46598     "EPL-2.0": [
46599         "Eclipse Public License 2.0",
46600         true,
46601         false
46602     ],
46603     "ErlPL-1.1": [
46604         "Erlang Public License v1.1",
46605         false,
46606         false
46607     ],
46608     "EUDatagrid": [
46609         "EU DataGrid Software License",
46610         true,
46611         false
46612     ],
46613     "EUPL-1.0": [
46614         "European Union Public License 1.0",
46615         false,
46616         false
46617     ],
46618     "EUPL-1.1": [
46619         "European Union Public License 1.1",
46620         true,
46621         false
46622     ],
46623     "EUPL-1.2": [
46624         "European Union Public License 1.2",
46625         true,
46626         false
46627     ],
46628     "Eurosym": [
46629         "Eurosym License",
46630         false,
46631         false
46632     ],
46633     "Fair": [
46634         "Fair License",
46635         true,
46636         false
46637     ],
46638     "Frameworx-1.0": [
46639         "Frameworx Open License 1.0",
46640         true,
46641         false
46642     ],
46643     "FreeImage": [
46644         "FreeImage Public License v1.0",
46645         false,
46646         false
46647     ],
46648     "FSFAP": [
46649         "FSF All Permissive License",
46650         false,
46651         false
46652     ],
46653     "FSFUL": [
46654         "FSF Unlimited License",
46655         false,
46656         false
46657     ],
46658     "FSFULLR": [
46659         "FSF Unlimited License (with License Retention)",
46660         false,
46661         false
46662     ],
46663     "FTL": [
46664         "Freetype Project License",
46665         false,
46666         false
46667     ],
46668     "GFDL-1.1": [
46669         "GNU Free Documentation License v1.1",
46670         false,
46671         true
46672     ],
46673     "GFDL-1.1-only": [
46674         "GNU Free Documentation License v1.1 only",
46675         false,
46676         false
46677     ],
46678     "GFDL-1.1-or-later": [
46679         "GNU Free Documentation License v1.1 or later",
46680         false,
46681         false
46682     ],
46683     "GFDL-1.2": [
46684         "GNU Free Documentation License v1.2",
46685         false,
46686         true
46687     ],
46688     "GFDL-1.2-only": [
46689         "GNU Free Documentation License v1.2 only",
46690         false,
46691         false
46692     ],
46693     "GFDL-1.2-or-later": [
46694         "GNU Free Documentation License v1.2 or later",
46695         false,
46696         false
46697     ],
46698     "GFDL-1.3": [
46699         "GNU Free Documentation License v1.3",
46700         false,
46701         true
46702     ],
46703     "GFDL-1.3-only": [
46704         "GNU Free Documentation License v1.3 only",
46705         false,
46706         false
46707     ],
46708     "GFDL-1.3-or-later": [
46709         "GNU Free Documentation License v1.3 or later",
46710         false,
46711         false
46712     ],
46713     "Giftware": [
46714         "Giftware License",
46715         false,
46716         false
46717     ],
46718     "GL2PS": [
46719         "GL2PS License",
46720         false,
46721         false
46722     ],
46723     "Glide": [
46724         "3dfx Glide License",
46725         false,
46726         false
46727     ],
46728     "Glulxe": [
46729         "Glulxe License",
46730         false,
46731         false
46732     ],
46733     "gnuplot": [
46734         "gnuplot License",
46735         false,
46736         false
46737     ],
46738     "GPL-1.0": [
46739         "GNU General Public License v1.0 only",
46740         false,
46741         true
46742     ],
46743     "GPL-1.0+": [
46744         "GNU General Public License v1.0 or later",
46745         false,
46746         true
46747     ],
46748     "GPL-1.0-only": [
46749         "GNU General Public License v1.0 only",
46750         false,
46751         false
46752     ],
46753     "GPL-1.0-or-later": [
46754         "GNU General Public License v1.0 or later",
46755         false,
46756         false
46757     ],
46758     "GPL-2.0": [
46759         "GNU General Public License v2.0 only",
46760         true,
46761         true
46762     ],
46763     "GPL-2.0+": [
46764         "GNU General Public License v2.0 or later",
46765         true,
46766         true
46767     ],
46768     "GPL-2.0-only": [
46769         "GNU General Public License v2.0 only",
46770         true,
46771         false
46772     ],
46773     "GPL-2.0-or-later": [
46774         "GNU General Public License v2.0 or later",
46775         true,
46776         false
46777     ],
46778     "GPL-2.0-with-autoconf-exception": [
46779         "GNU General Public License v2.0 w/Autoconf exception",
46780         false,
46781         true
46782     ],
46783     "GPL-2.0-with-bison-exception": [
46784         "GNU General Public License v2.0 w/Bison exception",
46785         false,
46786         true
46787     ],
46788     "GPL-2.0-with-classpath-exception": [
46789         "GNU General Public License v2.0 w/Classpath exception",
46790         false,
46791         true
46792     ],
46793     "GPL-2.0-with-font-exception": [
46794         "GNU General Public License v2.0 w/Font exception",
46795         false,
46796         true
46797     ],
46798     "GPL-2.0-with-GCC-exception": [
46799         "GNU General Public License v2.0 w/GCC Runtime Library exception",
46800         false,
46801         true
46802     ],
46803     "GPL-3.0": [
46804         "GNU General Public License v3.0 only",
46805         true,
46806         true
46807     ],
46808     "GPL-3.0+": [
46809         "GNU General Public License v3.0 or later",
46810         true,
46811         true
46812     ],
46813     "GPL-3.0-only": [
46814         "GNU General Public License v3.0 only",
46815         true,
46816         false
46817     ],
46818     "GPL-3.0-or-later": [
46819         "GNU General Public License v3.0 or later",
46820         true,
46821         false
46822     ],
46823     "GPL-3.0-with-autoconf-exception": [
46824         "GNU General Public License v3.0 w/Autoconf exception",
46825         false,
46826         true
46827     ],
46828     "GPL-3.0-with-GCC-exception": [
46829         "GNU General Public License v3.0 w/GCC Runtime Library exception",
46830         true,
46831         true
46832     ],
46833     "gSOAP-1.3b": [
46834         "gSOAP Public License v1.3b",
46835         false,
46836         false
46837     ],
46838     "HaskellReport": [
46839         "Haskell Language Report License",
46840         false,
46841         false
46842     ],
46843     "HPND": [
46844         "Historical Permission Notice and Disclaimer",
46845         true,
46846         false
46847     ],
46848     "IBM-pibs": [
46849         "IBM PowerPC Initialization and Boot Software",
46850         false,
46851         false
46852     ],
46853     "ICU": [
46854         "ICU License",
46855         false,
46856         false
46857     ],
46858     "IJG": [
46859         "Independent JPEG Group License",
46860         false,
46861         false
46862     ],
46863     "ImageMagick": [
46864         "ImageMagick License",
46865         false,
46866         false
46867     ],
46868     "iMatix": [
46869         "iMatix Standard Function Library Agreement",
46870         false,
46871         false
46872     ],
46873     "Imlib2": [
46874         "Imlib2 License",
46875         false,
46876         false
46877     ],
46878     "Info-ZIP": [
46879         "Info-ZIP License",
46880         false,
46881         false
46882     ],
46883     "Intel": [
46884         "Intel Open Source License",
46885         true,
46886         false
46887     ],
46888     "Intel-ACPI": [
46889         "Intel ACPI Software License Agreement",
46890         false,
46891         false
46892     ],
46893     "Interbase-1.0": [
46894         "Interbase Public License v1.0",
46895         false,
46896         false
46897     ],
46898     "IPA": [
46899         "IPA Font License",
46900         true,
46901         false
46902     ],
46903     "IPL-1.0": [
46904         "IBM Public License v1.0",
46905         true,
46906         false
46907     ],
46908     "ISC": [
46909         "ISC License",
46910         true,
46911         false
46912     ],
46913     "JasPer-2.0": [
46914         "JasPer License",
46915         false,
46916         false
46917     ],
46918     "JSON": [
46919         "JSON License",
46920         false,
46921         false
46922     ],
46923     "LAL-1.2": [
46924         "Licence Art Libre 1.2",
46925         false,
46926         false
46927     ],
46928     "LAL-1.3": [
46929         "Licence Art Libre 1.3",
46930         false,
46931         false
46932     ],
46933     "Latex2e": [
46934         "Latex2e License",
46935         false,
46936         false
46937     ],
46938     "Leptonica": [
46939         "Leptonica License",
46940         false,
46941         false
46942     ],
46943     "LGPL-2.0": [
46944         "GNU Library General Public License v2 only",
46945         true,
46946         true
46947     ],
46948     "LGPL-2.0+": [
46949         "GNU Library General Public License v2 or later",
46950         true,
46951         true
46952     ],
46953     "LGPL-2.0-only": [
46954         "GNU Library General Public License v2 only",
46955         true,
46956         false
46957     ],
46958     "LGPL-2.0-or-later": [
46959         "GNU Library General Public License v2 or later",
46960         true,
46961         false
46962     ],
46963     "LGPL-2.1": [
46964         "GNU Lesser General Public License v2.1 only",
46965         true,
46966         true
46967     ],
46968     "LGPL-2.1+": [
46969         "GNU Library General Public License v2 or later",
46970         true,
46971         true
46972     ],
46973     "LGPL-2.1-only": [
46974         "GNU Lesser General Public License v2.1 only",
46975         true,
46976         false
46977     ],
46978     "LGPL-2.1-or-later": [
46979         "GNU Lesser General Public License v2.1 or later",
46980         true,
46981         false
46982     ],
46983     "LGPL-3.0": [
46984         "GNU Lesser General Public License v3.0 only",
46985         true,
46986         true
46987     ],
46988     "LGPL-3.0+": [
46989         "GNU Lesser General Public License v3.0 or later",
46990         true,
46991         true
46992     ],
46993     "LGPL-3.0-only": [
46994         "GNU Lesser General Public License v3.0 only",
46995         true,
46996         false
46997     ],
46998     "LGPL-3.0-or-later": [
46999         "GNU Lesser General Public License v3.0 or later",
47000         true,
47001         false
47002     ],
47003     "LGPLLR": [
47004         "Lesser General Public License For Linguistic Resources",
47005         false,
47006         false
47007     ],
47008     "Libpng": [
47009         "libpng License",
47010         false,
47011         false
47012     ],
47013     "libtiff": [
47014         "libtiff License",
47015         false,
47016         false
47017     ],
47018     "LiLiQ-P-1.1": [
47019         "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1",
47020         true,
47021         false
47022     ],
47023     "LiLiQ-R-1.1": [
47024         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1",
47025         true,
47026         false
47027     ],
47028     "LiLiQ-Rplus-1.1": [
47029         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1",
47030         true,
47031         false
47032     ],
47033     "LPL-1.0": [
47034         "Lucent Public License Version 1.0",
47035         true,
47036         false
47037     ],
47038     "LPL-1.02": [
47039         "Lucent Public License v1.02",
47040         true,
47041         false
47042     ],
47043     "LPPL-1.0": [
47044         "LaTeX Project Public License v1.0",
47045         false,
47046         false
47047     ],
47048     "LPPL-1.1": [
47049         "LaTeX Project Public License v1.1",
47050         false,
47051         false
47052     ],
47053     "LPPL-1.2": [
47054         "LaTeX Project Public License v1.2",
47055         false,
47056         false
47057     ],
47058     "LPPL-1.3a": [
47059         "LaTeX Project Public License v1.3a",
47060         false,
47061         false
47062     ],
47063     "LPPL-1.3c": [
47064         "LaTeX Project Public License v1.3c",
47065         true,
47066         false
47067     ],
47068     "MakeIndex": [
47069         "MakeIndex License",
47070         false,
47071         false
47072     ],
47073     "MirOS": [
47074         "MirOS License",
47075         true,
47076         false
47077     ],
47078     "MIT": [
47079         "MIT License",
47080         true,
47081         false
47082     ],
47083     "MIT-advertising": [
47084         "Enlightenment License (e16)",
47085         false,
47086         false
47087     ],
47088     "MIT-CMU": [
47089         "CMU License",
47090         false,
47091         false
47092     ],
47093     "MIT-enna": [
47094         "enna License",
47095         false,
47096         false
47097     ],
47098     "MIT-feh": [
47099         "feh License",
47100         false,
47101         false
47102     ],
47103     "MITNFA": [
47104         "MIT +no-false-attribs license",
47105         false,
47106         false
47107     ],
47108     "Motosoto": [
47109         "Motosoto License",
47110         true,
47111         false
47112     ],
47113     "mpich2": [
47114         "mpich2 License",
47115         false,
47116         false
47117     ],
47118     "MPL-1.0": [
47119         "Mozilla Public License 1.0",
47120         true,
47121         false
47122     ],
47123     "MPL-1.1": [
47124         "Mozilla Public License 1.1",
47125         true,
47126         false
47127     ],
47128     "MPL-2.0": [
47129         "Mozilla Public License 2.0",
47130         true,
47131         false
47132     ],
47133     "MPL-2.0-no-copyleft-exception": [
47134         "Mozilla Public License 2.0 (no copyleft exception)",
47135         true,
47136         false
47137     ],
47138     "MS-PL": [
47139         "Microsoft Public License",
47140         true,
47141         false
47142     ],
47143     "MS-RL": [
47144         "Microsoft Reciprocal License",
47145         true,
47146         false
47147     ],
47148     "MTLL": [
47149         "Matrix Template Library License",
47150         false,
47151         false
47152     ],
47153     "Multics": [
47154         "Multics License",
47155         true,
47156         false
47157     ],
47158     "Mup": [
47159         "Mup License",
47160         false,
47161         false
47162     ],
47163     "NASA-1.3": [
47164         "NASA Open Source Agreement 1.3",
47165         true,
47166         false
47167     ],
47168     "Naumen": [
47169         "Naumen Public License",
47170         true,
47171         false
47172     ],
47173     "NBPL-1.0": [
47174         "Net Boolean Public License v1",
47175         false,
47176         false
47177     ],
47178     "NCSA": [
47179         "University of Illinois/NCSA Open Source License",
47180         true,
47181         false
47182     ],
47183     "Net-SNMP": [
47184         "Net-SNMP License",
47185         false,
47186         false
47187     ],
47188     "NetCDF": [
47189         "NetCDF license",
47190         false,
47191         false
47192     ],
47193     "Newsletr": [
47194         "Newsletr License",
47195         false,
47196         false
47197     ],
47198     "NGPL": [
47199         "Nethack General Public License",
47200         true,
47201         false
47202     ],
47203     "NLOD-1.0": [
47204         "Norwegian Licence for Open Government Data",
47205         false,
47206         false
47207     ],
47208     "NLPL": [
47209         "No Limit Public License",
47210         false,
47211         false
47212     ],
47213     "Nokia": [
47214         "Nokia Open Source License",
47215         true,
47216         false
47217     ],
47218     "NOSL": [
47219         "Netizen Open Source License",
47220         false,
47221         false
47222     ],
47223     "Noweb": [
47224         "Noweb License",
47225         false,
47226         false
47227     ],
47228     "NPL-1.0": [
47229         "Netscape Public License v1.0",
47230         false,
47231         false
47232     ],
47233     "NPL-1.1": [
47234         "Netscape Public License v1.1",
47235         false,
47236         false
47237     ],
47238     "NPOSL-3.0": [
47239         "Non-Profit Open Software License 3.0",
47240         true,
47241         false
47242     ],
47243     "NRL": [
47244         "NRL License",
47245         false,
47246         false
47247     ],
47248     "NTP": [
47249         "NTP License",
47250         true,
47251         false
47252     ],
47253     "Nunit": [
47254         "Nunit License",
47255         false,
47256         true
47257     ],
47258     "OCCT-PL": [
47259         "Open CASCADE Technology Public License",
47260         false,
47261         false
47262     ],
47263     "OCLC-2.0": [
47264         "OCLC Research Public License 2.0",
47265         true,
47266         false
47267     ],
47268     "ODbL-1.0": [
47269         "ODC Open Database License v1.0",
47270         false,
47271         false
47272     ],
47273     "OFL-1.0": [
47274         "SIL Open Font License 1.0",
47275         false,
47276         false
47277     ],
47278     "OFL-1.1": [
47279         "SIL Open Font License 1.1",
47280         true,
47281         false
47282     ],
47283     "OGTSL": [
47284         "Open Group Test Suite License",
47285         true,
47286         false
47287     ],
47288     "OLDAP-1.1": [
47289         "Open LDAP Public License v1.1",
47290         false,
47291         false
47292     ],
47293     "OLDAP-1.2": [
47294         "Open LDAP Public License v1.2",
47295         false,
47296         false
47297     ],
47298     "OLDAP-1.3": [
47299         "Open LDAP Public License v1.3",
47300         false,
47301         false
47302     ],
47303     "OLDAP-1.4": [
47304         "Open LDAP Public License v1.4",
47305         false,
47306         false
47307     ],
47308     "OLDAP-2.0": [
47309         "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
47310         false,
47311         false
47312     ],
47313     "OLDAP-2.0.1": [
47314         "Open LDAP Public License v2.0.1",
47315         false,
47316         false
47317     ],
47318     "OLDAP-2.1": [
47319         "Open LDAP Public License v2.1",
47320         false,
47321         false
47322     ],
47323     "OLDAP-2.2": [
47324         "Open LDAP Public License v2.2",
47325         false,
47326         false
47327     ],
47328     "OLDAP-2.2.1": [
47329         "Open LDAP Public License v2.2.1",
47330         false,
47331         false
47332     ],
47333     "OLDAP-2.2.2": [
47334         "Open LDAP Public License 2.2.2",
47335         false,
47336         false
47337     ],
47338     "OLDAP-2.3": [
47339         "Open LDAP Public License v2.3",
47340         false,
47341         false
47342     ],
47343     "OLDAP-2.4": [
47344         "Open LDAP Public License v2.4",
47345         false,
47346         false
47347     ],
47348     "OLDAP-2.5": [
47349         "Open LDAP Public License v2.5",
47350         false,
47351         false
47352     ],
47353     "OLDAP-2.6": [
47354         "Open LDAP Public License v2.6",
47355         false,
47356         false
47357     ],
47358     "OLDAP-2.7": [
47359         "Open LDAP Public License v2.7",
47360         false,
47361         false
47362     ],
47363     "OLDAP-2.8": [
47364         "Open LDAP Public License v2.8",
47365         false,
47366         false
47367     ],
47368     "OML": [
47369         "Open Market License",
47370         false,
47371         false
47372     ],
47373     "OpenSSL": [
47374         "OpenSSL License",
47375         false,
47376         false
47377     ],
47378     "OPL-1.0": [
47379         "Open Public License v1.0",
47380         false,
47381         false
47382     ],
47383     "OSET-PL-2.1": [
47384         "OSET Public License version 2.1",
47385         true,
47386         false
47387     ],
47388     "OSL-1.0": [
47389         "Open Software License 1.0",
47390         true,
47391         false
47392     ],
47393     "OSL-1.1": [
47394         "Open Software License 1.1",
47395         false,
47396         false
47397     ],
47398     "OSL-2.0": [
47399         "Open Software License 2.0",
47400         true,
47401         false
47402     ],
47403     "OSL-2.1": [
47404         "Open Software License 2.1",
47405         true,
47406         false
47407     ],
47408     "OSL-3.0": [
47409         "Open Software License 3.0",
47410         true,
47411         false
47412     ],
47413     "PDDL-1.0": [
47414         "ODC Public Domain Dedication & License 1.0",
47415         false,
47416         false
47417     ],
47418     "PHP-3.0": [
47419         "PHP License v3.0",
47420         true,
47421         false
47422     ],
47423     "PHP-3.01": [
47424         "PHP License v3.01",
47425         false,
47426         false
47427     ],
47428     "Plexus": [
47429         "Plexus Classworlds License",
47430         false,
47431         false
47432     ],
47433     "PostgreSQL": [
47434         "PostgreSQL License",
47435         true,
47436         false
47437     ],
47438     "psfrag": [
47439         "psfrag License",
47440         false,
47441         false
47442     ],
47443     "psutils": [
47444         "psutils License",
47445         false,
47446         false
47447     ],
47448     "Python-2.0": [
47449         "Python License 2.0",
47450         true,
47451         false
47452     ],
47453     "Qhull": [
47454         "Qhull License",
47455         false,
47456         false
47457     ],
47458     "QPL-1.0": [
47459         "Q Public License 1.0",
47460         true,
47461         false
47462     ],
47463     "Rdisc": [
47464         "Rdisc License",
47465         false,
47466         false
47467     ],
47468     "RHeCos-1.1": [
47469         "Red Hat eCos Public License v1.1",
47470         false,
47471         false
47472     ],
47473     "RPL-1.1": [
47474         "Reciprocal Public License 1.1",
47475         true,
47476         false
47477     ],
47478     "RPL-1.5": [
47479         "Reciprocal Public License 1.5",
47480         true,
47481         false
47482     ],
47483     "RPSL-1.0": [
47484         "RealNetworks Public Source License v1.0",
47485         true,
47486         false
47487     ],
47488     "RSA-MD": [
47489         "RSA Message-Digest License",
47490         false,
47491         false
47492     ],
47493     "RSCPL": [
47494         "Ricoh Source Code Public License",
47495         true,
47496         false
47497     ],
47498     "Ruby": [
47499         "Ruby License",
47500         false,
47501         false
47502     ],
47503     "SAX-PD": [
47504         "Sax Public Domain Notice",
47505         false,
47506         false
47507     ],
47508     "Saxpath": [
47509         "Saxpath License",
47510         false,
47511         false
47512     ],
47513     "SCEA": [
47514         "SCEA Shared Source License",
47515         false,
47516         false
47517     ],
47518     "Sendmail": [
47519         "Sendmail License",
47520         false,
47521         false
47522     ],
47523     "SGI-B-1.0": [
47524         "SGI Free Software License B v1.0",
47525         false,
47526         false
47527     ],
47528     "SGI-B-1.1": [
47529         "SGI Free Software License B v1.1",
47530         false,
47531         false
47532     ],
47533     "SGI-B-2.0": [
47534         "SGI Free Software License B v2.0",
47535         false,
47536         false
47537     ],
47538     "SimPL-2.0": [
47539         "Simple Public License 2.0",
47540         true,
47541         false
47542     ],
47543     "SISSL": [
47544         "Sun Industry Standards Source License v1.1",
47545         true,
47546         false
47547     ],
47548     "SISSL-1.2": [
47549         "Sun Industry Standards Source License v1.2",
47550         false,
47551         false
47552     ],
47553     "Sleepycat": [
47554         "Sleepycat License",
47555         true,
47556         false
47557     ],
47558     "SMLNJ": [
47559         "Standard ML of New Jersey License",
47560         false,
47561         false
47562     ],
47563     "SMPPL": [
47564         "Secure Messaging Protocol Public License",
47565         false,
47566         false
47567     ],
47568     "SNIA": [
47569         "SNIA Public License 1.1",
47570         false,
47571         false
47572     ],
47573     "Spencer-86": [
47574         "Spencer License 86",
47575         false,
47576         false
47577     ],
47578     "Spencer-94": [
47579         "Spencer License 94",
47580         false,
47581         false
47582     ],
47583     "Spencer-99": [
47584         "Spencer License 99",
47585         false,
47586         false
47587     ],
47588     "SPL-1.0": [
47589         "Sun Public License v1.0",
47590         true,
47591         false
47592     ],
47593     "StandardML-NJ": [
47594         "Standard ML of New Jersey License",
47595         false,
47596         true
47597     ],
47598     "SugarCRM-1.1.3": [
47599         "SugarCRM Public License v1.1.3",
47600         false,
47601         false
47602     ],
47603     "SWL": [
47604         "Scheme Widget Library (SWL) Software License Agreement",
47605         false,
47606         false
47607     ],
47608     "TCL": [
47609         "TCL/TK License",
47610         false,
47611         false
47612     ],
47613     "TCP-wrappers": [
47614         "TCP Wrappers License",
47615         false,
47616         false
47617     ],
47618     "TMate": [
47619         "TMate Open Source License",
47620         false,
47621         false
47622     ],
47623     "TORQUE-1.1": [
47624         "TORQUE v2.5+ Software License v1.1",
47625         false,
47626         false
47627     ],
47628     "TOSL": [
47629         "Trusster Open Source License",
47630         false,
47631         false
47632     ],
47633     "Unicode-DFS-2015": [
47634         "Unicode License Agreement - Data Files and Software (2015)",
47635         false,
47636         false
47637     ],
47638     "Unicode-DFS-2016": [
47639         "Unicode License Agreement - Data Files and Software (2016)",
47640         false,
47641         false
47642     ],
47643     "Unicode-TOU": [
47644         "Unicode Terms of Use",
47645         false,
47646         false
47647     ],
47648     "Unlicense": [
47649         "The Unlicense",
47650         false,
47651         false
47652     ],
47653     "UPL-1.0": [
47654         "Universal Permissive License v1.0",
47655         true,
47656         false
47657     ],
47658     "Vim": [
47659         "Vim License",
47660         false,
47661         false
47662     ],
47663     "VOSTROM": [
47664         "VOSTROM Public License for Open Source",
47665         false,
47666         false
47667     ],
47668     "VSL-1.0": [
47669         "Vovida Software License v1.0",
47670         true,
47671         false
47672     ],
47673     "W3C": [
47674         "W3C Software Notice and License (2002-12-31)",
47675         true,
47676         false
47677     ],
47678     "W3C-19980720": [
47679         "W3C Software Notice and License (1998-07-20)",
47680         false,
47681         false
47682     ],
47683     "W3C-20150513": [
47684         "W3C Software Notice and Document License (2015-05-13)",
47685         false,
47686         false
47687     ],
47688     "Watcom-1.0": [
47689         "Sybase Open Watcom Public License 1.0",
47690         true,
47691         false
47692     ],
47693     "Wsuipa": [
47694         "Wsuipa License",
47695         false,
47696         false
47697     ],
47698     "WTFPL": [
47699         "Do What The F*ck You Want To Public License",
47700         false,
47701         false
47702     ],
47703     "wxWindows": [
47704         "wxWindows Library License",
47705         false,
47706         true
47707     ],
47708     "X11": [
47709         "X11 License",
47710         false,
47711         false
47712     ],
47713     "Xerox": [
47714         "Xerox License",
47715         false,
47716         false
47717     ],
47718     "XFree86-1.1": [
47719         "XFree86 License 1.1",
47720         false,
47721         false
47722     ],
47723     "xinetd": [
47724         "xinetd License",
47725         false,
47726         false
47727     ],
47728     "Xnet": [
47729         "X.Net License",
47730         true,
47731         false
47732     ],
47733     "xpp": [
47734         "XPP License",
47735         false,
47736         false
47737     ],
47738     "XSkat": [
47739         "XSkat License",
47740         false,
47741         false
47742     ],
47743     "YPL-1.0": [
47744         "Yahoo! Public License v1.0",
47745         false,
47746         false
47747     ],
47748     "YPL-1.1": [
47749         "Yahoo! Public License v1.1",
47750         false,
47751         false
47752     ],
47753     "Zed": [
47754         "Zed License",
47755         false,
47756         false
47757     ],
47758     "Zend-2.0": [
47759         "Zend License v2.0",
47760         false,
47761         false
47762     ],
47763     "Zimbra-1.3": [
47764         "Zimbra Public License v1.3",
47765         false,
47766         false
47767     ],
47768     "Zimbra-1.4": [
47769         "Zimbra Public License v1.4",
47770         false,
47771         false
47772     ],
47773     "Zlib": [
47774         "zlib License",
47775         true,
47776         false
47777     ],
47778     "zlib-acknowledgement": [
47779         "zlib/libpng License with Acknowledgement",
47780         false,
47781         false
47782     ],
47783     "ZPL-1.1": [
47784         "Zope Public License 1.1",
47785         false,
47786         false
47787     ],
47788     "ZPL-2.0": [
47789         "Zope Public License 2.0",
47790         true,
47791         false
47792     ],
47793     "ZPL-2.1": [
47794         "Zope Public License 2.1",
47795         false,
47796         false
47797     ]
47798 }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
47799 $\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
47800 \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
47801 \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
47802 \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
47803 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
47804 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
47805 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
47806   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">\r
47807     <security>\r
47808       <requestedPrivileges>\r
47809         <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>\r
47810       </requestedPrivileges>\r
47811     </security>\r
47812   </trustInfo>\r
47813   <dependency>\r
47814     <dependentAssembly>\r
47815       <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>\r
47816     </dependentAssembly>\r
47817   </dependency>\r
47818 </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
47819
47820
47821
47822
47823
47824
47825
47826
47827
47828
47829 namespace Symfony\Component\Console;
47830
47831 use Symfony\Component\Console\Descriptor\TextDescriptor;
47832 use Symfony\Component\Console\Descriptor\XmlDescriptor;
47833 use Symfony\Component\Console\Exception\ExceptionInterface;
47834 use Symfony\Component\Console\Formatter\OutputFormatter;
47835 use Symfony\Component\Console\Helper\DebugFormatterHelper;
47836 use Symfony\Component\Console\Helper\Helper;
47837 use Symfony\Component\Console\Helper\ProcessHelper;
47838 use Symfony\Component\Console\Helper\QuestionHelper;
47839 use Symfony\Component\Console\Input\InputInterface;
47840 use Symfony\Component\Console\Input\ArgvInput;
47841 use Symfony\Component\Console\Input\ArrayInput;
47842 use Symfony\Component\Console\Input\InputDefinition;
47843 use Symfony\Component\Console\Input\InputOption;
47844 use Symfony\Component\Console\Input\InputArgument;
47845 use Symfony\Component\Console\Input\InputAwareInterface;
47846 use Symfony\Component\Console\Output\BufferedOutput;
47847 use Symfony\Component\Console\Output\OutputInterface;
47848 use Symfony\Component\Console\Output\ConsoleOutput;
47849 use Symfony\Component\Console\Output\ConsoleOutputInterface;
47850 use Symfony\Component\Console\Command\Command;
47851 use Symfony\Component\Console\Command\HelpCommand;
47852 use Symfony\Component\Console\Command\ListCommand;
47853 use Symfony\Component\Console\Helper\HelperSet;
47854 use Symfony\Component\Console\Helper\FormatterHelper;
47855 use Symfony\Component\Console\Helper\DialogHelper;
47856 use Symfony\Component\Console\Helper\ProgressHelper;
47857 use Symfony\Component\Console\Helper\TableHelper;
47858 use Symfony\Component\Console\Event\ConsoleCommandEvent;
47859 use Symfony\Component\Console\Event\ConsoleExceptionEvent;
47860 use Symfony\Component\Console\Event\ConsoleTerminateEvent;
47861 use Symfony\Component\Console\Exception\CommandNotFoundException;
47862 use Symfony\Component\Console\Exception\LogicException;
47863 use Symfony\Component\Debug\Exception\FatalThrowableError;
47864 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
47865
47866
47867
47868
47869
47870
47871
47872
47873
47874
47875
47876
47877
47878
47879
47880
47881 class Application
47882 {
47883 private $commands = array();
47884 private $wantHelps = false;
47885 private $runningCommand;
47886 private $name;
47887 private $version;
47888 private $catchExceptions = true;
47889 private $autoExit = true;
47890 private $definition;
47891 private $helperSet;
47892 private $dispatcher;
47893 private $terminalDimensions;
47894 private $defaultCommand;
47895 private $initialized;
47896
47897
47898
47899
47900
47901 public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
47902 {
47903 $this->name = $name;
47904 $this->version = $version;
47905 $this->defaultCommand = 'list';
47906 }
47907
47908 public function setDispatcher(EventDispatcherInterface $dispatcher)
47909 {
47910 $this->dispatcher = $dispatcher;
47911 }
47912
47913
47914
47915
47916
47917
47918
47919
47920 public function run(InputInterface $input = null, OutputInterface $output = null)
47921 {
47922 if (null === $input) {
47923 $input = new ArgvInput();
47924 }
47925
47926 if (null === $output) {
47927 $output = new ConsoleOutput();
47928 }
47929
47930 $this->configureIO($input, $output);
47931
47932 try {
47933 $e = null;
47934 $exitCode = $this->doRun($input, $output);
47935 } catch (\Exception $e) {
47936 }
47937
47938 if (null !== $e) {
47939 if (!$this->catchExceptions) {
47940 throw $e;
47941 }
47942
47943 if ($output instanceof ConsoleOutputInterface) {
47944 $this->renderException($e, $output->getErrorOutput());
47945 } else {
47946 $this->renderException($e, $output);
47947 }
47948
47949 $exitCode = $e->getCode();
47950 if (is_numeric($exitCode)) {
47951 $exitCode = (int) $exitCode;
47952 if (0 === $exitCode) {
47953 $exitCode = 1;
47954 }
47955 } else {
47956 $exitCode = 1;
47957 }
47958 }
47959
47960 if ($this->autoExit) {
47961 if ($exitCode > 255) {
47962 $exitCode = 255;
47963 }
47964
47965 exit($exitCode);
47966 }
47967
47968 return $exitCode;
47969 }
47970
47971
47972
47973
47974
47975
47976 public function doRun(InputInterface $input, OutputInterface $output)
47977 {
47978 if (true === $input->hasParameterOption(array('--version', '-V'))) {
47979 $output->writeln($this->getLongVersion());
47980
47981 return 0;
47982 }
47983
47984 $name = $this->getCommandName($input);
47985 if (true === $input->hasParameterOption(array('--help', '-h'))) {
47986 if (!$name) {
47987 $name = 'help';
47988 $input = new ArrayInput(array('command' => 'help'));
47989 } else {
47990 $this->wantHelps = true;
47991 }
47992 }
47993
47994 if (!$name) {
47995 $name = $this->defaultCommand;
47996 $definition = $this->getDefinition();
47997 $definition->setArguments(array_merge(
47998 $definition->getArguments(),
47999 array(
48000 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
48001 )
48002 ));
48003 }
48004
48005 $this->runningCommand = null;
48006
48007  $command = $this->find($name);
48008
48009 $this->runningCommand = $command;
48010 $exitCode = $this->doRunCommand($command, $input, $output);
48011 $this->runningCommand = null;
48012
48013 return $exitCode;
48014 }
48015
48016 public function setHelperSet(HelperSet $helperSet)
48017 {
48018 $this->helperSet = $helperSet;
48019 }
48020
48021
48022
48023
48024
48025
48026 public function getHelperSet()
48027 {
48028 if (!$this->helperSet) {
48029 $this->helperSet = $this->getDefaultHelperSet();
48030 }
48031
48032 return $this->helperSet;
48033 }
48034
48035 public function setDefinition(InputDefinition $definition)
48036 {
48037 $this->definition = $definition;
48038 }
48039
48040
48041
48042
48043
48044
48045 public function getDefinition()
48046 {
48047 if (!$this->definition) {
48048 $this->definition = $this->getDefaultInputDefinition();
48049 }
48050
48051 return $this->definition;
48052 }
48053
48054
48055
48056
48057
48058
48059 public function getHelp()
48060 {
48061 return $this->getLongVersion();
48062 }
48063
48064
48065
48066
48067
48068
48069 public function setCatchExceptions($boolean)
48070 {
48071 $this->catchExceptions = (bool) $boolean;
48072 }
48073
48074
48075
48076
48077
48078
48079 public function setAutoExit($boolean)
48080 {
48081 $this->autoExit = (bool) $boolean;
48082 }
48083
48084
48085
48086
48087
48088
48089 public function getName()
48090 {
48091 return $this->name;
48092 }
48093
48094
48095
48096
48097
48098
48099 public function setName($name)
48100 {
48101 $this->name = $name;
48102 }
48103
48104
48105
48106
48107
48108
48109 public function getVersion()
48110 {
48111 return $this->version;
48112 }
48113
48114
48115
48116
48117
48118
48119 public function setVersion($version)
48120 {
48121 $this->version = $version;
48122 }
48123
48124
48125
48126
48127
48128
48129 public function getLongVersion()
48130 {
48131 if ('UNKNOWN' !== $this->getName()) {
48132 if ('UNKNOWN' !== $this->getVersion()) {
48133 return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
48134 }
48135
48136 return sprintf('<info>%s</info>', $this->getName());
48137 }
48138
48139 return '<info>Console Tool</info>';
48140 }
48141
48142
48143
48144
48145
48146
48147
48148
48149 public function register($name)
48150 {
48151 return $this->add(new Command($name));
48152 }
48153
48154
48155
48156
48157
48158
48159
48160
48161 public function addCommands(array $commands)
48162 {
48163 foreach ($commands as $command) {
48164 $this->add($command);
48165 }
48166 }
48167
48168
48169
48170
48171
48172
48173
48174
48175
48176 public function add(Command $command)
48177 {
48178 $this->init();
48179
48180 $command->setApplication($this);
48181
48182 if (!$command->isEnabled()) {
48183 $command->setApplication(null);
48184
48185 return;
48186 }
48187
48188 if (null === $command->getDefinition()) {
48189 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
48190 }
48191
48192 $this->commands[$command->getName()] = $command;
48193
48194 foreach ($command->getAliases() as $alias) {
48195 $this->commands[$alias] = $command;
48196 }
48197
48198 return $command;
48199 }
48200
48201
48202
48203
48204
48205
48206
48207
48208
48209
48210 public function get($name)
48211 {
48212 $this->init();
48213
48214 if (!isset($this->commands[$name])) {
48215 throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
48216 }
48217
48218 $command = $this->commands[$name];
48219
48220 if ($this->wantHelps) {
48221 $this->wantHelps = false;
48222
48223 $helpCommand = $this->get('help');
48224 $helpCommand->setCommand($command);
48225
48226 return $helpCommand;
48227 }
48228
48229 return $command;
48230 }
48231
48232
48233
48234
48235
48236
48237
48238
48239 public function has($name)
48240 {
48241 $this->init();
48242
48243 return isset($this->commands[$name]);
48244 }
48245
48246
48247
48248
48249
48250
48251
48252
48253 public function getNamespaces()
48254 {
48255 $namespaces = array();
48256 foreach ($this->all() as $command) {
48257 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
48258
48259 foreach ($command->getAliases() as $alias) {
48260 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
48261 }
48262 }
48263
48264 return array_values(array_unique(array_filter($namespaces)));
48265 }
48266
48267
48268
48269
48270
48271
48272
48273
48274
48275
48276 public function findNamespace($namespace)
48277 {
48278 $allNamespaces = $this->getNamespaces();
48279 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
48280 $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
48281
48282 if (empty($namespaces)) {
48283 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
48284
48285 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
48286 if (1 == count($alternatives)) {
48287 $message .= "\n\nDid you mean this?\n    ";
48288 } else {
48289 $message .= "\n\nDid you mean one of these?\n    ";
48290 }
48291
48292 $message .= implode("\n    ", $alternatives);
48293 }
48294
48295 throw new CommandNotFoundException($message, $alternatives);
48296 }
48297
48298 $exact = in_array($namespace, $namespaces, true);
48299 if (count($namespaces) > 1 && !$exact) {
48300 throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
48301 }
48302
48303 return $exact ? $namespace : reset($namespaces);
48304 }
48305
48306
48307
48308
48309
48310
48311
48312
48313
48314
48315
48316
48317
48318 public function find($name)
48319 {
48320 $this->init();
48321
48322 $allCommands = array_keys($this->commands);
48323 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
48324 $commands = preg_grep('{^'.$expr.'}', $allCommands);
48325
48326 if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
48327 if (false !== $pos = strrpos($name, ':')) {
48328
48329  $this->findNamespace(substr($name, 0, $pos));
48330 }
48331
48332 $message = sprintf('Command "%s" is not defined.', $name);
48333
48334 if ($alternatives = $this->findAlternatives($name, $allCommands)) {
48335 if (1 == count($alternatives)) {
48336 $message .= "\n\nDid you mean this?\n    ";
48337 } else {
48338 $message .= "\n\nDid you mean one of these?\n    ";
48339 }
48340 $message .= implode("\n    ", $alternatives);
48341 }
48342
48343 throw new CommandNotFoundException($message, $alternatives);
48344 }
48345
48346
48347  if (count($commands) > 1) {
48348 $commandList = $this->commands;
48349 $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
48350 $commandName = $commandList[$nameOrAlias]->getName();
48351
48352 return $commandName === $nameOrAlias || !in_array($commandName, $commands);
48353 });
48354 }
48355
48356 $exact = in_array($name, $commands, true);
48357 if (count($commands) > 1 && !$exact) {
48358 $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
48359
48360 throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
48361 }
48362
48363 return $this->get($exact ? $name : reset($commands));
48364 }
48365
48366
48367
48368
48369
48370
48371
48372
48373
48374
48375 public function all($namespace = null)
48376 {
48377 $this->init();
48378
48379 if (null === $namespace) {
48380 return $this->commands;
48381 }
48382
48383 $commands = array();
48384 foreach ($this->commands as $name => $command) {
48385 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
48386 $commands[$name] = $command;
48387 }
48388 }
48389
48390 return $commands;
48391 }
48392
48393
48394
48395
48396
48397
48398
48399
48400 public static function getAbbreviations($names)
48401 {
48402 $abbrevs = array();
48403 foreach ($names as $name) {
48404 for ($len = strlen($name); $len > 0; --$len) {
48405 $abbrev = substr($name, 0, $len);
48406 $abbrevs[$abbrev][] = $name;
48407 }
48408 }
48409
48410 return $abbrevs;
48411 }
48412
48413
48414
48415
48416
48417
48418
48419
48420
48421
48422
48423 public function asText($namespace = null, $raw = false)
48424 {
48425 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
48426
48427 $descriptor = new TextDescriptor();
48428 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
48429 $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
48430
48431 return $output->fetch();
48432 }
48433
48434
48435
48436
48437
48438
48439
48440
48441
48442
48443
48444 public function asXml($namespace = null, $asDom = false)
48445 {
48446 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
48447
48448 $descriptor = new XmlDescriptor();
48449
48450 if ($asDom) {
48451 return $descriptor->getApplicationDocument($this, $namespace);
48452 }
48453
48454 $output = new BufferedOutput();
48455 $descriptor->describe($output, $this, array('namespace' => $namespace));
48456
48457 return $output->fetch();
48458 }
48459
48460
48461
48462
48463 public function renderException($e, $output)
48464 {
48465 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
48466
48467 do {
48468 $title = sprintf('  [%s]  ', get_class($e));
48469
48470 $len = Helper::strlen($title);
48471
48472 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
48473
48474  if (defined('HHVM_VERSION') && $width > 1 << 31) {
48475 $width = 1 << 31;
48476 }
48477 $lines = array();
48478 foreach (preg_split('/\r?\n/', trim($e->getMessage())) as $line) {
48479 foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
48480
48481  $lineLength = Helper::strlen($line) + 4;
48482 $lines[] = array($line, $lineLength);
48483
48484 $len = max($lineLength, $len);
48485 }
48486 }
48487
48488 $messages = array();
48489 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
48490 $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
48491 foreach ($lines as $line) {
48492 $messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
48493 }
48494 $messages[] = $emptyLine;
48495 $messages[] = '';
48496
48497 $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
48498
48499 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
48500 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
48501
48502
48503  $trace = $e->getTrace();
48504 array_unshift($trace, array(
48505 'function' => '',
48506 'file' => null !== $e->getFile() ? $e->getFile() : 'n/a',
48507 'line' => null !== $e->getLine() ? $e->getLine() : 'n/a',
48508 'args' => array(),
48509 ));
48510
48511 for ($i = 0, $count = count($trace); $i < $count; ++$i) {
48512 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
48513 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
48514 $function = $trace[$i]['function'];
48515 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
48516 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
48517
48518 $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
48519 }
48520
48521 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
48522 }
48523 } while ($e = $e->getPrevious());
48524
48525 if (null !== $this->runningCommand) {
48526 $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
48527 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
48528 }
48529 }
48530
48531
48532
48533
48534
48535
48536 protected function getTerminalWidth()
48537 {
48538 $dimensions = $this->getTerminalDimensions();
48539
48540 return $dimensions[0];
48541 }
48542
48543
48544
48545
48546
48547
48548 protected function getTerminalHeight()
48549 {
48550 $dimensions = $this->getTerminalDimensions();
48551
48552 return $dimensions[1];
48553 }
48554
48555
48556
48557
48558
48559
48560 public function getTerminalDimensions()
48561 {
48562 if ($this->terminalDimensions) {
48563 return $this->terminalDimensions;
48564 }
48565
48566 if ('\\' === DIRECTORY_SEPARATOR) {
48567
48568  if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
48569 return array((int) $matches[1], (int) $matches[2]);
48570 }
48571
48572  if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
48573 return array((int) $matches[1], (int) $matches[2]);
48574 }
48575 }
48576
48577 if ($sttyString = $this->getSttyColumns()) {
48578
48579  if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
48580 return array((int) $matches[2], (int) $matches[1]);
48581 }
48582
48583  if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
48584 return array((int) $matches[2], (int) $matches[1]);
48585 }
48586 }
48587
48588 return array(null, null);
48589 }
48590
48591
48592
48593
48594
48595
48596
48597
48598
48599
48600
48601 public function setTerminalDimensions($width, $height)
48602 {
48603 $this->terminalDimensions = array($width, $height);
48604
48605 return $this;
48606 }
48607
48608
48609
48610
48611 protected function configureIO(InputInterface $input, OutputInterface $output)
48612 {
48613 if (true === $input->hasParameterOption(array('--ansi'))) {
48614 $output->setDecorated(true);
48615 } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
48616 $output->setDecorated(false);
48617 }
48618
48619 if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
48620 $input->setInteractive(false);
48621 } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
48622 $inputStream = $this->getHelperSet()->get('question')->getInputStream();
48623 if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
48624 $input->setInteractive(false);
48625 }
48626 }
48627
48628 if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
48629 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
48630 $input->setInteractive(false);
48631 } else {
48632 if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || 3 === $input->getParameterOption('--verbose')) {
48633 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
48634 } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || 2 === $input->getParameterOption('--verbose')) {
48635 $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
48636 } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
48637 $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
48638 }
48639 }
48640 }
48641
48642
48643
48644
48645
48646
48647
48648
48649
48650 protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
48651 {
48652 foreach ($command->getHelperSet() as $helper) {
48653 if ($helper instanceof InputAwareInterface) {
48654 $helper->setInput($input);
48655 }
48656 }
48657
48658 if (null === $this->dispatcher) {
48659 return $command->run($input, $output);
48660 }
48661
48662
48663  try {
48664 $command->mergeApplicationDefinition();
48665 $input->bind($command->getDefinition());
48666 } catch (ExceptionInterface $e) {
48667
48668  }
48669
48670 $event = new ConsoleCommandEvent($command, $input, $output);
48671 $e = null;
48672
48673 try {
48674 $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
48675
48676 if ($event->commandShouldRun()) {
48677 $exitCode = $command->run($input, $output);
48678 } else {
48679 $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
48680 }
48681 } catch (\Exception $e) {
48682 } catch (\Throwable $e) {
48683 }
48684 if (null !== $e) {
48685 $x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
48686 $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
48687 $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
48688
48689 if ($x !== $event->getException()) {
48690 $e = $event->getException();
48691 }
48692 $exitCode = $e->getCode();
48693 }
48694
48695 $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
48696 $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
48697
48698 if (null !== $e) {
48699 throw $e;
48700 }
48701
48702 return $event->getExitCode();
48703 }
48704
48705
48706
48707
48708
48709
48710 protected function getCommandName(InputInterface $input)
48711 {
48712 return $input->getFirstArgument();
48713 }
48714
48715
48716
48717
48718
48719
48720 protected function getDefaultInputDefinition()
48721 {
48722 return new InputDefinition(array(
48723 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
48724
48725 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
48726 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
48727 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'),
48728 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
48729 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
48730 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
48731 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
48732 ));
48733 }
48734
48735
48736
48737
48738
48739
48740 protected function getDefaultCommands()
48741 {
48742 return array(new HelpCommand(), new ListCommand());
48743 }
48744
48745
48746
48747
48748
48749
48750 protected function getDefaultHelperSet()
48751 {
48752 return new HelperSet(array(
48753 new FormatterHelper(),
48754 new DialogHelper(false),
48755 new ProgressHelper(false),
48756 new TableHelper(false),
48757 new DebugFormatterHelper(),
48758 new ProcessHelper(),
48759 new QuestionHelper(),
48760 ));
48761 }
48762
48763
48764
48765
48766
48767
48768 private function getSttyColumns()
48769 {
48770 if (!function_exists('proc_open')) {
48771 return;
48772 }
48773
48774 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
48775 $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
48776 if (is_resource($process)) {
48777 $info = stream_get_contents($pipes[1]);
48778 fclose($pipes[1]);
48779 fclose($pipes[2]);
48780 proc_close($process);
48781
48782 return $info;
48783 }
48784 }
48785
48786
48787
48788
48789
48790
48791 private function getConsoleMode()
48792 {
48793 if (!function_exists('proc_open')) {
48794 return;
48795 }
48796
48797 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
48798 $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
48799 if (is_resource($process)) {
48800 $info = stream_get_contents($pipes[1]);
48801 fclose($pipes[1]);
48802 fclose($pipes[2]);
48803 proc_close($process);
48804
48805 if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
48806 return $matches[2].'x'.$matches[1];
48807 }
48808 }
48809 }
48810
48811
48812
48813
48814
48815
48816
48817
48818 private function getAbbreviationSuggestions($abbrevs)
48819 {
48820 return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
48821 }
48822
48823
48824
48825
48826
48827
48828
48829
48830
48831
48832
48833 public function extractNamespace($name, $limit = null)
48834 {
48835 $parts = explode(':', $name);
48836 array_pop($parts);
48837
48838 return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
48839 }
48840
48841
48842
48843
48844
48845
48846
48847
48848
48849
48850 private function findAlternatives($name, $collection)
48851 {
48852 $threshold = 1e3;
48853 $alternatives = array();
48854
48855 $collectionParts = array();
48856 foreach ($collection as $item) {
48857 $collectionParts[$item] = explode(':', $item);
48858 }
48859
48860 foreach (explode(':', $name) as $i => $subname) {
48861 foreach ($collectionParts as $collectionName => $parts) {
48862 $exists = isset($alternatives[$collectionName]);
48863 if (!isset($parts[$i]) && $exists) {
48864 $alternatives[$collectionName] += $threshold;
48865 continue;
48866 } elseif (!isset($parts[$i])) {
48867 continue;
48868 }
48869
48870 $lev = levenshtein($subname, $parts[$i]);
48871 if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
48872 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
48873 } elseif ($exists) {
48874 $alternatives[$collectionName] += $threshold;
48875 }
48876 }
48877 }
48878
48879 foreach ($collection as $item) {
48880 $lev = levenshtein($name, $item);
48881 if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
48882 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
48883 }
48884 }
48885
48886 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
48887 asort($alternatives);
48888
48889 return array_keys($alternatives);
48890 }
48891
48892
48893
48894
48895
48896
48897 public function setDefaultCommand($commandName)
48898 {
48899 $this->defaultCommand = $commandName;
48900 }
48901
48902 private function splitStringByWidth($string, $width)
48903 {
48904
48905  
48906  
48907  if (false === $encoding = mb_detect_encoding($string, null, true)) {
48908 return str_split($string, $width);
48909 }
48910
48911 $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
48912 $lines = array();
48913 $line = '';
48914 foreach (preg_split('//u', $utf8String) as $char) {
48915
48916  if (mb_strwidth($line.$char, 'utf8') <= $width) {
48917 $line .= $char;
48918 continue;
48919 }
48920
48921  $lines[] = str_pad($line, $width);
48922 $line = $char;
48923 }
48924
48925 $lines[] = count($lines) ? str_pad($line, $width) : $line;
48926
48927 mb_convert_variables($encoding, 'utf8', $lines);
48928
48929 return $lines;
48930 }
48931
48932
48933
48934
48935
48936
48937
48938
48939 private function extractAllNamespaces($name)
48940 {
48941
48942  $parts = explode(':', $name, -1);
48943 $namespaces = array();
48944
48945 foreach ($parts as $part) {
48946 if (count($namespaces)) {
48947 $namespaces[] = end($namespaces).':'.$part;
48948 } else {
48949 $namespaces[] = $part;
48950 }
48951 }
48952
48953 return $namespaces;
48954 }
48955
48956 private function init()
48957 {
48958 if ($this->initialized) {
48959 return;
48960 }
48961 $this->initialized = true;
48962
48963 foreach ($this->getDefaultCommands() as $command) {
48964 $this->add($command);
48965 }
48966 }
48967 }
48968 <?php
48969
48970
48971
48972
48973
48974
48975
48976
48977
48978
48979 namespace Symfony\Component\Console\Command;
48980
48981 use Symfony\Component\Console\Descriptor\TextDescriptor;
48982 use Symfony\Component\Console\Descriptor\XmlDescriptor;
48983 use Symfony\Component\Console\Exception\ExceptionInterface;
48984 use Symfony\Component\Console\Input\InputDefinition;
48985 use Symfony\Component\Console\Input\InputOption;
48986 use Symfony\Component\Console\Input\InputArgument;
48987 use Symfony\Component\Console\Input\InputInterface;
48988 use Symfony\Component\Console\Output\BufferedOutput;
48989 use Symfony\Component\Console\Output\OutputInterface;
48990 use Symfony\Component\Console\Application;
48991 use Symfony\Component\Console\Helper\HelperSet;
48992 use Symfony\Component\Console\Exception\InvalidArgumentException;
48993 use Symfony\Component\Console\Exception\LogicException;
48994
48995
48996
48997
48998
48999
49000 class Command
49001 {
49002 private $application;
49003 private $name;
49004 private $processTitle;
49005 private $aliases = array();
49006 private $definition;
49007 private $help;
49008 private $description;
49009 private $ignoreValidationErrors = false;
49010 private $applicationDefinitionMerged = false;
49011 private $applicationDefinitionMergedWithArgs = false;
49012 private $code;
49013 private $synopsis = array();
49014 private $usages = array();
49015 private $helperSet;
49016
49017
49018
49019
49020
49021
49022 public function __construct($name = null)
49023 {
49024 $this->definition = new InputDefinition();
49025
49026 if (null !== $name) {
49027 $this->setName($name);
49028 }
49029
49030 $this->configure();
49031
49032 if (!$this->name) {
49033 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
49034 }
49035 }
49036
49037
49038
49039
49040
49041
49042 public function ignoreValidationErrors()
49043 {
49044 $this->ignoreValidationErrors = true;
49045 }
49046
49047 public function setApplication(Application $application = null)
49048 {
49049 $this->application = $application;
49050 if ($application) {
49051 $this->setHelperSet($application->getHelperSet());
49052 } else {
49053 $this->helperSet = null;
49054 }
49055 }
49056
49057 public function setHelperSet(HelperSet $helperSet)
49058 {
49059 $this->helperSet = $helperSet;
49060 }
49061
49062
49063
49064
49065
49066
49067 public function getHelperSet()
49068 {
49069 return $this->helperSet;
49070 }
49071
49072
49073
49074
49075
49076
49077 public function getApplication()
49078 {
49079 return $this->application;
49080 }
49081
49082
49083
49084
49085
49086
49087
49088
49089
49090 public function isEnabled()
49091 {
49092 return true;
49093 }
49094
49095
49096
49097
49098 protected function configure()
49099 {
49100 }
49101
49102
49103
49104
49105
49106
49107
49108
49109
49110
49111
49112
49113
49114
49115
49116 protected function execute(InputInterface $input, OutputInterface $output)
49117 {
49118 throw new LogicException('You must override the execute() method in the concrete command class.');
49119 }
49120
49121
49122
49123
49124
49125
49126
49127
49128 protected function interact(InputInterface $input, OutputInterface $output)
49129 {
49130 }
49131
49132
49133
49134
49135
49136
49137
49138 protected function initialize(InputInterface $input, OutputInterface $output)
49139 {
49140 }
49141
49142
49143
49144
49145
49146
49147
49148
49149
49150
49151
49152
49153
49154
49155
49156 public function run(InputInterface $input, OutputInterface $output)
49157 {
49158
49159  $this->getSynopsis(true);
49160 $this->getSynopsis(false);
49161
49162
49163  $this->mergeApplicationDefinition();
49164
49165
49166  try {
49167 $input->bind($this->definition);
49168 } catch (ExceptionInterface $e) {
49169 if (!$this->ignoreValidationErrors) {
49170 throw $e;
49171 }
49172 }
49173
49174 $this->initialize($input, $output);
49175
49176 if (null !== $this->processTitle) {
49177 if (function_exists('cli_set_process_title')) {
49178 if (false === @cli_set_process_title($this->processTitle)) {
49179 if ('Darwin' === PHP_OS) {
49180 $output->writeln('<comment>Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.</comment>');
49181 } else {
49182 $error = error_get_last();
49183 trigger_error($error['message'], E_USER_WARNING);
49184 }
49185 }
49186 } elseif (function_exists('setproctitle')) {
49187 setproctitle($this->processTitle);
49188 } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
49189 $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
49190 }
49191 }
49192
49193 if ($input->isInteractive()) {
49194 $this->interact($input, $output);
49195 }
49196
49197
49198  
49199  
49200  if ($input->hasArgument('command') && null === $input->getArgument('command')) {
49201 $input->setArgument('command', $this->getName());
49202 }
49203
49204 $input->validate();
49205
49206 if ($this->code) {
49207 $statusCode = call_user_func($this->code, $input, $output);
49208 } else {
49209 $statusCode = $this->execute($input, $output);
49210 }
49211
49212 return is_numeric($statusCode) ? (int) $statusCode : 0;
49213 }
49214
49215
49216
49217
49218
49219
49220
49221
49222
49223
49224
49225
49226
49227
49228
49229 public function setCode($code)
49230 {
49231 if (!is_callable($code)) {
49232 throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
49233 }
49234
49235 if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
49236 $r = new \ReflectionFunction($code);
49237 if (null === $r->getClosureThis()) {
49238 if (PHP_VERSION_ID < 70000) {
49239
49240  
49241  
49242  
49243  $code = @\Closure::bind($code, $this);
49244 } else {
49245 $code = \Closure::bind($code, $this);
49246 }
49247 }
49248 }
49249
49250 $this->code = $code;
49251
49252 return $this;
49253 }
49254
49255
49256
49257
49258
49259
49260
49261
49262 public function mergeApplicationDefinition($mergeArgs = true)
49263 {
49264 if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
49265 return;
49266 }
49267
49268 $this->definition->addOptions($this->application->getDefinition()->getOptions());
49269
49270 if ($mergeArgs) {
49271 $currentArguments = $this->definition->getArguments();
49272 $this->definition->setArguments($this->application->getDefinition()->getArguments());
49273 $this->definition->addArguments($currentArguments);
49274 }
49275
49276 $this->applicationDefinitionMerged = true;
49277 if ($mergeArgs) {
49278 $this->applicationDefinitionMergedWithArgs = true;
49279 }
49280 }
49281
49282
49283
49284
49285
49286
49287
49288
49289 public function setDefinition($definition)
49290 {
49291 if ($definition instanceof InputDefinition) {
49292 $this->definition = $definition;
49293 } else {
49294 $this->definition->setDefinition($definition);
49295 }
49296
49297 $this->applicationDefinitionMerged = false;
49298
49299 return $this;
49300 }
49301
49302
49303
49304
49305
49306
49307 public function getDefinition()
49308 {
49309 return $this->definition;
49310 }
49311
49312
49313
49314
49315
49316
49317
49318
49319
49320
49321
49322 public function getNativeDefinition()
49323 {
49324 return $this->getDefinition();
49325 }
49326
49327
49328
49329
49330
49331
49332
49333
49334
49335
49336
49337 public function addArgument($name, $mode = null, $description = '', $default = null)
49338 {
49339 $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
49340
49341 return $this;
49342 }
49343
49344
49345
49346
49347
49348
49349
49350
49351
49352
49353
49354
49355 public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
49356 {
49357 $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
49358
49359 return $this;
49360 }
49361
49362
49363
49364
49365
49366
49367
49368
49369
49370
49371
49372
49373
49374
49375
49376 public function setName($name)
49377 {
49378 $this->validateName($name);
49379
49380 $this->name = $name;
49381
49382 return $this;
49383 }
49384
49385
49386
49387
49388
49389
49390
49391
49392
49393
49394
49395
49396
49397 public function setProcessTitle($title)
49398 {
49399 $this->processTitle = $title;
49400
49401 return $this;
49402 }
49403
49404
49405
49406
49407
49408
49409 public function getName()
49410 {
49411 return $this->name;
49412 }
49413
49414
49415
49416
49417
49418
49419
49420
49421 public function setDescription($description)
49422 {
49423 $this->description = $description;
49424
49425 return $this;
49426 }
49427
49428
49429
49430
49431
49432
49433 public function getDescription()
49434 {
49435 return $this->description;
49436 }
49437
49438
49439
49440
49441
49442
49443
49444
49445 public function setHelp($help)
49446 {
49447 $this->help = $help;
49448
49449 return $this;
49450 }
49451
49452
49453
49454
49455
49456
49457 public function getHelp()
49458 {
49459 return $this->help;
49460 }
49461
49462
49463
49464
49465
49466
49467
49468 public function getProcessedHelp()
49469 {
49470 $name = $this->name;
49471
49472 $placeholders = array(
49473 '%command.name%',
49474 '%command.full_name%',
49475 );
49476 $replacements = array(
49477 $name,
49478 $_SERVER['PHP_SELF'].' '.$name,
49479 );
49480
49481 return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
49482 }
49483
49484
49485
49486
49487
49488
49489
49490
49491
49492
49493 public function setAliases($aliases)
49494 {
49495 if (!is_array($aliases) && !$aliases instanceof \Traversable) {
49496 throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
49497 }
49498
49499 foreach ($aliases as $alias) {
49500 $this->validateName($alias);
49501 }
49502
49503 $this->aliases = $aliases;
49504
49505 return $this;
49506 }
49507
49508
49509
49510
49511
49512
49513 public function getAliases()
49514 {
49515 return $this->aliases;
49516 }
49517
49518
49519
49520
49521
49522
49523
49524
49525 public function getSynopsis($short = false)
49526 {
49527 $key = $short ? 'short' : 'long';
49528
49529 if (!isset($this->synopsis[$key])) {
49530 $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
49531 }
49532
49533 return $this->synopsis[$key];
49534 }
49535
49536
49537
49538
49539
49540
49541
49542
49543 public function addUsage($usage)
49544 {
49545 if (0 !== strpos($usage, $this->name)) {
49546 $usage = sprintf('%s %s', $this->name, $usage);
49547 }
49548
49549 $this->usages[] = $usage;
49550
49551 return $this;
49552 }
49553
49554
49555
49556
49557
49558
49559 public function getUsages()
49560 {
49561 return $this->usages;
49562 }
49563
49564
49565
49566
49567
49568
49569
49570
49571
49572
49573
49574 public function getHelper($name)
49575 {
49576 if (null === $this->helperSet) {
49577 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));
49578 }
49579
49580 return $this->helperSet->get($name);
49581 }
49582
49583
49584
49585
49586
49587
49588
49589
49590 public function asText()
49591 {
49592 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
49593
49594 $descriptor = new TextDescriptor();
49595 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
49596 $descriptor->describe($output, $this, array('raw_output' => true));
49597
49598 return $output->fetch();
49599 }
49600
49601
49602
49603
49604
49605
49606
49607
49608
49609
49610 public function asXml($asDom = false)
49611 {
49612 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
49613
49614 $descriptor = new XmlDescriptor();
49615
49616 if ($asDom) {
49617 return $descriptor->getCommandDocument($this);
49618 }
49619
49620 $output = new BufferedOutput();
49621 $descriptor->describe($output, $this);
49622
49623 return $output->fetch();
49624 }
49625
49626
49627
49628
49629
49630
49631
49632
49633
49634
49635 private function validateName($name)
49636 {
49637 if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
49638 throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
49639 }
49640 }
49641 }
49642 <?php
49643
49644
49645
49646
49647
49648
49649
49650
49651
49652
49653 namespace Symfony\Component\Console\Command;
49654
49655 use Symfony\Component\Console\Helper\DescriptorHelper;
49656 use Symfony\Component\Console\Input\InputArgument;
49657 use Symfony\Component\Console\Input\InputOption;
49658 use Symfony\Component\Console\Input\InputInterface;
49659 use Symfony\Component\Console\Output\OutputInterface;
49660
49661
49662
49663
49664
49665
49666 class HelpCommand extends Command
49667 {
49668 private $command;
49669
49670
49671
49672
49673 protected function configure()
49674 {
49675 $this->ignoreValidationErrors();
49676
49677 $this
49678 ->setName('help')
49679 ->setDefinition(array(
49680 new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
49681 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
49682 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
49683 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
49684 ))
49685 ->setDescription('Displays help for a command')
49686 ->setHelp(<<<'EOF'
49687 The <info>%command.name%</info> command displays help for a given command:
49688
49689   <info>php %command.full_name% list</info>
49690
49691 You can also output the help in other formats by using the <comment>--format</comment> option:
49692
49693   <info>php %command.full_name% --format=xml list</info>
49694
49695 To display the list of available commands, please use the <info>list</info> command.
49696 EOF
49697 )
49698 ;
49699 }
49700
49701 public function setCommand(Command $command)
49702 {
49703 $this->command = $command;
49704 }
49705
49706
49707
49708
49709 protected function execute(InputInterface $input, OutputInterface $output)
49710 {
49711 if (null === $this->command) {
49712 $this->command = $this->getApplication()->find($input->getArgument('command_name'));
49713 }
49714
49715 if ($input->getOption('xml')) {
49716 @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);
49717
49718 $input->setOption('format', 'xml');
49719 }
49720
49721 $helper = new DescriptorHelper();
49722 $helper->describe($output, $this->command, array(
49723 'format' => $input->getOption('format'),
49724 'raw_text' => $input->getOption('raw'),
49725 ));
49726
49727 $this->command = null;
49728 }
49729 }
49730 <?php
49731
49732
49733
49734
49735
49736
49737
49738
49739
49740
49741 namespace Symfony\Component\Console\Command;
49742
49743 use Symfony\Component\Console\Helper\DescriptorHelper;
49744 use Symfony\Component\Console\Input\InputArgument;
49745 use Symfony\Component\Console\Input\InputOption;
49746 use Symfony\Component\Console\Input\InputInterface;
49747 use Symfony\Component\Console\Output\OutputInterface;
49748 use Symfony\Component\Console\Input\InputDefinition;
49749
49750
49751
49752
49753
49754
49755 class ListCommand extends Command
49756 {
49757
49758
49759
49760 protected function configure()
49761 {
49762 $this
49763 ->setName('list')
49764 ->setDefinition($this->createDefinition())
49765 ->setDescription('Lists commands')
49766 ->setHelp(<<<'EOF'
49767 The <info>%command.name%</info> command lists all commands:
49768
49769   <info>php %command.full_name%</info>
49770
49771 You can also display the commands for a specific namespace:
49772
49773   <info>php %command.full_name% test</info>
49774
49775 You can also output the information in other formats by using the <comment>--format</comment> option:
49776
49777   <info>php %command.full_name% --format=xml</info>
49778
49779 It's also possible to get raw list of commands (useful for embedding command runner):
49780
49781   <info>php %command.full_name% --raw</info>
49782 EOF
49783 )
49784 ;
49785 }
49786
49787
49788
49789
49790 public function getNativeDefinition()
49791 {
49792 return $this->createDefinition();
49793 }
49794
49795
49796
49797
49798 protected function execute(InputInterface $input, OutputInterface $output)
49799 {
49800 if ($input->getOption('xml')) {
49801 @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);
49802
49803 $input->setOption('format', 'xml');
49804 }
49805
49806 $helper = new DescriptorHelper();
49807 $helper->describe($output, $this->getApplication(), array(
49808 'format' => $input->getOption('format'),
49809 'raw_text' => $input->getOption('raw'),
49810 'namespace' => $input->getArgument('namespace'),
49811 ));
49812 }
49813
49814
49815
49816
49817 private function createDefinition()
49818 {
49819 return new InputDefinition(array(
49820 new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
49821 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
49822 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
49823 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
49824 ));
49825 }
49826 }
49827 <?php
49828
49829
49830
49831
49832
49833
49834
49835
49836
49837
49838 namespace Symfony\Component\Console;
49839
49840
49841
49842
49843
49844
49845 final class ConsoleEvents
49846 {
49847
49848
49849
49850
49851
49852
49853
49854
49855
49856
49857 const COMMAND = 'console.command';
49858
49859
49860
49861
49862
49863
49864
49865
49866
49867
49868 const TERMINATE = 'console.terminate';
49869
49870
49871
49872
49873
49874
49875
49876
49877
49878
49879
49880 const EXCEPTION = 'console.exception';
49881 }
49882 <?php
49883
49884
49885
49886
49887
49888
49889
49890
49891
49892
49893 namespace Symfony\Component\Console\Descriptor;
49894
49895 use Symfony\Component\Console\Application;
49896 use Symfony\Component\Console\Command\Command;
49897 use Symfony\Component\Console\Exception\CommandNotFoundException;
49898
49899
49900
49901
49902
49903
49904 class ApplicationDescription
49905 {
49906 const GLOBAL_NAMESPACE = '_global';
49907
49908 private $application;
49909 private $namespace;
49910
49911
49912
49913
49914 private $namespaces;
49915
49916
49917
49918
49919 private $commands;
49920
49921
49922
49923
49924 private $aliases;
49925
49926 public function __construct(Application $application, $namespace = null)
49927 {
49928 $this->application = $application;
49929 $this->namespace = $namespace;
49930 }
49931
49932
49933
49934
49935 public function getNamespaces()
49936 {
49937 if (null === $this->namespaces) {
49938 $this->inspectApplication();
49939 }
49940
49941 return $this->namespaces;
49942 }
49943
49944
49945
49946
49947 public function getCommands()
49948 {
49949 if (null === $this->commands) {
49950 $this->inspectApplication();
49951 }
49952
49953 return $this->commands;
49954 }
49955
49956
49957
49958
49959
49960
49961
49962
49963 public function getCommand($name)
49964 {
49965 if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
49966 throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
49967 }
49968
49969 return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
49970 }
49971
49972 private function inspectApplication()
49973 {
49974 $this->commands = array();
49975 $this->namespaces = array();
49976
49977 $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
49978 foreach ($this->sortCommands($all) as $namespace => $commands) {
49979 $names = array();
49980
49981
49982 foreach ($commands as $name => $command) {
49983 if (!$command->getName()) {
49984 continue;
49985 }
49986
49987 if ($command->getName() === $name) {
49988 $this->commands[$name] = $command;
49989 } else {
49990 $this->aliases[$name] = $command;
49991 }
49992
49993 $names[] = $name;
49994 }
49995
49996 $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
49997 }
49998 }
49999
50000
50001
50002
50003 private function sortCommands(array $commands)
50004 {
50005 $namespacedCommands = array();
50006 $globalCommands = array();
50007 foreach ($commands as $name => $command) {
50008 $key = $this->application->extractNamespace($name, 1);
50009 if (!$key) {
50010 $globalCommands['_global'][$name] = $command;
50011 } else {
50012 $namespacedCommands[$key][$name] = $command;
50013 }
50014 }
50015 ksort($namespacedCommands);
50016 $namespacedCommands = array_merge($globalCommands, $namespacedCommands);
50017
50018 foreach ($namespacedCommands as &$commandsSet) {
50019 ksort($commandsSet);
50020 }
50021
50022  unset($commandsSet);
50023
50024 return $namespacedCommands;
50025 }
50026 }
50027 <?php
50028
50029
50030
50031
50032
50033
50034
50035
50036
50037
50038 namespace Symfony\Component\Console\Descriptor;
50039
50040 use Symfony\Component\Console\Application;
50041 use Symfony\Component\Console\Command\Command;
50042 use Symfony\Component\Console\Input\InputArgument;
50043 use Symfony\Component\Console\Input\InputDefinition;
50044 use Symfony\Component\Console\Input\InputOption;
50045 use Symfony\Component\Console\Output\OutputInterface;
50046 use Symfony\Component\Console\Exception\InvalidArgumentException;
50047
50048
50049
50050
50051
50052
50053 abstract class Descriptor implements DescriptorInterface
50054 {
50055
50056
50057
50058 private $output;
50059
50060
50061
50062
50063 public function describe(OutputInterface $output, $object, array $options = array())
50064 {
50065 $this->output = $output;
50066
50067 switch (true) {
50068 case $object instanceof InputArgument:
50069 $this->describeInputArgument($object, $options);
50070 break;
50071 case $object instanceof InputOption:
50072 $this->describeInputOption($object, $options);
50073 break;
50074 case $object instanceof InputDefinition:
50075 $this->describeInputDefinition($object, $options);
50076 break;
50077 case $object instanceof Command:
50078 $this->describeCommand($object, $options);
50079 break;
50080 case $object instanceof Application:
50081 $this->describeApplication($object, $options);
50082 break;
50083 default:
50084 throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
50085 }
50086 }
50087
50088
50089
50090
50091
50092
50093
50094 protected function write($content, $decorated = false)
50095 {
50096 $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
50097 }
50098
50099
50100
50101
50102
50103
50104 abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
50105
50106
50107
50108
50109
50110
50111 abstract protected function describeInputOption(InputOption $option, array $options = array());
50112
50113
50114
50115
50116
50117
50118 abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
50119
50120
50121
50122
50123
50124
50125 abstract protected function describeCommand(Command $command, array $options = array());
50126
50127
50128
50129
50130
50131
50132 abstract protected function describeApplication(Application $application, array $options = array());
50133 }
50134 <?php
50135
50136
50137
50138
50139
50140
50141
50142
50143
50144
50145 namespace Symfony\Component\Console\Descriptor;
50146
50147 use Symfony\Component\Console\Output\OutputInterface;
50148
50149
50150
50151
50152
50153
50154 interface DescriptorInterface
50155 {
50156
50157
50158
50159
50160
50161
50162
50163 public function describe(OutputInterface $output, $object, array $options = array());
50164 }
50165 <?php
50166
50167
50168
50169
50170
50171
50172
50173
50174
50175
50176 namespace Symfony\Component\Console\Descriptor;
50177
50178 use Symfony\Component\Console\Application;
50179 use Symfony\Component\Console\Command\Command;
50180 use Symfony\Component\Console\Input\InputArgument;
50181 use Symfony\Component\Console\Input\InputDefinition;
50182 use Symfony\Component\Console\Input\InputOption;
50183
50184
50185
50186
50187
50188
50189
50190
50191 class JsonDescriptor extends Descriptor
50192 {
50193
50194
50195
50196 protected function describeInputArgument(InputArgument $argument, array $options = array())
50197 {
50198 $this->writeData($this->getInputArgumentData($argument), $options);
50199 }
50200
50201
50202
50203
50204 protected function describeInputOption(InputOption $option, array $options = array())
50205 {
50206 $this->writeData($this->getInputOptionData($option), $options);
50207 }
50208
50209
50210
50211
50212 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
50213 {
50214 $this->writeData($this->getInputDefinitionData($definition), $options);
50215 }
50216
50217
50218
50219
50220 protected function describeCommand(Command $command, array $options = array())
50221 {
50222 $this->writeData($this->getCommandData($command), $options);
50223 }
50224
50225
50226
50227
50228 protected function describeApplication(Application $application, array $options = array())
50229 {
50230 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
50231 $description = new ApplicationDescription($application, $describedNamespace);
50232 $commands = array();
50233
50234 foreach ($description->getCommands() as $command) {
50235 $commands[] = $this->getCommandData($command);
50236 }
50237
50238 $data = $describedNamespace
50239 ? array('commands' => $commands, 'namespace' => $describedNamespace)
50240 : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
50241
50242 $this->writeData($data, $options);
50243 }
50244
50245
50246
50247
50248
50249
50250 private function writeData(array $data, array $options)
50251 {
50252 $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
50253 }
50254
50255
50256
50257
50258 private function getInputArgumentData(InputArgument $argument)
50259 {
50260 return array(
50261 'name' => $argument->getName(),
50262 'is_required' => $argument->isRequired(),
50263 'is_array' => $argument->isArray(),
50264 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
50265 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
50266 );
50267 }
50268
50269
50270
50271
50272 private function getInputOptionData(InputOption $option)
50273 {
50274 return array(
50275 'name' => '--'.$option->getName(),
50276 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
50277 'accept_value' => $option->acceptValue(),
50278 'is_value_required' => $option->isValueRequired(),
50279 'is_multiple' => $option->isArray(),
50280 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
50281 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
50282 );
50283 }
50284
50285
50286
50287
50288 private function getInputDefinitionData(InputDefinition $definition)
50289 {
50290 $inputArguments = array();
50291 foreach ($definition->getArguments() as $name => $argument) {
50292 $inputArguments[$name] = $this->getInputArgumentData($argument);
50293 }
50294
50295 $inputOptions = array();
50296 foreach ($definition->getOptions() as $name => $option) {
50297 $inputOptions[$name] = $this->getInputOptionData($option);
50298 }
50299
50300 return array('arguments' => $inputArguments, 'options' => $inputOptions);
50301 }
50302
50303
50304
50305
50306 private function getCommandData(Command $command)
50307 {
50308 $command->getSynopsis();
50309 $command->mergeApplicationDefinition(false);
50310
50311 return array(
50312 'name' => $command->getName(),
50313 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
50314 'description' => $command->getDescription(),
50315 'help' => $command->getProcessedHelp(),
50316 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
50317 );
50318 }
50319 }
50320 <?php
50321
50322
50323
50324
50325
50326
50327
50328
50329
50330
50331 namespace Symfony\Component\Console\Descriptor;
50332
50333 use Symfony\Component\Console\Application;
50334 use Symfony\Component\Console\Command\Command;
50335 use Symfony\Component\Console\Helper\Helper;
50336 use Symfony\Component\Console\Input\InputArgument;
50337 use Symfony\Component\Console\Input\InputDefinition;
50338 use Symfony\Component\Console\Input\InputOption;
50339
50340
50341
50342
50343
50344
50345
50346
50347 class MarkdownDescriptor extends Descriptor
50348 {
50349
50350
50351
50352 protected function describeInputArgument(InputArgument $argument, array $options = array())
50353 {
50354 $this->write(
50355 '**'.$argument->getName().':**'."\n\n"
50356 .'* Name: '.($argument->getName() ?: '<none>')."\n"
50357 .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
50358 .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
50359 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $argument->getDescription() ?: '<none>')."\n"
50360 .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
50361 );
50362 }
50363
50364
50365
50366
50367 protected function describeInputOption(InputOption $option, array $options = array())
50368 {
50369 $this->write(
50370 '**'.$option->getName().':**'."\n\n"
50371 .'* Name: `--'.$option->getName().'`'."\n"
50372 .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '<none>')."\n"
50373 .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
50374 .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
50375 .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
50376 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $option->getDescription() ?: '<none>')."\n"
50377 .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
50378 );
50379 }
50380
50381
50382
50383
50384 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
50385 {
50386 if ($showArguments = count($definition->getArguments()) > 0) {
50387 $this->write('### Arguments:');
50388 foreach ($definition->getArguments() as $argument) {
50389 $this->write("\n\n");
50390 $this->write($this->describeInputArgument($argument));
50391 }
50392 }
50393
50394 if (count($definition->getOptions()) > 0) {
50395 if ($showArguments) {
50396 $this->write("\n\n");
50397 }
50398
50399 $this->write('### Options:');
50400 foreach ($definition->getOptions() as $option) {
50401 $this->write("\n\n");
50402 $this->write($this->describeInputOption($option));
50403 }
50404 }
50405 }
50406
50407
50408
50409
50410 protected function describeCommand(Command $command, array $options = array())
50411 {
50412 $command->getSynopsis();
50413 $command->mergeApplicationDefinition(false);
50414
50415 $this->write(
50416 $command->getName()."\n"
50417 .str_repeat('-', Helper::strlen($command->getName()))."\n\n"
50418 .'* Description: '.($command->getDescription() ?: '<none>')."\n"
50419 .'* Usage:'."\n\n"
50420 .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
50421 return $carry.'  * `'.$usage.'`'."\n";
50422 })
50423 );
50424
50425 if ($help = $command->getProcessedHelp()) {
50426 $this->write("\n");
50427 $this->write($help);
50428 }
50429
50430 if ($command->getNativeDefinition()) {
50431 $this->write("\n\n");
50432 $this->describeInputDefinition($command->getNativeDefinition());
50433 }
50434 }
50435
50436
50437
50438
50439 protected function describeApplication(Application $application, array $options = array())
50440 {
50441 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
50442 $description = new ApplicationDescription($application, $describedNamespace);
50443
50444 $this->write($application->getName()."\n".str_repeat('=', Helper::strlen($application->getName())));
50445
50446 foreach ($description->getNamespaces() as $namespace) {
50447 if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
50448 $this->write("\n\n");
50449 $this->write('**'.$namespace['id'].':**');
50450 }
50451
50452 $this->write("\n\n");
50453 $this->write(implode("\n", array_map(function ($commandName) {
50454 return '* '.$commandName;
50455 }, $namespace['commands'])));
50456 }
50457
50458 foreach ($description->getCommands() as $command) {
50459 $this->write("\n\n");
50460 $this->write($this->describeCommand($command));
50461 }
50462 }
50463 }
50464 <?php
50465
50466
50467
50468
50469
50470
50471
50472
50473
50474
50475 namespace Symfony\Component\Console\Descriptor;
50476
50477 use Symfony\Component\Console\Application;
50478 use Symfony\Component\Console\Command\Command;
50479 use Symfony\Component\Console\Formatter\OutputFormatter;
50480 use Symfony\Component\Console\Helper\Helper;
50481 use Symfony\Component\Console\Input\InputArgument;
50482 use Symfony\Component\Console\Input\InputDefinition;
50483 use Symfony\Component\Console\Input\InputOption;
50484
50485
50486
50487
50488
50489
50490
50491
50492 class TextDescriptor extends Descriptor
50493 {
50494
50495
50496
50497 protected function describeInputArgument(InputArgument $argument, array $options = array())
50498 {
50499 if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
50500 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
50501 } else {
50502 $default = '';
50503 }
50504
50505 $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
50506 $spacingWidth = $totalWidth - strlen($argument->getName());
50507
50508 $this->writeText(sprintf('  <info>%s</info>  %s%s%s',
50509 $argument->getName(),
50510 str_repeat(' ', $spacingWidth),
50511
50512  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
50513 $default
50514 ), $options);
50515 }
50516
50517
50518
50519
50520 protected function describeInputOption(InputOption $option, array $options = array())
50521 {
50522 if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
50523 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
50524 } else {
50525 $default = '';
50526 }
50527
50528 $value = '';
50529 if ($option->acceptValue()) {
50530 $value = '='.strtoupper($option->getName());
50531
50532 if ($option->isValueOptional()) {
50533 $value = '['.$value.']';
50534 }
50535 }
50536
50537 $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
50538 $synopsis = sprintf('%s%s',
50539 $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
50540 sprintf('--%s%s', $option->getName(), $value)
50541 );
50542
50543 $spacingWidth = $totalWidth - Helper::strlen($synopsis);
50544
50545 $this->writeText(sprintf('  <info>%s</info>  %s%s%s%s',
50546 $synopsis,
50547 str_repeat(' ', $spacingWidth),
50548
50549  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
50550 $default,
50551 $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
50552 ), $options);
50553 }
50554
50555
50556
50557
50558 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
50559 {
50560 $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
50561 foreach ($definition->getArguments() as $argument) {
50562 $totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
50563 }
50564
50565 if ($definition->getArguments()) {
50566 $this->writeText('<comment>Arguments:</comment>', $options);
50567 $this->writeText("\n");
50568 foreach ($definition->getArguments() as $argument) {
50569 $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
50570 $this->writeText("\n");
50571 }
50572 }
50573
50574 if ($definition->getArguments() && $definition->getOptions()) {
50575 $this->writeText("\n");
50576 }
50577
50578 if ($definition->getOptions()) {
50579 $laterOptions = array();
50580
50581 $this->writeText('<comment>Options:</comment>', $options);
50582 foreach ($definition->getOptions() as $option) {
50583 if (strlen($option->getShortcut()) > 1) {
50584 $laterOptions[] = $option;
50585 continue;
50586 }
50587 $this->writeText("\n");
50588 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
50589 }
50590 foreach ($laterOptions as $option) {
50591 $this->writeText("\n");
50592 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
50593 }
50594 }
50595 }
50596
50597
50598
50599
50600 protected function describeCommand(Command $command, array $options = array())
50601 {
50602 $command->getSynopsis(true);
50603 $command->getSynopsis(false);
50604 $command->mergeApplicationDefinition(false);
50605
50606 $this->writeText('<comment>Usage:</comment>', $options);
50607 foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
50608 $this->writeText("\n");
50609 $this->writeText('  '.OutputFormatter::escape($usage), $options);
50610 }
50611 $this->writeText("\n");
50612
50613 $definition = $command->getNativeDefinition();
50614 if ($definition->getOptions() || $definition->getArguments()) {
50615 $this->writeText("\n");
50616 $this->describeInputDefinition($definition, $options);
50617 $this->writeText("\n");
50618 }
50619
50620 if ($help = $command->getProcessedHelp()) {
50621 $this->writeText("\n");
50622 $this->writeText('<comment>Help:</comment>', $options);
50623 $this->writeText("\n");
50624 $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
50625 $this->writeText("\n");
50626 }
50627 }
50628
50629
50630
50631
50632 protected function describeApplication(Application $application, array $options = array())
50633 {
50634 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
50635 $description = new ApplicationDescription($application, $describedNamespace);
50636
50637 if (isset($options['raw_text']) && $options['raw_text']) {
50638 $width = $this->getColumnWidth($description->getCommands());
50639
50640 foreach ($description->getCommands() as $command) {
50641 $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
50642 $this->writeText("\n");
50643 }
50644 } else {
50645 if ('' != $help = $application->getHelp()) {
50646 $this->writeText("$help\n\n", $options);
50647 }
50648
50649 $this->writeText("<comment>Usage:</comment>\n", $options);
50650 $this->writeText("  command [options] [arguments]\n\n", $options);
50651
50652 $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
50653
50654 $this->writeText("\n");
50655 $this->writeText("\n");
50656
50657 $width = $this->getColumnWidth($description->getCommands());
50658
50659 if ($describedNamespace) {
50660 $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
50661 } else {
50662 $this->writeText('<comment>Available commands:</comment>', $options);
50663 }
50664
50665
50666  foreach ($description->getNamespaces() as $namespace) {
50667 if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
50668 $this->writeText("\n");
50669 $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
50670 }
50671
50672 foreach ($namespace['commands'] as $name) {
50673 $this->writeText("\n");
50674 $spacingWidth = $width - Helper::strlen($name);
50675 $this->writeText(sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
50676 }
50677 }
50678
50679 $this->writeText("\n");
50680 }
50681 }
50682
50683
50684
50685
50686 private function writeText($content, array $options = array())
50687 {
50688 $this->write(
50689 isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
50690 isset($options['raw_output']) ? !$options['raw_output'] : true
50691 );
50692 }
50693
50694
50695
50696
50697
50698
50699
50700
50701 private function formatDefaultValue($default)
50702 {
50703 if (INF === $default) {
50704 return 'INF';
50705 }
50706
50707 if (is_string($default)) {
50708 $default = OutputFormatter::escape($default);
50709 } elseif (is_array($default)) {
50710 foreach ($default as $key => $value) {
50711 if (is_string($value)) {
50712 $default[$key] = OutputFormatter::escape($value);
50713 }
50714 }
50715 }
50716
50717 if (\PHP_VERSION_ID < 50400) {
50718 return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
50719 }
50720
50721 return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
50722 }
50723
50724
50725
50726
50727
50728
50729 private function getColumnWidth(array $commands)
50730 {
50731 $widths = array();
50732
50733 foreach ($commands as $command) {
50734 $widths[] = Helper::strlen($command->getName());
50735 foreach ($command->getAliases() as $alias) {
50736 $widths[] = Helper::strlen($alias);
50737 }
50738 }
50739
50740 return max($widths) + 2;
50741 }
50742
50743
50744
50745
50746
50747
50748 private function calculateTotalWidthForOptions(array $options)
50749 {
50750 $totalWidth = 0;
50751 foreach ($options as $option) {
50752
50753  $nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
50754
50755 if ($option->acceptValue()) {
50756 $valueLength = 1 + Helper::strlen($option->getName()); 
50757  $valueLength += $option->isValueOptional() ? 2 : 0; 
50758
50759 $nameLength += $valueLength;
50760 }
50761 $totalWidth = max($totalWidth, $nameLength);
50762 }
50763
50764 return $totalWidth;
50765 }
50766 }
50767 <?php
50768
50769
50770
50771
50772
50773
50774
50775
50776
50777
50778 namespace Symfony\Component\Console\Descriptor;
50779
50780 use Symfony\Component\Console\Application;
50781 use Symfony\Component\Console\Command\Command;
50782 use Symfony\Component\Console\Input\InputArgument;
50783 use Symfony\Component\Console\Input\InputDefinition;
50784 use Symfony\Component\Console\Input\InputOption;
50785
50786
50787
50788
50789
50790
50791
50792
50793 class XmlDescriptor extends Descriptor
50794 {
50795
50796
50797
50798 public function getInputDefinitionDocument(InputDefinition $definition)
50799 {
50800 $dom = new \DOMDocument('1.0', 'UTF-8');
50801 $dom->appendChild($definitionXML = $dom->createElement('definition'));
50802
50803 $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
50804 foreach ($definition->getArguments() as $argument) {
50805 $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
50806 }
50807
50808 $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
50809 foreach ($definition->getOptions() as $option) {
50810 $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
50811 }
50812
50813 return $dom;
50814 }
50815
50816
50817
50818
50819 public function getCommandDocument(Command $command)
50820 {
50821 $dom = new \DOMDocument('1.0', 'UTF-8');
50822 $dom->appendChild($commandXML = $dom->createElement('command'));
50823
50824 $command->getSynopsis();
50825 $command->mergeApplicationDefinition(false);
50826
50827 $commandXML->setAttribute('id', $command->getName());
50828 $commandXML->setAttribute('name', $command->getName());
50829
50830 $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
50831
50832 foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
50833 $usagesXML->appendChild($dom->createElement('usage', $usage));
50834 }
50835
50836 $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
50837 $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
50838
50839 $commandXML->appendChild($helpXML = $dom->createElement('help'));
50840 $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
50841
50842 $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
50843 $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
50844
50845 return $dom;
50846 }
50847
50848
50849
50850
50851
50852
50853
50854 public function getApplicationDocument(Application $application, $namespace = null)
50855 {
50856 $dom = new \DOMDocument('1.0', 'UTF-8');
50857 $dom->appendChild($rootXml = $dom->createElement('symfony'));
50858
50859 if ('UNKNOWN' !== $application->getName()) {
50860 $rootXml->setAttribute('name', $application->getName());
50861 if ('UNKNOWN' !== $application->getVersion()) {
50862 $rootXml->setAttribute('version', $application->getVersion());
50863 }
50864 }
50865
50866 $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
50867
50868 $description = new ApplicationDescription($application, $namespace);
50869
50870 if ($namespace) {
50871 $commandsXML->setAttribute('namespace', $namespace);
50872 }
50873
50874 foreach ($description->getCommands() as $command) {
50875 $this->appendDocument($commandsXML, $this->getCommandDocument($command));
50876 }
50877
50878 if (!$namespace) {
50879 $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
50880
50881 foreach ($description->getNamespaces() as $namespaceDescription) {
50882 $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
50883 $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
50884
50885 foreach ($namespaceDescription['commands'] as $name) {
50886 $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
50887 $commandXML->appendChild($dom->createTextNode($name));
50888 }
50889 }
50890 }
50891
50892 return $dom;
50893 }
50894
50895
50896
50897
50898 protected function describeInputArgument(InputArgument $argument, array $options = array())
50899 {
50900 $this->writeDocument($this->getInputArgumentDocument($argument));
50901 }
50902
50903
50904
50905
50906 protected function describeInputOption(InputOption $option, array $options = array())
50907 {
50908 $this->writeDocument($this->getInputOptionDocument($option));
50909 }
50910
50911
50912
50913
50914 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
50915 {
50916 $this->writeDocument($this->getInputDefinitionDocument($definition));
50917 }
50918
50919
50920
50921
50922 protected function describeCommand(Command $command, array $options = array())
50923 {
50924 $this->writeDocument($this->getCommandDocument($command));
50925 }
50926
50927
50928
50929
50930 protected function describeApplication(Application $application, array $options = array())
50931 {
50932 $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
50933 }
50934
50935
50936
50937
50938 private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
50939 {
50940 foreach ($importedParent->childNodes as $childNode) {
50941 $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
50942 }
50943 }
50944
50945
50946
50947
50948
50949
50950 private function writeDocument(\DOMDocument $dom)
50951 {
50952 $dom->formatOutput = true;
50953 $this->write($dom->saveXML());
50954 }
50955
50956
50957
50958
50959 private function getInputArgumentDocument(InputArgument $argument)
50960 {
50961 $dom = new \DOMDocument('1.0', 'UTF-8');
50962
50963 $dom->appendChild($objectXML = $dom->createElement('argument'));
50964 $objectXML->setAttribute('name', $argument->getName());
50965 $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
50966 $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
50967 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
50968 $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
50969
50970 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
50971 $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
50972 foreach ($defaults as $default) {
50973 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
50974 $defaultXML->appendChild($dom->createTextNode($default));
50975 }
50976
50977 return $dom;
50978 }
50979
50980
50981
50982
50983 private function getInputOptionDocument(InputOption $option)
50984 {
50985 $dom = new \DOMDocument('1.0', 'UTF-8');
50986
50987 $dom->appendChild($objectXML = $dom->createElement('option'));
50988 $objectXML->setAttribute('name', '--'.$option->getName());
50989 $pos = strpos($option->getShortcut(), '|');
50990 if (false !== $pos) {
50991 $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
50992 $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
50993 } else {
50994 $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
50995 }
50996 $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
50997 $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
50998 $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
50999 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
51000 $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
51001
51002 if ($option->acceptValue()) {
51003 $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
51004 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
51005
51006 if (!empty($defaults)) {
51007 foreach ($defaults as $default) {
51008 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
51009 $defaultXML->appendChild($dom->createTextNode($default));
51010 }
51011 }
51012 }
51013
51014 return $dom;
51015 }
51016 }
51017 <?php
51018
51019
51020
51021
51022
51023
51024
51025
51026
51027
51028 namespace Symfony\Component\Console\Event;
51029
51030
51031
51032
51033
51034
51035 class ConsoleCommandEvent extends ConsoleEvent
51036 {
51037
51038
51039
51040 const RETURN_CODE_DISABLED = 113;
51041
51042
51043
51044
51045 private $commandShouldRun = true;
51046
51047
51048
51049
51050
51051
51052 public function disableCommand()
51053 {
51054 return $this->commandShouldRun = false;
51055 }
51056
51057
51058
51059
51060
51061
51062 public function enableCommand()
51063 {
51064 return $this->commandShouldRun = true;
51065 }
51066
51067
51068
51069
51070
51071
51072 public function commandShouldRun()
51073 {
51074 return $this->commandShouldRun;
51075 }
51076 }
51077 <?php
51078
51079
51080
51081
51082
51083
51084
51085
51086
51087
51088 namespace Symfony\Component\Console\Event;
51089
51090 use Symfony\Component\Console\Command\Command;
51091 use Symfony\Component\Console\Input\InputInterface;
51092 use Symfony\Component\Console\Output\OutputInterface;
51093 use Symfony\Component\EventDispatcher\Event;
51094
51095
51096
51097
51098
51099
51100 class ConsoleEvent extends Event
51101 {
51102 protected $command;
51103
51104 private $input;
51105 private $output;
51106
51107 public function __construct(Command $command, InputInterface $input, OutputInterface $output)
51108 {
51109 $this->command = $command;
51110 $this->input = $input;
51111 $this->output = $output;
51112 }
51113
51114
51115
51116
51117
51118
51119 public function getCommand()
51120 {
51121 return $this->command;
51122 }
51123
51124
51125
51126
51127
51128
51129 public function getInput()
51130 {
51131 return $this->input;
51132 }
51133
51134
51135
51136
51137
51138
51139 public function getOutput()
51140 {
51141 return $this->output;
51142 }
51143 }
51144 <?php
51145
51146
51147
51148
51149
51150
51151
51152
51153
51154
51155 namespace Symfony\Component\Console\Event;
51156
51157 use Symfony\Component\Console\Command\Command;
51158 use Symfony\Component\Console\Input\InputInterface;
51159 use Symfony\Component\Console\Output\OutputInterface;
51160
51161
51162
51163
51164
51165
51166 class ConsoleExceptionEvent extends ConsoleEvent
51167 {
51168 private $exception;
51169 private $exitCode;
51170
51171 public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
51172 {
51173 parent::__construct($command, $input, $output);
51174
51175 $this->setException($exception);
51176 $this->exitCode = (int) $exitCode;
51177 }
51178
51179
51180
51181
51182
51183
51184 public function getException()
51185 {
51186 return $this->exception;
51187 }
51188
51189
51190
51191
51192
51193
51194
51195
51196 public function setException(\Exception $exception)
51197 {
51198 $this->exception = $exception;
51199 }
51200
51201
51202
51203
51204
51205
51206 public function getExitCode()
51207 {
51208 return $this->exitCode;
51209 }
51210 }
51211 <?php
51212
51213
51214
51215
51216
51217
51218
51219
51220
51221
51222 namespace Symfony\Component\Console\Event;
51223
51224 use Symfony\Component\Console\Command\Command;
51225 use Symfony\Component\Console\Input\InputInterface;
51226 use Symfony\Component\Console\Output\OutputInterface;
51227
51228
51229
51230
51231
51232
51233 class ConsoleTerminateEvent extends ConsoleEvent
51234 {
51235
51236
51237
51238
51239
51240 private $exitCode;
51241
51242 public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
51243 {
51244 parent::__construct($command, $input, $output);
51245
51246 $this->setExitCode($exitCode);
51247 }
51248
51249
51250
51251
51252
51253
51254 public function setExitCode($exitCode)
51255 {
51256 $this->exitCode = (int) $exitCode;
51257 }
51258
51259
51260
51261
51262
51263
51264 public function getExitCode()
51265 {
51266 return $this->exitCode;
51267 }
51268 }
51269 <?php
51270
51271
51272
51273
51274
51275
51276
51277
51278
51279
51280 namespace Symfony\Component\Console\Exception;
51281
51282
51283
51284
51285
51286
51287 class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
51288 {
51289 private $alternatives;
51290
51291
51292
51293
51294
51295
51296
51297 public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
51298 {
51299 parent::__construct($message, $code, $previous);
51300
51301 $this->alternatives = $alternatives;
51302 }
51303
51304
51305
51306
51307 public function getAlternatives()
51308 {
51309 return $this->alternatives;
51310 }
51311 }
51312 <?php
51313
51314
51315
51316
51317
51318
51319
51320
51321
51322
51323 namespace Symfony\Component\Console\Exception;
51324
51325
51326
51327
51328
51329
51330 interface ExceptionInterface
51331 {
51332 }
51333 <?php
51334
51335
51336
51337
51338
51339
51340
51341
51342
51343
51344 namespace Symfony\Component\Console\Exception;
51345
51346
51347
51348
51349 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
51350 {
51351 }
51352 <?php
51353
51354
51355
51356
51357
51358
51359
51360
51361
51362
51363 namespace Symfony\Component\Console\Exception;
51364
51365
51366
51367
51368
51369
51370 class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
51371 {
51372 }
51373 <?php
51374
51375
51376
51377
51378
51379
51380
51381
51382
51383
51384 namespace Symfony\Component\Console\Exception;
51385
51386
51387
51388
51389 class LogicException extends \LogicException implements ExceptionInterface
51390 {
51391 }
51392 <?php
51393
51394
51395
51396
51397
51398
51399
51400
51401
51402
51403 namespace Symfony\Component\Console\Exception;
51404
51405
51406
51407
51408 class RuntimeException extends \RuntimeException implements ExceptionInterface
51409 {
51410 }
51411 <?php
51412
51413
51414
51415
51416
51417
51418
51419
51420
51421
51422 namespace Symfony\Component\Console\Formatter;
51423
51424 use Symfony\Component\Console\Exception\InvalidArgumentException;
51425
51426
51427
51428
51429
51430
51431 class OutputFormatter implements OutputFormatterInterface
51432 {
51433 private $decorated;
51434 private $styles = array();
51435 private $styleStack;
51436
51437
51438
51439
51440
51441
51442
51443
51444 public static function escape($text)
51445 {
51446 $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
51447
51448 return self::escapeTrailingBackslash($text);
51449 }
51450
51451
51452
51453
51454
51455
51456
51457
51458
51459
51460 public static function escapeTrailingBackslash($text)
51461 {
51462 if ('\\' === substr($text, -1)) {
51463 $len = strlen($text);
51464 $text = rtrim($text, '\\');
51465 $text = str_replace("\0", '', $text);
51466 $text .= str_repeat("\0", $len - strlen($text));
51467 }
51468
51469 return $text;
51470 }
51471
51472
51473
51474
51475
51476
51477
51478 public function __construct($decorated = false, array $styles = array())
51479 {
51480 $this->decorated = (bool) $decorated;
51481
51482 $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
51483 $this->setStyle('info', new OutputFormatterStyle('green'));
51484 $this->setStyle('comment', new OutputFormatterStyle('yellow'));
51485 $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
51486
51487 foreach ($styles as $name => $style) {
51488 $this->setStyle($name, $style);
51489 }
51490
51491 $this->styleStack = new OutputFormatterStyleStack();
51492 }
51493
51494
51495
51496
51497 public function setDecorated($decorated)
51498 {
51499 $this->decorated = (bool) $decorated;
51500 }
51501
51502
51503
51504
51505 public function isDecorated()
51506 {
51507 return $this->decorated;
51508 }
51509
51510
51511
51512
51513 public function setStyle($name, OutputFormatterStyleInterface $style)
51514 {
51515 $this->styles[strtolower($name)] = $style;
51516 }
51517
51518
51519
51520
51521 public function hasStyle($name)
51522 {
51523 return isset($this->styles[strtolower($name)]);
51524 }
51525
51526
51527
51528
51529 public function getStyle($name)
51530 {
51531 if (!$this->hasStyle($name)) {
51532 throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
51533 }
51534
51535 return $this->styles[strtolower($name)];
51536 }
51537
51538
51539
51540
51541 public function format($message)
51542 {
51543 $message = (string) $message;
51544 $offset = 0;
51545 $output = '';
51546 $tagRegex = '[a-z][a-z0-9_=;-]*+';
51547 preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
51548 foreach ($matches[0] as $i => $match) {
51549 $pos = $match[1];
51550 $text = $match[0];
51551
51552 if (0 != $pos && '\\' == $message[$pos - 1]) {
51553 continue;
51554 }
51555
51556
51557  $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
51558 $offset = $pos + strlen($text);
51559
51560
51561  if ($open = '/' != $text[1]) {
51562 $tag = $matches[1][$i][0];
51563 } else {
51564 $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
51565 }
51566
51567 if (!$open && !$tag) {
51568
51569  $this->styleStack->pop();
51570 } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
51571 $output .= $this->applyCurrentStyle($text);
51572 } elseif ($open) {
51573 $this->styleStack->push($style);
51574 } else {
51575 $this->styleStack->pop($style);
51576 }
51577 }
51578
51579 $output .= $this->applyCurrentStyle(substr($message, $offset));
51580
51581 if (false !== strpos($output, "\0")) {
51582 return strtr($output, array("\0" => '\\', '\\<' => '<'));
51583 }
51584
51585 return str_replace('\\<', '<', $output);
51586 }
51587
51588
51589
51590
51591 public function getStyleStack()
51592 {
51593 return $this->styleStack;
51594 }
51595
51596
51597
51598
51599
51600
51601
51602
51603 private function createStyleFromString($string)
51604 {
51605 if (isset($this->styles[$string])) {
51606 return $this->styles[$string];
51607 }
51608
51609 if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
51610 return false;
51611 }
51612
51613 $style = new OutputFormatterStyle();
51614 foreach ($matches as $match) {
51615 array_shift($match);
51616
51617 if ('fg' == $match[0]) {
51618 $style->setForeground($match[1]);
51619 } elseif ('bg' == $match[0]) {
51620 $style->setBackground($match[1]);
51621 } else {
51622 try {
51623 $style->setOption($match[1]);
51624 } catch (\InvalidArgumentException $e) {
51625 return false;
51626 }
51627 }
51628 }
51629
51630 return $style;
51631 }
51632
51633
51634
51635
51636
51637
51638
51639
51640 private function applyCurrentStyle($text)
51641 {
51642 return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
51643 }
51644 }
51645 <?php
51646
51647
51648
51649
51650
51651
51652
51653
51654
51655
51656 namespace Symfony\Component\Console\Formatter;
51657
51658
51659
51660
51661
51662
51663 interface OutputFormatterInterface
51664 {
51665
51666
51667
51668
51669
51670 public function setDecorated($decorated);
51671
51672
51673
51674
51675
51676
51677 public function isDecorated();
51678
51679
51680
51681
51682
51683
51684
51685 public function setStyle($name, OutputFormatterStyleInterface $style);
51686
51687
51688
51689
51690
51691
51692
51693
51694 public function hasStyle($name);
51695
51696
51697
51698
51699
51700
51701
51702
51703
51704
51705 public function getStyle($name);
51706
51707
51708
51709
51710
51711
51712
51713
51714 public function format($message);
51715 }
51716 <?php
51717
51718
51719
51720
51721
51722
51723
51724
51725
51726
51727 namespace Symfony\Component\Console\Formatter;
51728
51729 use Symfony\Component\Console\Exception\InvalidArgumentException;
51730
51731
51732
51733
51734
51735
51736 class OutputFormatterStyle implements OutputFormatterStyleInterface
51737 {
51738 private static $availableForegroundColors = array(
51739 'black' => array('set' => 30, 'unset' => 39),
51740 'red' => array('set' => 31, 'unset' => 39),
51741 'green' => array('set' => 32, 'unset' => 39),
51742 'yellow' => array('set' => 33, 'unset' => 39),
51743 'blue' => array('set' => 34, 'unset' => 39),
51744 'magenta' => array('set' => 35, 'unset' => 39),
51745 'cyan' => array('set' => 36, 'unset' => 39),
51746 'white' => array('set' => 37, 'unset' => 39),
51747 'default' => array('set' => 39, 'unset' => 39),
51748 );
51749 private static $availableBackgroundColors = array(
51750 'black' => array('set' => 40, 'unset' => 49),
51751 'red' => array('set' => 41, 'unset' => 49),
51752 'green' => array('set' => 42, 'unset' => 49),
51753 'yellow' => array('set' => 43, 'unset' => 49),
51754 'blue' => array('set' => 44, 'unset' => 49),
51755 'magenta' => array('set' => 45, 'unset' => 49),
51756 'cyan' => array('set' => 46, 'unset' => 49),
51757 'white' => array('set' => 47, 'unset' => 49),
51758 'default' => array('set' => 49, 'unset' => 49),
51759 );
51760 private static $availableOptions = array(
51761 'bold' => array('set' => 1, 'unset' => 22),
51762 'underscore' => array('set' => 4, 'unset' => 24),
51763 'blink' => array('set' => 5, 'unset' => 25),
51764 'reverse' => array('set' => 7, 'unset' => 27),
51765 'conceal' => array('set' => 8, 'unset' => 28),
51766 );
51767
51768 private $foreground;
51769 private $background;
51770 private $options = array();
51771
51772
51773
51774
51775
51776
51777
51778
51779 public function __construct($foreground = null, $background = null, array $options = array())
51780 {
51781 if (null !== $foreground) {
51782 $this->setForeground($foreground);
51783 }
51784 if (null !== $background) {
51785 $this->setBackground($background);
51786 }
51787 if (count($options)) {
51788 $this->setOptions($options);
51789 }
51790 }
51791
51792
51793
51794
51795
51796
51797
51798
51799 public function setForeground($color = null)
51800 {
51801 if (null === $color) {
51802 $this->foreground = null;
51803
51804 return;
51805 }
51806
51807 if (!isset(static::$availableForegroundColors[$color])) {
51808 throw new InvalidArgumentException(sprintf(
51809 'Invalid foreground color specified: "%s". Expected one of (%s)',
51810 $color,
51811 implode(', ', array_keys(static::$availableForegroundColors))
51812 ));
51813 }
51814
51815 $this->foreground = static::$availableForegroundColors[$color];
51816 }
51817
51818
51819
51820
51821
51822
51823
51824
51825 public function setBackground($color = null)
51826 {
51827 if (null === $color) {
51828 $this->background = null;
51829
51830 return;
51831 }
51832
51833 if (!isset(static::$availableBackgroundColors[$color])) {
51834 throw new InvalidArgumentException(sprintf(
51835 'Invalid background color specified: "%s". Expected one of (%s)',
51836 $color,
51837 implode(', ', array_keys(static::$availableBackgroundColors))
51838 ));
51839 }
51840
51841 $this->background = static::$availableBackgroundColors[$color];
51842 }
51843
51844
51845
51846
51847
51848
51849
51850
51851 public function setOption($option)
51852 {
51853 if (!isset(static::$availableOptions[$option])) {
51854 throw new InvalidArgumentException(sprintf(
51855 'Invalid option specified: "%s". Expected one of (%s)',
51856 $option,
51857 implode(', ', array_keys(static::$availableOptions))
51858 ));
51859 }
51860
51861 if (!in_array(static::$availableOptions[$option], $this->options)) {
51862 $this->options[] = static::$availableOptions[$option];
51863 }
51864 }
51865
51866
51867
51868
51869
51870
51871
51872
51873 public function unsetOption($option)
51874 {
51875 if (!isset(static::$availableOptions[$option])) {
51876 throw new InvalidArgumentException(sprintf(
51877 'Invalid option specified: "%s". Expected one of (%s)',
51878 $option,
51879 implode(', ', array_keys(static::$availableOptions))
51880 ));
51881 }
51882
51883 $pos = array_search(static::$availableOptions[$option], $this->options);
51884 if (false !== $pos) {
51885 unset($this->options[$pos]);
51886 }
51887 }
51888
51889
51890
51891
51892 public function setOptions(array $options)
51893 {
51894 $this->options = array();
51895
51896 foreach ($options as $option) {
51897 $this->setOption($option);
51898 }
51899 }
51900
51901
51902
51903
51904
51905
51906
51907
51908 public function apply($text)
51909 {
51910 $setCodes = array();
51911 $unsetCodes = array();
51912
51913 if (null !== $this->foreground) {
51914 $setCodes[] = $this->foreground['set'];
51915 $unsetCodes[] = $this->foreground['unset'];
51916 }
51917 if (null !== $this->background) {
51918 $setCodes[] = $this->background['set'];
51919 $unsetCodes[] = $this->background['unset'];
51920 }
51921 if (count($this->options)) {
51922 foreach ($this->options as $option) {
51923 $setCodes[] = $option['set'];
51924 $unsetCodes[] = $option['unset'];
51925 }
51926 }
51927
51928 if (0 === count($setCodes)) {
51929 return $text;
51930 }
51931
51932 return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
51933 }
51934 }
51935 <?php
51936
51937
51938
51939
51940
51941
51942
51943
51944
51945
51946 namespace Symfony\Component\Console\Formatter;
51947
51948
51949
51950
51951
51952
51953 interface OutputFormatterStyleInterface
51954 {
51955
51956
51957
51958
51959
51960 public function setForeground($color = null);
51961
51962
51963
51964
51965
51966
51967 public function setBackground($color = null);
51968
51969
51970
51971
51972
51973
51974 public function setOption($option);
51975
51976
51977
51978
51979
51980
51981 public function unsetOption($option);
51982
51983
51984
51985
51986 public function setOptions(array $options);
51987
51988
51989
51990
51991
51992
51993
51994
51995 public function apply($text);
51996 }
51997 <?php
51998
51999
52000
52001
52002
52003
52004
52005
52006
52007
52008 namespace Symfony\Component\Console\Formatter;
52009
52010 use Symfony\Component\Console\Exception\InvalidArgumentException;
52011
52012
52013
52014
52015 class OutputFormatterStyleStack
52016 {
52017
52018
52019
52020 private $styles;
52021
52022 private $emptyStyle;
52023
52024 public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
52025 {
52026 $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
52027 $this->reset();
52028 }
52029
52030
52031
52032
52033 public function reset()
52034 {
52035 $this->styles = array();
52036 }
52037
52038
52039
52040
52041 public function push(OutputFormatterStyleInterface $style)
52042 {
52043 $this->styles[] = $style;
52044 }
52045
52046
52047
52048
52049
52050
52051
52052
52053 public function pop(OutputFormatterStyleInterface $style = null)
52054 {
52055 if (empty($this->styles)) {
52056 return $this->emptyStyle;
52057 }
52058
52059 if (null === $style) {
52060 return array_pop($this->styles);
52061 }
52062
52063 foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
52064 if ($style->apply('') === $stackedStyle->apply('')) {
52065 $this->styles = array_slice($this->styles, 0, $index);
52066
52067 return $stackedStyle;
52068 }
52069 }
52070
52071 throw new InvalidArgumentException('Incorrectly nested style tag found.');
52072 }
52073
52074
52075
52076
52077
52078
52079 public function getCurrent()
52080 {
52081 if (empty($this->styles)) {
52082 return $this->emptyStyle;
52083 }
52084
52085 return $this->styles[count($this->styles) - 1];
52086 }
52087
52088
52089
52090
52091 public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
52092 {
52093 $this->emptyStyle = $emptyStyle;
52094
52095 return $this;
52096 }
52097
52098
52099
52100
52101 public function getEmptyStyle()
52102 {
52103 return $this->emptyStyle;
52104 }
52105 }
52106 <?php
52107
52108
52109
52110
52111
52112
52113
52114
52115
52116
52117 namespace Symfony\Component\Console\Helper;
52118
52119
52120
52121
52122
52123
52124
52125
52126 class DebugFormatterHelper extends Helper
52127 {
52128 private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
52129 private $started = array();
52130 private $count = -1;
52131
52132
52133
52134
52135
52136
52137
52138
52139
52140
52141 public function start($id, $message, $prefix = 'RUN')
52142 {
52143 $this->started[$id] = array('border' => ++$this->count % count($this->colors));
52144
52145 return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
52146 }
52147
52148
52149
52150
52151
52152
52153
52154
52155
52156
52157
52158
52159 public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
52160 {
52161 $message = '';
52162
52163 if ($error) {
52164 if (isset($this->started[$id]['out'])) {
52165 $message .= "\n";
52166 unset($this->started[$id]['out']);
52167 }
52168 if (!isset($this->started[$id]['err'])) {
52169 $message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
52170 $this->started[$id]['err'] = true;
52171 }
52172
52173 $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
52174 } else {
52175 if (isset($this->started[$id]['err'])) {
52176 $message .= "\n";
52177 unset($this->started[$id]['err']);
52178 }
52179 if (!isset($this->started[$id]['out'])) {
52180 $message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
52181 $this->started[$id]['out'] = true;
52182 }
52183
52184 $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
52185 }
52186
52187 return $message;
52188 }
52189
52190
52191
52192
52193
52194
52195
52196
52197
52198
52199
52200 public function stop($id, $message, $successful, $prefix = 'RES')
52201 {
52202 $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
52203
52204 if ($successful) {
52205 return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
52206 }
52207
52208 $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
52209
52210 unset($this->started[$id]['out'], $this->started[$id]['err']);
52211
52212 return $message;
52213 }
52214
52215
52216
52217
52218
52219
52220 private function getBorder($id)
52221 {
52222 return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
52223 }
52224
52225
52226
52227
52228 public function getName()
52229 {
52230 return 'debug_formatter';
52231 }
52232 }
52233 <?php
52234
52235
52236
52237
52238
52239
52240
52241
52242
52243
52244 namespace Symfony\Component\Console\Helper;
52245
52246 use Symfony\Component\Console\Descriptor\DescriptorInterface;
52247 use Symfony\Component\Console\Descriptor\JsonDescriptor;
52248 use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
52249 use Symfony\Component\Console\Descriptor\TextDescriptor;
52250 use Symfony\Component\Console\Descriptor\XmlDescriptor;
52251 use Symfony\Component\Console\Output\OutputInterface;
52252 use Symfony\Component\Console\Exception\InvalidArgumentException;
52253
52254
52255
52256
52257
52258
52259 class DescriptorHelper extends Helper
52260 {
52261
52262
52263
52264 private $descriptors = array();
52265
52266 public function __construct()
52267 {
52268 $this
52269 ->register('txt', new TextDescriptor())
52270 ->register('xml', new XmlDescriptor())
52271 ->register('json', new JsonDescriptor())
52272 ->register('md', new MarkdownDescriptor())
52273 ;
52274 }
52275
52276
52277
52278
52279
52280
52281
52282
52283
52284
52285
52286
52287
52288
52289 public function describe(OutputInterface $output, $object, array $options = array())
52290 {
52291 $options = array_merge(array(
52292 'raw_text' => false,
52293 'format' => 'txt',
52294 ), $options);
52295
52296 if (!isset($this->descriptors[$options['format']])) {
52297 throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
52298 }
52299
52300 $descriptor = $this->descriptors[$options['format']];
52301 $descriptor->describe($output, $object, $options);
52302 }
52303
52304
52305
52306
52307
52308
52309
52310
52311
52312 public function register($format, DescriptorInterface $descriptor)
52313 {
52314 $this->descriptors[$format] = $descriptor;
52315
52316 return $this;
52317 }
52318
52319
52320
52321
52322 public function getName()
52323 {
52324 return 'descriptor';
52325 }
52326 }
52327 <?php
52328
52329
52330
52331
52332
52333
52334
52335
52336
52337
52338 namespace Symfony\Component\Console\Helper;
52339
52340 use Symfony\Component\Console\Exception\InvalidArgumentException;
52341 use Symfony\Component\Console\Exception\RuntimeException;
52342 use Symfony\Component\Console\Output\ConsoleOutputInterface;
52343 use Symfony\Component\Console\Output\OutputInterface;
52344 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
52345
52346
52347
52348
52349
52350
52351
52352
52353
52354 class DialogHelper extends InputAwareHelper
52355 {
52356 private $inputStream;
52357 private static $shell;
52358 private static $stty;
52359
52360 public function __construct($triggerDeprecationError = true)
52361 {
52362 if ($triggerDeprecationError) {
52363 @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);
52364 }
52365 }
52366
52367
52368
52369
52370
52371
52372
52373
52374
52375
52376
52377
52378
52379
52380
52381
52382 public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
52383 {
52384 if ($output instanceof ConsoleOutputInterface) {
52385 $output = $output->getErrorOutput();
52386 }
52387
52388 $width = max(array_map('strlen', array_keys($choices)));
52389
52390 $messages = (array) $question;
52391 foreach ($choices as $key => $value) {
52392 $messages[] = sprintf("  [<info>%-{$width}s</info>] %s", $key, $value);
52393 }
52394
52395 $output->writeln($messages);
52396
52397 $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
52398
52399  $selectedChoices = str_replace(' ', '', $picked);
52400
52401 if ($multiselect) {
52402
52403  if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
52404 throw new InvalidArgumentException(sprintf($errorMessage, $picked));
52405 }
52406 $selectedChoices = explode(',', $selectedChoices);
52407 } else {
52408 $selectedChoices = array($picked);
52409 }
52410
52411 $multiselectChoices = array();
52412
52413 foreach ($selectedChoices as $value) {
52414 if (empty($choices[$value])) {
52415 throw new InvalidArgumentException(sprintf($errorMessage, $value));
52416 }
52417 $multiselectChoices[] = $value;
52418 }
52419
52420 if ($multiselect) {
52421 return $multiselectChoices;
52422 }
52423
52424 return $picked;
52425 }, $attempts, $default);
52426
52427 return $result;
52428 }
52429
52430
52431
52432
52433
52434
52435
52436
52437
52438
52439
52440
52441
52442 public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
52443 {
52444 if ($this->input && !$this->input->isInteractive()) {
52445 return $default;
52446 }
52447
52448 if ($output instanceof ConsoleOutputInterface) {
52449 $output = $output->getErrorOutput();
52450 }
52451
52452 $output->write($question);
52453
52454 $inputStream = $this->inputStream ?: STDIN;
52455
52456 if (null === $autocomplete || !$this->hasSttyAvailable()) {
52457 $ret = fgets($inputStream, 4096);
52458 if (false === $ret) {
52459 throw new RuntimeException('Aborted');
52460 }
52461 $ret = trim($ret);
52462 } else {
52463 $ret = '';
52464
52465 $i = 0;
52466 $ofs = -1;
52467 $matches = $autocomplete;
52468 $numMatches = count($matches);
52469
52470 $sttyMode = shell_exec('stty -g');
52471
52472
52473  shell_exec('stty -icanon -echo');
52474
52475
52476  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
52477
52478
52479  while (!feof($inputStream)) {
52480 $c = fread($inputStream, 1);
52481
52482
52483  if ("\177" === $c) {
52484 if (0 === $numMatches && 0 !== $i) {
52485 --$i;
52486
52487  $output->write("\033[1D");
52488 }
52489
52490 if (0 === $i) {
52491 $ofs = -1;
52492 $matches = $autocomplete;
52493 $numMatches = count($matches);
52494 } else {
52495 $numMatches = 0;
52496 }
52497
52498
52499  $ret = substr($ret, 0, $i);
52500 } elseif ("\033" === $c) {
52501
52502  $c .= fread($inputStream, 2);
52503
52504
52505  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
52506 if ('A' === $c[2] && -1 === $ofs) {
52507 $ofs = 0;
52508 }
52509
52510 if (0 === $numMatches) {
52511 continue;
52512 }
52513
52514 $ofs += ('A' === $c[2]) ? -1 : 1;
52515 $ofs = ($numMatches + $ofs) % $numMatches;
52516 }
52517 } elseif (ord($c) < 32) {
52518 if ("\t" === $c || "\n" === $c) {
52519 if ($numMatches > 0 && -1 !== $ofs) {
52520 $ret = $matches[$ofs];
52521
52522  $output->write(substr($ret, $i));
52523 $i = strlen($ret);
52524 }
52525
52526 if ("\n" === $c) {
52527 $output->write($c);
52528 break;
52529 }
52530
52531 $numMatches = 0;
52532 }
52533
52534 continue;
52535 } else {
52536 $output->write($c);
52537 $ret .= $c;
52538 ++$i;
52539
52540 $numMatches = 0;
52541 $ofs = 0;
52542
52543 foreach ($autocomplete as $value) {
52544
52545  if (0 === strpos($value, $ret) && $i !== strlen($value)) {
52546 $matches[$numMatches++] = $value;
52547 }
52548 }
52549 }
52550
52551
52552  $output->write("\033[K");
52553
52554 if ($numMatches > 0 && -1 !== $ofs) {
52555
52556  $output->write("\0337");
52557
52558  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
52559
52560  $output->write("\0338");
52561 }
52562 }
52563
52564
52565  shell_exec(sprintf('stty %s', $sttyMode));
52566 }
52567
52568 return strlen($ret) > 0 ? $ret : $default;
52569 }
52570
52571
52572
52573
52574
52575
52576
52577
52578
52579
52580
52581
52582 public function askConfirmation(OutputInterface $output, $question, $default = true)
52583 {
52584 $answer = 'z';
52585 while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
52586 $answer = $this->ask($output, $question);
52587 }
52588
52589 if (false === $default) {
52590 return $answer && 'y' == strtolower($answer[0]);
52591 }
52592
52593 return !$answer || 'y' == strtolower($answer[0]);
52594 }
52595
52596
52597
52598
52599
52600
52601
52602
52603
52604
52605
52606
52607 public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
52608 {
52609 if ($output instanceof ConsoleOutputInterface) {
52610 $output = $output->getErrorOutput();
52611 }
52612
52613 if ('\\' === DIRECTORY_SEPARATOR) {
52614 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
52615
52616
52617  if ('phar:' === substr(__FILE__, 0, 5)) {
52618 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
52619 copy($exe, $tmpExe);
52620 $exe = $tmpExe;
52621 }
52622
52623 $output->write($question);
52624 $value = rtrim(shell_exec($exe));
52625 $output->writeln('');
52626
52627 if (isset($tmpExe)) {
52628 unlink($tmpExe);
52629 }
52630
52631 return $value;
52632 }
52633
52634 if ($this->hasSttyAvailable()) {
52635 $output->write($question);
52636
52637 $sttyMode = shell_exec('stty -g');
52638
52639 shell_exec('stty -echo');
52640 $value = fgets($this->inputStream ?: STDIN, 4096);
52641 shell_exec(sprintf('stty %s', $sttyMode));
52642
52643 if (false === $value) {
52644 throw new RuntimeException('Aborted');
52645 }
52646
52647 $value = trim($value);
52648 $output->writeln('');
52649
52650 return $value;
52651 }
52652
52653 if (false !== $shell = $this->getShell()) {
52654 $output->write($question);
52655 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
52656 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
52657 $value = rtrim(shell_exec($command));
52658 $output->writeln('');
52659
52660 return $value;
52661 }
52662
52663 if ($fallback) {
52664 return $this->ask($output, $question);
52665 }
52666
52667 throw new RuntimeException('Unable to hide the response');
52668 }
52669
52670
52671
52672
52673
52674
52675
52676
52677
52678
52679
52680
52681
52682
52683
52684
52685
52686
52687
52688 public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
52689 {
52690 $that = $this;
52691
52692 $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
52693 return $that->ask($output, $question, $default, $autocomplete);
52694 };
52695
52696 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
52697 }
52698
52699
52700
52701
52702
52703
52704
52705
52706
52707
52708
52709
52710
52711
52712
52713
52714
52715
52716
52717 public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
52718 {
52719 $that = $this;
52720
52721 $interviewer = function () use ($output, $question, $fallback, $that) {
52722 return $that->askHiddenResponse($output, $question, $fallback);
52723 };
52724
52725 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
52726 }
52727
52728
52729
52730
52731
52732
52733
52734
52735 public function setInputStream($stream)
52736 {
52737 $this->inputStream = $stream;
52738 }
52739
52740
52741
52742
52743
52744
52745 public function getInputStream()
52746 {
52747 return $this->inputStream;
52748 }
52749
52750
52751
52752
52753 public function getName()
52754 {
52755 return 'dialog';
52756 }
52757
52758
52759
52760
52761
52762
52763 private function getShell()
52764 {
52765 if (null !== self::$shell) {
52766 return self::$shell;
52767 }
52768
52769 self::$shell = false;
52770
52771 if (file_exists('/usr/bin/env')) {
52772
52773  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
52774 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
52775 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
52776 self::$shell = $sh;
52777 break;
52778 }
52779 }
52780 }
52781
52782 return self::$shell;
52783 }
52784
52785 private function hasSttyAvailable()
52786 {
52787 if (null !== self::$stty) {
52788 return self::$stty;
52789 }
52790
52791 exec('stty 2>&1', $output, $exitcode);
52792
52793 return self::$stty = 0 === $exitcode;
52794 }
52795
52796
52797
52798
52799
52800
52801
52802
52803
52804
52805
52806
52807
52808 private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
52809 {
52810 if ($output instanceof ConsoleOutputInterface) {
52811 $output = $output->getErrorOutput();
52812 }
52813
52814 $e = null;
52815 while (false === $attempts || $attempts--) {
52816 if (null !== $e) {
52817 $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
52818 }
52819
52820 try {
52821 return call_user_func($validator, $interviewer());
52822 } catch (\Exception $e) {
52823 }
52824 }
52825
52826 throw $e;
52827 }
52828 }
52829 <?php
52830
52831
52832
52833
52834
52835
52836
52837
52838
52839
52840 namespace Symfony\Component\Console\Helper;
52841
52842 use Symfony\Component\Console\Formatter\OutputFormatter;
52843
52844
52845
52846
52847
52848
52849 class FormatterHelper extends Helper
52850 {
52851
52852
52853
52854
52855
52856
52857
52858
52859
52860 public function formatSection($section, $message, $style = 'info')
52861 {
52862 return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
52863 }
52864
52865
52866
52867
52868
52869
52870
52871
52872
52873
52874 public function formatBlock($messages, $style, $large = false)
52875 {
52876 if (!is_array($messages)) {
52877 $messages = array($messages);
52878 }
52879
52880 $len = 0;
52881 $lines = array();
52882 foreach ($messages as $message) {
52883 $message = OutputFormatter::escape($message);
52884 $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
52885 $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
52886 }
52887
52888 $messages = $large ? array(str_repeat(' ', $len)) : array();
52889 for ($i = 0; isset($lines[$i]); ++$i) {
52890 $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
52891 }
52892 if ($large) {
52893 $messages[] = str_repeat(' ', $len);
52894 }
52895
52896 for ($i = 0; isset($messages[$i]); ++$i) {
52897 $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
52898 }
52899
52900 return implode("\n", $messages);
52901 }
52902
52903
52904
52905
52906 public function getName()
52907 {
52908 return 'formatter';
52909 }
52910 }
52911 <?php
52912
52913
52914
52915
52916
52917
52918
52919
52920
52921
52922 namespace Symfony\Component\Console\Helper;
52923
52924 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
52925
52926
52927
52928
52929
52930
52931 abstract class Helper implements HelperInterface
52932 {
52933 protected $helperSet = null;
52934
52935
52936
52937
52938 public function setHelperSet(HelperSet $helperSet = null)
52939 {
52940 $this->helperSet = $helperSet;
52941 }
52942
52943
52944
52945
52946 public function getHelperSet()
52947 {
52948 return $this->helperSet;
52949 }
52950
52951
52952
52953
52954
52955
52956
52957
52958 public static function strlen($string)
52959 {
52960 if (false === $encoding = mb_detect_encoding($string, null, true)) {
52961 return strlen($string);
52962 }
52963
52964 return mb_strwidth($string, $encoding);
52965 }
52966
52967 public static function formatTime($secs)
52968 {
52969 static $timeFormats = array(
52970 array(0, '< 1 sec'),
52971 array(1, '1 sec'),
52972 array(2, 'secs', 1),
52973 array(60, '1 min'),
52974 array(120, 'mins', 60),
52975 array(3600, '1 hr'),
52976 array(7200, 'hrs', 3600),
52977 array(86400, '1 day'),
52978 array(172800, 'days', 86400),
52979 );
52980
52981 foreach ($timeFormats as $index => $format) {
52982 if ($secs >= $format[0]) {
52983 if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
52984 || $index == count($timeFormats) - 1
52985 ) {
52986 if (2 == count($format)) {
52987 return $format[1];
52988 }
52989
52990 return floor($secs / $format[2]).' '.$format[1];
52991 }
52992 }
52993 }
52994 }
52995
52996 public static function formatMemory($memory)
52997 {
52998 if ($memory >= 1024 * 1024 * 1024) {
52999 return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
53000 }
53001
53002 if ($memory >= 1024 * 1024) {
53003 return sprintf('%.1f MiB', $memory / 1024 / 1024);
53004 }
53005
53006 if ($memory >= 1024) {
53007 return sprintf('%d KiB', $memory / 1024);
53008 }
53009
53010 return sprintf('%d B', $memory);
53011 }
53012
53013 public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
53014 {
53015 return self::strlen(self::removeDecoration($formatter, $string));
53016 }
53017
53018 public static function removeDecoration(OutputFormatterInterface $formatter, $string)
53019 {
53020 $isDecorated = $formatter->isDecorated();
53021 $formatter->setDecorated(false);
53022
53023  $string = $formatter->format($string);
53024
53025  $string = preg_replace("/\033\[[^m]*m/", '', $string);
53026 $formatter->setDecorated($isDecorated);
53027
53028 return $string;
53029 }
53030 }
53031 <?php
53032
53033
53034
53035
53036
53037
53038
53039
53040
53041
53042 namespace Symfony\Component\Console\Helper;
53043
53044
53045
53046
53047
53048
53049 interface HelperInterface
53050 {
53051
53052
53053
53054 public function setHelperSet(HelperSet $helperSet = null);
53055
53056
53057
53058
53059
53060
53061 public function getHelperSet();
53062
53063
53064
53065
53066
53067
53068 public function getName();
53069 }
53070 <?php
53071
53072
53073
53074
53075
53076
53077
53078
53079
53080
53081 namespace Symfony\Component\Console\Helper;
53082
53083 use Symfony\Component\Console\Command\Command;
53084 use Symfony\Component\Console\Exception\InvalidArgumentException;
53085
53086
53087
53088
53089
53090
53091 class HelperSet implements \IteratorAggregate
53092 {
53093
53094
53095
53096 private $helpers = array();
53097 private $command;
53098
53099
53100
53101
53102 public function __construct(array $helpers = array())
53103 {
53104 foreach ($helpers as $alias => $helper) {
53105 $this->set($helper, is_int($alias) ? null : $alias);
53106 }
53107 }
53108
53109
53110
53111
53112
53113
53114
53115 public function set(HelperInterface $helper, $alias = null)
53116 {
53117 $this->helpers[$helper->getName()] = $helper;
53118 if (null !== $alias) {
53119 $this->helpers[$alias] = $helper;
53120 }
53121
53122 $helper->setHelperSet($this);
53123 }
53124
53125
53126
53127
53128
53129
53130
53131
53132 public function has($name)
53133 {
53134 return isset($this->helpers[$name]);
53135 }
53136
53137
53138
53139
53140
53141
53142
53143
53144
53145
53146 public function get($name)
53147 {
53148 if (!$this->has($name)) {
53149 throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
53150 }
53151
53152 if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) {
53153 @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);
53154 } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) {
53155 @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);
53156 } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) {
53157 @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);
53158 }
53159
53160 return $this->helpers[$name];
53161 }
53162
53163 public function setCommand(Command $command = null)
53164 {
53165 $this->command = $command;
53166 }
53167
53168
53169
53170
53171
53172
53173 public function getCommand()
53174 {
53175 return $this->command;
53176 }
53177
53178
53179
53180
53181 public function getIterator()
53182 {
53183 return new \ArrayIterator($this->helpers);
53184 }
53185 }
53186 <?php
53187
53188
53189
53190
53191
53192
53193
53194
53195
53196
53197 namespace Symfony\Component\Console\Helper;
53198
53199 use Symfony\Component\Console\Input\InputInterface;
53200 use Symfony\Component\Console\Input\InputAwareInterface;
53201
53202
53203
53204
53205
53206
53207 abstract class InputAwareHelper extends Helper implements InputAwareInterface
53208 {
53209 protected $input;
53210
53211
53212
53213
53214 public function setInput(InputInterface $input)
53215 {
53216 $this->input = $input;
53217 }
53218 }
53219 <?php
53220
53221
53222
53223
53224
53225
53226
53227
53228
53229
53230 namespace Symfony\Component\Console\Helper;
53231
53232 use Symfony\Component\Console\Output\ConsoleOutputInterface;
53233 use Symfony\Component\Console\Output\OutputInterface;
53234 use Symfony\Component\Process\Exception\ProcessFailedException;
53235 use Symfony\Component\Process\Process;
53236 use Symfony\Component\Process\ProcessBuilder;
53237
53238
53239
53240
53241
53242
53243 class ProcessHelper extends Helper
53244 {
53245
53246
53247
53248
53249
53250
53251
53252
53253
53254
53255
53256
53257 public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
53258 {
53259 if ($output instanceof ConsoleOutputInterface) {
53260 $output = $output->getErrorOutput();
53261 }
53262
53263 $formatter = $this->getHelperSet()->get('debug_formatter');
53264
53265 if (is_array($cmd)) {
53266 $process = ProcessBuilder::create($cmd)->getProcess();
53267 } elseif ($cmd instanceof Process) {
53268 $process = $cmd;
53269 } else {
53270 $process = new Process($cmd);
53271 }
53272
53273 if ($verbosity <= $output->getVerbosity()) {
53274 $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
53275 }
53276
53277 if ($output->isDebug()) {
53278 $callback = $this->wrapCallback($output, $process, $callback);
53279 }
53280
53281 $process->run($callback);
53282
53283 if ($verbosity <= $output->getVerbosity()) {
53284 $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
53285 $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
53286 }
53287
53288 if (!$process->isSuccessful() && null !== $error) {
53289 $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
53290 }
53291
53292 return $process;
53293 }
53294
53295
53296
53297
53298
53299
53300
53301
53302
53303
53304
53305
53306
53307
53308
53309
53310
53311
53312
53313 public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
53314 {
53315 $process = $this->run($output, $cmd, $error, $callback);
53316
53317 if (!$process->isSuccessful()) {
53318 throw new ProcessFailedException($process);
53319 }
53320
53321 return $process;
53322 }
53323
53324
53325
53326
53327
53328
53329
53330
53331
53332
53333 public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
53334 {
53335 if ($output instanceof ConsoleOutputInterface) {
53336 $output = $output->getErrorOutput();
53337 }
53338
53339 $formatter = $this->getHelperSet()->get('debug_formatter');
53340
53341 $that = $this;
53342
53343 return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
53344 $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
53345
53346 if (null !== $callback) {
53347 call_user_func($callback, $type, $buffer);
53348 }
53349 };
53350 }
53351
53352
53353
53354
53355
53356
53357 public function escapeString($str)
53358 {
53359 return str_replace('<', '\\<', $str);
53360 }
53361
53362
53363
53364
53365 public function getName()
53366 {
53367 return 'process';
53368 }
53369 }
53370 <?php
53371
53372
53373
53374
53375
53376
53377
53378
53379
53380
53381 namespace Symfony\Component\Console\Helper;
53382
53383 use Symfony\Component\Console\Output\ConsoleOutputInterface;
53384 use Symfony\Component\Console\Output\OutputInterface;
53385 use Symfony\Component\Console\Exception\LogicException;
53386
53387
53388
53389
53390
53391
53392
53393 class ProgressBar
53394 {
53395 private $barWidth = 28;
53396 private $barChar;
53397 private $emptyBarChar = '-';
53398 private $progressChar = '>';
53399 private $format;
53400 private $internalFormat;
53401 private $redrawFreq = 1;
53402 private $output;
53403 private $step = 0;
53404 private $max;
53405 private $startTime;
53406 private $stepWidth;
53407 private $percent = 0.0;
53408 private $formatLineCount;
53409 private $messages = array();
53410 private $overwrite = true;
53411 private $firstRun = true;
53412
53413 private static $formatters;
53414 private static $formats;
53415
53416
53417
53418
53419
53420 public function __construct(OutputInterface $output, $max = 0)
53421 {
53422 if ($output instanceof ConsoleOutputInterface) {
53423 $output = $output->getErrorOutput();
53424 }
53425
53426 $this->output = $output;
53427 $this->setMaxSteps($max);
53428
53429 if (!$this->output->isDecorated()) {
53430
53431  $this->overwrite = false;
53432
53433
53434  $this->setRedrawFrequency($max / 10);
53435 }
53436
53437 $this->startTime = time();
53438 }
53439
53440
53441
53442
53443
53444
53445
53446
53447
53448 public static function setPlaceholderFormatterDefinition($name, $callable)
53449 {
53450 if (!self::$formatters) {
53451 self::$formatters = self::initPlaceholderFormatters();
53452 }
53453
53454 self::$formatters[$name] = $callable;
53455 }
53456
53457
53458
53459
53460
53461
53462
53463
53464 public static function getPlaceholderFormatterDefinition($name)
53465 {
53466 if (!self::$formatters) {
53467 self::$formatters = self::initPlaceholderFormatters();
53468 }
53469
53470 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
53471 }
53472
53473
53474
53475
53476
53477
53478
53479
53480
53481 public static function setFormatDefinition($name, $format)
53482 {
53483 if (!self::$formats) {
53484 self::$formats = self::initFormats();
53485 }
53486
53487 self::$formats[$name] = $format;
53488 }
53489
53490
53491
53492
53493
53494
53495
53496
53497 public static function getFormatDefinition($name)
53498 {
53499 if (!self::$formats) {
53500 self::$formats = self::initFormats();
53501 }
53502
53503 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
53504 }
53505
53506
53507
53508
53509
53510
53511
53512
53513
53514
53515
53516 public function setMessage($message, $name = 'message')
53517 {
53518 $this->messages[$name] = $message;
53519 }
53520
53521 public function getMessage($name = 'message')
53522 {
53523 return $this->messages[$name];
53524 }
53525
53526
53527
53528
53529
53530
53531 public function getStartTime()
53532 {
53533 return $this->startTime;
53534 }
53535
53536
53537
53538
53539
53540
53541 public function getMaxSteps()
53542 {
53543 return $this->max;
53544 }
53545
53546
53547
53548
53549
53550
53551
53552
53553 public function getStep()
53554 {
53555 @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);
53556
53557 return $this->getProgress();
53558 }
53559
53560
53561
53562
53563
53564
53565 public function getProgress()
53566 {
53567 return $this->step;
53568 }
53569
53570
53571
53572
53573
53574
53575
53576
53577 public function getStepWidth()
53578 {
53579 return $this->stepWidth;
53580 }
53581
53582
53583
53584
53585
53586
53587 public function getProgressPercent()
53588 {
53589 return $this->percent;
53590 }
53591
53592
53593
53594
53595
53596
53597 public function setBarWidth($size)
53598 {
53599 $this->barWidth = (int) $size;
53600 }
53601
53602
53603
53604
53605
53606
53607 public function getBarWidth()
53608 {
53609 return $this->barWidth;
53610 }
53611
53612
53613
53614
53615
53616
53617 public function setBarCharacter($char)
53618 {
53619 $this->barChar = $char;
53620 }
53621
53622
53623
53624
53625
53626
53627 public function getBarCharacter()
53628 {
53629 if (null === $this->barChar) {
53630 return $this->max ? '=' : $this->emptyBarChar;
53631 }
53632
53633 return $this->barChar;
53634 }
53635
53636
53637
53638
53639
53640
53641 public function setEmptyBarCharacter($char)
53642 {
53643 $this->emptyBarChar = $char;
53644 }
53645
53646
53647
53648
53649
53650
53651 public function getEmptyBarCharacter()
53652 {
53653 return $this->emptyBarChar;
53654 }
53655
53656
53657
53658
53659
53660
53661 public function setProgressCharacter($char)
53662 {
53663 $this->progressChar = $char;
53664 }
53665
53666
53667
53668
53669
53670
53671 public function getProgressCharacter()
53672 {
53673 return $this->progressChar;
53674 }
53675
53676
53677
53678
53679
53680
53681 public function setFormat($format)
53682 {
53683 $this->format = null;
53684 $this->internalFormat = $format;
53685 }
53686
53687
53688
53689
53690
53691
53692 public function setRedrawFrequency($freq)
53693 {
53694 $this->redrawFreq = max((int) $freq, 1);
53695 }
53696
53697
53698
53699
53700
53701
53702 public function start($max = null)
53703 {
53704 $this->startTime = time();
53705 $this->step = 0;
53706 $this->percent = 0.0;
53707
53708 if (null !== $max) {
53709 $this->setMaxSteps($max);
53710 }
53711
53712 $this->display();
53713 }
53714
53715
53716
53717
53718
53719
53720
53721
53722 public function advance($step = 1)
53723 {
53724 $this->setProgress($this->step + $step);
53725 }
53726
53727
53728
53729
53730
53731
53732
53733
53734
53735
53736 public function setCurrent($step)
53737 {
53738 @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);
53739
53740 $this->setProgress($step);
53741 }
53742
53743
53744
53745
53746
53747
53748 public function setOverwrite($overwrite)
53749 {
53750 $this->overwrite = (bool) $overwrite;
53751 }
53752
53753
53754
53755
53756
53757
53758
53759
53760 public function setProgress($step)
53761 {
53762 $step = (int) $step;
53763 if ($step < $this->step) {
53764 throw new LogicException('You can\'t regress the progress bar.');
53765 }
53766
53767 if ($this->max && $step > $this->max) {
53768 $this->max = $step;
53769 }
53770
53771 $prevPeriod = (int) ($this->step / $this->redrawFreq);
53772 $currPeriod = (int) ($step / $this->redrawFreq);
53773 $this->step = $step;
53774 $this->percent = $this->max ? (float) $this->step / $this->max : 0;
53775 if ($prevPeriod !== $currPeriod || $this->max === $step) {
53776 $this->display();
53777 }
53778 }
53779
53780
53781
53782
53783 public function finish()
53784 {
53785 if (!$this->max) {
53786 $this->max = $this->step;
53787 }
53788
53789 if ($this->step === $this->max && !$this->overwrite) {
53790
53791  return;
53792 }
53793
53794 $this->setProgress($this->max);
53795 }
53796
53797
53798
53799
53800 public function display()
53801 {
53802 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
53803 return;
53804 }
53805
53806 if (null === $this->format) {
53807 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
53808 }
53809
53810
53811  $self = $this;
53812 $output = $this->output;
53813 $messages = $this->messages;
53814 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
53815 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
53816 $text = call_user_func($formatter, $self, $output);
53817 } elseif (isset($messages[$matches[1]])) {
53818 $text = $messages[$matches[1]];
53819 } else {
53820 return $matches[0];
53821 }
53822
53823 if (isset($matches[2])) {
53824 $text = sprintf('%'.$matches[2], $text);
53825 }
53826
53827 return $text;
53828 }, $this->format));
53829 }
53830
53831
53832
53833
53834
53835
53836
53837
53838 public function clear()
53839 {
53840 if (!$this->overwrite) {
53841 return;
53842 }
53843
53844 if (null === $this->format) {
53845 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
53846 }
53847
53848 $this->overwrite('');
53849 }
53850
53851
53852
53853
53854
53855
53856 private function setRealFormat($format)
53857 {
53858
53859  if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
53860 $this->format = self::getFormatDefinition($format.'_nomax');
53861 } elseif (null !== self::getFormatDefinition($format)) {
53862 $this->format = self::getFormatDefinition($format);
53863 } else {
53864 $this->format = $format;
53865 }
53866
53867 $this->formatLineCount = substr_count($this->format, "\n");
53868 }
53869
53870
53871
53872
53873
53874
53875 private function setMaxSteps($max)
53876 {
53877 $this->max = max(0, (int) $max);
53878 $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
53879 }
53880
53881
53882
53883
53884
53885
53886 private function overwrite($message)
53887 {
53888 if ($this->overwrite) {
53889 if (!$this->firstRun) {
53890
53891  $this->output->write("\x0D");
53892
53893
53894  $this->output->write("\x1B[2K");
53895
53896
53897  if ($this->formatLineCount > 0) {
53898 $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
53899 }
53900 }
53901 } elseif ($this->step > 0) {
53902 $this->output->writeln('');
53903 }
53904
53905 $this->firstRun = false;
53906
53907 $this->output->write($message);
53908 }
53909
53910 private function determineBestFormat()
53911 {
53912 switch ($this->output->getVerbosity()) {
53913
53914  case OutputInterface::VERBOSITY_VERBOSE:
53915 return $this->max ? 'verbose' : 'verbose_nomax';
53916 case OutputInterface::VERBOSITY_VERY_VERBOSE:
53917 return $this->max ? 'very_verbose' : 'very_verbose_nomax';
53918 case OutputInterface::VERBOSITY_DEBUG:
53919 return $this->max ? 'debug' : 'debug_nomax';
53920 default:
53921 return $this->max ? 'normal' : 'normal_nomax';
53922 }
53923 }
53924
53925 private static function initPlaceholderFormatters()
53926 {
53927 return array(
53928 'bar' => function (ProgressBar $bar, OutputInterface $output) {
53929 $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
53930 $display = str_repeat($bar->getBarCharacter(), $completeBars);
53931 if ($completeBars < $bar->getBarWidth()) {
53932 $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
53933 $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
53934 }
53935
53936 return $display;
53937 },
53938 'elapsed' => function (ProgressBar $bar) {
53939 return Helper::formatTime(time() - $bar->getStartTime());
53940 },
53941 'remaining' => function (ProgressBar $bar) {
53942 if (!$bar->getMaxSteps()) {
53943 throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
53944 }
53945
53946 if (!$bar->getProgress()) {
53947 $remaining = 0;
53948 } else {
53949 $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
53950 }
53951
53952 return Helper::formatTime($remaining);
53953 },
53954 'estimated' => function (ProgressBar $bar) {
53955 if (!$bar->getMaxSteps()) {
53956 throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
53957 }
53958
53959 if (!$bar->getProgress()) {
53960 $estimated = 0;
53961 } else {
53962 $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
53963 }
53964
53965 return Helper::formatTime($estimated);
53966 },
53967 'memory' => function (ProgressBar $bar) {
53968 return Helper::formatMemory(memory_get_usage(true));
53969 },
53970 'current' => function (ProgressBar $bar) {
53971 return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
53972 },
53973 'max' => function (ProgressBar $bar) {
53974 return $bar->getMaxSteps();
53975 },
53976 'percent' => function (ProgressBar $bar) {
53977 return floor($bar->getProgressPercent() * 100);
53978 },
53979 );
53980 }
53981
53982 private static function initFormats()
53983 {
53984 return array(
53985 'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
53986 'normal_nomax' => ' %current% [%bar%]',
53987
53988 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
53989 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
53990
53991 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
53992 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
53993
53994 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
53995 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
53996 );
53997 }
53998 }
53999 <?php
54000
54001
54002
54003
54004
54005
54006
54007
54008
54009
54010 namespace Symfony\Component\Console\Helper;
54011
54012 use Symfony\Component\Console\Output\NullOutput;
54013 use Symfony\Component\Console\Output\ConsoleOutputInterface;
54014 use Symfony\Component\Console\Output\OutputInterface;
54015 use Symfony\Component\Console\Exception\LogicException;
54016
54017
54018
54019
54020
54021
54022
54023
54024
54025
54026 class ProgressHelper extends Helper
54027 {
54028 const FORMAT_QUIET = ' %percent%%';
54029 const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
54030 const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
54031 const FORMAT_QUIET_NOMAX = ' %current%';
54032 const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
54033 const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
54034
54035
54036  private $barWidth = 28;
54037 private $barChar = '=';
54038 private $emptyBarChar = '-';
54039 private $progressChar = '>';
54040 private $format = null;
54041 private $redrawFreq = 1;
54042
54043 private $lastMessagesLength;
54044 private $barCharOriginal;
54045
54046
54047
54048
54049 private $output;
54050
54051
54052
54053
54054
54055
54056 private $current;
54057
54058
54059
54060
54061
54062
54063 private $max;
54064
54065
54066
54067
54068
54069
54070 private $startTime;
54071
54072
54073
54074
54075
54076
54077 private $defaultFormatVars = array(
54078 'current',
54079 'max',
54080 'bar',
54081 'percent',
54082 'elapsed',
54083 );
54084
54085
54086
54087
54088
54089
54090 private $formatVars;
54091
54092
54093
54094
54095
54096
54097 private $widths = array(
54098 'current' => 4,
54099 'max' => 4,
54100 'percent' => 3,
54101 'elapsed' => 6,
54102 );
54103
54104
54105
54106
54107
54108
54109 private $timeFormats = array(
54110 array(0, '???'),
54111 array(2, '1 sec'),
54112 array(59, 'secs', 1),
54113 array(60, '1 min'),
54114 array(3600, 'mins', 60),
54115 array(5400, '1 hr'),
54116 array(86400, 'hrs', 3600),
54117 array(129600, '1 day'),
54118 array(604800, 'days', 86400),
54119 );
54120
54121 public function __construct($triggerDeprecationError = true)
54122 {
54123 if ($triggerDeprecationError) {
54124 @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);
54125 }
54126 }
54127
54128
54129
54130
54131
54132
54133 public function setBarWidth($size)
54134 {
54135 $this->barWidth = (int) $size;
54136 }
54137
54138
54139
54140
54141
54142
54143 public function setBarCharacter($char)
54144 {
54145 $this->barChar = $char;
54146 }
54147
54148
54149
54150
54151
54152
54153 public function setEmptyBarCharacter($char)
54154 {
54155 $this->emptyBarChar = $char;
54156 }
54157
54158
54159
54160
54161
54162
54163 public function setProgressCharacter($char)
54164 {
54165 $this->progressChar = $char;
54166 }
54167
54168
54169
54170
54171
54172
54173 public function setFormat($format)
54174 {
54175 $this->format = $format;
54176 }
54177
54178
54179
54180
54181
54182
54183 public function setRedrawFrequency($freq)
54184 {
54185 $this->redrawFreq = (int) $freq;
54186 }
54187
54188
54189
54190
54191
54192
54193
54194 public function start(OutputInterface $output, $max = null)
54195 {
54196 if ($output instanceof ConsoleOutputInterface) {
54197 $output = $output->getErrorOutput();
54198 }
54199
54200 $this->startTime = time();
54201 $this->current = 0;
54202 $this->max = (int) $max;
54203
54204
54205  $this->output = $output->isDecorated() ? $output : new NullOutput();
54206 $this->lastMessagesLength = 0;
54207 $this->barCharOriginal = '';
54208
54209 if (null === $this->format) {
54210 switch ($output->getVerbosity()) {
54211 case OutputInterface::VERBOSITY_QUIET:
54212 $this->format = self::FORMAT_QUIET_NOMAX;
54213 if ($this->max > 0) {
54214 $this->format = self::FORMAT_QUIET;
54215 }
54216 break;
54217 case OutputInterface::VERBOSITY_VERBOSE:
54218 case OutputInterface::VERBOSITY_VERY_VERBOSE:
54219 case OutputInterface::VERBOSITY_DEBUG:
54220 $this->format = self::FORMAT_VERBOSE_NOMAX;
54221 if ($this->max > 0) {
54222 $this->format = self::FORMAT_VERBOSE;
54223 }
54224 break;
54225 default:
54226 $this->format = self::FORMAT_NORMAL_NOMAX;
54227 if ($this->max > 0) {
54228 $this->format = self::FORMAT_NORMAL;
54229 }
54230 break;
54231 }
54232 }
54233
54234 $this->initialize();
54235 }
54236
54237
54238
54239
54240
54241
54242
54243
54244
54245 public function advance($step = 1, $redraw = false)
54246 {
54247 $this->setCurrent($this->current + $step, $redraw);
54248 }
54249
54250
54251
54252
54253
54254
54255
54256
54257
54258 public function setCurrent($current, $redraw = false)
54259 {
54260 if (null === $this->startTime) {
54261 throw new LogicException('You must start the progress bar before calling setCurrent().');
54262 }
54263
54264 $current = (int) $current;
54265
54266 if ($current < $this->current) {
54267 throw new LogicException('You can\'t regress the progress bar');
54268 }
54269
54270 if (0 === $this->current) {
54271 $redraw = true;
54272 }
54273
54274 $prevPeriod = (int) ($this->current / $this->redrawFreq);
54275
54276 $this->current = $current;
54277
54278 $currPeriod = (int) ($this->current / $this->redrawFreq);
54279 if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
54280 $this->display();
54281 }
54282 }
54283
54284
54285
54286
54287
54288
54289
54290
54291 public function display($finish = false)
54292 {
54293 if (null === $this->startTime) {
54294 throw new LogicException('You must start the progress bar before calling display().');
54295 }
54296
54297 $message = $this->format;
54298 foreach ($this->generate($finish) as $name => $value) {
54299 $message = str_replace("%{$name}%", $value, $message);
54300 }
54301 $this->overwrite($this->output, $message);
54302 }
54303
54304
54305
54306
54307
54308
54309
54310
54311 public function clear()
54312 {
54313 $this->overwrite($this->output, '');
54314 }
54315
54316
54317
54318
54319 public function finish()
54320 {
54321 if (null === $this->startTime) {
54322 throw new LogicException('You must start the progress bar before calling finish().');
54323 }
54324
54325 if (null !== $this->startTime) {
54326 if (!$this->max) {
54327 $this->barChar = $this->barCharOriginal;
54328 $this->display(true);
54329 }
54330 $this->startTime = null;
54331 $this->output->writeln('');
54332 $this->output = null;
54333 }
54334 }
54335
54336
54337
54338
54339 private function initialize()
54340 {
54341 $this->formatVars = array();
54342 foreach ($this->defaultFormatVars as $var) {
54343 if (false !== strpos($this->format, "%{$var}%")) {
54344 $this->formatVars[$var] = true;
54345 }
54346 }
54347
54348 if ($this->max > 0) {
54349 $this->widths['max'] = $this->strlen($this->max);
54350 $this->widths['current'] = $this->widths['max'];
54351 } else {
54352 $this->barCharOriginal = $this->barChar;
54353 $this->barChar = $this->emptyBarChar;
54354 }
54355 }
54356
54357
54358
54359
54360
54361
54362
54363
54364 private function generate($finish = false)
54365 {
54366 $vars = array();
54367 $percent = 0;
54368 if ($this->max > 0) {
54369 $percent = (float) $this->current / $this->max;
54370 }
54371
54372 if (isset($this->formatVars['bar'])) {
54373 if ($this->max > 0) {
54374 $completeBars = floor($percent * $this->barWidth);
54375 } else {
54376 if (!$finish) {
54377 $completeBars = floor($this->current % $this->barWidth);
54378 } else {
54379 $completeBars = $this->barWidth;
54380 }
54381 }
54382
54383 $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
54384 $bar = str_repeat($this->barChar, $completeBars);
54385 if ($completeBars < $this->barWidth) {
54386 $bar .= $this->progressChar;
54387 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
54388 }
54389
54390 $vars['bar'] = $bar;
54391 }
54392
54393 if (isset($this->formatVars['elapsed'])) {
54394 $elapsed = time() - $this->startTime;
54395 $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
54396 }
54397
54398 if (isset($this->formatVars['current'])) {
54399 $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
54400 }
54401
54402 if (isset($this->formatVars['max'])) {
54403 $vars['max'] = $this->max;
54404 }
54405
54406 if (isset($this->formatVars['percent'])) {
54407 $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
54408 }
54409
54410 return $vars;
54411 }
54412
54413
54414
54415
54416
54417
54418
54419
54420 private function humaneTime($secs)
54421 {
54422 $text = '';
54423 foreach ($this->timeFormats as $format) {
54424 if ($secs < $format[0]) {
54425 if (2 == count($format)) {
54426 $text = $format[1];
54427 break;
54428 } else {
54429 $text = ceil($secs / $format[2]).' '.$format[1];
54430 break;
54431 }
54432 }
54433 }
54434
54435 return $text;
54436 }
54437
54438
54439
54440
54441
54442
54443
54444 private function overwrite(OutputInterface $output, $message)
54445 {
54446 $length = $this->strlen($message);
54447
54448
54449  if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
54450 $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
54451 }
54452
54453
54454  $output->write("\x0D");
54455 $output->write($message);
54456
54457 $this->lastMessagesLength = $this->strlen($message);
54458 }
54459
54460
54461
54462
54463 public function getName()
54464 {
54465 return 'progress';
54466 }
54467 }
54468 <?php
54469
54470
54471
54472
54473
54474
54475
54476
54477
54478
54479 namespace Symfony\Component\Console\Helper;
54480
54481 use Symfony\Component\Console\Exception\InvalidArgumentException;
54482 use Symfony\Component\Console\Exception\LogicException;
54483 use Symfony\Component\Console\Output\OutputInterface;
54484
54485
54486
54487
54488 class ProgressIndicator
54489 {
54490 private $output;
54491 private $startTime;
54492 private $format;
54493 private $message;
54494 private $indicatorValues;
54495 private $indicatorCurrent;
54496 private $indicatorChangeInterval;
54497 private $indicatorUpdateTime;
54498 private $started = false;
54499
54500 private static $formatters;
54501 private static $formats;
54502
54503
54504
54505
54506
54507
54508
54509 public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
54510 {
54511 $this->output = $output;
54512
54513 if (null === $format) {
54514 $format = $this->determineBestFormat();
54515 }
54516
54517 if (null === $indicatorValues) {
54518 $indicatorValues = array('-', '\\', '|', '/');
54519 }
54520
54521 $indicatorValues = array_values($indicatorValues);
54522
54523 if (2 > count($indicatorValues)) {
54524 throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
54525 }
54526
54527 $this->format = self::getFormatDefinition($format);
54528 $this->indicatorChangeInterval = $indicatorChangeInterval;
54529 $this->indicatorValues = $indicatorValues;
54530 $this->startTime = time();
54531 }
54532
54533
54534
54535
54536
54537
54538 public function setMessage($message)
54539 {
54540 $this->message = $message;
54541
54542 $this->display();
54543 }
54544
54545
54546
54547
54548
54549
54550
54551
54552 public function getMessage()
54553 {
54554 return $this->message;
54555 }
54556
54557
54558
54559
54560
54561
54562
54563
54564 public function getStartTime()
54565 {
54566 return $this->startTime;
54567 }
54568
54569
54570
54571
54572
54573
54574
54575
54576 public function getCurrentValue()
54577 {
54578 return $this->indicatorValues[$this->indicatorCurrent % count($this->indicatorValues)];
54579 }
54580
54581
54582
54583
54584
54585
54586 public function start($message)
54587 {
54588 if ($this->started) {
54589 throw new LogicException('Progress indicator already started.');
54590 }
54591
54592 $this->message = $message;
54593 $this->started = true;
54594 $this->startTime = time();
54595 $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
54596 $this->indicatorCurrent = 0;
54597
54598 $this->display();
54599 }
54600
54601
54602
54603
54604 public function advance()
54605 {
54606 if (!$this->started) {
54607 throw new LogicException('Progress indicator has not yet been started.');
54608 }
54609
54610 if (!$this->output->isDecorated()) {
54611 return;
54612 }
54613
54614 $currentTime = $this->getCurrentTimeInMilliseconds();
54615
54616 if ($currentTime < $this->indicatorUpdateTime) {
54617 return;
54618 }
54619
54620 $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
54621 ++$this->indicatorCurrent;
54622
54623 $this->display();
54624 }
54625
54626
54627
54628
54629
54630
54631 public function finish($message)
54632 {
54633 if (!$this->started) {
54634 throw new LogicException('Progress indicator has not yet been started.');
54635 }
54636
54637 $this->message = $message;
54638 $this->display();
54639 $this->output->writeln('');
54640 $this->started = false;
54641 }
54642
54643
54644
54645
54646
54647
54648
54649
54650 public static function getFormatDefinition($name)
54651 {
54652 if (!self::$formats) {
54653 self::$formats = self::initFormats();
54654 }
54655
54656 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
54657 }
54658
54659
54660
54661
54662
54663
54664
54665
54666
54667 public static function setPlaceholderFormatterDefinition($name, $callable)
54668 {
54669 if (!self::$formatters) {
54670 self::$formatters = self::initPlaceholderFormatters();
54671 }
54672
54673 self::$formatters[$name] = $callable;
54674 }
54675
54676
54677
54678
54679
54680
54681
54682
54683 public static function getPlaceholderFormatterDefinition($name)
54684 {
54685 if (!self::$formatters) {
54686 self::$formatters = self::initPlaceholderFormatters();
54687 }
54688
54689 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
54690 }
54691
54692 private function display()
54693 {
54694 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
54695 return;
54696 }
54697
54698 $self = $this;
54699
54700 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
54701 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
54702 return call_user_func($formatter, $self);
54703 }
54704
54705 return $matches[0];
54706 }, $this->format));
54707 }
54708
54709 private function determineBestFormat()
54710 {
54711 switch ($this->output->getVerbosity()) {
54712
54713  case OutputInterface::VERBOSITY_VERBOSE:
54714 return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
54715 case OutputInterface::VERBOSITY_VERY_VERBOSE:
54716 case OutputInterface::VERBOSITY_DEBUG:
54717 return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
54718 default:
54719 return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
54720 }
54721 }
54722
54723
54724
54725
54726
54727
54728 private function overwrite($message)
54729 {
54730 if ($this->output->isDecorated()) {
54731 $this->output->write("\x0D\x1B[2K");
54732 $this->output->write($message);
54733 } else {
54734 $this->output->writeln($message);
54735 }
54736 }
54737
54738 private function getCurrentTimeInMilliseconds()
54739 {
54740 return round(microtime(true) * 1000);
54741 }
54742
54743 private static function initPlaceholderFormatters()
54744 {
54745 return array(
54746 'indicator' => function (ProgressIndicator $indicator) {
54747 return $indicator->getCurrentValue();
54748 },
54749 'message' => function (ProgressIndicator $indicator) {
54750 return $indicator->getMessage();
54751 },
54752 'elapsed' => function (ProgressIndicator $indicator) {
54753 return Helper::formatTime(time() - $indicator->getStartTime());
54754 },
54755 'memory' => function () {
54756 return Helper::formatMemory(memory_get_usage(true));
54757 },
54758 );
54759 }
54760
54761 private static function initFormats()
54762 {
54763 return array(
54764 'normal' => ' %indicator% %message%',
54765 'normal_no_ansi' => ' %message%',
54766
54767 'verbose' => ' %indicator% %message% (%elapsed:6s%)',
54768 'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
54769
54770 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
54771 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
54772 );
54773 }
54774 }
54775 <?php
54776
54777
54778
54779
54780
54781
54782
54783
54784
54785
54786 namespace Symfony\Component\Console\Helper;
54787
54788 use Symfony\Component\Console\Exception\InvalidArgumentException;
54789 use Symfony\Component\Console\Exception\RuntimeException;
54790 use Symfony\Component\Console\Formatter\OutputFormatter;
54791 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
54792 use Symfony\Component\Console\Input\InputInterface;
54793 use Symfony\Component\Console\Output\ConsoleOutputInterface;
54794 use Symfony\Component\Console\Output\OutputInterface;
54795 use Symfony\Component\Console\Question\Question;
54796 use Symfony\Component\Console\Question\ChoiceQuestion;
54797
54798
54799
54800
54801
54802
54803 class QuestionHelper extends Helper
54804 {
54805 private $inputStream;
54806 private static $shell;
54807 private static $stty;
54808
54809
54810
54811
54812
54813
54814
54815
54816 public function ask(InputInterface $input, OutputInterface $output, Question $question)
54817 {
54818 if ($output instanceof ConsoleOutputInterface) {
54819 $output = $output->getErrorOutput();
54820 }
54821
54822 if (!$input->isInteractive()) {
54823 return $question->getDefault();
54824 }
54825
54826 if (!$question->getValidator()) {
54827 return $this->doAsk($output, $question);
54828 }
54829
54830 $that = $this;
54831
54832 $interviewer = function () use ($output, $question, $that) {
54833 return $that->doAsk($output, $question);
54834 };
54835
54836 return $this->validateAttempts($interviewer, $output, $question);
54837 }
54838
54839
54840
54841
54842
54843
54844
54845
54846
54847
54848 public function setInputStream($stream)
54849 {
54850 if (!is_resource($stream)) {
54851 throw new InvalidArgumentException('Input stream must be a valid resource.');
54852 }
54853
54854 $this->inputStream = $stream;
54855 }
54856
54857
54858
54859
54860
54861
54862 public function getInputStream()
54863 {
54864 return $this->inputStream;
54865 }
54866
54867
54868
54869
54870 public function getName()
54871 {
54872 return 'question';
54873 }
54874
54875
54876
54877
54878
54879
54880
54881
54882
54883
54884 public function doAsk(OutputInterface $output, Question $question)
54885 {
54886 $this->writePrompt($output, $question);
54887
54888 $inputStream = $this->inputStream ?: STDIN;
54889 $autocomplete = $question->getAutocompleterValues();
54890
54891 if (null === $autocomplete || !$this->hasSttyAvailable()) {
54892 $ret = false;
54893 if ($question->isHidden()) {
54894 try {
54895 $ret = trim($this->getHiddenResponse($output, $inputStream));
54896 } catch (RuntimeException $e) {
54897 if (!$question->isHiddenFallback()) {
54898 throw $e;
54899 }
54900 }
54901 }
54902
54903 if (false === $ret) {
54904 $ret = fgets($inputStream, 4096);
54905 if (false === $ret) {
54906 throw new RuntimeException('Aborted');
54907 }
54908 $ret = trim($ret);
54909 }
54910 } else {
54911 $ret = trim($this->autocomplete($output, $question, $inputStream, is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
54912 }
54913
54914 $ret = strlen($ret) > 0 ? $ret : $question->getDefault();
54915
54916 if ($normalizer = $question->getNormalizer()) {
54917 return $normalizer($ret);
54918 }
54919
54920 return $ret;
54921 }
54922
54923
54924
54925
54926 protected function writePrompt(OutputInterface $output, Question $question)
54927 {
54928 $message = $question->getQuestion();
54929
54930 if ($question instanceof ChoiceQuestion) {
54931 $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
54932
54933 $messages = (array) $question->getQuestion();
54934 foreach ($question->getChoices() as $key => $value) {
54935 $width = $maxWidth - $this->strlen($key);
54936 $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
54937 }
54938
54939 $output->writeln($messages);
54940
54941 $message = $question->getPrompt();
54942 }
54943
54944 $output->write($message);
54945 }
54946
54947
54948
54949
54950 protected function writeError(OutputInterface $output, \Exception $error)
54951 {
54952 if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
54953 $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
54954 } else {
54955 $message = '<error>'.$error->getMessage().'</error>';
54956 }
54957
54958 $output->writeln($message);
54959 }
54960
54961
54962
54963
54964
54965
54966
54967
54968
54969
54970
54971 private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete)
54972 {
54973 $ret = '';
54974
54975 $i = 0;
54976 $ofs = -1;
54977 $matches = $autocomplete;
54978 $numMatches = count($matches);
54979
54980 $sttyMode = shell_exec('stty -g');
54981
54982
54983  shell_exec('stty -icanon -echo');
54984
54985
54986  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
54987
54988
54989  while (!feof($inputStream)) {
54990 $c = fread($inputStream, 1);
54991
54992
54993  if ("\177" === $c) {
54994 if (0 === $numMatches && 0 !== $i) {
54995 --$i;
54996
54997  $output->write("\033[1D");
54998 }
54999
55000 if (0 === $i) {
55001 $ofs = -1;
55002 $matches = $autocomplete;
55003 $numMatches = count($matches);
55004 } else {
55005 $numMatches = 0;
55006 }
55007
55008
55009  $ret = substr($ret, 0, $i);
55010 } elseif ("\033" === $c) {
55011
55012  $c .= fread($inputStream, 2);
55013
55014
55015  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
55016 if ('A' === $c[2] && -1 === $ofs) {
55017 $ofs = 0;
55018 }
55019
55020 if (0 === $numMatches) {
55021 continue;
55022 }
55023
55024 $ofs += ('A' === $c[2]) ? -1 : 1;
55025 $ofs = ($numMatches + $ofs) % $numMatches;
55026 }
55027 } elseif (ord($c) < 32) {
55028 if ("\t" === $c || "\n" === $c) {
55029 if ($numMatches > 0 && -1 !== $ofs) {
55030 $ret = $matches[$ofs];
55031
55032  $output->write(substr($ret, $i));
55033 $i = strlen($ret);
55034 }
55035
55036 if ("\n" === $c) {
55037 $output->write($c);
55038 break;
55039 }
55040
55041 $numMatches = 0;
55042 }
55043
55044 continue;
55045 } else {
55046 $output->write($c);
55047 $ret .= $c;
55048 ++$i;
55049
55050 $numMatches = 0;
55051 $ofs = 0;
55052
55053 foreach ($autocomplete as $value) {
55054
55055  if (0 === strpos($value, $ret) && $i !== strlen($value)) {
55056 $matches[$numMatches++] = $value;
55057 }
55058 }
55059 }
55060
55061
55062  $output->write("\033[K");
55063
55064 if ($numMatches > 0 && -1 !== $ofs) {
55065
55066  $output->write("\0337");
55067
55068  $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>');
55069
55070  $output->write("\0338");
55071 }
55072 }
55073
55074
55075  shell_exec(sprintf('stty %s', $sttyMode));
55076
55077 return $ret;
55078 }
55079
55080
55081
55082
55083
55084
55085
55086
55087
55088
55089
55090 private function getHiddenResponse(OutputInterface $output, $inputStream)
55091 {
55092 if ('\\' === DIRECTORY_SEPARATOR) {
55093 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
55094
55095
55096  if ('phar:' === substr(__FILE__, 0, 5)) {
55097 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
55098 copy($exe, $tmpExe);
55099 $exe = $tmpExe;
55100 }
55101
55102 $value = rtrim(shell_exec($exe));
55103 $output->writeln('');
55104
55105 if (isset($tmpExe)) {
55106 unlink($tmpExe);
55107 }
55108
55109 return $value;
55110 }
55111
55112 if ($this->hasSttyAvailable()) {
55113 $sttyMode = shell_exec('stty -g');
55114
55115 shell_exec('stty -echo');
55116 $value = fgets($inputStream, 4096);
55117 shell_exec(sprintf('stty %s', $sttyMode));
55118
55119 if (false === $value) {
55120 throw new RuntimeException('Aborted');
55121 }
55122
55123 $value = trim($value);
55124 $output->writeln('');
55125
55126 return $value;
55127 }
55128
55129 if (false !== $shell = $this->getShell()) {
55130 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
55131 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
55132 $value = rtrim(shell_exec($command));
55133 $output->writeln('');
55134
55135 return $value;
55136 }
55137
55138 throw new RuntimeException('Unable to hide the response.');
55139 }
55140
55141
55142
55143
55144
55145
55146
55147
55148
55149
55150
55151
55152 private function validateAttempts($interviewer, OutputInterface $output, Question $question)
55153 {
55154 $error = null;
55155 $attempts = $question->getMaxAttempts();
55156 while (null === $attempts || $attempts--) {
55157 if (null !== $error) {
55158 $this->writeError($output, $error);
55159 }
55160
55161 try {
55162 return call_user_func($question->getValidator(), $interviewer());
55163 } catch (RuntimeException $e) {
55164 throw $e;
55165 } catch (\Exception $error) {
55166 }
55167 }
55168
55169 throw $error;
55170 }
55171
55172
55173
55174
55175
55176
55177 private function getShell()
55178 {
55179 if (null !== self::$shell) {
55180 return self::$shell;
55181 }
55182
55183 self::$shell = false;
55184
55185 if (file_exists('/usr/bin/env')) {
55186
55187  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
55188 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
55189 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
55190 self::$shell = $sh;
55191 break;
55192 }
55193 }
55194 }
55195
55196 return self::$shell;
55197 }
55198
55199
55200
55201
55202
55203
55204 private function hasSttyAvailable()
55205 {
55206 if (null !== self::$stty) {
55207 return self::$stty;
55208 }
55209
55210 exec('stty 2>&1', $output, $exitcode);
55211
55212 return self::$stty = 0 === $exitcode;
55213 }
55214 }
55215 <?php
55216
55217
55218
55219
55220
55221
55222
55223
55224
55225
55226 namespace Symfony\Component\Console\Helper;
55227
55228 use Symfony\Component\Console\Exception\LogicException;
55229 use Symfony\Component\Console\Input\InputInterface;
55230 use Symfony\Component\Console\Output\OutputInterface;
55231 use Symfony\Component\Console\Question\ChoiceQuestion;
55232 use Symfony\Component\Console\Question\ConfirmationQuestion;
55233 use Symfony\Component\Console\Question\Question;
55234 use Symfony\Component\Console\Style\SymfonyStyle;
55235 use Symfony\Component\Console\Formatter\OutputFormatter;
55236
55237
55238
55239
55240
55241
55242 class SymfonyQuestionHelper extends QuestionHelper
55243 {
55244
55245
55246
55247 public function ask(InputInterface $input, OutputInterface $output, Question $question)
55248 {
55249 $validator = $question->getValidator();
55250 $question->setValidator(function ($value) use ($validator) {
55251 if (null !== $validator) {
55252 $value = $validator($value);
55253 } else {
55254
55255  if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
55256 throw new LogicException('A value is required.');
55257 }
55258 }
55259
55260 return $value;
55261 });
55262
55263 return parent::ask($input, $output, $question);
55264 }
55265
55266
55267
55268
55269 protected function writePrompt(OutputInterface $output, Question $question)
55270 {
55271 $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
55272 $default = $question->getDefault();
55273
55274 switch (true) {
55275 case null === $default:
55276 $text = sprintf(' <info>%s</info>:', $text);
55277
55278 break;
55279
55280 case $question instanceof ConfirmationQuestion:
55281 $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
55282
55283 break;
55284
55285 case $question instanceof ChoiceQuestion && $question->isMultiselect():
55286 $choices = $question->getChoices();
55287 $default = explode(',', $default);
55288
55289 foreach ($default as $key => $value) {
55290 $default[$key] = $choices[trim($value)];
55291 }
55292
55293 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
55294
55295 break;
55296
55297 case $question instanceof ChoiceQuestion:
55298 $choices = $question->getChoices();
55299 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default]));
55300
55301 break;
55302
55303 default:
55304 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
55305 }
55306
55307 $output->writeln($text);
55308
55309 if ($question instanceof ChoiceQuestion) {
55310 $width = max(array_map('strlen', array_keys($question->getChoices())));
55311
55312 foreach ($question->getChoices() as $key => $value) {
55313 $output->writeln(sprintf("  [<comment>%-${width}s</comment>] %s", $key, $value));
55314 }
55315 }
55316
55317 $output->write(' > ');
55318 }
55319
55320
55321
55322
55323 protected function writeError(OutputInterface $output, \Exception $error)
55324 {
55325 if ($output instanceof SymfonyStyle) {
55326 $output->newLine();
55327 $output->error($error->getMessage());
55328
55329 return;
55330 }
55331
55332 parent::writeError($output, $error);
55333 }
55334 }
55335 <?php
55336
55337
55338
55339
55340
55341
55342
55343
55344
55345
55346 namespace Symfony\Component\Console\Helper;
55347
55348 use Symfony\Component\Console\Output\OutputInterface;
55349 use Symfony\Component\Console\Exception\InvalidArgumentException;
55350
55351
55352
55353
55354
55355
55356
55357
55358
55359 class Table
55360 {
55361
55362
55363
55364 private $headers = array();
55365
55366
55367
55368
55369 private $rows = array();
55370
55371
55372
55373
55374 private $columnWidths = array();
55375
55376
55377
55378
55379
55380
55381 private $numberOfColumns;
55382
55383
55384
55385
55386 private $output;
55387
55388
55389
55390
55391 private $style;
55392
55393
55394
55395
55396 private $columnStyles = array();
55397
55398 private static $styles;
55399
55400 public function __construct(OutputInterface $output)
55401 {
55402 $this->output = $output;
55403
55404 if (!self::$styles) {
55405 self::$styles = self::initStyles();
55406 }
55407
55408 $this->setStyle('default');
55409 }
55410
55411
55412
55413
55414
55415
55416
55417 public static function setStyleDefinition($name, TableStyle $style)
55418 {
55419 if (!self::$styles) {
55420 self::$styles = self::initStyles();
55421 }
55422
55423 self::$styles[$name] = $style;
55424 }
55425
55426
55427
55428
55429
55430
55431
55432
55433 public static function getStyleDefinition($name)
55434 {
55435 if (!self::$styles) {
55436 self::$styles = self::initStyles();
55437 }
55438
55439 if (isset(self::$styles[$name])) {
55440 return self::$styles[$name];
55441 }
55442
55443 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
55444 }
55445
55446
55447
55448
55449
55450
55451
55452
55453 public function setStyle($name)
55454 {
55455 $this->style = $this->resolveStyle($name);
55456
55457 return $this;
55458 }
55459
55460
55461
55462
55463
55464
55465 public function getStyle()
55466 {
55467 return $this->style;
55468 }
55469
55470
55471
55472
55473
55474
55475
55476
55477
55478 public function setColumnStyle($columnIndex, $name)
55479 {
55480 $columnIndex = (int) $columnIndex;
55481
55482 $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
55483
55484 return $this;
55485 }
55486
55487
55488
55489
55490
55491
55492
55493
55494
55495
55496 public function getColumnStyle($columnIndex)
55497 {
55498 if (isset($this->columnStyles[$columnIndex])) {
55499 return $this->columnStyles[$columnIndex];
55500 }
55501
55502 return $this->getStyle();
55503 }
55504
55505 public function setHeaders(array $headers)
55506 {
55507 $headers = array_values($headers);
55508 if (!empty($headers) && !is_array($headers[0])) {
55509 $headers = array($headers);
55510 }
55511
55512 $this->headers = $headers;
55513
55514 return $this;
55515 }
55516
55517 public function setRows(array $rows)
55518 {
55519 $this->rows = array();
55520
55521 return $this->addRows($rows);
55522 }
55523
55524 public function addRows(array $rows)
55525 {
55526 foreach ($rows as $row) {
55527 $this->addRow($row);
55528 }
55529
55530 return $this;
55531 }
55532
55533 public function addRow($row)
55534 {
55535 if ($row instanceof TableSeparator) {
55536 $this->rows[] = $row;
55537
55538 return $this;
55539 }
55540
55541 if (!is_array($row)) {
55542 throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
55543 }
55544
55545 $this->rows[] = array_values($row);
55546
55547 return $this;
55548 }
55549
55550 public function setRow($column, array $row)
55551 {
55552 $this->rows[$column] = $row;
55553
55554 return $this;
55555 }
55556
55557
55558
55559
55560
55561
55562
55563
55564
55565
55566
55567
55568
55569 public function render()
55570 {
55571 $this->calculateNumberOfColumns();
55572 $rows = $this->buildTableRows($this->rows);
55573 $headers = $this->buildTableRows($this->headers);
55574
55575 $this->calculateColumnsWidth(array_merge($headers, $rows));
55576
55577 $this->renderRowSeparator();
55578 if (!empty($headers)) {
55579 foreach ($headers as $header) {
55580 $this->renderRow($header, $this->style->getCellHeaderFormat());
55581 $this->renderRowSeparator();
55582 }
55583 }
55584 foreach ($rows as $row) {
55585 if ($row instanceof TableSeparator) {
55586 $this->renderRowSeparator();
55587 } else {
55588 $this->renderRow($row, $this->style->getCellRowFormat());
55589 }
55590 }
55591 if (!empty($rows)) {
55592 $this->renderRowSeparator();
55593 }
55594
55595 $this->cleanup();
55596 }
55597
55598
55599
55600
55601
55602
55603 private function renderRowSeparator()
55604 {
55605 if (0 === $count = $this->numberOfColumns) {
55606 return;
55607 }
55608
55609 if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
55610 return;
55611 }
55612
55613 $markup = $this->style->getCrossingChar();
55614 for ($column = 0; $column < $count; ++$column) {
55615 $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
55616 }
55617
55618 $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
55619 }
55620
55621
55622
55623
55624 private function renderColumnSeparator()
55625 {
55626 return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
55627 }
55628
55629
55630
55631
55632
55633
55634
55635
55636
55637 private function renderRow(array $row, $cellFormat)
55638 {
55639 if (empty($row)) {
55640 return;
55641 }
55642
55643 $rowContent = $this->renderColumnSeparator();
55644 foreach ($this->getRowColumns($row) as $column) {
55645 $rowContent .= $this->renderCell($row, $column, $cellFormat);
55646 $rowContent .= $this->renderColumnSeparator();
55647 }
55648 $this->output->writeln($rowContent);
55649 }
55650
55651
55652
55653
55654
55655
55656
55657
55658 private function renderCell(array $row, $column, $cellFormat)
55659 {
55660 $cell = isset($row[$column]) ? $row[$column] : '';
55661 $width = $this->columnWidths[$column];
55662 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
55663
55664  foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
55665 $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
55666 }
55667 }
55668
55669
55670  if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
55671 $width += strlen($cell) - mb_strwidth($cell, $encoding);
55672 }
55673
55674 $style = $this->getColumnStyle($column);
55675
55676 if ($cell instanceof TableSeparator) {
55677 return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
55678 }
55679
55680 $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
55681 $content = sprintf($style->getCellRowContentFormat(), $cell);
55682
55683 return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
55684 }
55685
55686
55687
55688
55689 private function calculateNumberOfColumns()
55690 {
55691 if (null !== $this->numberOfColumns) {
55692 return;
55693 }
55694
55695 $columns = array(0);
55696 foreach (array_merge($this->headers, $this->rows) as $row) {
55697 if ($row instanceof TableSeparator) {
55698 continue;
55699 }
55700
55701 $columns[] = $this->getNumberOfColumns($row);
55702 }
55703
55704 $this->numberOfColumns = max($columns);
55705 }
55706
55707 private function buildTableRows($rows)
55708 {
55709 $unmergedRows = array();
55710 for ($rowKey = 0; $rowKey < count($rows); ++$rowKey) {
55711 $rows = $this->fillNextRows($rows, $rowKey);
55712
55713
55714  foreach ($rows[$rowKey] as $column => $cell) {
55715 if (!strstr($cell, "\n")) {
55716 continue;
55717 }
55718 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
55719 foreach ($lines as $lineKey => $line) {
55720 if ($cell instanceof TableCell) {
55721 $line = new TableCell($line, array('colspan' => $cell->getColspan()));
55722 }
55723 if (0 === $lineKey) {
55724 $rows[$rowKey][$column] = $line;
55725 } else {
55726 $unmergedRows[$rowKey][$lineKey][$column] = $line;
55727 }
55728 }
55729 }
55730 }
55731
55732 $tableRows = array();
55733 foreach ($rows as $rowKey => $row) {
55734 $tableRows[] = $this->fillCells($row);
55735 if (isset($unmergedRows[$rowKey])) {
55736 $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
55737 }
55738 }
55739
55740 return $tableRows;
55741 }
55742
55743
55744
55745
55746
55747
55748
55749
55750
55751 private function fillNextRows(array $rows, $line)
55752 {
55753 $unmergedRows = array();
55754 foreach ($rows[$line] as $column => $cell) {
55755 if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
55756 $nbLines = $cell->getRowspan() - 1;
55757 $lines = array($cell);
55758 if (strstr($cell, "\n")) {
55759 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
55760 $nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
55761
55762 $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
55763 unset($lines[0]);
55764 }
55765
55766
55767  $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
55768 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
55769 $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
55770 $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
55771 if ($nbLines === $unmergedRowKey - $line) {
55772 break;
55773 }
55774 }
55775 }
55776 }
55777
55778 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
55779
55780  if (isset($rows[$unmergedRowKey]) && is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
55781 foreach ($unmergedRow as $cellKey => $cell) {
55782
55783  array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
55784 }
55785 } else {
55786 $row = $this->copyRow($rows, $unmergedRowKey - 1);
55787 foreach ($unmergedRow as $column => $cell) {
55788 if (!empty($cell)) {
55789 $row[$column] = $unmergedRow[$column];
55790 }
55791 }
55792 array_splice($rows, $unmergedRowKey, 0, array($row));
55793 }
55794 }
55795
55796 return $rows;
55797 }
55798
55799
55800
55801
55802
55803
55804 private function fillCells($row)
55805 {
55806 $newRow = array();
55807 foreach ($row as $column => $cell) {
55808 $newRow[] = $cell;
55809 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
55810 foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
55811
55812  $newRow[] = '';
55813 }
55814 }
55815 }
55816
55817 return $newRow ?: $row;
55818 }
55819
55820
55821
55822
55823
55824
55825
55826 private function copyRow(array $rows, $line)
55827 {
55828 $row = $rows[$line];
55829 foreach ($row as $cellKey => $cellValue) {
55830 $row[$cellKey] = '';
55831 if ($cellValue instanceof TableCell) {
55832 $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
55833 }
55834 }
55835
55836 return $row;
55837 }
55838
55839
55840
55841
55842
55843
55844 private function getNumberOfColumns(array $row)
55845 {
55846 $columns = count($row);
55847 foreach ($row as $column) {
55848 $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
55849 }
55850
55851 return $columns;
55852 }
55853
55854
55855
55856
55857
55858
55859 private function getRowColumns(array $row)
55860 {
55861 $columns = range(0, $this->numberOfColumns - 1);
55862 foreach ($row as $cellKey => $cell) {
55863 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
55864
55865  $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
55866 }
55867 }
55868
55869 return $columns;
55870 }
55871
55872
55873
55874
55875
55876
55877 private function calculateColumnsWidth($rows)
55878 {
55879 for ($column = 0; $column < $this->numberOfColumns; ++$column) {
55880 $lengths = array();
55881 foreach ($rows as $row) {
55882 if ($row instanceof TableSeparator) {
55883 continue;
55884 }
55885
55886 foreach ($row as $i => $cell) {
55887 if ($cell instanceof TableCell) {
55888 $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
55889 $textLength = Helper::strlen($textContent);
55890 if ($textLength > 0) {
55891 $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
55892 foreach ($contentColumns as $position => $content) {
55893 $row[$i + $position] = $content;
55894 }
55895 }
55896 }
55897 }
55898
55899 $lengths[] = $this->getCellWidth($row, $column);
55900 }
55901
55902 $this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
55903 }
55904 }
55905
55906
55907
55908
55909
55910
55911 private function getColumnSeparatorWidth()
55912 {
55913 return strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
55914 }
55915
55916
55917
55918
55919
55920
55921
55922
55923
55924 private function getCellWidth(array $row, $column)
55925 {
55926 if (isset($row[$column])) {
55927 $cell = $row[$column];
55928 $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
55929
55930 return $cellWidth;
55931 }
55932
55933 return 0;
55934 }
55935
55936
55937
55938
55939 private function cleanup()
55940 {
55941 $this->columnWidths = array();
55942 $this->numberOfColumns = null;
55943 }
55944
55945 private static function initStyles()
55946 {
55947 $borderless = new TableStyle();
55948 $borderless
55949 ->setHorizontalBorderChar('=')
55950 ->setVerticalBorderChar(' ')
55951 ->setCrossingChar(' ')
55952 ;
55953
55954 $compact = new TableStyle();
55955 $compact
55956 ->setHorizontalBorderChar('')
55957 ->setVerticalBorderChar(' ')
55958 ->setCrossingChar('')
55959 ->setCellRowContentFormat('%s')
55960 ;
55961
55962 $styleGuide = new TableStyle();
55963 $styleGuide
55964 ->setHorizontalBorderChar('-')
55965 ->setVerticalBorderChar(' ')
55966 ->setCrossingChar(' ')
55967 ->setCellHeaderFormat('%s')
55968 ;
55969
55970 return array(
55971 'default' => new TableStyle(),
55972 'borderless' => $borderless,
55973 'compact' => $compact,
55974 'symfony-style-guide' => $styleGuide,
55975 );
55976 }
55977
55978 private function resolveStyle($name)
55979 {
55980 if ($name instanceof TableStyle) {
55981 return $name;
55982 }
55983
55984 if (isset(self::$styles[$name])) {
55985 return self::$styles[$name];
55986 }
55987
55988 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
55989 }
55990 }
55991 <?php
55992
55993
55994
55995
55996
55997
55998
55999
56000
56001
56002 namespace Symfony\Component\Console\Helper;
56003
56004 use Symfony\Component\Console\Exception\InvalidArgumentException;
56005
56006
56007
56008
56009 class TableCell
56010 {
56011 private $value;
56012 private $options = array(
56013 'rowspan' => 1,
56014 'colspan' => 1,
56015 );
56016
56017
56018
56019
56020
56021 public function __construct($value = '', array $options = array())
56022 {
56023 if (is_numeric($value) && !is_string($value)) {
56024 $value = (string) $value;
56025 }
56026
56027 $this->value = $value;
56028
56029
56030  if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
56031 throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
56032 }
56033
56034 $this->options = array_merge($this->options, $options);
56035 }
56036
56037
56038
56039
56040
56041
56042 public function __toString()
56043 {
56044 return $this->value;
56045 }
56046
56047
56048
56049
56050
56051
56052 public function getColspan()
56053 {
56054 return (int) $this->options['colspan'];
56055 }
56056
56057
56058
56059
56060
56061
56062 public function getRowspan()
56063 {
56064 return (int) $this->options['rowspan'];
56065 }
56066 }
56067 <?php
56068
56069
56070
56071
56072
56073
56074
56075
56076
56077
56078 namespace Symfony\Component\Console\Helper;
56079
56080 use Symfony\Component\Console\Output\OutputInterface;
56081 use Symfony\Component\Console\Output\NullOutput;
56082 use Symfony\Component\Console\Exception\InvalidArgumentException;
56083
56084
56085
56086
56087
56088
56089
56090
56091
56092
56093 class TableHelper extends Helper
56094 {
56095 const LAYOUT_DEFAULT = 0;
56096 const LAYOUT_BORDERLESS = 1;
56097 const LAYOUT_COMPACT = 2;
56098
56099 private $table;
56100
56101 public function __construct($triggerDeprecationError = true)
56102 {
56103 if ($triggerDeprecationError) {
56104 @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);
56105 }
56106
56107 $this->table = new Table(new NullOutput());
56108 }
56109
56110
56111
56112
56113
56114
56115
56116
56117
56118
56119 public function setLayout($layout)
56120 {
56121 switch ($layout) {
56122 case self::LAYOUT_BORDERLESS:
56123 $this->table->setStyle('borderless');
56124 break;
56125
56126 case self::LAYOUT_COMPACT:
56127 $this->table->setStyle('compact');
56128 break;
56129
56130 case self::LAYOUT_DEFAULT:
56131 $this->table->setStyle('default');
56132 break;
56133
56134 default:
56135 throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
56136 }
56137
56138 return $this;
56139 }
56140
56141 public function setHeaders(array $headers)
56142 {
56143 $this->table->setHeaders($headers);
56144
56145 return $this;
56146 }
56147
56148 public function setRows(array $rows)
56149 {
56150 $this->table->setRows($rows);
56151
56152 return $this;
56153 }
56154
56155 public function addRows(array $rows)
56156 {
56157 $this->table->addRows($rows);
56158
56159 return $this;
56160 }
56161
56162 public function addRow(array $row)
56163 {
56164 $this->table->addRow($row);
56165
56166 return $this;
56167 }
56168
56169 public function setRow($column, array $row)
56170 {
56171 $this->table->setRow($column, $row);
56172
56173 return $this;
56174 }
56175
56176
56177
56178
56179
56180
56181
56182
56183 public function setPaddingChar($paddingChar)
56184 {
56185 $this->table->getStyle()->setPaddingChar($paddingChar);
56186
56187 return $this;
56188 }
56189
56190
56191
56192
56193
56194
56195
56196
56197 public function setHorizontalBorderChar($horizontalBorderChar)
56198 {
56199 $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
56200
56201 return $this;
56202 }
56203
56204
56205
56206
56207
56208
56209
56210
56211 public function setVerticalBorderChar($verticalBorderChar)
56212 {
56213 $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
56214
56215 return $this;
56216 }
56217
56218
56219
56220
56221
56222
56223
56224
56225 public function setCrossingChar($crossingChar)
56226 {
56227 $this->table->getStyle()->setCrossingChar($crossingChar);
56228
56229 return $this;
56230 }
56231
56232
56233
56234
56235
56236
56237
56238
56239 public function setCellHeaderFormat($cellHeaderFormat)
56240 {
56241 $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
56242
56243 return $this;
56244 }
56245
56246
56247
56248
56249
56250
56251
56252
56253 public function setCellRowFormat($cellRowFormat)
56254 {
56255 $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
56256
56257 return $this;
56258 }
56259
56260
56261
56262
56263
56264
56265
56266
56267 public function setCellRowContentFormat($cellRowContentFormat)
56268 {
56269 $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
56270
56271 return $this;
56272 }
56273
56274
56275
56276
56277
56278
56279
56280
56281 public function setBorderFormat($borderFormat)
56282 {
56283 $this->table->getStyle()->setBorderFormat($borderFormat);
56284
56285 return $this;
56286 }
56287
56288
56289
56290
56291
56292
56293
56294
56295 public function setPadType($padType)
56296 {
56297 $this->table->getStyle()->setPadType($padType);
56298
56299 return $this;
56300 }
56301
56302
56303
56304
56305
56306
56307
56308
56309
56310
56311
56312
56313
56314 public function render(OutputInterface $output)
56315 {
56316 $p = new \ReflectionProperty($this->table, 'output');
56317 $p->setAccessible(true);
56318 $p->setValue($this->table, $output);
56319
56320 $this->table->render();
56321 }
56322
56323
56324
56325
56326 public function getName()
56327 {
56328 return 'table';
56329 }
56330 }
56331 <?php
56332
56333
56334
56335
56336
56337
56338
56339
56340
56341
56342 namespace Symfony\Component\Console\Helper;
56343
56344
56345
56346
56347
56348
56349 class TableSeparator extends TableCell
56350 {
56351 public function __construct(array $options = array())
56352 {
56353 parent::__construct('', $options);
56354 }
56355 }
56356 <?php
56357
56358
56359
56360
56361
56362
56363
56364
56365
56366
56367 namespace Symfony\Component\Console\Helper;
56368
56369 use Symfony\Component\Console\Exception\InvalidArgumentException;
56370 use Symfony\Component\Console\Exception\LogicException;
56371
56372
56373
56374
56375
56376
56377
56378 class TableStyle
56379 {
56380 private $paddingChar = ' ';
56381 private $horizontalBorderChar = '-';
56382 private $verticalBorderChar = '|';
56383 private $crossingChar = '+';
56384 private $cellHeaderFormat = '<info>%s</info>';
56385 private $cellRowFormat = '%s';
56386 private $cellRowContentFormat = ' %s ';
56387 private $borderFormat = '%s';
56388 private $padType = STR_PAD_RIGHT;
56389
56390
56391
56392
56393
56394
56395
56396
56397 public function setPaddingChar($paddingChar)
56398 {
56399 if (!$paddingChar) {
56400 throw new LogicException('The padding char must not be empty');
56401 }
56402
56403 $this->paddingChar = $paddingChar;
56404
56405 return $this;
56406 }
56407
56408
56409
56410
56411
56412
56413 public function getPaddingChar()
56414 {
56415 return $this->paddingChar;
56416 }
56417
56418
56419
56420
56421
56422
56423
56424
56425 public function setHorizontalBorderChar($horizontalBorderChar)
56426 {
56427 $this->horizontalBorderChar = $horizontalBorderChar;
56428
56429 return $this;
56430 }
56431
56432
56433
56434
56435
56436
56437 public function getHorizontalBorderChar()
56438 {
56439 return $this->horizontalBorderChar;
56440 }
56441
56442
56443
56444
56445
56446
56447
56448
56449 public function setVerticalBorderChar($verticalBorderChar)
56450 {
56451 $this->verticalBorderChar = $verticalBorderChar;
56452
56453 return $this;
56454 }
56455
56456
56457
56458
56459
56460
56461 public function getVerticalBorderChar()
56462 {
56463 return $this->verticalBorderChar;
56464 }
56465
56466
56467
56468
56469
56470
56471
56472
56473 public function setCrossingChar($crossingChar)
56474 {
56475 $this->crossingChar = $crossingChar;
56476
56477 return $this;
56478 }
56479
56480
56481
56482
56483
56484
56485 public function getCrossingChar()
56486 {
56487 return $this->crossingChar;
56488 }
56489
56490
56491
56492
56493
56494
56495
56496
56497 public function setCellHeaderFormat($cellHeaderFormat)
56498 {
56499 $this->cellHeaderFormat = $cellHeaderFormat;
56500
56501 return $this;
56502 }
56503
56504
56505
56506
56507
56508
56509 public function getCellHeaderFormat()
56510 {
56511 return $this->cellHeaderFormat;
56512 }
56513
56514
56515
56516
56517
56518
56519
56520
56521 public function setCellRowFormat($cellRowFormat)
56522 {
56523 $this->cellRowFormat = $cellRowFormat;
56524
56525 return $this;
56526 }
56527
56528
56529
56530
56531
56532
56533 public function getCellRowFormat()
56534 {
56535 return $this->cellRowFormat;
56536 }
56537
56538
56539
56540
56541
56542
56543
56544
56545 public function setCellRowContentFormat($cellRowContentFormat)
56546 {
56547 $this->cellRowContentFormat = $cellRowContentFormat;
56548
56549 return $this;
56550 }
56551
56552
56553
56554
56555
56556
56557 public function getCellRowContentFormat()
56558 {
56559 return $this->cellRowContentFormat;
56560 }
56561
56562
56563
56564
56565
56566
56567
56568
56569 public function setBorderFormat($borderFormat)
56570 {
56571 $this->borderFormat = $borderFormat;
56572
56573 return $this;
56574 }
56575
56576
56577
56578
56579
56580
56581 public function getBorderFormat()
56582 {
56583 return $this->borderFormat;
56584 }
56585
56586
56587
56588
56589
56590
56591
56592
56593 public function setPadType($padType)
56594 {
56595 if (!in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
56596 throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
56597 }
56598
56599 $this->padType = $padType;
56600
56601 return $this;
56602 }
56603
56604
56605
56606
56607
56608
56609 public function getPadType()
56610 {
56611 return $this->padType;
56612 }
56613 }
56614 <?php
56615
56616
56617
56618
56619
56620
56621
56622
56623
56624
56625 namespace Symfony\Component\Console\Input;
56626
56627 use Symfony\Component\Console\Exception\RuntimeException;
56628
56629
56630
56631
56632
56633
56634
56635
56636
56637
56638
56639
56640
56641
56642
56643
56644
56645
56646
56647
56648
56649
56650
56651
56652
56653
56654 class ArgvInput extends Input
56655 {
56656 private $tokens;
56657 private $parsed;
56658
56659
56660
56661
56662
56663 public function __construct(array $argv = null, InputDefinition $definition = null)
56664 {
56665 if (null === $argv) {
56666 $argv = $_SERVER['argv'];
56667 }
56668
56669
56670  array_shift($argv);
56671
56672 $this->tokens = $argv;
56673
56674 parent::__construct($definition);
56675 }
56676
56677 protected function setTokens(array $tokens)
56678 {
56679 $this->tokens = $tokens;
56680 }
56681
56682
56683
56684
56685 protected function parse()
56686 {
56687 $parseOptions = true;
56688 $this->parsed = $this->tokens;
56689 while (null !== $token = array_shift($this->parsed)) {
56690 if ($parseOptions && '' == $token) {
56691 $this->parseArgument($token);
56692 } elseif ($parseOptions && '--' == $token) {
56693 $parseOptions = false;
56694 } elseif ($parseOptions && 0 === strpos($token, '--')) {
56695 $this->parseLongOption($token);
56696 } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
56697 $this->parseShortOption($token);
56698 } else {
56699 $this->parseArgument($token);
56700 }
56701 }
56702 }
56703
56704
56705
56706
56707
56708
56709 private function parseShortOption($token)
56710 {
56711 $name = substr($token, 1);
56712
56713 if (strlen($name) > 1) {
56714 if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
56715
56716  $this->addShortOption($name[0], substr($name, 1));
56717 } else {
56718 $this->parseShortOptionSet($name);
56719 }
56720 } else {
56721 $this->addShortOption($name, null);
56722 }
56723 }
56724
56725
56726
56727
56728
56729
56730
56731
56732 private function parseShortOptionSet($name)
56733 {
56734 $len = strlen($name);
56735 for ($i = 0; $i < $len; ++$i) {
56736 if (!$this->definition->hasShortcut($name[$i])) {
56737 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
56738 }
56739
56740 $option = $this->definition->getOptionForShortcut($name[$i]);
56741 if ($option->acceptValue()) {
56742 $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
56743
56744 break;
56745 } else {
56746 $this->addLongOption($option->getName(), null);
56747 }
56748 }
56749 }
56750
56751
56752
56753
56754
56755
56756 private function parseLongOption($token)
56757 {
56758 $name = substr($token, 2);
56759
56760 if (false !== $pos = strpos($name, '=')) {
56761 if (0 === strlen($value = substr($name, $pos + 1))) {
56762 array_unshift($this->parsed, null);
56763 }
56764 $this->addLongOption(substr($name, 0, $pos), $value);
56765 } else {
56766 $this->addLongOption($name, null);
56767 }
56768 }
56769
56770
56771
56772
56773
56774
56775
56776
56777 private function parseArgument($token)
56778 {
56779 $c = count($this->arguments);
56780
56781
56782  if ($this->definition->hasArgument($c)) {
56783 $arg = $this->definition->getArgument($c);
56784 $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
56785
56786
56787  } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
56788 $arg = $this->definition->getArgument($c - 1);
56789 $this->arguments[$arg->getName()][] = $token;
56790
56791
56792  } else {
56793 $all = $this->definition->getArguments();
56794 if (count($all)) {
56795 throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
56796 }
56797
56798 throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
56799 }
56800 }
56801
56802
56803
56804
56805
56806
56807
56808
56809
56810 private function addShortOption($shortcut, $value)
56811 {
56812 if (!$this->definition->hasShortcut($shortcut)) {
56813 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
56814 }
56815
56816 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
56817 }
56818
56819
56820
56821
56822
56823
56824
56825
56826
56827 private function addLongOption($name, $value)
56828 {
56829 if (!$this->definition->hasOption($name)) {
56830 throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
56831 }
56832
56833 $option = $this->definition->getOption($name);
56834
56835
56836  if (!isset($value[0])) {
56837 $value = null;
56838 }
56839
56840 if (null !== $value && !$option->acceptValue()) {
56841 throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
56842 }
56843
56844 if (null === $value && $option->acceptValue() && count($this->parsed)) {
56845
56846  
56847  $next = array_shift($this->parsed);
56848 if (isset($next[0]) && '-' !== $next[0]) {
56849 $value = $next;
56850 } elseif (empty($next)) {
56851 $value = null;
56852 } else {
56853 array_unshift($this->parsed, $next);
56854 }
56855 }
56856
56857 if (null === $value) {
56858 if ($option->isValueRequired()) {
56859 throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
56860 }
56861
56862 if (!$option->isArray()) {
56863 $value = $option->isValueOptional() ? $option->getDefault() : true;
56864 }
56865 }
56866
56867 if ($option->isArray()) {
56868 $this->options[$name][] = $value;
56869 } else {
56870 $this->options[$name] = $value;
56871 }
56872 }
56873
56874
56875
56876
56877 public function getFirstArgument()
56878 {
56879 foreach ($this->tokens as $token) {
56880 if ($token && '-' === $token[0]) {
56881 continue;
56882 }
56883
56884 return $token;
56885 }
56886 }
56887
56888
56889
56890
56891 public function hasParameterOption($values)
56892 {
56893 $values = (array) $values;
56894
56895 foreach ($this->tokens as $token) {
56896 foreach ($values as $value) {
56897 if ($token === $value || 0 === strpos($token, $value.'=')) {
56898 return true;
56899 }
56900
56901 if (0 === strpos($token, '-') && 0 !== strpos($token, '--')) {
56902 $searchableToken = str_replace('-', '', $token);
56903 $searchableValue = str_replace('-', '', $value);
56904 if ('' !== $searchableToken && '' !== $searchableValue && false !== strpos($searchableToken, $searchableValue)) {
56905 return true;
56906 }
56907 }
56908 }
56909 }
56910
56911 return false;
56912 }
56913
56914
56915
56916
56917 public function getParameterOption($values, $default = false)
56918 {
56919 $values = (array) $values;
56920 $tokens = $this->tokens;
56921
56922 while (0 < count($tokens)) {
56923 $token = array_shift($tokens);
56924
56925 foreach ($values as $value) {
56926 if ($token === $value || 0 === strpos($token, $value.'=')) {
56927 if (false !== $pos = strpos($token, '=')) {
56928 return substr($token, $pos + 1);
56929 }
56930
56931 return array_shift($tokens);
56932 }
56933 }
56934 }
56935
56936 return $default;
56937 }
56938
56939
56940
56941
56942
56943
56944 public function __toString()
56945 {
56946 $self = $this;
56947 $tokens = array_map(function ($token) use ($self) {
56948 if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
56949 return $match[1].$self->escapeToken($match[2]);
56950 }
56951
56952 if ($token && '-' !== $token[0]) {
56953 return $self->escapeToken($token);
56954 }
56955
56956 return $token;
56957 }, $this->tokens);
56958
56959 return implode(' ', $tokens);
56960 }
56961 }
56962 <?php
56963
56964
56965
56966
56967
56968
56969
56970
56971
56972
56973 namespace Symfony\Component\Console\Input;
56974
56975 use Symfony\Component\Console\Exception\InvalidArgumentException;
56976 use Symfony\Component\Console\Exception\InvalidOptionException;
56977
56978
56979
56980
56981
56982
56983
56984
56985
56986
56987 class ArrayInput extends Input
56988 {
56989 private $parameters;
56990
56991 public function __construct(array $parameters, InputDefinition $definition = null)
56992 {
56993 $this->parameters = $parameters;
56994
56995 parent::__construct($definition);
56996 }
56997
56998
56999
57000
57001 public function getFirstArgument()
57002 {
57003 foreach ($this->parameters as $key => $value) {
57004 if ($key && '-' === $key[0]) {
57005 continue;
57006 }
57007
57008 return $value;
57009 }
57010 }
57011
57012
57013
57014
57015 public function hasParameterOption($values)
57016 {
57017 $values = (array) $values;
57018
57019 foreach ($this->parameters as $k => $v) {
57020 if (!is_int($k)) {
57021 $v = $k;
57022 }
57023
57024 if (in_array($v, $values)) {
57025 return true;
57026 }
57027 }
57028
57029 return false;
57030 }
57031
57032
57033
57034
57035 public function getParameterOption($values, $default = false)
57036 {
57037 $values = (array) $values;
57038
57039 foreach ($this->parameters as $k => $v) {
57040 if (is_int($k)) {
57041 if (in_array($v, $values)) {
57042 return true;
57043 }
57044 } elseif (in_array($k, $values)) {
57045 return $v;
57046 }
57047 }
57048
57049 return $default;
57050 }
57051
57052
57053
57054
57055
57056
57057 public function __toString()
57058 {
57059 $params = array();
57060 foreach ($this->parameters as $param => $val) {
57061 if ($param && '-' === $param[0]) {
57062 if (is_array($val)) {
57063 foreach ($val as $v) {
57064 $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : '');
57065 }
57066 } else {
57067 $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
57068 }
57069 } else {
57070 $params[] = is_array($val) ? array_map(array($this, 'escapeToken'), $val) : $this->escapeToken($val);
57071 }
57072 }
57073
57074 return implode(' ', $params);
57075 }
57076
57077
57078
57079
57080 protected function parse()
57081 {
57082 foreach ($this->parameters as $key => $value) {
57083 if (0 === strpos($key, '--')) {
57084 $this->addLongOption(substr($key, 2), $value);
57085 } elseif ('-' === $key[0]) {
57086 $this->addShortOption(substr($key, 1), $value);
57087 } else {
57088 $this->addArgument($key, $value);
57089 }
57090 }
57091 }
57092
57093
57094
57095
57096
57097
57098
57099
57100
57101 private function addShortOption($shortcut, $value)
57102 {
57103 if (!$this->definition->hasShortcut($shortcut)) {
57104 throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
57105 }
57106
57107 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
57108 }
57109
57110
57111
57112
57113
57114
57115
57116
57117
57118
57119 private function addLongOption($name, $value)
57120 {
57121 if (!$this->definition->hasOption($name)) {
57122 throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
57123 }
57124
57125 $option = $this->definition->getOption($name);
57126
57127 if (null === $value) {
57128 if ($option->isValueRequired()) {
57129 throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
57130 }
57131
57132 $value = $option->isValueOptional() ? $option->getDefault() : true;
57133 }
57134
57135 $this->options[$name] = $value;
57136 }
57137
57138
57139
57140
57141
57142
57143
57144
57145
57146 private function addArgument($name, $value)
57147 {
57148 if (!$this->definition->hasArgument($name)) {
57149 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
57150 }
57151
57152 $this->arguments[$name] = $value;
57153 }
57154 }
57155 <?php
57156
57157
57158
57159
57160
57161
57162
57163
57164
57165
57166 namespace Symfony\Component\Console\Input;
57167
57168 use Symfony\Component\Console\Exception\InvalidArgumentException;
57169 use Symfony\Component\Console\Exception\RuntimeException;
57170
57171
57172
57173
57174
57175
57176
57177
57178
57179
57180
57181
57182 abstract class Input implements InputInterface
57183 {
57184 protected $definition;
57185 protected $options = array();
57186 protected $arguments = array();
57187 protected $interactive = true;
57188
57189 public function __construct(InputDefinition $definition = null)
57190 {
57191 if (null === $definition) {
57192 $this->definition = new InputDefinition();
57193 } else {
57194 $this->bind($definition);
57195 $this->validate();
57196 }
57197 }
57198
57199
57200
57201
57202 public function bind(InputDefinition $definition)
57203 {
57204 $this->arguments = array();
57205 $this->options = array();
57206 $this->definition = $definition;
57207
57208 $this->parse();
57209 }
57210
57211
57212
57213
57214 abstract protected function parse();
57215
57216
57217
57218
57219 public function validate()
57220 {
57221 $definition = $this->definition;
57222 $givenArguments = $this->arguments;
57223
57224 $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
57225 return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
57226 });
57227
57228 if (count($missingArguments) > 0) {
57229 throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
57230 }
57231 }
57232
57233
57234
57235
57236 public function isInteractive()
57237 {
57238 return $this->interactive;
57239 }
57240
57241
57242
57243
57244 public function setInteractive($interactive)
57245 {
57246 $this->interactive = (bool) $interactive;
57247 }
57248
57249
57250
57251
57252 public function getArguments()
57253 {
57254 return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
57255 }
57256
57257
57258
57259
57260 public function getArgument($name)
57261 {
57262 if (!$this->definition->hasArgument($name)) {
57263 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
57264 }
57265
57266 return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
57267 }
57268
57269
57270
57271
57272 public function setArgument($name, $value)
57273 {
57274 if (!$this->definition->hasArgument($name)) {
57275 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
57276 }
57277
57278 $this->arguments[$name] = $value;
57279 }
57280
57281
57282
57283
57284 public function hasArgument($name)
57285 {
57286 return $this->definition->hasArgument($name);
57287 }
57288
57289
57290
57291
57292 public function getOptions()
57293 {
57294 return array_merge($this->definition->getOptionDefaults(), $this->options);
57295 }
57296
57297
57298
57299
57300 public function getOption($name)
57301 {
57302 if (!$this->definition->hasOption($name)) {
57303 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
57304 }
57305
57306 return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
57307 }
57308
57309
57310
57311
57312 public function setOption($name, $value)
57313 {
57314 if (!$this->definition->hasOption($name)) {
57315 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
57316 }
57317
57318 $this->options[$name] = $value;
57319 }
57320
57321
57322
57323
57324 public function hasOption($name)
57325 {
57326 return $this->definition->hasOption($name);
57327 }
57328
57329
57330
57331
57332
57333
57334
57335
57336 public function escapeToken($token)
57337 {
57338 return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
57339 }
57340 }
57341 <?php
57342
57343
57344
57345
57346
57347
57348
57349
57350
57351
57352 namespace Symfony\Component\Console\Input;
57353
57354 use Symfony\Component\Console\Exception\InvalidArgumentException;
57355 use Symfony\Component\Console\Exception\LogicException;
57356
57357
57358
57359
57360
57361
57362 class InputArgument
57363 {
57364 const REQUIRED = 1;
57365 const OPTIONAL = 2;
57366 const IS_ARRAY = 4;
57367
57368 private $name;
57369 private $mode;
57370 private $default;
57371 private $description;
57372
57373
57374
57375
57376
57377
57378
57379
57380
57381 public function __construct($name, $mode = null, $description = '', $default = null)
57382 {
57383 if (null === $mode) {
57384 $mode = self::OPTIONAL;
57385 } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
57386 throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
57387 }
57388
57389 $this->name = $name;
57390 $this->mode = $mode;
57391 $this->description = $description;
57392
57393 $this->setDefault($default);
57394 }
57395
57396
57397
57398
57399
57400
57401 public function getName()
57402 {
57403 return $this->name;
57404 }
57405
57406
57407
57408
57409
57410
57411 public function isRequired()
57412 {
57413 return self::REQUIRED === (self::REQUIRED & $this->mode);
57414 }
57415
57416
57417
57418
57419
57420
57421 public function isArray()
57422 {
57423 return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
57424 }
57425
57426
57427
57428
57429
57430
57431
57432
57433 public function setDefault($default = null)
57434 {
57435 if (self::REQUIRED === $this->mode && null !== $default) {
57436 throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
57437 }
57438
57439 if ($this->isArray()) {
57440 if (null === $default) {
57441 $default = array();
57442 } elseif (!is_array($default)) {
57443 throw new LogicException('A default value for an array argument must be an array.');
57444 }
57445 }
57446
57447 $this->default = $default;
57448 }
57449
57450
57451
57452
57453
57454
57455 public function getDefault()
57456 {
57457 return $this->default;
57458 }
57459
57460
57461
57462
57463
57464
57465 public function getDescription()
57466 {
57467 return $this->description;
57468 }
57469 }
57470 <?php
57471
57472
57473
57474
57475
57476
57477
57478
57479
57480
57481 namespace Symfony\Component\Console\Input;
57482
57483
57484
57485
57486
57487
57488
57489 interface InputAwareInterface
57490 {
57491
57492
57493
57494
57495
57496 public function setInput(InputInterface $input);
57497 }
57498 <?php
57499
57500
57501
57502
57503
57504
57505
57506
57507
57508
57509 namespace Symfony\Component\Console\Input;
57510
57511 use Symfony\Component\Console\Descriptor\TextDescriptor;
57512 use Symfony\Component\Console\Descriptor\XmlDescriptor;
57513 use Symfony\Component\Console\Output\BufferedOutput;
57514 use Symfony\Component\Console\Exception\InvalidArgumentException;
57515 use Symfony\Component\Console\Exception\LogicException;
57516
57517
57518
57519
57520
57521
57522
57523
57524
57525
57526
57527
57528
57529 class InputDefinition
57530 {
57531 private $arguments;
57532 private $requiredCount;
57533 private $hasAnArrayArgument = false;
57534 private $hasOptional;
57535 private $options;
57536 private $shortcuts;
57537
57538
57539
57540
57541 public function __construct(array $definition = array())
57542 {
57543 $this->setDefinition($definition);
57544 }
57545
57546
57547
57548
57549 public function setDefinition(array $definition)
57550 {
57551 $arguments = array();
57552 $options = array();
57553 foreach ($definition as $item) {
57554 if ($item instanceof InputOption) {
57555 $options[] = $item;
57556 } else {
57557 $arguments[] = $item;
57558 }
57559 }
57560
57561 $this->setArguments($arguments);
57562 $this->setOptions($options);
57563 }
57564
57565
57566
57567
57568
57569
57570 public function setArguments($arguments = array())
57571 {
57572 $this->arguments = array();
57573 $this->requiredCount = 0;
57574 $this->hasOptional = false;
57575 $this->hasAnArrayArgument = false;
57576 $this->addArguments($arguments);
57577 }
57578
57579
57580
57581
57582
57583
57584 public function addArguments($arguments = array())
57585 {
57586 if (null !== $arguments) {
57587 foreach ($arguments as $argument) {
57588 $this->addArgument($argument);
57589 }
57590 }
57591 }
57592
57593
57594
57595
57596 public function addArgument(InputArgument $argument)
57597 {
57598 if (isset($this->arguments[$argument->getName()])) {
57599 throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
57600 }
57601
57602 if ($this->hasAnArrayArgument) {
57603 throw new LogicException('Cannot add an argument after an array argument.');
57604 }
57605
57606 if ($argument->isRequired() && $this->hasOptional) {
57607 throw new LogicException('Cannot add a required argument after an optional one.');
57608 }
57609
57610 if ($argument->isArray()) {
57611 $this->hasAnArrayArgument = true;
57612 }
57613
57614 if ($argument->isRequired()) {
57615 ++$this->requiredCount;
57616 } else {
57617 $this->hasOptional = true;
57618 }
57619
57620 $this->arguments[$argument->getName()] = $argument;
57621 }
57622
57623
57624
57625
57626
57627
57628
57629
57630
57631
57632 public function getArgument($name)
57633 {
57634 if (!$this->hasArgument($name)) {
57635 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
57636 }
57637
57638 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
57639
57640 return $arguments[$name];
57641 }
57642
57643
57644
57645
57646
57647
57648
57649
57650 public function hasArgument($name)
57651 {
57652 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
57653
57654 return isset($arguments[$name]);
57655 }
57656
57657
57658
57659
57660
57661
57662 public function getArguments()
57663 {
57664 return $this->arguments;
57665 }
57666
57667
57668
57669
57670
57671
57672 public function getArgumentCount()
57673 {
57674 return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
57675 }
57676
57677
57678
57679
57680
57681
57682 public function getArgumentRequiredCount()
57683 {
57684 return $this->requiredCount;
57685 }
57686
57687
57688
57689
57690
57691
57692 public function getArgumentDefaults()
57693 {
57694 $values = array();
57695 foreach ($this->arguments as $argument) {
57696 $values[$argument->getName()] = $argument->getDefault();
57697 }
57698
57699 return $values;
57700 }
57701
57702
57703
57704
57705
57706
57707 public function setOptions($options = array())
57708 {
57709 $this->options = array();
57710 $this->shortcuts = array();
57711 $this->addOptions($options);
57712 }
57713
57714
57715
57716
57717
57718
57719 public function addOptions($options = array())
57720 {
57721 foreach ($options as $option) {
57722 $this->addOption($option);
57723 }
57724 }
57725
57726
57727
57728
57729 public function addOption(InputOption $option)
57730 {
57731 if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
57732 throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
57733 }
57734
57735 if ($option->getShortcut()) {
57736 foreach (explode('|', $option->getShortcut()) as $shortcut) {
57737 if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
57738 throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
57739 }
57740 }
57741 }
57742
57743 $this->options[$option->getName()] = $option;
57744 if ($option->getShortcut()) {
57745 foreach (explode('|', $option->getShortcut()) as $shortcut) {
57746 $this->shortcuts[$shortcut] = $option->getName();
57747 }
57748 }
57749 }
57750
57751
57752
57753
57754
57755
57756
57757
57758
57759
57760 public function getOption($name)
57761 {
57762 if (!$this->hasOption($name)) {
57763 throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
57764 }
57765
57766 return $this->options[$name];
57767 }
57768
57769
57770
57771
57772
57773
57774
57775
57776
57777
57778
57779 public function hasOption($name)
57780 {
57781 return isset($this->options[$name]);
57782 }
57783
57784
57785
57786
57787
57788
57789 public function getOptions()
57790 {
57791 return $this->options;
57792 }
57793
57794
57795
57796
57797
57798
57799
57800
57801 public function hasShortcut($name)
57802 {
57803 return isset($this->shortcuts[$name]);
57804 }
57805
57806
57807
57808
57809
57810
57811
57812
57813 public function getOptionForShortcut($shortcut)
57814 {
57815 return $this->getOption($this->shortcutToName($shortcut));
57816 }
57817
57818
57819
57820
57821
57822
57823 public function getOptionDefaults()
57824 {
57825 $values = array();
57826 foreach ($this->options as $option) {
57827 $values[$option->getName()] = $option->getDefault();
57828 }
57829
57830 return $values;
57831 }
57832
57833
57834
57835
57836
57837
57838
57839
57840
57841
57842 private function shortcutToName($shortcut)
57843 {
57844 if (!isset($this->shortcuts[$shortcut])) {
57845 throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
57846 }
57847
57848 return $this->shortcuts[$shortcut];
57849 }
57850
57851
57852
57853
57854
57855
57856
57857
57858 public function getSynopsis($short = false)
57859 {
57860 $elements = array();
57861
57862 if ($short && $this->getOptions()) {
57863 $elements[] = '[options]';
57864 } elseif (!$short) {
57865 foreach ($this->getOptions() as $option) {
57866 $value = '';
57867 if ($option->acceptValue()) {
57868 $value = sprintf(
57869 ' %s%s%s',
57870 $option->isValueOptional() ? '[' : '',
57871 strtoupper($option->getName()),
57872 $option->isValueOptional() ? ']' : ''
57873 );
57874 }
57875
57876 $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
57877 $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
57878 }
57879 }
57880
57881 if (count($elements) && $this->getArguments()) {
57882 $elements[] = '[--]';
57883 }
57884
57885 foreach ($this->getArguments() as $argument) {
57886 $element = '<'.$argument->getName().'>';
57887 if (!$argument->isRequired()) {
57888 $element = '['.$element.']';
57889 } elseif ($argument->isArray()) {
57890 $element = $element.' ('.$element.')';
57891 }
57892
57893 if ($argument->isArray()) {
57894 $element .= '...';
57895 }
57896
57897 $elements[] = $element;
57898 }
57899
57900 return implode(' ', $elements);
57901 }
57902
57903
57904
57905
57906
57907
57908
57909
57910 public function asText()
57911 {
57912 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
57913
57914 $descriptor = new TextDescriptor();
57915 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
57916 $descriptor->describe($output, $this, array('raw_output' => true));
57917
57918 return $output->fetch();
57919 }
57920
57921
57922
57923
57924
57925
57926
57927
57928
57929
57930 public function asXml($asDom = false)
57931 {
57932 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
57933
57934 $descriptor = new XmlDescriptor();
57935
57936 if ($asDom) {
57937 return $descriptor->getInputDefinitionDocument($this);
57938 }
57939
57940 $output = new BufferedOutput();
57941 $descriptor->describe($output, $this);
57942
57943 return $output->fetch();
57944 }
57945 }
57946 <?php
57947
57948
57949
57950
57951
57952
57953
57954
57955
57956
57957 namespace Symfony\Component\Console\Input;
57958
57959 use Symfony\Component\Console\Exception\InvalidArgumentException;
57960 use Symfony\Component\Console\Exception\RuntimeException;
57961
57962
57963
57964
57965
57966
57967 interface InputInterface
57968 {
57969
57970
57971
57972
57973
57974 public function getFirstArgument();
57975
57976
57977
57978
57979
57980
57981
57982
57983
57984
57985
57986 public function hasParameterOption($values);
57987
57988
57989
57990
57991
57992
57993
57994
57995
57996
57997
57998
57999 public function getParameterOption($values, $default = false);
58000
58001
58002
58003
58004 public function bind(InputDefinition $definition);
58005
58006
58007
58008
58009
58010
58011 public function validate();
58012
58013
58014
58015
58016
58017
58018 public function getArguments();
58019
58020
58021
58022
58023
58024
58025
58026
58027
58028
58029 public function getArgument($name);
58030
58031
58032
58033
58034
58035
58036
58037
58038
58039 public function setArgument($name, $value);
58040
58041
58042
58043
58044
58045
58046
58047
58048 public function hasArgument($name);
58049
58050
58051
58052
58053
58054
58055 public function getOptions();
58056
58057
58058
58059
58060
58061
58062
58063
58064
58065
58066 public function getOption($name);
58067
58068
58069
58070
58071
58072
58073
58074
58075
58076 public function setOption($name, $value);
58077
58078
58079
58080
58081
58082
58083
58084
58085 public function hasOption($name);
58086
58087
58088
58089
58090
58091
58092 public function isInteractive();
58093
58094
58095
58096
58097
58098
58099 public function setInteractive($interactive);
58100 }
58101 <?php
58102
58103
58104
58105
58106
58107
58108
58109
58110
58111
58112 namespace Symfony\Component\Console\Input;
58113
58114 use Symfony\Component\Console\Exception\InvalidArgumentException;
58115 use Symfony\Component\Console\Exception\LogicException;
58116
58117
58118
58119
58120
58121
58122 class InputOption
58123 {
58124 const VALUE_NONE = 1;
58125 const VALUE_REQUIRED = 2;
58126 const VALUE_OPTIONAL = 4;
58127 const VALUE_IS_ARRAY = 8;
58128
58129 private $name;
58130 private $shortcut;
58131 private $mode;
58132 private $default;
58133 private $description;
58134
58135
58136
58137
58138
58139
58140
58141
58142
58143
58144 public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
58145 {
58146 if (0 === strpos($name, '--')) {
58147 $name = substr($name, 2);
58148 }
58149
58150 if (empty($name)) {
58151 throw new InvalidArgumentException('An option name cannot be empty.');
58152 }
58153
58154 if (empty($shortcut)) {
58155 $shortcut = null;
58156 }
58157
58158 if (null !== $shortcut) {
58159 if (is_array($shortcut)) {
58160 $shortcut = implode('|', $shortcut);
58161 }
58162 $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
58163 $shortcuts = array_filter($shortcuts);
58164 $shortcut = implode('|', $shortcuts);
58165
58166 if (empty($shortcut)) {
58167 throw new InvalidArgumentException('An option shortcut cannot be empty.');
58168 }
58169 }
58170
58171 if (null === $mode) {
58172 $mode = self::VALUE_NONE;
58173 } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
58174 throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
58175 }
58176
58177 $this->name = $name;
58178 $this->shortcut = $shortcut;
58179 $this->mode = $mode;
58180 $this->description = $description;
58181
58182 if ($this->isArray() && !$this->acceptValue()) {
58183 throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
58184 }
58185
58186 $this->setDefault($default);
58187 }
58188
58189
58190
58191
58192
58193
58194 public function getShortcut()
58195 {
58196 return $this->shortcut;
58197 }
58198
58199
58200
58201
58202
58203
58204 public function getName()
58205 {
58206 return $this->name;
58207 }
58208
58209
58210
58211
58212
58213
58214 public function acceptValue()
58215 {
58216 return $this->isValueRequired() || $this->isValueOptional();
58217 }
58218
58219
58220
58221
58222
58223
58224 public function isValueRequired()
58225 {
58226 return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
58227 }
58228
58229
58230
58231
58232
58233
58234 public function isValueOptional()
58235 {
58236 return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
58237 }
58238
58239
58240
58241
58242
58243
58244 public function isArray()
58245 {
58246 return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
58247 }
58248
58249
58250
58251
58252
58253
58254
58255
58256 public function setDefault($default = null)
58257 {
58258 if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
58259 throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
58260 }
58261
58262 if ($this->isArray()) {
58263 if (null === $default) {
58264 $default = array();
58265 } elseif (!is_array($default)) {
58266 throw new LogicException('A default value for an array option must be an array.');
58267 }
58268 }
58269
58270 $this->default = $this->acceptValue() ? $default : false;
58271 }
58272
58273
58274
58275
58276
58277
58278 public function getDefault()
58279 {
58280 return $this->default;
58281 }
58282
58283
58284
58285
58286
58287
58288 public function getDescription()
58289 {
58290 return $this->description;
58291 }
58292
58293
58294
58295
58296
58297
58298 public function equals(InputOption $option)
58299 {
58300 return $option->getName() === $this->getName()
58301 && $option->getShortcut() === $this->getShortcut()
58302 && $option->getDefault() === $this->getDefault()
58303 && $option->isArray() === $this->isArray()
58304 && $option->isValueRequired() === $this->isValueRequired()
58305 && $option->isValueOptional() === $this->isValueOptional()
58306 ;
58307 }
58308 }
58309 <?php
58310
58311
58312
58313
58314
58315
58316
58317
58318
58319
58320 namespace Symfony\Component\Console\Input;
58321
58322 use Symfony\Component\Console\Exception\InvalidArgumentException;
58323
58324
58325
58326
58327
58328
58329
58330
58331
58332
58333 class StringInput extends ArgvInput
58334 {
58335 const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
58336 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
58337
58338
58339
58340
58341
58342
58343
58344 public function __construct($input, InputDefinition $definition = null)
58345 {
58346 if ($definition) {
58347 @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);
58348 }
58349
58350 parent::__construct(array(), null);
58351
58352 $this->setTokens($this->tokenize($input));
58353
58354 if (null !== $definition) {
58355 $this->bind($definition);
58356 }
58357 }
58358
58359
58360
58361
58362
58363
58364
58365
58366
58367
58368 private function tokenize($input)
58369 {
58370 $tokens = array();
58371 $length = strlen($input);
58372 $cursor = 0;
58373 while ($cursor < $length) {
58374 if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
58375 } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
58376 $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
58377 } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
58378 $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
58379 } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
58380 $tokens[] = stripcslashes($match[1]);
58381 } else {
58382
58383  throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
58384 }
58385
58386 $cursor += strlen($match[0]);
58387 }
58388
58389 return $tokens;
58390 }
58391 }
58392 Copyright (c) 2004-2017 Fabien Potencier
58393
58394 Permission is hereby granted, free of charge, to any person obtaining a copy
58395 of this software and associated documentation files (the "Software"), to deal
58396 in the Software without restriction, including without limitation the rights
58397 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
58398 copies of the Software, and to permit persons to whom the Software is furnished
58399 to do so, subject to the following conditions:
58400
58401 The above copyright notice and this permission notice shall be included in all
58402 copies or substantial portions of the Software.
58403
58404 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
58405 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
58406 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58407 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
58408 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
58409 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
58410 THE SOFTWARE.
58411 <?php
58412
58413
58414
58415
58416
58417
58418
58419
58420
58421
58422 namespace Symfony\Component\Console\Logger;
58423
58424 use Psr\Log\AbstractLogger;
58425 use Psr\Log\InvalidArgumentException;
58426 use Psr\Log\LogLevel;
58427 use Symfony\Component\Console\Output\OutputInterface;
58428 use Symfony\Component\Console\Output\ConsoleOutputInterface;
58429
58430
58431
58432
58433
58434
58435
58436
58437 class ConsoleLogger extends AbstractLogger
58438 {
58439 const INFO = 'info';
58440 const ERROR = 'error';
58441
58442 private $output;
58443 private $verbosityLevelMap = array(
58444 LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
58445 LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
58446 LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
58447 LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
58448 LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
58449 LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
58450 LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
58451 LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
58452 );
58453 private $formatLevelMap = array(
58454 LogLevel::EMERGENCY => self::ERROR,
58455 LogLevel::ALERT => self::ERROR,
58456 LogLevel::CRITICAL => self::ERROR,
58457 LogLevel::ERROR => self::ERROR,
58458 LogLevel::WARNING => self::INFO,
58459 LogLevel::NOTICE => self::INFO,
58460 LogLevel::INFO => self::INFO,
58461 LogLevel::DEBUG => self::INFO,
58462 );
58463
58464 public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
58465 {
58466 $this->output = $output;
58467 $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
58468 $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
58469 }
58470
58471
58472
58473
58474 public function log($level, $message, array $context = array())
58475 {
58476 if (!isset($this->verbosityLevelMap[$level])) {
58477 throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
58478 }
58479
58480
58481  if (self::ERROR === $this->formatLevelMap[$level] && $this->output instanceof ConsoleOutputInterface) {
58482 $output = $this->output->getErrorOutput();
58483 } else {
58484 $output = $this->output;
58485 }
58486
58487 if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
58488 $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
58489 }
58490 }
58491
58492
58493
58494
58495
58496
58497
58498
58499
58500
58501
58502 private function interpolate($message, array $context)
58503 {
58504
58505  $replace = array();
58506 foreach ($context as $key => $val) {
58507 if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
58508 $replace[sprintf('{%s}', $key)] = $val;
58509 }
58510 }
58511
58512
58513  return strtr($message, $replace);
58514 }
58515 }
58516 <?php
58517
58518
58519
58520
58521
58522
58523
58524
58525
58526
58527 namespace Symfony\Component\Console\Output;
58528
58529
58530
58531
58532 class BufferedOutput extends Output
58533 {
58534 private $buffer = '';
58535
58536
58537
58538
58539
58540
58541 public function fetch()
58542 {
58543 $content = $this->buffer;
58544 $this->buffer = '';
58545
58546 return $content;
58547 }
58548
58549
58550
58551
58552 protected function doWrite($message, $newline)
58553 {
58554 $this->buffer .= $message;
58555
58556 if ($newline) {
58557 $this->buffer .= PHP_EOL;
58558 }
58559 }
58560 }
58561 <?php
58562
58563
58564
58565
58566
58567
58568
58569
58570
58571
58572 namespace Symfony\Component\Console\Output;
58573
58574 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58575
58576
58577
58578
58579
58580
58581
58582
58583
58584
58585
58586
58587
58588
58589 class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
58590 {
58591 private $stderr;
58592
58593
58594
58595
58596
58597
58598 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
58599 {
58600 parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
58601
58602 $actualDecorated = $this->isDecorated();
58603 $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
58604
58605 if (null === $decorated) {
58606 $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
58607 }
58608 }
58609
58610
58611
58612
58613 public function setDecorated($decorated)
58614 {
58615 parent::setDecorated($decorated);
58616 $this->stderr->setDecorated($decorated);
58617 }
58618
58619
58620
58621
58622 public function setFormatter(OutputFormatterInterface $formatter)
58623 {
58624 parent::setFormatter($formatter);
58625 $this->stderr->setFormatter($formatter);
58626 }
58627
58628
58629
58630
58631 public function setVerbosity($level)
58632 {
58633 parent::setVerbosity($level);
58634 $this->stderr->setVerbosity($level);
58635 }
58636
58637
58638
58639
58640 public function getErrorOutput()
58641 {
58642 return $this->stderr;
58643 }
58644
58645
58646
58647
58648 public function setErrorOutput(OutputInterface $error)
58649 {
58650 $this->stderr = $error;
58651 }
58652
58653
58654
58655
58656
58657
58658
58659 protected function hasStdoutSupport()
58660 {
58661 return false === $this->isRunningOS400();
58662 }
58663
58664
58665
58666
58667
58668
58669
58670 protected function hasStderrSupport()
58671 {
58672 return false === $this->isRunningOS400();
58673 }
58674
58675
58676
58677
58678
58679
58680
58681 private function isRunningOS400()
58682 {
58683 $checks = array(
58684 function_exists('php_uname') ? php_uname('s') : '',
58685 getenv('OSTYPE'),
58686 PHP_OS,
58687 );
58688
58689 return false !== stripos(implode(';', $checks), 'OS400');
58690 }
58691
58692
58693
58694
58695 private function openOutputStream()
58696 {
58697 $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output';
58698
58699 return @fopen($outputStream, 'w') ?: fopen('php://output', 'w');
58700 }
58701
58702
58703
58704
58705 private function openErrorStream()
58706 {
58707 $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output';
58708
58709 return fopen($errorStream, 'w');
58710 }
58711 }
58712 <?php
58713
58714
58715
58716
58717
58718
58719
58720
58721
58722
58723 namespace Symfony\Component\Console\Output;
58724
58725
58726
58727
58728
58729
58730
58731 interface ConsoleOutputInterface extends OutputInterface
58732 {
58733
58734
58735
58736
58737
58738 public function getErrorOutput();
58739
58740 public function setErrorOutput(OutputInterface $error);
58741 }
58742 <?php
58743
58744
58745
58746
58747
58748
58749
58750
58751
58752
58753 namespace Symfony\Component\Console\Output;
58754
58755 use Symfony\Component\Console\Formatter\OutputFormatter;
58756 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58757
58758
58759
58760
58761
58762
58763
58764
58765
58766 class NullOutput implements OutputInterface
58767 {
58768
58769
58770
58771 public function setFormatter(OutputFormatterInterface $formatter)
58772 {
58773
58774  }
58775
58776
58777
58778
58779 public function getFormatter()
58780 {
58781
58782  return new OutputFormatter();
58783 }
58784
58785
58786
58787
58788 public function setDecorated($decorated)
58789 {
58790
58791  }
58792
58793
58794
58795
58796 public function isDecorated()
58797 {
58798 return false;
58799 }
58800
58801
58802
58803
58804 public function setVerbosity($level)
58805 {
58806
58807  }
58808
58809
58810
58811
58812 public function getVerbosity()
58813 {
58814 return self::VERBOSITY_QUIET;
58815 }
58816
58817
58818
58819
58820 public function isQuiet()
58821 {
58822 return true;
58823 }
58824
58825
58826
58827
58828 public function isVerbose()
58829 {
58830 return false;
58831 }
58832
58833
58834
58835
58836 public function isVeryVerbose()
58837 {
58838 return false;
58839 }
58840
58841
58842
58843
58844 public function isDebug()
58845 {
58846 return false;
58847 }
58848
58849
58850
58851
58852 public function writeln($messages, $options = self::OUTPUT_NORMAL)
58853 {
58854
58855  }
58856
58857
58858
58859
58860 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
58861 {
58862
58863  }
58864 }
58865 <?php
58866
58867
58868
58869
58870
58871
58872
58873
58874
58875
58876 namespace Symfony\Component\Console\Output;
58877
58878 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58879 use Symfony\Component\Console\Formatter\OutputFormatter;
58880
58881
58882
58883
58884
58885
58886
58887
58888
58889
58890
58891
58892
58893
58894 abstract class Output implements OutputInterface
58895 {
58896 private $verbosity;
58897 private $formatter;
58898
58899
58900
58901
58902
58903
58904 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
58905 {
58906 $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
58907 $this->formatter = $formatter ?: new OutputFormatter();
58908 $this->formatter->setDecorated($decorated);
58909 }
58910
58911
58912
58913
58914 public function setFormatter(OutputFormatterInterface $formatter)
58915 {
58916 $this->formatter = $formatter;
58917 }
58918
58919
58920
58921
58922 public function getFormatter()
58923 {
58924 return $this->formatter;
58925 }
58926
58927
58928
58929
58930 public function setDecorated($decorated)
58931 {
58932 $this->formatter->setDecorated($decorated);
58933 }
58934
58935
58936
58937
58938 public function isDecorated()
58939 {
58940 return $this->formatter->isDecorated();
58941 }
58942
58943
58944
58945
58946 public function setVerbosity($level)
58947 {
58948 $this->verbosity = (int) $level;
58949 }
58950
58951
58952
58953
58954 public function getVerbosity()
58955 {
58956 return $this->verbosity;
58957 }
58958
58959
58960
58961
58962 public function isQuiet()
58963 {
58964 return self::VERBOSITY_QUIET === $this->verbosity;
58965 }
58966
58967
58968
58969
58970 public function isVerbose()
58971 {
58972 return self::VERBOSITY_VERBOSE <= $this->verbosity;
58973 }
58974
58975
58976
58977
58978 public function isVeryVerbose()
58979 {
58980 return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
58981 }
58982
58983
58984
58985
58986 public function isDebug()
58987 {
58988 return self::VERBOSITY_DEBUG <= $this->verbosity;
58989 }
58990
58991
58992
58993
58994 public function writeln($messages, $options = self::OUTPUT_NORMAL)
58995 {
58996 $this->write($messages, true, $options);
58997 }
58998
58999
59000
59001
59002 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
59003 {
59004 $messages = (array) $messages;
59005
59006 $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
59007 $type = $types & $options ?: self::OUTPUT_NORMAL;
59008
59009 $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
59010 $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
59011
59012 if ($verbosity > $this->getVerbosity()) {
59013 return;
59014 }
59015
59016 foreach ($messages as $message) {
59017 switch ($type) {
59018 case OutputInterface::OUTPUT_NORMAL:
59019 $message = $this->formatter->format($message);
59020 break;
59021 case OutputInterface::OUTPUT_RAW:
59022 break;
59023 case OutputInterface::OUTPUT_PLAIN:
59024 $message = strip_tags($this->formatter->format($message));
59025 break;
59026 }
59027
59028 $this->doWrite($message, $newline);
59029 }
59030 }
59031
59032
59033
59034
59035
59036
59037
59038 abstract protected function doWrite($message, $newline);
59039 }
59040 <?php
59041
59042
59043
59044
59045
59046
59047
59048
59049
59050
59051 namespace Symfony\Component\Console\Output;
59052
59053 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59054
59055
59056
59057
59058
59059
59060 interface OutputInterface
59061 {
59062 const VERBOSITY_QUIET = 16;
59063 const VERBOSITY_NORMAL = 32;
59064 const VERBOSITY_VERBOSE = 64;
59065 const VERBOSITY_VERY_VERBOSE = 128;
59066 const VERBOSITY_DEBUG = 256;
59067
59068 const OUTPUT_NORMAL = 1;
59069 const OUTPUT_RAW = 2;
59070 const OUTPUT_PLAIN = 4;
59071
59072
59073
59074
59075
59076
59077
59078
59079 public function write($messages, $newline = false, $options = 0);
59080
59081
59082
59083
59084
59085
59086
59087 public function writeln($messages, $options = 0);
59088
59089
59090
59091
59092
59093
59094 public function setVerbosity($level);
59095
59096
59097
59098
59099
59100
59101 public function getVerbosity();
59102
59103
59104
59105
59106
59107
59108 public function setDecorated($decorated);
59109
59110
59111
59112
59113
59114
59115 public function isDecorated();
59116
59117 public function setFormatter(OutputFormatterInterface $formatter);
59118
59119
59120
59121
59122
59123
59124 public function getFormatter();
59125 }
59126 <?php
59127
59128
59129
59130
59131
59132
59133
59134
59135
59136
59137 namespace Symfony\Component\Console\Output;
59138
59139 use Symfony\Component\Console\Exception\InvalidArgumentException;
59140 use Symfony\Component\Console\Exception\RuntimeException;
59141 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59142
59143
59144
59145
59146
59147
59148
59149
59150
59151
59152
59153
59154
59155
59156 class StreamOutput extends Output
59157 {
59158 private $stream;
59159
59160
59161
59162
59163
59164
59165
59166
59167
59168 public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
59169 {
59170 if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
59171 throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
59172 }
59173
59174 $this->stream = $stream;
59175
59176 if (null === $decorated) {
59177 $decorated = $this->hasColorSupport();
59178 }
59179
59180 parent::__construct($verbosity, $decorated, $formatter);
59181 }
59182
59183
59184
59185
59186
59187
59188 public function getStream()
59189 {
59190 return $this->stream;
59191 }
59192
59193
59194
59195
59196 protected function doWrite($message, $newline)
59197 {
59198 if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
59199
59200  throw new RuntimeException('Unable to write output.');
59201 }
59202
59203 fflush($this->stream);
59204 }
59205
59206
59207
59208
59209
59210
59211
59212
59213
59214
59215
59216 protected function hasColorSupport()
59217 {
59218 if (DIRECTORY_SEPARATOR === '\\') {
59219 return
59220 '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
59221 || false !== getenv('ANSICON')
59222 || 'ON' === getenv('ConEmuANSI')
59223 || 'xterm' === getenv('TERM');
59224 }
59225
59226 return function_exists('posix_isatty') && @posix_isatty($this->stream);
59227 }
59228 }
59229 <?php
59230
59231
59232
59233
59234
59235
59236
59237
59238
59239
59240 namespace Symfony\Component\Console\Question;
59241
59242 use Symfony\Component\Console\Exception\InvalidArgumentException;
59243
59244
59245
59246
59247
59248
59249 class ChoiceQuestion extends Question
59250 {
59251 private $choices;
59252 private $multiselect = false;
59253 private $prompt = ' > ';
59254 private $errorMessage = 'Value "%s" is invalid';
59255
59256
59257
59258
59259
59260
59261 public function __construct($question, array $choices, $default = null)
59262 {
59263 if (!$choices) {
59264 throw new \LogicException('Choice question must have at least 1 choice available.');
59265 }
59266
59267 parent::__construct($question, $default);
59268
59269 $this->choices = $choices;
59270 $this->setValidator($this->getDefaultValidator());
59271 $this->setAutocompleterValues($choices);
59272 }
59273
59274
59275
59276
59277
59278
59279 public function getChoices()
59280 {
59281 return $this->choices;
59282 }
59283
59284
59285
59286
59287
59288
59289
59290
59291
59292
59293 public function setMultiselect($multiselect)
59294 {
59295 $this->multiselect = $multiselect;
59296 $this->setValidator($this->getDefaultValidator());
59297
59298 return $this;
59299 }
59300
59301
59302
59303
59304
59305
59306 public function isMultiselect()
59307 {
59308 return $this->multiselect;
59309 }
59310
59311
59312
59313
59314
59315
59316 public function getPrompt()
59317 {
59318 return $this->prompt;
59319 }
59320
59321
59322
59323
59324
59325
59326
59327
59328 public function setPrompt($prompt)
59329 {
59330 $this->prompt = $prompt;
59331
59332 return $this;
59333 }
59334
59335
59336
59337
59338
59339
59340
59341
59342
59343
59344 public function setErrorMessage($errorMessage)
59345 {
59346 $this->errorMessage = $errorMessage;
59347 $this->setValidator($this->getDefaultValidator());
59348
59349 return $this;
59350 }
59351
59352
59353
59354
59355
59356
59357 private function getDefaultValidator()
59358 {
59359 $choices = $this->choices;
59360 $errorMessage = $this->errorMessage;
59361 $multiselect = $this->multiselect;
59362 $isAssoc = $this->isAssoc($choices);
59363
59364 return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
59365
59366  $selectedChoices = str_replace(' ', '', $selected);
59367
59368 if ($multiselect) {
59369
59370  if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
59371 throw new InvalidArgumentException(sprintf($errorMessage, $selected));
59372 }
59373 $selectedChoices = explode(',', $selectedChoices);
59374 } else {
59375 $selectedChoices = array($selected);
59376 }
59377
59378 $multiselectChoices = array();
59379 foreach ($selectedChoices as $value) {
59380 $results = array();
59381 foreach ($choices as $key => $choice) {
59382 if ($choice === $value) {
59383 $results[] = $key;
59384 }
59385 }
59386
59387 if (count($results) > 1) {
59388 throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
59389 }
59390
59391 $result = array_search($value, $choices);
59392
59393 if (!$isAssoc) {
59394 if (false !== $result) {
59395 $result = $choices[$result];
59396 } elseif (isset($choices[$value])) {
59397 $result = $choices[$value];
59398 }
59399 } elseif (false === $result && isset($choices[$value])) {
59400 $result = $value;
59401 }
59402
59403 if (false === $result) {
59404 throw new InvalidArgumentException(sprintf($errorMessage, $value));
59405 }
59406
59407 $multiselectChoices[] = (string) $result;
59408 }
59409
59410 if ($multiselect) {
59411 return $multiselectChoices;
59412 }
59413
59414 return current($multiselectChoices);
59415 };
59416 }
59417 }
59418 <?php
59419
59420
59421
59422
59423
59424
59425
59426
59427
59428
59429 namespace Symfony\Component\Console\Question;
59430
59431
59432
59433
59434
59435
59436 class ConfirmationQuestion extends Question
59437 {
59438 private $trueAnswerRegex;
59439
59440
59441
59442
59443
59444
59445 public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
59446 {
59447 parent::__construct($question, (bool) $default);
59448
59449 $this->trueAnswerRegex = $trueAnswerRegex;
59450 $this->setNormalizer($this->getDefaultNormalizer());
59451 }
59452
59453
59454
59455
59456
59457
59458 private function getDefaultNormalizer()
59459 {
59460 $default = $this->getDefault();
59461 $regex = $this->trueAnswerRegex;
59462
59463 return function ($answer) use ($default, $regex) {
59464 if (is_bool($answer)) {
59465 return $answer;
59466 }
59467
59468 $answerIsTrue = (bool) preg_match($regex, $answer);
59469 if (false === $default) {
59470 return $answer && $answerIsTrue;
59471 }
59472
59473 return !$answer || $answerIsTrue;
59474 };
59475 }
59476 }
59477 <?php
59478
59479
59480
59481
59482
59483
59484
59485
59486
59487
59488 namespace Symfony\Component\Console\Question;
59489
59490 use Symfony\Component\Console\Exception\InvalidArgumentException;
59491 use Symfony\Component\Console\Exception\LogicException;
59492
59493
59494
59495
59496
59497
59498 class Question
59499 {
59500 private $question;
59501 private $attempts;
59502 private $hidden = false;
59503 private $hiddenFallback = true;
59504 private $autocompleterValues;
59505 private $validator;
59506 private $default;
59507 private $normalizer;
59508
59509
59510
59511
59512
59513 public function __construct($question, $default = null)
59514 {
59515 $this->question = $question;
59516 $this->default = $default;
59517 }
59518
59519
59520
59521
59522
59523
59524 public function getQuestion()
59525 {
59526 return $this->question;
59527 }
59528
59529
59530
59531
59532
59533
59534 public function getDefault()
59535 {
59536 return $this->default;
59537 }
59538
59539
59540
59541
59542
59543
59544 public function isHidden()
59545 {
59546 return $this->hidden;
59547 }
59548
59549
59550
59551
59552
59553
59554
59555
59556
59557
59558 public function setHidden($hidden)
59559 {
59560 if ($this->autocompleterValues) {
59561 throw new LogicException('A hidden question cannot use the autocompleter.');
59562 }
59563
59564 $this->hidden = (bool) $hidden;
59565
59566 return $this;
59567 }
59568
59569
59570
59571
59572
59573
59574 public function isHiddenFallback()
59575 {
59576 return $this->hiddenFallback;
59577 }
59578
59579
59580
59581
59582
59583
59584
59585
59586 public function setHiddenFallback($fallback)
59587 {
59588 $this->hiddenFallback = (bool) $fallback;
59589
59590 return $this;
59591 }
59592
59593
59594
59595
59596
59597
59598 public function getAutocompleterValues()
59599 {
59600 return $this->autocompleterValues;
59601 }
59602
59603
59604
59605
59606
59607
59608
59609
59610
59611
59612
59613 public function setAutocompleterValues($values)
59614 {
59615 if (is_array($values)) {
59616 $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
59617 }
59618
59619 if (null !== $values && !is_array($values) && !$values instanceof \Traversable) {
59620 throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.');
59621 }
59622
59623 if ($this->hidden) {
59624 throw new LogicException('A hidden question cannot use the autocompleter.');
59625 }
59626
59627 $this->autocompleterValues = $values;
59628
59629 return $this;
59630 }
59631
59632
59633
59634
59635
59636
59637
59638
59639 public function setValidator($validator)
59640 {
59641 $this->validator = $validator;
59642
59643 return $this;
59644 }
59645
59646
59647
59648
59649
59650
59651 public function getValidator()
59652 {
59653 return $this->validator;
59654 }
59655
59656
59657
59658
59659
59660
59661
59662
59663
59664
59665
59666
59667 public function setMaxAttempts($attempts)
59668 {
59669 if (null !== $attempts && $attempts < 1) {
59670 throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
59671 }
59672
59673 $this->attempts = $attempts;
59674
59675 return $this;
59676 }
59677
59678
59679
59680
59681
59682
59683
59684
59685 public function getMaxAttempts()
59686 {
59687 return $this->attempts;
59688 }
59689
59690
59691
59692
59693
59694
59695
59696
59697
59698
59699 public function setNormalizer($normalizer)
59700 {
59701 $this->normalizer = $normalizer;
59702
59703 return $this;
59704 }
59705
59706
59707
59708
59709
59710
59711
59712
59713 public function getNormalizer()
59714 {
59715 return $this->normalizer;
59716 }
59717
59718 protected function isAssoc($array)
59719 {
59720 return (bool) count(array_filter(array_keys($array), 'is_string'));
59721 }
59722 }
59723 <?php
59724
59725
59726
59727
59728
59729
59730
59731
59732
59733
59734 namespace Symfony\Component\Console;
59735
59736 use Symfony\Component\Console\Exception\RuntimeException;
59737 use Symfony\Component\Console\Input\StringInput;
59738 use Symfony\Component\Console\Output\ConsoleOutput;
59739 use Symfony\Component\Process\ProcessBuilder;
59740 use Symfony\Component\Process\PhpExecutableFinder;
59741
59742
59743
59744
59745
59746
59747
59748
59749
59750
59751
59752
59753 class Shell
59754 {
59755 private $application;
59756 private $history;
59757 private $output;
59758 private $hasReadline;
59759 private $processIsolation = false;
59760
59761
59762
59763
59764
59765 public function __construct(Application $application)
59766 {
59767 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
59768
59769 $this->hasReadline = function_exists('readline');
59770 $this->application = $application;
59771 $this->history = getenv('HOME').'/.history_'.$application->getName();
59772 $this->output = new ConsoleOutput();
59773 }
59774
59775
59776
59777
59778 public function run()
59779 {
59780 $this->application->setAutoExit(false);
59781 $this->application->setCatchExceptions(true);
59782
59783 if ($this->hasReadline) {
59784 readline_read_history($this->history);
59785 readline_completion_function(array($this, 'autocompleter'));
59786 }
59787
59788 $this->output->writeln($this->getHeader());
59789 $php = null;
59790 if ($this->processIsolation) {
59791 $finder = new PhpExecutableFinder();
59792 $php = $finder->find();
59793 $this->output->writeln(<<<'EOF'
59794 <info>Running with process isolation, you should consider this:</info>
59795   * each command is executed as separate process,
59796   * commands don't support interactivity, all params must be passed explicitly,
59797   * commands output is not colorized.
59798
59799 EOF
59800 );
59801 }
59802
59803 while (true) {
59804 $command = $this->readline();
59805
59806 if (false === $command) {
59807 $this->output->writeln("\n");
59808
59809 break;
59810 }
59811
59812 if ($this->hasReadline) {
59813 readline_add_history($command);
59814 readline_write_history($this->history);
59815 }
59816
59817 if ($this->processIsolation) {
59818 $pb = new ProcessBuilder();
59819
59820 $process = $pb
59821 ->add($php)
59822 ->add($_SERVER['argv'][0])
59823 ->add($command)
59824 ->inheritEnvironmentVariables(true)
59825 ->getProcess()
59826 ;
59827
59828 $output = $this->output;
59829 $process->run(function ($type, $data) use ($output) {
59830 $output->writeln($data);
59831 });
59832
59833 $ret = $process->getExitCode();
59834 } else {
59835 $ret = $this->application->run(new StringInput($command), $this->output);
59836 }
59837
59838 if (0 !== $ret) {
59839 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
59840 }
59841 }
59842 }
59843
59844
59845
59846
59847
59848
59849 protected function getHeader()
59850 {
59851 return <<<EOF
59852
59853 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
59854
59855 At the prompt, type <comment>help</comment> for some help,
59856 or <comment>list</comment> to get a list of available commands.
59857
59858 To exit the shell, type <comment>^D</comment>.
59859
59860 EOF;
59861 }
59862
59863
59864
59865
59866
59867
59868 protected function getPrompt()
59869 {
59870
59871  return $this->output->getFormatter()->format($this->application->getName().' > ');
59872 }
59873
59874 protected function getOutput()
59875 {
59876 return $this->output;
59877 }
59878
59879 protected function getApplication()
59880 {
59881 return $this->application;
59882 }
59883
59884
59885
59886
59887
59888
59889
59890
59891 private function autocompleter($text)
59892 {
59893 $info = readline_info();
59894 $text = substr($info['line_buffer'], 0, $info['end']);
59895
59896 if ($info['point'] !== $info['end']) {
59897 return true;
59898 }
59899
59900
59901  if (false === strpos($text, ' ') || !$text) {
59902 return array_keys($this->application->all());
59903 }
59904
59905
59906  try {
59907 $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
59908 } catch (\Exception $e) {
59909 return true;
59910 }
59911
59912 $list = array('--help');
59913 foreach ($command->getDefinition()->getOptions() as $option) {
59914 $list[] = '--'.$option->getName();
59915 }
59916
59917 return $list;
59918 }
59919
59920
59921
59922
59923
59924
59925 private function readline()
59926 {
59927 if ($this->hasReadline) {
59928 $line = readline($this->getPrompt());
59929 } else {
59930 $this->output->write($this->getPrompt());
59931 $line = fgets(STDIN, 1024);
59932 $line = (false === $line || '' === $line) ? false : rtrim($line);
59933 }
59934
59935 return $line;
59936 }
59937
59938 public function getProcessIsolation()
59939 {
59940 return $this->processIsolation;
59941 }
59942
59943 public function setProcessIsolation($processIsolation)
59944 {
59945 $this->processIsolation = (bool) $processIsolation;
59946
59947 if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
59948 throw new RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
59949 }
59950 }
59951 }
59952 <?php
59953
59954
59955
59956
59957
59958
59959
59960
59961
59962
59963 namespace Symfony\Component\Console\Style;
59964
59965 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59966 use Symfony\Component\Console\Helper\ProgressBar;
59967 use Symfony\Component\Console\Output\OutputInterface;
59968
59969
59970
59971
59972
59973
59974 abstract class OutputStyle implements OutputInterface, StyleInterface
59975 {
59976 private $output;
59977
59978 public function __construct(OutputInterface $output)
59979 {
59980 $this->output = $output;
59981 }
59982
59983
59984
59985
59986 public function newLine($count = 1)
59987 {
59988 $this->output->write(str_repeat(PHP_EOL, $count));
59989 }
59990
59991
59992
59993
59994
59995
59996 public function createProgressBar($max = 0)
59997 {
59998 return new ProgressBar($this->output, $max);
59999 }
60000
60001
60002
60003
60004 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
60005 {
60006 $this->output->write($messages, $newline, $type);
60007 }
60008
60009
60010
60011
60012 public function writeln($messages, $type = self::OUTPUT_NORMAL)
60013 {
60014 $this->output->writeln($messages, $type);
60015 }
60016
60017
60018
60019
60020 public function setVerbosity($level)
60021 {
60022 $this->output->setVerbosity($level);
60023 }
60024
60025
60026
60027
60028 public function getVerbosity()
60029 {
60030 return $this->output->getVerbosity();
60031 }
60032
60033
60034
60035
60036 public function setDecorated($decorated)
60037 {
60038 $this->output->setDecorated($decorated);
60039 }
60040
60041
60042
60043
60044 public function isDecorated()
60045 {
60046 return $this->output->isDecorated();
60047 }
60048
60049
60050
60051
60052 public function setFormatter(OutputFormatterInterface $formatter)
60053 {
60054 $this->output->setFormatter($formatter);
60055 }
60056
60057
60058
60059
60060 public function getFormatter()
60061 {
60062 return $this->output->getFormatter();
60063 }
60064 }
60065 <?php
60066
60067
60068
60069
60070
60071
60072
60073
60074
60075
60076 namespace Symfony\Component\Console\Style;
60077
60078
60079
60080
60081
60082
60083 interface StyleInterface
60084 {
60085
60086
60087
60088
60089
60090 public function title($message);
60091
60092
60093
60094
60095
60096
60097 public function section($message);
60098
60099
60100
60101
60102 public function listing(array $elements);
60103
60104
60105
60106
60107
60108
60109 public function text($message);
60110
60111
60112
60113
60114
60115
60116 public function success($message);
60117
60118
60119
60120
60121
60122
60123 public function error($message);
60124
60125
60126
60127
60128
60129
60130 public function warning($message);
60131
60132
60133
60134
60135
60136
60137 public function note($message);
60138
60139
60140
60141
60142
60143
60144 public function caution($message);
60145
60146
60147
60148
60149 public function table(array $headers, array $rows);
60150
60151
60152
60153
60154
60155
60156
60157
60158
60159
60160 public function ask($question, $default = null, $validator = null);
60161
60162
60163
60164
60165
60166
60167
60168
60169
60170 public function askHidden($question, $validator = null);
60171
60172
60173
60174
60175
60176
60177
60178
60179
60180 public function confirm($question, $default = true);
60181
60182
60183
60184
60185
60186
60187
60188
60189
60190
60191 public function choice($question, array $choices, $default = null);
60192
60193
60194
60195
60196
60197
60198 public function newLine($count = 1);
60199
60200
60201
60202
60203
60204
60205 public function progressStart($max = 0);
60206
60207
60208
60209
60210
60211
60212 public function progressAdvance($step = 1);
60213
60214
60215
60216
60217 public function progressFinish();
60218 }
60219 <?php
60220
60221
60222
60223
60224
60225
60226
60227
60228
60229
60230 namespace Symfony\Component\Console\Style;
60231
60232 use Symfony\Component\Console\Application;
60233 use Symfony\Component\Console\Exception\RuntimeException;
60234 use Symfony\Component\Console\Formatter\OutputFormatter;
60235 use Symfony\Component\Console\Helper\Helper;
60236 use Symfony\Component\Console\Helper\ProgressBar;
60237 use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
60238 use Symfony\Component\Console\Helper\Table;
60239 use Symfony\Component\Console\Input\InputInterface;
60240 use Symfony\Component\Console\Output\BufferedOutput;
60241 use Symfony\Component\Console\Output\OutputInterface;
60242 use Symfony\Component\Console\Question\ChoiceQuestion;
60243 use Symfony\Component\Console\Question\ConfirmationQuestion;
60244 use Symfony\Component\Console\Question\Question;
60245
60246
60247
60248
60249
60250
60251 class SymfonyStyle extends OutputStyle
60252 {
60253 const MAX_LINE_LENGTH = 120;
60254
60255 private $input;
60256 private $questionHelper;
60257 private $progressBar;
60258 private $lineLength;
60259 private $bufferedOutput;
60260
60261 public function __construct(InputInterface $input, OutputInterface $output)
60262 {
60263 $this->input = $input;
60264 $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
60265
60266  $this->lineLength = min($this->getTerminalWidth() - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
60267
60268 parent::__construct($output);
60269 }
60270
60271
60272
60273
60274
60275
60276
60277
60278
60279
60280 public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
60281 {
60282 $messages = is_array($messages) ? array_values($messages) : array($messages);
60283
60284 $this->autoPrependBlock();
60285 $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, true));
60286 $this->newLine();
60287 }
60288
60289
60290
60291
60292 public function title($message)
60293 {
60294 $this->autoPrependBlock();
60295 $this->writeln(array(
60296 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
60297 sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
60298 ));
60299 $this->newLine();
60300 }
60301
60302
60303
60304
60305 public function section($message)
60306 {
60307 $this->autoPrependBlock();
60308 $this->writeln(array(
60309 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
60310 sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
60311 ));
60312 $this->newLine();
60313 }
60314
60315
60316
60317
60318 public function listing(array $elements)
60319 {
60320 $this->autoPrependText();
60321 $elements = array_map(function ($element) {
60322 return sprintf(' * %s', $element);
60323 }, $elements);
60324
60325 $this->writeln($elements);
60326 $this->newLine();
60327 }
60328
60329
60330
60331
60332 public function text($message)
60333 {
60334 $this->autoPrependText();
60335
60336 $messages = is_array($message) ? array_values($message) : array($message);
60337 foreach ($messages as $message) {
60338 $this->writeln(sprintf(' %s', $message));
60339 }
60340 }
60341
60342
60343
60344
60345
60346
60347 public function comment($message)
60348 {
60349 $messages = is_array($message) ? array_values($message) : array($message);
60350
60351 $this->autoPrependBlock();
60352 $this->writeln($this->createBlock($messages, null, null, '<fg=default;bg=default> // </>'));
60353 $this->newLine();
60354 }
60355
60356
60357
60358
60359 public function success($message)
60360 {
60361 $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
60362 }
60363
60364
60365
60366
60367 public function error($message)
60368 {
60369 $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
60370 }
60371
60372
60373
60374
60375 public function warning($message)
60376 {
60377 $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
60378 }
60379
60380
60381
60382
60383 public function note($message)
60384 {
60385 $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
60386 }
60387
60388
60389
60390
60391 public function caution($message)
60392 {
60393 $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
60394 }
60395
60396
60397
60398
60399 public function table(array $headers, array $rows)
60400 {
60401 $style = clone Table::getStyleDefinition('symfony-style-guide');
60402 $style->setCellHeaderFormat('<info>%s</info>');
60403
60404 $table = new Table($this);
60405 $table->setHeaders($headers);
60406 $table->setRows($rows);
60407 $table->setStyle($style);
60408
60409 $table->render();
60410 $this->newLine();
60411 }
60412
60413
60414
60415
60416 public function ask($question, $default = null, $validator = null)
60417 {
60418 $question = new Question($question, $default);
60419 $question->setValidator($validator);
60420
60421 return $this->askQuestion($question);
60422 }
60423
60424
60425
60426
60427 public function askHidden($question, $validator = null)
60428 {
60429 $question = new Question($question);
60430
60431 $question->setHidden(true);
60432 $question->setValidator($validator);
60433
60434 return $this->askQuestion($question);
60435 }
60436
60437
60438
60439
60440 public function confirm($question, $default = true)
60441 {
60442 return $this->askQuestion(new ConfirmationQuestion($question, $default));
60443 }
60444
60445
60446
60447
60448 public function choice($question, array $choices, $default = null)
60449 {
60450 if (null !== $default) {
60451 $values = array_flip($choices);
60452 $default = $values[$default];
60453 }
60454
60455 return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
60456 }
60457
60458
60459
60460
60461 public function progressStart($max = 0)
60462 {
60463 $this->progressBar = $this->createProgressBar($max);
60464 $this->progressBar->start();
60465 }
60466
60467
60468
60469
60470 public function progressAdvance($step = 1)
60471 {
60472 $this->getProgressBar()->advance($step);
60473 }
60474
60475
60476
60477
60478 public function progressFinish()
60479 {
60480 $this->getProgressBar()->finish();
60481 $this->newLine(2);
60482 $this->progressBar = null;
60483 }
60484
60485
60486
60487
60488 public function createProgressBar($max = 0)
60489 {
60490 $progressBar = parent::createProgressBar($max);
60491
60492 if ('\\' !== DIRECTORY_SEPARATOR) {
60493 $progressBar->setEmptyBarCharacter('░'); 
60494  $progressBar->setProgressCharacter('');
60495 $progressBar->setBarCharacter('▓'); 
60496  }
60497
60498 return $progressBar;
60499 }
60500
60501
60502
60503
60504 public function askQuestion(Question $question)
60505 {
60506 if ($this->input->isInteractive()) {
60507 $this->autoPrependBlock();
60508 }
60509
60510 if (!$this->questionHelper) {
60511 $this->questionHelper = new SymfonyQuestionHelper();
60512 }
60513
60514 $answer = $this->questionHelper->ask($this->input, $this, $question);
60515
60516 if ($this->input->isInteractive()) {
60517 $this->newLine();
60518 $this->bufferedOutput->write("\n");
60519 }
60520
60521 return $answer;
60522 }
60523
60524
60525
60526
60527 public function writeln($messages, $type = self::OUTPUT_NORMAL)
60528 {
60529 parent::writeln($messages, $type);
60530 $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
60531 }
60532
60533
60534
60535
60536 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
60537 {
60538 parent::write($messages, $newline, $type);
60539 $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
60540 }
60541
60542
60543
60544
60545 public function newLine($count = 1)
60546 {
60547 parent::newLine($count);
60548 $this->bufferedOutput->write(str_repeat("\n", $count));
60549 }
60550
60551
60552
60553
60554 private function getProgressBar()
60555 {
60556 if (!$this->progressBar) {
60557 throw new RuntimeException('The ProgressBar is not started.');
60558 }
60559
60560 return $this->progressBar;
60561 }
60562
60563 private function getTerminalWidth()
60564 {
60565 $application = new Application();
60566 $dimensions = $application->getTerminalDimensions();
60567
60568 return $dimensions[0] ?: self::MAX_LINE_LENGTH;
60569 }
60570
60571 private function autoPrependBlock()
60572 {
60573 $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
60574
60575 if (!isset($chars[0])) {
60576 return $this->newLine(); 
60577  }
60578
60579  $this->newLine(2 - substr_count($chars, "\n"));
60580 }
60581
60582 private function autoPrependText()
60583 {
60584 $fetched = $this->bufferedOutput->fetch();
60585
60586  if ("\n" !== substr($fetched, -1)) {
60587 $this->newLine();
60588 }
60589 }
60590
60591 private function reduceBuffer($messages)
60592 {
60593
60594  
60595  return array_map(function ($value) {
60596 return substr($value, -4);
60597 }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
60598 }
60599
60600 private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
60601 {
60602 $indentLength = 0;
60603 $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
60604 $lines = array();
60605
60606 if (null !== $type) {
60607 $type = sprintf('[%s] ', $type);
60608 $indentLength = strlen($type);
60609 $lineIndentation = str_repeat(' ', $indentLength);
60610 }
60611
60612
60613  foreach ($messages as $key => $message) {
60614 if ($escape) {
60615 $message = OutputFormatter::escape($message);
60616 }
60617
60618 $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
60619
60620 if (count($messages) > 1 && $key < count($messages) - 1) {
60621 $lines[] = '';
60622 }
60623 }
60624
60625 $firstLineIndex = 0;
60626 if ($padding && $this->isDecorated()) {
60627 $firstLineIndex = 1;
60628 array_unshift($lines, '');
60629 $lines[] = '';
60630 }
60631
60632 foreach ($lines as $i => &$line) {
60633 if (null !== $type) {
60634 $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
60635 }
60636
60637 $line = $prefix.$line;
60638 $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
60639
60640 if ($style) {
60641 $line = sprintf('<%s>%s</>', $style, $line);
60642 }
60643 }
60644
60645 return $lines;
60646 }
60647 }
60648 <?php
60649
60650
60651
60652
60653
60654
60655
60656
60657
60658
60659 namespace Symfony\Component\Console\Tester;
60660
60661 use Symfony\Component\Console\Application;
60662 use Symfony\Component\Console\Input\ArrayInput;
60663 use Symfony\Component\Console\Input\InputInterface;
60664 use Symfony\Component\Console\Output\OutputInterface;
60665 use Symfony\Component\Console\Output\StreamOutput;
60666
60667
60668
60669
60670
60671
60672
60673
60674
60675
60676
60677 class ApplicationTester
60678 {
60679 private $application;
60680 private $input;
60681 private $output;
60682 private $statusCode;
60683
60684 public function __construct(Application $application)
60685 {
60686 $this->application = $application;
60687 }
60688
60689
60690
60691
60692
60693
60694
60695
60696
60697
60698
60699
60700
60701
60702
60703 public function run(array $input, $options = array())
60704 {
60705 $this->input = new ArrayInput($input);
60706 if (isset($options['interactive'])) {
60707 $this->input->setInteractive($options['interactive']);
60708 }
60709
60710 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
60711 if (isset($options['decorated'])) {
60712 $this->output->setDecorated($options['decorated']);
60713 }
60714 if (isset($options['verbosity'])) {
60715 $this->output->setVerbosity($options['verbosity']);
60716 }
60717
60718 return $this->statusCode = $this->application->run($this->input, $this->output);
60719 }
60720
60721
60722
60723
60724
60725
60726
60727
60728 public function getDisplay($normalize = false)
60729 {
60730 rewind($this->output->getStream());
60731
60732 $display = stream_get_contents($this->output->getStream());
60733
60734 if ($normalize) {
60735 $display = str_replace(PHP_EOL, "\n", $display);
60736 }
60737
60738 return $display;
60739 }
60740
60741
60742
60743
60744
60745
60746 public function getInput()
60747 {
60748 return $this->input;
60749 }
60750
60751
60752
60753
60754
60755
60756 public function getOutput()
60757 {
60758 return $this->output;
60759 }
60760
60761
60762
60763
60764
60765
60766 public function getStatusCode()
60767 {
60768 return $this->statusCode;
60769 }
60770 }
60771 <?php
60772
60773
60774
60775
60776
60777
60778
60779
60780
60781
60782 namespace Symfony\Component\Console\Tester;
60783
60784 use Symfony\Component\Console\Command\Command;
60785 use Symfony\Component\Console\Input\ArrayInput;
60786 use Symfony\Component\Console\Output\StreamOutput;
60787 use Symfony\Component\Console\Input\InputInterface;
60788 use Symfony\Component\Console\Output\OutputInterface;
60789
60790
60791
60792
60793
60794
60795 class CommandTester
60796 {
60797 private $command;
60798 private $input;
60799 private $output;
60800 private $statusCode;
60801
60802 public function __construct(Command $command)
60803 {
60804 $this->command = $command;
60805 }
60806
60807
60808
60809
60810
60811
60812
60813
60814
60815
60816
60817
60818
60819
60820
60821 public function execute(array $input, array $options = array())
60822 {
60823
60824  
60825  if (!isset($input['command'])
60826 && (null !== $application = $this->command->getApplication())
60827 && $application->getDefinition()->hasArgument('command')
60828 ) {
60829 $input = array_merge(array('command' => $this->command->getName()), $input);
60830 }
60831
60832 $this->input = new ArrayInput($input);
60833 if (isset($options['interactive'])) {
60834 $this->input->setInteractive($options['interactive']);
60835 }
60836
60837 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
60838 $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
60839 if (isset($options['verbosity'])) {
60840 $this->output->setVerbosity($options['verbosity']);
60841 }
60842
60843 return $this->statusCode = $this->command->run($this->input, $this->output);
60844 }
60845
60846
60847
60848
60849
60850
60851
60852
60853 public function getDisplay($normalize = false)
60854 {
60855 rewind($this->output->getStream());
60856
60857 $display = stream_get_contents($this->output->getStream());
60858
60859 if ($normalize) {
60860 $display = str_replace(PHP_EOL, "\n", $display);
60861 }
60862
60863 return $display;
60864 }
60865
60866
60867
60868
60869
60870
60871 public function getInput()
60872 {
60873 return $this->input;
60874 }
60875
60876
60877
60878
60879
60880
60881 public function getOutput()
60882 {
60883 return $this->output;
60884 }
60885
60886
60887
60888
60889
60890
60891 public function getStatusCode()
60892 {
60893 return $this->statusCode;
60894 }
60895 }
60896 <?php
60897
60898
60899
60900
60901
60902
60903
60904
60905
60906
60907 namespace Symfony\Component\Debug;
60908
60909 use Psr\Log\AbstractLogger;
60910
60911
60912
60913
60914
60915
60916 class BufferingLogger extends AbstractLogger
60917 {
60918 private $logs = array();
60919
60920 public function log($level, $message, array $context = array())
60921 {
60922 $this->logs[] = array($level, $message, $context);
60923 }
60924
60925 public function cleanLogs()
60926 {
60927 $logs = $this->logs;
60928 $this->logs = array();
60929
60930 return $logs;
60931 }
60932 }
60933 <?php
60934
60935
60936
60937
60938
60939
60940
60941
60942
60943
60944 namespace Symfony\Component\Debug;
60945
60946
60947
60948
60949
60950
60951 class Debug
60952 {
60953 private static $enabled = false;
60954
60955
60956
60957
60958
60959
60960
60961
60962
60963
60964
60965
60966 public static function enable($errorReportingLevel = null, $displayErrors = true)
60967 {
60968 if (static::$enabled) {
60969 return;
60970 }
60971
60972 static::$enabled = true;
60973
60974 if (null !== $errorReportingLevel) {
60975 error_reporting($errorReportingLevel);
60976 } else {
60977 error_reporting(-1);
60978 }
60979
60980 if ('cli' !== PHP_SAPI) {
60981 ini_set('display_errors', 0);
60982 ExceptionHandler::register();
60983 } elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
60984
60985  ini_set('display_errors', 1);
60986 }
60987 if ($displayErrors) {
60988 ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
60989 } else {
60990 ErrorHandler::register()->throwAt(0, true);
60991 }
60992
60993 DebugClassLoader::enable();
60994 }
60995 }
60996 <?php
60997
60998
60999
61000
61001
61002
61003
61004
61005
61006
61007 namespace Symfony\Component\Debug;
61008
61009
61010
61011
61012
61013
61014
61015
61016
61017
61018
61019
61020 class DebugClassLoader
61021 {
61022 private $classLoader;
61023 private $isFinder;
61024 private $loaded = array();
61025 private $wasFinder;
61026 private static $caseCheck;
61027 private static $deprecated = array();
61028 private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
61029 private static $darwinCache = array('/' => array('/', array()));
61030
61031
61032
61033
61034 public function __construct($classLoader)
61035 {
61036 $this->wasFinder = is_object($classLoader) && method_exists($classLoader, 'findFile');
61037
61038 if ($this->wasFinder) {
61039 @trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
61040 $this->classLoader = array($classLoader, 'loadClass');
61041 $this->isFinder = true;
61042 } else {
61043 $this->classLoader = $classLoader;
61044 $this->isFinder = is_array($classLoader) && method_exists($classLoader[0], 'findFile');
61045 }
61046
61047 if (!isset(self::$caseCheck)) {
61048 $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR);
61049 $i = strrpos($file, DIRECTORY_SEPARATOR);
61050 $dir = substr($file, 0, 1 + $i);
61051 $file = substr($file, 1 + $i);
61052 $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
61053 $test = realpath($dir.$test);
61054
61055 if (false === $test || false === $i) {
61056
61057  self::$caseCheck = 0;
61058 } elseif (substr($test, -strlen($file)) === $file) {
61059
61060  self::$caseCheck = 1;
61061 } elseif (false !== stripos(PHP_OS, 'darwin')) {
61062
61063  self::$caseCheck = 2;
61064 } else {
61065
61066  self::$caseCheck = 0;
61067 }
61068 }
61069 }
61070
61071
61072
61073
61074
61075
61076 public function getClassLoader()
61077 {
61078 return $this->wasFinder ? $this->classLoader[0] : $this->classLoader;
61079 }
61080
61081
61082
61083
61084 public static function enable()
61085 {
61086
61087  class_exists('Symfony\Component\Debug\ErrorHandler');
61088 class_exists('Psr\Log\LogLevel');
61089
61090 if (!is_array($functions = spl_autoload_functions())) {
61091 return;
61092 }
61093
61094 foreach ($functions as $function) {
61095 spl_autoload_unregister($function);
61096 }
61097
61098 foreach ($functions as $function) {
61099 if (!is_array($function) || !$function[0] instanceof self) {
61100 $function = array(new static($function), 'loadClass');
61101 }
61102
61103 spl_autoload_register($function);
61104 }
61105 }
61106
61107
61108
61109
61110 public static function disable()
61111 {
61112 if (!is_array($functions = spl_autoload_functions())) {
61113 return;
61114 }
61115
61116 foreach ($functions as $function) {
61117 spl_autoload_unregister($function);
61118 }
61119
61120 foreach ($functions as $function) {
61121 if (is_array($function) && $function[0] instanceof self) {
61122 $function = $function[0]->getClassLoader();
61123 }
61124
61125 spl_autoload_register($function);
61126 }
61127 }
61128
61129
61130
61131
61132
61133
61134
61135
61136
61137
61138 public function findFile($class)
61139 {
61140 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
61141
61142 if ($this->wasFinder) {
61143 return $this->classLoader[0]->findFile($class);
61144 }
61145 }
61146
61147
61148
61149
61150
61151
61152
61153
61154
61155
61156 public function loadClass($class)
61157 {
61158 ErrorHandler::stackErrors();
61159
61160 try {
61161 if ($this->isFinder && !isset($this->loaded[$class])) {
61162 $this->loaded[$class] = true;
61163 if ($file = $this->classLoader[0]->findFile($class)) {
61164 require $file;
61165 }
61166 } else {
61167 call_user_func($this->classLoader, $class);
61168 $file = false;
61169 }
61170 } catch (\Exception $e) {
61171 ErrorHandler::unstackErrors();
61172
61173 throw $e;
61174 } catch (\Throwable $e) {
61175 ErrorHandler::unstackErrors();
61176
61177 throw $e;
61178 }
61179
61180 ErrorHandler::unstackErrors();
61181
61182 $exists = class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
61183
61184 if ($class && '\\' === $class[0]) {
61185 $class = substr($class, 1);
61186 }
61187
61188 if ($exists) {
61189 $refl = new \ReflectionClass($class);
61190 $name = $refl->getName();
61191
61192 if ($name !== $class && 0 === strcasecmp($name, $class)) {
61193 throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name));
61194 }
61195
61196 if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
61197 @trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
61198 } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
61199 self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
61200 } else {
61201 if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
61202 $len = 0;
61203 $ns = '';
61204 } else {
61205 $ns = substr($name, 0, $len);
61206 }
61207 $parent = get_parent_class($class);
61208
61209 if (!$parent || strncmp($ns, $parent, $len)) {
61210 if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
61211 @trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
61212 }
61213
61214 $parentInterfaces = array();
61215 $deprecatedInterfaces = array();
61216 if ($parent) {
61217 foreach (class_implements($parent) as $interface) {
61218 $parentInterfaces[$interface] = 1;
61219 }
61220 }
61221
61222 foreach ($refl->getInterfaceNames() as $interface) {
61223 if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
61224 $deprecatedInterfaces[] = $interface;
61225 }
61226 foreach (class_implements($interface) as $interface) {
61227 $parentInterfaces[$interface] = 1;
61228 }
61229 }
61230
61231 foreach ($deprecatedInterfaces as $interface) {
61232 if (!isset($parentInterfaces[$interface])) {
61233 @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);
61234 }
61235 }
61236 }
61237 }
61238 }
61239
61240 if ($file) {
61241 if (!$exists) {
61242 if (false !== strpos($class, '/')) {
61243 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));
61244 }
61245
61246 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));
61247 }
61248 if (self::$caseCheck) {
61249 $real = explode('\\', $class.strrchr($file, '.'));
61250 $tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file));
61251
61252 $i = count($tail) - 1;
61253 $j = count($real) - 1;
61254
61255 while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
61256 --$i;
61257 --$j;
61258 }
61259
61260 array_splice($tail, 0, $i + 1);
61261 }
61262 if (self::$caseCheck && $tail) {
61263 $tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail);
61264 $tailLen = strlen($tail);
61265 $real = $refl->getFileName();
61266
61267 if (2 === self::$caseCheck) {
61268
61269
61270 $i = 1 + strrpos($real, '/');
61271 $file = substr($real, $i);
61272 $real = substr($real, 0, $i);
61273
61274 if (isset(self::$darwinCache[$real])) {
61275 $kDir = $real;
61276 } else {
61277 $kDir = strtolower($real);
61278
61279 if (isset(self::$darwinCache[$kDir])) {
61280 $real = self::$darwinCache[$kDir][0];
61281 } else {
61282 $dir = getcwd();
61283 chdir($real);
61284 $real = getcwd().'/';
61285 chdir($dir);
61286
61287 $dir = $real;
61288 $k = $kDir;
61289 $i = strlen($dir) - 1;
61290 while (!isset(self::$darwinCache[$k])) {
61291 self::$darwinCache[$k] = array($dir, array());
61292 self::$darwinCache[$dir] = &self::$darwinCache[$k];
61293
61294 while ('/' !== $dir[--$i]) {
61295 }
61296 $k = substr($k, 0, ++$i);
61297 $dir = substr($dir, 0, $i--);
61298 }
61299 }
61300 }
61301
61302 $dirFiles = self::$darwinCache[$kDir][1];
61303
61304 if (isset($dirFiles[$file])) {
61305 $kFile = $file;
61306 } else {
61307 $kFile = strtolower($file);
61308
61309 if (!isset($dirFiles[$kFile])) {
61310 foreach (scandir($real, 2) as $f) {
61311 if ('.' !== $f[0]) {
61312 $dirFiles[$f] = $f;
61313 if ($f === $file) {
61314 $kFile = $k = $file;
61315 } elseif ($f !== $k = strtolower($f)) {
61316 $dirFiles[$k] = $f;
61317 }
61318 }
61319 }
61320 self::$darwinCache[$kDir][1] = $dirFiles;
61321 }
61322 }
61323
61324 $real .= $dirFiles[$kFile];
61325 }
61326
61327 if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
61328 && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
61329 ) {
61330 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)));
61331 }
61332 }
61333
61334 return true;
61335 }
61336 }
61337 }
61338 <?php
61339
61340
61341
61342
61343
61344
61345
61346
61347
61348
61349 namespace Symfony\Component\Debug;
61350
61351 use Psr\Log\LogLevel;
61352 use Psr\Log\LoggerInterface;
61353 use Symfony\Component\Debug\Exception\ContextErrorException;
61354 use Symfony\Component\Debug\Exception\FatalErrorException;
61355 use Symfony\Component\Debug\Exception\FatalThrowableError;
61356 use Symfony\Component\Debug\Exception\OutOfMemoryException;
61357 use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
61358 use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
61359 use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
61360 use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
61361
61362
61363
61364
61365
61366
61367
61368
61369
61370
61371
61372
61373
61374
61375
61376
61377
61378
61379
61380
61381
61382
61383
61384 class ErrorHandler
61385 {
61386
61387
61388
61389 const TYPE_DEPRECATION = -100;
61390
61391 private $levels = array(
61392 E_DEPRECATED => 'Deprecated',
61393 E_USER_DEPRECATED => 'User Deprecated',
61394 E_NOTICE => 'Notice',
61395 E_USER_NOTICE => 'User Notice',
61396 E_STRICT => 'Runtime Notice',
61397 E_WARNING => 'Warning',
61398 E_USER_WARNING => 'User Warning',
61399 E_COMPILE_WARNING => 'Compile Warning',
61400 E_CORE_WARNING => 'Core Warning',
61401 E_USER_ERROR => 'User Error',
61402 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
61403 E_COMPILE_ERROR => 'Compile Error',
61404 E_PARSE => 'Parse Error',
61405 E_ERROR => 'Error',
61406 E_CORE_ERROR => 'Core Error',
61407 );
61408
61409 private $loggers = array(
61410 E_DEPRECATED => array(null, LogLevel::INFO),
61411 E_USER_DEPRECATED => array(null, LogLevel::INFO),
61412 E_NOTICE => array(null, LogLevel::WARNING),
61413 E_USER_NOTICE => array(null, LogLevel::WARNING),
61414 E_STRICT => array(null, LogLevel::WARNING),
61415 E_WARNING => array(null, LogLevel::WARNING),
61416 E_USER_WARNING => array(null, LogLevel::WARNING),
61417 E_COMPILE_WARNING => array(null, LogLevel::WARNING),
61418 E_CORE_WARNING => array(null, LogLevel::WARNING),
61419 E_USER_ERROR => array(null, LogLevel::CRITICAL),
61420 E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
61421 E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
61422 E_PARSE => array(null, LogLevel::CRITICAL),
61423 E_ERROR => array(null, LogLevel::CRITICAL),
61424 E_CORE_ERROR => array(null, LogLevel::CRITICAL),
61425 );
61426
61427 private $thrownErrors = 0x1FFF; 
61428  private $scopedErrors = 0x1FFF; 
61429  private $tracedErrors = 0x77FB; 
61430  private $screamedErrors = 0x55; 
61431  private $loggedErrors = 0;
61432
61433 private $loggedTraces = array();
61434 private $isRecursive = 0;
61435 private $isRoot = false;
61436 private $exceptionHandler;
61437 private $bootstrappingLogger;
61438
61439 private static $reservedMemory;
61440 private static $stackedErrors = array();
61441 private static $stackedErrorLevels = array();
61442 private static $toStringException = null;
61443 private static $exitCode = 0;
61444
61445
61446
61447
61448
61449
61450 private $displayErrors = 0x1FFF;
61451
61452
61453
61454
61455
61456
61457
61458
61459
61460 public static function register($handler = null, $replace = true)
61461 {
61462 if (null === self::$reservedMemory) {
61463 self::$reservedMemory = str_repeat('x', 10240);
61464 register_shutdown_function(__CLASS__.'::handleFatalError');
61465 }
61466
61467 $levels = -1;
61468
61469 if ($handlerIsNew = !$handler instanceof self) {
61470
61471  if (null !== $handler) {
61472 $levels = $replace ? $handler : 0;
61473 $replace = true;
61474 }
61475 $handler = new static();
61476 }
61477
61478 if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
61479 restore_error_handler();
61480
61481  set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
61482 $handler->isRoot = true;
61483 }
61484
61485 if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) {
61486 $handler = $prev[0];
61487 $replace = false;
61488 }
61489 if ($replace || !$prev) {
61490 $handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException')));
61491 } else {
61492 restore_error_handler();
61493 }
61494
61495 $handler->throwAt($levels & $handler->thrownErrors, true);
61496
61497 return $handler;
61498 }
61499
61500 public function __construct(BufferingLogger $bootstrappingLogger = null)
61501 {
61502 if ($bootstrappingLogger) {
61503 $this->bootstrappingLogger = $bootstrappingLogger;
61504 $this->setDefaultLogger($bootstrappingLogger);
61505 }
61506 }
61507
61508
61509
61510
61511
61512
61513
61514
61515 public function setDefaultLogger(LoggerInterface $logger, $levels = null, $replace = false)
61516 {
61517 $loggers = array();
61518
61519 if (is_array($levels)) {
61520 foreach ($levels as $type => $logLevel) {
61521 if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
61522 $loggers[$type] = array($logger, $logLevel);
61523 }
61524 }
61525 } else {
61526 if (null === $levels) {
61527 $levels = E_ALL | E_STRICT;
61528 }
61529 foreach ($this->loggers as $type => $log) {
61530 if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
61531 $log[0] = $logger;
61532 $loggers[$type] = $log;
61533 }
61534 }
61535 }
61536
61537 $this->setLoggers($loggers);
61538 }
61539
61540
61541
61542
61543
61544
61545
61546
61547
61548
61549 public function setLoggers(array $loggers)
61550 {
61551 $prevLogged = $this->loggedErrors;
61552 $prev = $this->loggers;
61553 $flush = array();
61554
61555 foreach ($loggers as $type => $log) {
61556 if (!isset($prev[$type])) {
61557 throw new \InvalidArgumentException('Unknown error type: '.$type);
61558 }
61559 if (!is_array($log)) {
61560 $log = array($log);
61561 } elseif (!array_key_exists(0, $log)) {
61562 throw new \InvalidArgumentException('No logger provided');
61563 }
61564 if (null === $log[0]) {
61565 $this->loggedErrors &= ~$type;
61566 } elseif ($log[0] instanceof LoggerInterface) {
61567 $this->loggedErrors |= $type;
61568 } else {
61569 throw new \InvalidArgumentException('Invalid logger provided');
61570 }
61571 $this->loggers[$type] = $log + $prev[$type];
61572
61573 if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
61574 $flush[$type] = $type;
61575 }
61576 }
61577 $this->reRegister($prevLogged | $this->thrownErrors);
61578
61579 if ($flush) {
61580 foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
61581 $type = $log[2]['type'];
61582 if (!isset($flush[$type])) {
61583 $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
61584 } elseif ($this->loggers[$type][0]) {
61585 $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
61586 }
61587 }
61588 }
61589
61590 return $prev;
61591 }
61592
61593
61594
61595
61596
61597
61598
61599
61600
61601
61602 public function setExceptionHandler($handler)
61603 {
61604 if (null !== $handler && !is_callable($handler)) {
61605 throw new \LogicException('The exception handler must be a valid PHP callable.');
61606 }
61607 $prev = $this->exceptionHandler;
61608 $this->exceptionHandler = $handler;
61609
61610 return $prev;
61611 }
61612
61613
61614
61615
61616
61617
61618
61619
61620
61621 public function throwAt($levels, $replace = false)
61622 {
61623 $prev = $this->thrownErrors;
61624 $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
61625 if (!$replace) {
61626 $this->thrownErrors |= $prev;
61627 }
61628 $this->reRegister($prev | $this->loggedErrors);
61629
61630
61631  $this->displayErrors = $this->thrownErrors;
61632
61633 return $prev;
61634 }
61635
61636
61637
61638
61639
61640
61641
61642
61643
61644 public function scopeAt($levels, $replace = false)
61645 {
61646 $prev = $this->scopedErrors;
61647 $this->scopedErrors = (int) $levels;
61648 if (!$replace) {
61649 $this->scopedErrors |= $prev;
61650 }
61651
61652 return $prev;
61653 }
61654
61655
61656
61657
61658
61659
61660
61661
61662
61663 public function traceAt($levels, $replace = false)
61664 {
61665 $prev = $this->tracedErrors;
61666 $this->tracedErrors = (int) $levels;
61667 if (!$replace) {
61668 $this->tracedErrors |= $prev;
61669 }
61670
61671 return $prev;
61672 }
61673
61674
61675
61676
61677
61678
61679
61680
61681
61682 public function screamAt($levels, $replace = false)
61683 {
61684 $prev = $this->screamedErrors;
61685 $this->screamedErrors = (int) $levels;
61686 if (!$replace) {
61687 $this->screamedErrors |= $prev;
61688 }
61689
61690 return $prev;
61691 }
61692
61693
61694
61695
61696 private function reRegister($prev)
61697 {
61698 if ($prev !== $this->thrownErrors | $this->loggedErrors) {
61699 $handler = set_error_handler('var_dump');
61700 $handler = is_array($handler) ? $handler[0] : null;
61701 restore_error_handler();
61702 if ($handler === $this) {
61703 restore_error_handler();
61704 if ($this->isRoot) {
61705 set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
61706 } else {
61707 set_error_handler(array($this, 'handleError'));
61708 }
61709 }
61710 }
61711 }
61712
61713
61714
61715
61716
61717
61718
61719
61720
61721
61722
61723
61724
61725
61726
61727 public function handleError($type, $message, $file, $line)
61728 {
61729 $level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
61730 $log = $this->loggedErrors & $type;
61731 $throw = $this->thrownErrors & $type & $level;
61732 $type &= $level | $this->screamedErrors;
61733
61734 if (!$type || (!$log && !$throw)) {
61735 return $type && $log;
61736 }
61737 $scope = $this->scopedErrors & $type;
61738
61739 if (4 < $numArgs = func_num_args()) {
61740 $context = $scope ? (func_get_arg(4) ?: array()) : array();
61741 $backtrace = 5 < $numArgs ? func_get_arg(5) : null; 
61742  } else {
61743 $context = array();
61744 $backtrace = null;
61745 }
61746
61747 if (isset($context['GLOBALS']) && $scope) {
61748 $e = $context; 
61749  unset($e['GLOBALS'], $context); 
61750  $context = $e;
61751 }
61752
61753 if (null !== $backtrace && $type & E_ERROR) {
61754
61755  
61756  
61757  $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
61758
61759 return true;
61760 }
61761
61762 if ($throw) {
61763 if (null !== self::$toStringException) {
61764 $throw = self::$toStringException;
61765 self::$toStringException = null;
61766 } elseif ($scope && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
61767
61768  $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
61769 } else {
61770 $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
61771 }
61772
61773 if (\PHP_VERSION_ID <= 50407 && (\PHP_VERSION_ID >= 50400 || \PHP_VERSION_ID <= 50317)) {
61774
61775  
61776  
61777
61778 $throw->errorHandlerCanary = new ErrorHandlerCanary();
61779 }
61780
61781 if (E_USER_ERROR & $type) {
61782 $backtrace = $backtrace ?: $throw->getTrace();
61783
61784 for ($i = 1; isset($backtrace[$i]); ++$i) {
61785 if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
61786 && '__toString' === $backtrace[$i]['function']
61787 && '->' === $backtrace[$i]['type']
61788 && !isset($backtrace[$i - 1]['class'])
61789 && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
61790 ) {
61791
61792  
61793  
61794  
61795  
61796  
61797
61798 foreach ($context as $e) {
61799 if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
61800 if (1 === $i) {
61801
61802  $throw = $e;
61803 break;
61804 }
61805 self::$toStringException = $e;
61806
61807 return true;
61808 }
61809 }
61810
61811 if (1 < $i) {
61812
61813  $this->handleException($throw);
61814
61815
61816  return false;
61817 }
61818 }
61819 }
61820 }
61821
61822 throw $throw;
61823 }
61824
61825
61826  $e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
61827 $trace = true;
61828
61829 if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
61830 $trace = false;
61831 } else {
61832 $this->loggedTraces[$e] = 1;
61833 }
61834
61835 $e = compact('type', 'file', 'line', 'level');
61836
61837 if ($type & $level) {
61838 if ($scope) {
61839 $e['scope_vars'] = $context;
61840 if ($trace) {
61841 $e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
61842 }
61843 } elseif ($trace) {
61844 if (null === $backtrace) {
61845 $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
61846 } else {
61847 foreach ($backtrace as &$frame) {
61848 unset($frame['args'], $frame);
61849 }
61850 $e['stack'] = $backtrace;
61851 }
61852 }
61853 }
61854
61855 if ($this->isRecursive) {
61856 $log = 0;
61857 } elseif (self::$stackedErrorLevels) {
61858 self::$stackedErrors[] = array($this->loggers[$type][0], ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
61859 } else {
61860 try {
61861 $this->isRecursive = true;
61862 $this->loggers[$type][0]->log(($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
61863 $this->isRecursive = false;
61864 } catch (\Exception $e) {
61865 $this->isRecursive = false;
61866
61867 throw $e;
61868 } catch (\Throwable $e) {
61869 $this->isRecursive = false;
61870
61871 throw $e;
61872 }
61873 }
61874
61875 return $type && $log;
61876 }
61877
61878
61879
61880
61881
61882
61883
61884
61885
61886 public function handleException($exception, array $error = null)
61887 {
61888 if (null === $error) {
61889 self::$exitCode = 255;
61890 }
61891 if (!$exception instanceof \Exception) {
61892 $exception = new FatalThrowableError($exception);
61893 }
61894 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
61895
61896 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
61897 $e = array(
61898 'type' => $type,
61899 'file' => $exception->getFile(),
61900 'line' => $exception->getLine(),
61901 'level' => error_reporting(),
61902 'stack' => $exception->getTrace(),
61903 );
61904 if ($exception instanceof FatalErrorException) {
61905 if ($exception instanceof FatalThrowableError) {
61906 $error = array(
61907 'type' => $type,
61908 'message' => $message = $exception->getMessage(),
61909 'file' => $e['file'],
61910 'line' => $e['line'],
61911 );
61912 } else {
61913 $message = 'Fatal '.$exception->getMessage();
61914 }
61915 } elseif ($exception instanceof \ErrorException) {
61916 $message = 'Uncaught '.$exception->getMessage();
61917 if ($exception instanceof ContextErrorException) {
61918 $e['context'] = $exception->getContext();
61919 }
61920 } else {
61921 $message = 'Uncaught Exception: '.$exception->getMessage();
61922 }
61923 }
61924 if ($this->loggedErrors & $type) {
61925 try {
61926 $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
61927 } catch (\Exception $handlerException) {
61928 } catch (\Throwable $handlerException) {
61929 }
61930 }
61931 if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
61932 foreach ($this->getFatalErrorHandlers() as $handler) {
61933 if ($e = $handler->handleError($error, $exception)) {
61934 $exception = $e;
61935 break;
61936 }
61937 }
61938 }
61939 if (empty($this->exceptionHandler)) {
61940 throw $exception; 
61941  }
61942 try {
61943 call_user_func($this->exceptionHandler, $exception);
61944 } catch (\Exception $handlerException) {
61945 } catch (\Throwable $handlerException) {
61946 }
61947 if (isset($handlerException)) {
61948 $this->exceptionHandler = null;
61949 $this->handleException($handlerException);
61950 }
61951 }
61952
61953
61954
61955
61956
61957
61958
61959
61960 public static function handleFatalError(array $error = null)
61961 {
61962 if (null === self::$reservedMemory) {
61963 return;
61964 }
61965
61966 self::$reservedMemory = null;
61967
61968 $handler = set_error_handler('var_dump');
61969 $handler = is_array($handler) ? $handler[0] : null;
61970 restore_error_handler();
61971
61972 if (!$handler instanceof self) {
61973 return;
61974 }
61975
61976 if ($exit = null === $error) {
61977 $error = error_get_last();
61978 }
61979
61980 try {
61981 while (self::$stackedErrorLevels) {
61982 static::unstackErrors();
61983 }
61984 } catch (\Exception $exception) {
61985
61986  } catch (\Throwable $exception) {
61987
61988  }
61989
61990 if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
61991
61992  $handler->throwAt(0, true);
61993 $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
61994
61995 if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
61996 $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
61997 } else {
61998 $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
61999 }
62000 }
62001
62002 try {
62003 if (isset($exception)) {
62004 self::$exitCode = 255;
62005 $handler->handleException($exception, $error);
62006 }
62007 } catch (FatalErrorException $e) {
62008
62009  }
62010
62011 if ($exit && self::$exitCode) {
62012 $exitCode = self::$exitCode;
62013 register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); });
62014 }
62015 }
62016
62017
62018
62019
62020
62021
62022
62023
62024
62025
62026
62027
62028 public static function stackErrors()
62029 {
62030 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
62031 }
62032
62033
62034
62035
62036 public static function unstackErrors()
62037 {
62038 $level = array_pop(self::$stackedErrorLevels);
62039
62040 if (null !== $level) {
62041 $e = error_reporting($level);
62042 if ($e !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
62043
62044  error_reporting($e);
62045 }
62046 }
62047
62048 if (empty(self::$stackedErrorLevels)) {
62049 $errors = self::$stackedErrors;
62050 self::$stackedErrors = array();
62051
62052 foreach ($errors as $e) {
62053 $e[0]->log($e[1], $e[2], $e[3]);
62054 }
62055 }
62056 }
62057
62058
62059
62060
62061
62062
62063
62064
62065 protected function getFatalErrorHandlers()
62066 {
62067 return array(
62068 new UndefinedFunctionFatalErrorHandler(),
62069 new UndefinedMethodFatalErrorHandler(),
62070 new ClassNotFoundFatalErrorHandler(),
62071 );
62072 }
62073
62074
62075
62076
62077
62078
62079
62080
62081 public function setLevel($level)
62082 {
62083 @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);
62084
62085 $level = null === $level ? error_reporting() : $level;
62086 $this->throwAt($level, true);
62087 }
62088
62089
62090
62091
62092
62093
62094
62095
62096 public function setDisplayErrors($displayErrors)
62097 {
62098 @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);
62099
62100 if ($displayErrors) {
62101 $this->throwAt($this->displayErrors, true);
62102 } else {
62103 $displayErrors = $this->displayErrors;
62104 $this->throwAt(0, true);
62105 $this->displayErrors = $displayErrors;
62106 }
62107 }
62108
62109
62110
62111
62112
62113
62114
62115
62116
62117 public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
62118 {
62119 @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);
62120
62121 $handler = set_error_handler('var_dump');
62122 $handler = is_array($handler) ? $handler[0] : null;
62123 restore_error_handler();
62124 if (!$handler instanceof self) {
62125 return;
62126 }
62127 if ('deprecation' === $channel) {
62128 $handler->setDefaultLogger($logger, E_DEPRECATED | E_USER_DEPRECATED, true);
62129 $handler->screamAt(E_DEPRECATED | E_USER_DEPRECATED);
62130 } elseif ('scream' === $channel) {
62131 $handler->setDefaultLogger($logger, E_ALL | E_STRICT, false);
62132 $handler->screamAt(E_ALL | E_STRICT);
62133 } elseif ('emergency' === $channel) {
62134 $handler->setDefaultLogger($logger, E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR, true);
62135 $handler->screamAt(E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
62136 }
62137 }
62138
62139
62140
62141
62142 public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
62143 {
62144 $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());
62145
62146 return $this->handleError($level, $message, $file, $line, (array) $context);
62147 }
62148
62149
62150
62151
62152
62153
62154 public function handleFatal()
62155 {
62156 @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);
62157
62158 static::handleFatalError();
62159 }
62160 }
62161
62162
62163
62164
62165
62166
62167
62168
62169 class ErrorHandlerCanary
62170 {
62171 private static $displayErrors = null;
62172
62173 public function __construct()
62174 {
62175 if (null === self::$displayErrors) {
62176 self::$displayErrors = ini_set('display_errors', 1);
62177 }
62178 }
62179
62180 public function __destruct()
62181 {
62182 if (null !== self::$displayErrors) {
62183 ini_set('display_errors', self::$displayErrors);
62184 self::$displayErrors = null;
62185 }
62186 }
62187 }
62188 <?php
62189
62190
62191
62192
62193
62194
62195
62196
62197
62198
62199 namespace Symfony\Component\Debug\Exception;
62200
62201
62202
62203
62204
62205
62206 class ClassNotFoundException extends FatalErrorException
62207 {
62208 public function __construct($message, \ErrorException $previous)
62209 {
62210 parent::__construct(
62211 $message,
62212 $previous->getCode(),
62213 $previous->getSeverity(),
62214 $previous->getFile(),
62215 $previous->getLine(),
62216 $previous->getPrevious()
62217 );
62218 $this->setTrace($previous->getTrace());
62219 }
62220 }
62221 <?php
62222
62223
62224
62225
62226
62227
62228
62229
62230
62231
62232 namespace Symfony\Component\Debug\Exception;
62233
62234
62235
62236
62237
62238
62239 class ContextErrorException extends \ErrorException
62240 {
62241 private $context = array();
62242
62243 public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
62244 {
62245 parent::__construct($message, $code, $severity, $filename, $lineno);
62246 $this->context = $context;
62247 }
62248
62249
62250
62251
62252 public function getContext()
62253 {
62254 return $this->context;
62255 }
62256 }
62257 <?php
62258
62259
62260
62261
62262
62263
62264
62265
62266
62267
62268 namespace Symfony\Component\Debug\Exception;
62269
62270 @trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
62271
62272
62273
62274
62275
62276
62277 class DummyException extends \ErrorException
62278 {
62279 }
62280 <?php
62281
62282
62283
62284
62285
62286
62287
62288
62289
62290
62291 namespace Symfony\Component\HttpKernel\Exception;
62292
62293
62294
62295
62296
62297
62298
62299
62300
62301
62302 class FatalErrorException extends \ErrorException
62303 {
62304 }
62305
62306 namespace Symfony\Component\Debug\Exception;
62307
62308 use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
62309
62310
62311
62312
62313
62314
62315 class FatalErrorException extends LegacyFatalErrorException
62316 {
62317 public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null)
62318 {
62319 parent::__construct($message, $code, $severity, $filename, $lineno);
62320
62321 if (null !== $trace) {
62322 if (!$traceArgs) {
62323 foreach ($trace as &$frame) {
62324 unset($frame['args'], $frame['this'], $frame);
62325 }
62326 }
62327
62328 $this->setTrace($trace);
62329 } elseif (null !== $traceOffset) {
62330 if (function_exists('xdebug_get_function_stack')) {
62331 $trace = xdebug_get_function_stack();
62332 if (0 < $traceOffset) {
62333 array_splice($trace, -$traceOffset);
62334 }
62335
62336 foreach ($trace as &$frame) {
62337 if (!isset($frame['type'])) {
62338
62339  if (isset($frame['class'])) {
62340 $frame['type'] = '::';
62341 }
62342 } elseif ('dynamic' === $frame['type']) {
62343 $frame['type'] = '->';
62344 } elseif ('static' === $frame['type']) {
62345 $frame['type'] = '::';
62346 }
62347
62348
62349  if (!$traceArgs) {
62350 unset($frame['params'], $frame['args']);
62351 } elseif (isset($frame['params']) && !isset($frame['args'])) {
62352 $frame['args'] = $frame['params'];
62353 unset($frame['params']);
62354 }
62355 }
62356
62357 unset($frame);
62358 $trace = array_reverse($trace);
62359 } elseif (function_exists('symfony_debug_backtrace')) {
62360 $trace = symfony_debug_backtrace();
62361 if (0 < $traceOffset) {
62362 array_splice($trace, 0, $traceOffset);
62363 }
62364 } else {
62365 $trace = array();
62366 }
62367
62368 $this->setTrace($trace);
62369 }
62370 }
62371
62372 protected function setTrace($trace)
62373 {
62374 $traceReflector = new \ReflectionProperty('Exception', 'trace');
62375 $traceReflector->setAccessible(true);
62376 $traceReflector->setValue($this, $trace);
62377 }
62378 }
62379 <?php
62380
62381
62382
62383
62384
62385
62386
62387
62388
62389
62390 namespace Symfony\Component\Debug\Exception;
62391
62392
62393
62394
62395
62396
62397 class FatalThrowableError extends FatalErrorException
62398 {
62399 public function __construct(\Throwable $e)
62400 {
62401 if ($e instanceof \ParseError) {
62402 $message = 'Parse error: '.$e->getMessage();
62403 $severity = E_PARSE;
62404 } elseif ($e instanceof \TypeError) {
62405 $message = 'Type error: '.$e->getMessage();
62406 $severity = E_RECOVERABLE_ERROR;
62407 } else {
62408 $message = $e->getMessage();
62409 $severity = E_ERROR;
62410 }
62411
62412 \ErrorException::__construct(
62413 $message,
62414 $e->getCode(),
62415 $severity,
62416 $e->getFile(),
62417 $e->getLine()
62418 );
62419
62420 $this->setTrace($e->getTrace());
62421 }
62422 }
62423 <?php
62424
62425
62426
62427
62428
62429
62430
62431
62432
62433
62434 namespace Symfony\Component\HttpKernel\Exception;
62435
62436 use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;
62437
62438
62439
62440
62441
62442
62443
62444
62445
62446
62447 class FlattenException
62448 {
62449 private $handler;
62450
62451 public static function __callStatic($method, $args)
62452 {
62453 if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) {
62454 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_called_class(), $method));
62455 }
62456
62457 return call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
62458 }
62459
62460 public function __call($method, $args)
62461 {
62462 if (!isset($this->handler)) {
62463 $this->handler = new DebugFlattenException();
62464 }
62465
62466 if (!method_exists($this->handler, $method)) {
62467 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
62468 }
62469
62470 return call_user_func_array(array($this->handler, $method), $args);
62471 }
62472 }
62473
62474 namespace Symfony\Component\Debug\Exception;
62475
62476 use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
62477 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
62478
62479
62480
62481
62482
62483
62484
62485
62486 class FlattenException extends LegacyFlattenException
62487 {
62488 private $message;
62489 private $code;
62490 private $previous;
62491 private $trace;
62492 private $class;
62493 private $statusCode;
62494 private $headers;
62495 private $file;
62496 private $line;
62497
62498 public static function create(\Exception $exception, $statusCode = null, array $headers = array())
62499 {
62500 $e = new static();
62501 $e->setMessage($exception->getMessage());
62502 $e->setCode($exception->getCode());
62503
62504 if ($exception instanceof HttpExceptionInterface) {
62505 $statusCode = $exception->getStatusCode();
62506 $headers = array_merge($headers, $exception->getHeaders());
62507 }
62508
62509 if (null === $statusCode) {
62510 $statusCode = 500;
62511 }
62512
62513 $e->setStatusCode($statusCode);
62514 $e->setHeaders($headers);
62515 $e->setTraceFromException($exception);
62516 $e->setClass(get_class($exception));
62517 $e->setFile($exception->getFile());
62518 $e->setLine($exception->getLine());
62519
62520 $previous = $exception->getPrevious();
62521
62522 if ($previous instanceof \Exception) {
62523 $e->setPrevious(static::create($previous));
62524 } elseif ($previous instanceof \Throwable) {
62525 $e->setPrevious(static::create(new FatalThrowableError($previous)));
62526 }
62527
62528 return $e;
62529 }
62530
62531 public function toArray()
62532 {
62533 $exceptions = array();
62534 foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
62535 $exceptions[] = array(
62536 'message' => $exception->getMessage(),
62537 'class' => $exception->getClass(),
62538 'trace' => $exception->getTrace(),
62539 );
62540 }
62541
62542 return $exceptions;
62543 }
62544
62545 public function getStatusCode()
62546 {
62547 return $this->statusCode;
62548 }
62549
62550 public function setStatusCode($code)
62551 {
62552 $this->statusCode = $code;
62553 }
62554
62555 public function getHeaders()
62556 {
62557 return $this->headers;
62558 }
62559
62560 public function setHeaders(array $headers)
62561 {
62562 $this->headers = $headers;
62563 }
62564
62565 public function getClass()
62566 {
62567 return $this->class;
62568 }
62569
62570 public function setClass($class)
62571 {
62572 $this->class = $class;
62573 }
62574
62575 public function getFile()
62576 {
62577 return $this->file;
62578 }
62579
62580 public function setFile($file)
62581 {
62582 $this->file = $file;
62583 }
62584
62585 public function getLine()
62586 {
62587 return $this->line;
62588 }
62589
62590 public function setLine($line)
62591 {
62592 $this->line = $line;
62593 }
62594
62595 public function getMessage()
62596 {
62597 return $this->message;
62598 }
62599
62600 public function setMessage($message)
62601 {
62602 $this->message = $message;
62603 }
62604
62605 public function getCode()
62606 {
62607 return $this->code;
62608 }
62609
62610 public function setCode($code)
62611 {
62612 $this->code = $code;
62613 }
62614
62615 public function getPrevious()
62616 {
62617 return $this->previous;
62618 }
62619
62620 public function setPrevious(FlattenException $previous)
62621 {
62622 $this->previous = $previous;
62623 }
62624
62625 public function getAllPrevious()
62626 {
62627 $exceptions = array();
62628 $e = $this;
62629 while ($e = $e->getPrevious()) {
62630 $exceptions[] = $e;
62631 }
62632
62633 return $exceptions;
62634 }
62635
62636 public function getTrace()
62637 {
62638 return $this->trace;
62639 }
62640
62641 public function setTraceFromException(\Exception $exception)
62642 {
62643 $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
62644 }
62645
62646 public function setTrace($trace, $file, $line)
62647 {
62648 $this->trace = array();
62649 $this->trace[] = array(
62650 'namespace' => '',
62651 'short_class' => '',
62652 'class' => '',
62653 'type' => '',
62654 'function' => '',
62655 'file' => $file,
62656 'line' => $line,
62657 'args' => array(),
62658 );
62659 foreach ($trace as $entry) {
62660 $class = '';
62661 $namespace = '';
62662 if (isset($entry['class'])) {
62663 $parts = explode('\\', $entry['class']);
62664 $class = array_pop($parts);
62665 $namespace = implode('\\', $parts);
62666 }
62667
62668 $this->trace[] = array(
62669 'namespace' => $namespace,
62670 'short_class' => $class,
62671 'class' => isset($entry['class']) ? $entry['class'] : '',
62672 'type' => isset($entry['type']) ? $entry['type'] : '',
62673 'function' => isset($entry['function']) ? $entry['function'] : null,
62674 'file' => isset($entry['file']) ? $entry['file'] : null,
62675 'line' => isset($entry['line']) ? $entry['line'] : null,
62676 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
62677 );
62678 }
62679 }
62680
62681 private function flattenArgs($args, $level = 0, &$count = 0)
62682 {
62683 $result = array();
62684 foreach ($args as $key => $value) {
62685 if (++$count > 1e4) {
62686 return array('array', '*SKIPPED over 10000 entries*');
62687 }
62688 if ($value instanceof \__PHP_Incomplete_Class) {
62689
62690  $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
62691 } elseif (is_object($value)) {
62692 $result[$key] = array('object', get_class($value));
62693 } elseif (is_array($value)) {
62694 if ($level > 10) {
62695 $result[$key] = array('array', '*DEEP NESTED ARRAY*');
62696 } else {
62697 $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
62698 }
62699 } elseif (null === $value) {
62700 $result[$key] = array('null', null);
62701 } elseif (is_bool($value)) {
62702 $result[$key] = array('boolean', $value);
62703 } elseif (is_resource($value)) {
62704 $result[$key] = array('resource', get_resource_type($value));
62705 } else {
62706 $result[$key] = array('string', (string) $value);
62707 }
62708 }
62709
62710 return $result;
62711 }
62712
62713 private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
62714 {
62715 $array = new \ArrayObject($value);
62716
62717 return $array['__PHP_Incomplete_Class_Name'];
62718 }
62719 }
62720 <?php
62721
62722
62723
62724
62725
62726
62727
62728
62729
62730
62731 namespace Symfony\Component\Debug\Exception;
62732
62733
62734
62735
62736
62737
62738 class OutOfMemoryException extends FatalErrorException
62739 {
62740 }
62741 <?php
62742
62743
62744
62745
62746
62747
62748
62749
62750
62751
62752 namespace Symfony\Component\Debug\Exception;
62753
62754
62755
62756
62757
62758
62759 class UndefinedFunctionException extends FatalErrorException
62760 {
62761 public function __construct($message, \ErrorException $previous)
62762 {
62763 parent::__construct(
62764 $message,
62765 $previous->getCode(),
62766 $previous->getSeverity(),
62767 $previous->getFile(),
62768 $previous->getLine(),
62769 $previous->getPrevious()
62770 );
62771 $this->setTrace($previous->getTrace());
62772 }
62773 }
62774 <?php
62775
62776
62777
62778
62779
62780
62781
62782
62783
62784
62785 namespace Symfony\Component\Debug\Exception;
62786
62787
62788
62789
62790
62791
62792 class UndefinedMethodException extends FatalErrorException
62793 {
62794 public function __construct($message, \ErrorException $previous)
62795 {
62796 parent::__construct(
62797 $message,
62798 $previous->getCode(),
62799 $previous->getSeverity(),
62800 $previous->getFile(),
62801 $previous->getLine(),
62802 $previous->getPrevious()
62803 );
62804 $this->setTrace($previous->getTrace());
62805 }
62806 }
62807 <?php
62808
62809
62810
62811
62812
62813
62814
62815
62816
62817
62818 namespace Symfony\Component\Debug;
62819
62820 use Symfony\Component\HttpFoundation\Response;
62821 use Symfony\Component\Debug\Exception\FlattenException;
62822 use Symfony\Component\Debug\Exception\OutOfMemoryException;
62823
62824
62825
62826
62827
62828
62829
62830
62831
62832
62833
62834
62835
62836 class ExceptionHandler
62837 {
62838 private $debug;
62839 private $charset;
62840 private $handler;
62841 private $caughtBuffer;
62842 private $caughtLength;
62843 private $fileLinkFormat;
62844
62845 public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
62846 {
62847 if (false !== strpos($charset, '%')) {
62848 @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);
62849
62850
62851  $pivot = $fileLinkFormat;
62852 $fileLinkFormat = $charset;
62853 $charset = $pivot;
62854 }
62855 $this->debug = $debug;
62856 $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
62857 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
62858 }
62859
62860
62861
62862
62863
62864
62865
62866
62867
62868
62869 public static function register($debug = true, $charset = null, $fileLinkFormat = null)
62870 {
62871 $handler = new static($debug, $charset, $fileLinkFormat);
62872
62873 $prev = set_exception_handler(array($handler, 'handle'));
62874 if (is_array($prev) && $prev[0] instanceof ErrorHandler) {
62875 restore_exception_handler();
62876 $prev[0]->setExceptionHandler(array($handler, 'handle'));
62877 }
62878
62879 return $handler;
62880 }
62881
62882
62883
62884
62885
62886
62887
62888
62889 public function setHandler($handler)
62890 {
62891 if (null !== $handler && !is_callable($handler)) {
62892 throw new \LogicException('The exception handler must be a valid PHP callable.');
62893 }
62894 $old = $this->handler;
62895 $this->handler = $handler;
62896
62897 return $old;
62898 }
62899
62900
62901
62902
62903
62904
62905
62906
62907 public function setFileLinkFormat($format)
62908 {
62909 $old = $this->fileLinkFormat;
62910 $this->fileLinkFormat = $format;
62911
62912 return $old;
62913 }
62914
62915
62916
62917
62918
62919
62920
62921
62922
62923 public function handle(\Exception $exception)
62924 {
62925 if (null === $this->handler || $exception instanceof OutOfMemoryException) {
62926 $this->failSafeHandle($exception);
62927
62928 return;
62929 }
62930
62931 $caughtLength = $this->caughtLength = 0;
62932
62933 ob_start(array($this, 'catchOutput'));
62934 $this->failSafeHandle($exception);
62935 while (null === $this->caughtBuffer && ob_end_flush()) {
62936
62937  }
62938 if (isset($this->caughtBuffer[0])) {
62939 ob_start(array($this, 'cleanOutput'));
62940 echo $this->caughtBuffer;
62941 $caughtLength = ob_get_length();
62942 }
62943 $this->caughtBuffer = null;
62944
62945 try {
62946 call_user_func($this->handler, $exception);
62947 $this->caughtLength = $caughtLength;
62948 } catch (\Exception $e) {
62949 if (!$caughtLength) {
62950
62951  throw $exception;
62952 }
62953 }
62954 }
62955
62956
62957
62958
62959
62960
62961
62962
62963 private function failSafeHandle(\Exception $exception)
62964 {
62965 if (class_exists('Symfony\Component\HttpFoundation\Response', false)
62966 && __CLASS__ !== get_class($this)
62967 && ($reflector = new \ReflectionMethod($this, 'createResponse'))
62968 && __CLASS__ !== $reflector->class
62969 ) {
62970 $response = $this->createResponse($exception);
62971 $response->sendHeaders();
62972 $response->sendContent();
62973 @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);
62974
62975 return;
62976 }
62977
62978 $this->sendPhpResponse($exception);
62979 }
62980
62981
62982
62983
62984
62985
62986
62987
62988
62989 public function sendPhpResponse($exception)
62990 {
62991 if (!$exception instanceof FlattenException) {
62992 $exception = FlattenException::create($exception);
62993 }
62994
62995 if (!headers_sent()) {
62996 header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
62997 foreach ($exception->getHeaders() as $name => $value) {
62998 header($name.': '.$value, false);
62999 }
63000 header('Content-Type: text/html; charset='.$this->charset);
63001 }
63002
63003 echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
63004 }
63005
63006
63007
63008
63009
63010
63011
63012
63013
63014
63015 public function createResponse($exception)
63016 {
63017 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
63018
63019 if (!$exception instanceof FlattenException) {
63020 $exception = FlattenException::create($exception);
63021 }
63022
63023 return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
63024 }
63025
63026
63027
63028
63029
63030
63031
63032
63033 public function getHtml($exception)
63034 {
63035 if (!$exception instanceof FlattenException) {
63036 $exception = FlattenException::create($exception);
63037 }
63038
63039 return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
63040 }
63041
63042
63043
63044
63045
63046
63047 public function getContent(FlattenException $exception)
63048 {
63049 switch ($exception->getStatusCode()) {
63050 case 404:
63051 $title = 'Sorry, the page you are looking for could not be found.';
63052 break;
63053 default:
63054 $title = 'Whoops, looks like something went wrong.';
63055 }
63056
63057 $content = '';
63058 if ($this->debug) {
63059 try {
63060 $count = count($exception->getAllPrevious());
63061 $total = $count + 1;
63062 foreach ($exception->toArray() as $position => $e) {
63063 $ind = $count - $position + 1;
63064 $class = $this->formatClass($e['class']);
63065 $message = nl2br($this->escapeHtml($e['message']));
63066 $content .= sprintf(<<<'EOF'
63067                         <h2 class="block_exception clear_fix">
63068                             <span class="exception_counter">%d/%d</span>
63069                             <span class="exception_title">%s%s:</span>
63070                             <span class="exception_message">%s</span>
63071                         </h2>
63072                         <div class="block">
63073                             <ol class="traces list_exception">
63074
63075 EOF
63076 , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
63077 foreach ($e['trace'] as $trace) {
63078 $content .= '       <li>';
63079 if ($trace['function']) {
63080 $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
63081 }
63082 if (isset($trace['file']) && isset($trace['line'])) {
63083 $content .= $this->formatPath($trace['file'], $trace['line']);
63084 }
63085 $content .= "</li>\n";
63086 }
63087
63088 $content .= "    </ol>\n</div>\n";
63089 }
63090 } catch (\Exception $e) {
63091
63092  if ($this->debug) {
63093 $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $this->escapeHtml($e->getMessage()));
63094 } else {
63095 $title = 'Whoops, looks like something went wrong.';
63096 }
63097 }
63098 }
63099
63100 return <<<EOF
63101             <div id="sf-resetcontent" class="sf-reset">
63102                 <h1>$title</h1>
63103                 $content
63104             </div>
63105 EOF;
63106 }
63107
63108
63109
63110
63111
63112
63113 public function getStylesheet(FlattenException $exception)
63114 {
63115 return <<<'EOF'
63116             .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
63117             .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
63118             .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
63119             .sf-reset .clear_fix { display:inline-block; }
63120             .sf-reset * html .clear_fix { height:1%; }
63121             .sf-reset .clear_fix { display:block; }
63122             .sf-reset, .sf-reset .block { margin: auto }
63123             .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
63124             .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
63125             .sf-reset strong { font-weight:bold; }
63126             .sf-reset a { color:#6c6159; cursor: default; }
63127             .sf-reset a img { border:none; }
63128             .sf-reset a:hover { text-decoration:underline; }
63129             .sf-reset em { font-style:italic; }
63130             .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
63131             .sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
63132             .sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
63133             .sf-reset .exception_message { margin-left: 3em; display: block; }
63134             .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
63135             .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
63136                 -webkit-border-bottom-right-radius: 16px;
63137                 -webkit-border-bottom-left-radius: 16px;
63138                 -moz-border-radius-bottomright: 16px;
63139                 -moz-border-radius-bottomleft: 16px;
63140                 border-bottom-right-radius: 16px;
63141                 border-bottom-left-radius: 16px;
63142                 border-bottom:1px solid #ccc;
63143                 border-right:1px solid #ccc;
63144                 border-left:1px solid #ccc;
63145                 word-wrap: break-word;
63146             }
63147             .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
63148                 -webkit-border-top-left-radius: 16px;
63149                 -webkit-border-top-right-radius: 16px;
63150                 -moz-border-radius-topleft: 16px;
63151                 -moz-border-radius-topright: 16px;
63152                 border-top-left-radius: 16px;
63153                 border-top-right-radius: 16px;
63154                 border-top:1px solid #ccc;
63155                 border-right:1px solid #ccc;
63156                 border-left:1px solid #ccc;
63157                 overflow: hidden;
63158                 word-wrap: break-word;
63159             }
63160             .sf-reset a { background:none; color:#868686; text-decoration:none; }
63161             .sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
63162             .sf-reset ol { padding: 10px 0; }
63163             .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
63164                 -webkit-border-radius: 10px;
63165                 -moz-border-radius: 10px;
63166                 border-radius: 10px;
63167                 border: 1px solid #ccc;
63168             }
63169 EOF;
63170 }
63171
63172 private function decorate($content, $css)
63173 {
63174 return <<<EOF
63175 <!DOCTYPE html>
63176 <html>
63177     <head>
63178         <meta charset="{$this->charset}" />
63179         <meta name="robots" content="noindex,nofollow" />
63180         <style>
63181             /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
63182             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;}
63183
63184             html { background: #eee; padding: 10px }
63185             img { border: 0; }
63186             #sf-resetcontent { width:970px; margin:0 auto; }
63187             $css
63188         </style>
63189     </head>
63190     <body>
63191         $content
63192     </body>
63193 </html>
63194 EOF;
63195 }
63196
63197 private function formatClass($class)
63198 {
63199 $parts = explode('\\', $class);
63200
63201 return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
63202 }
63203
63204 private function formatPath($path, $line)
63205 {
63206 $path = $this->escapeHtml($path);
63207 $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
63208
63209 if ($linkFormat = $this->fileLinkFormat) {
63210 $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
63211
63212 return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
63213 }
63214
63215 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);
63216 }
63217
63218
63219
63220
63221
63222
63223
63224
63225 private function formatArgs(array $args)
63226 {
63227 $result = array();
63228 foreach ($args as $key => $item) {
63229 if ('object' === $item[0]) {
63230 $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
63231 } elseif ('array' === $item[0]) {
63232 $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
63233 } elseif ('string' === $item[0]) {
63234 $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1]));
63235 } elseif ('null' === $item[0]) {
63236 $formattedValue = '<em>null</em>';
63237 } elseif ('boolean' === $item[0]) {
63238 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
63239 } elseif ('resource' === $item[0]) {
63240 $formattedValue = '<em>resource</em>';
63241 } else {
63242 $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true));
63243 }
63244
63245 $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
63246 }
63247
63248 return implode(', ', $result);
63249 }
63250
63251
63252
63253
63254
63255
63256 protected static function utf8Htmlize($str)
63257 {
63258 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
63259
63260 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
63261 }
63262
63263
63264
63265
63266 private function escapeHtml($str)
63267 {
63268 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset);
63269 }
63270
63271
63272
63273
63274 public function catchOutput($buffer)
63275 {
63276 $this->caughtBuffer = $buffer;
63277
63278 return '';
63279 }
63280
63281
63282
63283
63284 public function cleanOutput($buffer)
63285 {
63286 if ($this->caughtLength) {
63287
63288  $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
63289 if (isset($cleanBuffer[0])) {
63290 $buffer = $cleanBuffer;
63291 }
63292 }
63293
63294 return $buffer;
63295 }
63296 }
63297 <?php
63298
63299
63300
63301
63302
63303
63304
63305
63306
63307
63308 namespace Symfony\Component\Debug\FatalErrorHandler;
63309
63310 use Symfony\Component\Debug\Exception\ClassNotFoundException;
63311 use Symfony\Component\Debug\Exception\FatalErrorException;
63312 use Symfony\Component\Debug\DebugClassLoader;
63313 use Composer\Autoload\ClassLoader as ComposerClassLoader;
63314 use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
63315 use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
63316
63317
63318
63319
63320
63321
63322 class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
63323 {
63324
63325
63326
63327 public function handleError(array $error, FatalErrorException $exception)
63328 {
63329 $messageLen = strlen($error['message']);
63330 $notFoundSuffix = '\' not found';
63331 $notFoundSuffixLen = strlen($notFoundSuffix);
63332 if ($notFoundSuffixLen > $messageLen) {
63333 return;
63334 }
63335
63336 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
63337 return;
63338 }
63339
63340 foreach (array('class', 'interface', 'trait') as $typeName) {
63341 $prefix = ucfirst($typeName).' \'';
63342 $prefixLen = strlen($prefix);
63343 if (0 !== strpos($error['message'], $prefix)) {
63344 continue;
63345 }
63346
63347 $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
63348 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
63349 $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
63350 $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
63351 $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
63352 $tail = ' for another namespace?';
63353 } else {
63354 $className = $fullyQualifiedClassName;
63355 $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
63356 $tail = '?';
63357 }
63358
63359 if ($candidates = $this->getClassCandidates($className)) {
63360 $tail = array_pop($candidates).'"?';
63361 if ($candidates) {
63362 $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
63363 } else {
63364 $tail = ' for "'.$tail;
63365 }
63366 }
63367 $message .= "\nDid you forget a \"use\" statement".$tail;
63368
63369 return new ClassNotFoundException($message, $exception);
63370 }
63371 }
63372
63373
63374
63375
63376
63377
63378
63379
63380
63381
63382
63383 private function getClassCandidates($class)
63384 {
63385 if (!is_array($functions = spl_autoload_functions())) {
63386 return array();
63387 }
63388
63389
63390  $classes = array();
63391
63392 foreach ($functions as $function) {
63393 if (!is_array($function)) {
63394 continue;
63395 }
63396
63397  if ($function[0] instanceof DebugClassLoader) {
63398 $function = $function[0]->getClassLoader();
63399
63400
63401  if (is_object($function)) {
63402 $function = array($function);
63403 }
63404
63405 if (!is_array($function)) {
63406 continue;
63407 }
63408 }
63409
63410 if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader || $function[0] instanceof SymfonyUniversalClassLoader) {
63411 foreach ($function[0]->getPrefixes() as $prefix => $paths) {
63412 foreach ($paths as $path) {
63413 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
63414 }
63415 }
63416 }
63417 if ($function[0] instanceof ComposerClassLoader) {
63418 foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
63419 foreach ($paths as $path) {
63420 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
63421 }
63422 }
63423 }
63424 }
63425
63426 return array_unique($classes);
63427 }
63428
63429
63430
63431
63432
63433
63434
63435
63436 private function findClassInPath($path, $class, $prefix)
63437 {
63438 if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
63439 return array();
63440 }
63441
63442 $classes = array();
63443 $filename = $class.'.php';
63444 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
63445 if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
63446 $classes[] = $class;
63447 }
63448 }
63449
63450 return $classes;
63451 }
63452
63453
63454
63455
63456
63457
63458
63459
63460 private function convertFileToClass($path, $file, $prefix)
63461 {
63462 $candidates = array(
63463
63464  $namespacedClass = str_replace(array($path.DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
63465
63466  $prefix.$namespacedClass,
63467
63468  $prefix.'\\'.$namespacedClass,
63469
63470  str_replace('\\', '_', $namespacedClass),
63471
63472  str_replace('\\', '_', $prefix.$namespacedClass),
63473
63474  str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
63475 );
63476
63477 if ($prefix) {
63478 $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
63479 }
63480
63481
63482  
63483  
63484  foreach ($candidates as $candidate) {
63485 if ($this->classExists($candidate)) {
63486 return $candidate;
63487 }
63488 }
63489
63490 require_once $file;
63491
63492 foreach ($candidates as $candidate) {
63493 if ($this->classExists($candidate)) {
63494 return $candidate;
63495 }
63496 }
63497 }
63498
63499
63500
63501
63502
63503
63504 private function classExists($class)
63505 {
63506 return class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
63507 }
63508 }
63509 <?php
63510
63511
63512
63513
63514
63515
63516
63517
63518
63519
63520 namespace Symfony\Component\Debug\FatalErrorHandler;
63521
63522 use Symfony\Component\Debug\Exception\FatalErrorException;
63523
63524
63525
63526
63527
63528
63529 interface FatalErrorHandlerInterface
63530 {
63531
63532
63533
63534
63535
63536
63537
63538
63539 public function handleError(array $error, FatalErrorException $exception);
63540 }
63541 <?php
63542
63543
63544
63545
63546
63547
63548
63549
63550
63551
63552 namespace Symfony\Component\Debug\FatalErrorHandler;
63553
63554 use Symfony\Component\Debug\Exception\UndefinedFunctionException;
63555 use Symfony\Component\Debug\Exception\FatalErrorException;
63556
63557
63558
63559
63560
63561
63562 class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
63563 {
63564
63565
63566
63567 public function handleError(array $error, FatalErrorException $exception)
63568 {
63569 $messageLen = strlen($error['message']);
63570 $notFoundSuffix = '()';
63571 $notFoundSuffixLen = strlen($notFoundSuffix);
63572 if ($notFoundSuffixLen > $messageLen) {
63573 return;
63574 }
63575
63576 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
63577 return;
63578 }
63579
63580 $prefix = 'Call to undefined function ';
63581 $prefixLen = strlen($prefix);
63582 if (0 !== strpos($error['message'], $prefix)) {
63583 return;
63584 }
63585
63586 $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
63587 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
63588 $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
63589 $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
63590 $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
63591 } else {
63592 $functionName = $fullyQualifiedFunctionName;
63593 $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
63594 }
63595
63596 $candidates = array();
63597 foreach (get_defined_functions() as $type => $definedFunctionNames) {
63598 foreach ($definedFunctionNames as $definedFunctionName) {
63599 if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
63600 $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
63601 } else {
63602 $definedFunctionNameBasename = $definedFunctionName;
63603 }
63604
63605 if ($definedFunctionNameBasename === $functionName) {
63606 $candidates[] = '\\'.$definedFunctionName;
63607 }
63608 }
63609 }
63610
63611 if ($candidates) {
63612 sort($candidates);
63613 $last = array_pop($candidates).'"?';
63614 if ($candidates) {
63615 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
63616 } else {
63617 $candidates = '"'.$last;
63618 }
63619 $message .= "\nDid you mean to call ".$candidates;
63620 }
63621
63622 return new UndefinedFunctionException($message, $exception);
63623 }
63624 }
63625 <?php
63626
63627
63628
63629
63630
63631
63632
63633
63634
63635
63636 namespace Symfony\Component\Debug\FatalErrorHandler;
63637
63638 use Symfony\Component\Debug\Exception\FatalErrorException;
63639 use Symfony\Component\Debug\Exception\UndefinedMethodException;
63640
63641
63642
63643
63644
63645
63646 class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
63647 {
63648
63649
63650
63651 public function handleError(array $error, FatalErrorException $exception)
63652 {
63653 preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
63654 if (!$matches) {
63655 return;
63656 }
63657
63658 $className = $matches[1];
63659 $methodName = $matches[2];
63660
63661 $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
63662
63663 if (!class_exists($className) || null === $methods = get_class_methods($className)) {
63664
63665  return new UndefinedMethodException($message, $exception);
63666 }
63667
63668 $candidates = array();
63669 foreach ($methods as $definedMethodName) {
63670 $lev = levenshtein($methodName, $definedMethodName);
63671 if ($lev <= strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
63672 $candidates[] = $definedMethodName;
63673 }
63674 }
63675
63676 if ($candidates) {
63677 sort($candidates);
63678 $last = array_pop($candidates).'"?';
63679 if ($candidates) {
63680 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
63681 } else {
63682 $candidates = '"'.$last;
63683 }
63684
63685 $message .= "\nDid you mean to call ".$candidates;
63686 }
63687
63688 return new UndefinedMethodException($message, $exception);
63689 }
63690 }
63691 Copyright (c) 2004-2017 Fabien Potencier
63692
63693 Permission is hereby granted, free of charge, to any person obtaining a copy
63694 of this software and associated documentation files (the "Software"), to deal
63695 in the Software without restriction, including without limitation the rights
63696 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
63697 copies of the Software, and to permit persons to whom the Software is furnished
63698 to do so, subject to the following conditions:
63699
63700 The above copyright notice and this permission notice shall be included in all
63701 copies or substantial portions of the Software.
63702
63703 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63704 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63705 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63706 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63707 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63708 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
63709 THE SOFTWARE.
63710 <?php
63711
63712
63713
63714
63715
63716
63717
63718
63719
63720
63721 namespace Symfony\Component\Filesystem\Exception;
63722
63723
63724
63725
63726
63727
63728 interface ExceptionInterface
63729 {
63730 }
63731 <?php
63732
63733
63734
63735
63736
63737
63738
63739
63740
63741
63742 namespace Symfony\Component\Filesystem\Exception;
63743
63744
63745
63746
63747
63748
63749
63750 class FileNotFoundException extends IOException
63751 {
63752 public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
63753 {
63754 if (null === $message) {
63755 if (null === $path) {
63756 $message = 'File could not be found.';
63757 } else {
63758 $message = sprintf('File "%s" could not be found.', $path);
63759 }
63760 }
63761
63762 parent::__construct($message, $code, $previous, $path);
63763 }
63764 }
63765 <?php
63766
63767
63768
63769
63770
63771
63772
63773
63774
63775
63776 namespace Symfony\Component\Filesystem\Exception;
63777
63778
63779
63780
63781
63782
63783
63784
63785 class IOException extends \RuntimeException implements IOExceptionInterface
63786 {
63787 private $path;
63788
63789 public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
63790 {
63791 $this->path = $path;
63792
63793 parent::__construct($message, $code, $previous);
63794 }
63795
63796
63797
63798
63799 public function getPath()
63800 {
63801 return $this->path;
63802 }
63803 }
63804 <?php
63805
63806
63807
63808
63809
63810
63811
63812
63813
63814
63815 namespace Symfony\Component\Filesystem\Exception;
63816
63817
63818
63819
63820
63821
63822 interface IOExceptionInterface extends ExceptionInterface
63823 {
63824
63825
63826
63827
63828
63829 public function getPath();
63830 }
63831 <?php
63832
63833
63834
63835
63836
63837
63838
63839
63840
63841
63842 namespace Symfony\Component\Filesystem;
63843
63844 use Symfony\Component\Filesystem\Exception\IOException;
63845 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
63846
63847
63848
63849
63850
63851
63852 class Filesystem
63853 {
63854
63855
63856
63857
63858
63859
63860
63861
63862
63863
63864
63865
63866
63867
63868 public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
63869 {
63870 $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
63871 if ($originIsLocal && !is_file($originFile)) {
63872 throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
63873 }
63874
63875 $this->mkdir(dirname($targetFile));
63876
63877 $doCopy = true;
63878 if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
63879 $doCopy = filemtime($originFile) > filemtime($targetFile);
63880 }
63881
63882 if ($doCopy) {
63883
63884  if (false === $source = @fopen($originFile, 'r')) {
63885 throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
63886 }
63887
63888
63889  if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
63890 throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
63891 }
63892
63893 $bytesCopied = stream_copy_to_stream($source, $target);
63894 fclose($source);
63895 fclose($target);
63896 unset($source, $target);
63897
63898 if (!is_file($targetFile)) {
63899 throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
63900 }
63901
63902 if ($originIsLocal) {
63903
63904  @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
63905
63906 if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
63907 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);
63908 }
63909 }
63910 }
63911 }
63912
63913
63914
63915
63916
63917
63918
63919
63920
63921 public function mkdir($dirs, $mode = 0777)
63922 {
63923 foreach ($this->toIterator($dirs) as $dir) {
63924 if (is_dir($dir)) {
63925 continue;
63926 }
63927
63928 if (true !== @mkdir($dir, $mode, true)) {
63929 $error = error_get_last();
63930 if (!is_dir($dir)) {
63931
63932  if ($error) {
63933 throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']), 0, null, $dir);
63934 }
63935 throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
63936 }
63937 }
63938 }
63939 }
63940
63941
63942
63943
63944
63945
63946
63947
63948 public function exists($files)
63949 {
63950 $maxPathLength = PHP_MAXPATHLEN - 2;
63951
63952 foreach ($this->toIterator($files) as $file) {
63953 if (strlen($file) > $maxPathLength) {
63954 throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
63955 }
63956
63957 if (!file_exists($file)) {
63958 return false;
63959 }
63960 }
63961
63962 return true;
63963 }
63964
63965
63966
63967
63968
63969
63970
63971
63972
63973
63974 public function touch($files, $time = null, $atime = null)
63975 {
63976 foreach ($this->toIterator($files) as $file) {
63977 $touch = $time ? @touch($file, $time, $atime) : @touch($file);
63978 if (true !== $touch) {
63979 throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
63980 }
63981 }
63982 }
63983
63984
63985
63986
63987
63988
63989
63990
63991 public function remove($files)
63992 {
63993 if ($files instanceof \Traversable) {
63994 $files = iterator_to_array($files, false);
63995 } elseif (!is_array($files)) {
63996 $files = array($files);
63997 }
63998 $files = array_reverse($files);
63999 foreach ($files as $file) {
64000 if (is_link($file)) {
64001
64002  if (!@(unlink($file) || '\\' !== DIRECTORY_SEPARATOR || rmdir($file)) && file_exists($file)) {
64003 $error = error_get_last();
64004 throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, $error['message']));
64005 }
64006 } elseif (is_dir($file)) {
64007 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
64008
64009 if (!@rmdir($file) && file_exists($file)) {
64010 $error = error_get_last();
64011 throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, $error['message']));
64012 }
64013 } elseif (!@unlink($file) && file_exists($file)) {
64014 $error = error_get_last();
64015 throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, $error['message']));
64016 }
64017 }
64018 }
64019
64020
64021
64022
64023
64024
64025
64026
64027
64028
64029
64030 public function chmod($files, $mode, $umask = 0000, $recursive = false)
64031 {
64032 foreach ($this->toIterator($files) as $file) {
64033 if (true !== @chmod($file, $mode & ~$umask)) {
64034 throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
64035 }
64036 if ($recursive && is_dir($file) && !is_link($file)) {
64037 $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
64038 }
64039 }
64040 }
64041
64042
64043
64044
64045
64046
64047
64048
64049
64050
64051 public function chown($files, $user, $recursive = false)
64052 {
64053 foreach ($this->toIterator($files) as $file) {
64054 if ($recursive && is_dir($file) && !is_link($file)) {
64055 $this->chown(new \FilesystemIterator($file), $user, true);
64056 }
64057 if (is_link($file) && function_exists('lchown')) {
64058 if (true !== @lchown($file, $user)) {
64059 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
64060 }
64061 } else {
64062 if (true !== @chown($file, $user)) {
64063 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
64064 }
64065 }
64066 }
64067 }
64068
64069
64070
64071
64072
64073
64074
64075
64076
64077
64078 public function chgrp($files, $group, $recursive = false)
64079 {
64080 foreach ($this->toIterator($files) as $file) {
64081 if ($recursive && is_dir($file) && !is_link($file)) {
64082 $this->chgrp(new \FilesystemIterator($file), $group, true);
64083 }
64084 if (is_link($file) && function_exists('lchgrp')) {
64085 if (true !== @lchgrp($file, $group) || (defined('HHVM_VERSION') && !posix_getgrnam($group))) {
64086 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
64087 }
64088 } else {
64089 if (true !== @chgrp($file, $group)) {
64090 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
64091 }
64092 }
64093 }
64094 }
64095
64096
64097
64098
64099
64100
64101
64102
64103
64104
64105
64106 public function rename($origin, $target, $overwrite = false)
64107 {
64108
64109  if (!$overwrite && $this->isReadable($target)) {
64110 throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
64111 }
64112
64113 if (true !== @rename($origin, $target)) {
64114 if (is_dir($origin)) {
64115
64116  $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
64117 $this->remove($origin);
64118
64119 return;
64120 }
64121 throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
64122 }
64123 }
64124
64125
64126
64127
64128
64129
64130
64131
64132
64133
64134 private function isReadable($filename)
64135 {
64136 $maxPathLength = PHP_MAXPATHLEN - 2;
64137
64138 if (strlen($filename) > $maxPathLength) {
64139 throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename);
64140 }
64141
64142 return is_readable($filename);
64143 }
64144
64145
64146
64147
64148
64149
64150
64151
64152
64153
64154 public function symlink($originDir, $targetDir, $copyOnWindows = false)
64155 {
64156 if ('\\' === DIRECTORY_SEPARATOR) {
64157 $originDir = strtr($originDir, '/', '\\');
64158 $targetDir = strtr($targetDir, '/', '\\');
64159
64160 if ($copyOnWindows) {
64161 $this->mirror($originDir, $targetDir);
64162
64163 return;
64164 }
64165 }
64166
64167 $this->mkdir(dirname($targetDir));
64168
64169 $ok = false;
64170 if (is_link($targetDir)) {
64171 if (readlink($targetDir) != $originDir) {
64172 $this->remove($targetDir);
64173 } else {
64174 $ok = true;
64175 }
64176 }
64177
64178 if (!$ok && true !== @symlink($originDir, $targetDir)) {
64179 $report = error_get_last();
64180 if (is_array($report)) {
64181 if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
64182 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);
64183 }
64184 }
64185 throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
64186 }
64187 }
64188
64189
64190
64191
64192
64193
64194
64195
64196
64197 public function makePathRelative($endPath, $startPath)
64198 {
64199
64200  if ('\\' === DIRECTORY_SEPARATOR) {
64201 $endPath = str_replace('\\', '/', $endPath);
64202 $startPath = str_replace('\\', '/', $startPath);
64203 }
64204
64205 $stripDriveLetter = function ($path) {
64206 if (strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) {
64207 return substr($path, 2);
64208 }
64209
64210 return $path;
64211 };
64212
64213 $endPath = $stripDriveLetter($endPath);
64214 $startPath = $stripDriveLetter($startPath);
64215
64216
64217  $startPathArr = explode('/', trim($startPath, '/'));
64218 $endPathArr = explode('/', trim($endPath, '/'));
64219
64220 $normalizePathArray = function ($pathSegments, $absolute) {
64221 $result = array();
64222
64223 foreach ($pathSegments as $segment) {
64224 if ('..' === $segment && ($absolute || count($result))) {
64225 array_pop($result);
64226 } elseif ('.' !== $segment) {
64227 $result[] = $segment;
64228 }
64229 }
64230
64231 return $result;
64232 };
64233
64234 $startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath));
64235 $endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath));
64236
64237
64238  $index = 0;
64239 while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
64240 ++$index;
64241 }
64242
64243
64244  if (1 === count($startPathArr) && '' === $startPathArr[0]) {
64245 $depth = 0;
64246 } else {
64247 $depth = count($startPathArr) - $index;
64248 }
64249
64250
64251  $traverser = str_repeat('../', $depth);
64252
64253 $endPathRemainder = implode('/', array_slice($endPathArr, $index));
64254
64255
64256  $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
64257
64258 return '' === $relativePath ? './' : $relativePath;
64259 }
64260
64261
64262
64263
64264
64265
64266
64267
64268
64269
64270
64271
64272
64273
64274
64275 public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
64276 {
64277 $targetDir = rtrim($targetDir, '/\\');
64278 $originDir = rtrim($originDir, '/\\');
64279 $originDirLen = strlen($originDir);
64280
64281
64282  if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
64283 $deleteIterator = $iterator;
64284 if (null === $deleteIterator) {
64285 $flags = \FilesystemIterator::SKIP_DOTS;
64286 $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
64287 }
64288 $targetDirLen = strlen($targetDir);
64289 foreach ($deleteIterator as $file) {
64290 $origin = $originDir.substr($file->getPathname(), $targetDirLen);
64291 if (!$this->exists($origin)) {
64292 $this->remove($file);
64293 }
64294 }
64295 }
64296
64297 $copyOnWindows = false;
64298 if (isset($options['copy_on_windows'])) {
64299 $copyOnWindows = $options['copy_on_windows'];
64300 }
64301
64302 if (null === $iterator) {
64303 $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
64304 $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
64305 }
64306
64307 if ($this->exists($originDir)) {
64308 $this->mkdir($targetDir);
64309 }
64310
64311 foreach ($iterator as $file) {
64312 $target = $targetDir.substr($file->getPathname(), $originDirLen);
64313
64314 if ($copyOnWindows) {
64315 if (is_file($file)) {
64316 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
64317 } elseif (is_dir($file)) {
64318 $this->mkdir($target);
64319 } else {
64320 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
64321 }
64322 } else {
64323 if (is_link($file)) {
64324 $this->symlink($file->getLinkTarget(), $target);
64325 } elseif (is_dir($file)) {
64326 $this->mkdir($target);
64327 } elseif (is_file($file)) {
64328 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
64329 } else {
64330 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
64331 }
64332 }
64333 }
64334 }
64335
64336
64337
64338
64339
64340
64341
64342
64343 public function isAbsolutePath($file)
64344 {
64345 return strspn($file, '/\\', 0, 1)
64346 || (strlen($file) > 3 && ctype_alpha($file[0])
64347 && ':' === substr($file, 1, 1)
64348 && strspn($file, '/\\', 2, 1)
64349 )
64350 || null !== parse_url($file, PHP_URL_SCHEME)
64351 ;
64352 }
64353
64354
64355
64356
64357
64358
64359
64360
64361
64362
64363 public function tempnam($dir, $prefix)
64364 {
64365 list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
64366
64367
64368  if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) {
64369 $tmpFile = @tempnam($hierarchy, $prefix);
64370
64371
64372  if (false !== $tmpFile) {
64373 if (null !== $scheme && 'gs' !== $scheme) {
64374 return $scheme.'://'.$tmpFile;
64375 }
64376
64377 return $tmpFile;
64378 }
64379
64380 throw new IOException('A temporary file could not be created.');
64381 }
64382
64383
64384  for ($i = 0; $i < 10; ++$i) {
64385
64386  $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true);
64387
64388
64389  
64390  $handle = @fopen($tmpFile, 'x+');
64391
64392
64393  if (false === $handle) {
64394 continue;
64395 }
64396
64397
64398  @fclose($handle);
64399
64400 return $tmpFile;
64401 }
64402
64403 throw new IOException('A temporary file could not be created.');
64404 }
64405
64406
64407
64408
64409
64410
64411
64412
64413
64414
64415
64416 public function dumpFile($filename, $content, $mode = 0666)
64417 {
64418 $dir = dirname($filename);
64419
64420 if (!is_dir($dir)) {
64421 $this->mkdir($dir);
64422 }
64423
64424 if (!is_writable($dir)) {
64425 throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
64426 }
64427
64428 $tmpFile = $this->tempnam($dir, basename($filename));
64429
64430 if (false === @file_put_contents($tmpFile, $content)) {
64431 throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
64432 }
64433
64434 if (null !== $mode) {
64435 if (func_num_args() > 2) {
64436 @trigger_error('Support for modifying file permissions is deprecated since version 2.3.12 and will be removed in 3.0.', E_USER_DEPRECATED);
64437 }
64438
64439 $this->chmod($tmpFile, $mode);
64440 } elseif (file_exists($filename)) {
64441 @chmod($tmpFile, fileperms($filename));
64442 }
64443
64444 $this->rename($tmpFile, $filename, true);
64445 }
64446
64447
64448
64449
64450
64451
64452 private function toIterator($files)
64453 {
64454 if (!$files instanceof \Traversable) {
64455 $files = new \ArrayObject(is_array($files) ? $files : array($files));
64456 }
64457
64458 return $files;
64459 }
64460
64461
64462
64463
64464
64465
64466
64467
64468 private function getSchemeAndHierarchy($filename)
64469 {
64470 $components = explode('://', $filename, 2);
64471
64472 return 2 === count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
64473 }
64474 }
64475 Copyright (c) 2004-2017 Fabien Potencier
64476
64477 Permission is hereby granted, free of charge, to any person obtaining a copy
64478 of this software and associated documentation files (the "Software"), to deal
64479 in the Software without restriction, including without limitation the rights
64480 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
64481 copies of the Software, and to permit persons to whom the Software is furnished
64482 to do so, subject to the following conditions:
64483
64484 The above copyright notice and this permission notice shall be included in all
64485 copies or substantial portions of the Software.
64486
64487 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
64488 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64489 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
64490 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
64491 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
64492 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64493 THE SOFTWARE.
64494 <?php
64495
64496
64497
64498
64499
64500
64501
64502
64503
64504
64505 namespace Symfony\Component\Filesystem;
64506
64507 use Symfony\Component\Filesystem\Exception\IOException;
64508
64509
64510
64511
64512
64513
64514
64515
64516
64517
64518
64519
64520
64521
64522 class LockHandler
64523 {
64524 private $file;
64525 private $handle;
64526
64527
64528
64529
64530
64531
64532
64533 public function __construct($name, $lockPath = null)
64534 {
64535 $lockPath = $lockPath ?: sys_get_temp_dir();
64536
64537 if (!is_dir($lockPath)) {
64538 $fs = new Filesystem();
64539 $fs->mkdir($lockPath);
64540 }
64541
64542 if (!is_writable($lockPath)) {
64543 throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
64544 }
64545
64546 $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
64547 }
64548
64549
64550
64551
64552
64553
64554
64555
64556
64557
64558 public function lock($blocking = false)
64559 {
64560 if ($this->handle) {
64561 return true;
64562 }
64563
64564 $error = null;
64565
64566
64567  set_error_handler(function ($errno, $msg) use (&$error) {
64568 $error = $msg;
64569 });
64570
64571 if (!$this->handle = fopen($this->file, 'r')) {
64572 if ($this->handle = fopen($this->file, 'x')) {
64573 chmod($this->file, 0444);
64574 } elseif (!$this->handle = fopen($this->file, 'r')) {
64575 usleep(100); 
64576  $this->handle = fopen($this->file, 'r');
64577 }
64578 }
64579 restore_error_handler();
64580
64581 if (!$this->handle) {
64582 throw new IOException($error, 0, null, $this->file);
64583 }
64584
64585
64586  
64587  if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
64588 fclose($this->handle);
64589 $this->handle = null;
64590
64591 return false;
64592 }
64593
64594 return true;
64595 }
64596
64597
64598
64599
64600 public function release()
64601 {
64602 if ($this->handle) {
64603 flock($this->handle, LOCK_UN | LOCK_NB);
64604 fclose($this->handle);
64605 $this->handle = null;
64606 }
64607 }
64608 }
64609 <?php
64610
64611
64612
64613
64614
64615
64616
64617
64618
64619
64620 namespace Symfony\Component\Finder\Adapter;
64621
64622 @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);
64623
64624
64625
64626
64627
64628
64629
64630
64631 abstract class AbstractAdapter implements AdapterInterface
64632 {
64633 protected $followLinks = false;
64634 protected $mode = 0;
64635 protected $minDepth = 0;
64636 protected $maxDepth = PHP_INT_MAX;
64637 protected $exclude = array();
64638 protected $names = array();
64639 protected $notNames = array();
64640 protected $contains = array();
64641 protected $notContains = array();
64642 protected $sizes = array();
64643 protected $dates = array();
64644 protected $filters = array();
64645 protected $sort = false;
64646 protected $paths = array();
64647 protected $notPaths = array();
64648 protected $ignoreUnreadableDirs = false;
64649
64650 private static $areSupported = array();
64651
64652
64653
64654
64655 public function isSupported()
64656 {
64657 $name = $this->getName();
64658
64659 if (!array_key_exists($name, self::$areSupported)) {
64660 self::$areSupported[$name] = $this->canBeUsed();
64661 }
64662
64663 return self::$areSupported[$name];
64664 }
64665
64666
64667
64668
64669 public function setFollowLinks($followLinks)
64670 {
64671 $this->followLinks = $followLinks;
64672
64673 return $this;
64674 }
64675
64676
64677
64678
64679 public function setMode($mode)
64680 {
64681 $this->mode = $mode;
64682
64683 return $this;
64684 }
64685
64686
64687
64688
64689 public function setDepths(array $depths)
64690 {
64691 $this->minDepth = 0;
64692 $this->maxDepth = PHP_INT_MAX;
64693
64694 foreach ($depths as $comparator) {
64695 switch ($comparator->getOperator()) {
64696 case '>':
64697 $this->minDepth = $comparator->getTarget() + 1;
64698 break;
64699 case '>=':
64700 $this->minDepth = $comparator->getTarget();
64701 break;
64702 case '<':
64703 $this->maxDepth = $comparator->getTarget() - 1;
64704 break;
64705 case '<=':
64706 $this->maxDepth = $comparator->getTarget();
64707 break;
64708 default:
64709 $this->minDepth = $this->maxDepth = $comparator->getTarget();
64710 }
64711 }
64712
64713 return $this;
64714 }
64715
64716
64717
64718
64719 public function setExclude(array $exclude)
64720 {
64721 $this->exclude = $exclude;
64722
64723 return $this;
64724 }
64725
64726
64727
64728
64729 public function setNames(array $names)
64730 {
64731 $this->names = $names;
64732
64733 return $this;
64734 }
64735
64736
64737
64738
64739 public function setNotNames(array $notNames)
64740 {
64741 $this->notNames = $notNames;
64742
64743 return $this;
64744 }
64745
64746
64747
64748
64749 public function setContains(array $contains)
64750 {
64751 $this->contains = $contains;
64752
64753 return $this;
64754 }
64755
64756
64757
64758
64759 public function setNotContains(array $notContains)
64760 {
64761 $this->notContains = $notContains;
64762
64763 return $this;
64764 }
64765
64766
64767
64768
64769 public function setSizes(array $sizes)
64770 {
64771 $this->sizes = $sizes;
64772
64773 return $this;
64774 }
64775
64776
64777
64778
64779 public function setDates(array $dates)
64780 {
64781 $this->dates = $dates;
64782
64783 return $this;
64784 }
64785
64786
64787
64788
64789 public function setFilters(array $filters)
64790 {
64791 $this->filters = $filters;
64792
64793 return $this;
64794 }
64795
64796
64797
64798
64799 public function setSort($sort)
64800 {
64801 $this->sort = $sort;
64802
64803 return $this;
64804 }
64805
64806
64807
64808
64809 public function setPath(array $paths)
64810 {
64811 $this->paths = $paths;
64812
64813 return $this;
64814 }
64815
64816
64817
64818
64819 public function setNotPath(array $notPaths)
64820 {
64821 $this->notPaths = $notPaths;
64822
64823 return $this;
64824 }
64825
64826
64827
64828
64829 public function ignoreUnreadableDirs($ignore = true)
64830 {
64831 $this->ignoreUnreadableDirs = (bool) $ignore;
64832
64833 return $this;
64834 }
64835
64836
64837
64838
64839
64840
64841
64842
64843
64844
64845
64846
64847 abstract protected function canBeUsed();
64848 }
64849 <?php
64850
64851
64852
64853
64854
64855
64856
64857
64858
64859
64860 namespace Symfony\Component\Finder\Adapter;
64861
64862 @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);
64863
64864 use Symfony\Component\Finder\Exception\AccessDeniedException;
64865 use Symfony\Component\Finder\Iterator;
64866 use Symfony\Component\Finder\Shell\Shell;
64867 use Symfony\Component\Finder\Expression\Expression;
64868 use Symfony\Component\Finder\Shell\Command;
64869 use Symfony\Component\Finder\Comparator\NumberComparator;
64870 use Symfony\Component\Finder\Comparator\DateComparator;
64871
64872
64873
64874
64875
64876
64877
64878
64879 abstract class AbstractFindAdapter extends AbstractAdapter
64880 {
64881 protected $shell;
64882
64883 public function __construct()
64884 {
64885 $this->shell = new Shell();
64886 }
64887
64888
64889
64890
64891 public function searchInDirectory($dir)
64892 {
64893
64894  $dir = realpath($dir);
64895
64896
64897  if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
64898 return new Iterator\FilePathsIterator(array(), $dir);
64899 }
64900
64901 $command = Command::create();
64902 $find = $this->buildFindCommand($command, $dir);
64903
64904 if ($this->followLinks) {
64905 $find->add('-follow');
64906 }
64907
64908 $find->add('-mindepth')->add($this->minDepth + 1);
64909
64910 if (PHP_INT_MAX !== $this->maxDepth) {
64911 $find->add('-maxdepth')->add($this->maxDepth + 1);
64912 }
64913
64914 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
64915 $find->add('-type d');
64916 } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
64917 $find->add('-type f');
64918 }
64919
64920 $this->buildNamesFiltering($find, $this->names);
64921 $this->buildNamesFiltering($find, $this->notNames, true);
64922 $this->buildPathsFiltering($find, $dir, $this->paths);
64923 $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
64924 $this->buildSizesFiltering($find, $this->sizes);
64925 $this->buildDatesFiltering($find, $this->dates);
64926
64927 $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
64928 $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
64929
64930 if ($useGrep && ($this->contains || $this->notContains)) {
64931 $grep = $command->ins('grep');
64932 $this->buildContentFiltering($grep, $this->contains);
64933 $this->buildContentFiltering($grep, $this->notContains, true);
64934 }
64935
64936 if ($useSort) {
64937 $this->buildSorting($command, $this->sort);
64938 }
64939
64940 $command->setErrorHandler(
64941 $this->ignoreUnreadableDirs
64942
64943  ? function ($stderr) { }
64944 : function ($stderr) { throw new AccessDeniedException($stderr); }
64945 );
64946
64947 $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
64948 $iterator = new Iterator\FilePathsIterator($paths, $dir);
64949
64950 if ($this->exclude) {
64951 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
64952 }
64953
64954 if (!$useGrep && ($this->contains || $this->notContains)) {
64955 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
64956 }
64957
64958 if ($this->filters) {
64959 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
64960 }
64961
64962 if (!$useSort && $this->sort) {
64963 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
64964 $iterator = $iteratorAggregate->getIterator();
64965 }
64966
64967 return $iterator;
64968 }
64969
64970
64971
64972
64973 protected function canBeUsed()
64974 {
64975 return $this->shell->testCommand('find');
64976 }
64977
64978
64979
64980
64981
64982
64983
64984 protected function buildFindCommand(Command $command, $dir)
64985 {
64986 return $command
64987 ->ins('find')
64988 ->add('find ')
64989 ->arg($dir)
64990 ->add('-noleaf'); 
64991  }
64992
64993
64994
64995
64996
64997
64998 private function buildNamesFiltering(Command $command, array $names, $not = false)
64999 {
65000 if (0 === count($names)) {
65001 return;
65002 }
65003
65004 $command->add($not ? '-not' : null)->cmd('(');
65005
65006 foreach ($names as $i => $name) {
65007 $expr = Expression::create($name);
65008
65009
65010  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
65011 $expr = Expression::create($expr->getGlob()->toRegex(false));
65012 }
65013
65014
65015  
65016  
65017  if ($expr->isRegex()) {
65018 $regex = $expr->getRegex();
65019 $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
65020 ->setStartFlag(false)
65021 ->setStartJoker(true)
65022 ->replaceJokers('[^/]');
65023 if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
65024 $regex->setEndJoker(false)->append('[^/]*');
65025 }
65026 }
65027
65028 $command
65029 ->add($i > 0 ? '-or' : null)
65030 ->add($expr->isRegex()
65031 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
65032 : ($expr->isCaseSensitive() ? '-name' : '-iname')
65033 )
65034 ->arg($expr->renderPattern());
65035 }
65036
65037 $command->cmd(')');
65038 }
65039
65040
65041
65042
65043
65044
65045
65046 private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
65047 {
65048 if (0 === count($paths)) {
65049 return;
65050 }
65051
65052 $command->add($not ? '-not' : null)->cmd('(');
65053
65054 foreach ($paths as $i => $path) {
65055 $expr = Expression::create($path);
65056
65057
65058  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
65059 $expr = Expression::create($expr->getGlob()->toRegex(false));
65060 }
65061
65062
65063  if ($expr->isRegex()) {
65064 $regex = $expr->getRegex();
65065 $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
65066 } else {
65067 $expr->prepend('*')->append('*');
65068 }
65069
65070 $command
65071 ->add($i > 0 ? '-or' : null)
65072 ->add($expr->isRegex()
65073 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
65074 : ($expr->isCaseSensitive() ? '-path' : '-ipath')
65075 )
65076 ->arg($expr->renderPattern());
65077 }
65078
65079 $command->cmd(')');
65080 }
65081
65082
65083
65084
65085
65086 private function buildSizesFiltering(Command $command, array $sizes)
65087 {
65088 foreach ($sizes as $i => $size) {
65089 $command->add($i > 0 ? '-and' : null);
65090
65091 switch ($size->getOperator()) {
65092 case '<=':
65093 $command->add('-size -'.($size->getTarget() + 1).'c');
65094 break;
65095 case '>=':
65096 $command->add('-size +'.($size->getTarget() - 1).'c');
65097 break;
65098 case '>':
65099 $command->add('-size +'.$size->getTarget().'c');
65100 break;
65101 case '!=':
65102 $command->add('-size -'.$size->getTarget().'c');
65103 $command->add('-size +'.$size->getTarget().'c');
65104 break;
65105 case '<':
65106 default:
65107 $command->add('-size -'.$size->getTarget().'c');
65108 }
65109 }
65110 }
65111
65112
65113
65114
65115
65116 private function buildDatesFiltering(Command $command, array $dates)
65117 {
65118 foreach ($dates as $i => $date) {
65119 $command->add($i > 0 ? '-and' : null);
65120
65121 $mins = (int) round((time() - $date->getTarget()) / 60);
65122
65123 if (0 > $mins) {
65124
65125  $command->add(' -mmin -0');
65126
65127  return;
65128 }
65129
65130 switch ($date->getOperator()) {
65131 case '<=':
65132 $command->add('-mmin +'.($mins - 1));
65133 break;
65134 case '>=':
65135 $command->add('-mmin -'.($mins + 1));
65136 break;
65137 case '>':
65138 $command->add('-mmin -'.$mins);
65139 break;
65140 case '!=':
65141 $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
65142 break;
65143 case '<':
65144 default:
65145 $command->add('-mmin +'.$mins);
65146 }
65147 }
65148 }
65149
65150
65151
65152
65153
65154
65155
65156 private function buildSorting(Command $command, $sort)
65157 {
65158 $this->buildFormatSorting($command, $sort);
65159 }
65160
65161
65162
65163
65164
65165 abstract protected function buildFormatSorting(Command $command, $sort);
65166
65167
65168
65169
65170
65171
65172 abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
65173 }
65174 <?php
65175
65176
65177
65178
65179
65180
65181
65182
65183
65184
65185 namespace Symfony\Component\Finder\Adapter;
65186
65187
65188
65189
65190
65191
65192 interface AdapterInterface
65193 {
65194
65195
65196
65197
65198
65199 public function setFollowLinks($followLinks);
65200
65201
65202
65203
65204
65205
65206 public function setMode($mode);
65207
65208
65209
65210
65211 public function setExclude(array $exclude);
65212
65213
65214
65215
65216 public function setDepths(array $depths);
65217
65218
65219
65220
65221 public function setNames(array $names);
65222
65223
65224
65225
65226 public function setNotNames(array $notNames);
65227
65228
65229
65230
65231 public function setContains(array $contains);
65232
65233
65234
65235
65236 public function setNotContains(array $notContains);
65237
65238
65239
65240
65241 public function setSizes(array $sizes);
65242
65243
65244
65245
65246 public function setDates(array $dates);
65247
65248
65249
65250
65251 public function setFilters(array $filters);
65252
65253
65254
65255
65256
65257
65258 public function setSort($sort);
65259
65260
65261
65262
65263 public function setPath(array $paths);
65264
65265
65266
65267
65268 public function setNotPath(array $notPaths);
65269
65270
65271
65272
65273
65274
65275 public function ignoreUnreadableDirs($ignore = true);
65276
65277
65278
65279
65280
65281
65282 public function searchInDirectory($dir);
65283
65284
65285
65286
65287
65288
65289 public function isSupported();
65290
65291
65292
65293
65294
65295
65296 public function getName();
65297 }
65298 <?php
65299
65300
65301
65302
65303
65304
65305
65306
65307
65308
65309 namespace Symfony\Component\Finder\Adapter;
65310
65311 @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);
65312
65313 use Symfony\Component\Finder\Shell\Shell;
65314 use Symfony\Component\Finder\Shell\Command;
65315 use Symfony\Component\Finder\Iterator\SortableIterator;
65316 use Symfony\Component\Finder\Expression\Expression;
65317
65318
65319
65320
65321
65322
65323
65324
65325 class BsdFindAdapter extends AbstractFindAdapter
65326 {
65327
65328
65329
65330 public function getName()
65331 {
65332 return 'bsd_find';
65333 }
65334
65335
65336
65337
65338 protected function canBeUsed()
65339 {
65340 return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
65341 }
65342
65343
65344
65345
65346 protected function buildFormatSorting(Command $command, $sort)
65347 {
65348 switch ($sort) {
65349 case SortableIterator::SORT_BY_NAME:
65350 $command->ins('sort')->add('| sort');
65351
65352 return;
65353 case SortableIterator::SORT_BY_TYPE:
65354 $format = '%HT';
65355 break;
65356 case SortableIterator::SORT_BY_ACCESSED_TIME:
65357 $format = '%a';
65358 break;
65359 case SortableIterator::SORT_BY_CHANGED_TIME:
65360 $format = '%c';
65361 break;
65362 case SortableIterator::SORT_BY_MODIFIED_TIME:
65363 $format = '%m';
65364 break;
65365 default:
65366 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
65367 }
65368
65369 $command
65370 ->add('-print0 | xargs -0 stat -f')
65371 ->arg($format.'%t%N')
65372 ->add('| sort | cut -f 2');
65373 }
65374
65375
65376
65377
65378 protected function buildFindCommand(Command $command, $dir)
65379 {
65380 parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
65381
65382 return $command;
65383 }
65384
65385
65386
65387
65388 protected function buildContentFiltering(Command $command, array $contains, $not = false)
65389 {
65390 foreach ($contains as $contain) {
65391 $expr = Expression::create($contain);
65392
65393
65394  $command
65395 ->add('| grep -v \'^$\'')
65396 ->add('| xargs -I{} grep -I')
65397 ->add($expr->isCaseSensitive() ? null : '-i')
65398 ->add($not ? '-L' : '-l')
65399 ->add('-Ee')->arg($expr->renderPattern())
65400 ->add('{}')
65401 ;
65402 }
65403 }
65404 }
65405 <?php
65406
65407
65408
65409
65410
65411
65412
65413
65414
65415
65416 namespace Symfony\Component\Finder\Adapter;
65417
65418 @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);
65419
65420 use Symfony\Component\Finder\Shell\Shell;
65421 use Symfony\Component\Finder\Shell\Command;
65422 use Symfony\Component\Finder\Iterator\SortableIterator;
65423 use Symfony\Component\Finder\Expression\Expression;
65424
65425
65426
65427
65428
65429
65430
65431
65432 class GnuFindAdapter extends AbstractFindAdapter
65433 {
65434
65435
65436
65437 public function getName()
65438 {
65439 return 'gnu_find';
65440 }
65441
65442
65443
65444
65445 protected function buildFormatSorting(Command $command, $sort)
65446 {
65447 switch ($sort) {
65448 case SortableIterator::SORT_BY_NAME:
65449 $command->ins('sort')->add('| sort');
65450
65451 return;
65452 case SortableIterator::SORT_BY_TYPE:
65453 $format = '%y';
65454 break;
65455 case SortableIterator::SORT_BY_ACCESSED_TIME:
65456 $format = '%A@';
65457 break;
65458 case SortableIterator::SORT_BY_CHANGED_TIME:
65459 $format = '%C@';
65460 break;
65461 case SortableIterator::SORT_BY_MODIFIED_TIME:
65462 $format = '%T@';
65463 break;
65464 default:
65465 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
65466 }
65467
65468 $command
65469 ->get('find')
65470 ->add('-printf')
65471 ->arg($format.' %h/%f\\n')
65472 ->add('| sort | cut')
65473 ->arg('-d ')
65474 ->arg('-f2-')
65475 ;
65476 }
65477
65478
65479
65480
65481 protected function canBeUsed()
65482 {
65483 return Shell::TYPE_UNIX === $this->shell->getType() && parent::canBeUsed();
65484 }
65485
65486
65487
65488
65489 protected function buildFindCommand(Command $command, $dir)
65490 {
65491 return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
65492 }
65493
65494
65495
65496
65497 protected function buildContentFiltering(Command $command, array $contains, $not = false)
65498 {
65499 foreach ($contains as $contain) {
65500 $expr = Expression::create($contain);
65501
65502
65503  $command
65504 ->add('| xargs -I{} -r grep -I')
65505 ->add($expr->isCaseSensitive() ? null : '-i')
65506 ->add($not ? '-L' : '-l')
65507 ->add('-Ee')->arg($expr->renderPattern())
65508 ->add('{}')
65509 ;
65510 }
65511 }
65512 }
65513 <?php
65514
65515
65516
65517
65518
65519
65520
65521
65522
65523
65524 namespace Symfony\Component\Finder\Adapter;
65525
65526 @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);
65527
65528 use Symfony\Component\Finder\Iterator;
65529
65530
65531
65532
65533
65534
65535
65536
65537 class PhpAdapter extends AbstractAdapter
65538 {
65539
65540
65541
65542 public function searchInDirectory($dir)
65543 {
65544 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
65545
65546 if ($this->followLinks) {
65547 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
65548 }
65549
65550 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
65551
65552 if ($this->exclude) {
65553 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
65554 }
65555
65556 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
65557
65558 if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
65559 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
65560 }
65561
65562 if ($this->mode) {
65563 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
65564 }
65565
65566 if ($this->names || $this->notNames) {
65567 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
65568 }
65569
65570 if ($this->contains || $this->notContains) {
65571 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
65572 }
65573
65574 if ($this->sizes) {
65575 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
65576 }
65577
65578 if ($this->dates) {
65579 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
65580 }
65581
65582 if ($this->filters) {
65583 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
65584 }
65585
65586 if ($this->paths || $this->notPaths) {
65587 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
65588 }
65589
65590 if ($this->sort) {
65591 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
65592 $iterator = $iteratorAggregate->getIterator();
65593 }
65594
65595 return $iterator;
65596 }
65597
65598
65599
65600
65601 public function getName()
65602 {
65603 return 'php';
65604 }
65605
65606
65607
65608
65609 protected function canBeUsed()
65610 {
65611 return true;
65612 }
65613 }
65614 <?php
65615
65616
65617
65618
65619
65620
65621
65622
65623
65624
65625 namespace Symfony\Component\Finder\Comparator;
65626
65627
65628
65629
65630
65631
65632 class Comparator
65633 {
65634 private $target;
65635 private $operator = '==';
65636
65637
65638
65639
65640
65641
65642 public function getTarget()
65643 {
65644 return $this->target;
65645 }
65646
65647
65648
65649
65650
65651
65652 public function setTarget($target)
65653 {
65654 $this->target = $target;
65655 }
65656
65657
65658
65659
65660
65661
65662 public function getOperator()
65663 {
65664 return $this->operator;
65665 }
65666
65667
65668
65669
65670
65671
65672
65673
65674 public function setOperator($operator)
65675 {
65676 if (!$operator) {
65677 $operator = '==';
65678 }
65679
65680 if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
65681 throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
65682 }
65683
65684 $this->operator = $operator;
65685 }
65686
65687
65688
65689
65690
65691
65692
65693
65694 public function test($test)
65695 {
65696 switch ($this->operator) {
65697 case '>':
65698 return $test > $this->target;
65699 case '>=':
65700 return $test >= $this->target;
65701 case '<':
65702 return $test < $this->target;
65703 case '<=':
65704 return $test <= $this->target;
65705 case '!=':
65706 return $test != $this->target;
65707 }
65708
65709 return $test == $this->target;
65710 }
65711 }
65712 <?php
65713
65714
65715
65716
65717
65718
65719
65720
65721
65722
65723 namespace Symfony\Component\Finder\Comparator;
65724
65725
65726
65727
65728
65729
65730 class DateComparator extends Comparator
65731 {
65732
65733
65734
65735
65736
65737 public function __construct($test)
65738 {
65739 if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
65740 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
65741 }
65742
65743 try {
65744 $date = new \DateTime($matches[2]);
65745 $target = $date->format('U');
65746 } catch (\Exception $e) {
65747 throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
65748 }
65749
65750 $operator = isset($matches[1]) ? $matches[1] : '==';
65751 if ('since' === $operator || 'after' === $operator) {
65752 $operator = '>';
65753 }
65754
65755 if ('until' === $operator || 'before' === $operator) {
65756 $operator = '<';
65757 }
65758
65759 $this->setOperator($operator);
65760 $this->setTarget($target);
65761 }
65762 }
65763 <?php
65764
65765
65766
65767
65768
65769
65770
65771
65772
65773
65774 namespace Symfony\Component\Finder\Comparator;
65775
65776
65777
65778
65779
65780
65781
65782
65783
65784
65785
65786
65787
65788
65789
65790
65791
65792
65793
65794
65795
65796
65797 class NumberComparator extends Comparator
65798 {
65799
65800
65801
65802
65803
65804 public function __construct($test)
65805 {
65806 if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
65807 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
65808 }
65809
65810 $target = $matches[2];
65811 if (!is_numeric($target)) {
65812 throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
65813 }
65814 if (isset($matches[3])) {
65815
65816  switch (strtolower($matches[3])) {
65817 case 'k':
65818 $target *= 1000;
65819 break;
65820 case 'ki':
65821 $target *= 1024;
65822 break;
65823 case 'm':
65824 $target *= 1000000;
65825 break;
65826 case 'mi':
65827 $target *= 1024 * 1024;
65828 break;
65829 case 'g':
65830 $target *= 1000000000;
65831 break;
65832 case 'gi':
65833 $target *= 1024 * 1024 * 1024;
65834 break;
65835 }
65836 }
65837
65838 $this->setTarget($target);
65839 $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
65840 }
65841 }
65842 <?php
65843
65844
65845
65846
65847
65848
65849
65850
65851
65852
65853 namespace Symfony\Component\Finder\Exception;
65854
65855
65856
65857
65858 class AccessDeniedException extends \UnexpectedValueException
65859 {
65860 }
65861 <?php
65862
65863
65864
65865
65866
65867
65868
65869
65870
65871
65872 namespace Symfony\Component\Finder\Exception;
65873
65874 @trigger_error('The '.__NAMESPACE__.'\AdapterFailureException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65875
65876 use Symfony\Component\Finder\Adapter\AdapterInterface;
65877
65878
65879
65880
65881
65882
65883
65884
65885 class AdapterFailureException extends \RuntimeException implements ExceptionInterface
65886 {
65887 private $adapter;
65888
65889
65890
65891
65892
65893
65894 public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
65895 {
65896 $this->adapter = $adapter;
65897 parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
65898 }
65899
65900
65901
65902
65903 public function getAdapter()
65904 {
65905 return $this->adapter;
65906 }
65907 }
65908 <?php
65909
65910
65911
65912
65913
65914
65915
65916
65917
65918
65919 namespace Symfony\Component\Finder\Exception;
65920
65921
65922
65923
65924 interface ExceptionInterface
65925 {
65926
65927
65928
65929 public function getAdapter();
65930 }
65931 <?php
65932
65933
65934
65935
65936
65937
65938
65939
65940
65941
65942 namespace Symfony\Component\Finder\Exception;
65943
65944 @trigger_error('The '.__NAMESPACE__.'\OperationNotPermitedException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65945
65946
65947
65948
65949
65950
65951 class OperationNotPermitedException extends AdapterFailureException
65952 {
65953 }
65954 <?php
65955
65956
65957
65958
65959
65960
65961
65962
65963
65964
65965 namespace Symfony\Component\Finder\Exception;
65966
65967 @trigger_error('The '.__NAMESPACE__.'\ShellCommandFailureException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65968
65969 use Symfony\Component\Finder\Adapter\AdapterInterface;
65970 use Symfony\Component\Finder\Shell\Command;
65971
65972
65973
65974
65975
65976
65977 class ShellCommandFailureException extends AdapterFailureException
65978 {
65979 private $command;
65980
65981 public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
65982 {
65983 $this->command = $command;
65984 parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
65985 }
65986
65987
65988
65989
65990 public function getCommand()
65991 {
65992 return $this->command;
65993 }
65994 }
65995 <?php
65996
65997
65998
65999
66000
66001
66002
66003
66004
66005
66006 namespace Symfony\Component\Finder\Expression;
66007
66008 @trigger_error('The '.__NAMESPACE__.'\Expression class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66009
66010
66011
66012
66013 class Expression implements ValueInterface
66014 {
66015 const TYPE_REGEX = 1;
66016 const TYPE_GLOB = 2;
66017
66018
66019
66020
66021 private $value;
66022
66023
66024
66025
66026
66027
66028 public static function create($expr)
66029 {
66030 return new self($expr);
66031 }
66032
66033
66034
66035
66036 public function __construct($expr)
66037 {
66038 try {
66039 $this->value = Regex::create($expr);
66040 } catch (\InvalidArgumentException $e) {
66041 $this->value = new Glob($expr);
66042 }
66043 }
66044
66045
66046
66047
66048 public function __toString()
66049 {
66050 return $this->render();
66051 }
66052
66053
66054
66055
66056 public function render()
66057 {
66058 return $this->value->render();
66059 }
66060
66061
66062
66063
66064 public function renderPattern()
66065 {
66066 return $this->value->renderPattern();
66067 }
66068
66069
66070
66071
66072 public function isCaseSensitive()
66073 {
66074 return $this->value->isCaseSensitive();
66075 }
66076
66077
66078
66079
66080 public function getType()
66081 {
66082 return $this->value->getType();
66083 }
66084
66085
66086
66087
66088 public function prepend($expr)
66089 {
66090 $this->value->prepend($expr);
66091
66092 return $this;
66093 }
66094
66095
66096
66097
66098 public function append($expr)
66099 {
66100 $this->value->append($expr);
66101
66102 return $this;
66103 }
66104
66105
66106
66107
66108 public function isRegex()
66109 {
66110 return self::TYPE_REGEX === $this->value->getType();
66111 }
66112
66113
66114
66115
66116 public function isGlob()
66117 {
66118 return self::TYPE_GLOB === $this->value->getType();
66119 }
66120
66121
66122
66123
66124
66125
66126 public function getGlob()
66127 {
66128 if (self::TYPE_GLOB !== $this->value->getType()) {
66129 throw new \LogicException('Regex can\'t be transformed to glob.');
66130 }
66131
66132 return $this->value;
66133 }
66134
66135
66136
66137
66138 public function getRegex()
66139 {
66140 return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
66141 }
66142 }
66143 <?php
66144
66145
66146
66147
66148
66149
66150
66151
66152
66153
66154 namespace Symfony\Component\Finder\Expression;
66155
66156 @trigger_error('The '.__NAMESPACE__.'\Glob class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66157
66158 use Symfony\Component\Finder\Glob as FinderGlob;
66159
66160
66161
66162
66163 class Glob implements ValueInterface
66164 {
66165 private $pattern;
66166
66167
66168
66169
66170 public function __construct($pattern)
66171 {
66172 $this->pattern = $pattern;
66173 }
66174
66175
66176
66177
66178 public function render()
66179 {
66180 return $this->pattern;
66181 }
66182
66183
66184
66185
66186 public function renderPattern()
66187 {
66188 return $this->pattern;
66189 }
66190
66191
66192
66193
66194 public function getType()
66195 {
66196 return Expression::TYPE_GLOB;
66197 }
66198
66199
66200
66201
66202 public function isCaseSensitive()
66203 {
66204 return true;
66205 }
66206
66207
66208
66209
66210 public function prepend($expr)
66211 {
66212 $this->pattern = $expr.$this->pattern;
66213
66214 return $this;
66215 }
66216
66217
66218
66219
66220 public function append($expr)
66221 {
66222 $this->pattern .= $expr;
66223
66224 return $this;
66225 }
66226
66227
66228
66229
66230
66231
66232 public function isExpandable()
66233 {
66234 return false !== strpos($this->pattern, '{')
66235 && false !== strpos($this->pattern, '}');
66236 }
66237
66238
66239
66240
66241
66242
66243
66244 public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
66245 {
66246 $regex = FinderGlob::toRegex($this->pattern, $strictLeadingDot, $strictWildcardSlash, '');
66247
66248 return new Regex($regex);
66249 }
66250 }
66251 <?php
66252
66253
66254
66255
66256
66257
66258
66259
66260
66261
66262 namespace Symfony\Component\Finder\Expression;
66263
66264 @trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66265
66266
66267
66268
66269 class Regex implements ValueInterface
66270 {
66271 const START_FLAG = '^';
66272 const END_FLAG = '$';
66273 const BOUNDARY = '~';
66274 const JOKER = '.*';
66275 const ESCAPING = '\\';
66276
66277
66278
66279
66280 private $pattern;
66281
66282
66283
66284
66285 private $options;
66286
66287
66288
66289
66290 private $startFlag;
66291
66292
66293
66294
66295 private $endFlag;
66296
66297
66298
66299
66300 private $startJoker;
66301
66302
66303
66304
66305 private $endJoker;
66306
66307
66308
66309
66310
66311
66312
66313
66314 public static function create($expr)
66315 {
66316 if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
66317 $start = substr($m[1], 0, 1);
66318 $end = substr($m[1], -1);
66319
66320 if (
66321 ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
66322 || ('{' === $start && '}' === $end)
66323 || ('(' === $start && ')' === $end)
66324 ) {
66325 return new self(substr($m[1], 1, -1), $m[2], $end);
66326 }
66327 }
66328
66329 throw new \InvalidArgumentException('Given expression is not a regex.');
66330 }
66331
66332
66333
66334
66335
66336
66337 public function __construct($pattern, $options = '', $delimiter = null)
66338 {
66339 if (null !== $delimiter) {
66340
66341  $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
66342 }
66343
66344 $this->parsePattern($pattern);
66345 $this->options = $options;
66346 }
66347
66348
66349
66350
66351 public function __toString()
66352 {
66353 return $this->render();
66354 }
66355
66356
66357
66358
66359 public function render()
66360 {
66361 return self::BOUNDARY
66362 .$this->renderPattern()
66363 .self::BOUNDARY
66364 .$this->options;
66365 }
66366
66367
66368
66369
66370 public function renderPattern()
66371 {
66372 return ($this->startFlag ? self::START_FLAG : '')
66373 .($this->startJoker ? self::JOKER : '')
66374 .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
66375 .($this->endJoker ? self::JOKER : '')
66376 .($this->endFlag ? self::END_FLAG : '');
66377 }
66378
66379
66380
66381
66382 public function isCaseSensitive()
66383 {
66384 return !$this->hasOption('i');
66385 }
66386
66387
66388
66389
66390 public function getType()
66391 {
66392 return Expression::TYPE_REGEX;
66393 }
66394
66395
66396
66397
66398 public function prepend($expr)
66399 {
66400 $this->pattern = $expr.$this->pattern;
66401
66402 return $this;
66403 }
66404
66405
66406
66407
66408 public function append($expr)
66409 {
66410 $this->pattern .= $expr;
66411
66412 return $this;
66413 }
66414
66415
66416
66417
66418
66419
66420 public function hasOption($option)
66421 {
66422 return false !== strpos($this->options, $option);
66423 }
66424
66425
66426
66427
66428
66429
66430 public function addOption($option)
66431 {
66432 if (!$this->hasOption($option)) {
66433 $this->options .= $option;
66434 }
66435
66436 return $this;
66437 }
66438
66439
66440
66441
66442
66443
66444 public function removeOption($option)
66445 {
66446 $this->options = str_replace($option, '', $this->options);
66447
66448 return $this;
66449 }
66450
66451
66452
66453
66454
66455
66456 public function setStartFlag($startFlag)
66457 {
66458 $this->startFlag = $startFlag;
66459
66460 return $this;
66461 }
66462
66463
66464
66465
66466 public function hasStartFlag()
66467 {
66468 return $this->startFlag;
66469 }
66470
66471
66472
66473
66474
66475
66476 public function setEndFlag($endFlag)
66477 {
66478 $this->endFlag = (bool) $endFlag;
66479
66480 return $this;
66481 }
66482
66483
66484
66485
66486 public function hasEndFlag()
66487 {
66488 return $this->endFlag;
66489 }
66490
66491
66492
66493
66494
66495
66496 public function setStartJoker($startJoker)
66497 {
66498 $this->startJoker = $startJoker;
66499
66500 return $this;
66501 }
66502
66503
66504
66505
66506 public function hasStartJoker()
66507 {
66508 return $this->startJoker;
66509 }
66510
66511
66512
66513
66514
66515
66516 public function setEndJoker($endJoker)
66517 {
66518 $this->endJoker = (bool) $endJoker;
66519
66520 return $this;
66521 }
66522
66523
66524
66525
66526 public function hasEndJoker()
66527 {
66528 return $this->endJoker;
66529 }
66530
66531
66532
66533
66534 public function replaceJokers($replacement)
66535 {
66536 $replace = function ($subject) use ($replacement) {
66537 $subject = $subject[0];
66538 $replace = 0 === substr_count($subject, '\\') % 2;
66539
66540 return $replace ? str_replace('.', $replacement, $subject) : $subject;
66541 };
66542
66543 $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
66544
66545 return $this;
66546 }
66547
66548
66549
66550
66551 private function parsePattern($pattern)
66552 {
66553 if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
66554 $pattern = substr($pattern, 1);
66555 }
66556
66557 if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
66558 $pattern = substr($pattern, 2);
66559 }
66560
66561 if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
66562 $pattern = substr($pattern, 0, -1);
66563 }
66564
66565 if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
66566 $pattern = substr($pattern, 0, -2);
66567 }
66568
66569 $this->pattern = $pattern;
66570 }
66571 }
66572 <?php
66573
66574
66575
66576
66577
66578
66579
66580
66581
66582
66583 namespace Symfony\Component\Finder\Expression;
66584
66585 @trigger_error('The '.__NAMESPACE__.'\ValueInterface interface is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66586
66587
66588
66589
66590 interface ValueInterface
66591 {
66592
66593
66594
66595
66596
66597 public function render();
66598
66599
66600
66601
66602
66603
66604 public function renderPattern();
66605
66606
66607
66608
66609
66610
66611 public function isCaseSensitive();
66612
66613
66614
66615
66616
66617
66618 public function getType();
66619
66620
66621
66622
66623
66624
66625 public function prepend($expr);
66626
66627
66628
66629
66630
66631
66632 public function append($expr);
66633 }
66634 <?php
66635
66636
66637
66638
66639
66640
66641
66642
66643
66644
66645 namespace Symfony\Component\Finder;
66646
66647 use Symfony\Component\Finder\Adapter\AdapterInterface;
66648 use Symfony\Component\Finder\Adapter\GnuFindAdapter;
66649 use Symfony\Component\Finder\Adapter\BsdFindAdapter;
66650 use Symfony\Component\Finder\Adapter\PhpAdapter;
66651 use Symfony\Component\Finder\Comparator\DateComparator;
66652 use Symfony\Component\Finder\Comparator\NumberComparator;
66653 use Symfony\Component\Finder\Exception\ExceptionInterface;
66654 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
66655 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
66656 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
66657 use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
66658 use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
66659 use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
66660 use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
66661 use Symfony\Component\Finder\Iterator\SortableIterator;
66662
66663
66664
66665
66666
66667
66668
66669
66670
66671
66672
66673
66674
66675
66676 class Finder implements \IteratorAggregate, \Countable
66677 {
66678 const IGNORE_VCS_FILES = 1;
66679 const IGNORE_DOT_FILES = 2;
66680
66681 private $mode = 0;
66682 private $names = array();
66683 private $notNames = array();
66684 private $exclude = array();
66685 private $filters = array();
66686 private $depths = array();
66687 private $sizes = array();
66688 private $followLinks = false;
66689 private $sort = false;
66690 private $ignore = 0;
66691 private $dirs = array();
66692 private $dates = array();
66693 private $iterators = array();
66694 private $contains = array();
66695 private $notContains = array();
66696 private $adapters = null;
66697 private $paths = array();
66698 private $notPaths = array();
66699 private $ignoreUnreadableDirs = false;
66700
66701 private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
66702
66703 public function __construct()
66704 {
66705 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
66706 }
66707
66708
66709
66710
66711
66712
66713 public static function create()
66714 {
66715 return new static();
66716 }
66717
66718
66719
66720
66721
66722
66723
66724
66725
66726
66727
66728 public function addAdapter(AdapterInterface $adapter, $priority = 0)
66729 {
66730 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66731
66732 $this->initDefaultAdapters();
66733
66734 $this->adapters[$adapter->getName()] = array(
66735 'adapter' => $adapter,
66736 'priority' => $priority,
66737 'selected' => false,
66738 );
66739
66740 return $this->sortAdapters();
66741 }
66742
66743
66744
66745
66746
66747
66748
66749
66750 public function useBestAdapter()
66751 {
66752 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66753
66754 $this->initDefaultAdapters();
66755
66756 $this->resetAdapterSelection();
66757
66758 return $this->sortAdapters();
66759 }
66760
66761
66762
66763
66764
66765
66766
66767
66768
66769
66770
66771
66772 public function setAdapter($name)
66773 {
66774 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66775
66776 $this->initDefaultAdapters();
66777
66778 if (!isset($this->adapters[$name])) {
66779 throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
66780 }
66781
66782 $this->resetAdapterSelection();
66783 $this->adapters[$name]['selected'] = true;
66784
66785 return $this->sortAdapters();
66786 }
66787
66788
66789
66790
66791
66792
66793
66794
66795 public function removeAdapters()
66796 {
66797 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66798
66799 $this->adapters = array();
66800
66801 return $this;
66802 }
66803
66804
66805
66806
66807
66808
66809
66810
66811 public function getAdapters()
66812 {
66813 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66814
66815 $this->initDefaultAdapters();
66816
66817 return array_values(array_map(function (array $adapter) {
66818 return $adapter['adapter'];
66819 }, $this->adapters));
66820 }
66821
66822
66823
66824
66825
66826
66827 public function directories()
66828 {
66829 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
66830
66831 return $this;
66832 }
66833
66834
66835
66836
66837
66838
66839 public function files()
66840 {
66841 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
66842
66843 return $this;
66844 }
66845
66846
66847
66848
66849
66850
66851
66852
66853
66854
66855
66856
66857
66858
66859
66860
66861 public function depth($level)
66862 {
66863 $this->depths[] = new Comparator\NumberComparator($level);
66864
66865 return $this;
66866 }
66867
66868
66869
66870
66871
66872
66873
66874
66875
66876
66877
66878
66879
66880
66881
66882
66883
66884
66885
66886 public function date($date)
66887 {
66888 $this->dates[] = new Comparator\DateComparator($date);
66889
66890 return $this;
66891 }
66892
66893
66894
66895
66896
66897
66898
66899
66900
66901
66902
66903
66904
66905
66906
66907
66908 public function name($pattern)
66909 {
66910 $this->names[] = $pattern;
66911
66912 return $this;
66913 }
66914
66915
66916
66917
66918
66919
66920
66921
66922
66923
66924 public function notName($pattern)
66925 {
66926 $this->notNames[] = $pattern;
66927
66928 return $this;
66929 }
66930
66931
66932
66933
66934
66935
66936
66937
66938
66939
66940
66941
66942
66943
66944
66945 public function contains($pattern)
66946 {
66947 $this->contains[] = $pattern;
66948
66949 return $this;
66950 }
66951
66952
66953
66954
66955
66956
66957
66958
66959
66960
66961
66962
66963
66964
66965
66966 public function notContains($pattern)
66967 {
66968 $this->notContains[] = $pattern;
66969
66970 return $this;
66971 }
66972
66973
66974
66975
66976
66977
66978
66979
66980
66981
66982
66983
66984
66985
66986
66987
66988
66989 public function path($pattern)
66990 {
66991 $this->paths[] = $pattern;
66992
66993 return $this;
66994 }
66995
66996
66997
66998
66999
67000
67001
67002
67003
67004
67005
67006
67007
67008
67009
67010
67011
67012 public function notPath($pattern)
67013 {
67014 $this->notPaths[] = $pattern;
67015
67016 return $this;
67017 }
67018
67019
67020
67021
67022
67023
67024
67025
67026
67027
67028
67029
67030
67031
67032
67033 public function size($size)
67034 {
67035 $this->sizes[] = new Comparator\NumberComparator($size);
67036
67037 return $this;
67038 }
67039
67040
67041
67042
67043
67044
67045
67046
67047
67048
67049 public function exclude($dirs)
67050 {
67051 $this->exclude = array_merge($this->exclude, (array) $dirs);
67052
67053 return $this;
67054 }
67055
67056
67057
67058
67059
67060
67061
67062
67063
67064
67065 public function ignoreDotFiles($ignoreDotFiles)
67066 {
67067 if ($ignoreDotFiles) {
67068 $this->ignore |= static::IGNORE_DOT_FILES;
67069 } else {
67070 $this->ignore &= ~static::IGNORE_DOT_FILES;
67071 }
67072
67073 return $this;
67074 }
67075
67076
67077
67078
67079
67080
67081
67082
67083
67084
67085 public function ignoreVCS($ignoreVCS)
67086 {
67087 if ($ignoreVCS) {
67088 $this->ignore |= static::IGNORE_VCS_FILES;
67089 } else {
67090 $this->ignore &= ~static::IGNORE_VCS_FILES;
67091 }
67092
67093 return $this;
67094 }
67095
67096
67097
67098
67099
67100
67101
67102
67103 public static function addVCSPattern($pattern)
67104 {
67105 foreach ((array) $pattern as $p) {
67106 self::$vcsPatterns[] = $p;
67107 }
67108
67109 self::$vcsPatterns = array_unique(self::$vcsPatterns);
67110 }
67111
67112
67113
67114
67115
67116
67117
67118
67119
67120
67121
67122
67123 public function sort(\Closure $closure)
67124 {
67125 $this->sort = $closure;
67126
67127 return $this;
67128 }
67129
67130
67131
67132
67133
67134
67135
67136
67137
67138
67139 public function sortByName()
67140 {
67141 $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
67142
67143 return $this;
67144 }
67145
67146
67147
67148
67149
67150
67151
67152
67153
67154
67155 public function sortByType()
67156 {
67157 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
67158
67159 return $this;
67160 }
67161
67162
67163
67164
67165
67166
67167
67168
67169
67170
67171
67172
67173 public function sortByAccessedTime()
67174 {
67175 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
67176
67177 return $this;
67178 }
67179
67180
67181
67182
67183
67184
67185
67186
67187
67188
67189
67190
67191
67192
67193 public function sortByChangedTime()
67194 {
67195 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
67196
67197 return $this;
67198 }
67199
67200
67201
67202
67203
67204
67205
67206
67207
67208
67209
67210
67211 public function sortByModifiedTime()
67212 {
67213 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
67214
67215 return $this;
67216 }
67217
67218
67219
67220
67221
67222
67223
67224
67225
67226
67227
67228 public function filter(\Closure $closure)
67229 {
67230 $this->filters[] = $closure;
67231
67232 return $this;
67233 }
67234
67235
67236
67237
67238
67239
67240 public function followLinks()
67241 {
67242 $this->followLinks = true;
67243
67244 return $this;
67245 }
67246
67247
67248
67249
67250
67251
67252
67253
67254
67255
67256 public function ignoreUnreadableDirs($ignore = true)
67257 {
67258 $this->ignoreUnreadableDirs = (bool) $ignore;
67259
67260 return $this;
67261 }
67262
67263
67264
67265
67266
67267
67268
67269
67270
67271
67272 public function in($dirs)
67273 {
67274 $resolvedDirs = array();
67275
67276 foreach ((array) $dirs as $dir) {
67277 if (is_dir($dir)) {
67278 $resolvedDirs[] = $dir;
67279 } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
67280 $resolvedDirs = array_merge($resolvedDirs, $glob);
67281 } else {
67282 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
67283 }
67284 }
67285
67286 $this->dirs = array_merge($this->dirs, $resolvedDirs);
67287
67288 return $this;
67289 }
67290
67291
67292
67293
67294
67295
67296
67297
67298
67299
67300 public function getIterator()
67301 {
67302 if (0 === count($this->dirs) && 0 === count($this->iterators)) {
67303 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
67304 }
67305
67306 if (1 === count($this->dirs) && 0 === count($this->iterators)) {
67307 return $this->searchInDirectory($this->dirs[0]);
67308 }
67309
67310 $iterator = new \AppendIterator();
67311 foreach ($this->dirs as $dir) {
67312 $iterator->append($this->searchInDirectory($dir));
67313 }
67314
67315 foreach ($this->iterators as $it) {
67316 $iterator->append($it);
67317 }
67318
67319 return $iterator;
67320 }
67321
67322
67323
67324
67325
67326
67327
67328
67329
67330
67331
67332
67333 public function append($iterator)
67334 {
67335 if ($iterator instanceof \IteratorAggregate) {
67336 $this->iterators[] = $iterator->getIterator();
67337 } elseif ($iterator instanceof \Iterator) {
67338 $this->iterators[] = $iterator;
67339 } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
67340 $it = new \ArrayIterator();
67341 foreach ($iterator as $file) {
67342 $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
67343 }
67344 $this->iterators[] = $it;
67345 } else {
67346 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
67347 }
67348
67349 return $this;
67350 }
67351
67352
67353
67354
67355
67356
67357 public function count()
67358 {
67359 return iterator_count($this->getIterator());
67360 }
67361
67362
67363
67364
67365 private function sortAdapters()
67366 {
67367 uasort($this->adapters, function (array $a, array $b) {
67368 if ($a['selected'] || $b['selected']) {
67369 return $a['selected'] ? -1 : 1;
67370 }
67371
67372 return $a['priority'] > $b['priority'] ? -1 : 1;
67373 });
67374
67375 return $this;
67376 }
67377
67378
67379
67380
67381
67382
67383 private function searchInDirectory($dir)
67384 {
67385 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
67386 $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
67387 }
67388
67389 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
67390 $this->notPaths[] = '#(^|/)\..+(/|$)#';
67391 }
67392
67393 if ($this->adapters) {
67394 foreach ($this->adapters as $adapter) {
67395 if ($adapter['adapter']->isSupported()) {
67396 try {
67397 return $this
67398 ->buildAdapter($adapter['adapter'])
67399 ->searchInDirectory($dir);
67400 } catch (ExceptionInterface $e) {
67401 }
67402 }
67403 }
67404 }
67405
67406 $minDepth = 0;
67407 $maxDepth = PHP_INT_MAX;
67408
67409 foreach ($this->depths as $comparator) {
67410 switch ($comparator->getOperator()) {
67411 case '>':
67412 $minDepth = $comparator->getTarget() + 1;
67413 break;
67414 case '>=':
67415 $minDepth = $comparator->getTarget();
67416 break;
67417 case '<':
67418 $maxDepth = $comparator->getTarget() - 1;
67419 break;
67420 case '<=':
67421 $maxDepth = $comparator->getTarget();
67422 break;
67423 default:
67424 $minDepth = $maxDepth = $comparator->getTarget();
67425 }
67426 }
67427
67428 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
67429
67430 if ($this->followLinks) {
67431 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
67432 }
67433
67434 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
67435
67436 if ($this->exclude) {
67437 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
67438 }
67439
67440 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
67441
67442 if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
67443 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
67444 }
67445
67446 if ($this->mode) {
67447 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
67448 }
67449
67450 if ($this->names || $this->notNames) {
67451 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
67452 }
67453
67454 if ($this->contains || $this->notContains) {
67455 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
67456 }
67457
67458 if ($this->sizes) {
67459 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
67460 }
67461
67462 if ($this->dates) {
67463 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
67464 }
67465
67466 if ($this->filters) {
67467 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
67468 }
67469
67470 if ($this->paths || $this->notPaths) {
67471 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
67472 }
67473
67474 if ($this->sort) {
67475 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
67476 $iterator = $iteratorAggregate->getIterator();
67477 }
67478
67479 return $iterator;
67480 }
67481
67482
67483
67484
67485 private function buildAdapter(AdapterInterface $adapter)
67486 {
67487 return $adapter
67488 ->setFollowLinks($this->followLinks)
67489 ->setDepths($this->depths)
67490 ->setMode($this->mode)
67491 ->setExclude($this->exclude)
67492 ->setNames($this->names)
67493 ->setNotNames($this->notNames)
67494 ->setContains($this->contains)
67495 ->setNotContains($this->notContains)
67496 ->setSizes($this->sizes)
67497 ->setDates($this->dates)
67498 ->setFilters($this->filters)
67499 ->setSort($this->sort)
67500 ->setPath($this->paths)
67501 ->setNotPath($this->notPaths)
67502 ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
67503 }
67504
67505
67506
67507
67508 private function resetAdapterSelection()
67509 {
67510 $this->adapters = array_map(function (array $properties) {
67511 $properties['selected'] = false;
67512
67513 return $properties;
67514 }, $this->adapters);
67515 }
67516
67517 private function initDefaultAdapters()
67518 {
67519 if (null === $this->adapters) {
67520 $this->adapters = array();
67521 $this
67522 ->addAdapter(new GnuFindAdapter())
67523 ->addAdapter(new BsdFindAdapter())
67524 ->addAdapter(new PhpAdapter(), -50)
67525 ->setAdapter('php')
67526 ;
67527 }
67528 }
67529 }
67530 <?php
67531
67532
67533
67534
67535
67536
67537
67538
67539
67540
67541 namespace Symfony\Component\Finder;
67542
67543
67544
67545
67546
67547
67548
67549
67550
67551
67552
67553
67554
67555
67556
67557
67558
67559
67560
67561
67562
67563
67564
67565 class Glob
67566 {
67567
67568
67569
67570
67571
67572
67573
67574
67575
67576
67577 public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
67578 {
67579 $firstByte = true;
67580 $escaping = false;
67581 $inCurlies = 0;
67582 $regex = '';
67583 $sizeGlob = strlen($glob);
67584 for ($i = 0; $i < $sizeGlob; ++$i) {
67585 $car = $glob[$i];
67586 if ($firstByte) {
67587 if ($strictLeadingDot && '.' !== $car) {
67588 $regex .= '(?=[^\.])';
67589 }
67590
67591 $firstByte = false;
67592 }
67593
67594 if ('/' === $car) {
67595 $firstByte = true;
67596 }
67597
67598 if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
67599 $regex .= "\\$car";
67600 } elseif ('*' === $car) {
67601 $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
67602 } elseif ('?' === $car) {
67603 $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
67604 } elseif ('{' === $car) {
67605 $regex .= $escaping ? '\\{' : '(';
67606 if (!$escaping) {
67607 ++$inCurlies;
67608 }
67609 } elseif ('}' === $car && $inCurlies) {
67610 $regex .= $escaping ? '}' : ')';
67611 if (!$escaping) {
67612 --$inCurlies;
67613 }
67614 } elseif (',' === $car && $inCurlies) {
67615 $regex .= $escaping ? ',' : '|';
67616 } elseif ('\\' === $car) {
67617 if ($escaping) {
67618 $regex .= '\\\\';
67619 $escaping = false;
67620 } else {
67621 $escaping = true;
67622 }
67623
67624 continue;
67625 } else {
67626 $regex .= $car;
67627 }
67628 $escaping = false;
67629 }
67630
67631 return $delimiter.'^'.$regex.'$'.$delimiter;
67632 }
67633 }
67634 <?php
67635
67636
67637
67638
67639
67640
67641
67642
67643
67644
67645 namespace Symfony\Component\Finder\Iterator;
67646
67647
67648
67649
67650
67651
67652
67653
67654
67655 class CustomFilterIterator extends FilterIterator
67656 {
67657 private $filters = array();
67658
67659
67660
67661
67662
67663
67664
67665 public function __construct(\Iterator $iterator, array $filters)
67666 {
67667 foreach ($filters as $filter) {
67668 if (!is_callable($filter)) {
67669 throw new \InvalidArgumentException('Invalid PHP callback.');
67670 }
67671 }
67672 $this->filters = $filters;
67673
67674 parent::__construct($iterator);
67675 }
67676
67677
67678
67679
67680
67681
67682 public function accept()
67683 {
67684 $fileinfo = $this->current();
67685
67686 foreach ($this->filters as $filter) {
67687 if (false === call_user_func($filter, $fileinfo)) {
67688 return false;
67689 }
67690 }
67691
67692 return true;
67693 }
67694 }
67695 <?php
67696
67697
67698
67699
67700
67701
67702
67703
67704
67705
67706 namespace Symfony\Component\Finder\Iterator;
67707
67708 use Symfony\Component\Finder\Comparator\DateComparator;
67709
67710
67711
67712
67713
67714
67715 class DateRangeFilterIterator extends FilterIterator
67716 {
67717 private $comparators = array();
67718
67719
67720
67721
67722
67723 public function __construct(\Iterator $iterator, array $comparators)
67724 {
67725 $this->comparators = $comparators;
67726
67727 parent::__construct($iterator);
67728 }
67729
67730
67731
67732
67733
67734
67735 public function accept()
67736 {
67737 $fileinfo = $this->current();
67738
67739 if (!file_exists($fileinfo->getPathname())) {
67740 return false;
67741 }
67742
67743 $filedate = $fileinfo->getMTime();
67744 foreach ($this->comparators as $compare) {
67745 if (!$compare->test($filedate)) {
67746 return false;
67747 }
67748 }
67749
67750 return true;
67751 }
67752 }
67753 <?php
67754
67755
67756
67757
67758
67759
67760
67761
67762
67763
67764 namespace Symfony\Component\Finder\Iterator;
67765
67766
67767
67768
67769
67770
67771 class DepthRangeFilterIterator extends FilterIterator
67772 {
67773 private $minDepth = 0;
67774
67775
67776
67777
67778
67779
67780 public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
67781 {
67782 $this->minDepth = $minDepth;
67783 $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
67784
67785 parent::__construct($iterator);
67786 }
67787
67788
67789
67790
67791
67792
67793 public function accept()
67794 {
67795 return $this->getInnerIterator()->getDepth() >= $this->minDepth;
67796 }
67797 }
67798 <?php
67799
67800
67801
67802
67803
67804
67805
67806
67807
67808
67809 namespace Symfony\Component\Finder\Iterator;
67810
67811
67812
67813
67814
67815
67816 class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
67817 {
67818 private $iterator;
67819 private $isRecursive;
67820 private $excludedDirs = array();
67821 private $excludedPattern;
67822
67823
67824
67825
67826
67827 public function __construct(\Iterator $iterator, array $directories)
67828 {
67829 $this->iterator = $iterator;
67830 $this->isRecursive = $iterator instanceof \RecursiveIterator;
67831 $patterns = array();
67832 foreach ($directories as $directory) {
67833 $directory = rtrim($directory, '/');
67834 if (!$this->isRecursive || false !== strpos($directory, '/')) {
67835 $patterns[] = preg_quote($directory, '#');
67836 } else {
67837 $this->excludedDirs[$directory] = true;
67838 }
67839 }
67840 if ($patterns) {
67841 $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
67842 }
67843
67844 parent::__construct($iterator);
67845 }
67846
67847
67848
67849
67850
67851
67852 public function accept()
67853 {
67854 if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
67855 return false;
67856 }
67857
67858 if ($this->excludedPattern) {
67859 $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
67860 $path = str_replace('\\', '/', $path);
67861
67862 return !preg_match($this->excludedPattern, $path);
67863 }
67864
67865 return true;
67866 }
67867
67868 public function hasChildren()
67869 {
67870 return $this->isRecursive && $this->iterator->hasChildren();
67871 }
67872
67873 public function getChildren()
67874 {
67875 $children = new self($this->iterator->getChildren(), array());
67876 $children->excludedDirs = $this->excludedDirs;
67877 $children->excludedPattern = $this->excludedPattern;
67878
67879 return $children;
67880 }
67881 }
67882 <?php
67883
67884
67885
67886
67887
67888
67889
67890
67891
67892
67893 namespace Symfony\Component\Finder\Iterator;
67894
67895 @trigger_error('The '.__NAMESPACE__.'\FilePathsIterator class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67896
67897 use Symfony\Component\Finder\SplFileInfo;
67898
67899
67900
67901
67902
67903
67904
67905
67906 class FilePathsIterator extends \ArrayIterator
67907 {
67908
67909
67910
67911 private $baseDir;
67912
67913
67914
67915
67916 private $baseDirLength;
67917
67918
67919
67920
67921 private $subPath;
67922
67923
67924
67925
67926 private $subPathname;
67927
67928
67929
67930
67931 private $current;
67932
67933
67934
67935
67936
67937 public function __construct(array $paths, $baseDir)
67938 {
67939 $this->baseDir = $baseDir;
67940 $this->baseDirLength = strlen($baseDir);
67941
67942 parent::__construct($paths);
67943 }
67944
67945
67946
67947
67948
67949
67950
67951 public function __call($name, array $arguments)
67952 {
67953 return call_user_func_array(array($this->current(), $name), $arguments);
67954 }
67955
67956
67957
67958
67959
67960
67961 public function current()
67962 {
67963 return $this->current;
67964 }
67965
67966
67967
67968
67969 public function key()
67970 {
67971 return $this->current->getPathname();
67972 }
67973
67974 public function next()
67975 {
67976 parent::next();
67977 $this->buildProperties();
67978 }
67979
67980 public function rewind()
67981 {
67982 parent::rewind();
67983 $this->buildProperties();
67984 }
67985
67986
67987
67988
67989 public function getSubPath()
67990 {
67991 return $this->subPath;
67992 }
67993
67994
67995
67996
67997 public function getSubPathname()
67998 {
67999 return $this->subPathname;
68000 }
68001
68002 private function buildProperties()
68003 {
68004 $absolutePath = parent::current();
68005
68006 if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
68007 $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
68008 $dir = dirname($this->subPathname);
68009 $this->subPath = '.' === $dir ? '' : $dir;
68010 } else {
68011 $this->subPath = $this->subPathname = '';
68012 }
68013
68014 $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
68015 }
68016 }
68017 <?php
68018
68019
68020
68021
68022
68023
68024
68025
68026
68027
68028 namespace Symfony\Component\Finder\Iterator;
68029
68030
68031
68032
68033
68034
68035 class FileTypeFilterIterator extends FilterIterator
68036 {
68037 const ONLY_FILES = 1;
68038 const ONLY_DIRECTORIES = 2;
68039
68040 private $mode;
68041
68042
68043
68044
68045
68046 public function __construct(\Iterator $iterator, $mode)
68047 {
68048 $this->mode = $mode;
68049
68050 parent::__construct($iterator);
68051 }
68052
68053
68054
68055
68056
68057
68058 public function accept()
68059 {
68060 $fileinfo = $this->current();
68061 if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
68062 return false;
68063 } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
68064 return false;
68065 }
68066
68067 return true;
68068 }
68069 }
68070 <?php
68071
68072
68073
68074
68075
68076
68077
68078
68079
68080
68081 namespace Symfony\Component\Finder\Iterator;
68082
68083
68084
68085
68086
68087
68088
68089 class FilecontentFilterIterator extends MultiplePcreFilterIterator
68090 {
68091
68092
68093
68094
68095
68096 public function accept()
68097 {
68098 if (!$this->matchRegexps && !$this->noMatchRegexps) {
68099 return true;
68100 }
68101
68102 $fileinfo = $this->current();
68103
68104 if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
68105 return false;
68106 }
68107
68108 $content = $fileinfo->getContents();
68109 if (!$content) {
68110 return false;
68111 }
68112
68113 return $this->isAccepted($content);
68114 }
68115
68116
68117
68118
68119
68120
68121
68122
68123 protected function toRegex($str)
68124 {
68125 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
68126 }
68127 }
68128 <?php
68129
68130
68131
68132
68133
68134
68135
68136
68137
68138
68139 namespace Symfony\Component\Finder\Iterator;
68140
68141 use Symfony\Component\Finder\Glob;
68142
68143
68144
68145
68146
68147
68148 class FilenameFilterIterator extends MultiplePcreFilterIterator
68149 {
68150
68151
68152
68153
68154
68155 public function accept()
68156 {
68157 return $this->isAccepted($this->current()->getFilename());
68158 }
68159
68160
68161
68162
68163
68164
68165
68166
68167
68168
68169
68170 protected function toRegex($str)
68171 {
68172 return $this->isRegex($str) ? $str : Glob::toRegex($str);
68173 }
68174 }
68175 <?php
68176
68177
68178
68179
68180
68181
68182
68183
68184
68185
68186 namespace Symfony\Component\Finder\Iterator;
68187
68188
68189
68190
68191
68192
68193
68194
68195
68196 abstract class FilterIterator extends \FilterIterator
68197 {
68198
68199
68200
68201
68202
68203
68204 public function rewind()
68205 {
68206 if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
68207 parent::rewind();
68208
68209 return;
68210 }
68211
68212 $iterator = $this;
68213 while ($iterator instanceof \OuterIterator) {
68214 $innerIterator = $iterator->getInnerIterator();
68215
68216 if ($innerIterator instanceof RecursiveDirectoryIterator) {
68217
68218  if ($innerIterator->isRewindable()) {
68219 $innerIterator->next();
68220 $innerIterator->rewind();
68221 }
68222 } elseif ($innerIterator instanceof \FilesystemIterator) {
68223 $innerIterator->next();
68224 $innerIterator->rewind();
68225 }
68226
68227 $iterator = $innerIterator;
68228 }
68229
68230 parent::rewind();
68231 }
68232 }
68233 <?php
68234
68235
68236
68237
68238
68239
68240
68241
68242
68243
68244 namespace Symfony\Component\Finder\Iterator;
68245
68246
68247
68248
68249
68250
68251 abstract class MultiplePcreFilterIterator extends FilterIterator
68252 {
68253 protected $matchRegexps = array();
68254 protected $noMatchRegexps = array();
68255
68256
68257
68258
68259
68260
68261 public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
68262 {
68263 foreach ($matchPatterns as $pattern) {
68264 $this->matchRegexps[] = $this->toRegex($pattern);
68265 }
68266
68267 foreach ($noMatchPatterns as $pattern) {
68268 $this->noMatchRegexps[] = $this->toRegex($pattern);
68269 }
68270
68271 parent::__construct($iterator);
68272 }
68273
68274
68275
68276
68277
68278
68279
68280
68281
68282
68283
68284
68285 protected function isAccepted($string)
68286 {
68287
68288  foreach ($this->noMatchRegexps as $regex) {
68289 if (preg_match($regex, $string)) {
68290 return false;
68291 }
68292 }
68293
68294
68295  if ($this->matchRegexps) {
68296 foreach ($this->matchRegexps as $regex) {
68297 if (preg_match($regex, $string)) {
68298 return true;
68299 }
68300 }
68301
68302 return false;
68303 }
68304
68305
68306  return true;
68307 }
68308
68309
68310
68311
68312
68313
68314
68315
68316 protected function isRegex($str)
68317 {
68318 if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
68319 $start = substr($m[1], 0, 1);
68320 $end = substr($m[1], -1);
68321
68322 if ($start === $end) {
68323 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
68324 }
68325
68326 foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
68327 if ($start === $delimiters[0] && $end === $delimiters[1]) {
68328 return true;
68329 }
68330 }
68331 }
68332
68333 return false;
68334 }
68335
68336
68337
68338
68339
68340
68341
68342
68343 abstract protected function toRegex($str);
68344 }
68345 <?php
68346
68347
68348
68349
68350
68351
68352
68353
68354
68355
68356 namespace Symfony\Component\Finder\Iterator;
68357
68358
68359
68360
68361
68362
68363
68364 class PathFilterIterator extends MultiplePcreFilterIterator
68365 {
68366
68367
68368
68369
68370
68371 public function accept()
68372 {
68373 $filename = $this->current()->getRelativePathname();
68374
68375 if ('\\' === DIRECTORY_SEPARATOR) {
68376 $filename = str_replace('\\', '/', $filename);
68377 }
68378
68379 return $this->isAccepted($filename);
68380 }
68381
68382
68383
68384
68385
68386
68387
68388
68389
68390
68391
68392
68393
68394
68395
68396 protected function toRegex($str)
68397 {
68398 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
68399 }
68400 }
68401 <?php
68402
68403
68404
68405
68406
68407
68408
68409
68410
68411
68412 namespace Symfony\Component\Finder\Iterator;
68413
68414 use Symfony\Component\Finder\Exception\AccessDeniedException;
68415 use Symfony\Component\Finder\SplFileInfo;
68416
68417
68418
68419
68420
68421
68422 class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
68423 {
68424
68425
68426
68427 private $ignoreUnreadableDirs;
68428
68429
68430
68431
68432 private $rewindable;
68433
68434
68435  private $rootPath;
68436 private $subPath;
68437 private $directorySeparator = '/';
68438
68439
68440
68441
68442
68443
68444
68445
68446 public function __construct($path, $flags, $ignoreUnreadableDirs = false)
68447 {
68448 if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
68449 throw new \RuntimeException('This iterator only support returning current as fileinfo.');
68450 }
68451
68452 parent::__construct($path, $flags);
68453 $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
68454 $this->rootPath = (string) $path;
68455 if ('/' !== DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
68456 $this->directorySeparator = DIRECTORY_SEPARATOR;
68457 }
68458 }
68459
68460
68461
68462
68463
68464
68465 public function current()
68466 {
68467
68468
68469 if (null === $subPathname = $this->subPath) {
68470 $subPathname = $this->subPath = (string) $this->getSubPath();
68471 }
68472 if ('' !== $subPathname) {
68473 $subPathname .= $this->directorySeparator;
68474 }
68475 $subPathname .= $this->getFilename();
68476
68477 return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
68478 }
68479
68480
68481
68482
68483
68484
68485 public function getChildren()
68486 {
68487 try {
68488 $children = parent::getChildren();
68489
68490 if ($children instanceof self) {
68491
68492  $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
68493
68494
68495  $children->rewindable = &$this->rewindable;
68496 $children->rootPath = $this->rootPath;
68497 }
68498
68499 return $children;
68500 } catch (\UnexpectedValueException $e) {
68501 if ($this->ignoreUnreadableDirs) {
68502
68503  return new \RecursiveArrayIterator(array());
68504 } else {
68505 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
68506 }
68507 }
68508 }
68509
68510
68511
68512
68513 public function rewind()
68514 {
68515 if (false === $this->isRewindable()) {
68516 return;
68517 }
68518
68519
68520  if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
68521 parent::next();
68522 }
68523
68524 parent::rewind();
68525 }
68526
68527
68528
68529
68530
68531
68532 public function isRewindable()
68533 {
68534 if (null !== $this->rewindable) {
68535 return $this->rewindable;
68536 }
68537
68538
68539  if ('' === $this->getPath()) {
68540 return $this->rewindable = false;
68541 }
68542
68543 if (false !== $stream = @opendir($this->getPath())) {
68544 $infos = stream_get_meta_data($stream);
68545 closedir($stream);
68546
68547 if ($infos['seekable']) {
68548 return $this->rewindable = true;
68549 }
68550 }
68551
68552 return $this->rewindable = false;
68553 }
68554 }
68555 <?php
68556
68557
68558
68559
68560
68561
68562
68563
68564
68565
68566 namespace Symfony\Component\Finder\Iterator;
68567
68568 use Symfony\Component\Finder\Comparator\NumberComparator;
68569
68570
68571
68572
68573
68574
68575 class SizeRangeFilterIterator extends FilterIterator
68576 {
68577 private $comparators = array();
68578
68579
68580
68581
68582
68583 public function __construct(\Iterator $iterator, array $comparators)
68584 {
68585 $this->comparators = $comparators;
68586
68587 parent::__construct($iterator);
68588 }
68589
68590
68591
68592
68593
68594
68595 public function accept()
68596 {
68597 $fileinfo = $this->current();
68598 if (!$fileinfo->isFile()) {
68599 return true;
68600 }
68601
68602 $filesize = $fileinfo->getSize();
68603 foreach ($this->comparators as $compare) {
68604 if (!$compare->test($filesize)) {
68605 return false;
68606 }
68607 }
68608
68609 return true;
68610 }
68611 }
68612 <?php
68613
68614
68615
68616
68617
68618
68619
68620
68621
68622
68623 namespace Symfony\Component\Finder\Iterator;
68624
68625
68626
68627
68628
68629
68630 class SortableIterator implements \IteratorAggregate
68631 {
68632 const SORT_BY_NAME = 1;
68633 const SORT_BY_TYPE = 2;
68634 const SORT_BY_ACCESSED_TIME = 3;
68635 const SORT_BY_CHANGED_TIME = 4;
68636 const SORT_BY_MODIFIED_TIME = 5;
68637
68638 private $iterator;
68639 private $sort;
68640
68641
68642
68643
68644
68645
68646
68647 public function __construct(\Traversable $iterator, $sort)
68648 {
68649 $this->iterator = $iterator;
68650
68651 if (self::SORT_BY_NAME === $sort) {
68652 $this->sort = function ($a, $b) {
68653 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
68654 };
68655 } elseif (self::SORT_BY_TYPE === $sort) {
68656 $this->sort = function ($a, $b) {
68657 if ($a->isDir() && $b->isFile()) {
68658 return -1;
68659 } elseif ($a->isFile() && $b->isDir()) {
68660 return 1;
68661 }
68662
68663 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
68664 };
68665 } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
68666 $this->sort = function ($a, $b) {
68667 return $a->getATime() - $b->getATime();
68668 };
68669 } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
68670 $this->sort = function ($a, $b) {
68671 return $a->getCTime() - $b->getCTime();
68672 };
68673 } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
68674 $this->sort = function ($a, $b) {
68675 return $a->getMTime() - $b->getMTime();
68676 };
68677 } elseif (is_callable($sort)) {
68678 $this->sort = $sort;
68679 } else {
68680 throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
68681 }
68682 }
68683
68684 public function getIterator()
68685 {
68686 $array = iterator_to_array($this->iterator, true);
68687 uasort($array, $this->sort);
68688
68689 return new \ArrayIterator($array);
68690 }
68691 }
68692 Copyright (c) 2004-2017 Fabien Potencier
68693
68694 Permission is hereby granted, free of charge, to any person obtaining a copy
68695 of this software and associated documentation files (the "Software"), to deal
68696 in the Software without restriction, including without limitation the rights
68697 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
68698 copies of the Software, and to permit persons to whom the Software is furnished
68699 to do so, subject to the following conditions:
68700
68701 The above copyright notice and this permission notice shall be included in all
68702 copies or substantial portions of the Software.
68703
68704 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68705 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68706 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
68707 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
68708 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68709 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68710 THE SOFTWARE.
68711 <?php
68712
68713
68714
68715
68716
68717
68718
68719
68720
68721
68722 namespace Symfony\Component\Finder\Shell;
68723
68724 @trigger_error('The '.__NAMESPACE__.'\Command class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68725
68726
68727
68728
68729
68730
68731 class Command
68732 {
68733 private $parent;
68734 private $bits = array();
68735 private $labels = array();
68736
68737
68738
68739
68740 private $errorHandler;
68741
68742 public function __construct(Command $parent = null)
68743 {
68744 $this->parent = $parent;
68745 }
68746
68747
68748
68749
68750
68751
68752 public function __toString()
68753 {
68754 return $this->join();
68755 }
68756
68757
68758
68759
68760
68761
68762 public static function create(Command $parent = null)
68763 {
68764 return new self($parent);
68765 }
68766
68767
68768
68769
68770
68771
68772
68773
68774 public static function escape($input)
68775 {
68776 return escapeshellcmd($input);
68777 }
68778
68779
68780
68781
68782
68783
68784
68785
68786 public static function quote($input)
68787 {
68788 return escapeshellarg($input);
68789 }
68790
68791
68792
68793
68794
68795
68796
68797
68798 public function add($bit)
68799 {
68800 $this->bits[] = $bit;
68801
68802 return $this;
68803 }
68804
68805
68806
68807
68808
68809
68810
68811
68812 public function top($bit)
68813 {
68814 array_unshift($this->bits, $bit);
68815
68816 foreach ($this->labels as $label => $index) {
68817 $this->labels[$label] += 1;
68818 }
68819
68820 return $this;
68821 }
68822
68823
68824
68825
68826
68827
68828
68829
68830 public function arg($arg)
68831 {
68832 $this->bits[] = self::quote($arg);
68833
68834 return $this;
68835 }
68836
68837
68838
68839
68840
68841
68842
68843
68844 public function cmd($esc)
68845 {
68846 $this->bits[] = self::escape($esc);
68847
68848 return $this;
68849 }
68850
68851
68852
68853
68854
68855
68856
68857
68858
68859
68860 public function ins($label)
68861 {
68862 if (isset($this->labels[$label])) {
68863 throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
68864 }
68865
68866 $this->bits[] = self::create($this);
68867 $this->labels[$label] = count($this->bits) - 1;
68868
68869 return $this->bits[$this->labels[$label]];
68870 }
68871
68872
68873
68874
68875
68876
68877
68878
68879
68880
68881 public function get($label)
68882 {
68883 if (!isset($this->labels[$label])) {
68884 throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
68885 }
68886
68887 return $this->bits[$this->labels[$label]];
68888 }
68889
68890
68891
68892
68893
68894
68895
68896
68897 public function end()
68898 {
68899 if (null === $this->parent) {
68900 throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
68901 }
68902
68903 return $this->parent;
68904 }
68905
68906
68907
68908
68909
68910
68911 public function length()
68912 {
68913 return count($this->bits);
68914 }
68915
68916
68917
68918
68919 public function setErrorHandler(\Closure $errorHandler)
68920 {
68921 $this->errorHandler = $errorHandler;
68922
68923 return $this;
68924 }
68925
68926
68927
68928
68929 public function getErrorHandler()
68930 {
68931 return $this->errorHandler;
68932 }
68933
68934
68935
68936
68937
68938
68939
68940
68941 public function execute()
68942 {
68943 if (null === $errorHandler = $this->errorHandler) {
68944 exec($this->join(), $output);
68945 } else {
68946 $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
68947 $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
68948
68949 if ($error = stream_get_contents($pipes[2])) {
68950 $errorHandler($error);
68951 }
68952
68953 proc_close($process);
68954 }
68955
68956 return $output ?: array();
68957 }
68958
68959
68960
68961
68962
68963
68964 public function join()
68965 {
68966 return implode(' ', array_filter(
68967 array_map(function ($bit) {
68968 return $bit instanceof Command ? $bit->join() : ($bit ?: null);
68969 }, $this->bits),
68970 function ($bit) { return null !== $bit; }
68971 ));
68972 }
68973
68974
68975
68976
68977
68978
68979
68980
68981
68982 public function addAtIndex($bit, $index)
68983 {
68984 array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit);
68985
68986 return $this;
68987 }
68988 }
68989 <?php
68990
68991
68992
68993
68994
68995
68996
68997
68998
68999
69000 namespace Symfony\Component\Finder\Shell;
69001
69002 @trigger_error('The '.__NAMESPACE__.'\Shell class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69003
69004
69005
69006
69007
69008
69009 class Shell
69010 {
69011 const TYPE_UNIX = 1;
69012 const TYPE_DARWIN = 2;
69013 const TYPE_CYGWIN = 3;
69014 const TYPE_WINDOWS = 4;
69015 const TYPE_BSD = 5;
69016
69017
69018
69019
69020 private $type;
69021
69022
69023
69024
69025
69026
69027 public function getType()
69028 {
69029 if (null === $this->type) {
69030 $this->type = $this->guessType();
69031 }
69032
69033 return $this->type;
69034 }
69035
69036
69037
69038
69039
69040
69041
69042
69043 public function testCommand($command)
69044 {
69045 if (!function_exists('exec')) {
69046 return false;
69047 }
69048
69049
69050  $testCommand = 'which ';
69051 if (self::TYPE_WINDOWS === $this->type) {
69052 $testCommand = 'where ';
69053 }
69054
69055 $command = escapeshellcmd($command);
69056
69057 exec($testCommand.$command, $output, $code);
69058
69059 return 0 === $code && count($output) > 0;
69060 }
69061
69062
69063
69064
69065
69066
69067 private function guessType()
69068 {
69069 $os = strtolower(PHP_OS);
69070
69071 if (false !== strpos($os, 'cygwin')) {
69072 return self::TYPE_CYGWIN;
69073 }
69074
69075 if (false !== strpos($os, 'darwin')) {
69076 return self::TYPE_DARWIN;
69077 }
69078
69079 if (false !== strpos($os, 'bsd')) {
69080 return self::TYPE_BSD;
69081 }
69082
69083 if (0 === strpos($os, 'win')) {
69084 return self::TYPE_WINDOWS;
69085 }
69086
69087 return self::TYPE_UNIX;
69088 }
69089 }
69090 <?php
69091
69092
69093
69094
69095
69096
69097
69098
69099
69100
69101 namespace Symfony\Component\Finder;
69102
69103
69104
69105
69106
69107
69108 class SplFileInfo extends \SplFileInfo
69109 {
69110 private $relativePath;
69111 private $relativePathname;
69112
69113
69114
69115
69116
69117
69118 public function __construct($file, $relativePath, $relativePathname)
69119 {
69120 parent::__construct($file);
69121 $this->relativePath = $relativePath;
69122 $this->relativePathname = $relativePathname;
69123 }
69124
69125
69126
69127
69128
69129
69130
69131
69132 public function getRelativePath()
69133 {
69134 return $this->relativePath;
69135 }
69136
69137
69138
69139
69140
69141
69142
69143
69144 public function getRelativePathname()
69145 {
69146 return $this->relativePathname;
69147 }
69148
69149
69150
69151
69152
69153
69154
69155
69156 public function getContents()
69157 {
69158 $level = error_reporting(0);
69159 $content = file_get_contents($this->getPathname());
69160 error_reporting($level);
69161 if (false === $content) {
69162 $error = error_get_last();
69163 throw new \RuntimeException($error['message']);
69164 }
69165
69166 return $content;
69167 }
69168 }
69169 Copyright (c) 2014-2016 Fabien Potencier
69170
69171 Permission is hereby granted, free of charge, to any person obtaining a copy
69172 of this software and associated documentation files (the "Software"), to deal
69173 in the Software without restriction, including without limitation the rights
69174 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
69175 copies of the Software, and to permit persons to whom the Software is furnished
69176 to do so, subject to the following conditions:
69177
69178 The above copyright notice and this permission notice shall be included in all
69179 copies or substantial portions of the Software.
69180
69181 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
69182 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69183 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
69184 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
69185 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
69186 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
69187 THE SOFTWARE.
69188 <?php
69189
69190
69191
69192
69193
69194
69195
69196
69197
69198
69199 namespace Symfony\Polyfill\Mbstring;
69200
69201
69202
69203
69204
69205
69206
69207
69208
69209
69210
69211
69212
69213
69214
69215
69216
69217
69218
69219
69220
69221
69222
69223
69224
69225
69226
69227
69228
69229
69230
69231
69232
69233
69234
69235
69236
69237
69238
69239
69240
69241
69242
69243
69244
69245
69246
69247
69248
69249
69250
69251
69252
69253 final class Mbstring
69254 {
69255 const MB_CASE_FOLD = PHP_INT_MAX;
69256
69257 private static $encodingList = array('ASCII', 'UTF-8');
69258 private static $language = 'neutral';
69259 private static $internalEncoding = 'UTF-8';
69260 private static $caseFold = array(
69261 array('µ','ſ',"\xCD\x85",'ς',"\xCF\x90","\xCF\x91","\xCF\x95","\xCF\x96","\xCF\xB0","\xCF\xB1","\xCF\xB5","\xE1\xBA\x9B","\xE1\xBE\xBE"),
69262 array('μ','s','ι', 'σ','β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1",'ι'),
69263 );
69264
69265 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
69266 {
69267 if (is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
69268 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
69269 } else {
69270 $fromEncoding = self::getEncoding($fromEncoding);
69271 }
69272
69273 $toEncoding = self::getEncoding($toEncoding);
69274
69275 if ('BASE64' === $fromEncoding) {
69276 $s = base64_decode($s);
69277 $fromEncoding = $toEncoding;
69278 }
69279
69280 if ('BASE64' === $toEncoding) {
69281 return base64_encode($s);
69282 }
69283
69284 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
69285 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
69286 $fromEncoding = 'Windows-1252';
69287 }
69288 if ('UTF-8' !== $fromEncoding) {
69289 $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
69290 }
69291
69292 return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
69293 }
69294
69295 if ('HTML-ENTITIES' === $fromEncoding) {
69296 $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
69297 $fromEncoding = 'UTF-8';
69298 }
69299
69300 return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
69301 }
69302
69303 public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
69304 {
69305 $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
69306
69307 $ok = true;
69308 array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
69309 if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
69310 $ok = false;
69311 }
69312 });
69313
69314 return $ok ? $fromEncoding : false;
69315 }
69316
69317 public static function mb_decode_mimeheader($s)
69318 {
69319 return iconv_mime_decode($s, 2, self::$internalEncoding);
69320 }
69321
69322 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
69323 {
69324 trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
69325 }
69326
69327 public static function mb_convert_case($s, $mode, $encoding = null)
69328 {
69329 if ('' === $s .= '') {
69330 return '';
69331 }
69332
69333 $encoding = self::getEncoding($encoding);
69334
69335 if ('UTF-8' === $encoding) {
69336 $encoding = null;
69337 if (!preg_match('//u', $s)) {
69338 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
69339 }
69340 } else {
69341 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
69342 }
69343
69344 if (MB_CASE_TITLE == $mode) {
69345 $s = preg_replace_callback('/\b\p{Ll}/u', array(__CLASS__, 'title_case_upper'), $s);
69346 $s = preg_replace_callback('/\B[\p{Lu}\p{Lt}]+/u', array(__CLASS__, 'title_case_lower'), $s);
69347 } else {
69348 if (MB_CASE_UPPER == $mode) {
69349 static $upper = null;
69350 if (null === $upper) {
69351 $upper = self::getData('upperCase');
69352 }
69353 $map = $upper;
69354 } else {
69355 if (self::MB_CASE_FOLD === $mode) {
69356 $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
69357 }
69358
69359 static $lower = null;
69360 if (null === $lower) {
69361 $lower = self::getData('lowerCase');
69362 }
69363 $map = $lower;
69364 }
69365
69366 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
69367
69368 $i = 0;
69369 $len = strlen($s);
69370
69371 while ($i < $len) {
69372 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
69373 $uchr = substr($s, $i, $ulen);
69374 $i += $ulen;
69375
69376 if (isset($map[$uchr])) {
69377 $uchr = $map[$uchr];
69378 $nlen = strlen($uchr);
69379
69380 if ($nlen == $ulen) {
69381 $nlen = $i;
69382 do {
69383 $s[--$nlen] = $uchr[--$ulen];
69384 } while ($ulen);
69385 } else {
69386 $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
69387 $len += $nlen - $ulen;
69388 $i += $nlen - $ulen;
69389 }
69390 }
69391 }
69392 }
69393
69394 if (null === $encoding) {
69395 return $s;
69396 }
69397
69398 return iconv('UTF-8', $encoding.'//IGNORE', $s);
69399 }
69400
69401 public static function mb_internal_encoding($encoding = null)
69402 {
69403 if (null === $encoding) {
69404 return self::$internalEncoding;
69405 }
69406
69407 $encoding = self::getEncoding($encoding);
69408
69409 if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
69410 self::$internalEncoding = $encoding;
69411
69412 return true;
69413 }
69414
69415 return false;
69416 }
69417
69418 public static function mb_language($lang = null)
69419 {
69420 if (null === $lang) {
69421 return self::$language;
69422 }
69423
69424 switch ($lang = strtolower($lang)) {
69425 case 'uni':
69426 case 'neutral':
69427 self::$language = $lang;
69428
69429 return true;
69430 }
69431
69432 return false;
69433 }
69434
69435 public static function mb_list_encodings()
69436 {
69437 return array('UTF-8');
69438 }
69439
69440 public static function mb_encoding_aliases($encoding)
69441 {
69442 switch (strtoupper($encoding)) {
69443 case 'UTF8':
69444 case 'UTF-8':
69445 return array('utf8');
69446 }
69447
69448 return false;
69449 }
69450
69451 public static function mb_check_encoding($var = null, $encoding = null)
69452 {
69453 if (null === $encoding) {
69454 if (null === $var) {
69455 return false;
69456 }
69457 $encoding = self::$internalEncoding;
69458 }
69459
69460 return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
69461 }
69462
69463 public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
69464 {
69465 if (null === $encodingList) {
69466 $encodingList = self::$encodingList;
69467 } else {
69468 if (!is_array($encodingList)) {
69469 $encodingList = array_map('trim', explode(',', $encodingList));
69470 }
69471 $encodingList = array_map('strtoupper', $encodingList);
69472 }
69473
69474 foreach ($encodingList as $enc) {
69475 switch ($enc) {
69476 case 'ASCII':
69477 if (!preg_match('/[\x80-\xFF]/', $str)) {
69478 return $enc;
69479 }
69480 break;
69481
69482 case 'UTF8':
69483 case 'UTF-8':
69484 if (preg_match('//u', $str)) {
69485 return 'UTF-8';
69486 }
69487 break;
69488
69489 default:
69490 if (0 === strncmp($enc, 'ISO-8859-', 9)) {
69491 return $enc;
69492 }
69493 }
69494 }
69495
69496 return false;
69497 }
69498
69499 public static function mb_detect_order($encodingList = null)
69500 {
69501 if (null === $encodingList) {
69502 return self::$encodingList;
69503 }
69504
69505 if (!is_array($encodingList)) {
69506 $encodingList = array_map('trim', explode(',', $encodingList));
69507 }
69508 $encodingList = array_map('strtoupper', $encodingList);
69509
69510 foreach ($encodingList as $enc) {
69511 switch ($enc) {
69512 default:
69513 if (strncmp($enc, 'ISO-8859-', 9)) {
69514 return false;
69515 }
69516 case 'ASCII':
69517 case 'UTF8':
69518 case 'UTF-8':
69519 }
69520 }
69521
69522 self::$encodingList = $encodingList;
69523
69524 return true;
69525 }
69526
69527 public static function mb_strlen($s, $encoding = null)
69528 {
69529 $encoding = self::getEncoding($encoding);
69530 if ('CP850' === $encoding || 'ASCII' === $encoding) {
69531 return strlen($s);
69532 }
69533
69534 return @iconv_strlen($s, $encoding);
69535 }
69536
69537 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
69538 {
69539 $encoding = self::getEncoding($encoding);
69540 if ('CP850' === $encoding || 'ASCII' === $encoding) {
69541 return strpos($haystack, $needle, $offset);
69542 }
69543
69544 if ('' === $needle .= '') {
69545 trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
69546
69547 return false;
69548 }
69549
69550 return iconv_strpos($haystack, $needle, $offset, $encoding);
69551 }
69552
69553 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
69554 {
69555 $encoding = self::getEncoding($encoding);
69556 if ('CP850' === $encoding || 'ASCII' === $encoding) {
69557 return strrpos($haystack, $needle, $offset);
69558 }
69559
69560 if ($offset != (int) $offset) {
69561 $offset = 0;
69562 } elseif ($offset = (int) $offset) {
69563 if ($offset < 0) {
69564 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
69565 $offset = 0;
69566 } else {
69567 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
69568 }
69569 }
69570
69571 $pos = iconv_strrpos($haystack, $needle, $encoding);
69572
69573 return false !== $pos ? $offset + $pos : false;
69574 }
69575
69576 public static function mb_strtolower($s, $encoding = null)
69577 {
69578 return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
69579 }
69580
69581 public static function mb_strtoupper($s, $encoding = null)
69582 {
69583 return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
69584 }
69585
69586 public static function mb_substitute_character($c = null)
69587 {
69588 if (0 === strcasecmp($c, 'none')) {
69589 return true;
69590 }
69591
69592 return null !== $c ? false : 'none';
69593 }
69594
69595 public static function mb_substr($s, $start, $length = null, $encoding = null)
69596 {
69597 $encoding = self::getEncoding($encoding);
69598 if ('CP850' === $encoding || 'ASCII' === $encoding) {
69599 return substr($s, $start, null === $length ? 2147483647 : $length);
69600 }
69601
69602 if ($start < 0) {
69603 $start = iconv_strlen($s, $encoding) + $start;
69604 if ($start < 0) {
69605 $start = 0;
69606 }
69607 }
69608
69609 if (null === $length) {
69610 $length = 2147483647;
69611 } elseif ($length < 0) {
69612 $length = iconv_strlen($s, $encoding) + $length - $start;
69613 if ($length < 0) {
69614 return '';
69615 }
69616 }
69617
69618 return iconv_substr($s, $start, $length, $encoding).'';
69619 }
69620
69621 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
69622 {
69623 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
69624 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
69625
69626 return self::mb_strpos($haystack, $needle, $offset, $encoding);
69627 }
69628
69629 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
69630 {
69631 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
69632
69633 return self::getSubpart($pos, $part, $haystack, $encoding);
69634 }
69635
69636 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
69637 {
69638 $encoding = self::getEncoding($encoding);
69639 if ('CP850' === $encoding || 'ASCII' === $encoding) {
69640 return strrchr($haystack, $needle, $part);
69641 }
69642 $needle = self::mb_substr($needle, 0, 1, $encoding);
69643 $pos = iconv_strrpos($haystack, $needle, $encoding);
69644
69645 return self::getSubpart($pos, $part, $haystack, $encoding);
69646 }
69647
69648 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
69649 {
69650 $needle = self::mb_substr($needle, 0, 1, $encoding);
69651 $pos = self::mb_strripos($haystack, $needle, $encoding);
69652
69653 return self::getSubpart($pos, $part, $haystack, $encoding);
69654 }
69655
69656 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
69657 {
69658 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
69659 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
69660
69661 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
69662 }
69663
69664 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
69665 {
69666 $pos = strpos($haystack, $needle);
69667 if (false === $pos) {
69668 return false;
69669 }
69670 if ($part) {
69671 return substr($haystack, 0, $pos);
69672 }
69673
69674 return substr($haystack, $pos);
69675 }
69676
69677 public static function mb_get_info($type = 'all')
69678 {
69679 $info = array(
69680 'internal_encoding' => self::$internalEncoding,
69681 'http_output' => 'pass',
69682 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
69683 'func_overload' => 0,
69684 'func_overload_list' => 'no overload',
69685 'mail_charset' => 'UTF-8',
69686 'mail_header_encoding' => 'BASE64',
69687 'mail_body_encoding' => 'BASE64',
69688 'illegal_chars' => 0,
69689 'encoding_translation' => 'Off',
69690 'language' => self::$language,
69691 'detect_order' => self::$encodingList,
69692 'substitute_character' => 'none',
69693 'strict_detection' => 'Off',
69694 );
69695
69696 if ('all' === $type) {
69697 return $info;
69698 }
69699 if (isset($info[$type])) {
69700 return $info[$type];
69701 }
69702
69703 return false;
69704 }
69705
69706 public static function mb_http_input($type = '')
69707 {
69708 return false;
69709 }
69710
69711 public static function mb_http_output($encoding = null)
69712 {
69713 return null !== $encoding ? 'pass' === $encoding : 'pass';
69714 }
69715
69716 public static function mb_strwidth($s, $encoding = null)
69717 {
69718 $encoding = self::getEncoding($encoding);
69719
69720 if ('UTF-8' !== $encoding) {
69721 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
69722 }
69723
69724 $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);
69725
69726 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
69727 }
69728
69729 public static function mb_substr_count($haystack, $needle, $encoding = null)
69730 {
69731 return substr_count($haystack, $needle);
69732 }
69733
69734 public static function mb_output_handler($contents, $status)
69735 {
69736 return $contents;
69737 }
69738
69739 public static function mb_chr($code, $encoding = null)
69740 {
69741 if (0x80 > $code %= 0x200000) {
69742 $s = chr($code);
69743 } elseif (0x800 > $code) {
69744 $s = chr(0xC0 | $code >> 6).chr(0x80 | $code & 0x3F);
69745 } elseif (0x10000 > $code) {
69746 $s = chr(0xE0 | $code >> 12).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
69747 } else {
69748 $s = chr(0xF0 | $code >> 18).chr(0x80 | $code >> 12 & 0x3F).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
69749 }
69750
69751 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
69752 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
69753 }
69754
69755 return $s;
69756 }
69757
69758 public static function mb_ord($s, $encoding = null)
69759 {
69760 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
69761 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
69762 }
69763
69764 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
69765 if (0xF0 <= $code) {
69766 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
69767 }
69768 if (0xE0 <= $code) {
69769 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
69770 }
69771 if (0xC0 <= $code) {
69772 return (($code - 0xC0) << 6) + $s[2] - 0x80;
69773 }
69774
69775 return $code;
69776 }
69777
69778 private static function getSubpart($pos, $part, $haystack, $encoding)
69779 {
69780 if (false === $pos) {
69781 return false;
69782 }
69783 if ($part) {
69784 return self::mb_substr($haystack, 0, $pos, $encoding);
69785 }
69786
69787 return self::mb_substr($haystack, $pos, null, $encoding);
69788 }
69789
69790 private static function html_encoding_callback($m)
69791 {
69792 $i = 1;
69793 $entities = '';
69794 $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
69795
69796 while (isset($m[$i])) {
69797 if (0x80 > $m[$i]) {
69798 $entities .= chr($m[$i++]);
69799 continue;
69800 }
69801 if (0xF0 <= $m[$i]) {
69802 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
69803 } elseif (0xE0 <= $m[$i]) {
69804 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
69805 } else {
69806 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
69807 }
69808
69809 $entities .= '&#'.$c.';';
69810 }
69811
69812 return $entities;
69813 }
69814
69815 private static function title_case_lower($s)
69816 {
69817 return self::mb_convert_case($s[0], MB_CASE_LOWER, 'UTF-8');
69818 }
69819
69820 private static function title_case_upper($s)
69821 {
69822 return self::mb_convert_case($s[0], MB_CASE_UPPER, 'UTF-8');
69823 }
69824
69825 private static function getData($file)
69826 {
69827 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
69828 return require $file;
69829 }
69830
69831 return false;
69832 }
69833
69834 private static function getEncoding($encoding)
69835 {
69836 if (null === $encoding) {
69837 return self::$internalEncoding;
69838 }
69839
69840 $encoding = strtoupper($encoding);
69841
69842 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
69843 return 'CP850';
69844 }
69845 if ('UTF8' === $encoding) {
69846 return 'UTF-8';
69847 }
69848
69849 return $encoding;
69850 }
69851 }
69852 <?php
69853
69854 static $data = array (
69855 'A' => 'a',
69856 'B' => 'b',
69857 'C' => 'c',
69858 'D' => 'd',
69859 'E' => 'e',
69860 'F' => 'f',
69861 'G' => 'g',
69862 'H' => 'h',
69863 'I' => 'i',
69864 'J' => 'j',
69865 'K' => 'k',
69866 'L' => 'l',
69867 'M' => 'm',
69868 'N' => 'n',
69869 'O' => 'o',
69870 'P' => 'p',
69871 'Q' => 'q',
69872 'R' => 'r',
69873 'S' => 's',
69874 'T' => 't',
69875 'U' => 'u',
69876 'V' => 'v',
69877 'W' => 'w',
69878 'X' => 'x',
69879 'Y' => 'y',
69880 'Z' => 'z',
69881 'À' => 'à',
69882 'Á' => 'á',
69883 'Â' => 'â',
69884 'Ã' => 'ã',
69885 'Ä' => 'ä',
69886 'Å' => 'å',
69887 'Æ' => 'æ',
69888 'Ç' => 'ç',
69889 'È' => 'è',
69890 'É' => 'é',
69891 'Ê' => 'ê',
69892 'Ë' => 'ë',
69893 'Ì' => 'ì',
69894 'Í' => 'í',
69895 'Î' => 'î',
69896 'Ï' => 'ï',
69897 'Ð' => 'ð',
69898 'Ñ' => 'ñ',
69899 'Ò' => 'ò',
69900 'Ó' => 'ó',
69901 'Ô' => 'ô',
69902 'Õ' => 'õ',
69903 'Ö' => 'ö',
69904 'Ø' => 'ø',
69905 'Ù' => 'ù',
69906 'Ú' => 'ú',
69907 'Û' => 'û',
69908 'Ü' => 'ü',
69909 'Ý' => 'ý',
69910 'Þ' => 'þ',
69911 'Ā' => 'ā',
69912 'Ă' => 'ă',
69913 'Ą' => 'ą',
69914 'Ć' => 'ć',
69915 'Ĉ' => 'ĉ',
69916 'Ċ' => 'ċ',
69917 'Č' => 'č',
69918 'Ď' => 'ď',
69919 'Đ' => 'đ',
69920 'Ē' => 'ē',
69921 'Ĕ' => 'ĕ',
69922 'Ė' => 'ė',
69923 'Ę' => 'ę',
69924 'Ě' => 'ě',
69925 'Ĝ' => 'ĝ',
69926 'Ğ' => 'ğ',
69927 'Ġ' => 'ġ',
69928 'Ģ' => 'ģ',
69929 'Ĥ' => 'ĥ',
69930 'Ħ' => 'ħ',
69931 'Ĩ' => 'ĩ',
69932 'Ī' => 'ī',
69933 'Ĭ' => 'ĭ',
69934 'Į' => 'į',
69935 'İ' => 'i',
69936 'IJ' => 'ij',
69937 'Ĵ' => 'ĵ',
69938 'Ķ' => 'ķ',
69939 'Ĺ' => 'ĺ',
69940 'Ļ' => 'ļ',
69941 'Ľ' => 'ľ',
69942 'Ŀ' => 'ŀ',
69943 'Ł' => 'ł',
69944 'Ń' => 'ń',
69945 'Ņ' => 'ņ',
69946 'Ň' => 'ň',
69947 'Ŋ' => 'ŋ',
69948 'Ō' => 'ō',
69949 'Ŏ' => 'ŏ',
69950 'Ő' => 'ő',
69951 'Œ' => 'œ',
69952 'Ŕ' => 'ŕ',
69953 'Ŗ' => 'ŗ',
69954 'Ř' => 'ř',
69955 'Ś' => 'ś',
69956 'Ŝ' => 'ŝ',
69957 'Ş' => 'ş',
69958 'Š' => 'š',
69959 'Ţ' => 'ţ',
69960 'Ť' => 'ť',
69961 'Ŧ' => 'ŧ',
69962 'Ũ' => 'ũ',
69963 'Ū' => 'ū',
69964 'Ŭ' => 'ŭ',
69965 'Ů' => 'ů',
69966 'Ű' => 'ű',
69967 'Ų' => 'ų',
69968 'Ŵ' => 'ŵ',
69969 'Ŷ' => 'ŷ',
69970 'Ÿ' => 'ÿ',
69971 'Ź' => 'ź',
69972 'Ż' => 'ż',
69973 'Ž' => 'ž',
69974 'Ɓ' => 'ɓ',
69975 'Ƃ' => 'ƃ',
69976 'Ƅ' => 'ƅ',
69977 'Ɔ' => 'ɔ',
69978 'Ƈ' => 'ƈ',
69979 'Ɖ' => 'ɖ',
69980 'Ɗ' => 'ɗ',
69981 'Ƌ' => 'ƌ',
69982 'Ǝ' => 'ǝ',
69983 'Ə' => 'ə',
69984 'Ɛ' => 'ɛ',
69985 'Ƒ' => 'ƒ',
69986 'Ɠ' => 'ɠ',
69987 'Ɣ' => 'ɣ',
69988 'Ɩ' => 'ɩ',
69989 'Ɨ' => 'ɨ',
69990 'Ƙ' => 'ƙ',
69991 'Ɯ' => 'ɯ',
69992 'Ɲ' => 'ɲ',
69993 'Ɵ' => 'ɵ',
69994 'Ơ' => 'ơ',
69995 'Ƣ' => 'ƣ',
69996 'Ƥ' => 'ƥ',
69997 'Ʀ' => 'ʀ',
69998 'Ƨ' => 'ƨ',
69999 'Ʃ' => 'ʃ',
70000 'Ƭ' => 'ƭ',
70001 'Ʈ' => 'ʈ',
70002 'Ư' => 'ư',
70003 'Ʊ' => 'ʊ',
70004 'Ʋ' => 'ʋ',
70005 'Ƴ' => 'ƴ',
70006 'Ƶ' => 'ƶ',
70007 'Ʒ' => 'ʒ',
70008 'Ƹ' => 'ƹ',
70009 'Ƽ' => 'ƽ',
70010 'DŽ' => 'dž',
70011 'Dž' => 'dž',
70012 'LJ' => 'lj',
70013 'Lj' => 'lj',
70014 'NJ' => 'nj',
70015 'Nj' => 'nj',
70016 'Ǎ' => 'ǎ',
70017 'Ǐ' => 'ǐ',
70018 'Ǒ' => 'ǒ',
70019 'Ǔ' => 'ǔ',
70020 'Ǖ' => 'ǖ',
70021 'Ǘ' => 'ǘ',
70022 'Ǚ' => 'ǚ',
70023 'Ǜ' => 'ǜ',
70024 'Ǟ' => 'ǟ',
70025 'Ǡ' => 'ǡ',
70026 'Ǣ' => 'ǣ',
70027 'Ǥ' => 'ǥ',
70028 'Ǧ' => 'ǧ',
70029 'Ǩ' => 'ǩ',
70030 'Ǫ' => 'ǫ',
70031 'Ǭ' => 'ǭ',
70032 'Ǯ' => 'ǯ',
70033 'DZ' => 'dz',
70034 'Dz' => 'dz',
70035 'Ǵ' => 'ǵ',
70036 'Ƕ' => 'ƕ',
70037 'Ƿ' => 'ƿ',
70038 'Ǹ' => 'ǹ',
70039 'Ǻ' => 'ǻ',
70040 'Ǽ' => 'ǽ',
70041 'Ǿ' => 'ǿ',
70042 'Ȁ' => 'ȁ',
70043 'Ȃ' => 'ȃ',
70044 'Ȅ' => 'ȅ',
70045 'Ȇ' => 'ȇ',
70046 'Ȉ' => 'ȉ',
70047 'Ȋ' => 'ȋ',
70048 'Ȍ' => 'ȍ',
70049 'Ȏ' => 'ȏ',
70050 'Ȑ' => 'ȑ',
70051 'Ȓ' => 'ȓ',
70052 'Ȕ' => 'ȕ',
70053 'Ȗ' => 'ȗ',
70054 'Ș' => 'ș',
70055 'Ț' => 'ț',
70056 'Ȝ' => 'ȝ',
70057 'Ȟ' => 'ȟ',
70058 'Ƞ' => 'ƞ',
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 'Ϸ' => 'ϸ',
70133 'Ϲ' => 'ϲ',
70134 'Ϻ' => 'ϻ',
70135 'Ͻ' => 'ͻ',
70136 'Ͼ' => 'ͼ',
70137 'Ͽ' => 'ͽ',
70138 'Ѐ' => 'ѐ',
70139 'Ё' => 'ё',
70140 'Ђ' => 'ђ',
70141 'Ѓ' => 'ѓ',
70142 'Є' => 'є',
70143 'Ѕ' => 'ѕ',
70144 'І' => 'і',
70145 'Ї' => 'ї',
70146 'Ј' => 'ј',
70147 'Љ' => 'љ',
70148 'Њ' => 'њ',
70149 'Ћ' => 'ћ',
70150 'Ќ' => 'ќ',
70151 'Ѝ' => 'ѝ',
70152 'Ў' => 'ў',
70153 'Џ' => 'џ',
70154 'А' => 'а',
70155 'Б' => 'б',
70156 'В' => 'в',
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 'K' => 'k',
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 'Ⲝ' => 'ⲝ',
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 'A' => 'a',
70850 'B' => 'b',
70851 'C' => 'c',
70852 'D' => 'd',
70853 'E' => 'e',
70854 'F' => 'f',
70855 'G' => 'g',
70856 'H' => 'h',
70857 'I' => 'i',
70858 'J' => 'j',
70859 'K' => 'k',
70860 'L' => 'l',
70861 'M' => 'm',
70862 'N' => 'n',
70863 'O' => 'o',
70864 'P' => 'p',
70865 'Q' => 'q',
70866 'R' => 'r',
70867 'S' => 's',
70868 'T' => 't',
70869 'U' => 'u',
70870 'V' => 'v',
70871 'W' => 'w',
70872 'X' => 'x',
70873 'Y' => 'y',
70874 'Z' => 'z',
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 $result =& $data;
70950 unset($data);
70951
70952 return $result;
70953 <?php
70954
70955 static $data = array (
70956 'a' => 'A',
70957 'b' => 'B',
70958 'c' => 'C',
70959 'd' => 'D',
70960 'e' => 'E',
70961 'f' => 'F',
70962 'g' => 'G',
70963 'h' => 'H',
70964 'i' => 'I',
70965 'j' => 'J',
70966 'k' => 'K',
70967 'l' => 'L',
70968 'm' => 'M',
70969 'n' => 'N',
70970 'o' => 'O',
70971 'p' => 'P',
70972 'q' => 'Q',
70973 'r' => 'R',
70974 's' => 'S',
70975 't' => 'T',
70976 'u' => 'U',
70977 'v' => 'V',
70978 'w' => 'W',
70979 'x' => 'X',
70980 'y' => 'Y',
70981 'z' => 'Z',
70982 'µ' => 'Μ',
70983 'à' => 'À',
70984 'á' => 'Á',
70985 'â' => 'Â',
70986 'ã' => 'Ã',
70987 'ä' => 'Ä',
70988 'å' => 'Å',
70989 'æ' => 'Æ',
70990 'ç' => 'Ç',
70991 'è' => 'È',
70992 'é' => 'É',
70993 'ê' => 'Ê',
70994 'ë' => 'Ë',
70995 'ì' => 'Ì',
70996 'í' => 'Í',
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 'ı' => 'I',
71039 'ij' => 'IJ',
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 'ŵ' => 'Ŵ',
71072 'ŷ' => 'Ŷ',
71073 'ź' => 'Ź',
71074 'ż' => 'Ż',
71075 'ž' => 'Ž',
71076 'ſ' => 'S',
71077 'ƀ' => 'Ƀ',
71078 'ƃ' => 'Ƃ',
71079 'ƅ' => 'Ƅ',
71080 'ƈ' => 'Ƈ',
71081 'ƌ' => 'Ƌ',
71082 'ƒ' => 'Ƒ',
71083 'ƕ' => 'Ƕ',
71084 'ƙ' => 'Ƙ',
71085 'ƚ' => 'Ƚ',
71086 'ƞ' => 'Ƞ',
71087 'ơ' => 'Ơ',
71088 'ƣ' => 'Ƣ',
71089 'ƥ' => 'Ƥ',
71090 'ƨ' => 'Ƨ',
71091 'ƭ' => 'Ƭ',
71092 'ư' => 'Ư',
71093 'ƴ' => 'Ƴ',
71094 'ƶ' => 'Ƶ',
71095 'ƹ' => 'Ƹ',
71096 'ƽ' => 'Ƽ',
71097 'ƿ' => 'Ƿ',
71098 'Dž' => 'DŽ',
71099 'dž' => 'DŽ',
71100 'Lj' => 'LJ',
71101 'lj' => 'LJ',
71102 'Nj' => 'NJ',
71103 'nj' => 'NJ',
71104 'ǎ' => 'Ǎ',
71105 'ǐ' => 'Ǐ',
71106 'ǒ' => 'Ǒ',
71107 'ǔ' => 'Ǔ',
71108 'ǖ' => 'Ǖ',
71109 'ǘ' => 'Ǘ',
71110 'ǚ' => 'Ǚ',
71111 'ǜ' => 'Ǜ',
71112 'ǝ' => 'Ǝ',
71113 'ǟ' => 'Ǟ',
71114 'ǡ' => 'Ǡ',
71115 'ǣ' => 'Ǣ',
71116 'ǥ' => 'Ǥ',
71117 'ǧ' => 'Ǧ',
71118 'ǩ' => 'Ǩ',
71119 'ǫ' => 'Ǫ',
71120 'ǭ' => 'Ǭ',
71121 'ǯ' => 'Ǯ',
71122 'Dz' => 'DZ',
71123 'dz' => 'DZ',
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 'ɋ' => 'Ɋ',
71161 'ɍ' => 'Ɍ',
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 'ͱ' => 'Ͱ',
71199 'ͳ' => 'Ͳ',
71200 'ͷ' => 'Ͷ',
71201 'ͻ' => 'Ͻ',
71202 'ͼ' => 'Ͼ',
71203 'ͽ' => 'Ͽ',
71204 'ά' => 'Ά',
71205 'έ' => 'Έ',
71206 'ή' => 'Ή',
71207 'ί' => 'Ί',
71208 'α' => 'Α',
71209 'β' => 'Β',
71210 'γ' => 'Γ',
71211 'δ' => 'Δ',
71212 'ε' => 'Ε',
71213 'ζ' => 'Ζ',
71214 'η' => 'Η',
71215 'θ' => 'Θ',
71216 'ι' => 'Ι',
71217 'κ' => 'Κ',
71218 'λ' => 'Λ',
71219 'μ' => 'Μ',
71220 'ν' => 'Ν',
71221 'ξ' => 'Ξ',
71222 'ο' => 'Ο',
71223 'π' => 'Π',
71224 'ρ' => 'Ρ',
71225 'ς' => 'Σ',
71226 'σ' => 'Σ',
71227 'τ' => 'Τ',
71228 'υ' => 'Υ',
71229 'φ' => 'Φ',
71230 'χ' => 'Χ',
71231 'ψ' => 'Ψ',
71232 'ω' => 'Ω',
71233 'ϊ' => 'Ϊ',
71234 'ϋ' => 'Ϋ',
71235 'ό' => 'Ό',
71236 'ύ' => 'Ύ',
71237 'ώ' => 'Ώ',
71238 'ϐ' => 'Β',
71239 'ϑ' => 'Θ',
71240 'ϕ' => 'Φ',
71241 'ϖ' => 'Π',
71242 'ϗ' => 'Ϗ',
71243 'ϙ' => 'Ϙ',
71244 'ϛ' => 'Ϛ',
71245 'ϝ' => 'Ϝ',
71246 'ϟ' => 'Ϟ',
71247 'ϡ' => 'Ϡ',
71248 'ϣ' => 'Ϣ',
71249 'ϥ' => 'Ϥ',
71250 'ϧ' => 'Ϧ',
71251 'ϩ' => 'Ϩ',
71252 'ϫ' => 'Ϫ',
71253 'ϭ' => 'Ϭ',
71254 'ϯ' => 'Ϯ',
71255 'ϰ' => 'Κ',
71256 'ϱ' => 'Ρ',
71257 'ϲ' => 'Ϲ',
71258 'ϳ' => 'Ϳ',
71259 'ϵ' => 'Ε',
71260 'ϸ' => 'Ϸ',
71261 'ϻ' => 'Ϻ',
71262 'а' => 'А',
71263 'б' => 'Б',
71264 'в' => 'В',
71265 'г' => 'Г',
71266 'д' => 'Д',
71267 'е' => 'Е',
71268 'ж' => 'Ж',
71269 'з' => 'З',
71270 'и' => 'И',
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 'a' => 'A',
71959 'b' => 'B',
71960 'c' => 'C',
71961 'd' => 'D',
71962 'e' => 'E',
71963 'f' => 'F',
71964 'g' => 'G',
71965 'h' => 'H',
71966 'i' => 'I',
71967 'j' => 'J',
71968 'k' => 'K',
71969 'l' => 'L',
71970 'm' => 'M',
71971 'n' => 'N',
71972 'o' => 'O',
71973 'p' => 'P',
71974 'q' => 'Q',
71975 'r' => 'R',
71976 's' => 'S',
71977 't' => 'T',
71978 'u' => 'U',
71979 'v' => 'V',
71980 'w' => 'W',
71981 'x' => 'X',
71982 'y' => 'Y',
71983 'z' => 'Z',
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 $result =& $data;
72059 unset($data);
72060
72061 return $result;
72062 <?php
72063
72064
72065
72066
72067
72068
72069
72070
72071
72072
72073 use Symfony\Polyfill\Mbstring as p;
72074
72075 if (!function_exists('mb_strlen')) {
72076 define('MB_CASE_UPPER', 0);
72077 define('MB_CASE_LOWER', 1);
72078 define('MB_CASE_TITLE', 2);
72079
72080 function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
72081 function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
72082 function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
72083 function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
72084 function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
72085 function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
72086 function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
72087 function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
72088 function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
72089 function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
72090 function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
72091 function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
72092 function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
72093 function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
72094 function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
72095 function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
72096 function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
72097 function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
72098 function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
72099 function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
72100 function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
72101 function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
72102 function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
72103 function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
72104 function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
72105 function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
72106 function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
72107 function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
72108 function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
72109 function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
72110 function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
72111 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); }
72112 }
72113 if (!function_exists('mb_chr')) {
72114 function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
72115 function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
72116 function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
72117 }
72118 <?php
72119
72120
72121
72122
72123
72124
72125
72126
72127
72128
72129 namespace Symfony\Component\Process\Exception;
72130
72131
72132
72133
72134
72135
72136 interface ExceptionInterface
72137 {
72138 }
72139 <?php
72140
72141
72142
72143
72144
72145
72146
72147
72148
72149
72150 namespace Symfony\Component\Process\Exception;
72151
72152
72153
72154
72155
72156
72157 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
72158 {
72159 }
72160 <?php
72161
72162
72163
72164
72165
72166
72167
72168
72169
72170
72171 namespace Symfony\Component\Process\Exception;
72172
72173
72174
72175
72176
72177
72178 class LogicException extends \LogicException implements ExceptionInterface
72179 {
72180 }
72181 <?php
72182
72183
72184
72185
72186
72187
72188
72189
72190
72191
72192 namespace Symfony\Component\Process\Exception;
72193
72194 use Symfony\Component\Process\Process;
72195
72196
72197
72198
72199
72200
72201 class ProcessFailedException extends RuntimeException
72202 {
72203 private $process;
72204
72205 public function __construct(Process $process)
72206 {
72207 if ($process->isSuccessful()) {
72208 throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
72209 }
72210
72211 $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
72212 $process->getCommandLine(),
72213 $process->getExitCode(),
72214 $process->getExitCodeText(),
72215 $process->getWorkingDirectory()
72216 );
72217
72218 if (!$process->isOutputDisabled()) {
72219 $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
72220 $process->getOutput(),
72221 $process->getErrorOutput()
72222 );
72223 }
72224
72225 parent::__construct($error);
72226
72227 $this->process = $process;
72228 }
72229
72230 public function getProcess()
72231 {
72232 return $this->process;
72233 }
72234 }
72235 <?php
72236
72237
72238
72239
72240
72241
72242
72243
72244
72245
72246 namespace Symfony\Component\Process\Exception;
72247
72248 use Symfony\Component\Process\Process;
72249
72250
72251
72252
72253
72254
72255 class ProcessTimedOutException extends RuntimeException
72256 {
72257 const TYPE_GENERAL = 1;
72258 const TYPE_IDLE = 2;
72259
72260 private $process;
72261 private $timeoutType;
72262
72263 public function __construct(Process $process, $timeoutType)
72264 {
72265 $this->process = $process;
72266 $this->timeoutType = $timeoutType;
72267
72268 parent::__construct(sprintf(
72269 'The process "%s" exceeded the timeout of %s seconds.',
72270 $process->getCommandLine(),
72271 $this->getExceededTimeout()
72272 ));
72273 }
72274
72275 public function getProcess()
72276 {
72277 return $this->process;
72278 }
72279
72280 public function isGeneralTimeout()
72281 {
72282 return self::TYPE_GENERAL === $this->timeoutType;
72283 }
72284
72285 public function isIdleTimeout()
72286 {
72287 return self::TYPE_IDLE === $this->timeoutType;
72288 }
72289
72290 public function getExceededTimeout()
72291 {
72292 switch ($this->timeoutType) {
72293 case self::TYPE_GENERAL:
72294 return $this->process->getTimeout();
72295
72296 case self::TYPE_IDLE:
72297 return $this->process->getIdleTimeout();
72298
72299 default:
72300 throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
72301 }
72302 }
72303 }
72304 <?php
72305
72306
72307
72308
72309
72310
72311
72312
72313
72314
72315 namespace Symfony\Component\Process\Exception;
72316
72317
72318
72319
72320
72321
72322 class RuntimeException extends \RuntimeException implements ExceptionInterface
72323 {
72324 }
72325 <?php
72326
72327
72328
72329
72330
72331
72332
72333
72334
72335
72336 namespace Symfony\Component\Process;
72337
72338
72339
72340
72341
72342
72343
72344 class ExecutableFinder
72345 {
72346 private $suffixes = array('.exe', '.bat', '.cmd', '.com');
72347
72348
72349
72350
72351 public function setSuffixes(array $suffixes)
72352 {
72353 $this->suffixes = $suffixes;
72354 }
72355
72356
72357
72358
72359
72360
72361 public function addSuffix($suffix)
72362 {
72363 $this->suffixes[] = $suffix;
72364 }
72365
72366
72367
72368
72369
72370
72371
72372
72373
72374
72375 public function find($name, $default = null, array $extraDirs = array())
72376 {
72377 if (ini_get('open_basedir')) {
72378 $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
72379 $dirs = array();
72380 foreach ($searchPath as $path) {
72381
72382  if (@is_dir($path)) {
72383 $dirs[] = $path;
72384 } else {
72385 if (basename($path) == $name && @is_executable($path)) {
72386 return $path;
72387 }
72388 }
72389 }
72390 } else {
72391 $dirs = array_merge(
72392 explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
72393 $extraDirs
72394 );
72395 }
72396
72397 $suffixes = array('');
72398 if ('\\' === DIRECTORY_SEPARATOR) {
72399 $pathExt = getenv('PATHEXT');
72400 $suffixes = array_merge($suffixes, $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes);
72401 }
72402 foreach ($suffixes as $suffix) {
72403 foreach ($dirs as $dir) {
72404 if (@is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) {
72405 return $file;
72406 }
72407 }
72408 }
72409
72410 return $default;
72411 }
72412 }
72413 Copyright (c) 2004-2017 Fabien Potencier
72414
72415 Permission is hereby granted, free of charge, to any person obtaining a copy
72416 of this software and associated documentation files (the "Software"), to deal
72417 in the Software without restriction, including without limitation the rights
72418 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
72419 copies of the Software, and to permit persons to whom the Software is furnished
72420 to do so, subject to the following conditions:
72421
72422 The above copyright notice and this permission notice shall be included in all
72423 copies or substantial portions of the Software.
72424
72425 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
72426 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72427 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
72428 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
72429 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
72430 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
72431 THE SOFTWARE.
72432 <?php
72433
72434
72435
72436
72437
72438
72439
72440
72441
72442
72443 namespace Symfony\Component\Process;
72444
72445
72446
72447
72448
72449
72450
72451 class PhpExecutableFinder
72452 {
72453 private $executableFinder;
72454
72455 public function __construct()
72456 {
72457 $this->executableFinder = new ExecutableFinder();
72458 }
72459
72460
72461
72462
72463
72464
72465
72466
72467 public function find($includeArgs = true)
72468 {
72469 $args = $this->findArguments();
72470 $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
72471
72472
72473  if (defined('HHVM_VERSION')) {
72474 return (getenv('PHP_BINARY') ?: PHP_BINARY).$args;
72475 }
72476
72477
72478  if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg')) && is_file(PHP_BINARY)) {
72479 return PHP_BINARY.$args;
72480 }
72481
72482 if ($php = getenv('PHP_PATH')) {
72483 if (!is_executable($php)) {
72484 return false;
72485 }
72486
72487 return $php;
72488 }
72489
72490 if ($php = getenv('PHP_PEAR_PHP_BIN')) {
72491 if (is_executable($php)) {
72492 return $php;
72493 }
72494 }
72495
72496 $dirs = array(PHP_BINDIR);
72497 if ('\\' === DIRECTORY_SEPARATOR) {
72498 $dirs[] = 'C:\xampp\php\\';
72499 }
72500
72501 return $this->executableFinder->find('php', false, $dirs);
72502 }
72503
72504
72505
72506
72507
72508
72509 public function findArguments()
72510 {
72511 $arguments = array();
72512
72513 if (defined('HHVM_VERSION')) {
72514 $arguments[] = '--php';
72515 } elseif ('phpdbg' === PHP_SAPI) {
72516 $arguments[] = '-qrr';
72517 }
72518
72519 return $arguments;
72520 }
72521 }
72522 <?php
72523
72524
72525
72526
72527
72528
72529
72530
72531
72532
72533 namespace Symfony\Component\Process;
72534
72535 use Symfony\Component\Process\Exception\RuntimeException;
72536
72537
72538
72539
72540
72541
72542
72543
72544
72545
72546 class PhpProcess extends Process
72547 {
72548
72549
72550
72551
72552
72553
72554
72555 public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = array())
72556 {
72557 $executableFinder = new PhpExecutableFinder();
72558 if (false === $php = $executableFinder->find()) {
72559 $php = null;
72560 }
72561 if ('phpdbg' === PHP_SAPI) {
72562 $file = tempnam(sys_get_temp_dir(), 'dbg');
72563 file_put_contents($file, $script);
72564 register_shutdown_function('unlink', $file);
72565 $php .= ' '.ProcessUtils::escapeArgument($file);
72566 $script = null;
72567 }
72568 if ('\\' !== DIRECTORY_SEPARATOR && null !== $php) {
72569
72570  
72571  
72572  $php = 'exec '.$php;
72573 }
72574
72575 parent::__construct($php, $cwd, $env, $script, $timeout, $options);
72576 }
72577
72578
72579
72580
72581 public function setPhpBinary($php)
72582 {
72583 $this->setCommandLine($php);
72584 }
72585
72586
72587
72588
72589 public function start($callback = null)
72590 {
72591 if (null === $this->getCommandLine()) {
72592 throw new RuntimeException('Unable to find the PHP executable.');
72593 }
72594
72595 parent::start($callback);
72596 }
72597 }
72598 <?php
72599
72600
72601
72602
72603
72604
72605
72606
72607
72608
72609 namespace Symfony\Component\Process\Pipes;
72610
72611
72612
72613
72614
72615
72616 abstract class AbstractPipes implements PipesInterface
72617 {
72618 public $pipes = array();
72619
72620 private $inputBuffer = '';
72621 private $input;
72622 private $blocked = true;
72623
72624
72625
72626
72627 public function __construct($input)
72628 {
72629 if (is_resource($input)) {
72630 $this->input = $input;
72631 } elseif (is_string($input)) {
72632 $this->inputBuffer = $input;
72633 } else {
72634 $this->inputBuffer = (string) $input;
72635 }
72636 }
72637
72638
72639
72640
72641 public function close()
72642 {
72643 foreach ($this->pipes as $pipe) {
72644 fclose($pipe);
72645 }
72646 $this->pipes = array();
72647 }
72648
72649
72650
72651
72652
72653
72654 protected function hasSystemCallBeenInterrupted()
72655 {
72656 $lastError = error_get_last();
72657
72658
72659  return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
72660 }
72661
72662
72663
72664
72665 protected function unblock()
72666 {
72667 if (!$this->blocked) {
72668 return;
72669 }
72670
72671 foreach ($this->pipes as $pipe) {
72672 stream_set_blocking($pipe, 0);
72673 }
72674 if (null !== $this->input) {
72675 stream_set_blocking($this->input, 0);
72676 }
72677
72678 $this->blocked = false;
72679 }
72680
72681
72682
72683
72684 protected function write()
72685 {
72686 if (!isset($this->pipes[0])) {
72687 return;
72688 }
72689 $input = $this->input;
72690 $r = $e = array();
72691 $w = array($this->pipes[0]);
72692
72693
72694  if (false === $n = @stream_select($r, $w, $e, 0, 0)) {
72695 return;
72696 }
72697
72698 foreach ($w as $stdin) {
72699 if (isset($this->inputBuffer[0])) {
72700 $written = fwrite($stdin, $this->inputBuffer);
72701 $this->inputBuffer = substr($this->inputBuffer, $written);
72702 if (isset($this->inputBuffer[0])) {
72703 return array($this->pipes[0]);
72704 }
72705 }
72706
72707 if ($input) {
72708 for (;;) {
72709 $data = fread($input, self::CHUNK_SIZE);
72710 if (!isset($data[0])) {
72711 break;
72712 }
72713 $written = fwrite($stdin, $data);
72714 $data = substr($data, $written);
72715 if (isset($data[0])) {
72716 $this->inputBuffer = $data;
72717
72718 return array($this->pipes[0]);
72719 }
72720 }
72721 if (feof($input)) {
72722
72723  
72724  $this->input = null;
72725 }
72726 }
72727 }
72728
72729
72730  if (null === $this->input && !isset($this->inputBuffer[0])) {
72731 fclose($this->pipes[0]);
72732 unset($this->pipes[0]);
72733 } elseif (!$w) {
72734 return array($this->pipes[0]);
72735 }
72736 }
72737 }
72738 <?php
72739
72740
72741
72742
72743
72744
72745
72746
72747
72748
72749 namespace Symfony\Component\Process\Pipes;
72750
72751
72752
72753
72754
72755
72756
72757
72758 interface PipesInterface
72759 {
72760 const CHUNK_SIZE = 16384;
72761
72762
72763
72764
72765
72766
72767 public function getDescriptors();
72768
72769
72770
72771
72772
72773
72774 public function getFiles();
72775
72776
72777
72778
72779
72780
72781
72782
72783
72784 public function readAndWrite($blocking, $close = false);
72785
72786
72787
72788
72789
72790
72791 public function areOpen();
72792
72793
72794
72795
72796 public function close();
72797 }
72798 <?php
72799
72800
72801
72802
72803
72804
72805
72806
72807
72808
72809 namespace Symfony\Component\Process\Pipes;
72810
72811 use Symfony\Component\Process\Process;
72812
72813
72814
72815
72816
72817
72818
72819
72820 class UnixPipes extends AbstractPipes
72821 {
72822 private $ttyMode;
72823 private $ptyMode;
72824 private $disableOutput;
72825
72826 public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
72827 {
72828 $this->ttyMode = (bool) $ttyMode;
72829 $this->ptyMode = (bool) $ptyMode;
72830 $this->disableOutput = (bool) $disableOutput;
72831
72832 parent::__construct($input);
72833 }
72834
72835 public function __destruct()
72836 {
72837 $this->close();
72838 }
72839
72840
72841
72842
72843 public function getDescriptors()
72844 {
72845 if ($this->disableOutput) {
72846 $nullstream = fopen('/dev/null', 'c');
72847
72848 return array(
72849 array('pipe', 'r'),
72850 $nullstream,
72851 $nullstream,
72852 );
72853 }
72854
72855 if ($this->ttyMode) {
72856 return array(
72857 array('file', '/dev/tty', 'r'),
72858 array('file', '/dev/tty', 'w'),
72859 array('file', '/dev/tty', 'w'),
72860 );
72861 }
72862
72863 if ($this->ptyMode && Process::isPtySupported()) {
72864 return array(
72865 array('pty'),
72866 array('pty'),
72867 array('pty'),
72868 );
72869 }
72870
72871 return array(
72872 array('pipe', 'r'),
72873 array('pipe', 'w'), 
72874  array('pipe', 'w'), 
72875  );
72876 }
72877
72878
72879
72880
72881 public function getFiles()
72882 {
72883 return array();
72884 }
72885
72886
72887
72888
72889 public function readAndWrite($blocking, $close = false)
72890 {
72891 $this->unblock();
72892 $w = $this->write();
72893
72894 $read = $e = array();
72895 $r = $this->pipes;
72896 unset($r[0]);
72897
72898
72899  if (($r || $w) && false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
72900
72901  
72902  if (!$this->hasSystemCallBeenInterrupted()) {
72903 $this->pipes = array();
72904 }
72905
72906 return $read;
72907 }
72908
72909 foreach ($r as $pipe) {
72910
72911  
72912  $read[$type = array_search($pipe, $this->pipes, true)] = '';
72913
72914 do {
72915 $data = fread($pipe, self::CHUNK_SIZE);
72916 $read[$type] .= $data;
72917 } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
72918
72919 if (!isset($read[$type][0])) {
72920 unset($read[$type]);
72921 }
72922
72923 if ($close && feof($pipe)) {
72924 fclose($pipe);
72925 unset($this->pipes[$type]);
72926 }
72927 }
72928
72929 return $read;
72930 }
72931
72932
72933
72934
72935 public function areOpen()
72936 {
72937 return (bool) $this->pipes;
72938 }
72939
72940
72941
72942
72943
72944
72945
72946
72947
72948 public static function create(Process $process, $input)
72949 {
72950 return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
72951 }
72952 }
72953 <?php
72954
72955
72956
72957
72958
72959
72960
72961
72962
72963
72964 namespace Symfony\Component\Process\Pipes;
72965
72966 use Symfony\Component\Process\Process;
72967 use Symfony\Component\Process\Exception\RuntimeException;
72968
72969
72970
72971
72972
72973
72974
72975
72976
72977
72978
72979 class WindowsPipes extends AbstractPipes
72980 {
72981 private $files = array();
72982 private $fileHandles = array();
72983 private $readBytes = array(
72984 Process::STDOUT => 0,
72985 Process::STDERR => 0,
72986 );
72987 private $disableOutput;
72988
72989 public function __construct($disableOutput, $input)
72990 {
72991 $this->disableOutput = (bool) $disableOutput;
72992
72993 if (!$this->disableOutput) {
72994
72995  
72996  
72997  
72998  $pipes = array(
72999 Process::STDOUT => Process::OUT,
73000 Process::STDERR => Process::ERR,
73001 );
73002 $tmpCheck = false;
73003 $tmpDir = sys_get_temp_dir();
73004 $lastError = 'unknown reason';
73005 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
73006 for ($i = 0;; ++$i) {
73007 foreach ($pipes as $pipe => $name) {
73008 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
73009 if (file_exists($file) && !unlink($file)) {
73010 continue 2;
73011 }
73012 $h = fopen($file, 'xb');
73013 if (!$h) {
73014 $error = $lastError;
73015 if ($tmpCheck || $tmpCheck = unlink(tempnam(false, 'sf_check_'))) {
73016 continue;
73017 }
73018 restore_error_handler();
73019 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error));
73020 }
73021 if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) {
73022 continue 2;
73023 }
73024 if (isset($this->files[$pipe])) {
73025 unlink($this->files[$pipe]);
73026 }
73027 $this->files[$pipe] = $file;
73028 }
73029 break;
73030 }
73031 restore_error_handler();
73032 }
73033
73034 parent::__construct($input);
73035 }
73036
73037 public function __destruct()
73038 {
73039 $this->close();
73040 $this->removeFiles();
73041 }
73042
73043
73044
73045
73046 public function getDescriptors()
73047 {
73048 if ($this->disableOutput) {
73049 $nullstream = fopen('NUL', 'c');
73050
73051 return array(
73052 array('pipe', 'r'),
73053 $nullstream,
73054 $nullstream,
73055 );
73056 }
73057
73058
73059  
73060  
73061  return array(
73062 array('pipe', 'r'),
73063 array('file', 'NUL', 'w'),
73064 array('file', 'NUL', 'w'),
73065 );
73066 }
73067
73068
73069
73070
73071 public function getFiles()
73072 {
73073 return $this->files;
73074 }
73075
73076
73077
73078
73079 public function readAndWrite($blocking, $close = false)
73080 {
73081 $this->unblock();
73082 $w = $this->write();
73083 $read = $r = $e = array();
73084
73085 if ($blocking) {
73086 if ($w) {
73087 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
73088 } elseif ($this->fileHandles) {
73089 usleep(Process::TIMEOUT_PRECISION * 1E6);
73090 }
73091 }
73092 foreach ($this->fileHandles as $type => $fileHandle) {
73093 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
73094
73095 if (isset($data[0])) {
73096 $this->readBytes[$type] += strlen($data);
73097 $read[$type] = $data;
73098 }
73099 if ($close) {
73100 fclose($fileHandle);
73101 unset($this->fileHandles[$type]);
73102 }
73103 }
73104
73105 return $read;
73106 }
73107
73108
73109
73110
73111 public function areOpen()
73112 {
73113 return $this->pipes && $this->fileHandles;
73114 }
73115
73116
73117
73118
73119 public function close()
73120 {
73121 parent::close();
73122 foreach ($this->fileHandles as $handle) {
73123 fclose($handle);
73124 }
73125 $this->fileHandles = array();
73126 }
73127
73128
73129
73130
73131
73132
73133
73134
73135
73136 public static function create(Process $process, $input)
73137 {
73138 return new static($process->isOutputDisabled(), $input);
73139 }
73140
73141
73142
73143
73144 private function removeFiles()
73145 {
73146 foreach ($this->files as $filename) {
73147 if (file_exists($filename)) {
73148 @unlink($filename);
73149 }
73150 }
73151 $this->files = array();
73152 }
73153 }
73154 <?php
73155
73156
73157
73158
73159
73160
73161
73162
73163
73164
73165 namespace Symfony\Component\Process;
73166
73167 use Symfony\Component\Process\Exception\InvalidArgumentException;
73168 use Symfony\Component\Process\Exception\LogicException;
73169 use Symfony\Component\Process\Exception\ProcessFailedException;
73170 use Symfony\Component\Process\Exception\ProcessTimedOutException;
73171 use Symfony\Component\Process\Exception\RuntimeException;
73172 use Symfony\Component\Process\Pipes\PipesInterface;
73173 use Symfony\Component\Process\Pipes\UnixPipes;
73174 use Symfony\Component\Process\Pipes\WindowsPipes;
73175
73176
73177
73178
73179
73180
73181
73182
73183 class Process
73184 {
73185 const ERR = 'err';
73186 const OUT = 'out';
73187
73188 const STATUS_READY = 'ready';
73189 const STATUS_STARTED = 'started';
73190 const STATUS_TERMINATED = 'terminated';
73191
73192 const STDIN = 0;
73193 const STDOUT = 1;
73194 const STDERR = 2;
73195
73196
73197  const TIMEOUT_PRECISION = 0.2;
73198
73199 private $callback;
73200 private $commandline;
73201 private $cwd;
73202 private $env;
73203 private $input;
73204 private $starttime;
73205 private $lastOutputTime;
73206 private $timeout;
73207 private $idleTimeout;
73208 private $options;
73209 private $exitcode;
73210 private $fallbackStatus = array();
73211 private $processInformation;
73212 private $outputDisabled = false;
73213 private $stdout;
73214 private $stderr;
73215 private $enhanceWindowsCompatibility = true;
73216 private $enhanceSigchildCompatibility;
73217 private $process;
73218 private $status = self::STATUS_READY;
73219 private $incrementalOutputOffset = 0;
73220 private $incrementalErrorOutputOffset = 0;
73221 private $tty;
73222 private $pty;
73223
73224 private $useFileHandles = false;
73225
73226 private $processPipes;
73227
73228 private $latestSignal;
73229
73230 private static $sigchild;
73231
73232
73233
73234
73235
73236
73237 public static $exitCodes = array(
73238 0 => 'OK',
73239 1 => 'General error',
73240 2 => 'Misuse of shell builtins',
73241
73242 126 => 'Invoked command cannot execute',
73243 127 => 'Command not found',
73244 128 => 'Invalid exit argument',
73245
73246
73247  129 => 'Hangup',
73248 130 => 'Interrupt',
73249 131 => 'Quit and dump core',
73250 132 => 'Illegal instruction',
73251 133 => 'Trace/breakpoint trap',
73252 134 => 'Process aborted',
73253 135 => 'Bus error: "access to undefined portion of memory object"',
73254 136 => 'Floating point exception: "erroneous arithmetic operation"',
73255 137 => 'Kill (terminate immediately)',
73256 138 => 'User-defined 1',
73257 139 => 'Segmentation violation',
73258 140 => 'User-defined 2',
73259 141 => 'Write to pipe with no one reading',
73260 142 => 'Signal raised by alarm',
73261 143 => 'Termination (request to terminate)',
73262
73263  145 => 'Child process terminated, stopped (or continued*)',
73264 146 => 'Continue if stopped',
73265 147 => 'Stop executing temporarily',
73266 148 => 'Terminal stop signal',
73267 149 => 'Background process attempting to read from tty ("in")',
73268 150 => 'Background process attempting to write to tty ("out")',
73269 151 => 'Urgent data available on socket',
73270 152 => 'CPU time limit exceeded',
73271 153 => 'File size limit exceeded',
73272 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
73273 155 => 'Profiling timer expired',
73274
73275  157 => 'Pollable event',
73276
73277  159 => 'Bad syscall',
73278 );
73279
73280
73281
73282
73283
73284
73285
73286
73287
73288
73289
73290 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
73291 {
73292 if (!function_exists('proc_open')) {
73293 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
73294 }
73295
73296 $this->commandline = $commandline;
73297 $this->cwd = $cwd;
73298
73299
73300  
73301  
73302  
73303  if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || '\\' === DIRECTORY_SEPARATOR)) {
73304 $this->cwd = getcwd();
73305 }
73306 if (null !== $env) {
73307 $this->setEnv($env);
73308 }
73309
73310 $this->setInput($input);
73311 $this->setTimeout($timeout);
73312 $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR;
73313 $this->pty = false;
73314 $this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
73315 $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
73316 }
73317
73318 public function __destruct()
73319 {
73320 $this->stop(0);
73321 }
73322
73323 public function __clone()
73324 {
73325 $this->resetProcessData();
73326 }
73327
73328
73329
73330
73331
73332
73333
73334
73335
73336
73337
73338
73339
73340
73341
73342
73343
73344
73345
73346
73347 public function run($callback = null)
73348 {
73349 $this->start($callback);
73350
73351 return $this->wait();
73352 }
73353
73354
73355
73356
73357
73358
73359
73360
73361
73362
73363
73364
73365
73366
73367 public function mustRun($callback = null)
73368 {
73369 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73370 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
73371 }
73372
73373 if (0 !== $this->run($callback)) {
73374 throw new ProcessFailedException($this);
73375 }
73376
73377 return $this;
73378 }
73379
73380
73381
73382
73383
73384
73385
73386
73387
73388
73389
73390
73391
73392
73393
73394
73395
73396
73397
73398
73399 public function start($callback = null)
73400 {
73401 if ($this->isRunning()) {
73402 throw new RuntimeException('Process is already running');
73403 }
73404 if ($this->outputDisabled && null !== $callback) {
73405 throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
73406 }
73407
73408 $this->resetProcessData();
73409 $this->starttime = $this->lastOutputTime = microtime(true);
73410 $this->callback = $this->buildCallback($callback);
73411 $descriptors = $this->getDescriptors();
73412
73413 $commandline = $this->commandline;
73414
73415 if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
73416 $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')';
73417 foreach ($this->processPipes->getFiles() as $offset => $filename) {
73418 $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
73419 }
73420 $commandline .= '"';
73421
73422 if (!isset($this->options['bypass_shell'])) {
73423 $this->options['bypass_shell'] = true;
73424 }
73425 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73426
73427  $descriptors[3] = array('pipe', 'w');
73428
73429
73430  $commandline = '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
73431 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
73432
73433
73434  
73435  $ptsWorkaround = fopen(__FILE__, 'r');
73436 }
73437
73438 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
73439
73440 if (!is_resource($this->process)) {
73441 throw new RuntimeException('Unable to launch a new process.');
73442 }
73443 $this->status = self::STATUS_STARTED;
73444
73445 if (isset($descriptors[3])) {
73446 $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
73447 }
73448
73449 if ($this->tty) {
73450 return;
73451 }
73452
73453 $this->updateStatus(false);
73454 $this->checkTimeout();
73455 }
73456
73457
73458
73459
73460
73461
73462
73463
73464
73465
73466
73467
73468
73469
73470
73471
73472 public function restart($callback = null)
73473 {
73474 if ($this->isRunning()) {
73475 throw new RuntimeException('Process is already running');
73476 }
73477
73478 $process = clone $this;
73479 $process->start($callback);
73480
73481 return $process;
73482 }
73483
73484
73485
73486
73487
73488
73489
73490
73491
73492
73493
73494
73495
73496
73497
73498
73499 public function wait($callback = null)
73500 {
73501 $this->requireProcessIsStarted(__FUNCTION__);
73502
73503 $this->updateStatus(false);
73504 if (null !== $callback) {
73505 $this->callback = $this->buildCallback($callback);
73506 }
73507
73508 do {
73509 $this->checkTimeout();
73510 $running = '\\' === DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
73511 $this->readPipes($running, '\\' !== DIRECTORY_SEPARATOR || !$running);
73512 } while ($running);
73513
73514 while ($this->isRunning()) {
73515 usleep(1000);
73516 }
73517
73518 if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
73519 throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
73520 }
73521
73522 return $this->exitcode;
73523 }
73524
73525
73526
73527
73528
73529
73530 public function getPid()
73531 {
73532 return $this->isRunning() ? $this->processInformation['pid'] : null;
73533 }
73534
73535
73536
73537
73538
73539
73540
73541
73542
73543
73544
73545
73546 public function signal($signal)
73547 {
73548 $this->doSignal($signal, true);
73549
73550 return $this;
73551 }
73552
73553
73554
73555
73556
73557
73558
73559
73560
73561 public function disableOutput()
73562 {
73563 if ($this->isRunning()) {
73564 throw new RuntimeException('Disabling output while the process is running is not possible.');
73565 }
73566 if (null !== $this->idleTimeout) {
73567 throw new LogicException('Output can not be disabled while an idle timeout is set.');
73568 }
73569
73570 $this->outputDisabled = true;
73571
73572 return $this;
73573 }
73574
73575
73576
73577
73578
73579
73580
73581
73582 public function enableOutput()
73583 {
73584 if ($this->isRunning()) {
73585 throw new RuntimeException('Enabling output while the process is running is not possible.');
73586 }
73587
73588 $this->outputDisabled = false;
73589
73590 return $this;
73591 }
73592
73593
73594
73595
73596
73597
73598 public function isOutputDisabled()
73599 {
73600 return $this->outputDisabled;
73601 }
73602
73603
73604
73605
73606
73607
73608
73609
73610
73611 public function getOutput()
73612 {
73613 $this->readPipesForOutput(__FUNCTION__);
73614
73615 if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
73616 return '';
73617 }
73618
73619 return $ret;
73620 }
73621
73622
73623
73624
73625
73626
73627
73628
73629
73630
73631
73632
73633 public function getIncrementalOutput()
73634 {
73635 $this->readPipesForOutput(__FUNCTION__);
73636
73637 $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
73638 $this->incrementalOutputOffset = ftell($this->stdout);
73639
73640 if (false === $latest) {
73641 return '';
73642 }
73643
73644 return $latest;
73645 }
73646
73647
73648
73649
73650
73651
73652 public function clearOutput()
73653 {
73654 ftruncate($this->stdout, 0);
73655 fseek($this->stdout, 0);
73656 $this->incrementalOutputOffset = 0;
73657
73658 return $this;
73659 }
73660
73661
73662
73663
73664
73665
73666
73667
73668
73669 public function getErrorOutput()
73670 {
73671 $this->readPipesForOutput(__FUNCTION__);
73672
73673 if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
73674 return '';
73675 }
73676
73677 return $ret;
73678 }
73679
73680
73681
73682
73683
73684
73685
73686
73687
73688
73689
73690
73691
73692 public function getIncrementalErrorOutput()
73693 {
73694 $this->readPipesForOutput(__FUNCTION__);
73695
73696 $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
73697 $this->incrementalErrorOutputOffset = ftell($this->stderr);
73698
73699 if (false === $latest) {
73700 return '';
73701 }
73702
73703 return $latest;
73704 }
73705
73706
73707
73708
73709
73710
73711 public function clearErrorOutput()
73712 {
73713 ftruncate($this->stderr, 0);
73714 fseek($this->stderr, 0);
73715 $this->incrementalErrorOutputOffset = 0;
73716
73717 return $this;
73718 }
73719
73720
73721
73722
73723
73724
73725
73726
73727 public function getExitCode()
73728 {
73729 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73730 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
73731 }
73732
73733 $this->updateStatus(false);
73734
73735 return $this->exitcode;
73736 }
73737
73738
73739
73740
73741
73742
73743
73744
73745
73746
73747
73748
73749 public function getExitCodeText()
73750 {
73751 if (null === $exitcode = $this->getExitCode()) {
73752 return;
73753 }
73754
73755 return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
73756 }
73757
73758
73759
73760
73761
73762
73763 public function isSuccessful()
73764 {
73765 return 0 === $this->getExitCode();
73766 }
73767
73768
73769
73770
73771
73772
73773
73774
73775
73776
73777
73778 public function hasBeenSignaled()
73779 {
73780 $this->requireProcessIsTerminated(__FUNCTION__);
73781
73782 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73783 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
73784 }
73785
73786 return $this->processInformation['signaled'];
73787 }
73788
73789
73790
73791
73792
73793
73794
73795
73796
73797
73798
73799 public function getTermSignal()
73800 {
73801 $this->requireProcessIsTerminated(__FUNCTION__);
73802
73803 if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) {
73804 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
73805 }
73806
73807 return $this->processInformation['termsig'];
73808 }
73809
73810
73811
73812
73813
73814
73815
73816
73817
73818
73819 public function hasBeenStopped()
73820 {
73821 $this->requireProcessIsTerminated(__FUNCTION__);
73822
73823 return $this->processInformation['stopped'];
73824 }
73825
73826
73827
73828
73829
73830
73831
73832
73833
73834
73835 public function getStopSignal()
73836 {
73837 $this->requireProcessIsTerminated(__FUNCTION__);
73838
73839 return $this->processInformation['stopsig'];
73840 }
73841
73842
73843
73844
73845
73846
73847 public function isRunning()
73848 {
73849 if (self::STATUS_STARTED !== $this->status) {
73850 return false;
73851 }
73852
73853 $this->updateStatus(false);
73854
73855 return $this->processInformation['running'];
73856 }
73857
73858
73859
73860
73861
73862
73863 public function isStarted()
73864 {
73865 return self::STATUS_READY != $this->status;
73866 }
73867
73868
73869
73870
73871
73872
73873 public function isTerminated()
73874 {
73875 $this->updateStatus(false);
73876
73877 return self::STATUS_TERMINATED == $this->status;
73878 }
73879
73880
73881
73882
73883
73884
73885
73886
73887 public function getStatus()
73888 {
73889 $this->updateStatus(false);
73890
73891 return $this->status;
73892 }
73893
73894
73895
73896
73897
73898
73899
73900
73901
73902 public function stop($timeout = 10, $signal = null)
73903 {
73904 $timeoutMicro = microtime(true) + $timeout;
73905 if ($this->isRunning()) {
73906
73907  $this->doSignal(15, false);
73908 do {
73909 usleep(1000);
73910 } while ($this->isRunning() && microtime(true) < $timeoutMicro);
73911
73912 if ($this->isRunning()) {
73913
73914  
73915  $this->doSignal($signal ?: 9, false);
73916 }
73917 }
73918
73919 if ($this->isRunning()) {
73920 if (isset($this->fallbackStatus['pid'])) {
73921 unset($this->fallbackStatus['pid']);
73922
73923 return $this->stop(0, $signal);
73924 }
73925 $this->close();
73926 }
73927
73928 return $this->exitcode;
73929 }
73930
73931
73932
73933
73934
73935
73936
73937
73938 public function addOutput($line)
73939 {
73940 $this->lastOutputTime = microtime(true);
73941
73942 fseek($this->stdout, 0, SEEK_END);
73943 fwrite($this->stdout, $line);
73944 fseek($this->stdout, $this->incrementalOutputOffset);
73945 }
73946
73947
73948
73949
73950
73951
73952
73953
73954 public function addErrorOutput($line)
73955 {
73956 $this->lastOutputTime = microtime(true);
73957
73958 fseek($this->stderr, 0, SEEK_END);
73959 fwrite($this->stderr, $line);
73960 fseek($this->stderr, $this->incrementalErrorOutputOffset);
73961 }
73962
73963
73964
73965
73966
73967
73968 public function getCommandLine()
73969 {
73970 return $this->commandline;
73971 }
73972
73973
73974
73975
73976
73977
73978
73979
73980 public function setCommandLine($commandline)
73981 {
73982 $this->commandline = $commandline;
73983
73984 return $this;
73985 }
73986
73987
73988
73989
73990
73991
73992 public function getTimeout()
73993 {
73994 return $this->timeout;
73995 }
73996
73997
73998
73999
74000
74001
74002 public function getIdleTimeout()
74003 {
74004 return $this->idleTimeout;
74005 }
74006
74007
74008
74009
74010
74011
74012
74013
74014
74015
74016
74017
74018 public function setTimeout($timeout)
74019 {
74020 $this->timeout = $this->validateTimeout($timeout);
74021
74022 return $this;
74023 }
74024
74025
74026
74027
74028
74029
74030
74031
74032
74033
74034
74035
74036
74037 public function setIdleTimeout($timeout)
74038 {
74039 if (null !== $timeout && $this->outputDisabled) {
74040 throw new LogicException('Idle timeout can not be set while the output is disabled.');
74041 }
74042
74043 $this->idleTimeout = $this->validateTimeout($timeout);
74044
74045 return $this;
74046 }
74047
74048
74049
74050
74051
74052
74053
74054
74055
74056
74057 public function setTty($tty)
74058 {
74059 if ('\\' === DIRECTORY_SEPARATOR && $tty) {
74060 throw new RuntimeException('TTY mode is not supported on Windows platform.');
74061 }
74062 if ($tty) {
74063 static $isTtySupported;
74064
74065 if (null === $isTtySupported) {
74066 $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);
74067 }
74068
74069 if (!$isTtySupported) {
74070 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
74071 }
74072 }
74073
74074 $this->tty = (bool) $tty;
74075
74076 return $this;
74077 }
74078
74079
74080
74081
74082
74083
74084 public function isTty()
74085 {
74086 return $this->tty;
74087 }
74088
74089
74090
74091
74092
74093
74094
74095
74096 public function setPty($bool)
74097 {
74098 $this->pty = (bool) $bool;
74099
74100 return $this;
74101 }
74102
74103
74104
74105
74106
74107
74108 public function isPty()
74109 {
74110 return $this->pty;
74111 }
74112
74113
74114
74115
74116
74117
74118 public function getWorkingDirectory()
74119 {
74120 if (null === $this->cwd) {
74121
74122  
74123  return getcwd() ?: null;
74124 }
74125
74126 return $this->cwd;
74127 }
74128
74129
74130
74131
74132
74133
74134
74135
74136 public function setWorkingDirectory($cwd)
74137 {
74138 $this->cwd = $cwd;
74139
74140 return $this;
74141 }
74142
74143
74144
74145
74146
74147
74148 public function getEnv()
74149 {
74150 return $this->env;
74151 }
74152
74153
74154
74155
74156
74157
74158
74159
74160
74161
74162
74163
74164
74165
74166 public function setEnv(array $env)
74167 {
74168
74169  $env = array_filter($env, function ($value) {
74170 return !is_array($value);
74171 });
74172
74173 $this->env = array();
74174 foreach ($env as $key => $value) {
74175 $this->env[$key] = (string) $value;
74176 }
74177
74178 return $this;
74179 }
74180
74181
74182
74183
74184
74185
74186
74187
74188
74189
74190 public function getStdin()
74191 {
74192 @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);
74193
74194 return $this->getInput();
74195 }
74196
74197
74198
74199
74200
74201
74202 public function getInput()
74203 {
74204 return $this->input;
74205 }
74206
74207
74208
74209
74210
74211
74212
74213
74214
74215
74216
74217
74218
74219
74220 public function setStdin($stdin)
74221 {
74222 @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);
74223
74224 return $this->setInput($stdin);
74225 }
74226
74227
74228
74229
74230
74231
74232
74233
74234
74235
74236
74237
74238
74239
74240 public function setInput($input)
74241 {
74242 if ($this->isRunning()) {
74243 throw new LogicException('Input can not be set while the process is running.');
74244 }
74245
74246 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
74247
74248 return $this;
74249 }
74250
74251
74252
74253
74254
74255
74256 public function getOptions()
74257 {
74258 return $this->options;
74259 }
74260
74261
74262
74263
74264
74265
74266
74267
74268 public function setOptions(array $options)
74269 {
74270 $this->options = $options;
74271
74272 return $this;
74273 }
74274
74275
74276
74277
74278
74279
74280
74281
74282 public function getEnhanceWindowsCompatibility()
74283 {
74284 return $this->enhanceWindowsCompatibility;
74285 }
74286
74287
74288
74289
74290
74291
74292
74293
74294 public function setEnhanceWindowsCompatibility($enhance)
74295 {
74296 $this->enhanceWindowsCompatibility = (bool) $enhance;
74297
74298 return $this;
74299 }
74300
74301
74302
74303
74304
74305
74306 public function getEnhanceSigchildCompatibility()
74307 {
74308 return $this->enhanceSigchildCompatibility;
74309 }
74310
74311
74312
74313
74314
74315
74316
74317
74318
74319
74320
74321
74322 public function setEnhanceSigchildCompatibility($enhance)
74323 {
74324 $this->enhanceSigchildCompatibility = (bool) $enhance;
74325
74326 return $this;
74327 }
74328
74329
74330
74331
74332
74333
74334
74335
74336
74337 public function checkTimeout()
74338 {
74339 if (self::STATUS_STARTED !== $this->status) {
74340 return;
74341 }
74342
74343 if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
74344 $this->stop(0);
74345
74346 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
74347 }
74348
74349 if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
74350 $this->stop(0);
74351
74352 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
74353 }
74354 }
74355
74356
74357
74358
74359
74360
74361 public static function isPtySupported()
74362 {
74363 static $result;
74364
74365 if (null !== $result) {
74366 return $result;
74367 }
74368
74369 if ('\\' === DIRECTORY_SEPARATOR) {
74370 return $result = false;
74371 }
74372
74373 return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes);
74374 }
74375
74376
74377
74378
74379
74380
74381 private function getDescriptors()
74382 {
74383 if ('\\' === DIRECTORY_SEPARATOR) {
74384 $this->processPipes = WindowsPipes::create($this, $this->input);
74385 } else {
74386 $this->processPipes = UnixPipes::create($this, $this->input);
74387 }
74388
74389 return $this->processPipes->getDescriptors();
74390 }
74391
74392
74393
74394
74395
74396
74397
74398
74399
74400
74401
74402 protected function buildCallback($callback)
74403 {
74404 $that = $this;
74405 $out = self::OUT;
74406 $callback = function ($type, $data) use ($that, $callback, $out) {
74407 if ($out == $type) {
74408 $that->addOutput($data);
74409 } else {
74410 $that->addErrorOutput($data);
74411 }
74412
74413 if (null !== $callback) {
74414 call_user_func($callback, $type, $data);
74415 }
74416 };
74417
74418 return $callback;
74419 }
74420
74421
74422
74423
74424
74425
74426 protected function updateStatus($blocking)
74427 {
74428 if (self::STATUS_STARTED !== $this->status) {
74429 return;
74430 }
74431
74432 $this->processInformation = proc_get_status($this->process);
74433 $running = $this->processInformation['running'];
74434
74435 $this->readPipes($running && $blocking, '\\' !== DIRECTORY_SEPARATOR || !$running);
74436
74437 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
74438 $this->processInformation = $this->fallbackStatus + $this->processInformation;
74439 }
74440
74441 if (!$running) {
74442 $this->close();
74443 }
74444 }
74445
74446
74447
74448
74449
74450
74451 protected function isSigchildEnabled()
74452 {
74453 if (null !== self::$sigchild) {
74454 return self::$sigchild;
74455 }
74456
74457 if (!function_exists('phpinfo') || defined('HHVM_VERSION')) {
74458 return self::$sigchild = false;
74459 }
74460
74461 ob_start();
74462 phpinfo(INFO_GENERAL);
74463
74464 return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
74465 }
74466
74467
74468
74469
74470
74471
74472
74473
74474 private function readPipesForOutput($caller)
74475 {
74476 if ($this->outputDisabled) {
74477 throw new LogicException('Output has been disabled.');
74478 }
74479
74480 $this->requireProcessIsStarted($caller);
74481
74482 $this->updateStatus(false);
74483 }
74484
74485
74486
74487
74488
74489
74490
74491
74492
74493
74494 private function validateTimeout($timeout)
74495 {
74496 $timeout = (float) $timeout;
74497
74498 if (0.0 === $timeout) {
74499 $timeout = null;
74500 } elseif ($timeout < 0) {
74501 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
74502 }
74503
74504 return $timeout;
74505 }
74506
74507
74508
74509
74510
74511
74512
74513 private function readPipes($blocking, $close)
74514 {
74515 $result = $this->processPipes->readAndWrite($blocking, $close);
74516
74517 $callback = $this->callback;
74518 foreach ($result as $type => $data) {
74519 if (3 !== $type) {
74520 $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);
74521 } elseif (!isset($this->fallbackStatus['signaled'])) {
74522 $this->fallbackStatus['exitcode'] = (int) $data;
74523 }
74524 }
74525 }
74526
74527
74528
74529
74530
74531
74532 private function close()
74533 {
74534 $this->processPipes->close();
74535 if (is_resource($this->process)) {
74536 proc_close($this->process);
74537 }
74538 $this->exitcode = $this->processInformation['exitcode'];
74539 $this->status = self::STATUS_TERMINATED;
74540
74541 if (-1 === $this->exitcode) {
74542 if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
74543
74544  $this->exitcode = 128 + $this->processInformation['termsig'];
74545 } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
74546 $this->processInformation['signaled'] = true;
74547 $this->processInformation['termsig'] = -1;
74548 }
74549 }
74550
74551
74552  
74553  
74554  $this->callback = null;
74555
74556 return $this->exitcode;
74557 }
74558
74559
74560
74561
74562 private function resetProcessData()
74563 {
74564 $this->starttime = null;
74565 $this->callback = null;
74566 $this->exitcode = null;
74567 $this->fallbackStatus = array();
74568 $this->processInformation = null;
74569 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
74570 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
74571 $this->process = null;
74572 $this->latestSignal = null;
74573 $this->status = self::STATUS_READY;
74574 $this->incrementalOutputOffset = 0;
74575 $this->incrementalErrorOutputOffset = 0;
74576 }
74577
74578
74579
74580
74581
74582
74583
74584
74585
74586
74587
74588
74589
74590 private function doSignal($signal, $throwException)
74591 {
74592 if (null === $pid = $this->getPid()) {
74593 if ($throwException) {
74594 throw new LogicException('Can not send signal on a non running process.');
74595 }
74596
74597 return false;
74598 }
74599
74600 if ('\\' === DIRECTORY_SEPARATOR) {
74601 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
74602 if ($exitCode && $this->isRunning()) {
74603 if ($throwException) {
74604 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
74605 }
74606
74607 return false;
74608 }
74609 } else {
74610 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
74611 $ok = @proc_terminate($this->process, $signal);
74612 } elseif (function_exists('posix_kill')) {
74613 $ok = @posix_kill($pid, $signal);
74614 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
74615 $ok = false === fgets($pipes[2]);
74616 }
74617 if (!$ok) {
74618 if ($throwException) {
74619 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
74620 }
74621
74622 return false;
74623 }
74624 }
74625
74626 $this->latestSignal = (int) $signal;
74627 $this->fallbackStatus['signaled'] = true;
74628 $this->fallbackStatus['exitcode'] = -1;
74629 $this->fallbackStatus['termsig'] = $this->latestSignal;
74630
74631 return true;
74632 }
74633
74634
74635
74636
74637
74638
74639
74640
74641 private function requireProcessIsStarted($functionName)
74642 {
74643 if (!$this->isStarted()) {
74644 throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
74645 }
74646 }
74647
74648
74649
74650
74651
74652
74653
74654
74655 private function requireProcessIsTerminated($functionName)
74656 {
74657 if (!$this->isTerminated()) {
74658 throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
74659 }
74660 }
74661 }
74662 <?php
74663
74664
74665
74666
74667
74668
74669
74670
74671
74672
74673 namespace Symfony\Component\Process;
74674
74675 use Symfony\Component\Process\Exception\InvalidArgumentException;
74676 use Symfony\Component\Process\Exception\LogicException;
74677
74678
74679
74680
74681 class ProcessBuilder
74682 {
74683 private $arguments;
74684 private $cwd;
74685 private $env = array();
74686 private $input;
74687 private $timeout = 60;
74688 private $options = array();
74689 private $inheritEnv = true;
74690 private $prefix = array();
74691 private $outputDisabled = false;
74692
74693
74694
74695
74696 public function __construct(array $arguments = array())
74697 {
74698 $this->arguments = $arguments;
74699 }
74700
74701
74702
74703
74704
74705
74706
74707
74708 public static function create(array $arguments = array())
74709 {
74710 return new static($arguments);
74711 }
74712
74713
74714
74715
74716
74717
74718
74719
74720 public function add($argument)
74721 {
74722 $this->arguments[] = $argument;
74723
74724 return $this;
74725 }
74726
74727
74728
74729
74730
74731
74732
74733
74734
74735
74736 public function setPrefix($prefix)
74737 {
74738 $this->prefix = is_array($prefix) ? $prefix : array($prefix);
74739
74740 return $this;
74741 }
74742
74743
74744
74745
74746
74747
74748
74749
74750
74751
74752
74753 public function setArguments(array $arguments)
74754 {
74755 $this->arguments = $arguments;
74756
74757 return $this;
74758 }
74759
74760
74761
74762
74763
74764
74765
74766
74767 public function setWorkingDirectory($cwd)
74768 {
74769 $this->cwd = $cwd;
74770
74771 return $this;
74772 }
74773
74774
74775
74776
74777
74778
74779
74780
74781 public function inheritEnvironmentVariables($inheritEnv = true)
74782 {
74783 $this->inheritEnv = $inheritEnv;
74784
74785 return $this;
74786 }
74787
74788
74789
74790
74791
74792
74793
74794
74795
74796
74797
74798
74799 public function setEnv($name, $value)
74800 {
74801 $this->env[$name] = $value;
74802
74803 return $this;
74804 }
74805
74806
74807
74808
74809
74810
74811
74812
74813
74814
74815
74816
74817 public function addEnvironmentVariables(array $variables)
74818 {
74819 $this->env = array_replace($this->env, $variables);
74820
74821 return $this;
74822 }
74823
74824
74825
74826
74827
74828
74829
74830
74831
74832
74833
74834
74835 public function setInput($input)
74836 {
74837 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
74838
74839 return $this;
74840 }
74841
74842
74843
74844
74845
74846
74847
74848
74849
74850
74851
74852
74853 public function setTimeout($timeout)
74854 {
74855 if (null === $timeout) {
74856 $this->timeout = null;
74857
74858 return $this;
74859 }
74860
74861 $timeout = (float) $timeout;
74862
74863 if ($timeout < 0) {
74864 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
74865 }
74866
74867 $this->timeout = $timeout;
74868
74869 return $this;
74870 }
74871
74872
74873
74874
74875
74876
74877
74878
74879
74880 public function setOption($name, $value)
74881 {
74882 $this->options[$name] = $value;
74883
74884 return $this;
74885 }
74886
74887
74888
74889
74890
74891
74892 public function disableOutput()
74893 {
74894 $this->outputDisabled = true;
74895
74896 return $this;
74897 }
74898
74899
74900
74901
74902
74903
74904 public function enableOutput()
74905 {
74906 $this->outputDisabled = false;
74907
74908 return $this;
74909 }
74910
74911
74912
74913
74914
74915
74916
74917
74918 public function getProcess()
74919 {
74920 if (0 === count($this->prefix) && 0 === count($this->arguments)) {
74921 throw new LogicException('You must add() command arguments before calling getProcess().');
74922 }
74923
74924 $options = $this->options;
74925
74926 $arguments = array_merge($this->prefix, $this->arguments);
74927 $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
74928
74929 if ($this->inheritEnv) {
74930
74931  $env = array_replace($_ENV, $_SERVER, $this->env);
74932 } else {
74933 $env = $this->env;
74934 }
74935
74936 $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
74937
74938 if ($this->outputDisabled) {
74939 $process->disableOutput();
74940 }
74941
74942 return $process;
74943 }
74944 }
74945 <?php
74946
74947
74948
74949
74950
74951
74952
74953
74954
74955
74956 namespace Symfony\Component\Process;
74957
74958 use Symfony\Component\Process\Exception\InvalidArgumentException;
74959
74960
74961
74962
74963
74964
74965
74966
74967 class ProcessUtils
74968 {
74969
74970
74971
74972 private function __construct()
74973 {
74974 }
74975
74976
74977
74978
74979
74980
74981
74982
74983 public static function escapeArgument($argument)
74984 {
74985
74986  
74987  
74988  
74989  if ('\\' === DIRECTORY_SEPARATOR) {
74990 if ('' === $argument) {
74991 return escapeshellarg($argument);
74992 }
74993
74994 $escapedArgument = '';
74995 $quote = false;
74996 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
74997 if ('"' === $part) {
74998 $escapedArgument .= '\\"';
74999 } elseif (self::isSurroundedBy($part, '%')) {
75000
75001  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
75002 } else {
75003
75004  if ('\\' === substr($part, -1)) {
75005 $part .= '\\';
75006 }
75007 $quote = true;
75008 $escapedArgument .= $part;
75009 }
75010 }
75011 if ($quote) {
75012 $escapedArgument = '"'.$escapedArgument.'"';
75013 }
75014
75015 return $escapedArgument;
75016 }
75017
75018 return "'".str_replace("'", "'\\''", $argument)."'";
75019 }
75020
75021
75022
75023
75024
75025
75026
75027
75028
75029
75030
75031
75032
75033 public static function validateInput($caller, $input)
75034 {
75035 if (null !== $input) {
75036 if (is_resource($input)) {
75037 return $input;
75038 }
75039 if (is_string($input)) {
75040 return $input;
75041 }
75042 if (is_scalar($input)) {
75043 return (string) $input;
75044 }
75045
75046  if (is_object($input) && method_exists($input, '__toString')) {
75047 @trigger_error('Passing an object as an input is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
75048
75049 return (string) $input;
75050 }
75051
75052 throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
75053 }
75054
75055 return $input;
75056 }
75057
75058 private static function isSurroundedBy($arg, $char)
75059 {
75060 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
75061 }
75062 }
75063 Copyright (c) 2011 Jordi Boggiano
75064
75065 Permission is hereby granted, free of charge, to any person obtaining a copy
75066 of this software and associated documentation files (the "Software"), to deal
75067 in the Software without restriction, including without limitation the rights
75068 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75069 copies of the Software, and to permit persons to whom the Software is furnished
75070 to do so, subject to the following conditions:
75071
75072 The above copyright notice and this permission notice shall be included in all
75073 copies or substantial portions of the Software.
75074
75075 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75076 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75077 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75078 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75079 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75080 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75081 THE SOFTWARE.
75082 <?php
75083
75084
75085
75086
75087
75088
75089
75090
75091
75092
75093 namespace Seld\JsonLint;
75094
75095 class DuplicateKeyException extends ParsingException
75096 {
75097 public function __construct($message, $key, array $details = array())
75098 {
75099 $details['key'] = $key;
75100 parent::__construct($message, $details);
75101 }
75102
75103 public function getKey()
75104 {
75105 return $this->details['key'];
75106 }
75107 }
75108 <?php
75109
75110
75111
75112
75113
75114
75115
75116
75117
75118
75119 namespace Seld\JsonLint;
75120 use stdClass;
75121
75122
75123
75124
75125
75126
75127
75128
75129
75130
75131
75132
75133
75134
75135 class JsonParser
75136 {
75137 const DETECT_KEY_CONFLICTS = 1;
75138 const ALLOW_DUPLICATE_KEYS = 2;
75139 const PARSE_TO_ASSOC = 4;
75140
75141 private $lexer;
75142
75143 private $flags;
75144 private $stack;
75145 private $vstack; 
75146  private $lstack; 
75147
75148 private $symbols = array(
75149 'error' => 2,
75150 'JSONString' => 3,
75151 'STRING' => 4,
75152 'JSONNumber' => 5,
75153 'NUMBER' => 6,
75154 'JSONNullLiteral' => 7,
75155 'NULL' => 8,
75156 'JSONBooleanLiteral' => 9,
75157 'TRUE' => 10,
75158 'FALSE' => 11,
75159 'JSONText' => 12,
75160 'JSONValue' => 13,
75161 'EOF' => 14,
75162 'JSONObject' => 15,
75163 'JSONArray' => 16,
75164 '{' => 17,
75165 '}' => 18,
75166 'JSONMemberList' => 19,
75167 'JSONMember' => 20,
75168 ':' => 21,
75169 ',' => 22,
75170 '[' => 23,
75171 ']' => 24,
75172 'JSONElementList' => 25,
75173 '$accept' => 0,
75174 '$end' => 1,
75175 );
75176
75177 private $terminals_ = array(
75178 2 => "error",
75179 4 => "STRING",
75180 6 => "NUMBER",
75181 8 => "NULL",
75182 10 => "TRUE",
75183 11 => "FALSE",
75184 14 => "EOF",
75185 17 => "{",
75186 18 => "}",
75187 21 => ":",
75188 22 => ",",
75189 23 => "[",
75190 24 => "]",
75191 );
75192
75193 private $productions_ = array(
75194 0,
75195 array(3, 1),
75196 array(5, 1),
75197 array(7, 1),
75198 array(9, 1),
75199 array(9, 1),
75200 array(12, 2),
75201 array(13, 1),
75202 array(13, 1),
75203 array(13, 1),
75204 array(13, 1),
75205 array(13, 1),
75206 array(13, 1),
75207 array(15, 2),
75208 array(15, 3),
75209 array(20, 3),
75210 array(19, 1),
75211 array(19, 3),
75212 array(16, 2),
75213 array(16, 3),
75214 array(25, 1),
75215 array(25, 3)
75216 );
75217
75218 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)),
75219 );
75220
75221 private $defaultActions = array(
75222 16 => array(2, 6)
75223 );
75224
75225
75226
75227
75228
75229
75230 public function lint($input, $flags = 0)
75231 {
75232 try {
75233 $this->parse($input, $flags);
75234 } catch (ParsingException $e) {
75235 return $e;
75236 }
75237 }
75238
75239
75240
75241
75242
75243
75244
75245 public function parse($input, $flags = 0)
75246 {
75247 $this->failOnBOM($input);
75248
75249 $this->flags = $flags;
75250
75251 $this->stack = array(0);
75252 $this->vstack = array(null);
75253 $this->lstack = array();
75254
75255 $yytext = '';
75256 $yylineno = 0;
75257 $yyleng = 0;
75258 $recovering = 0;
75259 $TERROR = 2;
75260 $EOF = 1;
75261
75262 $this->lexer = new Lexer();
75263 $this->lexer->setInput($input);
75264
75265 $yyloc = $this->lexer->yylloc;
75266 $this->lstack[] = $yyloc;
75267
75268 $symbol = null;
75269 $preErrorSymbol = null;
75270 $state = null;
75271 $action = null;
75272 $a = null;
75273 $r = null;
75274 $yyval = new stdClass;
75275 $p = null;
75276 $len = null;
75277 $newState = null;
75278 $expected = null;
75279 $errStr = null;
75280
75281 while (true) {
75282
75283  $state = $this->stack[count($this->stack)-1];
75284
75285
75286  if (isset($this->defaultActions[$state])) {
75287 $action = $this->defaultActions[$state];
75288 } else {
75289 if ($symbol == null) {
75290 $symbol = $this->lex();
75291 }
75292
75293  $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false;
75294 }
75295
75296
75297  if (!$action || !$action[0]) {
75298 if (!$recovering) {
75299
75300  $expected = array();
75301 foreach ($this->table[$state] as $p => $ignore) {
75302 if (isset($this->terminals_[$p]) && $p > 2) {
75303 $expected[] = "'" . $this->terminals_[$p] . "'";
75304 }
75305 }
75306
75307 $message = null;
75308 if (in_array("'STRING'", $expected) && in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
75309 $message = "Invalid string";
75310 if ("'" === substr($this->lexer->match, 0, 1)) {
75311 $message .= ", it appears you used single quotes instead of double quotes";
75312 } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u])}', $this->lexer->getUpcomingInput(), $match)) {
75313 $message .= ", it appears you have an unescaped backslash at: ".$match[1];
75314 } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getUpcomingInput())) {
75315 $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
75316 }
75317 }
75318
75319 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
75320 $errStr .= $this->lexer->showPosition() . "\n";
75321 if ($message) {
75322 $errStr .= $message;
75323 } else {
75324 $errStr .= (count($expected) > 1) ? "Expected one of: " : "Expected: ";
75325 $errStr .= implode(', ', $expected);
75326 }
75327
75328 if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
75329 $errStr .= " - It appears you have an extra trailing comma";
75330 }
75331
75332 $this->parseError($errStr, array(
75333 'text' => $this->lexer->match,
75334 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol,
75335 'line' => $this->lexer->yylineno,
75336 'loc' => $yyloc,
75337 'expected' => $expected,
75338 ));
75339 }
75340
75341
75342  if ($recovering == 3) {
75343 if ($symbol == $EOF) {
75344 throw new ParsingException($errStr ?: 'Parsing halted.');
75345 }
75346
75347
75348  $yyleng = $this->lexer->yyleng;
75349 $yytext = $this->lexer->yytext;
75350 $yylineno = $this->lexer->yylineno;
75351 $yyloc = $this->lexer->yylloc;
75352 $symbol = $this->lex();
75353 }
75354
75355
75356  while (true) {
75357
75358  if (array_key_exists($TERROR, $this->table[$state])) {
75359 break;
75360 }
75361 if ($state == 0) {
75362 throw new ParsingException($errStr ?: 'Parsing halted.');
75363 }
75364 $this->popStack(1);
75365 $state = $this->stack[count($this->stack)-1];
75366 }
75367
75368 $preErrorSymbol = $symbol; 
75369  $symbol = $TERROR; 
75370  $state = $this->stack[count($this->stack)-1];
75371 $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false;
75372 $recovering = 3; 
75373  }
75374
75375
75376  if (is_array($action[0]) && count($action) > 1) {
75377 throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
75378 }
75379
75380 switch ($action[0]) {
75381 case 1: 
75382  $this->stack[] = $symbol;
75383 $this->vstack[] = $this->lexer->yytext;
75384 $this->lstack[] = $this->lexer->yylloc;
75385 $this->stack[] = $action[1]; 
75386  $symbol = null;
75387 if (!$preErrorSymbol) { 
75388  $yyleng = $this->lexer->yyleng;
75389 $yytext = $this->lexer->yytext;
75390 $yylineno = $this->lexer->yylineno;
75391 $yyloc = $this->lexer->yylloc;
75392 if ($recovering > 0) {
75393 $recovering--;
75394 }
75395 } else { 
75396  $symbol = $preErrorSymbol;
75397 $preErrorSymbol = null;
75398 }
75399 break;
75400
75401 case 2: 
75402  $len = $this->productions_[$action[1]][1];
75403
75404
75405  $yyval->token = $this->vstack[count($this->vstack) - $len]; 
75406  
75407  $yyval->store = array( 
75408  'first_line' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_line'],
75409 'last_line' => $this->lstack[count($this->lstack) - 1]['last_line'],
75410 'first_column' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_column'],
75411 'last_column' => $this->lstack[count($this->lstack) - 1]['last_column'],
75412 );
75413 $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack, $this->lstack);
75414
75415 if (!$r instanceof Undefined) {
75416 return $r;
75417 }
75418
75419 if ($len) {
75420 $this->popStack($len);
75421 }
75422
75423 $this->stack[] = $this->productions_[$action[1]][0]; 
75424  $this->vstack[] = $yyval->token;
75425 $this->lstack[] = $yyval->store;
75426 $newState = $this->table[$this->stack[count($this->stack)-2]][$this->stack[count($this->stack)-1]];
75427 $this->stack[] = $newState;
75428 break;
75429
75430 case 3: 
75431
75432 return true;
75433 }
75434 }
75435
75436 return true;
75437 }
75438
75439 protected function parseError($str, $hash)
75440 {
75441 throw new ParsingException($str, $hash);
75442 }
75443
75444
75445  
75446  
75447  private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens)
75448 {
75449
75450  $len = count($tokens) - 1;
75451 switch ($yystate) {
75452 case 1:
75453 $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
75454 $yyval->token = $yytext;
75455 break;
75456 case 2:
75457 if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) {
75458 $yyval->token = floatval($yytext);
75459 } else {
75460 $yyval->token = strpos($yytext, '.') === false ? intval($yytext) : floatval($yytext);
75461 }
75462 break;
75463 case 3:
75464 $yyval->token = null;
75465 break;
75466 case 4:
75467 $yyval->token = true;
75468 break;
75469 case 5:
75470 $yyval->token = false;
75471 break;
75472 case 6:
75473 return $yyval->token = $tokens[$len-1];
75474 case 13:
75475 if ($this->flags & self::PARSE_TO_ASSOC) {
75476 $yyval->token = array();
75477 } else {
75478 $yyval->token = new stdClass;
75479 }
75480 break;
75481 case 14:
75482 $yyval->token = $tokens[$len-1];
75483 break;
75484 case 15:
75485 $yyval->token = array($tokens[$len-2], $tokens[$len]);
75486 break;
75487 case 16:
75488 if (PHP_VERSION_ID < 70100) {
75489 $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
75490 } else {
75491 $property = $tokens[$len][0];
75492 }
75493 if ($this->flags & self::PARSE_TO_ASSOC) {
75494 $yyval->token = array();
75495 $yyval->token[$property] = $tokens[$len][1];
75496 } else {
75497 $yyval->token = new stdClass;
75498 $yyval->token->$property = $tokens[$len][1];
75499 }
75500 break;
75501 case 17:
75502 if ($this->flags & self::PARSE_TO_ASSOC) {
75503 $yyval->token =& $tokens[$len-2];
75504 $key = $tokens[$len][0];
75505 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
75506 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
75507 $errStr .= $this->lexer->showPosition() . "\n";
75508 $errStr .= "Duplicate key: ".$tokens[$len][0];
75509 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
75510 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) {
75511 $duplicateCount = 1;
75512 do {
75513 $duplicateKey = $key . '.' . $duplicateCount++;
75514 } while (isset($tokens[$len-2][$duplicateKey]));
75515 $key = $duplicateKey;
75516 }
75517 $tokens[$len-2][$key] = $tokens[$len][1];
75518 } else {
75519 $yyval->token = $tokens[$len-2];
75520 if (PHP_VERSION_ID < 70100) {
75521 $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
75522 } else {
75523 $key = $tokens[$len][0];
75524 }
75525 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
75526 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
75527 $errStr .= $this->lexer->showPosition() . "\n";
75528 $errStr .= "Duplicate key: ".$tokens[$len][0];
75529 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
75530 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) {
75531 $duplicateCount = 1;
75532 do {
75533 $duplicateKey = $key . '.' . $duplicateCount++;
75534 } while (isset($tokens[$len-2]->$duplicateKey));
75535 $key = $duplicateKey;
75536 }
75537 $tokens[$len-2]->$key = $tokens[$len][1];
75538 }
75539 break;
75540 case 18:
75541 $yyval->token = array();
75542 break;
75543 case 19:
75544 $yyval->token = $tokens[$len-1];
75545 break;
75546 case 20:
75547 $yyval->token = array($tokens[$len]);
75548 break;
75549 case 21:
75550 $tokens[$len-2][] = $tokens[$len];
75551 $yyval->token = $tokens[$len-2];
75552 break;
75553 }
75554
75555 return new Undefined();
75556 }
75557
75558 private function stringInterpolation($match)
75559 {
75560 switch ($match[0]) {
75561 case '\\\\':
75562 return '\\';
75563 case '\"':
75564 return '"';
75565 case '\b':
75566 return chr(8);
75567 case '\f':
75568 return chr(12);
75569 case '\n':
75570 return "\n";
75571 case '\r':
75572 return "\r";
75573 case '\t':
75574 return "\t";
75575 case '\/':
75576 return "/";
75577 default:
75578 return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', 0, 'UTF-8');
75579 }
75580 }
75581
75582 private function popStack($n)
75583 {
75584 $this->stack = array_slice($this->stack, 0, - (2 * $n));
75585 $this->vstack = array_slice($this->vstack, 0, - $n);
75586 $this->lstack = array_slice($this->lstack, 0, - $n);
75587 }
75588
75589 private function lex()
75590 {
75591 $token = $this->lexer->lex() ?: 1; 
75592  
75593  if (!is_numeric($token)) {
75594 $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token;
75595 }
75596
75597 return $token;
75598 }
75599
75600 private function failOnBOM($input)
75601 {
75602
75603  $bom = "\xEF\xBB\xBF";
75604
75605 if (substr($input, 0, 3) === $bom) {
75606 $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array());
75607 }
75608 }
75609 }
75610 <?php
75611
75612
75613
75614
75615
75616
75617
75618
75619
75620
75621 namespace Seld\JsonLint;
75622
75623
75624
75625
75626
75627
75628 class Lexer
75629 {
75630 private $EOF = 1;
75631 private $rules = array(
75632 0 => '/^\s+/',
75633 1 => '/^-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/',
75634 2 => '{^"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x1f\\\\"]++)*+"}',
75635 3 => '/^\{/',
75636 4 => '/^\}/',
75637 5 => '/^\[/',
75638 6 => '/^\]/',
75639 7 => '/^,/',
75640 8 => '/^:/',
75641 9 => '/^true\b/',
75642 10 => '/^false\b/',
75643 11 => '/^null\b/',
75644 12 => '/^$/',
75645 13 => '/^./',
75646 );
75647
75648 private $conditions = array(
75649 "INITIAL" => array(
75650 "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13),
75651 "inclusive" => true,
75652 ),
75653 );
75654
75655 private $conditionStack;
75656 private $input;
75657 private $more;
75658 private $done;
75659 private $matched;
75660
75661 public $match;
75662 public $yylineno;
75663 public $yyleng;
75664 public $yytext;
75665 public $yylloc;
75666
75667 public function lex()
75668 {
75669 $r = $this->next();
75670 if (!$r instanceof Undefined) {
75671 return $r;
75672 }
75673
75674 return $this->lex();
75675 }
75676
75677 public function setInput($input)
75678 {
75679 $this->input = $input;
75680 $this->more = false;
75681 $this->done = false;
75682 $this->yylineno = $this->yyleng = 0;
75683 $this->yytext = $this->matched = $this->match = '';
75684 $this->conditionStack = array('INITIAL');
75685 $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
75686
75687 return $this;
75688 }
75689
75690 public function showPosition()
75691 {
75692 $pre = str_replace("\n", '', $this->getPastInput());
75693 $c = str_repeat('-', max(0, strlen($pre) - 1)); 
75694
75695 return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
75696 }
75697
75698 public function getPastInput()
75699 {
75700 $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match));
75701
75702 return (strlen($past) > 20 ? '...' : '') . substr($past, -20);
75703 }
75704
75705 public function getUpcomingInput()
75706 {
75707 $next = $this->match;
75708 if (strlen($next) < 20) {
75709 $next .= substr($this->input, 0, 20 - strlen($next));
75710 }
75711
75712 return substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '');
75713 }
75714
75715 protected function parseError($str, $hash)
75716 {
75717 throw new \Exception($str);
75718 }
75719
75720 private function next()
75721 {
75722 if ($this->done) {
75723 return $this->EOF;
75724 }
75725 if ($this->input === '') {
75726 $this->done = true;
75727 }
75728
75729 $token = null;
75730 $match = null;
75731 $col = null;
75732 $lines = null;
75733
75734 if (!$this->more) {
75735 $this->yytext = '';
75736 $this->match = '';
75737 }
75738
75739 $rules = $this->getCurrentRules();
75740 $rulesLen = count($rules);
75741
75742 for ($i=0; $i < $rulesLen; $i++) {
75743 if (preg_match($this->rules[$rules[$i]], $this->input, $match)) {
75744 preg_match_all('/\n.*/', $match[0], $lines);
75745 $lines = $lines[0];
75746 if ($lines) {
75747 $this->yylineno += count($lines);
75748 }
75749
75750 $this->yylloc = array(
75751 'first_line' => $this->yylloc['last_line'],
75752 'last_line' => $this->yylineno+1,
75753 'first_column' => $this->yylloc['last_column'],
75754 'last_column' => $lines ? strlen($lines[count($lines) - 1]) - 1 : $this->yylloc['last_column'] + strlen($match[0]),
75755 );
75756 $this->yytext .= $match[0];
75757 $this->match .= $match[0];
75758 $this->yyleng = strlen($this->yytext);
75759 $this->more = false;
75760 $this->input = substr($this->input, strlen($match[0]));
75761 $this->matched .= $match[0];
75762 $token = $this->performAction($rules[$i], $this->conditionStack[count($this->conditionStack)-1]);
75763 if ($token) {
75764 return $token;
75765 }
75766
75767 return new Undefined();
75768 }
75769 }
75770
75771 if ($this->input === "") {
75772 return $this->EOF;
75773 }
75774
75775 $this->parseError(
75776 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(),
75777 array(
75778 'text' => "",
75779 'token' => null,
75780 'line' => $this->yylineno,
75781 )
75782 );
75783 }
75784
75785 private function getCurrentRules()
75786 {
75787 return $this->conditions[$this->conditionStack[count($this->conditionStack)-1]]['rules'];
75788 }
75789
75790 private function performAction($avoiding_name_collisions, $YY_START)
75791 {
75792 switch ($avoiding_name_collisions) {
75793 case 0:
75794 break;
75795 case 1:
75796 return 6;
75797 break;
75798 case 2:
75799 $this->yytext = substr($this->yytext, 1, $this->yyleng-2);
75800
75801 return 4;
75802 case 3:
75803 return 17;
75804 case 4:
75805 return 18;
75806 case 5:
75807 return 23;
75808 case 6:
75809 return 24;
75810 case 7:
75811 return 22;
75812 case 8:
75813 return 21;
75814 case 9:
75815 return 10;
75816 case 10:
75817 return 11;
75818 case 11:
75819 return 8;
75820 case 12:
75821 return 14;
75822 case 13:
75823 return 'INVALID';
75824 }
75825 }
75826 }
75827 <?php
75828
75829
75830
75831
75832
75833
75834
75835
75836
75837
75838 namespace Seld\JsonLint;
75839
75840 class ParsingException extends \Exception
75841 {
75842 protected $details;
75843
75844 public function __construct($message, $details = array())
75845 {
75846 $this->details = $details;
75847 parent::__construct($message);
75848 }
75849
75850 public function getDetails()
75851 {
75852 return $this->details;
75853 }
75854 }
75855 <?php
75856
75857
75858
75859
75860
75861
75862
75863
75864
75865
75866 namespace Seld\JsonLint;
75867
75868 class Undefined
75869 {
75870 }
75871 Copyright (c) 2015 Jordi Boggiano
75872
75873 Permission is hereby granted, free of charge, to any person obtaining a copy
75874 of this software and associated documentation files (the "Software"), to deal
75875 in the Software without restriction, including without limitation the rights
75876 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75877 copies of the Software, and to permit persons to whom the Software is furnished
75878 to do so, subject to the following conditions:
75879
75880 The above copyright notice and this permission notice shall be included in all
75881 copies or substantial portions of the Software.
75882
75883 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75884 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75885 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75886 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75887 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75888 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75889 THE SOFTWARE.
75890 <?php
75891
75892 require __DIR__.'/../vendor/autoload.php';
75893
75894 echo 'Say hello (visible): ';
75895
75896 $answer = Seld\CliPrompt\CliPrompt::prompt();
75897
75898 echo 'You answered: '.$answer . PHP_EOL;
75899
75900 echo 'Say hello (hidden): ';
75901
75902 $answer = Seld\CliPrompt\CliPrompt::hiddenPrompt();
75903
75904 echo 'You answered: '.$answer . PHP_EOL;
75905 <?php
75906
75907
75908
75909
75910
75911
75912
75913
75914
75915
75916 namespace Seld\CliPrompt;
75917
75918 class CliPrompt
75919 {
75920
75921
75922
75923
75924
75925 public static function prompt()
75926 {
75927 $stdin = fopen('php://stdin', 'r');
75928 $answer = self::trimAnswer(fgets($stdin, 4096));
75929 fclose($stdin);
75930
75931 return $answer;
75932 }
75933
75934
75935
75936
75937
75938
75939
75940
75941
75942
75943 public static function hiddenPrompt($allowFallback = false)
75944 {
75945
75946  if (defined('PHP_WINDOWS_VERSION_BUILD')) {
75947
75948  $exe = __DIR__.'\\..\\res\\hiddeninput.exe';
75949
75950
75951  if ('phar:' === substr(__FILE__, 0, 5)) {
75952 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
75953
75954
75955  
75956  $source = fopen($exe, 'r');
75957 $target = fopen($tmpExe, 'w+');
75958 stream_copy_to_stream($source, $target);
75959 fclose($source);
75960 fclose($target);
75961 unset($source, $target);
75962
75963 $exe = $tmpExe;
75964 }
75965
75966 $output = shell_exec($exe);
75967
75968
75969  if (isset($tmpExe)) {
75970 unlink($tmpExe);
75971 }
75972
75973 if ($output !== null) {
75974
75975  echo PHP_EOL;
75976
75977 return self::trimAnswer($output);
75978 }
75979 }
75980
75981 if (file_exists('/usr/bin/env')) {
75982
75983  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
75984 foreach (array('bash', 'zsh', 'ksh', 'csh', 'sh') as $sh) {
75985 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
75986 $shell = $sh;
75987 break;
75988 }
75989 }
75990
75991 if (isset($shell)) {
75992 $readCmd = ($shell === 'csh') ? 'set mypassword = $<' : 'read -r mypassword';
75993 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
75994 $output = shell_exec($command);
75995
75996 if ($output !== null) {
75997
75998  echo PHP_EOL;
75999
76000 return self::trimAnswer($output);
76001 }
76002 }
76003 }
76004
76005
76006  if (!$allowFallback) {
76007 throw new \RuntimeException('Could not prompt for input in a secure fashion, aborting');
76008 }
76009
76010 return self::prompt();
76011 }
76012
76013 private static function trimAnswer($str)
76014 {
76015 return preg_replace('{\r?\n$}D', '', $str);
76016 }
76017 }
76018 MIT License
76019
76020 Copyright (c) 2016
76021
76022 Permission is hereby granted, free of charge, to any person obtaining a copy
76023 of this software and associated documentation files (the "Software"), to deal
76024 in the Software without restriction, including without limitation the rights
76025 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
76026 copies of the Software, and to permit persons to whom the Software is
76027 furnished to do so, subject to the following conditions:
76028
76029 The above copyright notice and this permission notice shall be included in all
76030 copies or substantial portions of the Software.
76031
76032 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
76033 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
76034 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
76035 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76036 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
76037 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
76038 SOFTWARE.
76039 <?php
76040
76041 require __DIR__ . '/../vendor/autoload.php';
76042
76043 $data = json_decode(file_get_contents('data.json'));
76044
76045
76046 $validator = new JsonSchema\Validator();
76047 $validator->check($data, (object) array('$ref' => 'file://' . realpath('schema.json')));
76048
76049 if ($validator->isValid()) {
76050 echo "The supplied JSON validates against the schema.\n";
76051 } else {
76052 echo "JSON does not validate. Violations:\n";
76053 foreach ($validator->getErrors() as $error) {
76054 echo sprintf("[%s] %s\n", $error['property'], $error['message']);
76055 }
76056 }
76057 <?php
76058
76059
76060
76061
76062
76063
76064
76065
76066 namespace JsonSchema\Constraints;
76067
76068 use JsonSchema\Entity\JsonPointer;
76069 use JsonSchema\Exception\InvalidArgumentException;
76070 use JsonSchema\Exception\ValidationException;
76071 use JsonSchema\Validator;
76072
76073
76074
76075
76076
76077 class BaseConstraint
76078 {
76079
76080
76081
76082 protected $errors = array();
76083
76084
76085
76086
76087 protected $errorMask = Validator::ERROR_NONE;
76088
76089
76090
76091
76092 protected $factory;
76093
76094
76095
76096
76097 public function __construct(Factory $factory = null)
76098 {
76099 $this->factory = $factory ?: new Factory();
76100 }
76101
76102 public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null)
76103 {
76104 $error = array(
76105 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')),
76106 'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
76107 'message' => $message,
76108 'constraint' => $constraint,
76109 'context' => $this->factory->getErrorContext(),
76110 );
76111
76112 if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
76113 throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
76114 }
76115
76116 if (is_array($more) && count($more) > 0) {
76117 $error += $more;
76118 }
76119
76120 $this->errors[] = $error;
76121 $this->errorMask |= $error['context'];
76122 }
76123
76124 public function addErrors(array $errors)
76125 {
76126 if ($errors) {
76127 $this->errors = array_merge($this->errors, $errors);
76128 $errorMask = &$this->errorMask;
76129 array_walk($errors, function ($error) use (&$errorMask) {
76130 if (isset($error['context'])) {
76131 $errorMask |= $error['context'];
76132 }
76133 });
76134 }
76135 }
76136
76137 public function getErrors($errorContext = Validator::ERROR_ALL)
76138 {
76139 if ($errorContext === Validator::ERROR_ALL) {
76140 return $this->errors;
76141 }
76142
76143 return array_filter($this->errors, function ($error) use ($errorContext) {
76144 if ($errorContext & $error['context']) {
76145 return true;
76146 }
76147 });
76148 }
76149
76150 public function numErrors($errorContext = Validator::ERROR_ALL)
76151 {
76152 if ($errorContext === Validator::ERROR_ALL) {
76153 return count($this->errors);
76154 }
76155
76156 return count($this->getErrors($errorContext));
76157 }
76158
76159 public function isValid()
76160 {
76161 return !$this->getErrors();
76162 }
76163
76164
76165
76166
76167
76168 public function reset()
76169 {
76170 $this->errors = array();
76171 $this->errorMask = Validator::ERROR_NONE;
76172 }
76173
76174
76175
76176
76177
76178
76179 public function getErrorMask()
76180 {
76181 return $this->errorMask;
76182 }
76183
76184
76185
76186
76187
76188
76189
76190
76191 public static function arrayToObjectRecursive($array)
76192 {
76193 $json = json_encode($array);
76194 if (json_last_error() !== \JSON_ERROR_NONE) {
76195 $message = 'Unable to encode schema array as JSON';
76196 if (function_exists('json_last_error_msg')) {
76197 $message .= ': ' . json_last_error_msg();
76198 }
76199 throw new InvalidArgumentException($message);
76200 }
76201
76202 return (object) json_decode($json);
76203 }
76204 }
76205 <?php
76206
76207
76208
76209
76210
76211
76212
76213
76214 namespace JsonSchema\Constraints;
76215
76216 use JsonSchema\Entity\JsonPointer;
76217
76218
76219
76220
76221
76222
76223
76224 class CollectionConstraint extends Constraint
76225 {
76226
76227
76228
76229 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null)
76230 {
76231
76232  if (isset($schema->minItems) && count($value) < $schema->minItems) {
76233 $this->addError($path, 'There must be a minimum of ' . $schema->minItems . ' items in the array', 'minItems', array('minItems' => $schema->minItems));
76234 }
76235
76236
76237  if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
76238 $this->addError($path, 'There must be a maximum of ' . $schema->maxItems . ' items in the array', 'maxItems', array('maxItems' => $schema->maxItems));
76239 }
76240
76241
76242  if (isset($schema->uniqueItems) && $schema->uniqueItems) {
76243 $unique = $value;
76244 if (is_array($value) && count($value)) {
76245 $unique = array_map(function ($e) {
76246 return var_export($e, true);
76247 }, $value);
76248 }
76249 if (count(array_unique($unique)) != count($value)) {
76250 $this->addError($path, 'There are no duplicates allowed in the array', 'uniqueItems');
76251 }
76252 }
76253
76254
76255  if (isset($schema->items)) {
76256 $this->validateItems($value, $schema, $path, $i);
76257 }
76258 }
76259
76260
76261
76262
76263
76264
76265
76266
76267
76268 protected function validateItems(&$value, $schema = null, JsonPointer $path = null, $i = null)
76269 {
76270 if (is_object($schema->items)) {
76271
76272
76273 if (isset($schema->items->type)
76274 && (
76275 $schema->items->type == 'string'
76276 || $schema->items->type == 'number'
76277 || $schema->items->type == 'integer'
76278 )
76279 && !isset($schema->additionalItems)
76280 ) {
76281
76282  $type = $schema->items->type;
76283 $typeValidator = $this->factory->createInstanceFor('type');
76284 $validator = $this->factory->createInstanceFor($type === 'integer' ? 'number' : $type);
76285
76286 foreach ($value as $k => &$v) {
76287 $k_path = $this->incrementPath($path, $k);
76288 $typeValidator->check($v, $schema->items, $k_path, $i);
76289
76290 $validator->check($v, $schema->items, $k_path, $i);
76291 }
76292 unset($v); 
76293
76294 $this->addErrors($typeValidator->getErrors());
76295 $this->addErrors($validator->getErrors());
76296 } else {
76297 foreach ($value as $k => &$v) {
76298 $initErrors = $this->getErrors();
76299
76300
76301  $this->checkUndefined($v, $schema->items, $path, $k);
76302
76303
76304  if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
76305 $secondErrors = $this->getErrors();
76306 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
76307 }
76308
76309
76310  if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
76311 $this->errors = $secondErrors;
76312 } elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
76313 $this->errors = $initErrors;
76314 }
76315 }
76316 unset($v); 
76317
76318 }
76319 } else {
76320
76321  foreach ($value as $k => &$v) {
76322 if (array_key_exists($k, $schema->items)) {
76323 $this->checkUndefined($v, $schema->items[$k], $path, $k);
76324 } else {
76325
76326  if (property_exists($schema, 'additionalItems')) {
76327 if ($schema->additionalItems !== false) {
76328 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
76329 } else {
76330 $this->addError(
76331 $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems));
76332 }
76333 } else {
76334
76335  $this->checkUndefined($v, new \stdClass(), $path, $k);
76336 }
76337 }
76338 }
76339 unset($v); 
76340
76341
76342
76343  if (count($value) > 0) {
76344 for ($k = count($value); $k < count($schema->items); $k++) {
76345 $undefinedInstance = $this->factory->createInstanceFor('undefined');
76346 $this->checkUndefined($undefinedInstance, $schema->items[$k], $path, $k);
76347 }
76348 }
76349 }
76350 }
76351 }
76352 <?php
76353
76354
76355
76356
76357
76358
76359
76360
76361 namespace JsonSchema\Constraints;
76362
76363 use JsonSchema\Entity\JsonPointer;
76364 use JsonSchema\SchemaStorage;
76365 use JsonSchema\Uri\UriRetriever;
76366 use JsonSchema\UriRetrieverInterface;
76367
76368
76369
76370
76371
76372
76373
76374 abstract class Constraint extends BaseConstraint implements ConstraintInterface
76375 {
76376 protected $inlineSchemaProperty = '$schema';
76377
76378 const CHECK_MODE_NONE = 0x00000000;
76379 const CHECK_MODE_NORMAL = 0x00000001;
76380 const CHECK_MODE_TYPE_CAST = 0x00000002;
76381 const CHECK_MODE_COERCE_TYPES = 0x00000004;
76382 const CHECK_MODE_APPLY_DEFAULTS = 0x00000008;
76383 const CHECK_MODE_EXCEPTIONS = 0x00000010;
76384 const CHECK_MODE_DISABLE_FORMAT = 0x00000020;
76385 const CHECK_MODE_ONLY_REQUIRED_DEFAULTS = 0x00000080;
76386 const CHECK_MODE_VALIDATE_SCHEMA = 0x00000100;
76387
76388
76389
76390
76391
76392
76393
76394
76395
76396 protected function incrementPath(JsonPointer $path = null, $i)
76397 {
76398 $path = $path ?: new JsonPointer('');
76399 $path = $path->withPropertyPaths(
76400 array_merge(
76401 $path->getPropertyPaths(),
76402 array_filter(array($i), 'strlen')
76403 )
76404 );
76405
76406 return $path;
76407 }
76408
76409
76410
76411
76412
76413
76414
76415
76416
76417 protected function checkArray(&$value, $schema = null, JsonPointer $path = null, $i = null)
76418 {
76419 $validator = $this->factory->createInstanceFor('collection');
76420 $validator->check($value, $schema, $path, $i);
76421
76422 $this->addErrors($validator->getErrors());
76423 }
76424
76425
76426
76427
76428
76429
76430
76431
76432
76433
76434
76435 protected function checkObject(&$value, $schema = null, JsonPointer $path = null, $properties = null,
76436 $additionalProperties = null, $patternProperties = null, $appliedDefaults = array())
76437 {
76438 $validator = $this->factory->createInstanceFor('object');
76439 $validator->check($value, $schema, $path, $properties, $additionalProperties, $patternProperties, $appliedDefaults);
76440
76441 $this->addErrors($validator->getErrors());
76442 }
76443
76444
76445
76446
76447
76448
76449
76450
76451
76452 protected function checkType(&$value, $schema = null, JsonPointer $path = null, $i = null)
76453 {
76454 $validator = $this->factory->createInstanceFor('type');
76455 $validator->check($value, $schema, $path, $i);
76456
76457 $this->addErrors($validator->getErrors());
76458 }
76459
76460
76461
76462
76463
76464
76465
76466
76467
76468 protected function checkUndefined(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
76469 {
76470 $validator = $this->factory->createInstanceFor('undefined');
76471
76472 $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i, $fromDefault);
76473
76474 $this->addErrors($validator->getErrors());
76475 }
76476
76477
76478
76479
76480
76481
76482
76483
76484
76485 protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
76486 {
76487 $validator = $this->factory->createInstanceFor('string');
76488 $validator->check($value, $schema, $path, $i);
76489
76490 $this->addErrors($validator->getErrors());
76491 }
76492
76493
76494
76495
76496
76497
76498
76499
76500
76501 protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
76502 {
76503 $validator = $this->factory->createInstanceFor('number');
76504 $validator->check($value, $schema, $path, $i);
76505
76506 $this->addErrors($validator->getErrors());
76507 }
76508
76509
76510
76511
76512
76513
76514
76515
76516
76517 protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
76518 {
76519 $validator = $this->factory->createInstanceFor('enum');
76520 $validator->check($value, $schema, $path, $i);
76521
76522 $this->addErrors($validator->getErrors());
76523 }
76524
76525
76526
76527
76528
76529
76530
76531
76532
76533 protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
76534 {
76535 $validator = $this->factory->createInstanceFor('format');
76536 $validator->check($value, $schema, $path, $i);
76537
76538 $this->addErrors($validator->getErrors());
76539 }
76540
76541
76542
76543
76544
76545
76546 protected function getTypeCheck()
76547 {
76548 return $this->factory->getTypeCheck();
76549 }
76550
76551
76552
76553
76554
76555
76556 protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
76557 {
76558 $result = array_map(
76559 function ($path) {
76560 return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
76561 },
76562 $pointer->getPropertyPaths()
76563 );
76564
76565 return trim(implode('', $result), '.');
76566 }
76567 }
76568 <?php
76569
76570
76571
76572
76573
76574
76575
76576
76577 namespace JsonSchema\Constraints;
76578
76579 use JsonSchema\Entity\JsonPointer;
76580
76581
76582
76583
76584
76585
76586 interface ConstraintInterface
76587 {
76588
76589
76590
76591
76592
76593 public function getErrors();
76594
76595
76596
76597
76598
76599
76600 public function addErrors(array $errors);
76601
76602
76603
76604
76605
76606
76607
76608
76609
76610 public function addError(JsonPointer $path = null, $message, $constraint='', array $more = null);
76611
76612
76613
76614
76615
76616
76617 public function isValid();
76618
76619
76620
76621
76622
76623
76624
76625
76626
76627
76628
76629
76630
76631 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null);
76632 }
76633 <?php
76634
76635
76636
76637
76638
76639
76640
76641
76642 namespace JsonSchema\Constraints;
76643
76644 use JsonSchema\Entity\JsonPointer;
76645
76646
76647
76648
76649
76650
76651
76652 class EnumConstraint extends Constraint
76653 {
76654
76655
76656
76657 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76658 {
76659
76660  if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
76661 return;
76662 }
76663 $type = gettype($element);
76664
76665 foreach ($schema->enum as $enum) {
76666 $enumType = gettype($enum);
76667 if ($this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && $type == 'array' && $enumType == 'object') {
76668 if ((object) $element == $enum) {
76669 return;
76670 }
76671 }
76672
76673 if ($type === gettype($enum)) {
76674 if ($type == 'object') {
76675 if ($element == $enum) {
76676 return;
76677 }
76678 } elseif ($element === $enum) {
76679 return;
76680 }
76681 }
76682 }
76683
76684 $this->addError($path, 'Does not have a value in the enumeration ' . json_encode($schema->enum), 'enum', array('enum' => $schema->enum));
76685 }
76686 }
76687 <?php
76688
76689
76690
76691
76692
76693
76694
76695
76696 namespace JsonSchema\Constraints;
76697
76698 use JsonSchema\Constraints\Constraint;
76699 use JsonSchema\Exception\InvalidArgumentException;
76700 use JsonSchema\Exception\InvalidConfigException;
76701 use JsonSchema\SchemaStorage;
76702 use JsonSchema\SchemaStorageInterface;
76703 use JsonSchema\Uri\UriRetriever;
76704 use JsonSchema\UriRetrieverInterface;
76705 use JsonSchema\Validator;
76706
76707
76708
76709
76710 class Factory
76711 {
76712
76713
76714
76715 protected $schemaStorage;
76716
76717
76718
76719
76720 protected $uriRetriever;
76721
76722
76723
76724
76725 private $checkMode = Constraint::CHECK_MODE_NORMAL;
76726
76727
76728
76729
76730 private $typeCheck = array();
76731
76732
76733
76734
76735 protected $errorContext = Validator::ERROR_DOCUMENT_VALIDATION;
76736
76737
76738
76739
76740 protected $constraintMap = array(
76741 'array' => 'JsonSchema\Constraints\CollectionConstraint',
76742 'collection' => 'JsonSchema\Constraints\CollectionConstraint',
76743 'object' => 'JsonSchema\Constraints\ObjectConstraint',
76744 'type' => 'JsonSchema\Constraints\TypeConstraint',
76745 'undefined' => 'JsonSchema\Constraints\UndefinedConstraint',
76746 'string' => 'JsonSchema\Constraints\StringConstraint',
76747 'number' => 'JsonSchema\Constraints\NumberConstraint',
76748 'enum' => 'JsonSchema\Constraints\EnumConstraint',
76749 'format' => 'JsonSchema\Constraints\FormatConstraint',
76750 'schema' => 'JsonSchema\Constraints\SchemaConstraint',
76751 'validator' => 'JsonSchema\Validator'
76752 );
76753
76754
76755
76756
76757 private $instanceCache = array();
76758
76759
76760
76761
76762
76763
76764 public function __construct(
76765 SchemaStorageInterface $schemaStorage = null,
76766 UriRetrieverInterface $uriRetriever = null,
76767 $checkMode = Constraint::CHECK_MODE_NORMAL
76768 ) {
76769
76770  $this->setConfig($checkMode);
76771
76772 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
76773 $this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
76774 }
76775
76776
76777
76778
76779
76780
76781 public function setConfig($checkMode = Constraint::CHECK_MODE_NORMAL)
76782 {
76783 $this->checkMode = $checkMode;
76784 }
76785
76786
76787
76788
76789
76790
76791 public function addConfig($options)
76792 {
76793 $this->checkMode |= $options;
76794 }
76795
76796
76797
76798
76799
76800
76801 public function removeConfig($options)
76802 {
76803 $this->checkMode &= ~$options;
76804 }
76805
76806
76807
76808
76809
76810
76811
76812
76813 public function getConfig($options = null)
76814 {
76815 if ($options === null) {
76816 return $this->checkMode;
76817 }
76818
76819 return $this->checkMode & $options;
76820 }
76821
76822
76823
76824
76825 public function getUriRetriever()
76826 {
76827 return $this->uriRetriever;
76828 }
76829
76830 public function getSchemaStorage()
76831 {
76832 return $this->schemaStorage;
76833 }
76834
76835 public function getTypeCheck()
76836 {
76837 if (!isset($this->typeCheck[$this->checkMode])) {
76838 $this->typeCheck[$this->checkMode] = ($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST)
76839 ? new TypeCheck\LooseTypeCheck()
76840 : new TypeCheck\StrictTypeCheck();
76841 }
76842
76843 return $this->typeCheck[$this->checkMode];
76844 }
76845
76846
76847
76848
76849
76850
76851
76852 public function setConstraintClass($name, $class)
76853 {
76854
76855  if (!class_exists($class)) {
76856 throw new InvalidArgumentException('Unknown constraint ' . $name);
76857 }
76858
76859  if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
76860 throw new InvalidArgumentException('Invalid class ' . $name);
76861 }
76862 $this->constraintMap[$name] = $class;
76863
76864 return $this;
76865 }
76866
76867
76868
76869
76870
76871
76872
76873
76874
76875
76876 public function createInstanceFor($constraintName)
76877 {
76878 if (!isset($this->constraintMap[$constraintName])) {
76879 throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
76880 }
76881
76882 if (!isset($this->instanceCache[$constraintName])) {
76883 $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
76884 }
76885
76886 return clone $this->instanceCache[$constraintName];
76887 }
76888
76889
76890
76891
76892
76893
76894 public function getErrorContext()
76895 {
76896 return $this->errorContext;
76897 }
76898
76899
76900
76901
76902
76903
76904 public function setErrorContext($errorContext)
76905 {
76906 $this->errorContext = $errorContext;
76907 }
76908 }
76909 <?php
76910
76911
76912
76913
76914
76915
76916
76917
76918 namespace JsonSchema\Constraints;
76919
76920 use JsonSchema\Entity\JsonPointer;
76921 use JsonSchema\Rfc3339;
76922
76923
76924
76925
76926
76927
76928
76929
76930 class FormatConstraint extends Constraint
76931 {
76932
76933
76934
76935 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76936 {
76937 if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
76938 return;
76939 }
76940
76941 switch ($schema->format) {
76942 case 'date':
76943 if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
76944 $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format));
76945 }
76946 break;
76947
76948 case 'time':
76949 if (!$this->validateDateTime($element, 'H:i:s')) {
76950 $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format));
76951 }
76952 break;
76953
76954 case 'date-time':
76955 if (null === Rfc3339::createFromString($element)) {
76956 $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));
76957 }
76958 break;
76959
76960 case 'utc-millisec':
76961 if (!$this->validateDateTime($element, 'U')) {
76962 $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format));
76963 }
76964 break;
76965
76966 case 'regex':
76967 if (!$this->validateRegex($element)) {
76968 $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format));
76969 }
76970 break;
76971
76972 case 'color':
76973 if (!$this->validateColor($element)) {
76974 $this->addError($path, 'Invalid color', 'format', array('format' => $schema->format));
76975 }
76976 break;
76977
76978 case 'style':
76979 if (!$this->validateStyle($element)) {
76980 $this->addError($path, 'Invalid style', 'format', array('format' => $schema->format));
76981 }
76982 break;
76983
76984 case 'phone':
76985 if (!$this->validatePhone($element)) {
76986 $this->addError($path, 'Invalid phone number', 'format', array('format' => $schema->format));
76987 }
76988 break;
76989
76990 case 'uri':
76991 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
76992 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
76993 }
76994 break;
76995
76996 case 'uriref':
76997 case 'uri-reference':
76998 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
76999
77000  
77001  
77002  if (substr($element, 0, 2) === '//') { 
77003  $validURL = filter_var('scheme:' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
77004 } elseif (substr($element, 0, 1) === '/') { 
77005  $validURL = filter_var('scheme://host' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
77006 } elseif (strlen($element)) { 
77007  $pathParts = explode('/', $element, 2);
77008 if (strpos($pathParts[0], ':') !== false) {
77009 $validURL = null;
77010 } else {
77011 $validURL = filter_var('scheme://host/' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
77012 }
77013 } else {
77014 $validURL = null;
77015 }
77016 if ($validURL === null) {
77017 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
77018 }
77019 }
77020 break;
77021
77022 case 'email':
77023 $filterFlags = FILTER_NULL_ON_FAILURE;
77024 if (defined('FILTER_FLAG_EMAIL_UNICODE')) {
77025
77026  $filterFlags |= constant('FILTER_FLAG_EMAIL_UNICODE'); 
77027  }
77028 if (null === filter_var($element, FILTER_VALIDATE_EMAIL, $filterFlags)) {
77029 $this->addError($path, 'Invalid email', 'format', array('format' => $schema->format));
77030 }
77031 break;
77032
77033 case 'ip-address':
77034 case 'ipv4':
77035 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
77036 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
77037 }
77038 break;
77039
77040 case 'ipv6':
77041 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
77042 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
77043 }
77044 break;
77045
77046 case 'host-name':
77047 case 'hostname':
77048 if (!$this->validateHostname($element)) {
77049 $this->addError($path, 'Invalid hostname', 'format', array('format' => $schema->format));
77050 }
77051 break;
77052
77053 default:
77054
77055  
77056  
77057  
77058  
77059  
77060  break;
77061 }
77062 }
77063
77064 protected function validateDateTime($datetime, $format)
77065 {
77066 $dt = \DateTime::createFromFormat($format, $datetime);
77067
77068 if (!$dt) {
77069 return false;
77070 }
77071
77072 if ($datetime === $dt->format($format)) {
77073 return true;
77074 }
77075
77076
77077  
77078  
77079  
77080  if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', $datetime))) {
77081 return true;
77082 }
77083
77084 return false;
77085 }
77086
77087 protected function validateRegex($regex)
77088 {
77089 return false !== @preg_match('/' . $regex . '/u', '');
77090 }
77091
77092 protected function validateColor($color)
77093 {
77094 if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
77095 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
77096 'red', 'silver', 'teal', 'white', 'yellow'))) {
77097 return true;
77098 }
77099
77100 return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
77101 }
77102
77103 protected function validateStyle($style)
77104 {
77105 $properties = explode(';', rtrim($style, ';'));
77106 $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
77107
77108 return empty($invalidEntries);
77109 }
77110
77111 protected function validatePhone($phone)
77112 {
77113 return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
77114 }
77115
77116 protected function validateHostname($host)
77117 {
77118 $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';
77119
77120 return preg_match($hostnameRegex, $host);
77121 }
77122 }
77123 <?php
77124
77125
77126
77127
77128
77129
77130
77131
77132 namespace JsonSchema\Constraints;
77133
77134 use JsonSchema\Entity\JsonPointer;
77135
77136
77137
77138
77139
77140
77141
77142 class NumberConstraint extends Constraint
77143 {
77144
77145
77146
77147 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
77148 {
77149
77150  if (isset($schema->exclusiveMinimum)) {
77151 if (isset($schema->minimum)) {
77152 if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
77153 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum));
77154 } elseif ($element < $schema->minimum) {
77155 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
77156 }
77157 } else {
77158 $this->addError($path, 'Use of exclusiveMinimum requires presence of minimum', 'missingMinimum');
77159 }
77160 } elseif (isset($schema->minimum) && $element < $schema->minimum) {
77161 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
77162 }
77163
77164
77165  if (isset($schema->exclusiveMaximum)) {
77166 if (isset($schema->maximum)) {
77167 if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
77168 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum));
77169 } elseif ($element > $schema->maximum) {
77170 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
77171 }
77172 } else {
77173 $this->addError($path, 'Use of exclusiveMaximum requires presence of maximum', 'missingMaximum');
77174 }
77175 } elseif (isset($schema->maximum) && $element > $schema->maximum) {
77176 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
77177 }
77178
77179
77180  if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
77181 $this->addError($path, 'Is not divisible by ' . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy));
77182 }
77183
77184
77185  if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
77186 $this->addError($path, 'Must be a multiple of ' . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf));
77187 }
77188
77189 $this->checkFormat($element, $schema, $path, $i);
77190 }
77191
77192 private function fmod($number1, $number2)
77193 {
77194 $number1 = abs($number1);
77195 $modulus = fmod($number1, $number2);
77196 $precision = abs(0.0000000001);
77197 $diff = (float) ($modulus - $number2);
77198
77199 if (-$precision < $diff && $diff < $precision) {
77200 return 0.0;
77201 }
77202
77203 $decimals1 = mb_strpos($number1, '.') ? mb_strlen($number1) - mb_strpos($number1, '.') - 1 : 0;
77204 $decimals2 = mb_strpos($number2, '.') ? mb_strlen($number2) - mb_strpos($number2, '.') - 1 : 0;
77205
77206 return (float) round($modulus, max($decimals1, $decimals2));
77207 }
77208 }
77209 <?php
77210
77211
77212
77213
77214
77215
77216
77217
77218 namespace JsonSchema\Constraints;
77219
77220 use JsonSchema\Entity\JsonPointer;
77221
77222
77223
77224
77225
77226
77227
77228 class ObjectConstraint extends Constraint
77229 {
77230
77231
77232
77233 protected $appliedDefaults = array();
77234
77235
77236
77237
77238 public function check(&$element, $schema = null, JsonPointer $path = null, $properties = null,
77239 $additionalProp = null, $patternProperties = null, $appliedDefaults = array())
77240 {
77241 if ($element instanceof UndefinedConstraint) {
77242 return;
77243 }
77244
77245 $this->appliedDefaults = $appliedDefaults;
77246
77247 $matches = array();
77248 if ($patternProperties) {
77249
77250  $matches = $this->validatePatternProperties($element, $path, $patternProperties);
77251 }
77252
77253 if ($properties) {
77254
77255  $this->validateProperties($element, $properties, $path);
77256 }
77257
77258
77259  $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp);
77260 }
77261
77262 public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties)
77263 {
77264 $try = array('/', '#', '+', '~', '%');
77265 $matches = array();
77266 foreach ($patternProperties as $pregex => $schema) {
77267 $delimiter = '/';
77268
77269  foreach ($try as $delimiter) {
77270 if (strpos($pregex, $delimiter) === false) { 
77271  break;
77272 }
77273 }
77274
77275
77276  if (@preg_match($delimiter . $pregex . $delimiter . 'u', '') === false) {
77277 $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex));
77278 continue;
77279 }
77280 foreach ($element as $i => $value) {
77281 if (preg_match($delimiter . $pregex . $delimiter . 'u', $i)) {
77282 $matches[] = $i;
77283 $this->checkUndefined($value, $schema ?: new \stdClass(), $path, $i, in_array($i, $this->appliedDefaults));
77284 }
77285 }
77286 }
77287
77288 return $matches;
77289 }
77290
77291
77292
77293
77294
77295
77296
77297
77298
77299
77300
77301 public function validateElement($element, $matches, $schema = null, JsonPointer $path = null,
77302 $properties = null, $additionalProp = null)
77303 {
77304 $this->validateMinMaxConstraint($element, $schema, $path);
77305
77306 foreach ($element as $i => $value) {
77307 $definition = $this->getProperty($properties, $i);
77308
77309
77310  if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
77311 $this->addError($path, 'The property ' . $i . ' is not defined and the definition does not allow additional properties', 'additionalProp');
77312 }
77313
77314
77315  if (!in_array($i, $matches) && $additionalProp && !$definition) {
77316 if ($additionalProp === true) {
77317 $this->checkUndefined($value, null, $path, $i, in_array($i, $this->appliedDefaults));
77318 } else {
77319 $this->checkUndefined($value, $additionalProp, $path, $i, in_array($i, $this->appliedDefaults));
77320 }
77321 }
77322
77323
77324  $require = $this->getProperty($definition, 'requires');
77325 if ($require && !$this->getProperty($element, $require)) {
77326 $this->addError($path, 'The presence of the property ' . $i . ' requires that ' . $require . ' also be present', 'requires');
77327 }
77328
77329 $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
77330 if (is_object($property)) {
77331 $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
77332 }
77333 }
77334 }
77335
77336
77337
77338
77339
77340
77341
77342
77343 public function validateProperties(&$element, $properties = null, JsonPointer $path = null)
77344 {
77345 $undefinedConstraint = $this->factory->createInstanceFor('undefined');
77346
77347 foreach ($properties as $i => $value) {
77348 $property = &$this->getProperty($element, $i, $undefinedConstraint);
77349 $definition = $this->getProperty($properties, $i);
77350
77351 if (is_object($definition)) {
77352
77353  $this->checkUndefined($property, $definition, $path, $i, in_array($i, $this->appliedDefaults));
77354 }
77355 }
77356 }
77357
77358
77359
77360
77361
77362
77363
77364
77365
77366
77367 protected function &getProperty(&$element, $property, $fallback = null)
77368 {
77369 if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) ) {
77370 return $element[$property];
77371 } elseif (is_object($element) && property_exists($element, $property)) {
77372 return $element->$property;
77373 }
77374
77375 return $fallback;
77376 }
77377
77378
77379
77380
77381
77382
77383
77384
77385 protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null)
77386 {
77387
77388  if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
77389 if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
77390 $this->addError($path, 'Must contain a minimum of ' . $objectDefinition->minProperties . ' properties', 'minProperties', array('minProperties' => $objectDefinition->minProperties));
77391 }
77392 }
77393
77394  if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
77395 if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
77396 $this->addError($path, 'Must contain no more than ' . $objectDefinition->maxProperties . ' properties', 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties));
77397 }
77398 }
77399 }
77400 }
77401 <?php
77402
77403
77404
77405
77406
77407
77408
77409
77410 namespace JsonSchema\Constraints;
77411
77412 use JsonSchema\Entity\JsonPointer;
77413 use JsonSchema\Exception\InvalidArgumentException;
77414 use JsonSchema\Exception\InvalidSchemaException;
77415 use JsonSchema\Exception\RuntimeException;
77416 use JsonSchema\SchemaStorage;
77417 use JsonSchema\Validator;
77418
77419
77420
77421
77422
77423
77424
77425 class SchemaConstraint extends Constraint
77426 {
77427 const DEFAULT_SCHEMA_SPEC = 'http://json-schema.org/draft-04/schema#';
77428
77429
77430
77431
77432 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
77433 {
77434 if ($schema !== null) {
77435
77436  $validationSchema = $schema;
77437 } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
77438
77439  $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
77440 } else {
77441 throw new InvalidArgumentException('no schema found to verify against');
77442 }
77443
77444
77445  if (is_array($validationSchema)) {
77446 $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema);
77447 }
77448
77449
77450  
77451  if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) {
77452 if (!$this->getTypeCheck()->isObject($validationSchema)) {
77453 throw new RuntimeException('Cannot validate the schema of a non-object');
77454 }
77455 if ($this->getTypeCheck()->propertyExists($validationSchema, '$schema')) {
77456 $schemaSpec = $this->getTypeCheck()->propertyGet($validationSchema, '$schema');
77457 } else {
77458 $schemaSpec = self::DEFAULT_SCHEMA_SPEC;
77459 }
77460
77461
77462  $schemaStorage = $this->factory->getSchemaStorage();
77463 if (!$this->getTypeCheck()->isObject($schemaSpec)) {
77464 $schemaSpec = $schemaStorage->getSchema($schemaSpec);
77465 }
77466
77467
77468  $initialErrorCount = $this->numErrors();
77469 $initialConfig = $this->factory->getConfig();
77470 $initialContext = $this->factory->getErrorContext();
77471 $this->factory->removeConfig(self::CHECK_MODE_VALIDATE_SCHEMA | self::CHECK_MODE_APPLY_DEFAULTS);
77472 $this->factory->addConfig(self::CHECK_MODE_TYPE_CAST);
77473 $this->factory->setErrorContext(Validator::ERROR_SCHEMA_VALIDATION);
77474
77475
77476  try {
77477 $this->check($validationSchema, $schemaSpec);
77478 } catch (\Exception $e) {
77479 if ($this->factory->getConfig(self::CHECK_MODE_EXCEPTIONS)) {
77480 throw new InvalidSchemaException('Schema did not pass validation', 0, $e);
77481 }
77482 }
77483 if ($this->numErrors() > $initialErrorCount) {
77484 $this->addError($path, 'Schema is not valid', 'schema');
77485 }
77486
77487
77488  $this->factory->setConfig($initialConfig);
77489 $this->factory->setErrorContext($initialContext);
77490 }
77491
77492
77493  $this->checkUndefined($element, $validationSchema, $path, $i);
77494 }
77495 }
77496 <?php
77497
77498
77499
77500
77501
77502
77503
77504
77505 namespace JsonSchema\Constraints;
77506
77507 use JsonSchema\Entity\JsonPointer;
77508
77509
77510
77511
77512
77513
77514
77515 class StringConstraint extends Constraint
77516 {
77517
77518
77519
77520 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
77521 {
77522
77523  if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
77524 $this->addError($path, 'Must be at most ' . $schema->maxLength . ' characters long', 'maxLength', array(
77525 'maxLength' => $schema->maxLength,
77526 ));
77527 }
77528
77529
77530  if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
77531 $this->addError($path, 'Must be at least ' . $schema->minLength . ' characters long', 'minLength', array(
77532 'minLength' => $schema->minLength,
77533 ));
77534 }
77535
77536
77537  if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#u', $element)) {
77538 $this->addError($path, 'Does not match the regex pattern ' . $schema->pattern, 'pattern', array(
77539 'pattern' => $schema->pattern,
77540 ));
77541 }
77542
77543 $this->checkFormat($element, $schema, $path, $i);
77544 }
77545
77546 private function strlen($string)
77547 {
77548 if (extension_loaded('mbstring')) {
77549 return mb_strlen($string, mb_detect_encoding($string));
77550 }
77551
77552
77553  return strlen($string); 
77554  }
77555 }
77556 <?php
77557
77558 namespace JsonSchema\Constraints\TypeCheck;
77559
77560 class LooseTypeCheck implements TypeCheckInterface
77561 {
77562 public static function isObject($value)
77563 {
77564 return
77565 is_object($value) ||
77566 (is_array($value) && (count($value) == 0 || self::isAssociativeArray($value)));
77567 }
77568
77569 public static function isArray($value)
77570 {
77571 return
77572 is_array($value) &&
77573 (count($value) == 0 || !self::isAssociativeArray($value));
77574 }
77575
77576 public static function propertyGet($value, $property)
77577 {
77578 if (is_object($value)) {
77579 return $value->{$property};
77580 }
77581
77582 return $value[$property];
77583 }
77584
77585 public static function propertySet(&$value, $property, $data)
77586 {
77587 if (is_object($value)) {
77588 $value->{$property} = $data;
77589 } else {
77590 $value[$property] = $data;
77591 }
77592 }
77593
77594 public static function propertyExists($value, $property)
77595 {
77596 if (is_object($value)) {
77597 return property_exists($value, $property);
77598 }
77599
77600 return array_key_exists($property, $value);
77601 }
77602
77603 public static function propertyCount($value)
77604 {
77605 if (is_object($value)) {
77606 return count(get_object_vars($value));
77607 }
77608
77609 return count($value);
77610 }
77611
77612
77613
77614
77615
77616
77617
77618
77619 private static function isAssociativeArray($arr)
77620 {
77621 return array_keys($arr) !== range(0, count($arr) - 1);
77622 }
77623 }
77624 <?php
77625
77626 namespace JsonSchema\Constraints\TypeCheck;
77627
77628 class StrictTypeCheck implements TypeCheckInterface
77629 {
77630 public static function isObject($value)
77631 {
77632 return is_object($value);
77633 }
77634
77635 public static function isArray($value)
77636 {
77637 return is_array($value);
77638 }
77639
77640 public static function propertyGet($value, $property)
77641 {
77642 return $value->{$property};
77643 }
77644
77645 public static function propertySet(&$value, $property, $data)
77646 {
77647 $value->{$property} = $data;
77648 }
77649
77650 public static function propertyExists($value, $property)
77651 {
77652 return property_exists($value, $property);
77653 }
77654
77655 public static function propertyCount($value)
77656 {
77657 return count(get_object_vars($value));
77658 }
77659 }
77660 <?php
77661
77662 namespace JsonSchema\Constraints\TypeCheck;
77663
77664 interface TypeCheckInterface
77665 {
77666 public static function isObject($value);
77667
77668 public static function isArray($value);
77669
77670 public static function propertyGet($value, $property);
77671
77672 public static function propertySet(&$value, $property, $data);
77673
77674 public static function propertyExists($value, $property);
77675
77676 public static function propertyCount($value);
77677 }
77678 <?php
77679
77680
77681
77682
77683
77684
77685
77686
77687 namespace JsonSchema\Constraints;
77688
77689 use JsonSchema\Entity\JsonPointer;
77690 use JsonSchema\Exception\InvalidArgumentException;
77691 use UnexpectedValueException as StandardUnexpectedValueException;
77692
77693
77694
77695
77696
77697
77698
77699 class TypeConstraint extends Constraint
77700 {
77701
77702
77703
77704 public static $wording = array(
77705 'integer' => 'an integer',
77706 'number' => 'a number',
77707 'boolean' => 'a boolean',
77708 'object' => 'an object',
77709 'array' => 'an array',
77710 'string' => 'a string',
77711 'null' => 'a null',
77712 'any' => null, 
77713  0 => null, 
77714  );
77715
77716
77717
77718
77719 public function check(&$value = null, $schema = null, JsonPointer $path = null, $i = null)
77720 {
77721 $type = isset($schema->type) ? $schema->type : null;
77722 $isValid = false;
77723 $wording = array();
77724
77725 if (is_array($type)) {
77726 $this->validateTypesArray($value, $type, $wording, $isValid, $path);
77727 } elseif (is_object($type)) {
77728 $this->checkUndefined($value, $type, $path);
77729
77730 return;
77731 } else {
77732 $isValid = $this->validateType($value, $type);
77733 }
77734
77735 if ($isValid === false) {
77736 if (!is_array($type)) {
77737 $this->validateTypeNameWording($type);
77738 $wording[] = self::$wording[$type];
77739 }
77740 $this->addError($path, ucwords(gettype($value)) . ' value found, but ' .
77741 $this->implodeWith($wording, ', ', 'or') . ' is required', 'type');
77742 }
77743 }
77744
77745
77746
77747
77748
77749
77750
77751
77752
77753
77754
77755
77756 protected function validateTypesArray(&$value, array $type, &$validTypesWording, &$isValid, $path)
77757 {
77758 foreach ($type as $tp) {
77759
77760  
77761  if (is_object($tp)) {
77762 if (!$isValid) {
77763 $validator = $this->factory->createInstanceFor('type');
77764 $subSchema = new \stdClass();
77765 $subSchema->type = $tp;
77766 $validator->check($value, $subSchema, $path, null);
77767 $error = $validator->getErrors();
77768 $isValid = !(bool) $error;
77769 $validTypesWording[] = self::$wording['object'];
77770 }
77771 } else {
77772 $this->validateTypeNameWording($tp);
77773 $validTypesWording[] = self::$wording[$tp];
77774 if (!$isValid) {
77775 $isValid = $this->validateType($value, $tp);
77776 }
77777 }
77778 }
77779 }
77780
77781
77782
77783
77784
77785
77786
77787
77788
77789
77790
77791
77792 protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = false)
77793 {
77794 if ($listEnd === false || !isset($elements[1])) {
77795 return implode($delimiter, $elements);
77796 }
77797 $lastElement = array_slice($elements, -1);
77798 $firsElements = join($delimiter, array_slice($elements, 0, -1));
77799 $implodedElements = array_merge(array($firsElements), $lastElement);
77800
77801 return join(" $listEnd ", $implodedElements);
77802 }
77803
77804
77805
77806
77807
77808
77809
77810
77811
77812 protected function validateTypeNameWording($type)
77813 {
77814 if (!isset(self::$wording[$type])) {
77815 throw new StandardUnexpectedValueException(
77816 sprintf(
77817 'No wording for %s available, expected wordings are: [%s]',
77818 var_export($type, true),
77819 implode(', ', array_filter(self::$wording)))
77820 );
77821 }
77822 }
77823
77824
77825
77826
77827
77828
77829
77830
77831
77832
77833
77834 protected function validateType(&$value, $type)
77835 {
77836
77837  if (!$type) {
77838 return true;
77839 }
77840
77841 if ('any' === $type) {
77842 return true;
77843 }
77844
77845 if ('object' === $type) {
77846 return $this->getTypeCheck()->isObject($value);
77847 }
77848
77849 if ('array' === $type) {
77850 return $this->getTypeCheck()->isArray($value);
77851 }
77852
77853 $coerce = $this->factory->getConfig(Constraint::CHECK_MODE_COERCE_TYPES);
77854
77855 if ('integer' === $type) {
77856 if ($coerce) {
77857 $value = $this->toInteger($value);
77858 }
77859
77860 return is_int($value);
77861 }
77862
77863 if ('number' === $type) {
77864 if ($coerce) {
77865 $value = $this->toNumber($value);
77866 }
77867
77868 return is_numeric($value) && !is_string($value);
77869 }
77870
77871 if ('boolean' === $type) {
77872 if ($coerce) {
77873 $value = $this->toBoolean($value);
77874 }
77875
77876 return is_bool($value);
77877 }
77878
77879 if ('string' === $type) {
77880 return is_string($value);
77881 }
77882
77883 if ('email' === $type) {
77884 return is_string($value);
77885 }
77886
77887 if ('null' === $type) {
77888 return is_null($value);
77889 }
77890
77891 throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
77892 }
77893
77894
77895
77896
77897
77898
77899
77900
77901 protected function toBoolean($value)
77902 {
77903 if ($value === 'true') {
77904 return true;
77905 }
77906
77907 if ($value === 'false') {
77908 return false;
77909 }
77910
77911 return $value;
77912 }
77913
77914
77915
77916
77917
77918
77919
77920
77921 protected function toNumber($value)
77922 {
77923 if (is_numeric($value)) {
77924 return $value + 0; 
77925  }
77926
77927 return $value;
77928 }
77929
77930 protected function toInteger($value)
77931 {
77932 if (is_numeric($value) && (int) $value == $value) {
77933 return (int) $value; 
77934  }
77935
77936 return $value;
77937 }
77938 }
77939 <?php
77940
77941
77942
77943
77944
77945
77946
77947
77948 namespace JsonSchema\Constraints;
77949
77950 use JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
77951 use JsonSchema\Entity\JsonPointer;
77952 use JsonSchema\Exception\ValidationException;
77953 use JsonSchema\Uri\UriResolver;
77954
77955
77956
77957
77958
77959
77960
77961 class UndefinedConstraint extends Constraint
77962 {
77963
77964
77965
77966 protected $appliedDefaults = array();
77967
77968
77969
77970
77971 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
77972 {
77973 if (is_null($schema) || !is_object($schema)) {
77974 return;
77975 }
77976
77977 $path = $this->incrementPath($path ?: new JsonPointer(''), $i);
77978 if ($fromDefault) {
77979 $path->setFromDefault();
77980 }
77981
77982
77983  $this->validateCommonProperties($value, $schema, $path, $i);
77984
77985
77986  $this->validateOfProperties($value, $schema, $path, '');
77987
77988
77989  $this->validateTypes($value, $schema, $path, $i);
77990 }
77991
77992
77993
77994
77995
77996
77997
77998
77999
78000 public function validateTypes(&$value, $schema = null, JsonPointer $path, $i = null)
78001 {
78002
78003  if ($this->getTypeCheck()->isArray($value)) {
78004 $this->checkArray($value, $schema, $path, $i);
78005 }
78006
78007
78008  if (LooseTypeCheck::isObject($value)) { 
78009  
78010  
78011  $this->checkObject(
78012 $value,
78013 $schema,
78014 $path,
78015 isset($schema->properties) ? $schema->properties : null,
78016 isset($schema->additionalProperties) ? $schema->additionalProperties : null,
78017 isset($schema->patternProperties) ? $schema->patternProperties : null,
78018 $this->appliedDefaults
78019 );
78020 }
78021
78022
78023  if (is_string($value)) {
78024 $this->checkString($value, $schema, $path, $i);
78025 }
78026
78027
78028  if (is_numeric($value)) {
78029 $this->checkNumber($value, $schema, $path, $i);
78030 }
78031
78032
78033  if (isset($schema->enum)) {
78034 $this->checkEnum($value, $schema, $path, $i);
78035 }
78036 }
78037
78038
78039
78040
78041
78042
78043
78044
78045
78046 protected function validateCommonProperties(&$value, $schema = null, JsonPointer $path, $i = '')
78047 {
78048
78049  if (isset($schema->extends)) {
78050 if (is_string($schema->extends)) {
78051 $schema->extends = $this->validateUri($schema, $schema->extends);
78052 }
78053 if (is_array($schema->extends)) {
78054 foreach ($schema->extends as $extends) {
78055 $this->checkUndefined($value, $extends, $path, $i);
78056 }
78057 } else {
78058 $this->checkUndefined($value, $schema->extends, $path, $i);
78059 }
78060 }
78061
78062
78063  if (!$path->fromDefault()) {
78064 $this->applyDefaultValues($value, $schema, $path);
78065 }
78066
78067
78068  if ($this->getTypeCheck()->isObject($value)) {
78069 if (!($value instanceof self) && isset($schema->required) && is_array($schema->required)) {
78070
78071  foreach ($schema->required as $required) {
78072 if (!$this->getTypeCheck()->propertyExists($value, $required)) {
78073 $this->addError(
78074 $this->incrementPath($path ?: new JsonPointer(''), $required),
78075 'The property ' . $required . ' is required',
78076 'required'
78077 );
78078 }
78079 }
78080 } elseif (isset($schema->required) && !is_array($schema->required)) {
78081
78082  if ($schema->required && $value instanceof self) {
78083 $propertyPaths = $path->getPropertyPaths();
78084 $propertyName = end($propertyPaths);
78085 $this->addError(
78086 $path,
78087 'The property ' . $propertyName . ' is required',
78088 'required'
78089 );
78090 }
78091 }
78092 }
78093
78094
78095  if (!($value instanceof self)) {
78096 $this->checkType($value, $schema, $path, $i);
78097 }
78098
78099
78100  if (isset($schema->disallow)) {
78101 $initErrors = $this->getErrors();
78102
78103 $typeSchema = new \stdClass();
78104 $typeSchema->type = $schema->disallow;
78105 $this->checkType($value, $typeSchema, $path);
78106
78107
78108  if (count($this->getErrors()) == count($initErrors)) {
78109 $this->addError($path, 'Disallowed value was matched', 'disallow');
78110 } else {
78111 $this->errors = $initErrors;
78112 }
78113 }
78114
78115 if (isset($schema->not)) {
78116 $initErrors = $this->getErrors();
78117 $this->checkUndefined($value, $schema->not, $path, $i);
78118
78119
78120  if (count($this->getErrors()) == count($initErrors)) {
78121 $this->addError($path, 'Matched a schema which it should not', 'not');
78122 } else {
78123 $this->errors = $initErrors;
78124 }
78125 }
78126
78127
78128  if (isset($schema->dependencies) && $this->getTypeCheck()->isObject($value)) {
78129 $this->validateDependencies($value, $schema->dependencies, $path);
78130 }
78131 }
78132
78133
78134
78135
78136
78137
78138
78139
78140
78141
78142 private function shouldApplyDefaultValue($requiredOnly, $schema, $name = null, $parentSchema = null)
78143 {
78144
78145  if (!$requiredOnly) {
78146 return true;
78147 }
78148
78149  if (
78150 $name !== null
78151 && isset($parentSchema->required)
78152 && is_array($parentSchema->required)
78153 && in_array($name, $parentSchema->required)
78154 ) {
78155 return true;
78156 }
78157
78158  if (isset($schema->required) && !is_array($schema->required) && $schema->required) {
78159 return true;
78160 }
78161
78162  return false;
78163 }
78164
78165
78166
78167
78168
78169
78170
78171
78172 protected function applyDefaultValues(&$value, $schema, $path)
78173 {
78174
78175  if (!$this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
78176 return;
78177 }
78178
78179
78180  $requiredOnly = $this->factory->getConfig(self::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);
78181 if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
78182
78183  foreach ($schema->properties as $currentProperty => $propertyDefinition) {
78184 if (
78185 !LooseTypeCheck::propertyExists($value, $currentProperty)
78186 && property_exists($propertyDefinition, 'default')
78187 && $this->shouldApplyDefaultValue($requiredOnly, $propertyDefinition, $currentProperty, $schema)
78188 ) {
78189
78190  if (is_object($propertyDefinition->default)) {
78191 LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
78192 } else {
78193 LooseTypeCheck::propertySet($value, $currentProperty, $propertyDefinition->default);
78194 }
78195 $this->appliedDefaults[] = $currentProperty;
78196 }
78197 }
78198 } elseif (isset($schema->items) && LooseTypeCheck::isArray($value)) {
78199 $items = array();
78200 if (LooseTypeCheck::isArray($schema->items)) {
78201 $items = $schema->items;
78202 } elseif (isset($schema->minItems) && count($value) < $schema->minItems) {
78203 $items = array_fill(count($value), $schema->minItems - count($value), $schema->items);
78204 }
78205
78206  foreach ($items as $currentItem => $itemDefinition) {
78207 if (
78208 !array_key_exists($currentItem, $value)
78209 && property_exists($itemDefinition, 'default')
78210 && $this->shouldApplyDefaultValue($requiredOnly, $itemDefinition)) {
78211 if (is_object($itemDefinition->default)) {
78212 $value[$currentItem] = clone $itemDefinition->default;
78213 } else {
78214 $value[$currentItem] = $itemDefinition->default;
78215 }
78216 }
78217 $path->setFromDefault();
78218 }
78219 } elseif (
78220 $value instanceof self
78221 && property_exists($schema, 'default')
78222 && $this->shouldApplyDefaultValue($requiredOnly, $schema)) {
78223
78224  $value = is_object($schema->default) ? clone $schema->default : $schema->default;
78225 $path->setFromDefault();
78226 }
78227 }
78228
78229
78230
78231
78232
78233
78234
78235
78236
78237 protected function validateOfProperties(&$value, $schema, JsonPointer $path, $i = '')
78238 {
78239
78240  if ($value instanceof self) {
78241 return;
78242 }
78243
78244 if (isset($schema->allOf)) {
78245 $isValid = true;
78246 foreach ($schema->allOf as $allOf) {
78247 $initErrors = $this->getErrors();
78248 $this->checkUndefined($value, $allOf, $path, $i);
78249 $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
78250 }
78251 if (!$isValid) {
78252 $this->addError($path, 'Failed to match all schemas', 'allOf');
78253 }
78254 }
78255
78256 if (isset($schema->anyOf)) {
78257 $isValid = false;
78258 $startErrors = $this->getErrors();
78259 $caughtException = null;
78260 foreach ($schema->anyOf as $anyOf) {
78261 $initErrors = $this->getErrors();
78262 try {
78263 $this->checkUndefined($value, $anyOf, $path, $i);
78264 if ($isValid = (count($this->getErrors()) == count($initErrors))) {
78265 break;
78266 }
78267 } catch (ValidationException $e) {
78268 $isValid = false;
78269 }
78270 }
78271 if (!$isValid) {
78272 $this->addError($path, 'Failed to match at least one schema', 'anyOf');
78273 } else {
78274 $this->errors = $startErrors;
78275 }
78276 }
78277
78278 if (isset($schema->oneOf)) {
78279 $allErrors = array();
78280 $matchedSchemas = 0;
78281 $startErrors = $this->getErrors();
78282 foreach ($schema->oneOf as $oneOf) {
78283 try {
78284 $this->errors = array();
78285 $this->checkUndefined($value, $oneOf, $path, $i);
78286 if (count($this->getErrors()) == 0) {
78287 $matchedSchemas++;
78288 }
78289 $allErrors = array_merge($allErrors, array_values($this->getErrors()));
78290 } catch (ValidationException $e) {
78291
78292  
78293  }
78294 }
78295 if ($matchedSchemas !== 1) {
78296 $this->addErrors(array_merge($allErrors, $startErrors));
78297 $this->addError($path, 'Failed to match exactly one schema', 'oneOf');
78298 } else {
78299 $this->errors = $startErrors;
78300 }
78301 }
78302 }
78303
78304
78305
78306
78307
78308
78309
78310
78311
78312 protected function validateDependencies($value, $dependencies, JsonPointer $path, $i = '')
78313 {
78314 foreach ($dependencies as $key => $dependency) {
78315 if ($this->getTypeCheck()->propertyExists($value, $key)) {
78316 if (is_string($dependency)) {
78317
78318  if (!$this->getTypeCheck()->propertyExists($value, $dependency)) {
78319 $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
78320 }
78321 } elseif (is_array($dependency)) {
78322
78323  foreach ($dependency as $d) {
78324 if (!$this->getTypeCheck()->propertyExists($value, $d)) {
78325 $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
78326 }
78327 }
78328 } elseif (is_object($dependency)) {
78329
78330  $this->checkUndefined($value, $dependency, $path, $i);
78331 }
78332 }
78333 }
78334 }
78335
78336 protected function validateUri($schema, $schemaUri = null)
78337 {
78338 $resolver = new UriResolver();
78339 $retriever = $this->factory->getUriRetriever();
78340
78341 $jsonSchema = null;
78342 if ($resolver->isValid($schemaUri)) {
78343 $schemaId = property_exists($schema, 'id') ? $schema->id : null;
78344 $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
78345 }
78346
78347 return $jsonSchema;
78348 }
78349 }
78350 <?php
78351
78352
78353
78354
78355
78356
78357
78358
78359 namespace JsonSchema\Entity;
78360
78361 use JsonSchema\Exception\InvalidArgumentException;
78362
78363
78364
78365
78366
78367
78368 class JsonPointer
78369 {
78370
78371 private $filename;
78372
78373
78374 private $propertyPaths = array();
78375
78376
78377
78378
78379 private $fromDefault = false;
78380
78381
78382
78383
78384
78385
78386 public function __construct($value)
78387 {
78388 if (!is_string($value)) {
78389 throw new InvalidArgumentException('Ref value must be a string');
78390 }
78391
78392 $splitRef = explode('#', $value, 2);
78393 $this->filename = $splitRef[0];
78394 if (array_key_exists(1, $splitRef)) {
78395 $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
78396 }
78397 }
78398
78399
78400
78401
78402
78403
78404 private function decodePropertyPaths($propertyPathString)
78405 {
78406 $paths = array();
78407 foreach (explode('/', trim($propertyPathString, '/')) as $path) {
78408 $path = $this->decodePath($path);
78409 if (is_string($path) && '' !== $path) {
78410 $paths[] = $path;
78411 }
78412 }
78413
78414 return $paths;
78415 }
78416
78417
78418
78419
78420 private function encodePropertyPaths()
78421 {
78422 return array_map(
78423 array($this, 'encodePath'),
78424 $this->getPropertyPaths()
78425 );
78426 }
78427
78428
78429
78430
78431
78432
78433 private function decodePath($path)
78434 {
78435 return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
78436 }
78437
78438
78439
78440
78441
78442
78443 private function encodePath($path)
78444 {
78445 return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
78446 }
78447
78448
78449
78450
78451 public function getFilename()
78452 {
78453 return $this->filename;
78454 }
78455
78456
78457
78458
78459 public function getPropertyPaths()
78460 {
78461 return $this->propertyPaths;
78462 }
78463
78464
78465
78466
78467
78468
78469 public function withPropertyPaths(array $propertyPaths)
78470 {
78471 $new = clone $this;
78472 $new->propertyPaths = $propertyPaths;
78473
78474 return $new;
78475 }
78476
78477
78478
78479
78480 public function getPropertyPathAsString()
78481 {
78482 return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
78483 }
78484
78485
78486
78487
78488 public function __toString()
78489 {
78490 return $this->getFilename() . $this->getPropertyPathAsString();
78491 }
78492
78493
78494
78495
78496 public function setFromDefault()
78497 {
78498 $this->fromDefault = true;
78499 }
78500
78501
78502
78503
78504
78505
78506 public function fromDefault()
78507 {
78508 return $this->fromDefault;
78509 }
78510 }
78511 <?php
78512
78513 namespace JsonSchema\Exception;
78514
78515 interface ExceptionInterface
78516 {
78517 }
78518 <?php
78519
78520
78521
78522
78523
78524
78525
78526
78527 namespace JsonSchema\Exception;
78528
78529
78530
78531
78532 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
78533 {
78534 }
78535 <?php
78536
78537
78538
78539
78540
78541
78542
78543
78544 namespace JsonSchema\Exception;
78545
78546
78547
78548
78549 class InvalidConfigException extends RuntimeException
78550 {
78551 }
78552 <?php
78553
78554
78555
78556
78557
78558
78559
78560
78561 namespace JsonSchema\Exception;
78562
78563
78564
78565
78566 class InvalidSchemaException extends RuntimeException
78567 {
78568 }
78569 <?php
78570
78571
78572
78573
78574
78575
78576
78577
78578 namespace JsonSchema\Exception;
78579
78580
78581
78582
78583 class InvalidSchemaMediaTypeException extends RuntimeException
78584 {
78585 }
78586 <?php
78587
78588
78589
78590
78591
78592
78593
78594
78595 namespace JsonSchema\Exception;
78596
78597
78598
78599
78600 class InvalidSourceUriException extends InvalidArgumentException
78601 {
78602 }
78603 <?php
78604
78605
78606
78607
78608
78609
78610
78611
78612 namespace JsonSchema\Exception;
78613
78614
78615
78616
78617 class JsonDecodingException extends RuntimeException
78618 {
78619 public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
78620 {
78621 switch ($code) {
78622 case JSON_ERROR_DEPTH:
78623 $message = 'The maximum stack depth has been exceeded';
78624 break;
78625 case JSON_ERROR_STATE_MISMATCH:
78626 $message = 'Invalid or malformed JSON';
78627 break;
78628 case JSON_ERROR_CTRL_CHAR:
78629 $message = 'Control character error, possibly incorrectly encoded';
78630 break;
78631 case JSON_ERROR_UTF8:
78632 $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
78633 break;
78634 case JSON_ERROR_SYNTAX:
78635 $message = 'JSON syntax is malformed';
78636 break;
78637 default:
78638 $message = 'Syntax error';
78639 }
78640 parent::__construct($message, $code, $previous);
78641 }
78642 }
78643 <?php
78644
78645
78646
78647
78648
78649
78650
78651
78652 namespace JsonSchema\Exception;
78653
78654
78655
78656
78657 class ResourceNotFoundException extends RuntimeException
78658 {
78659 }
78660 <?php
78661
78662
78663
78664
78665
78666
78667
78668
78669 namespace JsonSchema\Exception;
78670
78671
78672
78673
78674 class RuntimeException extends \RuntimeException implements ExceptionInterface
78675 {
78676 }
78677 <?php
78678
78679
78680
78681
78682
78683
78684
78685
78686 namespace JsonSchema\Exception;
78687
78688
78689
78690
78691
78692
78693 class UnresolvableJsonPointerException extends InvalidArgumentException
78694 {
78695 }
78696 <?php
78697
78698
78699
78700
78701
78702
78703
78704
78705 namespace JsonSchema\Exception;
78706
78707
78708
78709
78710 class UriResolverException extends RuntimeException
78711 {
78712 }
78713 <?php
78714
78715
78716
78717
78718
78719
78720
78721
78722 namespace JsonSchema\Exception;
78723
78724 class ValidationException extends RuntimeException
78725 {
78726 }
78727 <?php
78728
78729
78730
78731
78732
78733
78734
78735
78736 namespace JsonSchema\Iterator;
78737
78738
78739
78740
78741
78742
78743 class ObjectIterator implements \Iterator, \Countable
78744 {
78745
78746 private $object;
78747
78748
78749 private $position = 0;
78750
78751
78752 private $data = array();
78753
78754
78755 private $initialized = false;
78756
78757
78758
78759
78760 public function __construct($object)
78761 {
78762 $this->object = $object;
78763 }
78764
78765
78766
78767
78768 public function current()
78769 {
78770 $this->initialize();
78771
78772 return $this->data[$this->position];
78773 }
78774
78775
78776
78777
78778 public function next()
78779 {
78780 $this->initialize();
78781 $this->position++;
78782 }
78783
78784
78785
78786
78787 public function key()
78788 {
78789 $this->initialize();
78790
78791 return $this->position;
78792 }
78793
78794
78795
78796
78797 public function valid()
78798 {
78799 $this->initialize();
78800
78801 return isset($this->data[$this->position]);
78802 }
78803
78804
78805
78806
78807 public function rewind()
78808 {
78809 $this->initialize();
78810 $this->position = 0;
78811 }
78812
78813
78814
78815
78816 public function count()
78817 {
78818 $this->initialize();
78819
78820 return count($this->data);
78821 }
78822
78823
78824
78825
78826 private function initialize()
78827 {
78828 if (!$this->initialized) {
78829 $this->data = $this->buildDataFromObject($this->object);
78830 $this->initialized = true;
78831 }
78832 }
78833
78834
78835
78836
78837
78838
78839 private function buildDataFromObject($object)
78840 {
78841 $result = array();
78842
78843 $stack = new \SplStack();
78844 $stack->push($object);
78845
78846 while (!$stack->isEmpty()) {
78847 $current = $stack->pop();
78848 if (is_object($current)) {
78849 array_push($result, $current);
78850 }
78851
78852 foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
78853 if (is_object($propertyValue) || is_array($propertyValue)) {
78854 $stack->push($propertyValue);
78855 }
78856 }
78857 }
78858
78859 return $result;
78860 }
78861
78862
78863
78864
78865
78866
78867 private function getDataFromItem($item)
78868 {
78869 if (!is_object($item) && !is_array($item)) {
78870 return array();
78871 }
78872
78873 return is_object($item) ? get_object_vars($item) : $item;
78874 }
78875 }
78876 <?php
78877
78878 namespace JsonSchema;
78879
78880 class Rfc3339
78881 {
78882 const REGEX = '/^(\d{4}-\d{2}-\d{2}[T ]{1}\d{2}:\d{2}:\d{2})(\.\d+)?(Z|([+-]\d{2}):?(\d{2}))$/';
78883
78884
78885
78886
78887
78888
78889
78890
78891 public static function createFromString($string)
78892 {
78893 if (!preg_match(self::REGEX, strtoupper($string), $matches)) {
78894 return null;
78895 }
78896
78897 $dateAndTime = $matches[1];
78898 $microseconds = $matches[2] ?: '.000000';
78899 $timeZone = 'Z' !== $matches[3] ? $matches[4] . ':' . $matches[5] : '+00:00';
78900 $dateFormat = strpos($dateAndTime, 'T') === false ? 'Y-m-d H:i:s.uP' : 'Y-m-d\TH:i:s.uP';
78901 $dateTime = \DateTime::createFromFormat($dateFormat, $dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
78902
78903 return $dateTime ?: null;
78904 }
78905 }
78906 <?php
78907
78908 namespace JsonSchema;
78909
78910 use JsonSchema\Constraints\BaseConstraint;
78911 use JsonSchema\Entity\JsonPointer;
78912 use JsonSchema\Exception\UnresolvableJsonPointerException;
78913 use JsonSchema\Uri\UriResolver;
78914 use JsonSchema\Uri\UriRetriever;
78915
78916 class SchemaStorage implements SchemaStorageInterface
78917 {
78918 const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema/';
78919
78920 protected $uriRetriever;
78921 protected $uriResolver;
78922 protected $schemas = array();
78923
78924 public function __construct(
78925 UriRetrieverInterface $uriRetriever = null,
78926 UriResolverInterface $uriResolver = null
78927 ) {
78928 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
78929 $this->uriResolver = $uriResolver ?: new UriResolver();
78930 }
78931
78932
78933
78934
78935 public function getUriRetriever()
78936 {
78937 return $this->uriRetriever;
78938 }
78939
78940
78941
78942
78943 public function getUriResolver()
78944 {
78945 return $this->uriResolver;
78946 }
78947
78948
78949
78950
78951 public function addSchema($id, $schema = null)
78952 {
78953 if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) {
78954
78955  
78956  
78957  $schema = $this->uriRetriever->retrieve($id);
78958 }
78959
78960
78961  if (is_array($schema)) {
78962 $schema = BaseConstraint::arrayToObjectRecursive($schema);
78963 }
78964
78965
78966  
78967  if (is_object($schema) && property_exists($schema, 'id')) {
78968 if ($schema->id == 'http://json-schema.org/draft-04/schema#') {
78969 $schema->properties->id->format = 'uri-reference';
78970 } elseif ($schema->id == 'http://json-schema.org/draft-03/schema#') {
78971 $schema->properties->id->format = 'uri-reference';
78972 $schema->properties->{'$ref'}->format = 'uri-reference';
78973 }
78974 }
78975
78976
78977  $this->expandRefs($schema, $id);
78978
78979 $this->schemas[$id] = $schema;
78980 }
78981
78982
78983
78984
78985
78986
78987
78988 private function expandRefs(&$schema, $base = null)
78989 {
78990 if (!is_object($schema)) {
78991 if (is_array($schema)) {
78992 foreach ($schema as &$member) {
78993 $this->expandRefs($member, $base);
78994 }
78995 }
78996
78997 return;
78998 }
78999
79000 if (property_exists($schema, 'id') && is_string($schema->id) && $base != $schema->id) {
79001 $base = $this->uriResolver->resolve($schema->id, $base);
79002 }
79003
79004 if (property_exists($schema, '$ref') && is_string($schema->{'$ref'})) {
79005 $refPointer = new JsonPointer($this->uriResolver->resolve($schema->{'$ref'}, $base));
79006 $schema->{'$ref'} = (string) $refPointer;
79007 }
79008
79009 foreach ($schema as &$member) {
79010 $this->expandRefs($member, $base);
79011 }
79012 }
79013
79014
79015
79016
79017 public function getSchema($id)
79018 {
79019 if (!array_key_exists($id, $this->schemas)) {
79020 $this->addSchema($id);
79021 }
79022
79023 return $this->schemas[$id];
79024 }
79025
79026
79027
79028
79029 public function resolveRef($ref)
79030 {
79031 $jsonPointer = new JsonPointer($ref);
79032
79033
79034  $fileName = $jsonPointer->getFilename();
79035 if (!strlen($fileName)) {
79036 throw new UnresolvableJsonPointerException(sprintf(
79037 "Could not resolve fragment '%s': no file is defined",
79038 $jsonPointer->getPropertyPathAsString()
79039 ));
79040 }
79041
79042
79043  $refSchema = $this->getSchema($fileName);
79044 foreach ($jsonPointer->getPropertyPaths() as $path) {
79045 if (is_object($refSchema) && property_exists($refSchema, $path)) {
79046 $refSchema = $this->resolveRefSchema($refSchema->{$path});
79047 } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) {
79048 $refSchema = $this->resolveRefSchema($refSchema[$path]);
79049 } else {
79050 throw new UnresolvableJsonPointerException(sprintf(
79051 'File: %s is found, but could not resolve fragment: %s',
79052 $jsonPointer->getFilename(),
79053 $jsonPointer->getPropertyPathAsString()
79054 ));
79055 }
79056 }
79057
79058 return $refSchema;
79059 }
79060
79061
79062
79063
79064 public function resolveRefSchema($refSchema)
79065 {
79066 if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) {
79067 $newSchema = $this->resolveRef($refSchema->{'$ref'});
79068 $refSchema = (object) (get_object_vars($refSchema) + get_object_vars($newSchema));
79069 unset($refSchema->{'$ref'});
79070 }
79071
79072 return $refSchema;
79073 }
79074 }
79075 <?php
79076
79077 namespace JsonSchema;
79078
79079 interface SchemaStorageInterface
79080 {
79081
79082
79083
79084
79085
79086
79087 public function addSchema($id, $schema = null);
79088
79089
79090
79091
79092
79093
79094
79095
79096 public function getSchema($id);
79097
79098
79099
79100
79101
79102
79103
79104
79105 public function resolveRef($ref);
79106
79107
79108
79109
79110
79111
79112
79113
79114 public function resolveRefSchema($refSchema);
79115 }
79116 <?php
79117
79118
79119
79120
79121
79122
79123 namespace JsonSchema\Uri\Retrievers;
79124
79125
79126
79127
79128
79129
79130
79131 abstract class AbstractRetriever implements UriRetrieverInterface
79132 {
79133
79134
79135
79136
79137
79138 protected $contentType;
79139
79140
79141
79142
79143
79144
79145 public function getContentType()
79146 {
79147 return $this->contentType;
79148 }
79149 }
79150 <?php
79151
79152
79153
79154
79155
79156
79157
79158
79159 namespace JsonSchema\Uri\Retrievers;
79160
79161 use JsonSchema\Exception\RuntimeException;
79162 use JsonSchema\Validator;
79163
79164
79165
79166
79167
79168
79169 class Curl extends AbstractRetriever
79170 {
79171 protected $messageBody;
79172
79173 public function __construct()
79174 {
79175 if (!function_exists('curl_init')) {
79176
79177  throw new RuntimeException('cURL not installed'); 
79178  }
79179 }
79180
79181
79182
79183
79184
79185
79186 public function retrieve($uri)
79187 {
79188 $ch = curl_init();
79189
79190 curl_setopt($ch, CURLOPT_URL, $uri);
79191 curl_setopt($ch, CURLOPT_HEADER, true);
79192 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
79193 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
79194
79195 $response = curl_exec($ch);
79196 if (false === $response) {
79197 throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
79198 }
79199
79200 $this->fetchMessageBody($response);
79201 $this->fetchContentType($response);
79202
79203 curl_close($ch);
79204
79205 return $this->messageBody;
79206 }
79207
79208
79209
79210
79211 private function fetchMessageBody($response)
79212 {
79213 preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
79214 $this->messageBody = $match[1];
79215 }
79216
79217
79218
79219
79220
79221
79222 protected function fetchContentType($response)
79223 {
79224 if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
79225 $this->contentType = trim($match[1]);
79226
79227 return true;
79228 }
79229
79230 return false;
79231 }
79232 }
79233 <?php
79234
79235
79236
79237
79238
79239
79240
79241
79242 namespace JsonSchema\Uri\Retrievers;
79243
79244 use JsonSchema\Exception\ResourceNotFoundException;
79245
79246
79247
79248
79249
79250
79251 class FileGetContents extends AbstractRetriever
79252 {
79253 protected $messageBody;
79254
79255
79256
79257
79258
79259
79260 public function retrieve($uri)
79261 {
79262 $errorMessage = null;
79263 set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
79264 $errorMessage = $errstr;
79265 });
79266 $response = file_get_contents($uri);
79267 restore_error_handler();
79268
79269 if ($errorMessage) {
79270 throw new ResourceNotFoundException($errorMessage);
79271 }
79272
79273 if (false === $response) {
79274 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
79275 }
79276
79277 if ($response == ''
79278 && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
79279 ) {
79280 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
79281 }
79282
79283 $this->messageBody = $response;
79284 if (!empty($http_response_header)) {
79285
79286  
79287  $this->fetchContentType($http_response_header); 
79288  } else { 
79289  
79290  $this->contentType = null;
79291 }
79292
79293 return $this->messageBody;
79294 }
79295
79296
79297
79298
79299
79300
79301 private function fetchContentType(array $headers)
79302 {
79303 foreach ($headers as $header) {
79304 if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
79305 return true;
79306 }
79307 }
79308
79309 return false;
79310 }
79311
79312
79313
79314
79315
79316
79317 protected static function getContentTypeMatchInHeader($header)
79318 {
79319 if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
79320 return trim($match[1]);
79321 }
79322
79323 return null;
79324 }
79325 }
79326 <?php
79327
79328 namespace JsonSchema\Uri\Retrievers;
79329
79330 use JsonSchema\Validator;
79331
79332
79333
79334
79335
79336
79337
79338
79339
79340
79341
79342
79343
79344 class PredefinedArray extends AbstractRetriever
79345 {
79346
79347
79348
79349
79350
79351 private $schemas;
79352
79353
79354
79355
79356
79357
79358
79359 public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
79360 {
79361 $this->schemas = $schemas;
79362 $this->contentType = $contentType;
79363 }
79364
79365
79366
79367
79368
79369
79370 public function retrieve($uri)
79371 {
79372 if (!array_key_exists($uri, $this->schemas)) {
79373 throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
79374 'The JSON schema "%s" was not found.',
79375 $uri
79376 ));
79377 }
79378
79379 return $this->schemas[$uri];
79380 }
79381 }
79382 <?php
79383
79384
79385
79386
79387
79388
79389
79390
79391 namespace JsonSchema\Uri\Retrievers;
79392
79393
79394
79395
79396
79397
79398 interface UriRetrieverInterface
79399 {
79400
79401
79402
79403
79404
79405
79406
79407
79408
79409 public function retrieve($uri);
79410
79411
79412
79413
79414
79415
79416 public function getContentType();
79417 }
79418 <?php
79419
79420
79421
79422
79423
79424
79425
79426
79427 namespace JsonSchema\Uri;
79428
79429 use JsonSchema\Exception\UriResolverException;
79430 use JsonSchema\UriResolverInterface;
79431
79432
79433
79434
79435
79436
79437 class UriResolver implements UriResolverInterface
79438 {
79439
79440
79441
79442
79443
79444
79445
79446 public function parse($uri)
79447 {
79448 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
79449
79450 $components = array();
79451 if (5 < count($match)) {
79452 $components = array(
79453 'scheme' => $match[2],
79454 'authority' => $match[4],
79455 'path' => $match[5]
79456 );
79457 }
79458 if (7 < count($match)) {
79459 $components['query'] = $match[7];
79460 }
79461 if (9 < count($match)) {
79462 $components['fragment'] = $match[9];
79463 }
79464
79465 return $components;
79466 }
79467
79468
79469
79470
79471
79472
79473
79474
79475 public function generate(array $components)
79476 {
79477 $uri = $components['scheme'] . '://'
79478 . $components['authority']
79479 . $components['path'];
79480
79481 if (array_key_exists('query', $components) && strlen($components['query'])) {
79482 $uri .= '?' . $components['query'];
79483 }
79484 if (array_key_exists('fragment', $components)) {
79485 $uri .= '#' . $components['fragment'];
79486 }
79487
79488 return $uri;
79489 }
79490
79491
79492
79493
79494 public function resolve($uri, $baseUri = null)
79495 {
79496
79497  if (
79498 !is_null($baseUri) &&
79499 !filter_var($baseUri, \FILTER_VALIDATE_URL) &&
79500 !preg_match('|^[^/]+://|u', $baseUri)
79501 ) {
79502 if (is_file($baseUri)) {
79503 $baseUri = 'file://' . realpath($baseUri);
79504 } elseif (is_dir($baseUri)) {
79505 $baseUri = 'file://' . realpath($baseUri) . '/';
79506 } else {
79507 $baseUri = 'file://' . getcwd() . '/' . $baseUri;
79508 }
79509 }
79510
79511 if ($uri == '') {
79512 return $baseUri;
79513 }
79514
79515 $components = $this->parse($uri);
79516 $path = $components['path'];
79517
79518 if (!empty($components['scheme'])) {
79519 return $uri;
79520 }
79521 $baseComponents = $this->parse($baseUri);
79522 $basePath = $baseComponents['path'];
79523
79524 $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
79525 if (isset($components['fragment'])) {
79526 $baseComponents['fragment'] = $components['fragment'];
79527 }
79528
79529 return $this->generate($baseComponents);
79530 }
79531
79532
79533
79534
79535
79536
79537
79538
79539
79540
79541
79542 public static function combineRelativePathWithBasePath($relativePath, $basePath)
79543 {
79544 $relativePath = self::normalizePath($relativePath);
79545 if ($relativePath == '') {
79546 return $basePath;
79547 }
79548 if ($relativePath[0] == '/') {
79549 return $relativePath;
79550 }
79551
79552 $basePathSegments = explode('/', $basePath);
79553
79554 preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
79555 $numLevelUp = strlen($match[0]) /3 + 1;
79556 if ($numLevelUp >= count($basePathSegments)) {
79557 throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
79558 }
79559
79560 $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
79561 $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
79562
79563 return implode('/', $basePathSegments) . '/' . $path;
79564 }
79565
79566
79567
79568
79569
79570
79571
79572
79573 private static function normalizePath($path)
79574 {
79575 $path = preg_replace('|((?<!\.)\./)*|', '', $path);
79576 $path = preg_replace('|//|', '/', $path);
79577
79578 return $path;
79579 }
79580
79581
79582
79583
79584
79585
79586 public function isValid($uri)
79587 {
79588 $components = $this->parse($uri);
79589
79590 return !empty($components);
79591 }
79592 }
79593 <?php
79594
79595
79596
79597
79598
79599
79600
79601
79602 namespace JsonSchema\Uri;
79603
79604 use JsonSchema\Exception\InvalidSchemaMediaTypeException;
79605 use JsonSchema\Exception\JsonDecodingException;
79606 use JsonSchema\Exception\ResourceNotFoundException;
79607 use JsonSchema\Uri\Retrievers\FileGetContents;
79608 use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
79609 use JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
79610 use JsonSchema\Validator;
79611
79612
79613
79614
79615
79616
79617 class UriRetriever implements BaseUriRetrieverInterface
79618 {
79619
79620
79621
79622 protected $translationMap = array(
79623
79624  '|^https?://json-schema.org/draft-(0[34])/schema#?|' => 'package://dist/schema/json-schema-draft-$1.json'
79625 );
79626
79627
79628
79629
79630 protected $uriRetriever = null;
79631
79632
79633
79634
79635
79636
79637 private $schemaCache = array();
79638
79639
79640
79641
79642
79643
79644
79645
79646
79647 public function confirmMediaType($uriRetriever, $uri)
79648 {
79649 $contentType = $uriRetriever->getContentType();
79650
79651 if (is_null($contentType)) {
79652
79653  return;
79654 }
79655
79656 if (in_array($contentType, array(Validator::SCHEMA_MEDIA_TYPE, 'application/json'))) {
79657 return;
79658 }
79659
79660 if (substr($uri, 0, 23) == 'http://json-schema.org/') {
79661
79662  return true;
79663 }
79664
79665 throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
79666 }
79667
79668
79669
79670
79671
79672
79673
79674
79675
79676 public function getUriRetriever()
79677 {
79678 if (is_null($this->uriRetriever)) {
79679 $this->setUriRetriever(new FileGetContents());
79680 }
79681
79682 return $this->uriRetriever;
79683 }
79684
79685
79686
79687
79688
79689
79690
79691
79692
79693
79694
79695
79696
79697
79698
79699 public function resolvePointer($jsonSchema, $uri)
79700 {
79701 $resolver = new UriResolver();
79702 $parsed = $resolver->parse($uri);
79703 if (empty($parsed['fragment'])) {
79704 return $jsonSchema;
79705 }
79706
79707 $path = explode('/', $parsed['fragment']);
79708 while ($path) {
79709 $pathElement = array_shift($path);
79710 if (!empty($pathElement)) {
79711 $pathElement = str_replace('~1', '/', $pathElement);
79712 $pathElement = str_replace('~0', '~', $pathElement);
79713 if (!empty($jsonSchema->$pathElement)) {
79714 $jsonSchema = $jsonSchema->$pathElement;
79715 } else {
79716 throw new ResourceNotFoundException(
79717 'Fragment "' . $parsed['fragment'] . '" not found'
79718 . ' in ' . $uri
79719 );
79720 }
79721
79722 if (!is_object($jsonSchema)) {
79723 throw new ResourceNotFoundException(
79724 'Fragment part "' . $pathElement . '" is no object '
79725 . ' in ' . $uri
79726 );
79727 }
79728 }
79729 }
79730
79731 return $jsonSchema;
79732 }
79733
79734
79735
79736
79737 public function retrieve($uri, $baseUri = null, $translate = true)
79738 {
79739 $resolver = new UriResolver();
79740 $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
79741
79742
79743  $arParts = $resolver->parse($resolvedUri);
79744 if (isset($arParts['fragment'])) {
79745 unset($arParts['fragment']);
79746 $fetchUri = $resolver->generate($arParts);
79747 }
79748
79749
79750  if ($translate) {
79751 $fetchUri = $this->translate($fetchUri);
79752 }
79753
79754 $jsonSchema = $this->loadSchema($fetchUri);
79755
79756
79757  $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
79758
79759 if ($jsonSchema instanceof \stdClass) {
79760 $jsonSchema->id = $resolvedUri;
79761 }
79762
79763 return $jsonSchema;
79764 }
79765
79766
79767
79768
79769
79770
79771
79772
79773
79774 protected function loadSchema($fetchUri)
79775 {
79776 if (isset($this->schemaCache[$fetchUri])) {
79777 return $this->schemaCache[$fetchUri];
79778 }
79779
79780 $uriRetriever = $this->getUriRetriever();
79781 $contents = $this->uriRetriever->retrieve($fetchUri);
79782 $this->confirmMediaType($uriRetriever, $fetchUri);
79783 $jsonSchema = json_decode($contents);
79784
79785 if (JSON_ERROR_NONE < $error = json_last_error()) {
79786 throw new JsonDecodingException($error);
79787 }
79788
79789 $this->schemaCache[$fetchUri] = $jsonSchema;
79790
79791 return $jsonSchema;
79792 }
79793
79794
79795
79796
79797
79798
79799
79800
79801 public function setUriRetriever(UriRetrieverInterface $uriRetriever)
79802 {
79803 $this->uriRetriever = $uriRetriever;
79804
79805 return $this;
79806 }
79807
79808
79809
79810
79811
79812
79813
79814
79815 public function parse($uri)
79816 {
79817 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
79818
79819 $components = array();
79820 if (5 < count($match)) {
79821 $components = array(
79822 'scheme' => $match[2],
79823 'authority' => $match[4],
79824 'path' => $match[5]
79825 );
79826 }
79827
79828 if (7 < count($match)) {
79829 $components['query'] = $match[7];
79830 }
79831
79832 if (9 < count($match)) {
79833 $components['fragment'] = $match[9];
79834 }
79835
79836 return $components;
79837 }
79838
79839
79840
79841
79842
79843
79844
79845
79846 public function generate(array $components)
79847 {
79848 $uri = $components['scheme'] . '://'
79849 . $components['authority']
79850 . $components['path'];
79851
79852 if (array_key_exists('query', $components)) {
79853 $uri .= $components['query'];
79854 }
79855
79856 if (array_key_exists('fragment', $components)) {
79857 $uri .= $components['fragment'];
79858 }
79859
79860 return $uri;
79861 }
79862
79863
79864
79865
79866
79867
79868
79869
79870
79871 public function resolve($uri, $baseUri = null)
79872 {
79873 $components = $this->parse($uri);
79874 $path = $components['path'];
79875
79876 if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
79877 return $uri;
79878 }
79879
79880 $baseComponents = $this->parse($baseUri);
79881 $basePath = $baseComponents['path'];
79882
79883 $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
79884
79885 return $this->generate($baseComponents);
79886 }
79887
79888
79889
79890
79891
79892
79893 public function isValid($uri)
79894 {
79895 $components = $this->parse($uri);
79896
79897 return !empty($components);
79898 }
79899
79900
79901
79902
79903 public function setTranslation($from, $to)
79904 {
79905 $this->translationMap[$from] = $to;
79906 }
79907
79908
79909
79910
79911 public function translate($uri)
79912 {
79913 foreach ($this->translationMap as $from => $to) {
79914 $uri = preg_replace($from, $to, $uri);
79915 }
79916
79917
79918  $uri = preg_replace('|^package://|', sprintf('file://%s/', realpath(__DIR__ . '/../../..')), $uri);
79919
79920 return $uri;
79921 }
79922 }
79923 <?php
79924
79925
79926
79927
79928
79929
79930
79931
79932 namespace JsonSchema;
79933
79934
79935
79936
79937 interface UriResolverInterface
79938 {
79939
79940
79941
79942
79943
79944
79945
79946
79947 public function resolve($uri, $baseUri = null);
79948 }
79949 <?php
79950
79951
79952
79953
79954
79955
79956
79957
79958 namespace JsonSchema;
79959
79960
79961
79962
79963 interface UriRetrieverInterface
79964 {
79965
79966
79967
79968
79969
79970
79971
79972
79973 public function retrieve($uri, $baseUri = null);
79974 }
79975 <?php
79976
79977
79978
79979
79980
79981
79982
79983
79984 namespace JsonSchema;
79985
79986 use JsonSchema\Constraints\BaseConstraint;
79987 use JsonSchema\Constraints\Constraint;
79988 use JsonSchema\Exception\InvalidConfigException;
79989 use JsonSchema\SchemaStorage;
79990
79991
79992
79993
79994
79995
79996
79997
79998
79999 class Validator extends BaseConstraint
80000 {
80001 const SCHEMA_MEDIA_TYPE = 'application/schema+json';
80002
80003 const ERROR_NONE = 0x00000000;
80004 const ERROR_ALL = 0xFFFFFFFF;
80005 const ERROR_DOCUMENT_VALIDATION = 0x00000001;
80006 const ERROR_SCHEMA_VALIDATION = 0x00000002;
80007
80008
80009
80010
80011
80012
80013
80014
80015
80016
80017 public function validate(&$value, $schema = null, $checkMode = null)
80018 {
80019
80020  if (is_array($schema)) {
80021 $schema = self::arrayToObjectRecursive($schema);
80022 }
80023
80024
80025  $initialCheckMode = $this->factory->getConfig();
80026 if ($checkMode !== null) {
80027 $this->factory->setConfig($checkMode);
80028 }
80029
80030
80031  if (is_object($schema) && property_exists($schema, 'id')) {
80032 $schemaURI = $schema->id;
80033 } else {
80034 $schemaURI = SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI;
80035 }
80036 $this->factory->getSchemaStorage()->addSchema($schemaURI, $schema);
80037
80038 $validator = $this->factory->createInstanceFor('schema');
80039 $validator->check(
80040 $value,
80041 $this->factory->getSchemaStorage()->getSchema($schemaURI)
80042 );
80043
80044 $this->factory->setConfig($initialCheckMode);
80045
80046 $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
80047
80048 return $validator->getErrorMask();
80049 }
80050
80051
80052
80053
80054 public function check($value, $schema)
80055 {
80056 return $this->validate($value, $schema);
80057 }
80058
80059
80060
80061
80062 public function coerce(&$value, $schema)
80063 {
80064 return $this->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
80065 }
80066 }
80067 Copyright (C) 2015 Composer
80068
80069 Permission is hereby granted, free of charge, to any person obtaining a copy of
80070 this software and associated documentation files (the "Software"), to deal in
80071 the Software without restriction, including without limitation the rights to
80072 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
80073 of the Software, and to permit persons to whom the Software is furnished to do
80074 so, subject to the following conditions:
80075
80076 The above copyright notice and this permission notice shall be included in all
80077 copies or substantial portions of the Software.
80078
80079 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
80080 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
80081 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
80082 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
80083 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
80084 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
80085 SOFTWARE.
80086 <?php
80087
80088
80089
80090
80091
80092
80093
80094
80095
80096
80097 namespace Composer\Spdx;
80098
80099 class SpdxLicenses
80100 {
80101
80102 const LICENSES_FILE = 'spdx-licenses.json';
80103
80104
80105 const EXCEPTIONS_FILE = 'spdx-exceptions.json';
80106
80107
80108
80109
80110
80111
80112
80113
80114
80115
80116
80117
80118
80119
80120 private $licenses;
80121
80122
80123
80124
80125 private $licensesExpression;
80126
80127
80128
80129
80130
80131
80132
80133
80134
80135
80136
80137
80138
80139
80140 private $exceptions;
80141
80142
80143
80144
80145 private $exceptionsExpression;
80146
80147 public function __construct()
80148 {
80149 $this->loadLicenses();
80150 $this->loadExceptions();
80151 }
80152
80153
80154
80155
80156
80157
80158
80159
80160
80161
80162
80163
80164
80165 public function getLicenseByIdentifier($identifier)
80166 {
80167 if (!isset($this->licenses[$identifier])) {
80168 return;
80169 }
80170
80171 $license = $this->licenses[$identifier];
80172 $license[3] = $license[2];
80173 $license[2] = 'https://spdx.org/licenses/' . $identifier . '.html#licenseText';
80174
80175 return $license;
80176 }
80177
80178
80179
80180
80181
80182
80183
80184
80185
80186
80187
80188
80189
80190 public function getExceptionByIdentifier($identifier)
80191 {
80192 if (!isset($this->exceptions[$identifier])) {
80193 return;
80194 }
80195
80196 $license = $this->exceptions[$identifier];
80197 $license[] = 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText';
80198
80199 return $license;
80200 }
80201
80202
80203
80204
80205
80206
80207
80208
80209 public function getIdentifierByName($name)
80210 {
80211 foreach ($this->licenses as $identifier => $licenseData) {
80212 if ($licenseData[0] === $name) {
80213 return $identifier;
80214 }
80215 }
80216
80217 foreach ($this->exceptions as $identifier => $licenseData) {
80218 if ($licenseData[0] === $name) {
80219 return $identifier;
80220 }
80221 }
80222 }
80223
80224
80225
80226
80227
80228
80229
80230
80231 public function isOsiApprovedByIdentifier($identifier)
80232 {
80233 return $this->licenses[$identifier][1];
80234 }
80235
80236
80237
80238
80239
80240
80241
80242
80243 public function isDeprecatedByIdentifier($identifier)
80244 {
80245 return $this->licenses[$identifier][2];
80246 }
80247
80248
80249
80250
80251
80252
80253
80254
80255 public function validate($license)
80256 {
80257 if (is_array($license)) {
80258 $count = count($license);
80259 if ($count !== count(array_filter($license, 'is_string'))) {
80260 throw new \InvalidArgumentException('Array of strings expected.');
80261 }
80262 $license = $count > 1 ? '(' . implode(' OR ', $license) . ')' : (string) reset($license);
80263 }
80264
80265 if (!is_string($license)) {
80266 throw new \InvalidArgumentException(sprintf(
80267 'Array or String expected, %s given.',
80268 gettype($license)
80269 ));
80270 }
80271
80272 return $this->isValidLicenseString($license);
80273 }
80274
80275
80276
80277
80278 public static function getResourcesDir()
80279 {
80280 return dirname(__DIR__) . '/res';
80281 }
80282
80283 private function loadLicenses()
80284 {
80285 if (null === $this->licenses) {
80286 $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
80287 $this->licenses = json_decode($json, true);
80288 }
80289 }
80290
80291 private function loadExceptions()
80292 {
80293 if (null === $this->exceptions) {
80294 $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
80295 $this->exceptions = json_decode($json, true);
80296 }
80297 }
80298
80299
80300
80301
80302 private function getLicensesExpression()
80303 {
80304 if (null === $this->licensesExpression) {
80305 $licenses = array_map('preg_quote', array_keys($this->licenses));
80306 rsort($licenses);
80307 $licenses = implode('|', $licenses);
80308 $this->licensesExpression = $licenses;
80309 }
80310
80311 return $this->licensesExpression;
80312 }
80313
80314
80315
80316
80317 private function getExceptionsExpression()
80318 {
80319 if (null === $this->exceptionsExpression) {
80320 $exceptions = array_map('preg_quote', array_keys($this->exceptions));
80321 rsort($exceptions);
80322 $exceptions = implode('|', $exceptions);
80323 $this->exceptionsExpression = $exceptions;
80324 }
80325
80326 return $this->exceptionsExpression;
80327 }
80328
80329
80330
80331
80332
80333
80334
80335
80336 private function isValidLicenseString($license)
80337 {
80338 if (isset($this->licenses[$license])) {
80339 return true;
80340 }
80341
80342 $licenses = $this->getLicensesExpression();
80343 $exceptions = $this->getExceptionsExpression();
80344
80345 $regex = <<<REGEX
80346 {
80347 (?(DEFINE)
80348     # idstring: 1*( ALPHA / DIGIT / - / . )
80349     (?<idstring>[\pL\pN.-]{1,})
80350
80351     # license-id: taken from list
80352     (?<licenseid>${licenses})
80353
80354     # license-exception-id: taken from list
80355     (?<licenseexceptionid>${exceptions})
80356
80357     # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
80358     (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))
80359
80360     # simple-expresssion: license-id / license-id+ / license-ref
80361     (?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref))
80362
80363     # compound-expression: 1*(
80364     #   simple-expression /
80365     #   simple-expression WITH license-exception-id /
80366     #   compound-expression AND compound-expression /
80367     #   compound-expression OR compound-expression
80368     # ) / ( compound-expression ) )
80369     (?<compound_head>
80370         (?&simple_expression) ( \s+ (?:with|WITH) \s+ (?&licenseexceptionid))?
80371             | \( \s* (?&compound_expression) \s* \)
80372     )
80373     (?<compound_expression>
80374         (?&compound_head) (?: \s+ (?:and|AND|or|OR) \s+ (?&compound_expression))?
80375     )
80376
80377     # license-expression: 1*1(simple-expression / compound-expression)
80378     (?<license_expression>(?&compound_expression) | (?&simple_expression))
80379 ) # end of define
80380
80381 ^(NONE | NOASSERTION | (?&license_expression))$
80382 }x
80383 REGEX;
80384
80385 $match = preg_match($regex, $license);
80386
80387 if (0 === $match) {
80388 return false;
80389 }
80390
80391 if (false === $match) {
80392 throw new \RuntimeException('Regex failed to compile/run.');
80393 }
80394
80395 return true;
80396 }
80397 }
80398 Copyright (C) 2015 Composer
80399
80400 Permission is hereby granted, free of charge, to any person obtaining a copy of
80401 this software and associated documentation files (the "Software"), to deal in
80402 the Software without restriction, including without limitation the rights to
80403 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
80404 of the Software, and to permit persons to whom the Software is furnished to do
80405 so, subject to the following conditions:
80406
80407 The above copyright notice and this permission notice shall be included in all
80408 copies or substantial portions of the Software.
80409
80410 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
80411 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
80412 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
80413 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
80414 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
80415 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
80416 SOFTWARE.
80417 <?php
80418
80419
80420
80421
80422
80423
80424
80425
80426
80427
80428 namespace Composer\Semver;
80429
80430 use Composer\Semver\Constraint\Constraint;
80431
80432 class Comparator
80433 {
80434
80435
80436
80437
80438
80439
80440
80441
80442 public static function greaterThan($version1, $version2)
80443 {
80444 return self::compare($version1, '>', $version2);
80445 }
80446
80447
80448
80449
80450
80451
80452
80453
80454
80455 public static function greaterThanOrEqualTo($version1, $version2)
80456 {
80457 return self::compare($version1, '>=', $version2);
80458 }
80459
80460
80461
80462
80463
80464
80465
80466
80467
80468 public static function lessThan($version1, $version2)
80469 {
80470 return self::compare($version1, '<', $version2);
80471 }
80472
80473
80474
80475
80476
80477
80478
80479
80480
80481 public static function lessThanOrEqualTo($version1, $version2)
80482 {
80483 return self::compare($version1, '<=', $version2);
80484 }
80485
80486
80487
80488
80489
80490
80491
80492
80493
80494 public static function equalTo($version1, $version2)
80495 {
80496 return self::compare($version1, '==', $version2);
80497 }
80498
80499
80500
80501
80502
80503
80504
80505
80506
80507 public static function notEqualTo($version1, $version2)
80508 {
80509 return self::compare($version1, '!=', $version2);
80510 }
80511
80512
80513
80514
80515
80516
80517
80518
80519
80520
80521 public static function compare($version1, $operator, $version2)
80522 {
80523 $constraint = new Constraint($operator, $version2);
80524
80525 return $constraint->matches(new Constraint('==', $version1));
80526 }
80527 }
80528 <?php
80529
80530
80531
80532
80533
80534
80535
80536
80537
80538
80539 namespace Composer\Semver\Constraint;
80540
80541 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);
80542
80543
80544
80545
80546 abstract class AbstractConstraint implements ConstraintInterface
80547 {
80548
80549 protected $prettyString;
80550
80551
80552
80553
80554
80555
80556 public function matches(ConstraintInterface $provider)
80557 {
80558 if ($provider instanceof $this) {
80559
80560  return $this->matchSpecific($provider);
80561 }
80562
80563
80564  return $provider->matches($this);
80565 }
80566
80567
80568
80569
80570 public function setPrettyString($prettyString)
80571 {
80572 $this->prettyString = $prettyString;
80573 }
80574
80575
80576
80577
80578 public function getPrettyString()
80579 {
80580 if ($this->prettyString) {
80581 return $this->prettyString;
80582 }
80583
80584 return $this->__toString();
80585 }
80586
80587
80588  
80589  
80590 }
80591 <?php
80592
80593
80594
80595
80596
80597
80598
80599
80600
80601
80602 namespace Composer\Semver\Constraint;
80603
80604
80605
80606
80607 class Constraint implements ConstraintInterface
80608 {
80609
80610 const OP_EQ = 0;
80611 const OP_LT = 1;
80612 const OP_LE = 2;
80613 const OP_GT = 3;
80614 const OP_GE = 4;
80615 const OP_NE = 5;
80616
80617
80618
80619
80620
80621
80622 private static $transOpStr = array(
80623 '=' => self::OP_EQ,
80624 '==' => self::OP_EQ,
80625 '<' => self::OP_LT,
80626 '<=' => self::OP_LE,
80627 '>' => self::OP_GT,
80628 '>=' => self::OP_GE,
80629 '<>' => self::OP_NE,
80630 '!=' => self::OP_NE,
80631 );
80632
80633
80634
80635
80636
80637
80638 private static $transOpInt = array(
80639 self::OP_EQ => '==',
80640 self::OP_LT => '<',
80641 self::OP_LE => '<=',
80642 self::OP_GT => '>',
80643 self::OP_GE => '>=',
80644 self::OP_NE => '!=',
80645 );
80646
80647
80648 protected $operator;
80649
80650
80651 protected $version;
80652
80653
80654 protected $prettyString;
80655
80656
80657
80658
80659
80660
80661 public function matches(ConstraintInterface $provider)
80662 {
80663 if ($provider instanceof $this) {
80664 return $this->matchSpecific($provider);
80665 }
80666
80667
80668  return $provider->matches($this);
80669 }
80670
80671
80672
80673
80674 public function setPrettyString($prettyString)
80675 {
80676 $this->prettyString = $prettyString;
80677 }
80678
80679
80680
80681
80682 public function getPrettyString()
80683 {
80684 if ($this->prettyString) {
80685 return $this->prettyString;
80686 }
80687
80688 return $this->__toString();
80689 }
80690
80691
80692
80693
80694
80695
80696 public static function getSupportedOperators()
80697 {
80698 return array_keys(self::$transOpStr);
80699 }
80700
80701
80702
80703
80704
80705
80706
80707
80708
80709 public function __construct($operator, $version)
80710 {
80711 if (!isset(self::$transOpStr[$operator])) {
80712 throw new \InvalidArgumentException(sprintf(
80713 'Invalid operator "%s" given, expected one of: %s',
80714 $operator,
80715 implode(', ', self::getSupportedOperators())
80716 ));
80717 }
80718
80719 $this->operator = self::$transOpStr[$operator];
80720 $this->version = $version;
80721 }
80722
80723
80724
80725
80726
80727
80728
80729
80730
80731
80732
80733 public function versionCompare($a, $b, $operator, $compareBranches = false)
80734 {
80735 if (!isset(self::$transOpStr[$operator])) {
80736 throw new \InvalidArgumentException(sprintf(
80737 'Invalid operator "%s" given, expected one of: %s',
80738 $operator,
80739 implode(', ', self::getSupportedOperators())
80740 ));
80741 }
80742
80743 $aIsBranch = 'dev-' === substr($a, 0, 4);
80744 $bIsBranch = 'dev-' === substr($b, 0, 4);
80745
80746 if ($aIsBranch && $bIsBranch) {
80747 return $operator === '==' && $a === $b;
80748 }
80749
80750
80751  if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
80752 return false;
80753 }
80754
80755 return version_compare($a, $b, $operator);
80756 }
80757
80758
80759
80760
80761
80762
80763
80764 public function matchSpecific(Constraint $provider, $compareBranches = false)
80765 {
80766 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
80767 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
80768
80769 $isEqualOp = self::OP_EQ === $this->operator;
80770 $isNonEqualOp = self::OP_NE === $this->operator;
80771 $isProviderEqualOp = self::OP_EQ === $provider->operator;
80772 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
80773
80774
80775  
80776  if ($isNonEqualOp || $isProviderNonEqualOp) {
80777 return !$isEqualOp && !$isProviderEqualOp
80778 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
80779 }
80780
80781
80782  
80783  if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
80784 return true;
80785 }
80786
80787 if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
80788
80789  
80790  if ($provider->version === $this->version
80791 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
80792 && self::$transOpInt[$this->operator] !== $noEqualOp) {
80793 return false;
80794 }
80795
80796 return true;
80797 }
80798
80799 return false;
80800 }
80801
80802
80803
80804
80805 public function __toString()
80806 {
80807 return self::$transOpInt[$this->operator] . ' ' . $this->version;
80808 }
80809 }
80810 <?php
80811
80812
80813
80814
80815
80816
80817
80818
80819
80820
80821 namespace Composer\Semver\Constraint;
80822
80823 interface ConstraintInterface
80824 {
80825
80826
80827
80828
80829
80830 public function matches(ConstraintInterface $provider);
80831
80832
80833
80834
80835 public function getPrettyString();
80836
80837
80838
80839
80840 public function __toString();
80841 }
80842 <?php
80843
80844
80845
80846
80847
80848
80849
80850
80851
80852
80853 namespace Composer\Semver\Constraint;
80854
80855
80856
80857
80858 class EmptyConstraint implements ConstraintInterface
80859 {
80860
80861 protected $prettyString;
80862
80863
80864
80865
80866
80867
80868 public function matches(ConstraintInterface $provider)
80869 {
80870 return true;
80871 }
80872
80873
80874
80875
80876 public function setPrettyString($prettyString)
80877 {
80878 $this->prettyString = $prettyString;
80879 }
80880
80881
80882
80883
80884 public function getPrettyString()
80885 {
80886 if ($this->prettyString) {
80887 return $this->prettyString;
80888 }
80889
80890 return $this->__toString();
80891 }
80892
80893
80894
80895
80896 public function __toString()
80897 {
80898 return '[]';
80899 }
80900 }
80901 <?php
80902
80903
80904
80905
80906
80907
80908
80909
80910
80911
80912 namespace Composer\Semver\Constraint;
80913
80914
80915
80916
80917 class MultiConstraint implements ConstraintInterface
80918 {
80919
80920 protected $constraints;
80921
80922
80923 protected $prettyString;
80924
80925
80926 protected $conjunctive;
80927
80928
80929
80930
80931
80932 public function __construct(array $constraints, $conjunctive = true)
80933 {
80934 $this->constraints = $constraints;
80935 $this->conjunctive = $conjunctive;
80936 }
80937
80938
80939
80940
80941 public function getConstraints()
80942 {
80943 return $this->constraints;
80944 }
80945
80946
80947
80948
80949 public function isConjunctive()
80950 {
80951 return $this->conjunctive;
80952 }
80953
80954
80955
80956
80957 public function isDisjunctive()
80958 {
80959 return !$this->conjunctive;
80960 }
80961
80962
80963
80964
80965
80966
80967 public function matches(ConstraintInterface $provider)
80968 {
80969 if (false === $this->conjunctive) {
80970 foreach ($this->constraints as $constraint) {
80971 if ($constraint->matches($provider)) {
80972 return true;
80973 }
80974 }
80975
80976 return false;
80977 }
80978
80979 foreach ($this->constraints as $constraint) {
80980 if (!$constraint->matches($provider)) {
80981 return false;
80982 }
80983 }
80984
80985 return true;
80986 }
80987
80988
80989
80990
80991 public function setPrettyString($prettyString)
80992 {
80993 $this->prettyString = $prettyString;
80994 }
80995
80996
80997
80998
80999 public function getPrettyString()
81000 {
81001 if ($this->prettyString) {
81002 return $this->prettyString;
81003 }
81004
81005 return $this->__toString();
81006 }
81007
81008
81009
81010
81011 public function __toString()
81012 {
81013 $constraints = array();
81014 foreach ($this->constraints as $constraint) {
81015 $constraints[] = (string) $constraint;
81016 }
81017
81018 return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
81019 }
81020 }
81021 <?php
81022
81023
81024
81025
81026
81027
81028
81029
81030
81031
81032 namespace Composer\Semver;
81033
81034 use Composer\Semver\Constraint\Constraint;
81035
81036 class Semver
81037 {
81038 const SORT_ASC = 1;
81039 const SORT_DESC = -1;
81040
81041
81042 private static $versionParser;
81043
81044
81045
81046
81047
81048
81049
81050
81051
81052 public static function satisfies($version, $constraints)
81053 {
81054 if (null === self::$versionParser) {
81055 self::$versionParser = new VersionParser();
81056 }
81057
81058 $versionParser = self::$versionParser;
81059 $provider = new Constraint('==', $versionParser->normalize($version));
81060 $constraints = $versionParser->parseConstraints($constraints);
81061
81062 return $constraints->matches($provider);
81063 }
81064
81065
81066
81067
81068
81069
81070
81071
81072
81073 public static function satisfiedBy(array $versions, $constraints)
81074 {
81075 $versions = array_filter($versions, function ($version) use ($constraints) {
81076 return Semver::satisfies($version, $constraints);
81077 });
81078
81079 return array_values($versions);
81080 }
81081
81082
81083
81084
81085
81086
81087
81088
81089 public static function sort(array $versions)
81090 {
81091 return self::usort($versions, self::SORT_ASC);
81092 }
81093
81094
81095
81096
81097
81098
81099
81100
81101 public static function rsort(array $versions)
81102 {
81103 return self::usort($versions, self::SORT_DESC);
81104 }
81105
81106
81107
81108
81109
81110
81111
81112 private static function usort(array $versions, $direction)
81113 {
81114 if (null === self::$versionParser) {
81115 self::$versionParser = new VersionParser();
81116 }
81117
81118 $versionParser = self::$versionParser;
81119 $normalized = array();
81120
81121
81122  
81123  foreach ($versions as $key => $version) {
81124 $normalized[] = array($versionParser->normalize($version), $key);
81125 }
81126
81127 usort($normalized, function (array $left, array $right) use ($direction) {
81128 if ($left[0] === $right[0]) {
81129 return 0;
81130 }
81131
81132 if (Comparator::lessThan($left[0], $right[0])) {
81133 return -$direction;
81134 }
81135
81136 return $direction;
81137 });
81138
81139
81140  $sorted = array();
81141 foreach ($normalized as $item) {
81142 $sorted[] = $versions[$item[1]];
81143 }
81144
81145 return $sorted;
81146 }
81147 }
81148 <?php
81149
81150
81151
81152
81153
81154
81155
81156
81157
81158
81159 namespace Composer\Semver;
81160
81161 use Composer\Semver\Constraint\ConstraintInterface;
81162 use Composer\Semver\Constraint\EmptyConstraint;
81163 use Composer\Semver\Constraint\MultiConstraint;
81164 use Composer\Semver\Constraint\Constraint;
81165
81166
81167
81168
81169
81170
81171 class VersionParser
81172 {
81173
81174
81175
81176
81177
81178
81179
81180
81181
81182
81183
81184
81185
81186 private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
81187
81188
81189 private static $stabilities = array('stable', 'RC', 'beta', 'alpha', 'dev');
81190
81191
81192
81193
81194
81195
81196
81197
81198 public static function parseStability($version)
81199 {
81200 $version = preg_replace('{#.+$}i', '', $version);
81201
81202 if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
81203 return 'dev';
81204 }
81205
81206 preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
81207 if (!empty($match[3])) {
81208 return 'dev';
81209 }
81210
81211 if (!empty($match[1])) {
81212 if ('beta' === $match[1] || 'b' === $match[1]) {
81213 return 'beta';
81214 }
81215 if ('alpha' === $match[1] || 'a' === $match[1]) {
81216 return 'alpha';
81217 }
81218 if ('rc' === $match[1]) {
81219 return 'RC';
81220 }
81221 }
81222
81223 return 'stable';
81224 }
81225
81226
81227
81228
81229
81230
81231 public static function normalizeStability($stability)
81232 {
81233 $stability = strtolower($stability);
81234
81235 return $stability === 'rc' ? 'RC' : $stability;
81236 }
81237
81238
81239
81240
81241
81242
81243
81244
81245
81246
81247
81248 public function normalize($version, $fullVersion = null)
81249 {
81250 $version = trim($version);
81251 if (null === $fullVersion) {
81252 $fullVersion = $version;
81253 }
81254
81255
81256  if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
81257 $version = $match[1];
81258 }
81259
81260
81261  if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
81262 return '9999999-dev';
81263 }
81264
81265
81266  if ('dev-' === strtolower(substr($version, 0, 4))) {
81267 return 'dev-' . substr($version, 4);
81268 }
81269
81270
81271  if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
81272 $version = $match[1];
81273 }
81274
81275
81276  if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
81277 $version = $matches[1]
81278 . (!empty($matches[2]) ? $matches[2] : '.0')
81279 . (!empty($matches[3]) ? $matches[3] : '.0')
81280 . (!empty($matches[4]) ? $matches[4] : '.0');
81281 $index = 5;
81282
81283  } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) {
81284 $version = preg_replace('{\D}', '.', $matches[1]);
81285 $index = 2;
81286 }
81287
81288
81289  if (isset($index)) {
81290 if (!empty($matches[$index])) {
81291 if ('stable' === $matches[$index]) {
81292 return $version;
81293 }
81294 $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? ltrim($matches[$index + 1], '.-') : '');
81295 }
81296
81297 if (!empty($matches[$index + 2])) {
81298 $version .= '-dev';
81299 }
81300
81301 return $version;
81302 }
81303
81304
81305  if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
81306 try {
81307 return $this->normalizeBranch($match[1]);
81308 } catch (\Exception $e) {
81309 }
81310 }
81311
81312 $extraMessage = '';
81313 if (preg_match('{ +as +' . preg_quote($version) . '$}', $fullVersion)) {
81314 $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
81315 } elseif (preg_match('{^' . preg_quote($version) . ' +as +}', $fullVersion)) {
81316 $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
81317 }
81318
81319 throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage);
81320 }
81321
81322
81323
81324
81325
81326
81327
81328
81329 public function parseNumericAliasPrefix($branch)
81330 {
81331 if (preg_match('{^(?P<version>(\d++\\.)*\d++)(?:\.x)?-dev$}i', $branch, $matches)) {
81332 return $matches['version'] . '.';
81333 }
81334
81335 return false;
81336 }
81337
81338
81339
81340
81341
81342
81343
81344
81345 public function normalizeBranch($name)
81346 {
81347 $name = trim($name);
81348
81349 if (in_array($name, array('master', 'trunk', 'default'))) {
81350 return $this->normalize($name);
81351 }
81352
81353 if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
81354 $version = '';
81355 for ($i = 1; $i < 5; ++$i) {
81356 $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
81357 }
81358
81359 return str_replace('x', '9999999', $version) . '-dev';
81360 }
81361
81362 return 'dev-' . $name;
81363 }
81364
81365
81366
81367
81368
81369
81370
81371
81372 public function parseConstraints($constraints)
81373 {
81374 $prettyConstraint = $constraints;
81375
81376 if (preg_match('{^([^,\s]*?)@(' . implode('|', self::$stabilities) . ')$}i', $constraints, $match)) {
81377 $constraints = empty($match[1]) ? '*' : $match[1];
81378 }
81379
81380 if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) {
81381 $constraints = $match[1];
81382 }
81383
81384 $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
81385 $orGroups = array();
81386 foreach ($orConstraints as $constraints) {
81387 $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
81388 if (count($andConstraints) > 1) {
81389 $constraintObjects = array();
81390 foreach ($andConstraints as $constraint) {
81391 foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
81392 $constraintObjects[] = $parsedConstraint;
81393 }
81394 }
81395 } else {
81396 $constraintObjects = $this->parseConstraint($andConstraints[0]);
81397 }
81398
81399 if (1 === count($constraintObjects)) {
81400 $constraint = $constraintObjects[0];
81401 } else {
81402 $constraint = new MultiConstraint($constraintObjects);
81403 }
81404
81405 $orGroups[] = $constraint;
81406 }
81407
81408 if (1 === count($orGroups)) {
81409 $constraint = $orGroups[0];
81410 } elseif (2 === count($orGroups)
81411
81412  
81413  && $orGroups[0] instanceof MultiConstraint
81414 && $orGroups[1] instanceof MultiConstraint
81415 && 2 === count($orGroups[0]->getConstraints())
81416 && 2 === count($orGroups[1]->getConstraints())
81417 && ($a = (string) $orGroups[0])
81418 && substr($a, 0, 3) === '[>=' && (false !== ($posA = strpos($a, '<', 4)))
81419 && ($b = (string) $orGroups[1])
81420 && substr($b, 0, 3) === '[>=' && (false !== ($posB = strpos($b, '<', 4)))
81421 && substr($a, $posA + 2, -1) === substr($b, 4, $posB - 5)
81422 ) {
81423 $constraint = new MultiConstraint(array(
81424 new Constraint('>=', substr($a, 4, $posA - 5)),
81425 new Constraint('<', substr($b, $posB + 2, -1)),
81426 ));
81427 } else {
81428 $constraint = new MultiConstraint($orGroups, false);
81429 }
81430
81431 $constraint->setPrettyString($prettyConstraint);
81432
81433 return $constraint;
81434 }
81435
81436
81437
81438
81439
81440
81441
81442
81443 private function parseConstraint($constraint)
81444 {
81445 if (preg_match('{^([^,\s]+?)@(' . implode('|', self::$stabilities) . ')$}i', $constraint, $match)) {
81446 $constraint = $match[1];
81447 if ($match[2] !== 'stable') {
81448 $stabilityModifier = $match[2];
81449 }
81450 }
81451
81452 if (preg_match('{^v?[xX*](\.[xX*])*$}i', $constraint)) {
81453 return array(new EmptyConstraint());
81454 }
81455
81456 $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?' . self::$modifierRegex . '(?:\+[^\s]+)?';
81457
81458
81459  
81460  
81461  
81462  
81463  if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
81464 if (substr($constraint, 0, 2) === '~>') {
81465 throw new \UnexpectedValueException(
81466 'Could not parse version constraint ' . $constraint . ': ' .
81467 'Invalid operator "~>", you probably meant to use the "~" operator'
81468 );
81469 }
81470
81471
81472  if (isset($matches[4]) && '' !== $matches[4]) {
81473 $position = 4;
81474 } elseif (isset($matches[3]) && '' !== $matches[3]) {
81475 $position = 3;
81476 } elseif (isset($matches[2]) && '' !== $matches[2]) {
81477 $position = 2;
81478 } else {
81479 $position = 1;
81480 }
81481
81482
81483  $stabilitySuffix = '';
81484 if (!empty($matches[5])) {
81485 $stabilitySuffix .= '-' . $this->expandStability($matches[5]) . (!empty($matches[6]) ? $matches[6] : '');
81486 }
81487
81488 if (!empty($matches[7])) {
81489 $stabilitySuffix .= '-dev';
81490 }
81491
81492 if (!$stabilitySuffix) {
81493 $stabilitySuffix = '-dev';
81494 }
81495
81496 $lowVersion = $this->manipulateVersionString($matches, $position, 0) . $stabilitySuffix;
81497 $lowerBound = new Constraint('>=', $lowVersion);
81498
81499
81500  
81501  $highPosition = max(1, $position - 1);
81502 $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
81503 $upperBound = new Constraint('<', $highVersion);
81504
81505 return array(
81506 $lowerBound,
81507 $upperBound,
81508 );
81509 }
81510
81511
81512  
81513  
81514  
81515  
81516  if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
81517
81518  if ('0' !== $matches[1] || '' === $matches[2]) {
81519 $position = 1;
81520 } elseif ('0' !== $matches[2] || '' === $matches[3]) {
81521 $position = 2;
81522 } else {
81523 $position = 3;
81524 }
81525
81526
81527  $stabilitySuffix = '';
81528 if (empty($matches[5]) && empty($matches[7])) {
81529 $stabilitySuffix .= '-dev';
81530 }
81531
81532 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
81533 $lowerBound = new Constraint('>=', $lowVersion);
81534
81535
81536  
81537  $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
81538 $upperBound = new Constraint('<', $highVersion);
81539
81540 return array(
81541 $lowerBound,
81542 $upperBound,
81543 );
81544 }
81545
81546
81547  
81548  
81549  
81550  if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
81551 if (isset($matches[3]) && '' !== $matches[3]) {
81552 $position = 3;
81553 } elseif (isset($matches[2]) && '' !== $matches[2]) {
81554 $position = 2;
81555 } else {
81556 $position = 1;
81557 }
81558
81559 $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
81560 $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
81561
81562 if ($lowVersion === '0.0.0.0-dev') {
81563 return array(new Constraint('<', $highVersion));
81564 }
81565
81566 return array(
81567 new Constraint('>=', $lowVersion),
81568 new Constraint('<', $highVersion),
81569 );
81570 }
81571
81572
81573  
81574  
81575  
81576  
81577  
81578  if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
81579
81580  $lowStabilitySuffix = '';
81581 if (empty($matches[6]) && empty($matches[8])) {
81582 $lowStabilitySuffix = '-dev';
81583 }
81584
81585 $lowVersion = $this->normalize($matches['from']);
81586 $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
81587
81588 $empty = function ($x) {
81589 return ($x === 0 || $x === '0') ? false : empty($x);
81590 };
81591
81592 if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) {
81593 $highVersion = $this->normalize($matches['to']);
81594 $upperBound = new Constraint('<=', $highVersion);
81595 } else {
81596 $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]);
81597 $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev';
81598 $upperBound = new Constraint('<', $highVersion);
81599 }
81600
81601 return array(
81602 $lowerBound,
81603 $upperBound,
81604 );
81605 }
81606
81607
81608  if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
81609 try {
81610 $version = $this->normalize($matches[2]);
81611
81612 if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') {
81613 $version .= '-' . $stabilityModifier;
81614 } elseif ('<' === $matches[1] || '>=' === $matches[1]) {
81615 if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
81616 if (substr($matches[2], 0, 4) !== 'dev-') {
81617 $version .= '-dev';
81618 }
81619 }
81620 }
81621
81622 return array(new Constraint($matches[1] ?: '=', $version));
81623 } catch (\Exception $e) {
81624 }
81625 }
81626
81627 $message = 'Could not parse version constraint ' . $constraint;
81628 if (isset($e)) {
81629 $message .= ': ' . $e->getMessage();
81630 }
81631
81632 throw new \UnexpectedValueException($message);
81633 }
81634
81635
81636
81637
81638
81639
81640
81641
81642
81643
81644
81645
81646
81647 private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
81648 {
81649 for ($i = 4; $i > 0; --$i) {
81650 if ($i > $position) {
81651 $matches[$i] = $pad;
81652 } elseif ($i === $position && $increment) {
81653 $matches[$i] += $increment;
81654
81655  if ($matches[$i] < 0) {
81656 $matches[$i] = $pad;
81657 --$position;
81658
81659
81660  if ($i === 1) {
81661 return;
81662 }
81663 }
81664 }
81665 }
81666
81667 return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
81668 }
81669
81670
81671
81672
81673
81674
81675
81676
81677 private function expandStability($stability)
81678 {
81679 $stability = strtolower($stability);
81680
81681 switch ($stability) {
81682 case 'a':
81683 return 'alpha';
81684 case 'b':
81685 return 'beta';
81686 case 'p':
81687 case 'pl':
81688 return 'patch';
81689 case 'rc':
81690 return 'RC';
81691 default:
81692 return $stability;
81693 }
81694 }
81695 }
81696 Copyright (C) 2016 Composer
81697
81698 Permission is hereby granted, free of charge, to any person obtaining a copy of
81699 this software and associated documentation files (the "Software"), to deal in
81700 the Software without restriction, including without limitation the rights to
81701 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
81702 of the Software, and to permit persons to whom the Software is furnished to do
81703 so, subject to the following conditions:
81704
81705 The above copyright notice and this permission notice shall be included in all
81706 copies or substantial portions of the Software.
81707
81708 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81709 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81710 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
81711 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81712 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
81713 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
81714 SOFTWARE.
81715 <?php
81716
81717
81718
81719
81720
81721
81722
81723
81724
81725
81726 namespace Composer\CaBundle;
81727
81728 use Psr\Log\LoggerInterface;
81729 use Symfony\Component\Process\PhpProcess;
81730
81731
81732
81733
81734
81735 class CaBundle
81736 {
81737 private static $caPath;
81738 private static $caFileValidity = array();
81739 private static $useOpensslParse;
81740
81741
81742
81743
81744
81745
81746
81747
81748
81749
81750
81751
81752
81753
81754
81755
81756
81757
81758
81759
81760
81761
81762
81763
81764
81765
81766
81767
81768
81769
81770
81771
81772
81773
81774
81775
81776
81777
81778 public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
81779 {
81780 if (self::$caPath !== null) {
81781 return self::$caPath;
81782 }
81783
81784
81785  
81786  $envCertFile = getenv('SSL_CERT_FILE');
81787 if ($envCertFile && is_readable($envCertFile) && static::validateCaFile($envCertFile, $logger)) {
81788 return self::$caPath = $envCertFile;
81789 }
81790
81791
81792  
81793  $envCertDir = getenv('SSL_CERT_DIR');
81794 if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) {
81795 return self::$caPath = $envCertDir;
81796 }
81797
81798 $configured = ini_get('openssl.cafile');
81799 if ($configured && strlen($configured) > 0 && is_readable($configured) && static::validateCaFile($configured, $logger)) {
81800 return self::$caPath = $configured;
81801 }
81802
81803 $configured = ini_get('openssl.capath');
81804 if ($configured && is_dir($configured) && is_readable($configured)) {
81805 return self::$caPath = $configured;
81806 }
81807
81808 $caBundlePaths = array(
81809 '/etc/pki/tls/certs/ca-bundle.crt', 
81810  '/etc/ssl/certs/ca-certificates.crt', 
81811  '/etc/ssl/ca-bundle.pem', 
81812  '/usr/local/share/certs/ca-root-nss.crt', 
81813  '/usr/ssl/certs/ca-bundle.crt', 
81814  '/opt/local/share/curl/curl-ca-bundle.crt', 
81815  '/usr/local/share/curl/curl-ca-bundle.crt', 
81816  '/usr/share/ssl/certs/ca-bundle.crt', 
81817  '/etc/ssl/cert.pem', 
81818  '/usr/local/etc/ssl/cert.pem', 
81819  '/usr/local/etc/openssl/cert.pem', 
81820  );
81821
81822 foreach ($caBundlePaths as $caBundle) {
81823 if (@is_readable($caBundle) && static::validateCaFile($caBundle, $logger)) {
81824 return self::$caPath = $caBundle;
81825 }
81826 }
81827
81828 foreach ($caBundlePaths as $caBundle) {
81829 $caBundle = dirname($caBundle);
81830 if (@is_dir($caBundle) && glob($caBundle.'/*')) {
81831 return self::$caPath = $caBundle;
81832 }
81833 }
81834
81835 return self::$caPath = static::getBundledCaBundlePath(); 
81836  }
81837
81838
81839
81840
81841
81842
81843
81844
81845 public static function getBundledCaBundlePath()
81846 {
81847 $caBundleFile = __DIR__.'/../res/cacert.pem';
81848
81849
81850  
81851  if (0 === strpos($caBundleFile, 'phar://')) {
81852 file_put_contents(
81853 $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
81854 file_get_contents($caBundleFile)
81855 );
81856
81857 register_shutdown_function(function() use ($tempCaBundleFile) {
81858 @unlink($tempCaBundleFile);
81859 });
81860
81861 $caBundleFile = $tempCaBundleFile;
81862 }
81863
81864 return $caBundleFile;
81865 }
81866
81867
81868
81869
81870
81871
81872
81873
81874
81875 public static function validateCaFile($filename, LoggerInterface $logger = null)
81876 {
81877 static $warned = false;
81878
81879 if (isset(self::$caFileValidity[$filename])) {
81880 return self::$caFileValidity[$filename];
81881 }
81882
81883 $contents = file_get_contents($filename);
81884
81885
81886  
81887  if (!static::isOpensslParseSafe()) {
81888 if (!$warned && $logger) {
81889 $logger->warning(sprintf(
81890 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
81891 PHP_VERSION
81892 ));
81893 $warned = true;
81894 }
81895
81896 $isValid = !empty($contents);
81897 } else {
81898 $isValid = (bool) openssl_x509_parse($contents);
81899 }
81900
81901 if ($logger) {
81902 $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
81903 }
81904
81905 return self::$caFileValidity[$filename] = $isValid;
81906 }
81907
81908
81909
81910
81911
81912
81913
81914
81915
81916 public static function isOpensslParseSafe()
81917 {
81918 if (null !== self::$useOpensslParse) {
81919 return self::$useOpensslParse;
81920 }
81921
81922 if (PHP_VERSION_ID >= 50600) {
81923 return self::$useOpensslParse = true;
81924 }
81925
81926
81927  
81928  
81929  
81930  if (
81931 (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
81932 || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
81933 || (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
81934 ) {
81935
81936  return self::$useOpensslParse = true;
81937 }
81938
81939 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
81940
81941  return self::$useOpensslParse = false;
81942 }
81943
81944 $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
81945 $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
81946
81947 if (preg_match($regex, PHP_VERSION, $m)) {
81948 return ((int) $m[1]) >= $fixedVersion;
81949 }
81950
81951 return false;
81952 };
81953
81954
81955  if (
81956 $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) 
81957  || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) 
81958  || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) 
81959  ) {
81960 return self::$useOpensslParse = true;
81961 }
81962
81963
81964  if (!class_exists('Symfony\Component\Process\PhpProcess')) {
81965 return self::$useOpensslParse = false;
81966 }
81967
81968
81969  
81970  
81971  
81972  
81973  
81974
81975
81976  
81977  $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
81978 $script = <<<'EOT'
81979
81980 error_reporting(-1);
81981 $info = openssl_x509_parse(base64_decode('%s'));
81982 var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
81983
81984 EOT;
81985 $script = '<'."?php\n".sprintf($script, $cert);
81986
81987 try {
81988 $process = new PhpProcess($script);
81989 $process->mustRun();
81990 } catch (\Exception $e) {
81991
81992  
81993  return self::$useOpensslParse = false;
81994 }
81995
81996 $output = preg_split('{\r?\n}', trim($process->getOutput()));
81997 $errorOutput = trim($process->getErrorOutput());
81998
81999 if (
82000 count($output) === 3
82001 && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
82002 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
82003 && $output[2] === 'int(-1)'
82004 && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
82005 ) {
82006
82007  return self::$useOpensslParse = true;
82008 }
82009
82010 return self::$useOpensslParse = false;
82011 }
82012
82013
82014
82015
82016 public static function reset()
82017 {
82018 self::$caFileValidity = array();
82019 self::$caPath = null;
82020 self::$useOpensslParse = null;
82021 }
82022 }
82023 Copyright (c) 2012 PHP Framework Interoperability Group
82024
82025 Permission is hereby granted, free of charge, to any person obtaining a copy 
82026 of this software and associated documentation files (the "Software"), to deal
82027 in the Software without restriction, including without limitation the rights 
82028 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
82029 copies of the Software, and to permit persons to whom the Software is 
82030 furnished to do so, subject to the following conditions:
82031
82032 The above copyright notice and this permission notice shall be included in 
82033 all copies or substantial portions of the Software.
82034
82035 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
82036 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
82037 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
82038 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
82039 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
82040 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
82041 THE SOFTWARE.
82042 <?php
82043
82044 namespace Psr\Log;
82045
82046
82047
82048
82049
82050
82051
82052
82053 abstract class AbstractLogger implements LoggerInterface
82054 {
82055
82056
82057
82058
82059
82060
82061
82062
82063 public function emergency($message, array $context = array())
82064 {
82065 $this->log(LogLevel::EMERGENCY, $message, $context);
82066 }
82067
82068
82069
82070
82071
82072
82073
82074
82075
82076
82077
82078
82079 public function alert($message, array $context = array())
82080 {
82081 $this->log(LogLevel::ALERT, $message, $context);
82082 }
82083
82084
82085
82086
82087
82088
82089
82090
82091
82092
82093
82094 public function critical($message, array $context = array())
82095 {
82096 $this->log(LogLevel::CRITICAL, $message, $context);
82097 }
82098
82099
82100
82101
82102
82103
82104
82105
82106
82107
82108 public function error($message, array $context = array())
82109 {
82110 $this->log(LogLevel::ERROR, $message, $context);
82111 }
82112
82113
82114
82115
82116
82117
82118
82119
82120
82121
82122
82123
82124 public function warning($message, array $context = array())
82125 {
82126 $this->log(LogLevel::WARNING, $message, $context);
82127 }
82128
82129
82130
82131
82132
82133
82134
82135
82136
82137 public function notice($message, array $context = array())
82138 {
82139 $this->log(LogLevel::NOTICE, $message, $context);
82140 }
82141
82142
82143
82144
82145
82146
82147
82148
82149
82150
82151
82152 public function info($message, array $context = array())
82153 {
82154 $this->log(LogLevel::INFO, $message, $context);
82155 }
82156
82157
82158
82159
82160
82161
82162
82163
82164
82165 public function debug($message, array $context = array())
82166 {
82167 $this->log(LogLevel::DEBUG, $message, $context);
82168 }
82169 }
82170 <?php
82171
82172 namespace Psr\Log;
82173
82174 class InvalidArgumentException extends \InvalidArgumentException
82175 {
82176 }
82177 <?php
82178
82179 namespace Psr\Log;
82180
82181
82182
82183
82184 class LogLevel
82185 {
82186 const EMERGENCY = 'emergency';
82187 const ALERT = 'alert';
82188 const CRITICAL = 'critical';
82189 const ERROR = 'error';
82190 const WARNING = 'warning';
82191 const NOTICE = 'notice';
82192 const INFO = 'info';
82193 const DEBUG = 'debug';
82194 }
82195 <?php
82196
82197 namespace Psr\Log;
82198
82199
82200
82201
82202 interface LoggerAwareInterface
82203 {
82204
82205
82206
82207
82208
82209
82210
82211 public function setLogger(LoggerInterface $logger);
82212 }
82213 <?php
82214
82215 namespace Psr\Log;
82216
82217
82218
82219
82220 trait LoggerAwareTrait
82221 {
82222
82223
82224
82225
82226
82227 protected $logger;
82228
82229
82230
82231
82232
82233
82234 public function setLogger(LoggerInterface $logger)
82235 {
82236 $this->logger = $logger;
82237 }
82238 }
82239 <?php
82240
82241 namespace Psr\Log;
82242
82243
82244
82245
82246
82247
82248
82249
82250
82251
82252
82253
82254
82255
82256
82257
82258 interface LoggerInterface
82259 {
82260
82261
82262
82263
82264
82265
82266
82267
82268 public function emergency($message, array $context = array());
82269
82270
82271
82272
82273
82274
82275
82276
82277
82278
82279
82280
82281 public function alert($message, array $context = array());
82282
82283
82284
82285
82286
82287
82288
82289
82290
82291
82292
82293 public function critical($message, array $context = array());
82294
82295
82296
82297
82298
82299
82300
82301
82302
82303
82304 public function error($message, array $context = array());
82305
82306
82307
82308
82309
82310
82311
82312
82313
82314
82315
82316
82317 public function warning($message, array $context = array());
82318
82319
82320
82321
82322
82323
82324
82325
82326
82327 public function notice($message, array $context = array());
82328
82329
82330
82331
82332
82333
82334
82335
82336
82337
82338
82339 public function info($message, array $context = array());
82340
82341
82342
82343
82344
82345
82346
82347
82348
82349 public function debug($message, array $context = array());
82350
82351
82352
82353
82354
82355
82356
82357
82358
82359
82360 public function log($level, $message, array $context = array());
82361 }
82362 <?php
82363
82364 namespace Psr\Log;
82365
82366
82367
82368
82369
82370
82371
82372
82373
82374 trait LoggerTrait
82375 {
82376
82377
82378
82379
82380
82381
82382
82383
82384 public function emergency($message, array $context = array())
82385 {
82386 $this->log(LogLevel::EMERGENCY, $message, $context);
82387 }
82388
82389
82390
82391
82392
82393
82394
82395
82396
82397
82398
82399
82400 public function alert($message, array $context = array())
82401 {
82402 $this->log(LogLevel::ALERT, $message, $context);
82403 }
82404
82405
82406
82407
82408
82409
82410
82411
82412
82413
82414
82415 public function critical($message, array $context = array())
82416 {
82417 $this->log(LogLevel::CRITICAL, $message, $context);
82418 }
82419
82420
82421
82422
82423
82424
82425
82426
82427
82428
82429 public function error($message, array $context = array())
82430 {
82431 $this->log(LogLevel::ERROR, $message, $context);
82432 }
82433
82434
82435
82436
82437
82438
82439
82440
82441
82442
82443
82444
82445 public function warning($message, array $context = array())
82446 {
82447 $this->log(LogLevel::WARNING, $message, $context);
82448 }
82449
82450
82451
82452
82453
82454
82455
82456
82457
82458 public function notice($message, array $context = array())
82459 {
82460 $this->log(LogLevel::NOTICE, $message, $context);
82461 }
82462
82463
82464
82465
82466
82467
82468
82469
82470
82471
82472
82473 public function info($message, array $context = array())
82474 {
82475 $this->log(LogLevel::INFO, $message, $context);
82476 }
82477
82478
82479
82480
82481
82482
82483
82484
82485
82486 public function debug($message, array $context = array())
82487 {
82488 $this->log(LogLevel::DEBUG, $message, $context);
82489 }
82490
82491
82492
82493
82494
82495
82496
82497
82498
82499
82500 abstract public function log($level, $message, array $context = array());
82501 }
82502 <?php
82503
82504 namespace Psr\Log;
82505
82506
82507
82508
82509
82510
82511
82512
82513
82514 class NullLogger extends AbstractLogger
82515 {
82516
82517
82518
82519
82520
82521
82522
82523
82524
82525 public function log($level, $message, array $context = array())
82526 {
82527
82528  }
82529 }
82530 <?php
82531
82532 namespace Psr\Log\Test;
82533
82534 use Psr\Log\LoggerInterface;
82535 use Psr\Log\LogLevel;
82536
82537
82538
82539
82540
82541
82542
82543 abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase
82544 {
82545
82546
82547
82548 abstract public function getLogger();
82549
82550
82551
82552
82553
82554
82555
82556
82557
82558
82559 abstract public function getLogs();
82560
82561 public function testImplements()
82562 {
82563 $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
82564 }
82565
82566
82567
82568
82569 public function testLogsAtAllLevels($level, $message)
82570 {
82571 $logger = $this->getLogger();
82572 $logger->{$level}($message, array('user' => 'Bob'));
82573 $logger->log($level, $message, array('user' => 'Bob'));
82574
82575 $expected = array(
82576 $level.' message of level '.$level.' with context: Bob',
82577 $level.' message of level '.$level.' with context: Bob',
82578 );
82579 $this->assertEquals($expected, $this->getLogs());
82580 }
82581
82582 public function provideLevelsAndMessages()
82583 {
82584 return array(
82585 LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
82586 LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
82587 LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
82588 LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
82589 LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
82590 LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
82591 LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
82592 LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
82593 );
82594 }
82595
82596
82597
82598
82599 public function testThrowsOnInvalidLevel()
82600 {
82601 $logger = $this->getLogger();
82602 $logger->log('invalid level', 'Foo');
82603 }
82604
82605 public function testContextReplacement()
82606 {
82607 $logger = $this->getLogger();
82608 $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
82609
82610 $expected = array('info {Message {nothing} Bob Bar a}');
82611 $this->assertEquals($expected, $this->getLogs());
82612 }
82613
82614 public function testObjectCastToString()
82615 {
82616 if (method_exists($this, 'createPartialMock')) {
82617 $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
82618 } else {
82619 $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
82620 }
82621 $dummy->expects($this->once())
82622 ->method('__toString')
82623 ->will($this->returnValue('DUMMY'));
82624
82625 $this->getLogger()->warning($dummy);
82626
82627 $expected = array('warning DUMMY');
82628 $this->assertEquals($expected, $this->getLogs());
82629 }
82630
82631 public function testContextCanContainAnything()
82632 {
82633 $context = array(
82634 'bool' => true,
82635 'null' => null,
82636 'string' => 'Foo',
82637 'int' => 0,
82638 'float' => 0.5,
82639 'nested' => array('with object' => new DummyTest),
82640 'object' => new \DateTime,
82641 'resource' => fopen('php://memory', 'r'),
82642 );
82643
82644 $this->getLogger()->warning('Crazy context data', $context);
82645
82646 $expected = array('warning Crazy context data');
82647 $this->assertEquals($expected, $this->getLogs());
82648 }
82649
82650 public function testContextExceptionKeyCanBeExceptionOrOtherValues()
82651 {
82652 $logger = $this->getLogger();
82653 $logger->warning('Random message', array('exception' => 'oops'));
82654 $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
82655
82656 $expected = array(
82657 'warning Random message',
82658 'critical Uncaught Exception!'
82659 );
82660 $this->assertEquals($expected, $this->getLogs());
82661 }
82662 }
82663
82664 class DummyTest
82665 {
82666 public function __toString()
82667 {
82668 }
82669 }
82670 <?php
82671
82672
82673
82674 require_once __DIR__ . '/composer/autoload_real.php';
82675
82676 return ComposerAutoloaderInitComposerPhar1515162522::getLoader();
82677 <?php
82678
82679
82680
82681 $vendorDir = dirname(dirname(__FILE__));
82682 $baseDir = dirname($vendorDir);
82683
82684 return array(
82685 );
82686 <?php
82687
82688
82689
82690 $vendorDir = dirname(dirname(__FILE__));
82691 $baseDir = dirname($vendorDir);
82692
82693 return array(
82694 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
82695 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
82696 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
82697 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
82698 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
82699 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
82700 'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
82701 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
82702 'Seld\\CliPrompt\\' => array($vendorDir . '/seld/cli-prompt/src'),
82703 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
82704 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
82705 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
82706 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
82707 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
82708 'Composer\\' => array($baseDir . '/src/Composer'),
82709 );
82710 <?php
82711
82712
82713
82714 $vendorDir = dirname(dirname(__FILE__));
82715 $baseDir = dirname($vendorDir);
82716
82717 return array(
82718 );
82719 <?php
82720
82721
82722
82723 $vendorDir = dirname(dirname(__FILE__));
82724 $baseDir = dirname($vendorDir);
82725
82726 return array(
82727 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
82728 );
82729 <?php
82730
82731
82732
82733 class ComposerAutoloaderInitComposerPhar1515162522
82734 {
82735 private static $loader;
82736
82737 public static function loadClassLoader($class)
82738 {
82739 if ('Composer\Autoload\ClassLoader' === $class) {
82740 require __DIR__ . '/ClassLoader.php';
82741 }
82742 }
82743
82744 public static function getLoader()
82745 {
82746 if (null !== self::$loader) {
82747 return self::$loader;
82748 }
82749
82750 spl_autoload_register(array('ComposerAutoloaderInitComposerPhar1515162522', 'loadClassLoader'), true, true);
82751 self::$loader = $loader = new \Composer\Autoload\ClassLoader();
82752 spl_autoload_unregister(array('ComposerAutoloaderInitComposerPhar1515162522', 'loadClassLoader'));
82753
82754 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
82755 if ($useStaticLoader) {
82756 require_once __DIR__ . '/autoload_static.php';
82757
82758 call_user_func(\Composer\Autoload\ComposerStaticInitComposerPhar1515162522::getInitializer($loader));
82759 } else {
82760 $map = require __DIR__ . '/autoload_namespaces.php';
82761 foreach ($map as $namespace => $path) {
82762 $loader->set($namespace, $path);
82763 }
82764
82765 $map = require __DIR__ . '/autoload_psr4.php';
82766 foreach ($map as $namespace => $path) {
82767 $loader->setPsr4($namespace, $path);
82768 }
82769
82770 $classMap = require __DIR__ . '/autoload_classmap.php';
82771 if ($classMap) {
82772 $loader->addClassMap($classMap);
82773 }
82774 }
82775
82776 $loader->register(true);
82777
82778 if ($useStaticLoader) {
82779 $includeFiles = Composer\Autoload\ComposerStaticInitComposerPhar1515162522::$files;
82780 } else {
82781 $includeFiles = require __DIR__ . '/autoload_files.php';
82782 }
82783 foreach ($includeFiles as $fileIdentifier => $file) {
82784 composerRequireComposerPhar1515162522($fileIdentifier, $file);
82785 }
82786
82787 return $loader;
82788 }
82789 }
82790
82791 function composerRequireComposerPhar1515162522($fileIdentifier, $file)
82792 {
82793 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
82794 require $file;
82795
82796 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
82797 }
82798 }
82799 <?php
82800
82801
82802
82803 namespace Composer\Autoload;
82804
82805 class ComposerStaticInitComposerPhar1515162522
82806 {
82807 public static $files = array (
82808 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
82809 );
82810
82811 public static $prefixLengthsPsr4 = array (
82812 'S' => 
82813 array (
82814 'Symfony\\Polyfill\\Mbstring\\' => 26,
82815 'Symfony\\Component\\Process\\' => 26,
82816 'Symfony\\Component\\Finder\\' => 25,
82817 'Symfony\\Component\\Filesystem\\' => 29,
82818 'Symfony\\Component\\Debug\\' => 24,
82819 'Symfony\\Component\\Console\\' => 26,
82820 'Seld\\PharUtils\\' => 15,
82821 'Seld\\JsonLint\\' => 14,
82822 'Seld\\CliPrompt\\' => 15,
82823 ),
82824 'P' => 
82825 array (
82826 'Psr\\Log\\' => 8,
82827 ),
82828 'J' => 
82829 array (
82830 'JsonSchema\\' => 11,
82831 ),
82832 'C' => 
82833 array (
82834 'Composer\\Spdx\\' => 14,
82835 'Composer\\Semver\\' => 16,
82836 'Composer\\CaBundle\\' => 18,
82837 'Composer\\' => 9,
82838 ),
82839 );
82840
82841 public static $prefixDirsPsr4 = array (
82842 'Symfony\\Polyfill\\Mbstring\\' => 
82843 array (
82844 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
82845 ),
82846 'Symfony\\Component\\Process\\' => 
82847 array (
82848 0 => __DIR__ . '/..' . '/symfony/process',
82849 ),
82850 'Symfony\\Component\\Finder\\' => 
82851 array (
82852 0 => __DIR__ . '/..' . '/symfony/finder',
82853 ),
82854 'Symfony\\Component\\Filesystem\\' => 
82855 array (
82856 0 => __DIR__ . '/..' . '/symfony/filesystem',
82857 ),
82858 'Symfony\\Component\\Debug\\' => 
82859 array (
82860 0 => __DIR__ . '/..' . '/symfony/debug',
82861 ),
82862 'Symfony\\Component\\Console\\' => 
82863 array (
82864 0 => __DIR__ . '/..' . '/symfony/console',
82865 ),
82866 'Seld\\PharUtils\\' => 
82867 array (
82868 0 => __DIR__ . '/..' . '/seld/phar-utils/src',
82869 ),
82870 'Seld\\JsonLint\\' => 
82871 array (
82872 0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
82873 ),
82874 'Seld\\CliPrompt\\' => 
82875 array (
82876 0 => __DIR__ . '/..' . '/seld/cli-prompt/src',
82877 ),
82878 'Psr\\Log\\' => 
82879 array (
82880 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
82881 ),
82882 'JsonSchema\\' => 
82883 array (
82884 0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema',
82885 ),
82886 'Composer\\Spdx\\' => 
82887 array (
82888 0 => __DIR__ . '/..' . '/composer/spdx-licenses/src',
82889 ),
82890 'Composer\\Semver\\' => 
82891 array (
82892 0 => __DIR__ . '/..' . '/composer/semver/src',
82893 ),
82894 'Composer\\CaBundle\\' => 
82895 array (
82896 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
82897 ),
82898 'Composer\\' => 
82899 array (
82900 0 => __DIR__ . '/../..' . '/src/Composer',
82901 ),
82902 );
82903
82904 public static function getInitializer(ClassLoader $loader)
82905 {
82906 return \Closure::bind(function () use ($loader) {
82907 $loader->prefixLengthsPsr4 = ComposerStaticInitComposerPhar1515162522::$prefixLengthsPsr4;
82908 $loader->prefixDirsPsr4 = ComposerStaticInitComposerPhar1515162522::$prefixDirsPsr4;
82909
82910 }, null, ClassLoader::class);
82911 }
82912 }
82913 <?php
82914
82915
82916
82917
82918
82919
82920
82921
82922
82923
82924
82925 namespace Composer\Autoload;
82926
82927
82928
82929
82930
82931
82932
82933
82934
82935
82936
82937
82938
82939
82940
82941
82942
82943
82944
82945
82946
82947
82948
82949
82950
82951
82952
82953
82954
82955 class ClassLoader
82956 {
82957
82958  private $prefixLengthsPsr4 = array();
82959 private $prefixDirsPsr4 = array();
82960 private $fallbackDirsPsr4 = array();
82961
82962
82963  private $prefixesPsr0 = array();
82964 private $fallbackDirsPsr0 = array();
82965
82966 private $useIncludePath = false;
82967 private $classMap = array();
82968 private $classMapAuthoritative = false;
82969 private $missingClasses = array();
82970 private $apcuPrefix;
82971
82972 public function getPrefixes()
82973 {
82974 if (!empty($this->prefixesPsr0)) {
82975 return call_user_func_array('array_merge', $this->prefixesPsr0);
82976 }
82977
82978 return array();
82979 }
82980
82981 public function getPrefixesPsr4()
82982 {
82983 return $this->prefixDirsPsr4;
82984 }
82985
82986 public function getFallbackDirs()
82987 {
82988 return $this->fallbackDirsPsr0;
82989 }
82990
82991 public function getFallbackDirsPsr4()
82992 {
82993 return $this->fallbackDirsPsr4;
82994 }
82995
82996 public function getClassMap()
82997 {
82998 return $this->classMap;
82999 }
83000
83001
83002
83003
83004 public function addClassMap(array $classMap)
83005 {
83006 if ($this->classMap) {
83007 $this->classMap = array_merge($this->classMap, $classMap);
83008 } else {
83009 $this->classMap = $classMap;
83010 }
83011 }
83012
83013
83014
83015
83016
83017
83018
83019
83020
83021 public function add($prefix, $paths, $prepend = false)
83022 {
83023 if (!$prefix) {
83024 if ($prepend) {
83025 $this->fallbackDirsPsr0 = array_merge(
83026 (array) $paths,
83027 $this->fallbackDirsPsr0
83028 );
83029 } else {
83030 $this->fallbackDirsPsr0 = array_merge(
83031 $this->fallbackDirsPsr0,
83032 (array) $paths
83033 );
83034 }
83035
83036 return;
83037 }
83038
83039 $first = $prefix[0];
83040 if (!isset($this->prefixesPsr0[$first][$prefix])) {
83041 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
83042
83043 return;
83044 }
83045 if ($prepend) {
83046 $this->prefixesPsr0[$first][$prefix] = array_merge(
83047 (array) $paths,
83048 $this->prefixesPsr0[$first][$prefix]
83049 );
83050 } else {
83051 $this->prefixesPsr0[$first][$prefix] = array_merge(
83052 $this->prefixesPsr0[$first][$prefix],
83053 (array) $paths
83054 );
83055 }
83056 }
83057
83058
83059
83060
83061
83062
83063
83064
83065
83066
83067
83068 public function addPsr4($prefix, $paths, $prepend = false)
83069 {
83070 if (!$prefix) {
83071
83072  if ($prepend) {
83073 $this->fallbackDirsPsr4 = array_merge(
83074 (array) $paths,
83075 $this->fallbackDirsPsr4
83076 );
83077 } else {
83078 $this->fallbackDirsPsr4 = array_merge(
83079 $this->fallbackDirsPsr4,
83080 (array) $paths
83081 );
83082 }
83083 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
83084
83085  $length = strlen($prefix);
83086 if ('\\' !== $prefix[$length - 1]) {
83087 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
83088 }
83089 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
83090 $this->prefixDirsPsr4[$prefix] = (array) $paths;
83091 } elseif ($prepend) {
83092
83093  $this->prefixDirsPsr4[$prefix] = array_merge(
83094 (array) $paths,
83095 $this->prefixDirsPsr4[$prefix]
83096 );
83097 } else {
83098
83099  $this->prefixDirsPsr4[$prefix] = array_merge(
83100 $this->prefixDirsPsr4[$prefix],
83101 (array) $paths
83102 );
83103 }
83104 }
83105
83106
83107
83108
83109
83110
83111
83112
83113 public function set($prefix, $paths)
83114 {
83115 if (!$prefix) {
83116 $this->fallbackDirsPsr0 = (array) $paths;
83117 } else {
83118 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
83119 }
83120 }
83121
83122
83123
83124
83125
83126
83127
83128
83129
83130
83131 public function setPsr4($prefix, $paths)
83132 {
83133 if (!$prefix) {
83134 $this->fallbackDirsPsr4 = (array) $paths;
83135 } else {
83136 $length = strlen($prefix);
83137 if ('\\' !== $prefix[$length - 1]) {
83138 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
83139 }
83140 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
83141 $this->prefixDirsPsr4[$prefix] = (array) $paths;
83142 }
83143 }
83144
83145
83146
83147
83148
83149
83150 public function setUseIncludePath($useIncludePath)
83151 {
83152 $this->useIncludePath = $useIncludePath;
83153 }
83154
83155
83156
83157
83158
83159
83160
83161 public function getUseIncludePath()
83162 {
83163 return $this->useIncludePath;
83164 }
83165
83166
83167
83168
83169
83170
83171
83172 public function setClassMapAuthoritative($classMapAuthoritative)
83173 {
83174 $this->classMapAuthoritative = $classMapAuthoritative;
83175 }
83176
83177
83178
83179
83180
83181
83182 public function isClassMapAuthoritative()
83183 {
83184 return $this->classMapAuthoritative;
83185 }
83186
83187
83188
83189
83190
83191
83192 public function setApcuPrefix($apcuPrefix)
83193 {
83194 $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
83195 }
83196
83197
83198
83199
83200
83201
83202 public function getApcuPrefix()
83203 {
83204 return $this->apcuPrefix;
83205 }
83206
83207
83208
83209
83210
83211
83212 public function register($prepend = false)
83213 {
83214 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
83215 }
83216
83217
83218
83219
83220 public function unregister()
83221 {
83222 spl_autoload_unregister(array($this, 'loadClass'));
83223 }
83224
83225
83226
83227
83228
83229
83230
83231 public function loadClass($class)
83232 {
83233 if ($file = $this->findFile($class)) {
83234 includeFile($file);
83235
83236 return true;
83237 }
83238 }
83239
83240
83241
83242
83243
83244
83245
83246
83247 public function findFile($class)
83248 {
83249
83250  if (isset($this->classMap[$class])) {
83251 return $this->classMap[$class];
83252 }
83253 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
83254 return false;
83255 }
83256 if (null !== $this->apcuPrefix) {
83257 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
83258 if ($hit) {
83259 return $file;
83260 }
83261 }
83262
83263 $file = $this->findFileWithExtension($class, '.php');
83264
83265
83266  if (false === $file && defined('HHVM_VERSION')) {
83267 $file = $this->findFileWithExtension($class, '.hh');
83268 }
83269
83270 if (null !== $this->apcuPrefix) {
83271 apcu_add($this->apcuPrefix.$class, $file);
83272 }
83273
83274 if (false === $file) {
83275
83276  $this->missingClasses[$class] = true;
83277 }
83278
83279 return $file;
83280 }
83281
83282 private function findFileWithExtension($class, $ext)
83283 {
83284
83285  $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
83286
83287 $first = $class[0];
83288 if (isset($this->prefixLengthsPsr4[$first])) {
83289 $subPath = $class;
83290 while (false !== $lastPos = strrpos($subPath, '\\')) {
83291 $subPath = substr($subPath, 0, $lastPos);
83292 $search = $subPath.'\\';
83293 if (isset($this->prefixDirsPsr4[$search])) {
83294 $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
83295 foreach ($this->prefixDirsPsr4[$search] as $dir) {
83296 if (file_exists($file = $dir . $pathEnd)) {
83297 return $file;
83298 }
83299 }
83300 }
83301 }
83302 }
83303
83304
83305  foreach ($this->fallbackDirsPsr4 as $dir) {
83306 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
83307 return $file;
83308 }
83309 }
83310
83311
83312  if (false !== $pos = strrpos($class, '\\')) {
83313
83314  $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
83315 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
83316 } else {
83317
83318  $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
83319 }
83320
83321 if (isset($this->prefixesPsr0[$first])) {
83322 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
83323 if (0 === strpos($class, $prefix)) {
83324 foreach ($dirs as $dir) {
83325 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
83326 return $file;
83327 }
83328 }
83329 }
83330 }
83331 }
83332
83333
83334  foreach ($this->fallbackDirsPsr0 as $dir) {
83335 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
83336 return $file;
83337 }
83338 }
83339
83340
83341  if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
83342 return $file;
83343 }
83344
83345 return false;
83346 }
83347 }
83348
83349
83350
83351
83352
83353
83354 function includeFile($file)
83355 {
83356 include $file;
83357 }
83358 ##
83359 ## Bundle of CA Root Certificates
83360 ##
83361 ## Certificate data from Mozilla as of: Wed Sep 20 03:12:05 2017 GMT
83362 ##
83363 ## This is a bundle of X.509 certificates of public Certificate Authorities
83364 ## (CA). These were automatically extracted from Mozilla's root certificates
83365 ## file (certdata.txt).  This file can be found in the mozilla source tree:
83366 ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
83367 ##
83368 ## It contains the certificates in PEM format and therefore
83369 ## can be directly used with curl / libcurl / php_curl, or with
83370 ## an Apache+mod_ssl webserver for SSL client authentication.
83371 ## Just configure this file as the SSLCACertificateFile.
83372 ##
83373 ## Conversion done with mk-ca-bundle.pl version 1.27.
83374 ## SHA256: 2b2dbe5244e0047e088c597998883a913f6c5fffd1cb5c0fe5a368c8466cb2ec
83375 ##
83376
83377
83378 GlobalSign Root CA
83379 ==================
83380 -----BEGIN CERTIFICATE-----
83381 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
83382 GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
83383 b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
83384 BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
83385 VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
83386 DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
83387 THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
83388 Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
83389 c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
83390 gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
83391 HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
83392 AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
83393 Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
83394 j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
83395 hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
83396 X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
83397 -----END CERTIFICATE-----
83398
83399 GlobalSign Root CA - R2
83400 =======================
83401 -----BEGIN CERTIFICATE-----
83402 MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
83403 YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
83404 bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
83405 aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
83406 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
83407 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
83408 s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
83409 S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
83410 TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
83411 ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
83412 FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
83413 YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
83414 BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
83415 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
83416 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
83417 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
83418 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
83419 -----END CERTIFICATE-----
83420
83421 Verisign Class 3 Public Primary Certification Authority - G3
83422 ============================================================
83423 -----BEGIN CERTIFICATE-----
83424 MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
83425 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
83426 cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
83427 IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
83428 dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
83429 CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
83430 dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
83431 cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
83432 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
83433 ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
83434 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
83435 cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
83436 EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
83437 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
83438 ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
83439 j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
83440 /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
83441 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
83442 t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
83443 -----END CERTIFICATE-----
83444
83445 Entrust.net Premium 2048 Secure Server CA
83446 =========================================
83447 -----BEGIN CERTIFICATE-----
83448 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
83449 ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
83450 bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
83451 BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
83452 NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
83453 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
83454 MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
83455 ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
83456 MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
83457 Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
83458 hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
83459 nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
83460 VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
83461 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
83462 KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
83463 T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
83464 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
83465 J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
83466 nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
83467 -----END CERTIFICATE-----
83468
83469 Baltimore CyberTrust Root
83470 =========================
83471 -----BEGIN CERTIFICATE-----
83472 MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
83473 ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
83474 ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
83475 SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
83476 dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
83477 uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
83478 UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
83479 G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
83480 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
83481 l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
83482 VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
83483 BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
83484 cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
83485 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
83486 Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
83487 RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
83488 -----END CERTIFICATE-----
83489
83490 AddTrust External Root
83491 ======================
83492 -----BEGIN CERTIFICATE-----
83493 MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
83494 QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
83495 VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
83496 NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
83497 cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
83498 Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
83499 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
83500 Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
83501 aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
83502 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
83503 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
83504 BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
83505 VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
83506 VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
83507 IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
83508 j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
83509 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
83510 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
83511 G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
83512 -----END CERTIFICATE-----
83513
83514 Entrust Root Certification Authority
83515 ====================================
83516 -----BEGIN CERTIFICATE-----
83517 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
83518 BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
83519 b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
83520 A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
83521 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
83522 MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
83523 Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
83524 dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
83525 ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
83526 A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
83527 Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
83528 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
83529 rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
83530 DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
83531 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
83532 hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
83533 A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
83534 Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
83535 v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
83536 W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
83537 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
83538 -----END CERTIFICATE-----
83539
83540 GeoTrust Global CA
83541 ==================
83542 -----BEGIN CERTIFICATE-----
83543 MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
83544 Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
83545 MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
83546 LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
83547 CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
83548 BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
83549 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
83550 T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
83551 vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
83552 AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
83553 DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
83554 zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
83555 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
83556 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
83557 XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
83558 Mw==
83559 -----END CERTIFICATE-----
83560
83561 GeoTrust Universal CA
83562 =====================
83563 -----BEGIN CERTIFICATE-----
83564 MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
83565 R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
83566 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
83567 Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
83568 ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
83569 JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
83570 RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
83571 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
83572 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
83573 qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
83574 Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
83575 Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
83576 KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
83577 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
83578 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
83579 hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
83580 aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
83581 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
83582 oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
83583 xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
83584 KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
83585 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
83586 xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
83587 p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
83588 P/rmMuGNG2+k5o7Y+SlIis5z/iw=
83589 -----END CERTIFICATE-----
83590
83591 GeoTrust Universal CA 2
83592 =======================
83593 -----BEGIN CERTIFICATE-----
83594 MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
83595 R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
83596 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
83597 SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
83598 A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
83599 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
83600 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
83601 JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
83602 QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
83603 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
83604 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
83605 ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
83606 SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
83607 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
83608 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
83609 BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
83610 dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
83611 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
83612 mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
83613 A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
83614 Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
83615 pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
83616 FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
83617 gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
83618 X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
83619 -----END CERTIFICATE-----
83620
83621 Visa eCommerce Root
83622 ===================
83623 -----BEGIN CERTIFICATE-----
83624 MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
83625 EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
83626 QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
83627 WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
83628 VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
83629 bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
83630 F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
83631 RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
83632 TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
83633 /k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
83634 GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
83635 MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
83636 CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
83637 YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
83638 zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
83639 YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
83640 398znM/jra6O1I7mT1GvFpLgXPYHDw==
83641 -----END CERTIFICATE-----
83642
83643 Certum Root CA
83644 ==============
83645 -----BEGIN CERTIFICATE-----
83646 MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK
83647 ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla
83648 Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u
83649 by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x
83650 wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL
83651 kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ
83652 89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K
83653 Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P
83654 NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq
83655 hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+
83656 GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg
83657 GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/
83658 0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS
83659 qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw==
83660 -----END CERTIFICATE-----
83661
83662 Comodo AAA Services root
83663 ========================
83664 -----BEGIN CERTIFICATE-----
83665 MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
83666 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
83667 TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
83668 MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
83669 c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
83670 BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
83671 ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
83672 C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
83673 i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
83674 Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
83675 Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
83676 Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
83677 BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
83678 cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
83679 LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
83680 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
83681 Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
83682 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
83683 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
83684 -----END CERTIFICATE-----
83685
83686 QuoVadis Root CA
83687 ================
83688 -----BEGIN CERTIFICATE-----
83689 MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
83690 ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
83691 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
83692 MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
83693 cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
83694 EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
83695 AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
83696 J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
83697 F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
83698 YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
83699 AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
83700 PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
83701 ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
83702 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
83703 YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
83704 ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
83705 Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
83706 Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
83707 BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
83708 FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
83709 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
83710 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
83711 fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
83712 LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
83713 gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
83714 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
83715 5nrQNiOKSnQ2+Q==
83716 -----END CERTIFICATE-----
83717
83718 QuoVadis Root CA 2
83719 ==================
83720 -----BEGIN CERTIFICATE-----
83721 MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
83722 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
83723 ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
83724 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
83725 DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
83726 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
83727 lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
83728 lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
83729 lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
83730 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
83731 wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
83732 D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
83733 BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
83734 J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
83735 DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
83736 a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
83737 ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
83738 Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
83739 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
83740 VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
83741 +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
83742 IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
83743 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
83744 f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
83745 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
83746 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
83747 -----END CERTIFICATE-----
83748
83749 QuoVadis Root CA 3
83750 ==================
83751 -----BEGIN CERTIFICATE-----
83752 MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
83753 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
83754 OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
83755 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
83756 DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
83757 DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
83758 KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
83759 DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
83760 BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
83761 p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
83762 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
83763 MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
83764 Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
83765 uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
83766 BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
83767 YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
83768 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
83769 BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
83770 VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
83771 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
83772 AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
83773 qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
83774 hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
83775 POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
83776 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
83777 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
83778 bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
83779 g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
83780 vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
83781 qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
83782 -----END CERTIFICATE-----
83783
83784 Security Communication Root CA
83785 ==============================
83786 -----BEGIN CERTIFICATE-----
83787 MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
83788 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
83789 HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
83790 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
83791 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
83792 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
83793 DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
83794 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
83795 DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
83796 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
83797 DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
83798 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
83799 mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
83800 s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
83801 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
83802 FL39vmwLAw==
83803 -----END CERTIFICATE-----
83804
83805 Sonera Class 2 Root CA
83806 ======================
83807 -----BEGIN CERTIFICATE-----
83808 MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
83809 U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
83810 NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
83811 IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
83812 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
83813 dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
83814 f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
83815 tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
83816 nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
83817 XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
83818 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
83819 cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
83820 Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
83821 EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
83822 llpwrN9M
83823 -----END CERTIFICATE-----
83824
83825 Camerfirma Chambers of Commerce Root
83826 ====================================
83827 -----BEGIN CERTIFICATE-----
83828 MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
83829 QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
83830 ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx
83831 NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp
83832 cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn
83833 MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC
83834 AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU
83835 xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH
83836 NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW
83837 DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV
83838 d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud
83839 EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v
83840 cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P
83841 AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh
83842 bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD
83843 VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
83844 aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi
83845 fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD
83846 L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN
83847 UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n
83848 ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1
83849 erfutGWaIZDgqtCYvDi1czyL+Nw=
83850 -----END CERTIFICATE-----
83851
83852 Camerfirma Global Chambersign Root
83853 ==================================
83854 -----BEGIN CERTIFICATE-----
83855 MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
83856 QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
83857 ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx
83858 NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
83859 YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg
83860 MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw
83861 ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J
83862 1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O
83863 by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl
83864 6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c
83865 8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/
83866 BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j
83867 aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B
83868 Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj
83869 aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y
83870 ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
83871 bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA
83872 PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y
83873 gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ
83874 PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4
83875 IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes
83876 t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
83877 -----END CERTIFICATE-----
83878
83879 XRamp Global CA Root
83880 ====================
83881 -----BEGIN CERTIFICATE-----
83882 MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
83883 BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
83884 dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
83885 dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
83886 HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
83887 U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
83888 dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
83889 IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
83890 foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
83891 zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
83892 AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
83893 xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
83894 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
83895 oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
83896 AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
83897 /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
83898 qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
83899 nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
83900 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
83901 -----END CERTIFICATE-----
83902
83903 Go Daddy Class 2 CA
83904 ===================
83905 -----BEGIN CERTIFICATE-----
83906 MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
83907 VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
83908 ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
83909 A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
83910 RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
83911 ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
83912 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
83913 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
83914 YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
83915 vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
83916 BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
83917 atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
83918 MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
83919 A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
83920 PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
83921 I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
83922 HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
83923 Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
83924 vZ8=
83925 -----END CERTIFICATE-----
83926
83927 Starfield Class 2 CA
83928 ====================
83929 -----BEGIN CERTIFICATE-----
83930 MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
83931 U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
83932 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
83933 MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
83934 A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
83935 SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
83936 bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
83937 JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
83938 epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
83939 F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
83940 MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
83941 hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
83942 bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
83943 QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
83944 afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
83945 PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
83946 xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
83947 KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
83948 QBFGmh95DmK/D5fs4C8fF5Q=
83949 -----END CERTIFICATE-----
83950
83951 StartCom Certification Authority
83952 ================================
83953 -----BEGIN CERTIFICATE-----
83954 MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
83955 U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
83956 ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
83957 NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
83958 LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
83959 U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
83960 ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
83961 o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
83962 Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
83963 eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
83964 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
83965 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
83966 osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
83967 untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
83968 UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
83969 37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
83970 FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0
83971 Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj
83972 YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH
83973 AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw
83974 Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg
83975 U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5
83976 LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl
83977 cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh
83978 cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT
83979 dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC
83980 AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh
83981 3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm
83982 vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk
83983 fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3
83984 fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ
83985 EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
83986 yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl
83987 1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/
83988 lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro
83989 g14=
83990 -----END CERTIFICATE-----
83991
83992 Taiwan GRCA
83993 ===========
83994 -----BEGIN CERTIFICATE-----
83995 MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
83996 EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
83997 DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
83998 dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
83999 ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
84000 w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
84001 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
84002 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
84003 htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
84004 J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
84005 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
84006 B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
84007 O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
84008 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
84009 HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
84010 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
84011 TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
84012 Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
84013 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
84014 D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
84015 DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
84016 Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
84017 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
84018 CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
84019 +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
84020 -----END CERTIFICATE-----
84021
84022 DigiCert Assured ID Root CA
84023 ===========================
84024 -----BEGIN CERTIFICATE-----
84025 MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
84026 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
84027 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
84028 MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
84029 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
84030 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
84031 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
84032 UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
84033 /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
84034 oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
84035 GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
84036 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
84037 hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
84038 EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
84039 SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
84040 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
84041 +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
84042 -----END CERTIFICATE-----
84043
84044 DigiCert Global Root CA
84045 =======================
84046 -----BEGIN CERTIFICATE-----
84047 MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
84048 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
84049 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
84050 MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
84051 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
84052 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
84053 TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
84054 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
84055 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
84056 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
84057 o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
84058 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
84059 BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
84060 EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
84061 tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
84062 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
84063 CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
84064 -----END CERTIFICATE-----
84065
84066 DigiCert High Assurance EV Root CA
84067 ==================================
84068 -----BEGIN CERTIFICATE-----
84069 MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
84070 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
84071 KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
84072 MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
84073 MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
84074 Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
84075 Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
84076 OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
84077 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
84078 NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
84079 h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
84080 Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
84081 JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
84082 V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
84083 myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
84084 mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
84085 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
84086 -----END CERTIFICATE-----
84087
84088 Certplus Class 2 Primary CA
84089 ===========================
84090 -----BEGIN CERTIFICATE-----
84091 MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
84092 BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
84093 OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
84094 dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
84095 ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
84096 5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
84097 Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
84098 YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
84099 e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
84100 CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
84101 YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
84102 L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
84103 P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
84104 TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
84105 7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
84106 //1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
84107 l7+ijrRU
84108 -----END CERTIFICATE-----
84109
84110 DST Root CA X3
84111 ==============
84112 -----BEGIN CERTIFICATE-----
84113 MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
84114 ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
84115 DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
84116 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
84117 ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
84118 rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
84119 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
84120 xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
84121 utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
84122 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
84123 MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
84124 dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
84125 GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
84126 RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
84127 fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
84128 -----END CERTIFICATE-----
84129
84130 DST ACES CA X6
84131 ==============
84132 -----BEGIN CERTIFICATE-----
84133 MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG
84134 EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT
84135 MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha
84136 MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE
84137 CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC
84138 AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI
84139 DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa
84140 pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow
84141 GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy
84142 MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud
84143 EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu
84144 Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy
84145 dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU
84146 CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2
84147 5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t
84148 Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
84149 nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs
84150 vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3
84151 oKfN5XozNmr6mis=
84152 -----END CERTIFICATE-----
84153
84154 SwissSign Gold CA - G2
84155 ======================
84156 -----BEGIN CERTIFICATE-----
84157 MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
84158 EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
84159 MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
84160 c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
84161 AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
84162 t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
84163 jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
84164 vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
84165 ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
84166 AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
84167 jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
84168 peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
84169 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
84170 GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
84171 AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
84172 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
84173 L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
84174 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
84175 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
84176 Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
84177 Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
84178 mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
84179 vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
84180 KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
84181 NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
84182 viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
84183 -----END CERTIFICATE-----
84184
84185 SwissSign Silver CA - G2
84186 ========================
84187 -----BEGIN CERTIFICATE-----
84188 MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
84189 BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
84190 DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
84191 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
84192 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
84193 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
84194 +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
84195 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
84196 MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
84197 qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
84198 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
84199 ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
84200 celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
84201 CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
84202 BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
84203 tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
84204 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
84205 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
84206 kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
84207 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
84208 /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
84209 DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
84210 e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
84211 WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
84212 DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
84213 DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
84214 -----END CERTIFICATE-----
84215
84216 GeoTrust Primary Certification Authority
84217 ========================================
84218 -----BEGIN CERTIFICATE-----
84219 MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
84220 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
84221 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
84222 CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
84223 cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
84224 CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
84225 b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
84226 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
84227 RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
84228 tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
84229 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
84230 hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
84231 Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
84232 NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
84233 Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
84234 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
84235 -----END CERTIFICATE-----
84236
84237 thawte Primary Root CA
84238 ======================
84239 -----BEGIN CERTIFICATE-----
84240 MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
84241 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
84242 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
84243 cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
84244 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
84245 SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
84246 KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
84247 FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
84248 oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
84249 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
84250 q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
84251 aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
84252 afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
84253 VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
84254 AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
84255 uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
84256 xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
84257 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
84258 z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
84259 -----END CERTIFICATE-----
84260
84261 VeriSign Class 3 Public Primary Certification Authority - G5
84262 ============================================================
84263 -----BEGIN CERTIFICATE-----
84264 MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
84265 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
84266 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
84267 IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
84268 ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
84269 yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
84270 biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
84271 dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
84272 YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
84273 ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
84274 j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
84275 Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
84276 Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
84277 fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
84278 BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
84279 Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
84280 aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
84281 SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
84282 X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
84283 KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
84284 Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
84285 ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
84286 -----END CERTIFICATE-----
84287
84288 SecureTrust CA
84289 ==============
84290 -----BEGIN CERTIFICATE-----
84291 MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
84292 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
84293 dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
84294 BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
84295 ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
84296 OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
84297 DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
84298 GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
84299 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
84300 ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
84301 BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
84302 aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
84303 KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
84304 SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
84305 mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
84306 nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
84307 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
84308 -----END CERTIFICATE-----
84309
84310 Secure Global CA
84311 ================
84312 -----BEGIN CERTIFICATE-----
84313 MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
84314 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
84315 bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
84316 MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
84317 Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
84318 YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
84319 bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
84320 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
84321 HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
84322 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
84323 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
84324 oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
84325 MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
84326 OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
84327 CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
84328 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
84329 f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
84330 -----END CERTIFICATE-----
84331
84332 COMODO Certification Authority
84333 ==============================
84334 -----BEGIN CERTIFICATE-----
84335 MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
84336 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
84337 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
84338 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
84339 MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
84340 T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
84341 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
84342 +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
84343 xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
84344 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
84345 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
84346 rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
84347 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
84348 b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
84349 AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
84350 OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
84351 RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
84352 IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
84353 +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
84354 -----END CERTIFICATE-----
84355
84356 Network Solutions Certificate Authority
84357 =======================================
84358 -----BEGIN CERTIFICATE-----
84359 MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
84360 EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
84361 IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
84362 MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
84363 MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
84364 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
84365 jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
84366 aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
84367 crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
84368 /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
84369 AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
84370 BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
84371 bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
84372 A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
84373 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
84374 GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
84375 wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
84376 ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
84377 -----END CERTIFICATE-----
84378
84379 COMODO ECC Certification Authority
84380 ==================================
84381 -----BEGIN CERTIFICATE-----
84382 MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
84383 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
84384 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
84385 dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
84386 GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
84387 Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
84388 b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
84389 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
84390 wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
84391 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
84392 FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
84393 U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
84394 -----END CERTIFICATE-----
84395
84396 Security Communication EV RootCA1
84397 =================================
84398 -----BEGIN CERTIFICATE-----
84399 MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
84400 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh
84401 dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE
84402 BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl
84403 Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
84404 AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO
84405 /VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX
84406 WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z
84407 ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4
84408 bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK
84409 9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
84410 SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm
84411 iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG
84412 Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW
84413 mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW
84414 T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
84415 -----END CERTIFICATE-----
84416
84417 OISTE WISeKey Global Root GA CA
84418 ===============================
84419 -----BEGIN CERTIFICATE-----
84420 MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
84421 BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
84422 A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
84423 bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
84424 VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
84425 IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
84426 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
84427 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
84428 Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
84429 d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
84430 /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
84431 LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
84432 AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
84433 KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
84434 MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
84435 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
84436 hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
84437 okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
84438 -----END CERTIFICATE-----
84439
84440 Certigna
84441 ========
84442 -----BEGIN CERTIFICATE-----
84443 MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
84444 EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
84445 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
84446 Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
84447 XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
84448 GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
84449 ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
84450 DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
84451 Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
84452 tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
84453 BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
84454 SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
84455 hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
84456 ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
84457 PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
84458 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
84459 WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
84460 -----END CERTIFICATE-----
84461
84462 Deutsche Telekom Root CA 2
84463 ==========================
84464 -----BEGIN CERTIFICATE-----
84465 MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
84466 RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
84467 A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
84468 MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
84469 A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
84470 b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
84471 bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
84472 KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
84473 AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
84474 Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
84475 jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
84476 HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
84477 E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
84478 zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
84479 rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
84480 dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
84481 Cm26OWMohpLzGITY+9HPBVZkVw==
84482 -----END CERTIFICATE-----
84483
84484 Cybertrust Global Root
84485 ======================
84486 -----BEGIN CERTIFICATE-----
84487 MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
84488 ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
84489 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
84490 ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
84491 +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
84492 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
84493 AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
84494 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
84495 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
84496 BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
84497 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
84498 A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
84499 lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
84500 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
84501 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
84502 X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
84503 WL1WMRJOEcgh4LMRkWXbtKaIOM5V
84504 -----END CERTIFICATE-----
84505
84506 ePKI Root Certification Authority
84507 =================================
84508 -----BEGIN CERTIFICATE-----
84509 MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
84510 EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
84511 Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
84512 MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
84513 MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
84514 AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
84515 IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
84516 lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
84517 qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
84518 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
84519 WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
84520 ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
84521 lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
84522 vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
84523 Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
84524 MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
84525 ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
84526 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
84527 KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
84528 xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
84529 NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
84530 GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
84531 xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
84532 gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
84533 sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
84534 BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
84535 -----END CERTIFICATE-----
84536
84537 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
84538 =============================================================================================================================
84539 -----BEGIN CERTIFICATE-----
84540 MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH
84541 DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q
84542 aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry
84543 b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV
84544 BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg
84545 S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4
84546 MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl
84547 IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF
84548 n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl
84549 IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft
84550 dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl
84551 cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B
84552 AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO
84553 Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1
84554 xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR
84555 6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
84556 hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd
84557 BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
84558 MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4
84559 N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT
84560 y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh
84561 LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M
84562 dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI=
84563 -----END CERTIFICATE-----
84564
84565 certSIGN ROOT CA
84566 ================
84567 -----BEGIN CERTIFICATE-----
84568 MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
84569 VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
84570 Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
84571 CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
84572 JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
84573 rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
84574 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
84575 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
84576 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
84577 Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
84578 AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
84579 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
84580 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
84581 vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
84582 TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
84583 -----END CERTIFICATE-----
84584
84585 GeoTrust Primary Certification Authority - G3
84586 =============================================
84587 -----BEGIN CERTIFICATE-----
84588 MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
84589 BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
84590 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
84591 eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
84592 NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
84593 YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
84594 LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
84595 hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
84596 K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
84597 c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
84598 IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
84599 dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
84600 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
84601 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
84602 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
84603 Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
84604 AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
84605 t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
84606 -----END CERTIFICATE-----
84607
84608 thawte Primary Root CA - G2
84609 ===========================
84610 -----BEGIN CERTIFICATE-----
84611 MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
84612 VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
84613 IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
84614 Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
84615 MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
84616 b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
84617 IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
84618 LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
84619 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
84620 mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
84621 G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
84622 rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
84623 -----END CERTIFICATE-----
84624
84625 thawte Primary Root CA - G3
84626 ===========================
84627 -----BEGIN CERTIFICATE-----
84628 MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
84629 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
84630 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
84631 cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
84632 ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
84633 d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
84634 VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
84635 A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
84636 MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
84637 P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
84638 +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
84639 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
84640 vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
84641 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
84642 KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
84643 A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
84644 t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
84645 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
84646 er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
84647 -----END CERTIFICATE-----
84648
84649 GeoTrust Primary Certification Authority - G2
84650 =============================================
84651 -----BEGIN CERTIFICATE-----
84652 MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
84653 VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
84654 Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
84655 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
84656 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
84657 MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
84658 b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
84659 BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
84660 KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
84661 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
84662 EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
84663 ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
84664 npaqBA+K
84665 -----END CERTIFICATE-----
84666
84667 VeriSign Universal Root Certification Authority
84668 ===============================================
84669 -----BEGIN CERTIFICATE-----
84670 MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
84671 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
84672 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
84673 IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
84674 IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
84675 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
84676 cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
84677 IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
84678 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
84679 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
84680 MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
84681 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
84682 AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
84683 tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
84684 CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
84685 a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
84686 DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
84687 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
84688 Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
84689 P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
84690 wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
84691 mJO37M2CYfE45k+XmCpajQ==
84692 -----END CERTIFICATE-----
84693
84694 VeriSign Class 3 Public Primary Certification Authority - G4
84695 ============================================================
84696 -----BEGIN CERTIFICATE-----
84697 MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
84698 VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
84699 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
84700 ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
84701 YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
84702 MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
84703 cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
84704 b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
84705 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
84706 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
84707 rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
84708 /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
84709 HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
84710 Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
84711 A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
84712 AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
84713 -----END CERTIFICATE-----
84714
84715 NetLock Arany (Class Gold) Főtanúsítvány
84716 ========================================
84717 -----BEGIN CERTIFICATE-----
84718 MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
84719 A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
84720 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
84721 cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
84722 MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
84723 ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
84724 biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
84725 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
84726 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
84727 /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
84728 H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
84729 fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
84730 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
84731 BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
84732 qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
84733 YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
84734 bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
84735 NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
84736 dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
84737 -----END CERTIFICATE-----
84738
84739 Staat der Nederlanden Root CA - G2
84740 ==================================
84741 -----BEGIN CERTIFICATE-----
84742 MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
84743 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
84744 Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
84745 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
84746 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
84747 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
84748 vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
84749 CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
84750 e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
84751 OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
84752 CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
84753 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
84754 trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
84755 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
84756 AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
84757 ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
84758 HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
84759 A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
84760 +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
84761 f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
84762 kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
84763 CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
84764 URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
84765 CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
84766 oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
84767 IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
84768 66+KAQ==
84769 -----END CERTIFICATE-----
84770
84771 Hongkong Post Root CA 1
84772 =======================
84773 -----BEGIN CERTIFICATE-----
84774 MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
84775 DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
84776 NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
84777 IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
84778 AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
84779 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
84780 auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
84781 qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
84782 V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
84783 HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
84784 h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
84785 l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
84786 IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
84787 T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
84788 c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
84789 -----END CERTIFICATE-----
84790
84791 SecureSign RootCA11
84792 ===================
84793 -----BEGIN CERTIFICATE-----
84794 MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
84795 SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
84796 b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
84797 KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
84798 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
84799 TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
84800 wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
84801 g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
84802 O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
84803 bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
84804 t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
84805 OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
84806 bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
84807 Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
84808 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
84809 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
84810 -----END CERTIFICATE-----
84811
84812 ACEDICOM Root
84813 =============
84814 -----BEGIN CERTIFICATE-----
84815 MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD
84816 T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4
84817 MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG
84818 A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF
84819 AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk
84820 WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD
84821 YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew
84822 MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb
84823 m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk
84824 HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT
84825 xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2
84826 3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9
84827 2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq
84828 TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz
84829 4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU
84830 9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
84831 bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg
84832 aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP
84833 eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk
84834 zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1
84835 ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI
84836 KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq
84837 nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE
84838 I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp
84839 MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o
84840 tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA==
84841 -----END CERTIFICATE-----
84842
84843 Microsec e-Szigno Root CA 2009
84844 ==============================
84845 -----BEGIN CERTIFICATE-----
84846 MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
84847 MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
84848 c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
84849 dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
84850 BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
84851 U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
84852 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
84853 fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
84854 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
84855 pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
84856 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
84857 AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
84858 QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
84859 FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
84860 lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
84861 I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
84862 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
84863 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
84864 LXpUq3DDfSJlgnCW
84865 -----END CERTIFICATE-----
84866
84867 GlobalSign Root CA - R3
84868 =======================
84869 -----BEGIN CERTIFICATE-----
84870 MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
84871 YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
84872 bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
84873 aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
84874 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
84875 iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
84876 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
84877 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
84878 OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
84879 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
84880 FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
84881 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
84882 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
84883 bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
84884 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
84885 kpeDMdmztcpHWD9f
84886 -----END CERTIFICATE-----
84887
84888 Autoridad de Certificacion Firmaprofesional CIF A62634068
84889 =========================================================
84890 -----BEGIN CERTIFICATE-----
84891 MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
84892 BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
84893 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
84894 QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
84895 NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
84896 Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
84897 B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
84898 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
84899 ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
84900 plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
84901 MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
84902 LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
84903 bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
84904 vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
84905 EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
84906 DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
84907 cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
84908 bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
84909 ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
84910 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
84911 R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
84912 T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
84913 Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
84914 osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
84915 crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
84916 saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
84917 KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
84918 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
84919 -----END CERTIFICATE-----
84920
84921 Izenpe.com
84922 ==========
84923 -----BEGIN CERTIFICATE-----
84924 MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
84925 EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
84926 MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
84927 QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
84928 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
84929 ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
84930 +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
84931 PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
84932 OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
84933 F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
84934 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
84935 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
84936 leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
84937 AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
84938 SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
84939 NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
84940 MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
84941 BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
84942 Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
84943 kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
84944 hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
84945 g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
84946 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
84947 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
84948 ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
84949 Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
84950 WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
84951 -----END CERTIFICATE-----
84952
84953 Chambers of Commerce Root - 2008
84954 ================================
84955 -----BEGIN CERTIFICATE-----
84956 MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
84957 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
84958 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
84959 QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
84960 Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
84961 ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
84962 EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
84963 cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
84964 AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
84965 XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
84966 h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
84967 ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
84968 NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
84969 D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
84970 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
84971 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
84972 ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
84973 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
84974 G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
84975 BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
84976 bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
84977 bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
84978 CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
84979 AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
84980 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
84981 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
84982 RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
84983 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
84984 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
84985 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
84986 zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
84987 nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
84988 OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
84989 -----END CERTIFICATE-----
84990
84991 Global Chambersign Root - 2008
84992 ==============================
84993 -----BEGIN CERTIFICATE-----
84994 MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
84995 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
84996 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
84997 QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
84998 NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
84999 Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
85000 QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
85001 aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
85002 VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
85003 XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
85004 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
85005 /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
85006 TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
85007 H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
85008 Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
85009 HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
85010 wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
85011 AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
85012 BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
85013 BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
85014 aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
85015 aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
85016 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
85017 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
85018 /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
85019 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
85020 dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
85021 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
85022 foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
85023 qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
85024 P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
85025 c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
85026 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
85027 -----END CERTIFICATE-----
85028
85029 Go Daddy Root Certificate Authority - G2
85030 ========================================
85031 -----BEGIN CERTIFICATE-----
85032 MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
85033 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
85034 MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
85035 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
85036 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
85037 A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
85038 hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
85039 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
85040 +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
85041 fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
85042 NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
85043 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
85044 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
85045 vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
85046 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
85047 N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
85048 LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
85049 -----END CERTIFICATE-----
85050
85051 Starfield Root Certificate Authority - G2
85052 =========================================
85053 -----BEGIN CERTIFICATE-----
85054 MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
85055 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
85056 b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
85057 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
85058 DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
85059 VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
85060 dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
85061 W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
85062 bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
85063 N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
85064 ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
85065 JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
85066 AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
85067 TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
85068 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
85069 F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
85070 pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
85071 c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
85072 -----END CERTIFICATE-----
85073
85074 Starfield Services Root Certificate Authority - G2
85075 ==================================================
85076 -----BEGIN CERTIFICATE-----
85077 MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
85078 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
85079 b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
85080 IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
85081 BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
85082 dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
85083 Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
85084 AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
85085 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
85086 hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
85087 LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
85088 rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
85089 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
85090 SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
85091 E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
85092 xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
85093 iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
85094 YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
85095 -----END CERTIFICATE-----
85096
85097 AffirmTrust Commercial
85098 ======================
85099 -----BEGIN CERTIFICATE-----
85100 MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
85101 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
85102 MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
85103 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
85104 AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
85105 DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
85106 C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
85107 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
85108 MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
85109 HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
85110 AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
85111 hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
85112 qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
85113 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
85114 sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
85115 -----END CERTIFICATE-----
85116
85117 AffirmTrust Networking
85118 ======================
85119 -----BEGIN CERTIFICATE-----
85120 MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
85121 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
85122 MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
85123 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
85124 AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
85125 Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
85126 dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
85127 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
85128 h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
85129 HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
85130 AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
85131 UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
85132 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
85133 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
85134 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
85135 -----END CERTIFICATE-----
85136
85137 AffirmTrust Premium
85138 ===================
85139 -----BEGIN CERTIFICATE-----
85140 MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
85141 BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
85142 OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
85143 dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
85144 MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
85145 BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
85146 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
85147 +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
85148 GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
85149 p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
85150 S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
85151 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
85152 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
85153 +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
85154 /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
85155 MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
85156 Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
85157 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
85158 L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
85159 +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
85160 BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
85161 IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
85162 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
85163 zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
85164 -----END CERTIFICATE-----
85165
85166 AffirmTrust Premium ECC
85167 =======================
85168 -----BEGIN CERTIFICATE-----
85169 MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
85170 BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
85171 MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
85172 cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
85173 IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
85174 N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
85175 BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
85176 BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
85177 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
85178 eQ==
85179 -----END CERTIFICATE-----
85180
85181 Certum Trusted Network CA
85182 =========================
85183 -----BEGIN CERTIFICATE-----
85184 MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
85185 ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
85186 biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
85187 MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
85188 ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
85189 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
85190 AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
85191 l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
85192 J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
85193 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
85194 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
85195 Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
85196 DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
85197 jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
85198 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
85199 Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
85200 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
85201 -----END CERTIFICATE-----
85202
85203 Certinomis - Autorité Racine
85204 ============================
85205 -----BEGIN CERTIFICATE-----
85206 MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
85207 Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg
85208 LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG
85209 A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw
85210 JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD
85211 ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa
85212 wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly
85213 Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw
85214 2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N
85215 jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q
85216 c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC
85217 lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb
85218 xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g
85219 530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna
85220 4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
85221 A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ
85222 KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x
85223 WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva
85224 R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40
85225 nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B
85226 CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv
85227 JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE
85228 qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b
85229 WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE
85230 wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/
85231 vgt2Fl43N+bYdJeimUV5
85232 -----END CERTIFICATE-----
85233
85234 TWCA Root Certification Authority
85235 =================================
85236 -----BEGIN CERTIFICATE-----
85237 MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
85238 VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
85239 dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
85240 EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
85241 IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
85242 AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
85243 QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
85244 oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
85245 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
85246 y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
85247 BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
85248 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
85249 mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
85250 QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
85251 T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
85252 Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
85253 -----END CERTIFICATE-----
85254
85255 Security Communication RootCA2
85256 ==============================
85257 -----BEGIN CERTIFICATE-----
85258 MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
85259 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
85260 dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
85261 SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
85262 aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
85263 ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
85264 +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
85265 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
85266 spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
85267 EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
85268 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
85269 CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
85270 u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
85271 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
85272 tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
85273 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
85274 -----END CERTIFICATE-----
85275
85276 EC-ACC
85277 ======
85278 -----BEGIN CERTIFICATE-----
85279 MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
85280 BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
85281 ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
85282 VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
85283 CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
85284 BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
85285 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
85286 SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
85287 Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
85288 cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
85289 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
85290 w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
85291 ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
85292 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
85293 E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
85294 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
85295 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
85296 VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
85297 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
85298 dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
85299 lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
85300 Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
85301 l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
85302 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
85303 5EI=
85304 -----END CERTIFICATE-----
85305
85306 Hellenic Academic and Research Institutions RootCA 2011
85307 =======================================================
85308 -----BEGIN CERTIFICATE-----
85309 MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
85310 O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
85311 aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
85312 IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
85313 AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
85314 IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
85315 IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
85316 AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
85317 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
85318 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
85319 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
85320 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
85321 MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
85322 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
85323 b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
85324 XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
85325 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
85326 /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
85327 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
85328 -----END CERTIFICATE-----
85329
85330 Actalis Authentication Root CA
85331 ==============================
85332 -----BEGIN CERTIFICATE-----
85333 MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
85334 BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
85335 AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
85336 MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
85337 IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
85338 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
85339 wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
85340 by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
85341 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
85342 YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
85343 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
85344 EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
85345 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
85346 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
85347 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
85348 iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
85349 ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
85350 WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
85351 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
85352 K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
85353 Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
85354 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
85355 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
85356 lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
85357 OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
85358 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
85359 -----END CERTIFICATE-----
85360
85361 Trustis FPS Root CA
85362 ===================
85363 -----BEGIN CERTIFICATE-----
85364 MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
85365 EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
85366 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
85367 BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
85368 KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
85369 RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
85370 H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
85371 cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
85372 o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
85373 AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
85374 BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
85375 GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
85376 yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
85377 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
85378 l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
85379 iB6XzCGcKQENZetX2fNXlrtIzYE=
85380 -----END CERTIFICATE-----
85381
85382 StartCom Certification Authority
85383 ================================
85384 -----BEGIN CERTIFICATE-----
85385 MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
85386 U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
85387 ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
85388 NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
85389 LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
85390 U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
85391 ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
85392 o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
85393 Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
85394 eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
85395 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
85396 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
85397 osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
85398 untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
85399 UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
85400 37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
85401 VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ
85402 Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0
85403 dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu
85404 c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv
85405 bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0
85406 aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0
85407 aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t
85408 L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG
85409 cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5
85410 fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm
85411 N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN
85412 Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T
85413 tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX
85414 e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA
85415 2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs
85416 HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
85417 JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib
85418 D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8=
85419 -----END CERTIFICATE-----
85420
85421 StartCom Certification Authority G2
85422 ===================================
85423 -----BEGIN CERTIFICATE-----
85424 MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
85425 U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
85426 RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE
85427 ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp
85428 dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O
85429 o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG
85430 4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi
85431 Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul
85432 Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs
85433 O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H
85434 vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L
85435 nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS
85436 FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa
85437 z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E
85438 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ
85439 KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
85440 2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk
85441 J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+
85442 JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG
85443 /+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc
85444 nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld
85445 blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc
85446 l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm
85447 7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm
85448 obp573PYtlNXLfbQ4ddI
85449 -----END CERTIFICATE-----
85450
85451 Buypass Class 2 Root CA
85452 =======================
85453 -----BEGIN CERTIFICATE-----
85454 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
85455 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
85456 DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
85457 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
85458 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
85459 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
85460 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
85461 /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
85462 CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
85463 awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
85464 zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
85465 Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
85466 Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
85467 M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
85468 VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
85469 AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
85470 A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
85471 osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
85472 aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
85473 DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
85474 LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
85475 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
85476 wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
85477 CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
85478 rJgWVqA=
85479 -----END CERTIFICATE-----
85480
85481 Buypass Class 3 Root CA
85482 =======================
85483 -----BEGIN CERTIFICATE-----
85484 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
85485 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
85486 DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
85487 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
85488 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
85489 sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
85490 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
85491 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
85492 ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
85493 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
85494 /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
85495 RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
85496 Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
85497 j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
85498 VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
85499 AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
85500 cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
85501 uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
85502 Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
85503 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
85504 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
85505 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
85506 UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
85507 eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
85508 Cp/HuZc=
85509 -----END CERTIFICATE-----
85510
85511 T-TeleSec GlobalRoot Class 3
85512 ============================
85513 -----BEGIN CERTIFICATE-----
85514 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
85515 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
85516 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
85517 MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
85518 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
85519 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
85520 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
85521 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
85522 NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
85523 iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
85524 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
85525 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
85526 AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
85527 fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
85528 ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
85529 P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
85530 e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
85531 -----END CERTIFICATE-----
85532
85533 EE Certification Centre Root CA
85534 ===============================
85535 -----BEGIN CERTIFICATE-----
85536 MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
85537 EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
85538 dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
85539 MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
85540 UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
85541 ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
85542 DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
85543 TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
85544 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
85545 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
85546 P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
85547 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
85548 MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
85549 BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
85550 xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
85551 lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
85552 uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
85553 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
85554 dcGWxZ0=
85555 -----END CERTIFICATE-----
85556
85557 TURKTRUST Certificate Services Provider Root 2007
85558 =================================================
85559 -----BEGIN CERTIFICATE-----
85560 MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
85561 bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
85562 MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
85563 QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X
85564 DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl
85565 a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN
85566 BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
85567 bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw
85568 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N
85569 YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv
85570 KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya
85571 KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT
85572 rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC
85573 AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP
85574 BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s
85575 Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I
85576 aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO
85577 Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb
85578 BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK
85579 poRq0Tl9
85580 -----END CERTIFICATE-----
85581
85582 D-TRUST Root Class 3 CA 2 2009
85583 ==============================
85584 -----BEGIN CERTIFICATE-----
85585 MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85586 DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
85587 Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
85588 LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
85589 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
85590 ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
85591 BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
85592 KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
85593 p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
85594 AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
85595 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
85596 eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
85597 MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
85598 PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
85599 OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
85600 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
85601 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
85602 dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
85603 X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
85604 -----END CERTIFICATE-----
85605
85606 D-TRUST Root Class 3 CA 2 EV 2009
85607 =================================
85608 -----BEGIN CERTIFICATE-----
85609 MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85610 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
85611 OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85612 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
85613 OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
85614 egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
85615 zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
85616 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
85617 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
85618 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
85619 cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
85620 ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
85621 MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
85622 b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
85623 c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
85624 PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
85625 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
85626 ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
85627 NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
85628 w9y4AyHqnxbxLFS1
85629 -----END CERTIFICATE-----
85630
85631 PSCProcert
85632 ==========
85633 -----BEGIN CERTIFICATE-----
85634 MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1dG9yaWRhZCBk
85635 ZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9sYW5vMQswCQYDVQQGEwJWRTEQ
85636 MA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlzdHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lz
85637 dGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBl
85638 cmludGVuZGVuY2lhIGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUw
85639 IwYJKoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEwMFoXDTIw
85640 MTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHByb2NlcnQubmV0LnZlMQ8w
85641 DQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGExKjAoBgNVBAsTIVByb3ZlZWRvciBkZSBD
85642 ZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZp
85643 Y2FjaW9uIEVsZWN0cm9uaWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIw
85644 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo97BVC
85645 wfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74BCXfgI8Qhd19L3uA
85646 3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38GieU89RLAu9MLmV+QfI4tL3czkkoh
85647 RqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmO
85648 EO8GqQKJ/+MMbpfg353bIdD0PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG2
85649 0qCZyFSTXai20b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH
85650 0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/6mnbVSKVUyqU
85651 td+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1mv6JpIzi4mWCZDlZTOpx+FIyw
85652 Bm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvp
85653 r2uKGcfLFFb14dq12fy/czja+eevbqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/
85654 AgEBMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAz
85655 Ni0wMB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFDgBStuyId
85656 xuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRp
85657 ZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQH
85658 EwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5h
85659 Y2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5k
85660 ZW5jaWEgZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG
85661 9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQDAgEGME0GA1UdEQRG
85662 MESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0wMDAwMDKgGwYFYIZeAgKgEgwQUklG
85663 LUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEagRKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52
85664 ZS9sY3IvQ0VSVElGSUNBRE8tUkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNy
85665 YWl6LnN1c2NlcnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v
85666 Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsGAQUFBwIBFh5o
85667 dHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcNAQELBQADggIBACtZ6yKZu4Sq
85668 T96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmN
85669 g7+mvTV+LFwxNG9s2/NkAZiqlCxB3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4q
85670 uxtxj7mkoP3YldmvWb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1
85671 n8GhHVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHmpHmJWhSn
85672 FFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXzsOfIt+FTvZLm8wyWuevo
85673 5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bEqCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq
85674 3TNWOByyrYDT13K9mmyZY+gAu0F2BbdbmRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5
85675 poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y
85676 eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km
85677 -----END CERTIFICATE-----
85678
85679 CA Disig Root R1
85680 ================
85681 -----BEGIN CERTIFICATE-----
85682 MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNVBAYTAlNLMRMw
85683 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
85684 ZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQyMDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sx
85685 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
85686 c2lnIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy
85687 3QRkD2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/oOI7bm+V8
85688 u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3AfQ+lekLZWnDZv6fXARz2
85689 m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJeIgpFy4QxTaz+29FHuvlglzmxZcfe+5nk
85690 CiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8noc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTa
85691 YVKvJrT1cU/J19IG32PK/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6
85692 vpmumwKjrckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD3AjL
85693 LhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE7cderVC6xkGbrPAX
85694 ZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkCyC2fg69naQanMVXVz0tv/wQFx1is
85695 XxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLdqvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNV
85696 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ
85697 04IwDQYJKoZIhvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR
85698 xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaASfX8MPWbTx9B
85699 LxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXoHqJPYNcHKfyyo6SdbhWSVhlM
85700 CrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpBemOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5Gfb
85701 VSUZP/3oNn6z4eGBrxEWi1CXYBmCAMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85
85702 YmLLW1AL14FABZyb7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKS
85703 ds+xDzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvkF7mGnjix
85704 lAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqFa3qdnom2piiZk4hA9z7N
85705 UaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsTQ6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJ
85706 a7+h89n07eLw4+1knj0vllJPgFOL
85707 -----END CERTIFICATE-----
85708
85709 CA Disig Root R2
85710 ================
85711 -----BEGIN CERTIFICATE-----
85712 MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
85713 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
85714 ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
85715 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
85716 c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
85717 w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
85718 xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
85719 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
85720 GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
85721 g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
85722 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
85723 koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
85724 Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
85725 Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
85726 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
85727 Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
85728 tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
85729 sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
85730 dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
85731 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
85732 mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
85733 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
85734 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
85735 UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
85736 7+ZtsH8tZ/3zbBt1RqPlShfppNcL
85737 -----END CERTIFICATE-----
85738
85739 ACCVRAIZ1
85740 =========
85741 -----BEGIN CERTIFICATE-----
85742 MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
85743 SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
85744 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
85745 UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
85746 DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
85747 jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
85748 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
85749 aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
85750 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
85751 WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
85752 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
85753 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
85754 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
85755 Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
85756 Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
85757 Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
85758 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
85759 Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
85760 QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
85761 AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
85762 YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
85763 AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
85764 IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
85765 aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
85766 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
85767 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
85768 hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
85769 R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
85770 YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
85771 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
85772 TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
85773 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
85774 I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
85775 Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
85776 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
85777 EfbRD0tVNEYqi4Y7
85778 -----END CERTIFICATE-----
85779
85780 TWCA Global Root CA
85781 ===================
85782 -----BEGIN CERTIFICATE-----
85783 MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
85784 CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
85785 QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
85786 EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
85787 Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
85788 nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
85789 r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
85790 Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
85791 tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
85792 KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
85793 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
85794 yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
85795 kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
85796 zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
85797 AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
85798 cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
85799 LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
85800 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
85801 /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
85802 lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
85803 A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
85804 i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
85805 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
85806 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
85807 -----END CERTIFICATE-----
85808
85809 TeliaSonera Root CA v1
85810 ======================
85811 -----BEGIN CERTIFICATE-----
85812 MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
85813 CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
85814 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
85815 VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
85816 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
85817 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
85818 B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
85819 Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
85820 oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
85821 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
85822 oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
85823 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
85824 TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
85825 AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
85826 DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
85827 zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
85828 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
85829 pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
85830 G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
85831 c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
85832 JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
85833 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
85834 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
85835 WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
85836 -----END CERTIFICATE-----
85837
85838 E-Tugra Certification Authority
85839 ===============================
85840 -----BEGIN CERTIFICATE-----
85841 MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
85842 DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
85843 ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
85844 ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
85845 NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
85846 QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
85847 cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
85848 DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
85849 MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
85850 hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
85851 CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
85852 ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
85853 BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
85854 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
85855 rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
85856 jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
85857 rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
85858 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
85859 /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
85860 MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
85861 kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
85862 XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
85863 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
85864 a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
85865 dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
85866 KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
85867 Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
85868 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
85869 C7TbO6Orb1wdtn7os4I07QZcJA==
85870 -----END CERTIFICATE-----
85871
85872 T-TeleSec GlobalRoot Class 2
85873 ============================
85874 -----BEGIN CERTIFICATE-----
85875 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
85876 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
85877 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
85878 MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
85879 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
85880 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
85881 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
85882 SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
85883 vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
85884 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
85885 WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
85886 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
85887 YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
85888 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
85889 vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
85890 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
85891 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
85892 -----END CERTIFICATE-----
85893
85894 Atos TrustedRoot 2011
85895 =====================
85896 -----BEGIN CERTIFICATE-----
85897 MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
85898 cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
85899 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
85900 A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
85901 hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
85902 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
85903 DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
85904 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
85905 z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
85906 l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
85907 bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
85908 CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
85909 k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
85910 TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
85911 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
85912 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
85913 -----END CERTIFICATE-----
85914
85915 QuoVadis Root CA 1 G3
85916 =====================
85917 -----BEGIN CERTIFICATE-----
85918 MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
85919 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85920 b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
85921 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
85922 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
85923 PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
85924 PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
85925 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
85926 ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
85927 g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
85928 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
85929 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
85930 iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
85931 t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85932 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
85933 hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
85934 MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
85935 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
85936 Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
85937 +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
85938 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
85939 wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
85940 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
85941 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
85942 hMJKzRwuJIczYOXD
85943 -----END CERTIFICATE-----
85944
85945 QuoVadis Root CA 2 G3
85946 =====================
85947 -----BEGIN CERTIFICATE-----
85948 MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
85949 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85950 b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
85951 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
85952 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
85953 ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
85954 NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
85955 oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
85956 MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
85957 V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
85958 L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
85959 sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
85960 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
85961 lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85962 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
85963 hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
85964 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
85965 pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
85966 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
85967 dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
85968 U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
85969 mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
85970 zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
85971 JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
85972 O3jtZsSOeWmD3n+M
85973 -----END CERTIFICATE-----
85974
85975 QuoVadis Root CA 3 G3
85976 =====================
85977 -----BEGIN CERTIFICATE-----
85978 MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
85979 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85980 b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
85981 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
85982 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
85983 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
85984 Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
85985 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
85986 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
85987 VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
85988 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
85989 Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
85990 dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
85991 rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85992 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
85993 hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
85994 KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
85995 t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
85996 TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
85997 DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
85998 Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
85999 hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
86000 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
86001 dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
86002 PpxxVJkES/1Y+Zj0
86003 -----END CERTIFICATE-----
86004
86005 DigiCert Assured ID Root G2
86006 ===========================
86007 -----BEGIN CERTIFICATE-----
86008 MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
86009 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
86010 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
86011 MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
86012 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
86013 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
86014 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
86015 bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
86016 VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
86017 YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
86018 lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
86019 w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
86020 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
86021 d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
86022 hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
86023 jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
86024 IhNzbM8m9Yop5w==
86025 -----END CERTIFICATE-----
86026
86027 DigiCert Assured ID Root G3
86028 ===========================
86029 -----BEGIN CERTIFICATE-----
86030 MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
86031 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
86032 VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
86033 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
86034 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
86035 BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
86036 RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
86037 KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
86038 UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
86039 YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
86040 1vUhZscv6pZjamVFkpUBtA==
86041 -----END CERTIFICATE-----
86042
86043 DigiCert Global Root G2
86044 =======================
86045 -----BEGIN CERTIFICATE-----
86046 MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
86047 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
86048 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
86049 MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
86050 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
86051 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
86052 kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
86053 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
86054 BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
86055 UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
86056 o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
86057 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
86058 F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
86059 WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
86060 QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
86061 iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
86062 MrY=
86063 -----END CERTIFICATE-----
86064
86065 DigiCert Global Root G3
86066 =======================
86067 -----BEGIN CERTIFICATE-----
86068 MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
86069 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
86070 VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
86071 MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
86072 aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
86073 AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
86074 YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
86075 BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
86076 Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
86077 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
86078 VOKa5Vt8sycX
86079 -----END CERTIFICATE-----
86080
86081 DigiCert Trusted Root G4
86082 ========================
86083 -----BEGIN CERTIFICATE-----
86084 MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
86085 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
86086 HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
86087 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
86088 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
86089 CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
86090 pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
86091 k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
86092 vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
86093 QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
86094 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
86095 mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
86096 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
86097 dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
86098 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
86099 DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
86100 ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
86101 ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
86102 yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
86103 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
86104 ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
86105 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
86106 /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
86107 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
86108 G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
86109 82Z+
86110 -----END CERTIFICATE-----
86111
86112 WoSign
86113 ======
86114 -----BEGIN CERTIFICATE-----
86115 MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQG
86116 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNVBAMTIUNlcnRpZmljYXRpb24g
86117 QXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJ
86118 BgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNh
86119 dGlvbiBBdXRob3JpdHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
86120 vcqNrLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1UfcIiePyO
86121 CbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcSccf+Hb0v1naMQFXQoOXXDX
86122 2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2ZjC1vt7tj/id07sBMOby8w7gLJKA84X5
86123 KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4Mx1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR
86124 +ScPewavVIMYe+HdVHpRaG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ez
86125 EC8wQjchzDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDaruHqk
86126 lWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221KmYo0SLwX3OSACCK2
86127 8jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvASh0JWzko/amrzgD5LkhLJuYwTKVY
86128 yrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWvHYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0C
86129 AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R
86130 8bNLtwYgFP6HEtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1
86131 LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJMuYhOZO9sxXq
86132 T2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2eJXLOC62qx1ViC777Y7NhRCOj
86133 y+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VNg64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC
86134 2nz4SNAzqfkHx5Xh9T71XXG68pWpdIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes
86135 5cVAWubXbHssw1abR80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/
86136 EaEQPkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGcexGATVdVh
86137 mVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+J7x6v+Db9NpSvd4MVHAx
86138 kUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMlOtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGi
86139 kpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWTee5Ehr7XHuQe+w==
86140 -----END CERTIFICATE-----
86141
86142 WoSign China
86143 ============
86144 -----BEGIN CERTIFICATE-----
86145 MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQG
86146 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMMEkNBIOayg+mAmuagueiv
86147 geS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYD
86148 VQQKExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjAN
86149 BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k
86150 8H/rD195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld19AXbbQs5
86151 uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExfv5RxadmWPgxDT74wwJ85
86152 dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnkUkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5
86153 Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+LNVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFy
86154 b7Ao65vh4YOhn0pdr8yb+gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc
86155 76DbT52VqyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6KyX2m
86156 +Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0GAbQOXDBGVWCvOGU6
86157 yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaKJ/kR8slC/k7e3x9cxKSGhxYzoacX
86158 GKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwECAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
86159 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUA
86160 A4ICAQBqinA4WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6
86161 yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj/feTZU7n85iY
86162 r83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6jBAyvd0zaziGfjk9DgNyp115
86163 j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0A
86164 kLppRQjbbpCBhqcqBT/mhDn4t/lXX0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97
86165 qA4bLJyuQHCH2u2nFoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Y
86166 jj4Du9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10lO1Hm13ZB
86167 ONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Leie2uPAmvylezkolwQOQv
86168 T8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR12KvxAmLBsX5VYc8T1yaw15zLKYs4SgsO
86169 kI26oQ==
86170 -----END CERTIFICATE-----
86171
86172 COMODO RSA Certification Authority
86173 ==================================
86174 -----BEGIN CERTIFICATE-----
86175 MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
86176 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
86177 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
86178 biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
86179 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
86180 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
86181 dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
86182 dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
86183 FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
86184 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
86185 x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
86186 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
86187 OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
86188 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
86189 GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
86190 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
86191 FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
86192 DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
86193 rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
86194 nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
86195 tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
86196 sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
86197 pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
86198 zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
86199 ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
86200 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
86201 LaZRfyHBNVOFBkpdn627G190
86202 -----END CERTIFICATE-----
86203
86204 USERTrust RSA Certification Authority
86205 =====================================
86206 -----BEGIN CERTIFICATE-----
86207 MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
86208 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
86209 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
86210 dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
86211 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
86212 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
86213 dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
86214 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
86215 Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
86216 RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
86217 +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
86218 /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
86219 Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
86220 lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
86221 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
86222 eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
86223 BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
86224 MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
86225 FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
86226 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
86227 Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
86228 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
86229 FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
86230 yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
86231 J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
86232 sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
86233 Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
86234 -----END CERTIFICATE-----
86235
86236 USERTrust ECC Certification Authority
86237 =====================================
86238 -----BEGIN CERTIFICATE-----
86239 MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
86240 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
86241 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
86242 biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
86243 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
86244 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
86245 biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
86246 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
86247 nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
86248 HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
86249 HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
86250 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
86251 -----END CERTIFICATE-----
86252
86253 GlobalSign ECC Root CA - R4
86254 ===========================
86255 -----BEGIN CERTIFICATE-----
86256 MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
86257 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
86258 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
86259 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
86260 EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
86261 OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
86262 AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
86263 MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
86264 JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
86265 -----END CERTIFICATE-----
86266
86267 GlobalSign ECC Root CA - R5
86268 ===========================
86269 -----BEGIN CERTIFICATE-----
86270 MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
86271 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
86272 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
86273 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
86274 EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
86275 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
86276 h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
86277 BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
86278 uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
86279 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
86280 -----END CERTIFICATE-----
86281
86282 Staat der Nederlanden Root CA - G3
86283 ==================================
86284 -----BEGIN CERTIFICATE-----
86285 MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
86286 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
86287 Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
86288 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
86289 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
86290 olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
86291 x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
86292 EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
86293 Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
86294 mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
86295 1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
86296 07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
86297 FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
86298 41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
86299 AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
86300 yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
86301 U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
86302 KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
86303 v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
86304 8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
86305 8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
86306 mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
86307 1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
86308 JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
86309 tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
86310 -----END CERTIFICATE-----
86311
86312 Staat der Nederlanden EV Root CA
86313 ================================
86314 -----BEGIN CERTIFICATE-----
86315 MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
86316 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
86317 RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
86318 MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
86319 cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
86320 SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
86321 O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
86322 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
86323 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
86324 XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
86325 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
86326 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
86327 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
86328 fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
86329 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
86330 ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
86331 eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
86332 c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
86333 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
86334 b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
86335 f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
86336 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
86337 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
86338 DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
86339 eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
86340 -----END CERTIFICATE-----
86341
86342 IdenTrust Commercial Root CA 1
86343 ==============================
86344 -----BEGIN CERTIFICATE-----
86345 MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
86346 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
86347 b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
86348 MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
86349 IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
86350 hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
86351 mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
86352 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
86353 XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
86354 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
86355 NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
86356 WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
86357 xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
86358 uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
86359 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
86360 hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
86361 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
86362 ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
86363 ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
86364 YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
86365 feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
86366 kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
86367 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
86368 Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
86369 cGzM7vRX+Bi6hG6H
86370 -----END CERTIFICATE-----
86371
86372 IdenTrust Public Sector Root CA 1
86373 =================================
86374 -----BEGIN CERTIFICATE-----
86375 MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
86376 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
86377 ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
86378 UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
86379 b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
86380 P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
86381 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
86382 rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
86383 qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
86384 mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
86385 ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
86386 LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
86387 iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
86388 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
86389 Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
86390 DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
86391 t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
86392 mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
86393 GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
86394 m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
86395 NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
86396 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
86397 ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
86398 ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
86399 3Wl9af0AVqW3rLatt8o+Ae+c
86400 -----END CERTIFICATE-----
86401
86402 Entrust Root Certification Authority - G2
86403 =========================================
86404 -----BEGIN CERTIFICATE-----
86405 MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
86406 BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
86407 bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
86408 b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
86409 HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
86410 DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
86411 OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
86412 eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
86413 MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
86414 /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
86415 HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
86416 s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
86417 TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
86418 AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
86419 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
86420 iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
86421 Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
86422 nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
86423 vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
86424 e4pIb4tF9g==
86425 -----END CERTIFICATE-----
86426
86427 Entrust Root Certification Authority - EC1
86428 ==========================================
86429 -----BEGIN CERTIFICATE-----
86430 MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
86431 FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
86432 YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
86433 ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
86434 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
86435 FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
86436 LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
86437 dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
86438 IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
86439 AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
86440 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
86441 FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
86442 vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
86443 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
86444 -----END CERTIFICATE-----
86445
86446 CFCA EV ROOT
86447 ============
86448 -----BEGIN CERTIFICATE-----
86449 MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
86450 CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
86451 IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
86452 MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
86453 DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
86454 BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
86455 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
86456 uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
86457 ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
86458 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
86459 py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
86460 gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
86461 hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
86462 tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
86463 BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
86464 /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
86465 ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
86466 ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
86467 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
86468 E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
86469 BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
86470 aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
86471 PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
86472 kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
86473 ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
86474 -----END CERTIFICATE-----
86475
86476 TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5
86477 ====================================================
86478 -----BEGIN CERTIFICATE-----
86479 MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UEBhMCVFIxDzAN
86480 BgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
86481 bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1Qg
86482 RWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAw
86483 ODA3MDFaFw0yMzA0MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0w
86484 SwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnE
86485 n2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRp
86486 ZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
86487 CgKCAQEApCUZ4WWe60ghUEoI5RHwWrom/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537
86488 jVJp45wnEFPzpALFp/kRGml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1m
86489 ep5Fimh34khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z5UNP
86490 9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0hO8EuPbJbKoCPrZV
86491 4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QIDAQABo0IwQDAdBgNVHQ4EFgQUVpkH
86492 HtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
86493 hvcNAQELBQADggEBAJ5FdnsXSDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPo
86494 BP5yCccLqh0lVX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq
86495 URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nfpeYVhDfwwvJl
86496 lpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CFYv4HAqGEVka+lgqaE9chTLd8
86497 B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW+qtB4Uu2NQvAmxU=
86498 -----END CERTIFICATE-----
86499
86500 Certinomis - Root CA
86501 ====================
86502 -----BEGIN CERTIFICATE-----
86503 MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
86504 Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg
86505 LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx
86506 EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD
86507 ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos
86508 P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo
86509 d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap
86510 z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00
86511 8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x
86512 RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE
86513 6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t
86514 FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV
86515 PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH
86516 i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj
86517 YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I
86518 6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF
86519 AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV
86520 WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw
86521 Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX
86522 lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ
86523 y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9
86524 Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng
86525 DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi
86526 I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM
86527 cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr
86528 hkIGuUE=
86529 -----END CERTIFICATE-----
86530
86531 OISTE WISeKey Global Root GB CA
86532 ===============================
86533 -----BEGIN CERTIFICATE-----
86534 MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
86535 EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
86536 ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
86537 MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
86538 VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
86539 b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
86540 scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
86541 rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
86542 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
86543 Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
86544 GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
86545 /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
86546 hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
86547 dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
86548 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
86549 HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
86550 Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
86551 -----END CERTIFICATE-----
86552
86553 Certification Authority of WoSign G2
86554 ====================================
86555 -----BEGIN CERTIFICATE-----
86556 MIIDfDCCAmSgAwIBAgIQayXaioidfLwPBbOxemFFRDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQG
86557 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxLTArBgNVBAMTJENlcnRpZmljYXRpb24g
86558 QXV0aG9yaXR5IG9mIFdvU2lnbiBHMjAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMFgx
86559 CzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEtMCsGA1UEAxMkQ2VydGlm
86560 aWNhdGlvbiBBdXRob3JpdHkgb2YgV29TaWduIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
86561 CgKCAQEAvsXEoCKASU+/2YcRxlPhuw+9YH+v9oIOH9ywjj2X4FA8jzrvZjtFB5sg+OPXJYY1kBai
86562 XW8wGQiHC38Gsp1ij96vkqVg1CuAmlI/9ZqD6TRay9nVYlzmDuDfBpgOgHzKtB0TiGsOqCR3A9Du
86563 W/PKaZE1OVbFbeP3PU9ekzgkyhjpJMuSA93MHD0JcOQg5PGurLtzaaNjOg9FD6FKmsLRY6zLEPg9
86564 5k4ot+vElbGs/V6r+kHLXZ1L3PR8du9nfwB6jdKgGlxNIuG12t12s9R23164i5jIFFTMaxeSt+BK
86565 v0mUYQs4kI9dJGwlezt52eJ+na2fmKEG/HgUYFf47oB3sQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
86566 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU+mCp62XF3RYUCE4MD42b4Pdkr2cwDQYJKoZI
86567 hvcNAQELBQADggEBAFfDejaCnI2Y4qtAqkePx6db7XznPWZaOzG73/MWM5H8fHulwqZm46qwtyeY
86568 P0nXYGdnPzZPSsvxFPpahygc7Y9BMsaV+X3avXtbwrAh449G3CE4Q3RM+zD4F3LBMvzIkRfEzFg3
86569 TgvMWvchNSiDbGAtROtSjFA9tWwS1/oJu2yySrHFieT801LYYRf+epSEj3m2M1m6D8QL4nCgS3gu
86570 +sif/a+RZQp4OBXllxcU3fngLDT4ONCEIgDAFFEYKwLcMFrw6AF8NTojrwjkr6qOKEJJLvD1mTS+
86571 7Q9LGOHSJDy7XUe3IfKN0QqZjuNuPq1w4I+5ysxugTH2e5x6eeRncRg=
86572 -----END CERTIFICATE-----
86573
86574 CA WoSign ECC Root
86575 ==================
86576 -----BEGIN CERTIFICATE-----
86577 MIICCTCCAY+gAwIBAgIQaEpYcIBr8I8C+vbe6LCQkDAKBggqhkjOPQQDAzBGMQswCQYDVQQGEwJD
86578 TjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMTEkNBIFdvU2lnbiBFQ0MgUm9v
86579 dDAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQK
86580 ExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAxMSQ0EgV29TaWduIEVDQyBSb290MHYwEAYHKoZI
86581 zj0CAQYFK4EEACIDYgAE4f2OuEMkq5Z7hcK6C62N4DrjJLnSsb6IOsq/Srj57ywvr1FQPEd1bPiU
86582 t5v8KB7FVMxjnRZLU8HnIKvNrCXSf4/CwVqCXjCLelTOA7WRf6qU0NGKSMyCBSah1VES1ns2o0Iw
86583 QDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqv3VWqP2h4syhf3R
86584 MluARZPzA7gwCgYIKoZIzj0EAwMDaAAwZQIxAOSkhLCB1T2wdKyUpOgOPQB0TKGXa/kNUTyh2Tv0
86585 Daupn75OcsqF1NnstTJFGG+rrQIwfcf3aWMvoeGY7xMQ0Xk/0f7qO3/eVvSQsRUR2LIiFdAvwyYu
86586 a/GRspBl9JrmkO5K
86587 -----END CERTIFICATE-----
86588
86589 SZAFIR ROOT CA2
86590 ===============
86591 -----BEGIN CERTIFICATE-----
86592 MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
86593 A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
86594 BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
86595 BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
86596 VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
86597 qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
86598 DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
86599 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
86600 ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
86601 ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
86602 AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
86603 AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
86604 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
86605 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
86606 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
86607 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
86608 -----END CERTIFICATE-----
86609
86610 Certum Trusted Network CA 2
86611 ===========================
86612 -----BEGIN CERTIFICATE-----
86613 MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
86614 BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
86615 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
86616 ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
86617 TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
86618 cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
86619 IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
86620 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
86621 CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
86622 Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
86623 uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
86624 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
86625 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
86626 Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
86627 hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
86628 BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86629 AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
86630 hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
86631 Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
86632 L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
86633 clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
86634 pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
86635 w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
86636 J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
86637 ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
86638 is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
86639 zAYspsbiDrW5viSP
86640 -----END CERTIFICATE-----
86641
86642 Hellenic Academic and Research Institutions RootCA 2015
86643 =======================================================
86644 -----BEGIN CERTIFICATE-----
86645 MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
86646 BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
86647 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
86648 YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
86649 MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
86650 QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
86651 BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
86652 MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
86653 bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
86654 iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
86655 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
86656 FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
86657 i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
86658 GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
86659 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
86660 iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
86661 Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86662 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
86663 hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
86664 D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
86665 d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
86666 d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
86667 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
86668 davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
86669 Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
86670 J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
86671 JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
86672 p/UsQu0yrbYhnr68
86673 -----END CERTIFICATE-----
86674
86675 Hellenic Academic and Research Institutions ECC RootCA 2015
86676 ===========================================================
86677 -----BEGIN CERTIFICATE-----
86678 MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
86679 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
86680 cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
86681 aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
86682 MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
86683 IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
86684 VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
86685 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
86686 dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
86687 Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
86688 BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
86689 GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
86690 dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
86691 -----END CERTIFICATE-----
86692
86693 Certplus Root CA G1
86694 ===================
86695 -----BEGIN CERTIFICATE-----
86696 MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUAMD4xCzAJBgNV
86697 BAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTAe
86698 Fw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhD
86699 ZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQAD
86700 ggIPADCCAgoCggIBANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHN
86701 r49aiZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt6kuJPKNx
86702 Qv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP0FG7Yn2ksYyy/yARujVj
86703 BYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTv
86704 LRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDEEW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2
86705 z4QTd28n6v+WZxcIbekN1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc
86706 4nBvCGrch2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCTmehd
86707 4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV4EJQeIQEQWGw9CEj
86708 jy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPOWftwenMGE9nTdDckQQoRb5fc5+R+
86709 ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G
86710 A1UdDgQWBBSowcCbkahDFXxdBie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHY
86711 lwuBsTANBgkqhkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh
86712 66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7/SMNkPX0XtPG
86713 YX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BSS7CTKtQ+FjPlnsZlFT5kOwQ/
86714 2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F
86715 6ALEUz65noe8zDUa3qHpimOHZR4RKttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilX
86716 CNQ314cnrUlZp5GrRHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWe
86717 tUNy6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEVV/xuZDDC
86718 VRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5g4VCXA9DO2pJNdWY9BW/
86719 +mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl++O/QmueD6i9a5jc2NvLi6Td11n0bt3+
86720 qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo=
86721 -----END CERTIFICATE-----
86722
86723 Certplus Root CA G2
86724 ===================
86725 -----BEGIN CERTIFICATE-----
86726 MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4xCzAJBgNVBAYT
86727 AkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjAeFw0x
86728 NDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0
86729 cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IA
86730 BM0PW1aC3/BFGtat93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uN
86731 Am8xIk0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0PAQH/BAQD
86732 AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMB8GA1Ud
86733 IwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqGSM49BAMDA2gAMGUCMHD+sAvZ94OX7PNV
86734 HdTcswYO/jOYnYs5kGuUIe22113WTNchp+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjl
86735 vPl5adytRSv3tjFzzAalU5ORGpOucGpnutee5WEaXw==
86736 -----END CERTIFICATE-----
86737
86738 OpenTrust Root CA G1
86739 ====================
86740 -----BEGIN CERTIFICATE-----
86741 MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV
86742 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx
86743 MB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
86744 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEB
86745 AQUAA4ICDwAwggIKAoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7fa
86746 Yp6bwiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX/uMftk87
86747 ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR077F9jAHiOH3BX2pfJLKO
86748 YheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGPuY4zbGneWK2gDqdkVBFpRGZPTBKnjix9
86749 xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLxp2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO
86750 9z0M+Yo0FMT7MzUj8czxKselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq
86751 3ywgsNw2TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+WG+Oi
86752 n6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPwvFEVVJSmdz7QdFG9
86753 URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYYEQRVzXR7z2FwefR7LFxckvzluFqr
86754 TJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
86755 /zAdBgNVHQ4EFgQUl0YhVyE12jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/Px
86756 N3DlCPaTKbYwDQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E
86757 PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kfgLMtMrpkZ2Cv
86758 uVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbSFXJfLkur1J1juONI5f6ELlgK
86759 n0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLh
86760 X4SPgPL0DTatdrOjteFkdjpY3H1PXlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80
86761 nR14SohWZ25g/4/Ii+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcm
86762 GS3tTAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L9109S5zvE/
86763 bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/KyPu1svf0OnWZzsD2097+o
86764 4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJAwSQiumPv+i2tCqjI40cHLI5kqiPAlxA
86765 OXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj1oxx
86766 -----END CERTIFICATE-----
86767
86768 OpenTrust Root CA G2
86769 ====================
86770 -----BEGIN CERTIFICATE-----
86771 MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUAMEAxCzAJBgNV
86772 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcy
86773 MB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
86774 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEB
86775 AQUAA4ICDwAwggIKAoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+
86776 Ntmh/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78eCbY2albz
86777 4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/61UWY0jUJ9gNDlP7ZvyCV
86778 eYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fEFY8ElggGQgT4hNYdvJGmQr5J1WqIP7wt
86779 UdGejeBSzFfdNTVY27SPJIjki9/ca1TSgSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz
86780 3GIZ38i1MH/1PCZ1Eb3XG7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj
86781 3CzMpSZyYhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaHvGOz
86782 9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4t/bQWVyJ98LVtZR0
86783 0dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/gh7PU3+06yzbXfZqfUAkBXKJOAGT
86784 y3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
86785 /zAdBgNVHQ4EFgQUajn6QiL35okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59
86786 M4PLuG53hq8wDQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz
86787 Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0nXGEL8pZ0keI
86788 mUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qTRmTFAHneIWv2V6CG1wZy7HBG
86789 S4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpTwm+bREx50B1ws9efAvSyB7DH5fitIw6mVskp
86790 EndI2S9G/Tvw/HRwkqWOOAgfZDC2t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ
86791 6e18CL13zSdkzJTaTkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97kr
86792 gCf2o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU3jg9CcCo
86793 SmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eAiN1nE28daCSLT7d0geX0
86794 YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14fWKGVyasvc0rQLW6aWQ9VGHgtPFGml4vm
86795 u7JwqkwR3v98KzfUetF3NI/n+UL3PIEMS1IK
86796 -----END CERTIFICATE-----
86797
86798 OpenTrust Root CA G3
86799 ====================
86800 -----BEGIN CERTIFICATE-----
86801 MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAxCzAJBgNVBAYT
86802 AkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEczMB4X
86803 DTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9w
86804 ZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQA
86805 IgNiAARK7liuTcpm3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5B
86806 ta1doYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4GA1UdDwEB
86807 /wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAf
86808 BgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAKBggqhkjOPQQDAwNpADBmAjEAj6jcnboM
86809 BBf6Fek9LykBl7+BFjNAk2z8+e2AcG+qj9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta
86810 3U1fJAuwACEl74+nBCZx4nxp5V2a+EEfOzmTk51V6s2N8fvB
86811 -----END CERTIFICATE-----
86812
86813 ISRG Root X1
86814 ============
86815 -----BEGIN CERTIFICATE-----
86816 MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
86817 BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
86818 EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
86819 EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
86820 DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
86821 Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
86822 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
86823 b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
86824 Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
86825 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
86826 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
86827 hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
86828 usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
86829 OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
86830 A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
86831 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
86832 ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
86833 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
86834 hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
86835 TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
86836 e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
86837 JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
86838 YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
86839 JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
86840 m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
86841 -----END CERTIFICATE-----
86842
86843 AC RAIZ FNMT-RCM
86844 ================
86845 -----BEGIN CERTIFICATE-----
86846 MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
86847 AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
86848 MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
86849 TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
86850 ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
86851 qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
86852 btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
86853 j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
86854 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
86855 WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
86856 tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
86857 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
86858 ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
86859 i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
86860 FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
86861 dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
86862 nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
86863 D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
86864 j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
86865 Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
86866 +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
86867 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
86868 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
86869 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
86870 rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
86871 -----END CERTIFICATE-----
86872
86873 Amazon Root CA 1
86874 ================
86875 -----BEGIN CERTIFICATE-----
86876 MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
86877 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
86878 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
86879 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
86880 ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
86881 FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
86882 gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
86883 dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
86884 VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
86885 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
86886 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
86887 CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
86888 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
86889 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
86890 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
86891 -----END CERTIFICATE-----
86892
86893 Amazon Root CA 2
86894 ================
86895 -----BEGIN CERTIFICATE-----
86896 MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
86897 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
86898 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
86899 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
86900 ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
86901 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
86902 N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
86903 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
86904 fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
86905 kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
86906 btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
86907 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
86908 c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
86909 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
86910 DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
86911 A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
86912 +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
86913 YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
86914 xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
86915 gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
86916 aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
86917 Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
86918 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
86919 JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
86920 -----END CERTIFICATE-----
86921
86922 Amazon Root CA 3
86923 ================
86924 -----BEGIN CERTIFICATE-----
86925 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
86926 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
86927 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
86928 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
86929 f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
86930 Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
86931 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
86932 eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
86933 -----END CERTIFICATE-----
86934
86935 Amazon Root CA 4
86936 ================
86937 -----BEGIN CERTIFICATE-----
86938 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
86939 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
86940 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
86941 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
86942 /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
86943 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
86944 HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
86945 MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
86946 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
86947 -----END CERTIFICATE-----
86948
86949 LuxTrust Global Root 2
86950 ======================
86951 -----BEGIN CERTIFICATE-----
86952 MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG
86953 A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh
86954 bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW
86955 MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC
86956 AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm
86957 Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2
86958 xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC
86959 wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm
86960 1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm
86961 FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF
86962 wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/
86963 a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U
86964 ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ
86965 MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB
86966 /zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5
86967 Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
86968 +Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ
86969 FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN
86970 H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW
86971 7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu
86972 ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA
86973 VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR
86974 TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
86975 /f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc
86976 7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
86977 iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
86978 -----END CERTIFICATE-----
86979
86980 TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
86981 =============================================
86982 -----BEGIN CERTIFICATE-----
86983 MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
86984 D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
86985 IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
86986 TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
86987 ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
86988 VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
86989 c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
86990 bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
86991 IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
86992 MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
86993 6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
86994 wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
86995 3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
86996 WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
86997 ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
86998 KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
86999 AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
87000 lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
87001 e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
87002 q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
87003 -----END CERTIFICATE-----
87004 <?php
87005
87006 if (PHP_SAPI !== 'cli') {
87007     echo 'Warning: Composer should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
87008 }
87009
87010 require __DIR__.'/../src/bootstrap.php';
87011
87012 use Composer\Factory;
87013 use Composer\XdebugHandler;
87014 use Composer\Console\Application;
87015
87016 error_reporting(-1);
87017
87018 // Create output for XdebugHandler and Application
87019 $output = Factory::createOutput();
87020
87021 $xdebug = new XdebugHandler($output);
87022 $xdebug->check();
87023 unset($xdebug);
87024
87025 if (function_exists('ini_set')) {
87026     @ini_set('display_errors', 1);
87027
87028     $memoryInBytes = function ($value) {
87029         $unit = strtolower(substr($value, -1, 1));
87030         $value = (int) $value;
87031         switch($unit) {
87032             case 'g':
87033                 $value *= 1024;
87034                 // no break (cumulative multiplier)
87035             case 'm':
87036                 $value *= 1024;
87037                 // no break (cumulative multiplier)
87038             case 'k':
87039                 $value *= 1024;
87040         }
87041
87042         return $value;
87043     };
87044
87045     $memoryLimit = trim(ini_get('memory_limit'));
87046     // Increase memory_limit if it is lower than 1.5GB
87047     if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
87048         @ini_set('memory_limit', '1536M');
87049     }
87050     // Set user defined memory limit
87051     if ($memoryLimit = getenv('COMPOSER_MEMORY_LIMIT')) {
87052         @ini_set('memory_limit', $memoryLimit);
87053     }
87054     unset($memoryInBytes, $memoryLimit);
87055 }
87056
87057 putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
87058
87059 // run the command application
87060 $application = new Application();
87061 $application->run(null, $output);
87062
87063 Copyright (c) Nils Adermann, Jordi Boggiano
87064
87065 Permission is hereby granted, free of charge, to any person obtaining a copy
87066 of this software and associated documentation files (the "Software"), to deal
87067 in the Software without restriction, including without limitation the rights
87068 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
87069 copies of the Software, and to permit persons to whom the Software is furnished
87070 to do so, subject to the following conditions:
87071
87072 The above copyright notice and this permission notice shall be included in all
87073 copies or substantial portions of the Software.
87074
87075 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
87076 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87077 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
87078 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
87079 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
87080 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
87081 THE SOFTWARE.
87082
87083 çæ\1dXm4U\ f_jE\99\14\ eù~\1a~\8de\ 2\0\0\0GBMB