Upgraded drupal core with security updates
[yaffs-website] / composer.phar
1 #!/usr/bin/env php
2 <?php
3 /*
4  * This file is part of Composer.
5  *
6  * (c) Nils Adermann <naderman@naderman.de>
7  *     Jordi Boggiano <j.boggiano@seld.be>
8  *
9  * For the full copyright and license information, please view
10  * the license that is located at the bottom of this file.
11  */
12
13 // Avoid APC causing random fatal errors per https://github.com/composer/composer/issues/264
14 if (extension_loaded('apc') && ini_get('apc.enable_cli') && ini_get('apc.cache_by_default')) {
15     if (version_compare(phpversion('apc'), '3.0.12', '>=')) {
16         ini_set('apc.cache_by_default', 0);
17     } else {
18         fwrite(STDERR, 'Warning: APC <= 3.0.12 may cause fatal errors when running composer commands.'.PHP_EOL);
19         fwrite(STDERR, 'Update APC, or set apc.enable_cli or apc.cache_by_default to 0 in your php.ini.'.PHP_EOL);
20     }
21 }
22
23 Phar::mapPhar('composer.phar');
24 require 'phar://composer.phar/bin/composer';
25
26 __HALT_COMPILER(); ?>\r
27 w\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\ 5b\0\0\1a\17\8bY\ 5b\0\0¼cí߶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Autoload/ClassMapGenerator.php«\11\0\0\1a\17\8b\11\0\0\10ëÊ\9a\ 1\0\0\0\0\0\0\16\0\0\0src/Composer/Cache.phpt\13\0\0\1a\17\8bYt\13\0\0\0\11&#¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Command/AboutCommand.phpË\ 2\0\0\1a\17\8b\ 2\0\0º¡Ãh¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/ArchiveCommand.phpL\14\0\0\1a\17\8bYL\14\0\0\85\r;V¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/BaseCommand.phpÉ        \0\0\1a\17\8bYÉ \0\0\97P!£¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Command/BaseDependencyCommand.phpÉ\18\0\0\1a\17\8b\18\0\0D{²Ð¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/ClearCacheCommand.php]\ 5\0\0\1a\17\8bY]\ 5\0\0\1f\82ß´¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/ConfigCommand.php\aH\0\0\1a\17\8bY\aH\0\0\ fÃæ\ 5\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Command/CreateProjectCommand.phpì4\0\0\1a\17\8bYì4\0\0\13ô\18\8d\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/DependsCommand.php·\ 2\0\0\1a\17\8b\ 2\0\0o±¹ú¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/DiagnoseCommand.phpÍF\0\0\1a\17\8bYÍF\0\0²E>F¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Command/DumpAutoloadCommand.php¨       \0\0\1a\17\8bY¨ \0\0g/\94\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ExecCommand.phpi\a\0\0\1a\17\8bYi\a\0\0\ 4\80\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/GlobalCommand.phpü\a\0\0\1a\17\8b\a\0\0ÝH\8f\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/HomeCommand.php\1f\ e\0\0\1a\17\8bY\1f\ e\0\0\16±¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/InitCommand.phpT>\0\0\1a\17\8bYT>\0\0\16\16Oø¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/InstallCommand.phpý\13\0\0\1a\17\8b\13\0\00ö:\89\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/LicensesCommand.php&\ e\0\0\1a\17\8bY&\ e\0\0Óv\83\1e\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/OutdatedCommand.php°
28 \0\0\1a\17\8b
29 \0\07àzk¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/ProhibitsCommand.phpË\ 2\0\0\1a\17\8b\ 2\0\0\1ag\8fð¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/RemoveCommand.php\ 1\16\0\0\1a\17\8bY\ 1\16\0\0 O4\v\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/RequireCommand.php\9d\1f\0\0\1a\17\8bY\9d\1f\0\0BùÊǶ\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/RunScriptCommand.php \f\0\0\1a\17\8b\f\0\0\ 3G\92\7f\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Command/ScriptAliasCommand.php\ 3\ 5\0\0\1a\17\8bY\ 3\ 5\0\0ÃJJü¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/SearchCommand.phpã\b\0\0\1a\17\8b\b\0\0ñ\v¼w¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/SelfUpdateCommand.phpï0\0\0\1a\17\8bYï0\0\0û­\ 3\f\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ShowCommand.php\85d\0\0\1a\17\8bY\85d\0\0ó\87*é¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/StatusCommand.php/\15\0\0\1a\17\8bY/\15\0\0ôE\12\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/SuggestsCommand.php©\r\0\0\1a\17\8b\r\0\0\96º×U¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/UpdateCommand.php["\0\0\1a\17\8bY["\0\0IyYì¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/ValidateCommand.php\18\14\0\0\1a\17\8bY\18\14\0\0lp\9c\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Composer.phpù  \0\0\1a\17\8bYù \0\01N«®¶\ 1\0\0\0\0\0\0\17\0\0\0src/Composer/Config.phpÅ"\0\0\1a\17\8bYÅ"\0\0\9d¡¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Config/ConfigSourceInterface.php\ e\ 2\0\0\1a\17\8bY\ e\ 2\0\0³\f[/¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Config/JsonConfigSource.php!\13\0\0\1a\17\8bY!\13\0\0¾S\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Console/Application.php¶2\0\0\1a\17\8bY¶2\0\0A7Ò\18\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Console/HtmlOutputFormatter.php3\ 6\0\0\1a\17\8bY3\ 6\0\0Ú\81Eu¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/DependencyResolver/Decisions.phpQ\ f\0\0\1a\17\8bYQ\ f\0\0?\98¬$¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/DefaultPolicy.php\ 2\17\0\0\1a\17\8bY\ 2\17\0\0õÝv\7f\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/GenericRule.php·\ 3\0\0\1a\17\8b\ 3\0\0Ì~¯³¶\ 1\0\0\0\0\0\0>\0\0\0src/Composer/DependencyResolver/Operation/InstallOperation.phpC\ 2\0\0\1a\17\8bYC\ 2\0\0´\õ*¶\ 1\0\0\0\0\0\0I\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php÷\ 2\0\0\1a\17\8b\ 2\0\0ïÎà÷¶\ 1\0\0\0\0\0\0K\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpý\ 2\0\0\1a\17\8b\ 2\0\0\193#\86\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ\0\0\0\1a\17\8b\0\0\0Ùâ&ä¶\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/SolverOperation.php¹\ 1\0\0\1a\17\8b\ 1\0\0&¢e
30\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/UninstallOperation.phpI\ 2\0\0\1a\17\8bYI\ 2\0\0FûÂɶ\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/UpdateOperation.phph\ 3\0\0\1a\17\8bYh\ 3\0\0öSÕ]¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/PolicyInterface.php­\ 1\0\0\1a\17\8b\ 1\0\0\18\9f\8b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Pool.php°"\0\0\1a\17\8bY°"\0\0\1d   \8e\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Problem.php\99\16\0\0\1a\17\8bY\99\16\0\0\ 3´\87Ķ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Request.php\83\ 4\0\0\1a\17\8bY\83\ 4\0\0åVP\84\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Rule.php¶\18\0\0\1a\17\8b\18\0\0Ú{\8d\8d\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/Rule2Literals.php§\ 4\0\0\1a\17\8b\ 4\0\0~Ð'ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/RuleSet.phpª
31 \0\0\1a\17\8b
32 \0\0\82\e\ 1\0\0\0\0\0\04\0\0\0src/Composer/DependencyResolver/RuleSetGenerator.phpO\e\0\0\1a\17\8bYO\e\0\0³Q[â¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/RuleSetIterator.php\14\ 6\0\0\1a\17\8bY\14\ 6\0\0}õÇù¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchChain.phpi\ 1\0\0\1a\17\8bYi\ 1\0\0\9a\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchGraph.phpá\ 6\0\0\1a\17\8b\ 6\0\0\89rôv¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/RuleWatchNode.phpñ\ 3\0\0\1a\17\8b\ 3\0\0ë\95\e\93\ 1\0\0\0\0\0\0*\0\0\0src/Composer/DependencyResolver/Solver.php\9f8\0\0\1a\17\8bY\9f8\0\0\1epöb¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/DependencyResolver/SolverBugException.php\98\ 1\0\0\1a\17\8bY\98\ 1\0\0\7f"qN¶\ 1\0\0\0\0\0\0;\0\0\0src/Composer/DependencyResolver/SolverProblemsException.php¤\a\0\0\1a\17\8b\a\0\0Ä\1d~\a\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/Transaction.phpô\13\0\0\1a\17\8b\13\0\0cïTܶ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Downloader/ArchiveDownloader.php¸\ e\0\0\1a\17\8b\ e\0\0±°Y\b\ 1\0\0\0\0\0\01\0\0\0src/Composer/Downloader/ChangeReportInterface.phpÌ\0\0\0\1a\17\8b\0\0\0¯à¨¿¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Downloader/DownloadManager.phpG\15\0\0\1a\17\8bYG\15\0\0\8a(í»¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/DownloaderInterface.phpÊ\ 1\0\0\1a\17\8b\ 1\0\0gs!l¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Downloader/DvcsDownloaderInterface.phpÑ\0\0\0\1a\17\8b\0\0\0\9c¿¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/FileDownloader.phpì\17\0\0\1a\17\8b\17\0\04\1eø\ 1\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/FilesystemException.php
33 \ 1\0\0\1a\17\8bY
34 \ 1\0\0.-\1e\8b\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Downloader/FossilDownloader.php`\v\0\0\1a\17\8bY`\v\0\0ÿI©u¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/GitDownloader.php\9d3\0\0\1a\17\8bY\9d3\0\01mU¥¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/GzipDownloader.phpó\ 6\0\0\1a\17\8b\ 6\0\0}Úo¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/HgDownloader.php8 \0\0\1a\17\8bY8 \0\0ëyàn¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PathDownloader.phpS\10\0\0\1a\17\8bYS\10\0\0Êfý|¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Downloader/PearPackageExtractor.phpu\e\0\0\1a\17\8bYu\e\0\0z\84\15\87\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/PerforceDownloader.phpÃ\a\0\0\1a\17\8b\a\0\0\1c\91Èý¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PharDownloader.phpå\0\0\0\1a\17\8b\0\0\0ÞÉ\1fç¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/RarDownloader.php\9e\a\0\0\1a\17\8bY\9e\a\0\06      3U¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/SvnDownloader.phpG\11\0\0\1a\17\8bYG\11\0\0\86íV\96\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/TarDownloader.phpã\0\0\0\1a\17\8b\0\0\0Í\92X?¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/TransportException.php=\ 2\0\0\1a\17\8bY=\ 2\0\0ZÎÈÞ¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Downloader/VcsCapableDownloaderInterface.phpÔ\0\0\0\1a\17\8b\0\0\0`§ôö¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/VcsDownloader.php"\16\0\0\1a\17\8bY"\16\0\0\9c\1a\9f\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/XzDownloader.php§\ 4\0\0\1a\17\8b\ 4\0\0W$;á¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/ZipDownloader.php\98\13\0\0\1a\17\8bY\98\13\0\0\9b@\ 2ü¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/EventDispatcher/Event.php \ 2\0\0\1a\17\8b\ 2\0\0±\99jï¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/EventDispatcher/EventDispatcher.phpß0\0\0\1a\17\8bYß0\0\0}f\18\a\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/EventSubscriberInterface.php©\0\0\0\1a\17\8b\0\0\0\ 1\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/ScriptExecutionException.phpv\0\0\0\1a\17\8bYv\0\0\0wZ8S¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Exception/NoSslException.phpf\0\0\0\1a\17\8bYf\0\0\0ËíM\9d\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Factory.phpS=\0\0\1a\17\8bYS=\0\0Fíж\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/BaseIO.php\8c\10\0\0\1a\17\8bY\8c\10\0\0(\82l\91\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/IO/BufferIO.php*\ 4\0\0\1a\17\8bY*\ 4\0\0¢®hT¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/IO/ConsoleIO.php;\15\0\0\1a\17\8bY;\15\0\0Ê\17\9b\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/IO/IOInterface.phpì\ 5\0\0\1a\17\8b\ 5\0\0\0Õ\9d\ e\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/NullIO.phpÀ\ 4\0\0\1a\17\8b\ 4\0\0F`sʶ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/Installer.phpv\9a\0\0\1a\17\8bYv\9a\0\0¸f¡u¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/BinaryInstaller.php\10\13\0\0\1a\17\8bY\10\13\0\0\8dv÷j¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Installer/BinaryPresenceInterface.phpË\0\0\0\1a\17\8b\0\0\0À5\9a¨¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/InstallationManager.php-\17\0\0\1a\17\8bY-\17\0\0¾}\8c\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Installer/InstallerEvent.php\ e\ 6\0\0\1a\17\8bY\ e\ 6\0\0lÔzi¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/InstallerEvents.phpÞ\0\0\0\1a\17\8b\0\0\0ì\9f@G¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Installer/InstallerInterface.phpã\ 2\0\0\1a\17\8b\ 2\0\0^\83\93ʶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/LibraryInstaller.php^\13\0\0\1a\17\8bY^\13\0\0\10\1aÍr¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Installer/MetapackageInstaller.php\9c\ 4\0\0\1a\17\8bY\9c\ 4\0\0Æ\12Å!¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/NoopInstaller.php+\ 5\0\0\1a\17\8bY+\ 5\0\0À·M}¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Installer/PackageEvent.phpe\ 3\0\0\1a\17\8bYe\ 3\0\0;° \1a\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PackageEvents.php¸\ 1\0\0\1a\17\8b\ 1\0\0dbØs¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/PearBinaryInstaller.phpâ\f\0\0\1a\17\8b\f\0\0;øiU¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PearInstaller.php¢\a\0\0\1a\17\8b\a\0\0È\82¶Ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/PluginInstaller.php\9f\ 6\0\0\1a\17\8bY\9f\ 6\0\0<tú,¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/ProjectInstaller.php\1d\ 6\0\0\1a\17\8bY\1d\ 6\0\0*0@P¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Installer/SuggestedPackagesReporter.php\10\a\0\0\1a\17\8bY\10\a\0\0+±]Ķ\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Json/JsonFile.php\ 3\14\0\0\1a\17\8bY\ 3\14\0\0VVN\15\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Json/JsonFormatter.php\ 6\ 6\0\0\1a\17\8bY\ 6\ 6\0\0\1eÐqu¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Json/JsonManipulator.phpé1\0\0\1a\17\8bYé1\0\0Ë\ 3Æï¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Json/JsonValidationException.php\\ 1\0\0\1a\17\8bY\\ 1\0\0.Xóܶ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Package/AliasPackage.php\ 5\17\0\0\1a\17\8bY\ 5\17\0\0¹\97~\9a\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFilter.php       \ 2\0\0\1a\17\8b\ 2\0\0yY+¦¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFinder.phpÞ\ 5\0\0\1a\17\8b\ 5\0\0\f²²¹¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Archiver/ArchiveManager.php°\f\0\0\1a\17\8b\f\0\0gþÒ)¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/ArchiverInterface.php\a\ 1\0\0\1a\17\8bY\a\ 1\0\0ñ´>\v\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/BaseExcludeFilter.php\96\ 6\0\0\1a\17\8bY\96\ 6\0\0y¶=ƶ\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ComposerExcludeFilter.php\1f\ 1\0\0\1a\17\8bY\1f\ 1\0\0\8bSZ0¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Package/Archiver/GitExcludeFilter.phpq\ 3\0\0\1a\17\8bYq\ 3\0\05¾i&¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Archiver/HgExcludeFilter.php\13\ 5\0\0\1a\17\8bY\13\ 5\0\0~\94\ e¸¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Archiver/PharArchiver.php>\ 6\0\0\1a\17\8bY>\ 6\0\0 5\89í¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/Archiver/ZipArchiver.php¼\ 4\0\0\1a\17\8b\ 4\0\0\91XÝë¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/BasePackage.php&\r\0\0\1a\17\8bY&\r\0\0\e'\1fݶ\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Package/CompletePackage.phpü\ 6\0\0\1a\17\8b\ 6\0\0þM˶¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/CompletePackageInterface.phpõ\ 1\0\0\1a\17\8b\ 1\0\0¦Ê\81ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Dumper/ArrayDumper.phpë\v\0\0\1a\17\8b\v\0\0Ó8WE¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Package/Link.php\88\ 5\0\0\1a\17\8bY\88\ 5\0\0å¶Y«¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/EmptyConstraint.php\82\ 1\0\0\1a\17\8bY\82\ 1\0\0\ eé~\8b\ 1\0\0\0\0\0\0?\0\0\0src/Composer/Package/LinkConstraint/LinkConstraintInterface.phpd\ 1\0\0\1a\17\8bYd\ 1\0\0¤ôLn¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/MultiConstraint.php\82\ 1\0\0\1a\17\8bY\82\ 1\0\0ób`ý¶\ 1\0\0\0\0\0\0:\0\0\0src/Composer/Package/LinkConstraint/SpecificConstraint.phpi\ 1\0\0\1a\17\8bYi\ 1\0\0Þ\94\9a\ 1\0\0\0\0\0\09\0\0\0src/Composer/Package/LinkConstraint/VersionConstraint.phpX\ 1\0\0\1a\17\8bYX\ 1\0\0\ 2}`y¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Loader/ArrayLoader.php¸\1e\0\0\1a\17\8b\1e\0\06\r¤\1d\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Loader/InvalidPackageException.phpE\ 2\0\0\1a\17\8bYE\ 2\0\0xb\13¾¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Loader/JsonLoader.phpù\ 1\0\0\1a\17\8b\ 1\0\0!~\88\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Loader/LoaderInterface.php²\0\0\0\1a\17\8b\0\0\0¦}úζ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Loader/RootPackageLoader.php½\16\0\0\1a\17\8b\16\0\0\8d\ 1\0\0\0\0\0\05\0\0\0src/Composer/Package/Loader/ValidatingArrayLoader.phpõ2\0\0\1a\17\8bYõ2\0\0ÞEY7¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Package/Locker.php©!\0\0\1a\17\8bY©!\0\0A\8aõë¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Package/Package.phpÉ\1a\0\0\1a\17\8b\1a\0\0\8f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/PackageInterface.php \a\0\0\1a\17\8b\a\0\0ûÇ^ƶ\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/RootAliasPackage.php\1f   \0\0\1a\17\8bY\1f \0\0      _\80ø¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/RootPackage.php\11\ 5\0\0\1a\17\8bY\11\ 5\0\0\ 2\8eÎ_¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/RootPackageInterface.php¹\ 3\0\0\1a\17\8b\ 3\0\0"maV¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Version/VersionGuesser.phpÊ\1c\0\0\1a\17\8b\1c\0\0É{\13¯¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Version/VersionParser.phpø\ 3\0\0\1a\17\8b\ 3\0\0\1e¾3l¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Version/VersionSelector.phpK\f\0\0\1a\17\8bYK\f\0\0²<\ fȶ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Plugin/Capability/Capability.phpW\0\0\0\1a\17\8bYW\0\0\0æ_¨1¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Plugin/Capability/CommandProvider.php\97\0\0\0\1a\17\8bY\97\0\0\0ûOâ>¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Plugin/Capable.php\7f\0\0\0\1a\17\8bY\7f\0\0\0Æq\15\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/CommandEvent.phpâ\ 2\0\0\1a\17\8b\ 2\0\0³ÆÇW¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/PluginEvents.phpÂ\0\0\0\1a\17\8b\0\0\0^Íþ\ 6\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Plugin/PluginInterface.phpô\0\0\0\1a\17\8b\0\0\0)'*ض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Plugin/PluginManager.php\1f$\0\0\1a\17\8bY\1f$\0\0ë\8e"»¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Plugin/PreFileDownloadEvent.php`\ 2\0\0\1a\17\8bY`\ 2\0\0\09-ζ\ 1\0\0\0\0\0\04\0\0\0src/Composer/Question/StrictConfirmationQuestion.php\1e\ 5\0\0\1a\17\8bY\1e\ 5\0\0'.³è¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Repository/ArrayRepository.php\13\ e\0\0\1a\17\8bY\13\ e\0\0éÌt\0\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ArtifactRepository.php»\f\0\0\1a\17\8b\f\0\0\88Ý÷<¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/BaseRepository.php_\r\0\0\1a\17\8bY_\r\0\0\96ûß\ e\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ComposerRepository.php\T\0\0\1a\17\8bY\T\0\0+\8a;ê¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/CompositeRepository.php;\b\0\0\1a\17\8bY;\b\0\0¤¯S\1f\ 1\0\0\0\0\0\0;\0\0\0src/Composer/Repository/ConfigurableRepositoryInterface.php\85\0\0\0\1a\17\8bY\85\0\0\0±\9f_\1c\ 1\0\0\0\0\0\00\0\0\0src/Composer/Repository/FilesystemRepository.php×\ 4\0\0\1a\17\8b\ 4\0\0I\9cª\13\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/InstalledArrayRepository.php£\0\0\0\1a\17\8b\0\0\0/ö~>¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Repository/InstalledFilesystemRepository.php£\0\0\0\1a\17\8b\0\0\0V
35 \95\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/InstalledRepositoryInterface.php\87\0\0\0\1a\17\8bY\87\0\0\0\18£9p¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/Repository/InvalidRepositoryException.phpn\0\0\0\1a\17\8bYn\0\0\0à\93ë\98\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/PackageRepository.phpj\ 3\0\0\1a\17\8bYj\ 3\0\0¥ôò̶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PathRepository.phpY        \0\0\1a\17\8bYY \0\0(\97¾3¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Pear/BaseChannelReader.phpI\ 5\0\0\1a\17\8bYI\ 5\0\0c\b6³¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ChannelInfo.phpÄ\ 1\0\0\1a\17\8b\ 1\0\0:T*ɶ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Pear/ChannelReader.phpí\ 6\0\0\1a\17\8b\ 6\0\0?ÈYT¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest10Reader.phpÁ \0\0\1a\17\8bYÁ \0\0\ 4O\80ë¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest11Reader.php& \0\0\1a\17\8bY& \0\0òUb\b\ 1\0\0\0\0\0\05\0\0\0src/Composer/Repository/Pear/DependencyConstraint.phpq\ 2\0\0\1a\17\8bYq\ 2\0\09\ e\17\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Pear/DependencyInfo.phpq\ 1\0\0\1a\17\8bYq\ 1\0\0fºTò¶\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/Pear/PackageDependencyParser.php\85\16\0\0\1a\17\8bY\85\16\0\0÷$Li¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/PackageInfo.php°\ 3\0\0\1a\17\8b\ 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\1a\17\8bY\92\ 1\0\0o\93\8aö\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PearRepository.phpª\16\0\0\1a\17\8b\16\0\0)\9f\83\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/PlatformRepository.php\ 1\e\0\0\1a\17\8bY\ 1\e\0\0\ 3_Mì¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryFactory.php\95\11\0\0\1a\17\8bY\95\11\0\0\80\83§\1d\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/RepositoryInterface.phpÛ\ 1\0\0\1a\17\8b\ 1\0\0\92\11âÁ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryManager.php,
36 \0\0\1a\17\8bY,
37 \0\0¾\85\\95\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/RepositorySecurityException.phpo\0\0\0\1a\17\8bYo\0\0\0pÕ«ª¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Vcs/BitbucketDriver.phpô\1e\0\0\1a\17\8b\1e\0\0\ 4x¤ü¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/FossilDriver.php \12\0\0\1a\17\8b\12\0\0]\8bÉQ¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/GitBitbucketDriver.phpê\ 5\0\0\1a\17\8b\ 5\0\0Ã\8e»\14\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/GitDriver.phpØ\11\0\0\1a\17\8b\11\0\0Ý"T̶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitHubDriver.phpz+\0\0\1a\17\8bYz+\0\0\13\1fÚb¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitLabDriver.phpì!\0\0\1a\17\8bYì!\0\0.?j\19\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/Vcs/HgBitbucketDriver.phpä\ 5\0\0\1a\17\8b\ 5\0\0i\9büà¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Repository/Vcs/HgDriver.phpe\12\0\0\1a\17\8bYe\12\0\0O!O\13\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Vcs/PerforceDriver.phpO     \0\0\1a\17\8bYO \0\0@ËóN¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/SvnDriver.php\15\e\0\0\1a\17\8bY\15\e\0\0\1dÕzï¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/VcsDriver.phpæ
38 \0\0\1a\17\8b
39 \0\0eׯ-¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/VcsDriverInterface.php÷\ 2\0\0\1a\17\8b\ 2\0\0ÇX[\89\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/VcsRepository.php´\1e\0\0\1a\17\8b\1e\0\0\ 1ªÖG¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Repository/WritableArrayRepository.php\ f\ 3\0\0\1a\17\8bY\ f\ 3\0\0¾G\17\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/WritableRepositoryInterface.php\89\ 1\0\0\1a\17\8bY\89\ 1\0\0\91/sï¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/CommandEvent.phpW\0\0\0\1a\17\8bYW\0\0\0£VZt¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Script/Event.phpµ\ 2\0\0\1a\17\8b\ 2\0\0lt¦M¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/PackageEvent.php\9c\0\0\0\1a\17\8bY\9c\0\0\0§ÿÉ\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/ScriptEvents.phpP\ 4\0\0\1a\17\8bYP\ 4\0\0\87\8f\ 4¶¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/SelfUpdate/Keys.php\9d\ 1\0\0\1a\17\8bY\9d\ 1\0\0\vîÊN¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/SelfUpdate/Versions.phpì\ 5\0\0\1a\17\8b\ 5\0\0͵\91\83\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/AuthHelper.phpË\ 3\0\0\1a\17\8b\ 3\0\0>zx\96\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/Bitbucket.php%\15\0\0\1a\17\8bY%\15\0\0n=gÓ¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/ComposerMirror.php±\ 4\0\0\1a\17\8b\ 4\0\0­½øض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ConfigValidator.phpu\12\0\0\1a\17\8bYu\12\0\0m\ 5áض\ 1\0\0\0\0\0\0"\0\0\0src/Composer/Util/ErrorHandler.php\87\ 4\0\0\1a\17\8bY\87\ 4\0\0He\1c\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/Filesystem.phps.\0\0\1a\17\8bYs.\0\0\9bÍ®à¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Git.phpn$\0\0\1a\17\8bYn$\0\05XÇ\ e\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitHub.phpÏ
40 \0\0\1a\17\8b
41 \0\0ÁØ\å¶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitLab.php\99\f\0\0\1a\17\8bY\99\f\0\0\17BLF¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/IniHelper.php\9d\ 2\0\0\1a\17\8bY\9d\ 2\0\0Çþ\82\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/NoProxyPattern.php¾\ 6\0\0\1a\17\8b\ 6\0\0Z+°m¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Perforce.php\1e2\0\0\1a\17\8bY\1e2\0\0­\ 65P¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Platform.phpü\ 4\0\0\1a\17\8b\ 4\0\0s­fç¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ProcessExecutor.php\f\b\0\0\1a\17\8bY\f\b\0\0\88)sw¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Util/RemoteFilesystem.php°c\0\0\1a\17\8bY°c\0\0Î\95mo¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Silencer.phpò\ 2\0\0\1a\17\8b\ 2\0\0.\8e\7fܶ\ 1\0\0\0\0\0\0!\0\0\0src/Composer/Util/SpdxLicense.php\ 3\ 1\0\0\1a\17\8bY\ 3\ 1\0\0¾7
42 ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Util/StreamContextFactory.phpÍ\ f\0\0\1a\17\8b\ f\0\0\8bK:8¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Svn.php¾\11\0\0\1a\17\8b\11\0\0Ík\93ܶ\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/TlsHelper.phpp
43 \0\0\1a\17\8bYp
44 \0\0¤eÞæ¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/XdebugHandler.php\93\ f\0\0\1a\17\8bY\93\ f\0\0\1cF·­¶\ 1\0\0\0\0\0\0\11\0\0\0src/bootstrap.php¹\ 1\0\0\1a\17\8b\ 1\0\0\15I}\9c\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Autoload/ClassLoader.php\8b4\0\0\1a\17\8bY\8b4\0\0Q\9f\94¼¶\ 1\0\0\0\0\0\0#\0\0\0res/composer-repository-schema.jsonð\ f\0\0\1a\17\8b\ f\0\0\81GÐà¶\ 1\0\0\0\0\0\0\18\0\0\0res/composer-schema.json_\93\0\0\1a\17\8bY_\93\0\0¤H\10õ¶\ 1\0\0\0\0\0\06\0\0\0vendor/composer/spdx-licenses/res/spdx-exceptions.jsoní\ 6\0\0\1a\17\8b\ 6\0\0ÆÅz±¶\ 1\0\0\0\0\0\04\0\0\0vendor/composer/spdx-licenses/res/spdx-licenses.jsonïf\0\0\1a\17\8bYïf\0\0"ï@\96\ 1\0\0\0\0\0\0*\0\0\0vendor/seld/cli-prompt/res/hiddeninput.exe\0$\0\0\1a\17\8bY\0$\0\0\95\8d¥v¶\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Application.php¥V\0\0\1a\17\8bY¥V\0\0\15«8\88\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Command/Command.php
45 #\0\0\1a\17\8bY
46 #\0\0\13¢\11Á¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/HelpCommand.phpÝ\a\0\0\1a\17\8b\a\0\0\99\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/ListCommand.phpZ\b\0\0\1a\17\8bYZ\b\0\0É£ \16\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/ConsoleEvents.phpï\0\0\0\1a\17\8b\0\0\0\rÕH¸¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/console/Descriptor/ApplicationDescription.phpß\b\0\0\1a\17\8b\b\0\0µ\8c°7¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Descriptor/Descriptor.php\9d\a\0\0\1a\17\8bY\9d\a\0\0\b;~Ķ\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Descriptor/DescriptorInterface.phpü\0\0\0\1a\17\8b\0\0\0±Q\aµ¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/JsonDescriptor.phpì\r\0\0\1a\17\8b\r\0\0á8-\8c\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Descriptor/MarkdownDescriptor.php¹\ e\0\0\1a\17\8b\ e\0\0k\9f.a¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/TextDescriptor.php\93\1e\0\0\1a\17\8bY\93\1e\0\0»]Ïø¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Descriptor/XmlDescriptor.php\ f\1c\0\0\1a\17\8bY\ f\1c\0\0\ 4\8bP$¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Event/ConsoleCommandEvent.php²\ 1\0\0\1a\17\8b\ 1\0\0Zk\89\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Event/ConsoleEvent.phpÅ\ 2\0\0\1a\17\8b\ 2\0\0ÒxÛ\¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleExceptionEvent.php\12\ 3\0\0\1a\17\8bY\12\ 3\0\0á\162é¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleTerminateEvent.phpz\ 2\0\0\1a\17\8bYz\ 2\0\0³,îL¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/CommandNotFoundException.phpÔ\ 1\0\0\1a\17\8b\ 1\0\0È÷ L¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Exception/ExceptionInterface.phpf\0\0\0\1a\17\8bYf\0\0\0¡ABª¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/InvalidArgumentException.php¦\0\0\0\1a\17\8b\0\0\0Ö̽Z¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/console/Exception/InvalidOptionException.php¦\0\0\0\1a\17\8b\0\0\0\13Ë×H¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Exception/LogicException.php\92\0\0\0\1a\17\8bY\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\1a\17\8bY\96\0\0\0Ùí,6¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Formatter/OutputFormatter.php\f\ e\0\0\1a\17\8bY\f\ e\0\0\83á&B¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Formatter/OutputFormatterInterface.php\8c\ 1\0\0\1a\17\8bY\8c\ 1\0\0òññÀ¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyle.phpL\10\0\0\1a\17\8bYL\10\0\0\8a\908<¶\ 1\0\0\0\0\0\0B\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php\86\ 1\0\0\1a\17\8bY\86\ 1\0\0ÝRÚ­¶\ 1\0\0\0\0\0\0>\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleStack.phpL\ 5\0\0\1a\17\8bYL\ 5\0\0.=\16\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Helper/DebugFormatterHelper.phpx\b\0\0\1a\17\8bYx\b\0\0N©Ø¼¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/DescriptorHelper.phpz\ 5\0\0\1a\17\8bYz\ 5\0\0fÉÚý¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Helper/DialogHelper.phpú\1e\0\0\1a\17\8b\1e\0\0hX\8fö\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/FormatterHelper.phpc\ 4\0\0\1a\17\8bYc\ 4\0\0\93ý«N¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Helper/Helper.php¬\a\0\0\1a\17\8b\a\0\0OÜs¢¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/HelperInterface.phpç\0\0\0\1a\17\8b\0\0\0 \18Çã¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/HelperSet.phpÐ\a\0\0\1a\17\8b\a\0\0a\88~\r\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/InputAwareHelper.phpc\ 1\0\0\1a\17\8bYc\ 1\0\0ñø\90\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Helper/ProcessHelper.phpÑ     \0\0\1a\17\8bYÑ \0\0@±ã\81\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/ProgressBar.phps%\0\0\1a\17\8bYs%\0\0鯦\81\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/ProgressHelper.php\\e\0\0\1a\17\8bY\\e\0\0\12?\8bá¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Helper/ProgressIndicator.phpK\14\0\0\1a\17\8bYK\14\0\0í\1cÍ°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/QuestionHelper.php\7f\e\0\0\1a\17\8bY\7f\e\0\0a4Íý¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Helper/SymfonyQuestionHelper.phpl
47 \0\0\1a\17\8bYl
48 \0\0\1e÷ÞL¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/console/Helper/Table.php¢*\0\0\1a\17\8bY¢*\0\0\0\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/TableCell.php\87\ 3\0\0\1a\17\8bY\87\ 3\0\0¨*æ\18\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/TableHelper.php\13\f\0\0\1a\17\8bY\13\f\0\0¦pm\87\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/TableSeparator.phpÍ\0\0\0\1a\17\8b\0\0\0Qßa²¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Helper/TableStyle.php\1f
49 \0\0\1a\17\8bY\1f
50 \0\0PÞµ¦¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Input/ArgvInput.php\14\15\0\0\1a\17\8bY\14\15\0\0¯Ü\10\9c\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Input/ArrayInput.php_
51 \0\0\1a\17\8bY_
52 \0\0[µðɶ\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Input/Input.phpª\v\0\0\1a\17\8b\v\0\0\ 3\1a\1f¶¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Input/InputArgument.php\12\ 6\0\0\1a\17\8bY\12\ 6\0\0ÁÜ\17\90\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Input/InputAwareInterface.php\9a\0\0\0\1a\17\8bY\9a\0\0\0\87jT\9f\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Input/InputDefinition.php\96\19\0\0\1a\17\8bY\96\19\0\00Oly¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Input/InputInterface.php\9f\ 3\0\0\1a\17\8bY\9f\ 3\0\0¥R6Û¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/InputOption.php\1c\f\0\0\1a\17\8bY\1c\f\0\0\87¹§\7f\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/StringInput.php\98\ 6\0\0\1a\17\8bY\98\ 6\0\0 \1dÚ¤¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/console/LICENSE)\ 4\0\0\1a\17\8bY)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Logger/ConsoleLogger.php< \0\0\1a\17\8bY< \0\0:âÇl¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Output/BufferedOutput.phpb\ 1\0\0\1a\17\8bYb\ 1\0\0çA?¦¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Output/ConsoleOutput.phpµ\a\0\0\1a\17\8b\a\0\0
53 ¢S\¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Output/ConsoleOutputInterface.phpå\0\0\0\1a\17\8b\0\0\0rNô\0\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Output/NullOutput.phpÏ\ 3\0\0\1a\17\8b\ 3\0\0®\98\8b\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Output/Output.php\9a    \0\0\1a\17\8bY\9a \0\001 ý¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Output/OutputInterface.php\1c\ 3\0\0\1a\17\8bY\1c\ 3\0\0\1aÓÚ>¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Output/StreamOutput.phpÄ\ 5\0\0\1a\17\8b\ 5\0\0õ\1aí\95\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Question/ChoiceQuestion.phpy
54 \0\0\1a\17\8bYy
55 \0\0.\ f\Q¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Question/ConfirmationQuestion.phpé\ 2\0\0\1a\17\8b\ 2\0\0\83\17Q@¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Question/Question.php#
56 \0\0\1a\17\8bY#
57 \0\0e¯ \ e\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/console/Shell.phpé\ f\0\0\1a\17\8b\ f\0\0½fü\91\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Style/OutputStyle.php_\ 5\0\0\1a\17\8bY_\ 5\0\0\ 4û\ 5µ¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Style/StyleInterface.phpÔ\ 3\0\0\1a\17\8b\ 3\0\0 ßÊj¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Style/SymfonyStyle.php¼\1f\0\0\1a\17\8b\1f\0\0öÅPg¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Tester/ApplicationTester.phpÔ\ 5\0\0\1a\17\8b\ 5\0\0¬ì¤d¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Tester/CommandTester.php¯\ 6\0\0\1a\17\8b\ 6\0\0{8"÷¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/debug/BufferingLogger.phpt\ 1\0\0\1a\17\8bYt\ 1\0\0=\0hܶ\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/debug/Debug.phpé\ 2\0\0\1a\17\8b\ 2\0\0Àxa?¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/DebugClassLoader.phpï\1d\0\0\1a\17\8b\1d\0\0ß<§ê¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/debug/ErrorHandler.php\80C\0\0\1a\17\8bY\80C\0\0¥æõ¾¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/debug/Exception/ClassNotFoundException.php\84\ 1\0\0\1a\17\8bY\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\1a\17\8bY\98\ 1\0\0-
58 d2¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/debug/Exception/DummyException.php\ 2\ 1\0\0\1a\17\8bY\ 2\ 1\0\0-"ûd¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalErrorException.phpï\ 6\0\0\1a\17\8b\ 6\0\0æ\ffz¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalThrowableError.phpD\ 2\0\0\1a\17\8bYD\ 2\0\0¡\fÂí¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/debug/Exception/FlattenException.php²\16\0\0\1a\17\8b\16\0\0HòÑ\ f\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/debug/Exception/OutOfMemoryException.php~\0\0\0\1a\17\8bY~\0\0\0ë¨oâ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/debug/Exception/UndefinedFunctionException.php\88\ 1\0\0\1a\17\8bY\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\1a\17\8bY\86\ 1\0\0¨LÚ:¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/ExceptionHandler.php\1f3\0\0\1a\17\8bY\1f3\0\0%\E\17\ 1\0\0\0\0\0\0I\0\0\0vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php7\12\0\0\1a\17\8bY7\12\0\0Ñj/=¶\ 1\0\0\0\0\0\0E\0\0\0vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php\ 3\ 1\0\0\1a\17\8bY\ 3\ 1\0\0ĹBV¶\ 1\0\0\0\0\0\0M\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.phpu\b\0\0\1a\17\8bYu\b\0\0éj\ 3\19\ 1\0\0\0\0\0\0K\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.phpN\ 5\0\0\1a\17\8bYN\ 5\0\0Ço-ç¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/symfony/debug/LICENSE)\ 4\0\0\1a\17\8bY)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/filesystem/Exception/ExceptionInterface.phpi\0\0\0\1a\17\8bYi\0\0\0$ ÿ\9b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/filesystem/Exception/FileNotFoundException.php¼\ 1\0\0\1a\17\8b\ 1\0\0pí\¶¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/filesystem/Exception/IOException.php\87\ 1\0\0\1a\17\8bY\87\ 1\0\0\80ü#Ѷ\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/filesystem/Exception/IOExceptionInterface.php¦\0\0\0\1a\17\8b\0\0\0jÙwM¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/filesystem/Filesystem.php¦1\0\0\1a\17\8bY¦1\0\0\8dò\86\ 1\0\0\0\0\0\0!\0\0\0vendor/symfony/filesystem/LICENSE)\ 4\0\0\1a\17\8bY)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/filesystem/LockHandler.php¢\ 5\0\0\1a\17\8b\ 5\0\0D\91;i¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Adapter/AbstractAdapter.php\\v\0\0\1a\17\8bY\\v\0\0Æ\93É\80\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Adapter/AbstractFindAdapter.php\91\19\0\0\1a\17\8bY\91\19\0\0ao¦È¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/finder/Adapter/AdapterInterface.php±\ 3\0\0\1a\17\8b\ 3\0\0ä»Ê&¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/BsdFindAdapter.php2\a\0\0\1a\17\8bY2\a\0\0Q/ÇC¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/GnuFindAdapter.php\15\a\0\0\1a\17\8bY\15\a\0\0\r\17¡¾¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/finder/Adapter/PhpAdapter.phpô\a\0\0\1a\17\8b\a\0\0\16\1d:?¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Comparator/Comparator.php\8c\ 3\0\0\1a\17\8bY\8c\ 3\0\0\16wþT¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Comparator/DateComparator.php%\ 3\0\0\1a\17\8bY%\ 3\0\0L¿EǶ\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Comparator/NumberComparator.php~\ 3\0\0\1a\17\8bY~\ 3\0\0\94\87 x¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Exception/AccessDeniedException.php\84\0\0\0\1a\17\8bY\84\0\0\0½¾s\9c\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Exception/AdapterFailureException.php¯\ 2\0\0\1a\17\8b\ 2\0\0\9côÔÁ¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/finder/Exception/ExceptionInterface.php\84\0\0\0\1a\17\8bY\84\0\0\0\1cGz-¶\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Exception/OperationNotPermitedException.php)\ 1\0\0\1a\17\8bY)\ 1\0\0ìcj=¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/finder/Exception/ShellCommandFailureException.phpÂ\ 2\0\0\1a\17\8b\ 2\0\0\19v\82ȶ\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Expression/Expression.php\a\ 6\0\0\1a\17\8bY\a\ 6\0\0µoÔ\ 6\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/finder/Expression/Glob.phpi\ 4\0\0\1a\17\8bYi\ 4\0\0@\8a\eº¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/finder/Expression/Regex.php\ 6\ f\0\0\1a\17\8bY\ 6\ f\0\0p8\0\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Expression/ValueInterface.phpÍ\ 1\0\0\1a\17\8b\ 1\0\0²~øb¶\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/finder/Finder.phpÂ-\0\0\1a\17\8bYÂ-\0\0\1e\98f´¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/finder/Glob.phpK\ 5\0\0\1a\17\8bYK\ 5\0\0já±n¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/finder/Iterator/CustomFilterIterator.php]\ 2\0\0\1a\17\8bY]\ 2\0\0tà±µ¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpz\ 2\0\0\1a\17\8bYz\ 2\0\0ÂT-\ 5\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpð\ 1\0\0\1a\17\8b\ 1\0\0ß0\99\ 4\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.phpï\ 5\0\0\1a\17\8b\ 5\0\0¾\8dÒâ¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/finder/Iterator/FilePathsIterator.php \ 6\0\0\1a\17\8b\ 6\0\0fQCe¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FileTypeFilterIterator.php\\ 2\0\0\1a\17\8bY\\ 2\0\0p\91'\98\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/finder/Iterator/FilecontentFilterIterator.php5\ 2\0\0\1a\17\8bY5\ 2\0\0\9aí\1f\14\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FilenameFilterIterator.phpr\ 1\0\0\1a\17\8bYr\ 1\0\0t\b\1a\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Iterator/FilterIterator.phpÃ\ 2\0\0\1a\17\8b\ 2\0\0\9a+µÞ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php/\ 5\0\0\1a\17\8bY/\ 5\0\0»Ç\1f\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Iterator/PathFilterIterator.phpÏ\ 1\0\0\1a\17\8b\ 1\0\0º\1cªÇ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php\15   \0\0\1a\17\8bY\15 \0\0ìt\90¶¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpg\ 2\0\0\1a\17\8bYg\ 2\0\0\97é¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Iterator/SortableIterator.php,\ 6\0\0\1a\17\8bY,\ 6\0\0\96\1c\ 1\0\0\0\0\0\0\1d\0\0\0vendor/symfony/finder/LICENSE)\ 4\0\0\1a\17\8bY)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/finder/Shell/Command.phpS\v\0\0\1a\17\8bYS\v\0\0cC\85\99\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/Shell/Shell.phpp\ 4\0\0\1a\17\8bYp\ 4\0\0\18Ó}g¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/SplFileInfo.phpÿ\ 2\0\0\1a\17\8bYÿ\ 2\0\0Ë\rOÀ¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/polyfill-mbstring/LICENSE)\ 4\0\0\1a\17\8bY)\ 4\0\0î*L\14\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/polyfill-mbstring/Mbstring.phpÄ6\0\0\1a\17\8bYÄ6\0\0U.\17ݶ\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php2A\0\0\1a\17\8bY2A\0\0½\11=¨¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php¡A\0\0\1a\17\8bY¡A\0\0\ eÚ    Í¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/polyfill-mbstring/bootstrap.php±\ f\0\0\1a\17\8b\ f\0\0|\8a©Ò¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/process/Exception/ExceptionInterface.phpf\0\0\0\1a\17\8bYf\0\0\0]ö>T¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/InvalidArgumentException.php¨\0\0\0\1a\17\8b\0\0\0ÐÀ+_¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/process/Exception/LogicException.php\94\0\0\0\1a\17\8bY\94\0\0\0 ³ãñ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/process/Exception/ProcessFailedException.phpx\ 3\0\0\1a\17\8bYx\ 3\0\0¨Ìzy¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/ProcessTimedOutException.php\1f\ 4\0\0\1a\17\8bY\1f\ 4\0\0.     Ãá¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/process/Exception/RuntimeException.php\98\0\0\0\1a\17\8bY\98\0\0\0¢\eØ:¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/process/ExecutableFinder.php\9b\ 4\0\0\1a\17\8bY\9b\ 4\0\0ý\82m\9b\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/process/LICENSE)\ 4\0\0\1a\17\8bY)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/PhpExecutableFinder.phpg\ 4\0\0\1a\17\8bYg\ 4\0\0\8dçµ\ 6\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/process/PhpProcess.phpü\ 3\0\0\1a\17\8b\ 3\0\0_\17\97\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/Pipes/AbstractPipes.php^\a\0\0\1a\17\8bY^\a\0\0%s\85ï¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/process/Pipes/PipesInterface.phpD\ 1\0\0\1a\17\8bYD\ 1\0\0vØ\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/process/Pipes/UnixPipes.phpå\a\0\0\1a\17\8b\a\0\0\ 1È¥\ 4\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/process/Pipes/WindowsPipes.php\8d\v\0\0\1a\17\8bY\8d\v\0\0\85®\1e\ 1\0\0\0\0\0\0"\0\0\0vendor/symfony/process/Process.php§R\0\0\1a\17\8bY§R\0\0+Á¥\1f\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/process/ProcessBuilder.phpã
59 \0\0\1a\17\8b
60 \0\0ʧ°\88\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/process/ProcessUtils.phpK\ 6\0\0\1a\17\8bYK\ 6\0\0µ½~ò¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/seld/jsonlint/LICENSE"\ 4\0\0\1a\17\8bY"\ 4\0\0a\83sy¶\ 1\0\0\0\0\0\0@\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php*\ 1\0\0\1a\17\8bY*\ 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\1a\17\8bY/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\1a\17\8bY\ 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\1a\17\8bY\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\1a\17\8bY>\0\0\0ÿq\9f\9f\ 1\0\0\0\0\0\0\1e\0\0\0vendor/seld/cli-prompt/LICENSE"\ 4\0\0\1a\17\8bY"\ 4\0\0\88ñ?e¶\ 1\0\0\0\0\0\0&\0\0\0vendor/seld/cli-prompt/res/example.php'\ 1\0\0\1a\17\8bY'\ 1\0\0I\1c\ 5£¶\ 1\0\0\0\0\0\0(\0\0\0vendor/seld/cli-prompt/src/CliPrompt.phpC\ 6\0\0\1a\17\8bYC\ 6\0\0Ð}\8d\ 1\0\0\0\0\0\0(\0\0\0vendor/justinrainbow/json-schema/LICENSE \ 4\0\0\1a\17\8b\ 4\0\0ºç\ 6©¶\ 1\0\0\0\0\0\0.\0\0\0vendor/justinrainbow/json-schema/demo/demo.phpñ\ 1\0\0\1a\17\8b\ 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\1a\17\8bY¡ \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\1a\17\8bY.\r\0\0[÷3í¶\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php\f\ e\0\0\1a\17\8bY\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\1a\17\8b\ 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\1a\17\8bY]\ 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\1a\17\8bY;\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\1a\17\8bY\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
61 \0\0\1a\17\8bY\9a
62 \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\1a\17\8b\11\0\0©Å¼x¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.phpN \0\0\1a\17\8bYN \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\1a\17\8bY\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\1a\17\8bYa\ 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\1a\17\8bYp\ 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\1a\17\8bY\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\1a\17\8bY&\ f\0\04\98©T¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php\ e!\0\0\1a\17\8bY\ e!\0\0\90Ò¶Z¶\ 1\0\0\0\0\0\0F\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.phpè\ 6\0\0\1a\17\8b\ 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\1a\17\8bYI\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\1a\17\8bY\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\1a\17\8bYl\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\1a\17\8bYl\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\1a\17\8bYu\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\1a\17\8bYw\0\0\0N-ò[¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ\ 2\0\0\1a\17\8b\ 2\0\0\r
63\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpo\0\0\0\1a\17\8bYo\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\1a\17\8bY\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\1a\17\8bY\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\1a\17\8bYj\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\1a\17\8bYf\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\1a\17\8b\ 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\1a\17\8b\ 2\0\0f4÷³¶\ 1\0\0\0\0\0\0A\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php\84\f\0\0\1a\17\8bY\84\f\0\0Nt³è¶\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php\ 1\ 1\0\0\1a\17\8bY\ 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\1a\17\8b\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\1a\17\8b\ 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\1a\17\8bY%\ 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\1a\17\8bY,\ 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\1a\17\8b\0\0\0ÿ\8bÁå¶\ 1\0\0\0\0\0\0C\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php\96  \0\0\1a\17\8bY\96 \0\0=&ßͶ\ 1\0\0\0\0\0\0D\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php&\13\0\0\1a\17\8bY&\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\1a\17\8bY\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\1a\17\8bY\85\0\0\0íæ\e\ 1\0\0\0\0\0\0=\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Validator.phpn\ 5\0\0\1a\17\8bYn\ 5\0\0\90Ñ|§¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/spdx-licenses/LICENSE\1c\ 4\0\0\1a\17\8bY\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\02\0\0\0vendor/composer/spdx-licenses/src/SpdxLicenses.phpç\11\0\0\1a\17\8b\11\0\0·\96U ¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/composer/semver/LICENSE\1c\ 4\0\0\1a\17\8bY\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\0)\0\0\0vendor/composer/semver/src/Comparator.php\ 2\ 4\0\0\1a\17\8bY\ 2\ 4\0\0wl\83ï¶\ 1\0\0\0\0\0\0<\0\0\0vendor/composer/semver/src/Constraint/AbstractConstraint.php×\ 2\0\0\1a\17\8b\ 2\0\0õî>\8e\ 1\0\0\0\0\0\04\0\0\0vendor/composer/semver/src/Constraint/Constraint.phpª\f\0\0\1a\17\8b\f\0\0ÇO7²¶\ 1\0\0\0\0\0\0=\0\0\0vendor/composer/semver/src/Constraint/ConstraintInterface.phpß\0\0\0\1a\17\8b\0\0\00C,\87\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/EmptyConstraint.phpé\ 1\0\0\1a\17\8b\ 1\0\0!-Ø\99\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/MultiConstraint.php1\ 5\0\0\1a\17\8bY1\ 5\0\0í xU¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/semver/src/Semver.phpv\ 6\0\0\1a\17\8bYv\ 6\0\0\8b×È\9b\ 1\0\0\0\0\0\0,\0\0\0vendor/composer/semver/src/VersionParser.php¿*\0\0\1a\17\8bY¿*\0\0\13)mƶ\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/ca-bundle/LICENSE\1c\ 4\0\0\1a\17\8bY\1c\ 4\0\0*!^`¶\ 1\0\0\0\0\0\0*\0\0\0vendor/composer/ca-bundle/src/CaBundle.php½\e\0\0\1a\17\8b\e\0\0e\1c\e\1e\ 1\0\0\0\0\0\0\16\0\0\0vendor/psr/log/LICENSE=\ 4\0\0\1a\17\8bY=\ 4\0\0\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/AbstractLogger.php;\ 4\0\0\1a\17\8bY;\ 4\0\0ñ>3[¶\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/InvalidArgumentException.php`\0\0\0\1a\17\8bY`\0\0\0 \88X1¶\ 1\0\0\0\0\0\0#\0\0\0vendor/psr/log/Psr/Log/LogLevel.phpû\0\0\0\1a\17\8b\0\0\0jðñ8¶\ 1\0\0\0\0\0\0/\0\0\0vendor/psr/log/Psr/Log/LoggerAwareInterface.php|\0\0\0\1a\17\8bY|\0\0\0$\13£\88\ 1\0\0\0\0\0\0+\0\0\0vendor/psr/log/Psr/Log/LoggerAwareTrait.php§\0\0\0\1a\17\8b\0\0\0T½úB¶\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/LoggerInterface.phpÆ\ 2\0\0\1a\17\8b\ 2\0\0»\12sg¶\ 1\0\0\0\0\0\0&\0\0\0vendor/psr/log/Psr/Log/LoggerTrait.phpi\ 4\0\0\1a\17\8bYi\ 4\0\035§Þ¶\ 1\0\0\0\0\0\0%\0\0\0vendor/psr/log/Psr/Log/NullLogger.php\9e\0\0\0\1a\17\8bY\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\1a\17\8b\f\0\0iq0ض\ 1\0\0\0\0\0\0\13\0\0\0vendor/autoload.php\82\0\0\0\1a\17\8bY\82\0\0\0\82ñUç¶\ 1\0\0\0\0\0\0'\0\0\0vendor/composer/autoload_namespaces.phpd\0\0\0\1a\17\8bYd\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_psr4.php\98\ 4\0\0\1a\17\8bY\98\ 4\0\0\9e\1c{¢¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/autoload_classmap.phpd\0\0\0\1a\17\8bYd\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0"\0\0\0vendor/composer/autoload_files.phpÃ\0\0\0\1a\17\8b\0\0\0ÒÂür¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_real.phpI\a\0\0\1a\17\8bYI\a\0\0]\90\¦¶\ 1\0\0\0\0\0\0#\0\0\0vendor/composer/autoload_static.php¬ \0\0\1a\17\8bY¬ \0\0ì9z
64\ 1\0\0\0\0\0\0\1f\0\0\0vendor/composer/ClassLoader.php\9c\18\0\0\1a\17\8bY\9c\18\0\0¥ÂåN¶\ 1\0\0\0\0\0\0(\0\0\0vendor/composer/ca-bundle/res/cacert.pem\ 1ÿ\ 3\0\1a\17\8bY\ 1ÿ\ 3\0-=Jn¶\ 1\0\0\0\0\0\0\f\0\0\0bin/composer\8b\ 5\0\0\1a\17\8bY\8b\ 5\0\0íeG\9a\ 1\0\0\0\0\0\0\a\0\0\0LICENSE.\ 4\0\0\1a\17\8bY.\ 4\0\0 Õ\b\ 3\ 1\0\0\0\0\0\0<?php
65
66
67
68
69
70
71
72
73
74
75
76 namespace Composer\Autoload;
77
78 use Composer\Config;
79 use Composer\EventDispatcher\EventDispatcher;
80 use Composer\Installer\InstallationManager;
81 use Composer\IO\IOInterface;
82 use Composer\Package\AliasPackage;
83 use Composer\Package\PackageInterface;
84 use Composer\Repository\InstalledRepositoryInterface;
85 use Composer\Util\Filesystem;
86 use Composer\Script\ScriptEvents;
87
88
89
90
91
92 class AutoloadGenerator
93 {
94
95
96
97 private $eventDispatcher;
98
99
100
101
102 private $io;
103
104
105
106
107 private $devMode = false;
108
109
110
111
112 private $classMapAuthoritative = false;
113
114
115
116
117 private $apcu = false;
118
119
120
121
122 private $runScripts = false;
123
124 public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
125 {
126 $this->eventDispatcher = $eventDispatcher;
127 $this->io = $io;
128 }
129
130 public function setDevMode($devMode = true)
131 {
132 $this->devMode = (bool) $devMode;
133 }
134
135
136
137
138
139
140
141 public function setClassMapAuthoritative($classMapAuthoritative)
142 {
143 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
144 }
145
146
147
148
149
150
151 public function setApcu($apcu)
152 {
153 $this->apcu = (bool) $apcu;
154 }
155
156
157
158
159
160
161 public function setRunScripts($runScripts = true)
162 {
163 $this->runScripts = (bool) $runScripts;
164 }
165
166 public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
167 {
168 if ($this->classMapAuthoritative) {
169
170  $scanPsr0Packages = true;
171 }
172 if ($this->runScripts) {
173 $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
174 'optimize' => (bool) $scanPsr0Packages,
175 ));
176 }
177
178 $filesystem = new Filesystem();
179 $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
180
181  
182  
183  $basePath = $filesystem->normalizePath(realpath(realpath(getcwd())));
184 $vendorPath = $filesystem->normalizePath(realpath(realpath($config->get('vendor-dir'))));
185 $useGlobalIncludePath = (bool) $config->get('use-include-path');
186 $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
187 $targetDir = $vendorPath.'/'.$targetDir;
188 $filesystem->ensureDirectoryExists($targetDir);
189
190 $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
191 $vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
192 $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
193
194 $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
195 $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
196
197 $namespacesFile = <<<EOF
198 <?php
199
200 // autoload_namespaces.php @generated by Composer
201
202 \$vendorDir = $vendorPathCode52;
203 \$baseDir = $appBaseDirCode;
204
205 return array(
206
207 EOF;
208
209 $psr4File = <<<EOF
210 <?php
211
212 // autoload_psr4.php @generated by Composer
213
214 \$vendorDir = $vendorPathCode52;
215 \$baseDir = $appBaseDirCode;
216
217 return array(
218
219 EOF;
220
221
222  $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
223 $autoloads = $this->parseAutoloads($packageMap, $mainPackage);
224
225
226  foreach ($autoloads['psr-0'] as $namespace => $paths) {
227 $exportedPaths = array();
228 foreach ($paths as $path) {
229 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
230 }
231 $exportedPrefix = var_export($namespace, true);
232 $namespacesFile .= "    $exportedPrefix => ";
233 $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
234 }
235 $namespacesFile .= ");\n";
236
237
238  foreach ($autoloads['psr-4'] as $namespace => $paths) {
239 $exportedPaths = array();
240 foreach ($paths as $path) {
241 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
242 }
243 $exportedPrefix = var_export($namespace, true);
244 $psr4File .= "    $exportedPrefix => ";
245 $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
246 }
247 $psr4File .= ");\n";
248
249 $classmapFile = <<<EOF
250 <?php
251
252 // autoload_classmap.php @generated by Composer
253
254 \$vendorDir = $vendorPathCode52;
255 \$baseDir = $appBaseDirCode;
256
257 return array(
258
259 EOF;
260
261
262  $targetDirLoader = null;
263 $mainAutoload = $mainPackage->getAutoload();
264 if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
265 $levels = count(explode('/', $filesystem->normalizePath($mainPackage->getTargetDir())));
266 $prefixes = implode(', ', array_map(function ($prefix) {
267 return var_export($prefix, true);
268 }, array_keys($mainAutoload['psr-0'])));
269 $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
270
271 $targetDirLoader = <<<EOF
272
273     public static function autoload(\$class)
274     {
275         \$dir = $baseDirFromTargetDirCode . '/';
276         \$prefixes = array($prefixes);
277         foreach (\$prefixes as \$prefix) {
278             if (0 !== strpos(\$class, \$prefix)) {
279                 continue;
280             }
281             \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), $levels)).'.php';
282             if (!\$path = stream_resolve_include_path(\$path)) {
283                 return false;
284             }
285             require \$path;
286
287             return true;
288         }
289     }
290
291 EOF;
292 }
293
294 $blacklist = null;
295 if (!empty($autoloads['exclude-from-classmap'])) {
296 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
297 }
298
299
300  $classMap = array();
301 if ($scanPsr0Packages) {
302 $namespacesToScan = array();
303
304
305  foreach (array('psr-0', 'psr-4') as $psrType) {
306 foreach ($autoloads[$psrType] as $namespace => $paths) {
307 $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
308 }
309 }
310
311 krsort($namespacesToScan);
312
313 foreach ($namespacesToScan as $namespace => $groups) {
314 foreach ($groups as $group) {
315 foreach ($group['paths'] as $dir) {
316 $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
317 if (!is_dir($dir)) {
318 continue;
319 }
320
321 $namespaceFilter = $namespace === '' ? null : $namespace;
322 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespaceFilter, $classMap);
323 }
324 }
325 }
326 }
327
328 foreach ($autoloads['classmap'] as $dir) {
329 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, $classMap);
330 }
331
332 ksort($classMap);
333 foreach ($classMap as $class => $code) {
334 $classmapFile .= '    '.var_export($class, true).' => '.$code;
335 }
336 $classmapFile .= ");\n";
337
338 if (!$suffix) {
339 if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
340 $content = file_get_contents($vendorPath.'/autoload.php');
341 if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
342 $suffix = $match[1];
343 }
344 }
345
346 if (!$suffix) {
347 $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true));
348 }
349 }
350
351 file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
352 file_put_contents($targetDir.'/autoload_psr4.php', $psr4File);
353 file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);
354 $includePathFilePath = $targetDir.'/include_paths.php';
355 if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
356 file_put_contents($includePathFilePath, $includePathFileContents);
357 } elseif (file_exists($includePathFilePath)) {
358 unlink($includePathFilePath);
359 }
360 $includeFilesFilePath = $targetDir.'/autoload_files.php';
361 if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
362 file_put_contents($includeFilesFilePath, $includeFilesFileContents);
363 } elseif (file_exists($includeFilesFilePath)) {
364 unlink($includeFilesFilePath);
365 }
366 file_put_contents($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
367 file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
368 file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
369
370 $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
371 $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
372
373 if ($this->runScripts) {
374 $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
375 'optimize' => (bool) $scanPsr0Packages,
376 ));
377 }
378 }
379
380 private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist = null, $namespaceFilter = null, array $classMap = array())
381 {
382 foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter) as $class => $path) {
383 $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
384 if (!isset($classMap[$class])) {
385 $classMap[$class] = $pathCode;
386 } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
387 $this->io->writeError(
388 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
389 ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
390 );
391 }
392 }
393
394 return $classMap;
395 }
396
397 private function generateClassMap($dir, $blacklist = null, $namespaceFilter = null, $showAmbiguousWarning = true)
398 {
399 return ClassMapGenerator::createMap($dir, $blacklist, $showAmbiguousWarning ? $this->io : null, $namespaceFilter);
400 }
401
402 public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
403 {
404
405  $packageMap = array(array($mainPackage, ''));
406
407 foreach ($packages as $package) {
408 if ($package instanceof AliasPackage) {
409 continue;
410 }
411 $this->validatePackage($package);
412
413 $packageMap[] = array(
414 $package,
415 $installationManager->getInstallPath($package),
416 );
417 }
418
419 return $packageMap;
420 }
421
422
423
424
425
426
427 protected function validatePackage(PackageInterface $package)
428 {
429 $autoload = $package->getAutoload();
430 if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
431 $name = $package->getName();
432 $package->getTargetDir();
433 throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '$name'.");
434 }
435 if (!empty($autoload['psr-4'])) {
436 foreach ($autoload['psr-4'] as $namespace => $dirs) {
437 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
438 throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '$namespace' does not, use '$namespace\\'.");
439 }
440 }
441 }
442 }
443
444
445
446
447
448
449
450
451 public function parseAutoloads(array $packageMap, PackageInterface $mainPackage)
452 {
453 $mainPackageMap = array_shift($packageMap);
454 $sortedPackageMap = $this->sortPackageMap($packageMap);
455 $sortedPackageMap[] = $mainPackageMap;
456 array_unshift($packageMap, $mainPackageMap);
457
458 $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
459 $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
460 $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
461 $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
462 $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
463
464 krsort($psr0);
465 krsort($psr4);
466
467 return array(
468 'psr-0' => $psr0,
469 'psr-4' => $psr4,
470 'classmap' => $classmap,
471 'files' => $files,
472 'exclude-from-classmap' => $exclude,
473 );
474 }
475
476
477
478
479
480
481
482 public function createLoader(array $autoloads)
483 {
484 $loader = new ClassLoader();
485
486 if (isset($autoloads['psr-0'])) {
487 foreach ($autoloads['psr-0'] as $namespace => $path) {
488 $loader->add($namespace, $path);
489 }
490 }
491
492 if (isset($autoloads['psr-4'])) {
493 foreach ($autoloads['psr-4'] as $namespace => $path) {
494 $loader->addPsr4($namespace, $path);
495 }
496 }
497
498 if (isset($autoloads['classmap'])) {
499 $blacklist = null;
500 if (!empty($autoloads['exclude-from-classmap'])) {
501 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
502 }
503
504 foreach ($autoloads['classmap'] as $dir) {
505 try {
506 $loader->addClassMap($this->generateClassMap($dir, $blacklist, null, false));
507 } catch (\RuntimeException $e) {
508 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
509 }
510 }
511 }
512
513 return $loader;
514 }
515
516 protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
517 {
518 $includePaths = array();
519
520 foreach ($packageMap as $item) {
521 list($package, $installPath) = $item;
522
523 if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
524 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
525 }
526
527 foreach ($package->getIncludePaths() as $includePath) {
528 $includePath = trim($includePath, '/');
529 $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
530 }
531 }
532
533 if (!$includePaths) {
534 return;
535 }
536
537 $includePathsCode = '';
538 foreach ($includePaths as $path) {
539 $includePathsCode .= "    " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
540 }
541
542 return <<<EOF
543 <?php
544
545 // include_paths.php @generated by Composer
546
547 \$vendorDir = $vendorPathCode;
548 \$baseDir = $appBaseDirCode;
549
550 return array(
551 $includePathsCode);
552
553 EOF;
554 }
555
556 protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
557 {
558 $filesCode = '';
559 foreach ($files as $fileIdentifier => $functionFile) {
560 $filesCode .= '    ' . var_export($fileIdentifier, true) . ' => '
561 . $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile) . ",\n";
562 }
563
564 if (!$filesCode) {
565 return false;
566 }
567
568 return <<<EOF
569 <?php
570
571 // autoload_files.php @generated by Composer
572
573 \$vendorDir = $vendorPathCode;
574 \$baseDir = $appBaseDirCode;
575
576 return array(
577 $filesCode);
578
579 EOF;
580 }
581
582 protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $path)
583 {
584 if (!$filesystem->isAbsolutePath($path)) {
585 $path = $basePath . '/' . $path;
586 }
587 $path = $filesystem->normalizePath($path);
588
589 $baseDir = '';
590 if (strpos($path.'/', $vendorPath.'/') === 0) {
591 $path = substr($path, strlen($vendorPath));
592 $baseDir = '$vendorDir';
593
594 if ($path !== false) {
595 $baseDir .= " . ";
596 }
597 } else {
598 $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, true));
599 if (!$filesystem->isAbsolutePath($path)) {
600 $baseDir = '$baseDir . ';
601 $path = '/' . $path;
602 }
603 }
604
605 if (preg_match('/\.phar.+$/', $path)) {
606 $baseDir = "'phar://' . " . $baseDir;
607 }
608
609 return $baseDir . (($path !== false) ? var_export($path, true) : "");
610 }
611
612 protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix)
613 {
614 $lastChar = $vendorPathToTargetDirCode[strlen($vendorPathToTargetDirCode) - 1];
615 if ("'" === $lastChar || '"' === $lastChar) {
616 $vendorPathToTargetDirCode = substr($vendorPathToTargetDirCode, 0, -1).'/autoload_real.php'.$lastChar;
617 } else {
618 $vendorPathToTargetDirCode .= " . '/autoload_real.php'";
619 }
620
621 return <<<AUTOLOAD
622 <?php
623
624 // autoload.php @generated by Composer
625
626 require_once $vendorPathToTargetDirCode;
627
628 return ComposerAutoloaderInit$suffix::getLoader();
629
630 AUTOLOAD;
631 }
632
633 protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion = 70000)
634 {
635 $file = <<<HEADER
636 <?php
637
638 // autoload_real.php @generated by Composer
639
640 class ComposerAutoloaderInit$suffix
641 {
642     private static \$loader;
643
644     public static function loadClassLoader(\$class)
645     {
646         if ('Composer\\Autoload\\ClassLoader' === \$class) {
647             require __DIR__ . '/ClassLoader.php';
648         }
649     }
650
651     public static function getLoader()
652     {
653         if (null !== self::\$loader) {
654             return self::\$loader;
655         }
656
657         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader);
658         self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
659         spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
660
661
662 HEADER;
663
664 if ($useIncludePath) {
665 $file .= <<<'INCLUDE_PATH'
666         $includePaths = require __DIR__ . '/include_paths.php';
667         array_push($includePaths, get_include_path());
668         set_include_path(implode(PATH_SEPARATOR, $includePaths));
669
670
671 INCLUDE_PATH;
672 }
673
674 $file .= <<<STATIC_INIT
675         \$useStaticLoader = PHP_VERSION_ID >= $staticPhpVersion && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
676         if (\$useStaticLoader) {
677             require_once __DIR__ . '/autoload_static.php';
678
679             call_user_func(\Composer\Autoload\ComposerStaticInit$suffix::getInitializer(\$loader));
680         } else {
681
682 STATIC_INIT;
683
684 if (!$this->classMapAuthoritative) {
685 $file .= <<<'PSR04'
686             $map = require __DIR__ . '/autoload_namespaces.php';
687             foreach ($map as $namespace => $path) {
688                 $loader->set($namespace, $path);
689             }
690
691             $map = require __DIR__ . '/autoload_psr4.php';
692             foreach ($map as $namespace => $path) {
693                 $loader->setPsr4($namespace, $path);
694             }
695
696
697 PSR04;
698 }
699
700 if ($useClassMap) {
701 $file .= <<<'CLASSMAP'
702             $classMap = require __DIR__ . '/autoload_classmap.php';
703             if ($classMap) {
704                 $loader->addClassMap($classMap);
705             }
706
707 CLASSMAP;
708 }
709
710 $file .= "        }\n\n";
711
712 if ($this->classMapAuthoritative) {
713 $file .= <<<'CLASSMAPAUTHORITATIVE'
714         $loader->setClassMapAuthoritative(true);
715
716 CLASSMAPAUTHORITATIVE;
717 }
718
719 if ($this->apcu) {
720 $apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
721 $file .= <<<APCU
722         \$loader->setApcuPrefix('$apcuPrefix');
723
724 APCU;
725 }
726
727 if ($useGlobalIncludePath) {
728 $file .= <<<'INCLUDEPATH'
729         $loader->setUseIncludePath(true);
730
731 INCLUDEPATH;
732 }
733
734 if ($targetDirLoader) {
735 $file .= <<<REGISTER_TARGET_DIR_AUTOLOAD
736         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true, true);
737
738
739 REGISTER_TARGET_DIR_AUTOLOAD;
740 }
741
742 $file .= <<<REGISTER_LOADER
743         \$loader->register($prependAutoloader);
744
745
746 REGISTER_LOADER;
747
748 if ($useIncludeFiles) {
749 $file .= <<<INCLUDE_FILES
750         if (\$useStaticLoader) {
751             \$includeFiles = Composer\Autoload\ComposerStaticInit$suffix::\$files;
752         } else {
753             \$includeFiles = require __DIR__ . '/autoload_files.php';
754         }
755         foreach (\$includeFiles as \$fileIdentifier => \$file) {
756             composerRequire$suffix(\$fileIdentifier, \$file);
757         }
758
759
760 INCLUDE_FILES;
761 }
762
763 $file .= <<<METHOD_FOOTER
764         return \$loader;
765     }
766
767 METHOD_FOOTER;
768
769 $file .= $targetDirLoader;
770
771 if ($useIncludeFiles) {
772 return $file . <<<FOOTER
773 }
774
775 function composerRequire$suffix(\$fileIdentifier, \$file)
776 {
777     if (empty(\$GLOBALS['__composer_autoload_files'][\$fileIdentifier])) {
778         require \$file;
779
780         \$GLOBALS['__composer_autoload_files'][\$fileIdentifier] = true;
781     }
782 }
783
784 FOOTER;
785 }
786
787 return $file . <<<FOOTER
788 }
789
790 FOOTER;
791 }
792
793 protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion)
794 {
795 $staticPhpVersion = 50600;
796
797 $file = <<<HEADER
798 <?php
799
800 // autoload_static.php @generated by Composer
801
802 namespace Composer\Autoload;
803
804 class ComposerStaticInit$suffix
805 {
806
807 HEADER;
808
809 $loader = new ClassLoader();
810
811 $map = require $targetDir . '/autoload_namespaces.php';
812 foreach ($map as $namespace => $path) {
813 $loader->set($namespace, $path);
814 }
815
816 $map = require $targetDir . '/autoload_psr4.php';
817 foreach ($map as $namespace => $path) {
818 $loader->setPsr4($namespace, $path);
819 }
820
821 $classMap = require $targetDir . '/autoload_classmap.php';
822 if ($classMap) {
823 $loader->addClassMap($classMap);
824 }
825
826 $filesystem = new Filesystem();
827
828 $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
829 $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
830
831 $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
832 $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
833
834 $initializer = '';
835 $prefix = "\0Composer\Autoload\ClassLoader\0";
836 $prefixLen = strlen($prefix);
837 if (file_exists($targetDir . '/autoload_files.php')) {
838 $maps = array('files' => require $targetDir . '/autoload_files.php');
839 } else {
840 $maps = array();
841 }
842
843 foreach ((array) $loader as $prop => $value) {
844 if ($value && 0 === strpos($prop, $prefix)) {
845 $maps[substr($prop, $prefixLen)] = $value;
846 }
847 }
848
849 foreach ($maps as $prop => $value) {
850 if (count($value) > 32767) {
851
852  
853  $staticPhpVersion = 70000;
854 }
855 $value = var_export($value, true);
856 $value = str_replace($absoluteVendorPathCode, $vendorPathCode, $value);
857 $value = str_replace($absoluteAppBaseDirCode, $appBaseDirCode, $value);
858 $value = ltrim(preg_replace('/^ */m', '    $0$0', $value));
859
860 $file .= sprintf("    public static $%s = %s;\n\n", $prop, $value);
861 if ('files' !== $prop) {
862 $initializer .= "            \$loader->$prop = ComposerStaticInit$suffix::\$$prop;\n";
863 }
864 }
865
866 return $file . <<<INITIALIZER
867     public static function getInitializer(ClassLoader \$loader)
868     {
869         return \Closure::bind(function () use (\$loader) {
870 $initializer
871         }, null, ClassLoader::class);
872     }
873 }
874
875 INITIALIZER;
876 }
877
878 protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
879 {
880 $autoloads = array();
881
882 foreach ($packageMap as $item) {
883 list($package, $installPath) = $item;
884
885 $autoload = $package->getAutoload();
886 if ($this->devMode && $package === $mainPackage) {
887 $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
888 }
889
890
891  if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
892 continue;
893 }
894 if (null !== $package->getTargetDir() && $package !== $mainPackage) {
895 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
896 }
897
898 foreach ($autoload[$type] as $namespace => $paths) {
899 foreach ((array) $paths as $path) {
900 if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
901
902  if ($package === $mainPackage) {
903 $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
904 $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
905 } else {
906
907  $path = $package->getTargetDir() . '/' . $path;
908 }
909 }
910
911 if ($type === 'exclude-from-classmap') {
912
913  $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
914
915
916  $path = str_replace('\\*\\*', '.+?', $path);
917 $path = str_replace('\\*', '[^/]+?', $path);
918
919
920  $updir = null;
921 $path = preg_replace_callback(
922 '{^((?:(?:\\\\\\.){1,2}+/)+)}',
923 function ($matches) use (&$updir) {
924 if (isset($matches[1])) {
925
926  $updir = str_replace('\\.', '.', $matches[1]);
927 }
928
929 return '';
930 },
931 $path
932 );
933 if (empty($installPath)) {
934 $installPath = strtr(getcwd(), '\\', '/');
935 }
936
937 $resolvedPath = realpath($installPath . '/' . $updir);
938 $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path;
939 continue;
940 }
941
942 $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
943
944 if ($type === 'files') {
945 $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
946 continue;
947 } elseif ($type === 'classmap') {
948 $autoloads[] = $relativePath;
949 continue;
950 }
951
952 $autoloads[$namespace][] = $relativePath;
953 }
954 }
955 }
956
957 return $autoloads;
958 }
959
960 protected function getFileIdentifier(PackageInterface $package, $path)
961 {
962 return md5($package->getName() . ':' . $path);
963 }
964
965
966
967
968
969
970
971
972
973 protected function sortPackageMap(array $packageMap)
974 {
975 $packages = array();
976 $paths = array();
977 $usageList = array();
978
979 foreach ($packageMap as $item) {
980 list($package, $path) = $item;
981 $name = $package->getName();
982 $packages[$name] = $package;
983 $paths[$name] = $path;
984
985 foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) {
986 $target = $link->getTarget();
987 $usageList[$target][] = $name;
988 }
989 }
990
991 $computing = array();
992 $computed = array();
993 $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
994
995  if (isset($computed[$name])) {
996 return $computed[$name];
997 }
998
999
1000  if (isset($computing[$name])) {
1001 return 0;
1002 }
1003
1004 $computing[$name] = true;
1005 $weight = 0;
1006
1007 if (isset($usageList[$name])) {
1008 foreach ($usageList[$name] as $user) {
1009 $weight -= 1 - $computeImportance($user);
1010 }
1011 }
1012
1013 unset($computing[$name]);
1014 $computed[$name] = $weight;
1015
1016 return $weight;
1017 };
1018
1019 $weightList = array();
1020
1021 foreach ($packages as $name => $package) {
1022 $weight = $computeImportance($name);
1023 $weightList[$name] = $weight;
1024 }
1025
1026 $stable_sort = function (&$array) {
1027 static $transform, $restore;
1028
1029 $i = 0;
1030
1031 if (!$transform) {
1032 $transform = function (&$v, $k) use (&$i) {
1033 $v = array($v, ++$i, $k, $v);
1034 };
1035
1036 $restore = function (&$v, $k) {
1037 $v = $v[3];
1038 };
1039 }
1040
1041 array_walk($array, $transform);
1042 asort($array);
1043 array_walk($array, $restore);
1044 };
1045
1046 $stable_sort($weightList);
1047
1048 $sortedPackageMap = array();
1049
1050 foreach (array_keys($weightList) as $name) {
1051 $sortedPackageMap[] = array($packages[$name], $paths[$name]);
1052 }
1053
1054 return $sortedPackageMap;
1055 }
1056
1057
1058
1059
1060
1061
1062
1063 protected function safeCopy($source, $target)
1064 {
1065 $source = fopen($source, 'r');
1066 $target = fopen($target, 'w+');
1067
1068 stream_copy_to_stream($source, $target);
1069 fclose($source);
1070 fclose($target);
1071 }
1072 }
1073 <?php
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091 namespace Composer\Autoload;
1092
1093 use Symfony\Component\Finder\Finder;
1094 use Composer\IO\IOInterface;
1095 use Composer\Util\Filesystem;
1096
1097
1098
1099
1100
1101
1102
1103 class ClassMapGenerator
1104 {
1105
1106
1107
1108
1109
1110
1111 public static function dump($dirs, $file)
1112 {
1113 $maps = array();
1114
1115 foreach ($dirs as $dir) {
1116 $maps = array_merge($maps, static::createMap($dir));
1117 }
1118
1119 file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
1120 }
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 public static function createMap($path, $blacklist = null, IOInterface $io = null, $namespace = null)
1134 {
1135 if (is_string($path)) {
1136 if (is_file($path)) {
1137 $path = array(new \SplFileInfo($path));
1138 } elseif (is_dir($path)) {
1139 $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
1140 } else {
1141 throw new \RuntimeException(
1142 'Could not scan for classes inside "'.$path.
1143 '" which does not appear to be a file nor a folder'
1144 );
1145 }
1146 }
1147
1148 $map = array();
1149 $filesystem = new Filesystem();
1150 $cwd = realpath(getcwd());
1151
1152 foreach ($path as $file) {
1153 $filePath = $file->getPathname();
1154 if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
1155 continue;
1156 }
1157
1158 if (!$filesystem->isAbsolutePath($filePath)) {
1159 $filePath = $cwd . '/' . $filePath;
1160 $filePath = $filesystem->normalizePath($filePath);
1161 } else {
1162 $filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath);
1163 }
1164
1165
1166  if ($blacklist && preg_match($blacklist, strtr(realpath($filePath), '\\', '/'))) {
1167 continue;
1168 }
1169
1170 $classes = self::findClasses($filePath);
1171
1172 foreach ($classes as $class) {
1173
1174  if (null !== $namespace && 0 !== strpos($class, $namespace)) {
1175 continue;
1176 }
1177
1178 if (!isset($map[$class])) {
1179 $map[$class] = $filePath;
1180 } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
1181 $io->writeError(
1182 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
1183 ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
1184 );
1185 }
1186 }
1187 }
1188
1189 return $map;
1190 }
1191
1192
1193
1194
1195
1196
1197
1198
1199 private static function findClasses($path)
1200 {
1201 $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
1202 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
1203 $extraTypes .= '|enum';
1204 }
1205
1206
1207  
1208  $contents = @php_strip_whitespace($path);
1209 if (!$contents) {
1210 if (!file_exists($path)) {
1211 $message = 'File at "%s" does not exist, check your classmap definitions';
1212 } elseif (!is_readable($path)) {
1213 $message = 'File at "%s" is not readable, check its permissions';
1214 } elseif ('' === trim(file_get_contents($path))) {
1215
1216  return array();
1217 } else {
1218 $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
1219 }
1220 $error = error_get_last();
1221 if (isset($error['message'])) {
1222 $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
1223 }
1224 throw new \RuntimeException(sprintf($message, $path));
1225 }
1226
1227
1228  if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
1229 return array();
1230 }
1231
1232
1233  $contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents);
1234
1235  $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
1236
1237  if (substr($contents, 0, 2) !== '<?') {
1238 $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
1239 if ($replacements === 0) {
1240 return array();
1241 }
1242 }
1243
1244  $contents = preg_replace('{\?>.+<\?}s', '?><?', $contents);
1245
1246  $pos = strrpos($contents, '?>');
1247 if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
1248 $contents = substr($contents, 0, $pos);
1249 }
1250
1251 preg_match_all('{
1252             (?:
1253                  \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
1254                | \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*+ [\{;]
1255             )
1256         }ix', $contents, $matches);
1257
1258 $classes = array();
1259 $namespace = '';
1260
1261 for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
1262 if (!empty($matches['ns'][$i])) {
1263 $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
1264 } else {
1265 $name = $matches['name'][$i];
1266
1267  if ($name === 'extends' || $name === 'implements') {
1268 continue;
1269 }
1270 if ($name[0] === ':') {
1271
1272  $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
1273 } elseif ($matches['type'][$i] === 'enum') {
1274
1275  
1276  
1277  
1278  $name = rtrim($name, ':');
1279 }
1280 $classes[] = ltrim($namespace . $name, '\\');
1281 }
1282 }
1283
1284 return $classes;
1285 }
1286 }
1287 <?php
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299 namespace Composer;
1300
1301 use Composer\IO\IOInterface;
1302 use Composer\Util\Filesystem;
1303 use Composer\Util\Silencer;
1304 use Symfony\Component\Finder\Finder;
1305
1306
1307
1308
1309
1310
1311 class Cache
1312 {
1313 private static $cacheCollected = false;
1314 private $io;
1315 private $root;
1316 private $enabled = true;
1317 private $whitelist;
1318 private $filesystem;
1319
1320
1321
1322
1323
1324
1325
1326 public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
1327 {
1328 $this->io = $io;
1329 $this->root = rtrim($cacheDir, '/\\') . '/';
1330 $this->whitelist = $whitelist;
1331 $this->filesystem = $filesystem ?: new Filesystem();
1332
1333 if (preg_match('{(^|[\\\\/])(\$null|NUL|/dev/null)([\\\\/]|$)}', $cacheDir)) {
1334 $this->enabled = false;
1335
1336 return;
1337 }
1338
1339 if (
1340 (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, true))
1341 || !is_writable($this->root)
1342 ) {
1343 $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
1344 $this->enabled = false;
1345 }
1346 }
1347
1348 public function isEnabled()
1349 {
1350 return $this->enabled;
1351 }
1352
1353 public function getRoot()
1354 {
1355 return $this->root;
1356 }
1357
1358 public function read($file)
1359 {
1360 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1361 if ($this->enabled && file_exists($this->root . $file)) {
1362 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1363
1364 return file_get_contents($this->root . $file);
1365 }
1366
1367 return false;
1368 }
1369
1370 public function write($file, $contents)
1371 {
1372 if ($this->enabled) {
1373 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1374
1375 $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
1376
1377 try {
1378 return file_put_contents($this->root . $file, $contents);
1379 } catch (\ErrorException $e) {
1380 $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', true, IOInterface::DEBUG);
1381 if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
1382
1383  unlink($this->root . $file);
1384
1385 $message = sprintf(
1386 '<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available</warning>',
1387 $this->root . $file,
1388 $m[1],
1389 $m[2],
1390 @disk_free_space($this->root . dirname($file))
1391 );
1392
1393 $this->io->writeError($message);
1394
1395 return false;
1396 }
1397
1398 throw $e;
1399 }
1400 }
1401
1402 return false;
1403 }
1404
1405
1406
1407
1408 public function copyFrom($file, $source)
1409 {
1410 if ($this->enabled) {
1411 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1412 $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
1413
1414 if (!file_exists($source)) {
1415 $this->io->writeError('<error>'.$source.' does not exist, can not write into cache</error>');
1416 } elseif ($this->io->isDebug()) {
1417 $this->io->writeError('Writing '.$this->root . $file.' into cache from '.$source);
1418 }
1419
1420 return copy($source, $this->root . $file);
1421 }
1422
1423 return false;
1424 }
1425
1426
1427
1428
1429 public function copyTo($file, $target)
1430 {
1431 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1432 if ($this->enabled && file_exists($this->root . $file)) {
1433 try {
1434 touch($this->root . $file, filemtime($this->root . $file), time());
1435 } catch (\ErrorException $e) {
1436
1437  
1438  Silencer::call('touch', $this->root . $file);
1439 }
1440
1441 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1442
1443 return copy($this->root . $file, $target);
1444 }
1445
1446 return false;
1447 }
1448
1449 public function gcIsNecessary()
1450 {
1451 return (!self::$cacheCollected && !mt_rand(0, 50));
1452 }
1453
1454 public function remove($file)
1455 {
1456 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1457 if ($this->enabled && file_exists($this->root . $file)) {
1458 return $this->filesystem->unlink($this->root . $file);
1459 }
1460
1461 return false;
1462 }
1463
1464 public function clear()
1465 {
1466 if ($this->enabled) {
1467 return $this->filesystem->removeDirectory($this->root);
1468 }
1469
1470 return false;
1471 }
1472
1473 public function gc($ttl, $maxSize)
1474 {
1475 if ($this->enabled) {
1476 $expire = new \DateTime();
1477 $expire->modify('-'.$ttl.' seconds');
1478
1479 $finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
1480 foreach ($finder as $file) {
1481 $this->filesystem->unlink($file->getPathname());
1482 }
1483
1484 $totalSize = $this->filesystem->size($this->root);
1485 if ($totalSize > $maxSize) {
1486 $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
1487 while ($totalSize > $maxSize && $iterator->valid()) {
1488 $filepath = $iterator->current()->getPathname();
1489 $totalSize -= $this->filesystem->size($filepath);
1490 $this->filesystem->unlink($filepath);
1491 $iterator->next();
1492 }
1493 }
1494
1495 self::$cacheCollected = true;
1496
1497 return true;
1498 }
1499
1500 return false;
1501 }
1502
1503 public function sha1($file)
1504 {
1505 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1506 if ($this->enabled && file_exists($this->root . $file)) {
1507 return sha1_file($this->root . $file);
1508 }
1509
1510 return false;
1511 }
1512
1513 public function sha256($file)
1514 {
1515 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1516 if ($this->enabled && file_exists($this->root . $file)) {
1517 return hash_file('sha256', $this->root . $file);
1518 }
1519
1520 return false;
1521 }
1522
1523 protected function getFinder()
1524 {
1525 return Finder::create()->in($this->root)->files();
1526 }
1527 }
1528 <?php
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540 namespace Composer\Command;
1541
1542 use Symfony\Component\Console\Input\InputInterface;
1543 use Symfony\Component\Console\Output\OutputInterface;
1544
1545
1546
1547
1548 class AboutCommand extends BaseCommand
1549 {
1550 protected function configure()
1551 {
1552 $this
1553 ->setName('about')
1554 ->setDescription('Shows the short information about Composer.')
1555 ->setHelp(<<<EOT
1556 <info>php composer.phar about</info>
1557 EOT
1558 )
1559 ;
1560 }
1561
1562 protected function execute(InputInterface $input, OutputInterface $output)
1563 {
1564 $this->getIO()->write(<<<EOT
1565 <info>Composer - Package Management for PHP</info>
1566 <comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
1567 See https://getcomposer.org/ for more information.</comment>
1568 EOT
1569 );
1570 }
1571 }
1572 <?php
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584 namespace Composer\Command;
1585
1586 use Composer\Factory;
1587 use Composer\IO\IOInterface;
1588 use Composer\Config;
1589 use Composer\Composer;
1590 use Composer\Repository\CompositeRepository;
1591 use Composer\Repository\RepositoryFactory;
1592 use Composer\Script\ScriptEvents;
1593 use Composer\Plugin\CommandEvent;
1594 use Composer\Plugin\PluginEvents;
1595 use Composer\Util\Filesystem;
1596 use Symfony\Component\Console\Input\InputArgument;
1597 use Symfony\Component\Console\Input\InputInterface;
1598 use Symfony\Component\Console\Input\InputOption;
1599 use Symfony\Component\Console\Output\OutputInterface;
1600
1601
1602
1603
1604
1605
1606 class ArchiveCommand extends BaseCommand
1607 {
1608 protected function configure()
1609 {
1610 $this
1611 ->setName('archive')
1612 ->setDescription('Creates an archive of this composer package.')
1613 ->setDefinition(array(
1614 new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project'),
1615 new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'),
1616 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar or zip'),
1617 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
1618 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
1619 .' Note that the format will be appended.'),
1620 new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
1621 ))
1622 ->setHelp(<<<EOT
1623 The <info>archive</info> command creates an archive of the specified format
1624 containing the files and directories of the Composer project or the specified
1625 package in the specified version and writes it to the specified directory.
1626
1627 <info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
1628
1629 EOT
1630 )
1631 ;
1632 }
1633
1634 protected function execute(InputInterface $input, OutputInterface $output)
1635 {
1636 $config = Factory::createConfig();
1637 $composer = $this->getComposer(false);
1638 if ($composer) {
1639 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
1640 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
1641 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
1642 }
1643
1644 if (null === $input->getOption('format')) {
1645 $input->setOption('format', $config->get('archive-format'));
1646 }
1647 if (null === $input->getOption('dir')) {
1648 $input->setOption('dir', $config->get('archive-dir'));
1649 }
1650
1651 $returnCode = $this->archive(
1652 $this->getIO(),
1653 $config,
1654 $input->getArgument('package'),
1655 $input->getArgument('version'),
1656 $input->getOption('format'),
1657 $input->getOption('dir'),
1658 $input->getOption('file'),
1659 $input->getOption('ignore-filters'),
1660 $composer
1661 );
1662
1663 if (0 === $returnCode && $composer) {
1664 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
1665 }
1666
1667 return $returnCode;
1668 }
1669
1670 protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null, $ignoreFilters = false, Composer $composer = null)
1671 {
1672 if ($composer) {
1673 $archiveManager = $composer->getArchiveManager();
1674 } else {
1675 $factory = new Factory;
1676 $downloadManager = $factory->createDownloadManager($io, $config);
1677 $archiveManager = $factory->createArchiveManager($config, $downloadManager);
1678 }
1679
1680 if ($packageName) {
1681 $package = $this->selectPackage($io, $packageName, $version);
1682
1683 if (!$package) {
1684 return 1;
1685 }
1686 } else {
1687 $package = $this->getComposer()->getPackage();
1688 }
1689
1690 $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
1691 $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
1692 $fs = new Filesystem;
1693 $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
1694
1695 $io->writeError('Created: ', false);
1696 $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
1697
1698 return 0;
1699 }
1700
1701 protected function selectPackage(IOInterface $io, $packageName, $version = null)
1702 {
1703 $io->writeError('<info>Searching for the specified package.</info>');
1704
1705 if ($composer = $this->getComposer(false)) {
1706 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
1707 $repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
1708 } else {
1709 $defaultRepos = RepositoryFactory::defaultRepos($this->getIO());
1710 $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
1711 $repo = new CompositeRepository($defaultRepos);
1712 }
1713
1714 $packages = $repo->findPackages($packageName, $version);
1715
1716 if (count($packages) > 1) {
1717 $package = reset($packages);
1718 $io->writeError('<info>Found multiple matches, selected '.$package->getPrettyString().'.</info>');
1719 $io->writeError('Alternatives were '.implode(', ', array_map(function ($p) {
1720 return $p->getPrettyString();
1721 }, $packages)).'.');
1722 $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
1723 } elseif ($packages) {
1724 $package = reset($packages);
1725 $io->writeError('<info>Found an exact match '.$package->getPrettyString().'.</info>');
1726 } else {
1727 $io->writeError('<error>Could not find a package matching '.$packageName.'.</error>');
1728
1729 return false;
1730 }
1731
1732 return $package;
1733 }
1734 }
1735 <?php
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747 namespace Composer\Command;
1748
1749 use Composer\Composer;
1750 use Composer\Config;
1751 use Composer\Console\Application;
1752 use Composer\IO\IOInterface;
1753 use Composer\IO\NullIO;
1754 use Symfony\Component\Console\Input\InputInterface;
1755 use Symfony\Component\Console\Output\OutputInterface;
1756 use Symfony\Component\Console\Command\Command;
1757
1758
1759
1760
1761
1762
1763
1764 abstract class BaseCommand extends Command
1765 {
1766
1767
1768
1769 private $composer;
1770
1771
1772
1773
1774 private $io;
1775
1776
1777
1778
1779
1780
1781
1782 public function getComposer($required = true, $disablePlugins = null)
1783 {
1784 if (null === $this->composer) {
1785 $application = $this->getApplication();
1786 if ($application instanceof Application) {
1787
1788 $this->composer = $application->getComposer($required, $disablePlugins);
1789 } elseif ($required) {
1790 throw new \RuntimeException(
1791 'Could not create a Composer\Composer instance, you must inject '.
1792 'one if this command is not used with a Composer\Console\Application instance'
1793 );
1794 }
1795 }
1796
1797 return $this->composer;
1798 }
1799
1800
1801
1802
1803 public function setComposer(Composer $composer)
1804 {
1805 $this->composer = $composer;
1806 }
1807
1808
1809
1810
1811 public function resetComposer()
1812 {
1813 $this->composer = null;
1814 $this->getApplication()->resetComposer();
1815 }
1816
1817
1818
1819
1820
1821
1822
1823
1824 public function isProxyCommand()
1825 {
1826 return false;
1827 }
1828
1829
1830
1831
1832 public function getIO()
1833 {
1834 if (null === $this->io) {
1835 $application = $this->getApplication();
1836 if ($application instanceof Application) {
1837
1838 $this->io = $application->getIO();
1839 } else {
1840 $this->io = new NullIO();
1841 }
1842 }
1843
1844 return $this->io;
1845 }
1846
1847
1848
1849
1850 public function setIO(IOInterface $io)
1851 {
1852 $this->io = $io;
1853 }
1854
1855
1856
1857
1858 protected function initialize(InputInterface $input, OutputInterface $output)
1859 {
1860 if (true === $input->hasParameterOption(array('--no-ansi')) && $input->hasOption('no-progress')) {
1861 $input->setOption('no-progress', true);
1862 }
1863
1864 parent::initialize($input, $output);
1865 }
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876 protected function getPreferredInstallOptions(Config $config, InputInterface $input, $keepVcsRequiresPreferSource = false)
1877 {
1878 $preferSource = false;
1879 $preferDist = false;
1880
1881 switch ($config->get('preferred-install')) {
1882 case 'source':
1883 $preferSource = true;
1884 break;
1885 case 'dist':
1886 $preferDist = true;
1887 break;
1888 case 'auto':
1889 default:
1890
1891  break;
1892 }
1893
1894 if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
1895 $preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
1896 $preferDist = $input->getOption('prefer-dist');
1897 }
1898
1899 return array($preferSource, $preferDist);
1900 }
1901 }
1902 <?php
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914 namespace Composer\Command;
1915
1916 use Composer\DependencyResolver\Pool;
1917 use Composer\Package\Link;
1918 use Composer\Package\PackageInterface;
1919 use Composer\Repository\ArrayRepository;
1920 use Composer\Repository\CompositeRepository;
1921 use Composer\Repository\PlatformRepository;
1922 use Composer\Repository\RepositoryFactory;
1923 use Composer\Plugin\CommandEvent;
1924 use Composer\Plugin\PluginEvents;
1925 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
1926 use Composer\Package\Version\VersionParser;
1927 use Symfony\Component\Console\Helper\Table;
1928 use Symfony\Component\Console\Input\InputArgument;
1929 use Symfony\Component\Console\Input\InputInterface;
1930 use Symfony\Component\Console\Input\InputOption;
1931 use Symfony\Component\Console\Output\OutputInterface;
1932
1933
1934
1935
1936
1937
1938 class BaseDependencyCommand extends BaseCommand
1939 {
1940 const ARGUMENT_PACKAGE = 'package';
1941 const ARGUMENT_CONSTRAINT = 'constraint';
1942 const OPTION_RECURSIVE = 'recursive';
1943 const OPTION_TREE = 'tree';
1944
1945 protected $colors;
1946
1947
1948
1949
1950 protected function configure()
1951 {
1952 $this->setDefinition(array(
1953 new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
1954 new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
1955 new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
1956 new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
1957 ));
1958 }
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968 protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
1969 {
1970
1971  $composer = $this->getComposer();
1972 $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
1973 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
1974
1975
1976  $platformOverrides = $composer->getConfig()->get('platform') ?: array();
1977 $repository = new CompositeRepository(array(
1978 new ArrayRepository(array($composer->getPackage())),
1979 $composer->getRepositoryManager()->getLocalRepository(),
1980 new PlatformRepository(array(), $platformOverrides),
1981 ));
1982 $pool = new Pool();
1983 $pool->addRepository($repository);
1984
1985
1986  list($needle, $textConstraint) = array_pad(
1987 explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
1988 2,
1989 $input->getArgument(self::ARGUMENT_CONSTRAINT)
1990 );
1991
1992
1993  $packages = $pool->whatProvides($needle);
1994 if (empty($packages)) {
1995 throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
1996 }
1997
1998
1999  
2000  if (!$repository->findPackage($needle, $textConstraint)) {
2001 $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
2002 if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
2003 $repository->addRepository(new ArrayRepository(array(clone $match)));
2004 }
2005 }
2006
2007
2008  $needles = array($needle);
2009 if ($inverted) {
2010 foreach ($packages as $package) {
2011 $needles = array_merge($needles, array_map(function (Link $link) {
2012 return $link->getTarget();
2013 }, $package->getReplaces()));
2014 }
2015 }
2016
2017
2018  if ('*' !== $textConstraint) {
2019 $versionParser = new VersionParser();
2020 $constraint = $versionParser->parseConstraints($textConstraint);
2021 } else {
2022 $constraint = null;
2023 }
2024
2025
2026  $renderTree = $input->getOption(self::OPTION_TREE);
2027 $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
2028
2029
2030  $results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
2031 if (empty($results)) {
2032 $extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
2033 $this->getIO()->writeError(sprintf('<info>There is no installed package depending on "%s"%s</info>',
2034 $needle, $extra));
2035 } elseif ($renderTree) {
2036 $this->initStyles($output);
2037 $root = $packages[0];
2038 $this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
2039 $this->printTree($results);
2040 } else {
2041 $this->printTable($output, $results);
2042 }
2043
2044 return 0;
2045 }
2046
2047
2048
2049
2050
2051
2052
2053 protected function printTable(OutputInterface $output, $results)
2054 {
2055 $table = array();
2056 $doubles = array();
2057 do {
2058 $queue = array();
2059 $rows = array();
2060 foreach ($results as $result) {
2061
2062
2063
2064
2065 list($package, $link, $children) = $result;
2066 $unique = (string) $link;
2067 if (isset($doubles[$unique])) {
2068 continue;
2069 }
2070 $doubles[$unique] = true;
2071 $version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
2072 $rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
2073 if ($children) {
2074 $queue = array_merge($queue, $children);
2075 }
2076 }
2077 $results = $queue;
2078 $table = array_merge($rows, $table);
2079 } while (!empty($results));
2080
2081
2082  $renderer = new Table($output);
2083 $renderer->setStyle('compact');
2084 $renderer->getStyle()->setVerticalBorderChar('');
2085 $renderer->getStyle()->setCellRowContentFormat('%s  ');
2086 $renderer->setRows($table)->render();
2087 }
2088
2089
2090
2091
2092
2093
2094 protected function initStyles(OutputInterface $output)
2095 {
2096 $this->colors = array(
2097 'green',
2098 'yellow',
2099 'cyan',
2100 'magenta',
2101 'blue',
2102 );
2103
2104 foreach ($this->colors as $color) {
2105 $style = new OutputFormatterStyle($color);
2106 $output->getFormatter()->setStyle($color, $style);
2107 }
2108 }
2109
2110
2111
2112
2113
2114
2115
2116
2117 protected function printTree($results, $prefix = '', $level = 1)
2118 {
2119 $count = count($results);
2120 $idx = 0;
2121 foreach ($results as $result) {
2122
2123
2124
2125
2126
2127 list($package, $link, $children) = $result;
2128
2129 $color = $this->colors[$level % count($this->colors)];
2130 $prevColor = $this->colors[($level - 1) % count($this->colors)];
2131 $isLast = (++$idx == $count);
2132 $versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
2133 $packageText = rtrim(sprintf('<%s>%s</%1$s> %s', $color, $package->getPrettyName(), $versionText));
2134 $linkText = sprintf('%s <%s>%s</%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
2135 $circularWarn = $children === false ? '(circular dependency aborted here)' : '';
2136 $this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
2137 if ($children) {
2138 $this->printTree($children, $prefix . ($isLast ? '   ' : '│  '), $level + 1);
2139 }
2140 }
2141 }
2142
2143 private function writeTreeLine($line)
2144 {
2145 $io = $this->getIO();
2146 if (!$io->isDecorated()) {
2147 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
2148 }
2149
2150 $io->write($line);
2151 }
2152 }
2153 <?php
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165 namespace Composer\Command;
2166
2167 use Composer\Cache;
2168 use Composer\Factory;
2169 use Symfony\Component\Console\Input\InputInterface;
2170 use Symfony\Component\Console\Output\OutputInterface;
2171
2172
2173
2174
2175 class ClearCacheCommand extends BaseCommand
2176 {
2177 protected function configure()
2178 {
2179 $this
2180 ->setName('clear-cache')
2181 ->setAliases(array('clearcache'))
2182 ->setDescription('Clears composer\'s internal package cache.')
2183 ->setHelp(<<<EOT
2184 The <info>clear-cache</info> deletes all cached packages from composer's
2185 cache directory.
2186 EOT
2187 )
2188 ;
2189 }
2190
2191 protected function execute(InputInterface $input, OutputInterface $output)
2192 {
2193 $config = Factory::createConfig();
2194 $io = $this->getIO();
2195
2196 $cachePaths = array(
2197 'cache-vcs-dir' => $config->get('cache-vcs-dir'),
2198 'cache-repo-dir' => $config->get('cache-repo-dir'),
2199 'cache-files-dir' => $config->get('cache-files-dir'),
2200 'cache-dir' => $config->get('cache-dir'),
2201 );
2202
2203 foreach ($cachePaths as $key => $cachePath) {
2204 $cachePath = realpath($cachePath);
2205 if (!$cachePath) {
2206 $io->writeError("<info>Cache directory does not exist ($key): $cachePath</info>");
2207
2208 continue;
2209 }
2210 $cache = new Cache($io, $cachePath);
2211 if (!$cache->isEnabled()) {
2212 $io->writeError("<info>Cache is not enabled ($key): $cachePath</info>");
2213
2214 continue;
2215 }
2216
2217 $io->writeError("<info>Clearing cache ($key): $cachePath</info>");
2218 $cache->clear();
2219 }
2220
2221 $io->writeError('<info>All caches cleared.</info>');
2222 }
2223 }
2224 <?php
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236 namespace Composer\Command;
2237
2238 use Composer\Util\Platform;
2239 use Composer\Util\Silencer;
2240 use Symfony\Component\Console\Input\InputInterface;
2241 use Symfony\Component\Console\Input\InputArgument;
2242 use Symfony\Component\Console\Input\InputOption;
2243 use Symfony\Component\Console\Output\OutputInterface;
2244 use Composer\Config;
2245 use Composer\Config\JsonConfigSource;
2246 use Composer\Factory;
2247 use Composer\Json\JsonFile;
2248 use Composer\Semver\VersionParser;
2249 use Composer\Package\BasePackage;
2250
2251
2252
2253
2254
2255 class ConfigCommand extends BaseCommand
2256 {
2257
2258
2259
2260 protected $config;
2261
2262
2263
2264
2265 protected $configFile;
2266
2267
2268
2269
2270 protected $configSource;
2271
2272
2273
2274
2275 protected $authConfigFile;
2276
2277
2278
2279
2280 protected $authConfigSource;
2281
2282
2283
2284
2285 protected function configure()
2286 {
2287 $this
2288 ->setName('config')
2289 ->setDescription('Sets config options.')
2290 ->setDefinition(array(
2291 new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'),
2292 new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'),
2293 new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
2294 new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
2295 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
2296 new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
2297 new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
2298 new InputArgument('setting-key', null, 'Setting key'),
2299 new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
2300 ))
2301 ->setHelp(<<<EOT
2302 This command allows you to edit composer config settings and repositories
2303 in either the local composer.json file or the global config.json file.
2304
2305 Additionally it lets you edit most properties in the local composer.json.
2306
2307 To set a config setting:
2308
2309     <comment>%command.full_name% bin-dir bin/</comment>
2310
2311 To read a config setting:
2312
2313     <comment>%command.full_name% bin-dir</comment>
2314     Outputs: <info>bin</info>
2315
2316 To edit the global config.json file:
2317
2318     <comment>%command.full_name% --global</comment>
2319
2320 To add a repository:
2321
2322     <comment>%command.full_name% repositories.foo vcs https://bar.com</comment>
2323
2324 To remove a repository (repo is a short alias for repositories):
2325
2326     <comment>%command.full_name% --unset repo.foo</comment>
2327
2328 To disable packagist:
2329
2330     <comment>%command.full_name% repo.packagist false</comment>
2331
2332 You can alter repositories in the global config.json file by passing in the
2333 <info>--global</info> option.
2334
2335 To edit the file in an external editor:
2336
2337     <comment>%command.full_name% --editor</comment>
2338
2339 To choose your editor you can set the "EDITOR" env variable.
2340
2341 To get a list of configuration values in the file:
2342
2343     <comment>%command.full_name% --list</comment>
2344
2345 You can always pass more than one option. As an example, if you want to edit the
2346 global config.json file.
2347
2348     <comment>%command.full_name% --editor --global</comment>
2349 EOT
2350 )
2351 ;
2352 }
2353
2354
2355
2356
2357 protected function initialize(InputInterface $input, OutputInterface $output)
2358 {
2359 parent::initialize($input, $output);
2360
2361 if ($input->getOption('global') && null !== $input->getOption('file')) {
2362 throw new \RuntimeException('--file and --global can not be combined');
2363 }
2364
2365 $io = $this->getIO();
2366 $this->config = Factory::createConfig($io);
2367
2368
2369  
2370  $configFile = $input->getOption('global')
2371 ? ($this->config->get('home') . '/config.json')
2372 : ($input->getOption('file') ?: Factory::getComposerFile());
2373
2374
2375  if (
2376 ($configFile === 'composer.json' || $configFile === './composer.json')
2377 && !file_exists($configFile)
2378 && realpath(getcwd()) === realpath($this->config->get('home'))
2379 ) {
2380 file_put_contents($configFile, "{\n}\n");
2381 }
2382
2383 $this->configFile = new JsonFile($configFile, null, $io);
2384 $this->configSource = new JsonConfigSource($this->configFile);
2385
2386 $authConfigFile = $input->getOption('global')
2387 ? ($this->config->get('home') . '/auth.json')
2388 : dirname(realpath($configFile)) . '/auth.json';
2389
2390 $this->authConfigFile = new JsonFile($authConfigFile, null, $io);
2391 $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
2392
2393
2394  if ($input->getOption('global') && !$this->configFile->exists()) {
2395 touch($this->configFile->getPath());
2396 $this->configFile->write(array('config' => new \ArrayObject));
2397 Silencer::call('chmod', $this->configFile->getPath(), 0600);
2398 }
2399 if ($input->getOption('global') && !$this->authConfigFile->exists()) {
2400 touch($this->authConfigFile->getPath());
2401 $this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject));
2402 Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
2403 }
2404
2405 if (!$this->configFile->exists()) {
2406 throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
2407 }
2408 }
2409
2410
2411
2412
2413 protected function execute(InputInterface $input, OutputInterface $output)
2414 {
2415
2416  if ($input->getOption('editor')) {
2417 $editor = escapeshellcmd(getenv('EDITOR'));
2418 if (!$editor) {
2419 if (Platform::isWindows()) {
2420 $editor = 'notepad';
2421 } else {
2422 foreach (array('editor', 'vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
2423 if (exec('which '.$candidate)) {
2424 $editor = $candidate;
2425 break;
2426 }
2427 }
2428 }
2429 }
2430
2431 $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
2432 system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
2433
2434 return 0;
2435 }
2436
2437 if (!$input->getOption('global')) {
2438 $this->config->merge($this->configFile->read());
2439 $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
2440 }
2441
2442
2443  if ($input->getOption('list')) {
2444 $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
2445
2446 return 0;
2447 }
2448
2449 $settingKey = $input->getArgument('setting-key');
2450 if (!$settingKey) {
2451 return 0;
2452 }
2453
2454
2455  if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
2456 throw new \RuntimeException('You can not combine a setting value with --unset');
2457 }
2458
2459
2460  if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
2461 $properties = array('name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra');
2462 $rawData = $this->configFile->read();
2463 $data = $this->config->all();
2464 if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
2465 if (!isset($matches[1]) || $matches[1] === '') {
2466 $value = isset($data['repositories']) ? $data['repositories'] : array();
2467 } else {
2468 if (!isset($data['repositories'][$matches[1]])) {
2469 throw new \InvalidArgumentException('There is no '.$matches[1].' repository defined');
2470 }
2471
2472 $value = $data['repositories'][$matches[1]];
2473 }
2474 } elseif (strpos($settingKey, '.')) {
2475 $bits = explode('.', $settingKey);
2476 if ($bits[0] === 'extra') {
2477 $data = $rawData;
2478 } else {
2479 $data = $data['config'];
2480 }
2481 $match = false;
2482 foreach ($bits as $bit) {
2483 $key = isset($key) ? $key.'.'.$bit : $bit;
2484 $match = false;
2485 if (isset($data[$key])) {
2486 $match = true;
2487 $data = $data[$key];
2488 unset($key);
2489 }
2490 }
2491
2492 if (!$match) {
2493 throw new \RuntimeException($settingKey.' is not defined.');
2494 }
2495
2496 $value = $data;
2497 } elseif (isset($data['config'][$settingKey])) {
2498 $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
2499 } elseif (in_array($settingKey, $properties, true) && isset($rawData[$settingKey])) {
2500 $value = $rawData[$settingKey];
2501 } else {
2502 throw new \RuntimeException($settingKey.' is not defined');
2503 }
2504
2505 if (is_array($value)) {
2506 $value = json_encode($value);
2507 }
2508
2509 $this->getIO()->write($value);
2510
2511 return 0;
2512 }
2513
2514 $values = $input->getArgument('setting-value'); 
2515
2516 $booleanValidator = function ($val) {
2517 return in_array($val, array('true', 'false', '1', '0'), true);
2518 };
2519 $booleanNormalizer = function ($val) {
2520 return $val !== 'false' && (bool) $val;
2521 };
2522
2523
2524  $uniqueConfigValues = array(
2525 'process-timeout' => array('is_numeric', 'intval'),
2526 'use-include-path' => array($booleanValidator, $booleanNormalizer),
2527 'preferred-install' => array(
2528 function ($val) {
2529 return in_array($val, array('auto', 'source', 'dist'), true);
2530 },
2531 function ($val) {
2532 return $val;
2533 },
2534 ),
2535 'store-auths' => array(
2536 function ($val) {
2537 return in_array($val, array('true', 'false', 'prompt'), true);
2538 },
2539 function ($val) {
2540 if ('prompt' === $val) {
2541 return 'prompt';
2542 }
2543
2544 return $val !== 'false' && (bool) $val;
2545 },
2546 ),
2547 'notify-on-install' => array($booleanValidator, $booleanNormalizer),
2548 'vendor-dir' => array('is_string', function ($val) {
2549 return $val;
2550 }),
2551 'bin-dir' => array('is_string', function ($val) {
2552 return $val;
2553 }),
2554 'archive-dir' => array('is_string', function ($val) {
2555 return $val;
2556 }),
2557 'archive-format' => array('is_string', function ($val) {
2558 return $val;
2559 }),
2560 'data-dir' => array('is_string', function ($val) {
2561 return $val;
2562 }),
2563 'cache-dir' => array('is_string', function ($val) {
2564 return $val;
2565 }),
2566 'cache-files-dir' => array('is_string', function ($val) {
2567 return $val;
2568 }),
2569 'cache-repo-dir' => array('is_string', function ($val) {
2570 return $val;
2571 }),
2572 'cache-vcs-dir' => array('is_string', function ($val) {
2573 return $val;
2574 }),
2575 'cache-ttl' => array('is_numeric', 'intval'),
2576 'cache-files-ttl' => array('is_numeric', 'intval'),
2577 'cache-files-maxsize' => array(
2578 function ($val) {
2579 return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0;
2580 },
2581 function ($val) {
2582 return $val;
2583 },
2584 ),
2585 'bin-compat' => array(
2586 function ($val) {
2587 return in_array($val, array('auto', 'full'));
2588 },
2589 function ($val) {
2590 return $val;
2591 },
2592 ),
2593 'discard-changes' => array(
2594 function ($val) {
2595 return in_array($val, array('stash', 'true', 'false', '1', '0'), true);
2596 },
2597 function ($val) {
2598 if ('stash' === $val) {
2599 return 'stash';
2600 }
2601
2602 return $val !== 'false' && (bool) $val;
2603 },
2604 ),
2605 'autoloader-suffix' => array('is_string', function ($val) {
2606 return $val === 'null' ? null : $val;
2607 }),
2608 'sort-packages' => array($booleanValidator, $booleanNormalizer),
2609 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
2610 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
2611 'apcu-autoloader' => array($booleanValidator, $booleanNormalizer),
2612 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
2613 'disable-tls' => array($booleanValidator, $booleanNormalizer),
2614 'secure-http' => array($booleanValidator, $booleanNormalizer),
2615 'cafile' => array(
2616 function ($val) {
2617 return file_exists($val) && is_readable($val);
2618 },
2619 function ($val) {
2620 return $val === 'null' ? null : $val;
2621 },
2622 ),
2623 'capath' => array(
2624 function ($val) {
2625 return is_dir($val) && is_readable($val);
2626 },
2627 function ($val) {
2628 return $val === 'null' ? null : $val;
2629 },
2630 ),
2631 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
2632 'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
2633 );
2634 $multiConfigValues = array(
2635 'github-protocols' => array(
2636 function ($vals) {
2637 if (!is_array($vals)) {
2638 return 'array expected';
2639 }
2640
2641 foreach ($vals as $val) {
2642 if (!in_array($val, array('git', 'https', 'ssh'))) {
2643 return 'valid protocols include: git, https, ssh';
2644 }
2645 }
2646
2647 return true;
2648 },
2649 function ($vals) {
2650 return $vals;
2651 },
2652 ),
2653 'github-domains' => array(
2654 function ($vals) {
2655 if (!is_array($vals)) {
2656 return 'array expected';
2657 }
2658
2659 return true;
2660 },
2661 function ($vals) {
2662 return $vals;
2663 },
2664 ),
2665 'gitlab-domains' => array(
2666 function ($vals) {
2667 if (!is_array($vals)) {
2668 return 'array expected';
2669 }
2670
2671 return true;
2672 },
2673 function ($vals) {
2674 return $vals;
2675 },
2676 ),
2677 );
2678
2679 if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) {
2680 return $this->configSource->removeConfigSetting($settingKey);
2681 }
2682 if (isset($uniqueConfigValues[$settingKey])) {
2683 return $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
2684 }
2685 if (isset($multiConfigValues[$settingKey])) {
2686 return $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
2687 }
2688
2689
2690  $uniqueProps = array(
2691 'name' => array('is_string', function ($val) {
2692 return $val;
2693 }),
2694 'type' => array('is_string', function ($val) {
2695 return $val;
2696 }),
2697 'description' => array('is_string', function ($val) {
2698 return $val;
2699 }),
2700 'homepage' => array('is_string', function ($val) {
2701 return $val;
2702 }),
2703 'version' => array('is_string', function ($val) {
2704 return $val;
2705 }),
2706 'minimum-stability' => array(
2707 function ($val) {
2708 return isset(BasePackage::$stabilities[VersionParser::normalizeStability($val)]);
2709 },
2710 function ($val) {
2711 return VersionParser::normalizeStability($val);
2712 },
2713 ),
2714 'prefer-stable' => array($booleanValidator, $booleanNormalizer),
2715 );
2716 $multiProps = array(
2717 'keywords' => array(
2718 function ($vals) {
2719 if (!is_array($vals)) {
2720 return 'array expected';
2721 }
2722
2723 return true;
2724 },
2725 function ($vals) {
2726 return $vals;
2727 },
2728 ),
2729 'license' => array(
2730 function ($vals) {
2731 if (!is_array($vals)) {
2732 return 'array expected';
2733 }
2734
2735 return true;
2736 },
2737 function ($vals) {
2738 return $vals;
2739 },
2740 ),
2741 );
2742
2743 if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) {
2744 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');
2745 }
2746 if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
2747 return $this->configSource->removeProperty($settingKey);
2748 }
2749 if (isset($uniqueProps[$settingKey])) {
2750 return $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
2751 }
2752 if (isset($multiProps[$settingKey])) {
2753 return $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
2754 }
2755
2756
2757  if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
2758 if ($input->getOption('unset')) {
2759 return $this->configSource->removeRepository($matches[1]);
2760 }
2761
2762 if (2 === count($values)) {
2763 return $this->configSource->addRepository($matches[1], array(
2764 'type' => $values[0],
2765 'url' => $values[1],
2766 ));
2767 }
2768
2769 if (1 === count($values)) {
2770 $value = strtolower($values[0]);
2771 if (true === $booleanValidator($value)) {
2772 if (false === $booleanNormalizer($value)) {
2773 return $this->configSource->addRepository($matches[1], false);
2774 }
2775 } else {
2776 $value = JsonFile::parseJson($values[0]);
2777
2778 return $this->configSource->addRepository($matches[1], $value);
2779 }
2780 }
2781
2782 throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
2783 }
2784
2785
2786  if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) {
2787 if ($input->getOption('unset')) {
2788 return $this->configSource->removeProperty($settingKey);
2789 }
2790
2791 return $this->configSource->addProperty($settingKey, $values[0]);
2792 }
2793
2794
2795  if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
2796 if ($input->getOption('unset')) {
2797 return $this->configSource->removeConfigSetting($settingKey);
2798 }
2799
2800 return $this->configSource->addConfigSetting($settingKey, $values[0]);
2801 }
2802
2803
2804  if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic)\.(.+)/', $settingKey, $matches)) {
2805 if ($input->getOption('unset')) {
2806 $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2807 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2808
2809 return;
2810 }
2811
2812 if ($matches[1] === 'bitbucket-oauth') {
2813 if (2 !== count($values)) {
2814 throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got '.count($values));
2815 }
2816 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2817 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
2818 } elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token'), true)) {
2819 if (1 !== count($values)) {
2820 throw new \RuntimeException('Too many arguments, expected only one token');
2821 }
2822 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2823 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], $values[0]);
2824 } elseif ($matches[1] === 'http-basic') {
2825 if (2 !== count($values)) {
2826 throw new \RuntimeException('Expected two arguments (username, password), got '.count($values));
2827 }
2828 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2829 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
2830 }
2831
2832 return;
2833 }
2834
2835 throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
2836 }
2837
2838 protected function handleSingleValue($key, array $callbacks, array $values, $method)
2839 {
2840 list($validator, $normalizer) = $callbacks;
2841 if (1 !== count($values)) {
2842 throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
2843 }
2844
2845 if (true !== $validation = $validator($values[0])) {
2846 throw new \RuntimeException(sprintf(
2847 '"%s" is an invalid value'.($validation ? ' ('.$validation.')' : ''),
2848 $values[0]
2849 ));
2850 }
2851
2852 return call_user_func(array($this->configSource, $method), $key, $normalizer($values[0]));
2853 }
2854
2855 protected function handleMultiValue($key, array $callbacks, array $values, $method)
2856 {
2857 list($validator, $normalizer) = $callbacks;
2858 if (true !== $validation = $validator($values)) {
2859 throw new \RuntimeException(sprintf(
2860 '%s is an invalid value'.($validation ? ' ('.$validation.')' : ''),
2861 json_encode($values)
2862 ));
2863 }
2864
2865 return call_user_func(array($this->configSource, $method), $key, $normalizer($values));
2866 }
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876 protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
2877 {
2878 $origK = $k;
2879 $io = $this->getIO();
2880 foreach ($contents as $key => $value) {
2881 if ($k === null && !in_array($key, array('config', 'repositories'))) {
2882 continue;
2883 }
2884
2885 $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null;
2886
2887 if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
2888 $k .= preg_replace('{^config\.}', '', $key . '.');
2889 $this->listConfiguration($value, $rawVal, $output, $k);
2890 $k = $origK;
2891
2892 continue;
2893 }
2894
2895 if (is_array($value)) {
2896 $value = array_map(function ($val) {
2897 return is_array($val) ? json_encode($val) : $val;
2898 }, $value);
2899
2900 $value = '['.implode(', ', $value).']';
2901 }
2902
2903 if (is_bool($value)) {
2904 $value = var_export($value, true);
2905 }
2906
2907 if (is_string($rawVal) && $rawVal != $value) {
2908 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>');
2909 } else {
2910 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>');
2911 }
2912 }
2913 }
2914 }
2915 <?php
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927 namespace Composer\Command;
2928
2929 use Composer\Config;
2930 use Composer\Factory;
2931 use Composer\Installer;
2932 use Composer\Installer\ProjectInstaller;
2933 use Composer\Installer\InstallationManager;
2934 use Composer\Installer\SuggestedPackagesReporter;
2935 use Composer\IO\IOInterface;
2936 use Composer\Package\BasePackage;
2937 use Composer\DependencyResolver\Pool;
2938 use Composer\DependencyResolver\Operation\InstallOperation;
2939 use Composer\Package\Version\VersionSelector;
2940 use Composer\Package\AliasPackage;
2941 use Composer\Repository\RepositoryFactory;
2942 use Composer\Repository\CompositeRepository;
2943 use Composer\Repository\PlatformRepository;
2944 use Composer\Repository\InstalledFilesystemRepository;
2945 use Composer\Script\ScriptEvents;
2946 use Composer\Util\Silencer;
2947 use Symfony\Component\Console\Input\InputArgument;
2948 use Symfony\Component\Console\Input\InputInterface;
2949 use Symfony\Component\Console\Input\InputOption;
2950 use Symfony\Component\Console\Output\OutputInterface;
2951 use Symfony\Component\Finder\Finder;
2952 use Composer\Json\JsonFile;
2953 use Composer\Config\JsonConfigSource;
2954 use Composer\Util\Filesystem;
2955 use Composer\Package\Version\VersionParser;
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965 class CreateProjectCommand extends BaseCommand
2966 {
2967
2968
2969
2970 protected $suggestedPackagesReporter;
2971
2972 protected function configure()
2973 {
2974 $this
2975 ->setName('create-project')
2976 ->setDescription('Creates new project from a package into given directory.')
2977 ->setDefinition(array(
2978 new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'),
2979 new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'),
2980 new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
2981 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
2982 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
2983 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
2984 new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
2985 new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
2986 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
2987 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
2988 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
2989 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'),
2990 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
2991 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.'),
2992 new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deletion vcs folder.'),
2993 new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
2994 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
2995 ))
2996 ->setHelp(<<<EOT
2997 The <info>create-project</info> command creates a new project from a given
2998 package into a new directory. If executed without params and in a directory
2999 with a composer.json file it installs the packages for the current project.
3000
3001 You can use this command to bootstrap new projects or setup a clean
3002 version-controlled installation for developers of your project.
3003
3004 <info>php composer.phar create-project vendor/project target-directory [version]</info>
3005
3006 You can also specify the version with the package name using = or : as separator.
3007
3008 <info>php composer.phar create-project vendor/project:version target-directory</info>
3009
3010 To install unstable packages, either specify the version you want, or use the
3011 --stability=dev (where dev can be one of RC, beta, alpha or dev).
3012
3013 To setup a developer workable version you should create the project using the source
3014 controlled code by appending the <info>'--prefer-source'</info> flag.
3015
3016 To install a package from another repository than the default one you
3017 can pass the <info>'--repository=https://myrepository.org'</info> flag.
3018
3019 EOT
3020 )
3021 ;
3022 }
3023
3024 protected function execute(InputInterface $input, OutputInterface $output)
3025 {
3026 $config = Factory::createConfig();
3027 $io = $this->getIO();
3028
3029 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input, true);
3030
3031 if ($input->getOption('dev')) {
3032 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
3033 }
3034 if ($input->getOption('no-custom-installers')) {
3035 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
3036 $input->setOption('no-plugins', true);
3037 }
3038
3039 return $this->installProject(
3040 $io,
3041 $config,
3042 $input,
3043 $input->getArgument('package'),
3044 $input->getArgument('directory'),
3045 $input->getArgument('version'),
3046 $input->getOption('stability'),
3047 $preferSource,
3048 $preferDist,
3049 !$input->getOption('no-dev'),
3050 $input->getOption('repository') ?: $input->getOption('repository-url'),
3051 $input->getOption('no-plugins'),
3052 $input->getOption('no-scripts'),
3053 $input->getOption('keep-vcs'),
3054 $input->getOption('no-progress'),
3055 $input->getOption('no-install'),
3056 $input->getOption('ignore-platform-reqs'),
3057 !$input->getOption('no-secure-http')
3058 );
3059 }
3060
3061 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)
3062 {
3063 $oldCwd = getcwd();
3064
3065
3066  $io->loadConfiguration($config);
3067
3068 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
3069
3070 if ($packageName !== null) {
3071 $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $keepVcs, $noProgress, $ignorePlatformReqs, $secureHttp);
3072 } else {
3073 $installedFromVcs = false;
3074 }
3075
3076 $composer = Factory::create($io, null, $disablePlugins);
3077 $composer->getDownloadManager()->setOutputProgress(!$noProgress);
3078
3079 $fs = new Filesystem();
3080
3081 if ($noScripts === false) {
3082
3083  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
3084 }
3085
3086 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($composer->getConfig(), $input);
3087
3088
3089  if ($noInstall === false) {
3090 $installer = Installer::create($io, $composer);
3091 $installer->setPreferSource($preferSource)
3092 ->setPreferDist($preferDist)
3093 ->setDevMode($installDevPackages)
3094 ->setRunScripts(!$noScripts)
3095 ->setIgnorePlatformRequirements($ignorePlatformReqs)
3096 ->setSuggestedPackagesReporter($this->suggestedPackagesReporter);
3097
3098 if ($disablePlugins) {
3099 $installer->disablePlugins();
3100 }
3101
3102 $status = $installer->run();
3103 if (0 !== $status) {
3104 return $status;
3105 }
3106 }
3107
3108 $hasVcs = $installedFromVcs;
3109 if (!$keepVcs && $installedFromVcs
3110 && (
3111 !$io->isInteractive()
3112 || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true)
3113 )
3114 ) {
3115 $finder = new Finder();
3116 $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
3117 foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_') as $vcsName) {
3118 $finder->name($vcsName);
3119 }
3120
3121 try {
3122 $dirs = iterator_to_array($finder);
3123 unset($finder);
3124 foreach ($dirs as $dir) {
3125 if (!$fs->removeDirectory($dir)) {
3126 throw new \RuntimeException('Could not remove '.$dir);
3127 }
3128 }
3129 } catch (\Exception $e) {
3130 $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
3131 }
3132
3133 $hasVcs = false;
3134 }
3135
3136
3137  if (!$hasVcs) {
3138 $package = $composer->getPackage();
3139 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3140 foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
3141 foreach ($package->{'get'.$meta['method']}() as $link) {
3142 if ($link->getPrettyConstraint() === 'self.version') {
3143 $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
3144 }
3145 }
3146 }
3147 }
3148
3149 if ($noScripts === false) {
3150
3151  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
3152 }
3153
3154 chdir($oldCwd);
3155 $vendorComposerDir = $composer->getConfig()->get('vendor-dir').'/composer';
3156 if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
3157 Silencer::call('rmdir', $vendorComposerDir);
3158 $vendorDir = $composer->getConfig()->get('vendor-dir');
3159 if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
3160 Silencer::call('rmdir', $vendorDir);
3161 }
3162 }
3163
3164 return 0;
3165 }
3166
3167 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)
3168 {
3169 if (!$secureHttp) {
3170 $config->merge(array('config' => array('secure-http' => false)));
3171 }
3172
3173 if (null === $repository) {
3174 $sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config));
3175 } else {
3176 $sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true);
3177 }
3178
3179 $parser = new VersionParser();
3180 $requirements = $parser->parseNameVersionPairs(array($packageName));
3181 $name = strtolower($requirements[0]['name']);
3182 if (!$packageVersion && isset($requirements[0]['version'])) {
3183 $packageVersion = $requirements[0]['version'];
3184 }
3185
3186 if (null === $stability) {
3187 if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
3188 $stability = $match[1];
3189 } else {
3190 $stability = VersionParser::parseStability($packageVersion);
3191 }
3192 }
3193
3194 $stability = VersionParser::normalizeStability($stability);
3195
3196 if (!isset(BasePackage::$stabilities[$stability])) {
3197 throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
3198 }
3199
3200 $pool = new Pool($stability);
3201 $pool->addRepository($sourceRepo);
3202
3203 $phpVersion = null;
3204 $prettyPhpVersion = null;
3205 if (!$ignorePlatformReqs) {
3206 $platformOverrides = $config->get('platform') ?: array();
3207
3208  $platform = new PlatformRepository(array(), $platformOverrides);
3209 $phpPackage = $platform->findPackage('php', '*');
3210 $phpVersion = $phpPackage->getVersion();
3211 $prettyPhpVersion = $phpPackage->getPrettyVersion();
3212 }
3213
3214
3215  $versionSelector = new VersionSelector($pool);
3216 $package = $versionSelector->findBestCandidate($name, $packageVersion, $phpVersion, $stability);
3217
3218 if (!$package) {
3219 $errorMessage = "Could not find package $name with " . ($packageVersion ? "version $packageVersion" : "stability $stability");
3220 if ($phpVersion && $versionSelector->findBestCandidate($name, $packageVersion, null, $stability)) {
3221 throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version '.$prettyPhpVersion.'.');
3222 }
3223
3224 throw new \InvalidArgumentException($errorMessage .'.');
3225 }
3226
3227 if (null === $directory) {
3228 $parts = explode("/", $name, 2);
3229 $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
3230 }
3231
3232
3233  if (function_exists('pcntl_signal')) {
3234 declare(ticks=100);
3235 pcntl_signal(SIGINT, function () use ($directory) {
3236 $fs = new Filesystem();
3237 $fs->removeDirectory($directory);
3238 exit(130);
3239 });
3240 }
3241
3242 $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')</info>');
3243
3244 if ($disablePlugins) {
3245 $io->writeError('<info>Plugins have been disabled.</info>');
3246 }
3247
3248 if ($package instanceof AliasPackage) {
3249 $package = $package->getAliasOf();
3250 }
3251
3252 if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) {
3253 $package->setSourceReference(substr($package->getPrettyVersion(), 4));
3254 }
3255
3256 $dm = $this->createDownloadManager($io, $config);
3257 $dm->setPreferSource($preferSource)
3258 ->setPreferDist($preferDist)
3259 ->setOutputProgress(!$noProgress);
3260
3261 $projectInstaller = new ProjectInstaller($directory, $dm);
3262 $im = $this->createInstallationManager();
3263 $im->addInstaller($projectInstaller);
3264 $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
3265 $im->notifyInstalls($io);
3266
3267
3268  $this->suggestedPackagesReporter->addSuggestionsFromPackage($package);
3269
3270 $installedFromVcs = 'source' === $package->getInstallationSource();
3271
3272 $io->writeError('<info>Created project in ' . $directory . '</info>');
3273 chdir($directory);
3274
3275 $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
3276 putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
3277
3278 return $installedFromVcs;
3279 }
3280
3281 protected function createDownloadManager(IOInterface $io, Config $config)
3282 {
3283 $factory = new Factory();
3284
3285 return $factory->createDownloadManager($io, $config);
3286 }
3287
3288 protected function createInstallationManager()
3289 {
3290 return new InstallationManager();
3291 }
3292 }
3293 <?php
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305 namespace Composer\Command;
3306
3307 use Symfony\Component\Console\Input\InputInterface;
3308 use Symfony\Component\Console\Output\OutputInterface;
3309
3310
3311
3312
3313 class DependsCommand extends BaseDependencyCommand
3314 {
3315
3316
3317
3318 protected function configure()
3319 {
3320 parent::configure();
3321
3322 $this
3323 ->setName('depends')
3324 ->setAliases(array('why'))
3325 ->setDescription('Shows which packages cause the given package to be installed.')
3326 ->setHelp(<<<EOT
3327 Displays detailed information about where a package is referenced.
3328
3329 <info>php composer.phar depends composer/composer</info>
3330
3331 EOT
3332 )
3333 ;
3334 }
3335
3336
3337
3338
3339
3340
3341
3342
3343 protected function execute(InputInterface $input, OutputInterface $output)
3344 {
3345 return parent::doExecute($input, $output, false);
3346 }
3347 }
3348 <?php
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360 namespace Composer\Command;
3361
3362 use Composer\Composer;
3363 use Composer\Factory;
3364 use Composer\Config;
3365 use Composer\Downloader\TransportException;
3366 use Composer\Plugin\CommandEvent;
3367 use Composer\Plugin\PluginEvents;
3368 use Composer\Util\ConfigValidator;
3369 use Composer\Util\IniHelper;
3370 use Composer\Util\ProcessExecutor;
3371 use Composer\Util\RemoteFilesystem;
3372 use Composer\Util\StreamContextFactory;
3373 use Composer\SelfUpdate\Keys;
3374 use Composer\SelfUpdate\Versions;
3375 use Composer\IO\NullIO;
3376 use Symfony\Component\Console\Input\InputInterface;
3377 use Symfony\Component\Console\Output\OutputInterface;
3378
3379
3380
3381
3382 class DiagnoseCommand extends BaseCommand
3383 {
3384
3385 protected $rfs;
3386
3387
3388 protected $process;
3389
3390
3391 protected $exitCode = 0;
3392
3393 protected function configure()
3394 {
3395 $this
3396 ->setName('diagnose')
3397 ->setDescription('Diagnoses the system to identify common errors.')
3398 ->setHelp(<<<EOT
3399 The <info>diagnose</info> command checks common errors to help debugging problems.
3400
3401 The process exit code will be 1 in case of warnings and 2 for errors.
3402
3403 EOT
3404 )
3405 ;
3406 }
3407
3408
3409
3410
3411 protected function execute(InputInterface $input, OutputInterface $output)
3412 {
3413 $composer = $this->getComposer(false);
3414 $io = $this->getIO();
3415
3416 if ($composer) {
3417 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
3418 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
3419
3420 $io->write('Checking composer.json: ', false);
3421 $this->outputResult($this->checkComposerSchema());
3422 }
3423
3424 if ($composer) {
3425 $config = $composer->getConfig();
3426 } else {
3427 $config = Factory::createConfig();
3428 }
3429
3430 $config->merge(array('config' => array('secure-http' => false)));
3431 $config->prohibitUrlByConfig('http://packagist.org', new NullIO);
3432
3433 $this->rfs = Factory::createRemoteFilesystem($io, $config);
3434 $this->process = new ProcessExecutor($io);
3435
3436 $io->write('Checking platform settings: ', false);
3437 $this->outputResult($this->checkPlatform());
3438
3439 $io->write('Checking git settings: ', false);
3440 $this->outputResult($this->checkGit());
3441
3442 $io->write('Checking http connectivity to packagist: ', false);
3443 $this->outputResult($this->checkHttp('http', $config));
3444
3445 $io->write('Checking https connectivity to packagist: ', false);
3446 $this->outputResult($this->checkHttp('https', $config));
3447
3448 $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
3449 if (!empty($opts['http']['proxy'])) {
3450 $io->write('Checking HTTP proxy: ', false);
3451 $this->outputResult($this->checkHttpProxy());
3452 $io->write('Checking HTTP proxy support for request_fulluri: ', false);
3453 $this->outputResult($this->checkHttpProxyFullUriRequestParam());
3454 $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
3455 $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
3456 }
3457
3458 if ($oauth = $config->get('github-oauth')) {
3459 foreach ($oauth as $domain => $token) {
3460 $io->write('Checking '.$domain.' oauth access: ', false);
3461 $this->outputResult($this->checkGithubOauth($domain, $token));
3462 }
3463 } else {
3464 $io->write('Checking github.com rate limit: ', false);
3465 try {
3466 $rate = $this->getGithubRateLimit('github.com');
3467 $this->outputResult(true);
3468 if (10 > $rate['remaining']) {
3469 $io->write('<warning>WARNING</warning>');
3470 $io->write(sprintf(
3471 '<comment>Github has a rate limit on their API. '
3472 . 'You currently have <options=bold>%u</options=bold> '
3473 . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
3474 . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
3475 . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>',
3476 $rate['remaining'],
3477 $rate['limit']
3478 ));
3479 }
3480 } catch (\Exception $e) {
3481 if ($e instanceof TransportException && $e->getCode() === 401) {
3482 $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
3483 } else {
3484 $this->outputResult($e);
3485 }
3486 }
3487 }
3488
3489 $io->write('Checking disk free space: ', false);
3490 $this->outputResult($this->checkDiskSpace($config));
3491
3492 if ('phar:' === substr(__FILE__, 0, 5)) {
3493 $io->write('Checking pubkeys: ', false);
3494 $this->outputResult($this->checkPubKeys($config));
3495
3496 $io->write('Checking composer version: ', false);
3497 $this->outputResult($this->checkVersion($config));
3498 }
3499
3500 return $this->exitCode;
3501 }
3502
3503 private function checkComposerSchema()
3504 {
3505 $validator = new ConfigValidator($this->getIO());
3506 list($errors, , $warnings) = $validator->validate(Factory::getComposerFile());
3507
3508 if ($errors || $warnings) {
3509 $messages = array(
3510 'error' => $errors,
3511 'warning' => $warnings,
3512 );
3513
3514 $output = '';
3515 foreach ($messages as $style => $msgs) {
3516 foreach ($msgs as $msg) {
3517 $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . PHP_EOL;
3518 }
3519 }
3520
3521 return rtrim($output);
3522 }
3523
3524 return true;
3525 }
3526
3527 private function checkGit()
3528 {
3529 $this->process->execute('git config color.ui', $output);
3530 if (strtolower(trim($output)) === 'always') {
3531 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>';
3532 }
3533
3534 return true;
3535 }
3536
3537 private function checkHttp($proto, Config $config)
3538 {
3539 $disableTls = false;
3540 $result = array();
3541 if ($proto === 'https' && $config->get('disable-tls') === true) {
3542 $disableTls = true;
3543 $result[] = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
3544 }
3545 if ($proto === 'https' && !extension_loaded('openssl') && !$disableTls) {
3546 $result[] = '<error>Composer is configured to use SSL/TLS protection but the openssl extension is not available.</error>';
3547 }
3548
3549 try {
3550 $this->rfs->getContents('packagist.org', $proto . '://packagist.org/packages.json', false);
3551 } catch (TransportException $e) {
3552 if (false !== strpos($e->getMessage(), 'cafile')) {
3553 $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
3554 $result[] = '<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>';
3555 $result[] = '<error>You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option.</error>';
3556 } else {
3557 array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage());
3558 }
3559 }
3560
3561 if (count($result) > 0) {
3562 return $result;
3563 }
3564
3565 return true;
3566 }
3567
3568 private function checkHttpProxy()
3569 {
3570 $protocol = extension_loaded('openssl') ? 'https' : 'http';
3571 try {
3572 $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://packagist.org/packages.json', false), true);
3573 $hash = reset($json['provider-includes']);
3574 $hash = $hash['sha256'];
3575 $path = str_replace('%hash%', $hash, key($json['provider-includes']));
3576 $provider = $this->rfs->getContents('packagist.org', $protocol . '://packagist.org/'.$path, false);
3577
3578 if (hash('sha256', $provider) !== $hash) {
3579 return 'It seems that your proxy is modifying http traffic on the fly';
3580 }
3581 } catch (\Exception $e) {
3582 return $e;
3583 }
3584
3585 return true;
3586 }
3587
3588
3589
3590
3591
3592
3593
3594
3595 private function checkHttpProxyFullUriRequestParam()
3596 {
3597 $url = 'http://packagist.org/packages.json';
3598 try {
3599 $this->rfs->getContents('packagist.org', $url, false);
3600 } catch (TransportException $e) {
3601 try {
3602 $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
3603 } catch (TransportException $e) {
3604 return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
3605 }
3606
3607 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"';
3608 }
3609
3610 return true;
3611 }
3612
3613
3614
3615
3616
3617
3618
3619
3620 private function checkHttpsProxyFullUriRequestParam()
3621 {
3622 if (!extension_loaded('openssl')) {
3623 return 'You need the openssl extension installed for this check';
3624 }
3625
3626 $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
3627 try {
3628 $this->rfs->getContents('github.com', $url, false);
3629 } catch (TransportException $e) {
3630 try {
3631 $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
3632 } catch (TransportException $e) {
3633 return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
3634 }
3635
3636 return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
3637 }
3638
3639 return true;
3640 }
3641
3642 private function checkGithubOauth($domain, $token)
3643 {
3644 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3645 try {
3646 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
3647
3648 return $this->rfs->getContents($domain, $url, false, array(
3649 'retry-auth-failure' => false,
3650 )) ? true : 'Unexpected error';
3651 } catch (\Exception $e) {
3652 if ($e instanceof TransportException && $e->getCode() === 401) {
3653 return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
3654 }
3655
3656 return $e;
3657 }
3658 }
3659
3660
3661
3662
3663
3664
3665
3666 private function getGithubRateLimit($domain, $token = null)
3667 {
3668 if ($token) {
3669 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3670 }
3671
3672 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
3673 $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
3674 $data = json_decode($json, true);
3675
3676 return $data['resources']['core'];
3677 }
3678
3679 private function checkDiskSpace($config)
3680 {
3681 $minSpaceFree = 1024 * 1024;
3682 if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
3683 || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
3684 ) {
3685 return '<error>The disk hosting '.$dir.' is full</error>';
3686 }
3687
3688 return true;
3689 }
3690
3691 private function checkPubKeys($config)
3692 {
3693 $home = $config->get('home');
3694 $errors = array();
3695 $io = $this->getIO();
3696
3697 if (file_exists($home.'/keys.tags.pub') && file_exists($home.'/keys.dev.pub')) {
3698 $io->write('');
3699 }
3700
3701 if (file_exists($home.'/keys.tags.pub')) {
3702 $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.tags.pub'));
3703 } else {
3704 $errors[] = '<error>Missing pubkey for tags verification</error>';
3705 }
3706
3707 if (file_exists($home.'/keys.dev.pub')) {
3708 $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.dev.pub'));
3709 } else {
3710 $errors[] = '<error>Missing pubkey for dev verification</error>';
3711 }
3712
3713 if ($errors) {
3714 $errors[] = '<error>Run composer self-update --update-keys to set them up</error>';
3715 }
3716
3717 return $errors ?: true;
3718 }
3719
3720 private function checkVersion($config)
3721 {
3722 $versionsUtil = new Versions($config, $this->rfs);
3723 $latest = $versionsUtil->getLatest();
3724
3725 if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
3726 return '<comment>You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')</comment>';
3727 }
3728
3729 return true;
3730 }
3731
3732
3733
3734
3735 private function outputResult($result)
3736 {
3737 $io = $this->getIO();
3738 if (true === $result) {
3739 $io->write('<info>OK</info>');
3740
3741 return;
3742 }
3743
3744 $hadError = false;
3745 if ($result instanceof \Exception) {
3746 $result = '<error>['.get_class($result).'] '.$result->getMessage().'</error>';
3747 }
3748
3749 if (!$result) {
3750
3751  $hadError = true;
3752 } else {
3753 if (!is_array($result)) {
3754 $result = array($result);
3755 }
3756 foreach ($result as $message) {
3757 if (false !== strpos($message, '<error>')) {
3758 $hadError = true;
3759 }
3760 }
3761 }
3762
3763 if ($hadError) {
3764 $io->write('<error>FAIL</error>');
3765 $this->exitCode = 2;
3766 } else {
3767 $io->write('<warning>WARNING</warning>');
3768 $this->exitCode = 1;
3769 }
3770
3771 if ($result) {
3772 foreach ($result as $message) {
3773 $io->write($message);
3774 }
3775 }
3776 }
3777
3778 private function checkPlatform()
3779 {
3780 $output = '';
3781 $out = function ($msg, $style) use (&$output) {
3782 $output .= '<'.$style.'>'.$msg.'</'.$style.'>'.PHP_EOL;
3783 };
3784
3785
3786  $errors = array();
3787 $warnings = array();
3788 $displayIniMessage = false;
3789
3790 $iniMessage = PHP_EOL.PHP_EOL.IniHelper::getMessage();
3791 $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.';
3792
3793 if (!function_exists('json_decode')) {
3794 $errors['json'] = true;
3795 }
3796
3797 if (!extension_loaded('Phar')) {
3798 $errors['phar'] = true;
3799 }
3800
3801 if (!extension_loaded('filter')) {
3802 $errors['filter'] = true;
3803 }
3804
3805 if (!extension_loaded('hash')) {
3806 $errors['hash'] = true;
3807 }
3808
3809 if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
3810 $errors['iconv_mbstring'] = true;
3811 }
3812
3813 if (!ini_get('allow_url_fopen')) {
3814 $errors['allow_url_fopen'] = true;
3815 }
3816
3817 if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
3818 $errors['ioncube'] = ioncube_loader_version();
3819 }
3820
3821 if (PHP_VERSION_ID < 50302) {
3822 $errors['php'] = PHP_VERSION;
3823 }
3824
3825 if (!isset($errors['php']) && PHP_VERSION_ID < 50304) {
3826 $warnings['php'] = PHP_VERSION;
3827 }
3828
3829 if (!extension_loaded('openssl')) {
3830 $errors['openssl'] = true;
3831 }
3832
3833 if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) {
3834 $warnings['openssl_version'] = true;
3835 }
3836
3837 if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) {
3838 $warnings['apc_cli'] = true;
3839 }
3840
3841 if (!extension_loaded('zlib')) {
3842 $warnings['zlib'] = true;
3843 }
3844
3845 ob_start();
3846 phpinfo(INFO_GENERAL);
3847 $phpinfo = ob_get_clean();
3848 if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
3849 $configure = $match[1];
3850
3851 if (false !== strpos($configure, '--enable-sigchild')) {
3852 $warnings['sigchild'] = true;
3853 }
3854
3855 if (false !== strpos($configure, '--with-curlwrappers')) {
3856 $warnings['curlwrappers'] = true;
3857 }
3858 }
3859
3860 if (ini_get('xdebug.profiler_enabled')) {
3861 $warnings['xdebug_profile'] = true;
3862 } elseif (extension_loaded('xdebug')) {
3863 $warnings['xdebug_loaded'] = true;
3864 }
3865
3866 if (!empty($errors)) {
3867 foreach ($errors as $error => $current) {
3868 switch ($error) {
3869 case 'json':
3870 $text = PHP_EOL."The json extension is missing.".PHP_EOL;
3871 $text .= "Install it or recompile php without --disable-json";
3872 break;
3873
3874 case 'phar':
3875 $text = PHP_EOL."The phar extension is missing.".PHP_EOL;
3876 $text .= "Install it or recompile php without --disable-phar";
3877 break;
3878
3879 case 'filter':
3880 $text = PHP_EOL."The filter extension is missing.".PHP_EOL;
3881 $text .= "Install it or recompile php without --disable-filter";
3882 break;
3883
3884 case 'hash':
3885 $text = PHP_EOL."The hash extension is missing.".PHP_EOL;
3886 $text .= "Install it or recompile php without --disable-hash";
3887 break;
3888
3889 case 'iconv_mbstring':
3890 $text = PHP_EOL."The iconv OR mbstring extension is required and both are missing.".PHP_EOL;
3891 $text .= "Install either of them or recompile php without --disable-iconv";
3892 break;
3893
3894 case 'unicode':
3895 $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
3896 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
3897 $text .= "    detect_unicode = Off";
3898 $displayIniMessage = true;
3899 break;
3900
3901 case 'suhosin':
3902 $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
3903 $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;
3904 $text .= "    suhosin.executor.include.whitelist = phar ".$current;
3905 $displayIniMessage = true;
3906 break;
3907
3908 case 'php':
3909 $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
3910 break;
3911
3912 case 'allow_url_fopen':
3913 $text = PHP_EOL."The allow_url_fopen setting is incorrect.".PHP_EOL;
3914 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
3915 $text .= "    allow_url_fopen = On";
3916 $displayIniMessage = true;
3917 break;
3918
3919 case 'ioncube':
3920 $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
3921 $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;
3922 $text .= "    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
3923 $displayIniMessage = true;
3924 break;
3925
3926 case 'openssl':
3927 $text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
3928 $text .= "If possible you should enable it or recompile php with --with-openssl";
3929 break;
3930 }
3931 $out($text, 'error');
3932 }
3933
3934 $output .= PHP_EOL;
3935 }
3936
3937 if (!empty($warnings)) {
3938 foreach ($warnings as $warning => $current) {
3939 switch ($warning) {
3940 case 'apc_cli':
3941 $text = "The apc.enable_cli setting is incorrect.".PHP_EOL;
3942 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
3943 $text .= "  apc.enable_cli = Off";
3944 $displayIniMessage = true;
3945 break;
3946
3947 case 'zlib':
3948 $text = 'The zlib extension is not loaded, this can slow down Composer a lot.'.PHP_EOL;
3949 $text .= 'If possible, enable it or recompile php with --with-zlib'.PHP_EOL;
3950 $displayIniMessage = true;
3951 break;
3952
3953 case 'sigchild':
3954 $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms.".PHP_EOL;
3955 $text .= "Recompile it without this flag if possible, see also:".PHP_EOL;
3956 $text .= "  https://bugs.php.net/bug.php?id=22999";
3957 break;
3958
3959 case 'curlwrappers':
3960 $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.".PHP_EOL;
3961 $text .= " Recompile it without this flag if possible";
3962 break;
3963
3964 case 'php':
3965 $text = "Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL;
3966 $text .= " Composer works with 5.3.2+ for most people, but there might be edge case issues.";
3967 break;
3968
3969 case 'openssl_version':
3970
3971  $opensslVersion = strstr(trim(strstr(OPENSSL_VERSION_TEXT, ' ')), ' ', true);
3972 $opensslVersion = $opensslVersion ?: OPENSSL_VERSION_TEXT;
3973
3974 $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1.".PHP_EOL;
3975 $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above.";
3976 break;
3977
3978 case 'xdebug_loaded':
3979 $text = "The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL;
3980 $text .= " Disabling it when using Composer is recommended.";
3981 break;
3982
3983 case 'xdebug_profile':
3984 $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL;
3985 $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL;
3986 $text .= "  xdebug.profiler_enabled = 0";
3987 $displayIniMessage = true;
3988 break;
3989 }
3990 $out($text, 'comment');
3991 }
3992 }
3993
3994 if ($displayIniMessage) {
3995 $out($iniMessage, 'comment');
3996 }
3997
3998 return !$warnings && !$errors ? true : $output;
3999 }
4000 }
4001 <?php
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013 namespace Composer\Command;
4014
4015 use Composer\Plugin\CommandEvent;
4016 use Composer\Plugin\PluginEvents;
4017 use Symfony\Component\Console\Input\InputInterface;
4018 use Symfony\Component\Console\Input\InputOption;
4019 use Symfony\Component\Console\Output\OutputInterface;
4020
4021
4022
4023
4024 class DumpAutoloadCommand extends BaseCommand
4025 {
4026 protected function configure()
4027 {
4028 $this
4029 ->setName('dump-autoload')
4030 ->setAliases(array('dumpautoload'))
4031 ->setDescription('Dumps the autoloader.')
4032 ->setDefinition(array(
4033 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
4034 new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
4035 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
4036 new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
4037 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
4038 ))
4039 ->setHelp(<<<EOT
4040 <info>php composer.phar dump-autoload</info>
4041 EOT
4042 )
4043 ;
4044 }
4045
4046 protected function execute(InputInterface $input, OutputInterface $output)
4047 {
4048 $composer = $this->getComposer();
4049
4050 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
4051 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
4052
4053 $installationManager = $composer->getInstallationManager();
4054 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
4055 $package = $composer->getPackage();
4056 $config = $composer->getConfig();
4057
4058 $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
4059 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
4060 $apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
4061
4062 if ($optimize || $authoritative) {
4063 $this->getIO()->writeError('<info>Generating optimized autoload files</info>');
4064 } else {
4065 $this->getIO()->writeError('<info>Generating autoload files</info>');
4066 }
4067
4068 $generator = $composer->getAutoloadGenerator();
4069 $generator->setDevMode(!$input->getOption('no-dev'));
4070 $generator->setClassMapAuthoritative($authoritative);
4071 $generator->setApcu($apcu);
4072 $generator->setRunScripts(!$input->getOption('no-scripts'));
4073 $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
4074 }
4075 }
4076 <?php
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088 namespace Composer\Command;
4089
4090 use Symfony\Component\Console\Input\InputInterface;
4091 use Symfony\Component\Console\Input\InputOption;
4092 use Symfony\Component\Console\Output\OutputInterface;
4093 use Symfony\Component\Console\Input\InputArgument;
4094
4095
4096
4097
4098 class ExecCommand extends BaseCommand
4099 {
4100 protected function configure()
4101 {
4102 $this
4103 ->setName('exec')
4104 ->setDescription('Executes a vendored binary/script.')
4105 ->setDefinition(array(
4106 new InputOption('list', 'l', InputOption::VALUE_NONE),
4107 new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit'),
4108 new InputArgument(
4109 'args',
4110 InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
4111 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
4112 ),
4113 ))
4114 ;
4115 }
4116
4117 protected function execute(InputInterface $input, OutputInterface $output)
4118 {
4119 $composer = $this->getComposer();
4120 $binDir = $composer->getConfig()->get('bin-dir');
4121 if ($input->getOption('list') || !$input->getArgument('binary')) {
4122 $bins = glob($binDir . '/*');
4123 $bins = array_merge($bins, array_map(function ($e) {
4124 return "$e (local)";
4125 }, $composer->getPackage()->getBinaries()));
4126
4127 if (!$bins) {
4128 throw new \RuntimeException("No binaries found in composer.json or in bin-dir ($binDir)");
4129 }
4130
4131 $this->getIO()->write(<<<EOT
4132 <comment>Available binaries:</comment>
4133 EOT
4134 );
4135
4136 foreach ($bins as $bin) {
4137
4138  if (isset($previousBin) && $bin === $previousBin.'.bat') {
4139 continue;
4140 }
4141
4142 $previousBin = $bin;
4143 $bin = basename($bin);
4144 $this->getIO()->write(<<<EOT
4145 <info>- $bin</info>
4146 EOT
4147 );
4148 }
4149
4150 return 0;
4151 }
4152
4153 $binary = $input->getArgument('binary');
4154
4155 $dispatcher = $composer->getEventDispatcher();
4156 $dispatcher->addListener('__exec_command', $binary);
4157 if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
4158 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
4159 }
4160
4161 return $dispatcher->dispatchScript('__exec_command', true, $input->getArgument('args'));
4162 }
4163 }
4164 <?php
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176 namespace Composer\Command;
4177
4178 use Composer\Factory;
4179 use Symfony\Component\Console\Input\InputInterface;
4180 use Symfony\Component\Console\Input\InputArgument;
4181 use Symfony\Component\Console\Input\StringInput;
4182 use Symfony\Component\Console\Output\OutputInterface;
4183
4184
4185
4186
4187 class GlobalCommand extends BaseCommand
4188 {
4189 protected function configure()
4190 {
4191 $this
4192 ->setName('global')
4193 ->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME).')
4194 ->setDefinition(array(
4195 new InputArgument('command-name', InputArgument::REQUIRED, ''),
4196 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
4197 ))
4198 ->setHelp(<<<EOT
4199 Use this command as a wrapper to run other Composer commands
4200 within the global context of COMPOSER_HOME.
4201
4202 You can use this to install CLI utilities globally, all you need
4203 is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.
4204
4205 COMPOSER_HOME is c:\Users\<user>\AppData\Roaming\Composer on Windows
4206 and /home/<user>/.composer on unix systems.
4207
4208 If your system uses freedesktop.org standards, then it will first check
4209 XDG_CONFIG_HOME or default to /home/<user>/.config/composer
4210
4211 Note: This path may vary depending on customizations to bin-dir in
4212 composer.json or the environmental variable COMPOSER_BIN_DIR.
4213
4214 EOT
4215 )
4216 ;
4217 }
4218
4219 public function run(InputInterface $input, OutputInterface $output)
4220 {
4221
4222  $tokens = preg_split('{\s+}', $input->__toString());
4223 $args = array();
4224 foreach ($tokens as $token) {
4225 if ($token && $token[0] !== '-') {
4226 $args[] = $token;
4227 if (count($args) >= 2) {
4228 break;
4229 }
4230 }
4231 }
4232
4233
4234  if (count($args) < 2) {
4235 return parent::run($input, $output);
4236 }
4237
4238
4239  $config = Factory::createConfig();
4240 chdir($config->get('home'));
4241 $this->getIO()->writeError('<info>Changed current directory to '.$config->get('home').'</info>');
4242
4243
4244  $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
4245 $this->getApplication()->resetComposer();
4246
4247 return $this->getApplication()->run($input, $output);
4248 }
4249
4250
4251
4252
4253 public function isProxyCommand()
4254 {
4255 return true;
4256 }
4257 }
4258 <?php
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270 namespace Composer\Command;
4271
4272 use Composer\Package\CompletePackageInterface;
4273 use Composer\Repository\RepositoryInterface;
4274 use Composer\Repository\ArrayRepository;
4275 use Composer\Repository\RepositoryFactory;
4276 use Composer\Util\Platform;
4277 use Composer\Util\ProcessExecutor;
4278 use Symfony\Component\Console\Input\InputArgument;
4279 use Symfony\Component\Console\Input\InputOption;
4280 use Symfony\Component\Console\Input\InputInterface;
4281 use Symfony\Component\Console\Output\OutputInterface;
4282
4283
4284
4285
4286 class HomeCommand extends BaseCommand
4287 {
4288
4289
4290
4291 protected function configure()
4292 {
4293 $this
4294 ->setName('browse')
4295 ->setAliases(array('home'))
4296 ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
4297 ->setDefinition(array(
4298 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Package(s) to browse to.'),
4299 new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
4300 new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
4301 ))
4302 ->setHelp(<<<EOT
4303 The home command opens or shows a package's repository URL or
4304 homepage in your default browser.
4305
4306 To open the homepage by default, use -H or --homepage.
4307 To show instead of open the repository or homepage URL, use -s or --show.
4308 EOT
4309 );
4310 }
4311
4312
4313
4314
4315 protected function execute(InputInterface $input, OutputInterface $output)
4316 {
4317 $repos = $this->initializeRepos();
4318 $io = $this->getIO();
4319 $return = 0;
4320
4321 foreach ($input->getArgument('packages') as $packageName) {
4322 $handled = false;
4323 $packageExists = false;
4324 foreach ($repos as $repo) {
4325 foreach ($repo->findPackages($packageName) as $package) {
4326 $packageExists = true;
4327 if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
4328 $handled = true;
4329 break 2;
4330 }
4331 }
4332 }
4333
4334 if (!$packageExists) {
4335 $return = 1;
4336 $io->writeError('<warning>Package '.$packageName.' not found</warning>');
4337 }
4338
4339 if (!$handled) {
4340 $return = 1;
4341 $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
4342 }
4343 }
4344
4345 return $return;
4346 }
4347
4348 private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
4349 {
4350 $support = $package->getSupport();
4351 $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
4352 if (!$url || $showHomepage) {
4353 $url = $package->getHomepage();
4354 }
4355
4356 if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
4357 return false;
4358 }
4359
4360 if ($showOnly) {
4361 $this->getIO()->write(sprintf('<info>%s</info>', $url));
4362 } else {
4363 $this->openBrowser($url);
4364 }
4365
4366 return true;
4367 }
4368
4369
4370
4371
4372
4373
4374 private function openBrowser($url)
4375 {
4376 $url = ProcessExecutor::escape($url);
4377
4378 $process = new ProcessExecutor($this->getIO());
4379 if (Platform::isWindows()) {
4380 return $process->execute('start "web" explorer "' . $url . '"', $output);
4381 }
4382
4383 $linux = $process->execute('which xdg-open', $output);
4384 $osx = $process->execute('which open', $output);
4385
4386 if (0 === $linux) {
4387 $process->execute('xdg-open ' . $url, $output);
4388 } elseif (0 === $osx) {
4389 $process->execute('open ' . $url, $output);
4390 } else {
4391 $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
4392 }
4393 }
4394
4395
4396
4397
4398
4399
4400
4401
4402 private function initializeRepos()
4403 {
4404 $composer = $this->getComposer(false);
4405
4406 if ($composer) {
4407 return array_merge(
4408 array(new ArrayRepository(array($composer->getPackage()))), 
4409  array($composer->getRepositoryManager()->getLocalRepository()), 
4410  $composer->getRepositoryManager()->getRepositories() 
4411  );
4412 }
4413
4414 return RepositoryFactory::defaultRepos($this->getIO());
4415 }
4416 }
4417 <?php
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429 namespace Composer\Command;
4430
4431 use Composer\DependencyResolver\Pool;
4432 use Composer\Json\JsonFile;
4433 use Composer\Factory;
4434 use Composer\Repository\RepositoryFactory;
4435 use Composer\Package\BasePackage;
4436 use Composer\Package\Version\VersionParser;
4437 use Composer\Package\Version\VersionSelector;
4438 use Composer\Repository\CompositeRepository;
4439 use Composer\Repository\PlatformRepository;
4440 use Composer\Util\ProcessExecutor;
4441 use Symfony\Component\Console\Input\InputInterface;
4442 use Symfony\Component\Console\Input\InputOption;
4443 use Symfony\Component\Console\Output\OutputInterface;
4444 use Symfony\Component\Process\Process;
4445 use Symfony\Component\Process\ExecutableFinder;
4446
4447
4448
4449
4450
4451 class InitCommand extends BaseCommand
4452 {
4453
4454 protected $repos;
4455
4456
4457 private $gitConfig;
4458
4459
4460 private $pool;
4461
4462
4463
4464
4465 protected function configure()
4466 {
4467 $this
4468 ->setName('init')
4469 ->setDescription('Creates a basic composer.json file in current directory.')
4470 ->setDefinition(array(
4471 new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
4472 new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
4473 new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
4474
4475  new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of package (e.g. library, project, metapackage, composer-plugin)'),
4476 new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
4477 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"'),
4478 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"'),
4479 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
4480 new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
4481 new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
4482 ))
4483 ->setHelp(<<<EOT
4484 The <info>init</info> command creates a basic composer.json file
4485 in the current directory.
4486
4487 <info>php composer.phar init</info>
4488
4489 EOT
4490 )
4491 ;
4492 }
4493
4494
4495
4496
4497 protected function execute(InputInterface $input, OutputInterface $output)
4498 {
4499 $io = $this->getIO();
4500
4501 $whitelist = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license');
4502 $options = array_filter(array_intersect_key($input->getOptions(), array_flip($whitelist)));
4503
4504 if (isset($options['author'])) {
4505 $options['authors'] = $this->formatAuthors($options['author']);
4506 unset($options['author']);
4507 }
4508
4509 $repositories = $input->getOption('repository');
4510 if ($repositories) {
4511 $config = Factory::createConfig($io);
4512 foreach ($repositories as $repo) {
4513 $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
4514 }
4515 }
4516
4517 if (isset($options['stability'])) {
4518 $options['minimum-stability'] = $options['stability'];
4519 unset($options['stability']);
4520 }
4521
4522 $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass;
4523 if (array() === $options['require']) {
4524 $options['require'] = new \stdClass;
4525 }
4526
4527 if (isset($options['require-dev'])) {
4528 $options['require-dev'] = $this->formatRequirements($options['require-dev']);
4529 if (array() === $options['require-dev']) {
4530 $options['require-dev'] = new \stdClass;
4531 }
4532 }
4533
4534 $file = new JsonFile(Factory::getComposerFile());
4535 $json = $file->encode($options);
4536
4537 if ($input->isInteractive()) {
4538 $io->writeError(array('', $json, ''));
4539 if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
4540 $io->writeError('<error>Command aborted</error>');
4541
4542 return 1;
4543 }
4544 }
4545
4546 $file->write($options);
4547
4548 if ($input->isInteractive() && is_dir('.git')) {
4549 $ignoreFile = realpath('.gitignore');
4550
4551 if (false === $ignoreFile) {
4552 $ignoreFile = realpath('.') . '/.gitignore';
4553 }
4554
4555 if (!$this->hasVendorIgnore($ignoreFile)) {
4556 $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
4557
4558 if ($io->askConfirmation($question, true)) {
4559 $this->addVendorIgnore($ignoreFile);
4560 }
4561 }
4562 }
4563 }
4564
4565
4566
4567
4568 protected function interact(InputInterface $input, OutputInterface $output)
4569 {
4570 $git = $this->getGitConfig();
4571 $io = $this->getIO();
4572 $formatter = $this->getHelperSet()->get('formatter');
4573
4574
4575  $repositories = $input->getOption('repository');
4576 if ($repositories) {
4577 $config = Factory::createConfig($io);
4578 $repos = array(new PlatformRepository);
4579 foreach ($repositories as $repo) {
4580 $repos[] = RepositoryFactory::fromString($io, $config, $repo);
4581 }
4582 $repos[] = RepositoryFactory::createRepo($io, $config, array(
4583 'type' => 'composer',
4584 'url' => 'https://packagist.org',
4585 ));
4586
4587 $this->repos = new CompositeRepository($repos);
4588 unset($repos, $config, $repositories);
4589 }
4590
4591 $io->writeError(array(
4592 '',
4593 $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
4594 '',
4595 ));
4596
4597
4598  $io->writeError(array(
4599 '',
4600 'This command will guide you through creating your composer.json config.',
4601 '',
4602 ));
4603
4604 $cwd = realpath(".");
4605
4606 if (!$name = $input->getOption('name')) {
4607 $name = basename($cwd);
4608 $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
4609 $name = strtolower($name);
4610 if (isset($git['github.user'])) {
4611 $name = $git['github.user'] . '/' . $name;
4612 } elseif (!empty($_SERVER['USERNAME'])) {
4613 $name = $_SERVER['USERNAME'] . '/' . $name;
4614 } elseif (!empty($_SERVER['USER'])) {
4615 $name = $_SERVER['USER'] . '/' . $name;
4616 } elseif (get_current_user()) {
4617 $name = get_current_user() . '/' . $name;
4618 } else {
4619
4620  $name = $name . '/' . $name;
4621 }
4622 $name = strtolower($name);
4623 } else {
4624 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $name)) {
4625 throw new \InvalidArgumentException(
4626 '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_.-]+'
4627 );
4628 }
4629 }
4630
4631 $name = $io->askAndValidate(
4632 'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
4633 function ($value) use ($name) {
4634 if (null === $value) {
4635 return $name;
4636 }
4637
4638 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $value)) {
4639 throw new \InvalidArgumentException(
4640 '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_.-]+'
4641 );
4642 }
4643
4644 return $value;
4645 },
4646 null,
4647 $name
4648 );
4649 $input->setOption('name', $name);
4650
4651 $description = $input->getOption('description') ?: false;
4652 $description = $io->ask(
4653 'Description [<comment>'.$description.'</comment>]: ',
4654 $description
4655 );
4656 $input->setOption('description', $description);
4657
4658 if (null === $author = $input->getOption('author')) {
4659 if (isset($git['user.name']) && isset($git['user.email'])) {
4660 $author = sprintf('%s <%s>', $git['user.name'], $git['user.email']);
4661 }
4662 }
4663
4664 $self = $this;
4665 $author = $io->askAndValidate(
4666 'Author [<comment>'.$author.'</comment>, n to skip]: ',
4667 function ($value) use ($self, $author) {
4668 if ($value === 'n' || $value === 'no') {
4669 return;
4670 }
4671 $value = $value ?: $author;
4672 $author = $self->parseAuthorString($value);
4673
4674 return sprintf('%s <%s>', $author['name'], $author['email']);
4675 },
4676 null,
4677 $author
4678 );
4679 $input->setOption('author', $author);
4680
4681 $minimumStability = $input->getOption('stability') ?: null;
4682 $minimumStability = $io->askAndValidate(
4683 'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
4684 function ($value) use ($self, $minimumStability) {
4685 if (null === $value) {
4686 return $minimumStability;
4687 }
4688
4689 if (!isset(BasePackage::$stabilities[$value])) {
4690 throw new \InvalidArgumentException(
4691 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
4692 implode(', ', array_keys(BasePackage::$stabilities))
4693 );
4694 }
4695
4696 return $value;
4697 },
4698 null,
4699 $minimumStability
4700 );
4701 $input->setOption('stability', $minimumStability);
4702
4703 $type = $input->getOption('type') ?: false;
4704 $type = $io->ask(
4705 'Package Type (e.g. library, project, metapackage, composer-plugin) [<comment>'.$type.'</comment>]: ',
4706 $type
4707 );
4708 $input->setOption('type', $type);
4709
4710 $license = $input->getOption('license') ?: false;
4711 $license = $io->ask(
4712 'License [<comment>'.$license.'</comment>]: ',
4713 $license
4714 );
4715 $input->setOption('license', $license);
4716
4717 $io->writeError(array('', 'Define your dependencies.', ''));
4718
4719 $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
4720 $require = $input->getOption('require');
4721 $requirements = array();
4722 if ($require || $io->askConfirmation($question, true)) {
4723 $requirements = $this->determineRequirements($input, $output, $require);
4724 }
4725 $input->setOption('require', $requirements);
4726
4727 $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
4728 $requireDev = $input->getOption('require-dev');
4729 $devRequirements = array();
4730 if ($requireDev || $io->askConfirmation($question, true)) {
4731 $devRequirements = $this->determineRequirements($input, $output, $requireDev);
4732 }
4733 $input->setOption('require-dev', $devRequirements);
4734 }
4735
4736
4737
4738
4739
4740
4741 public function parseAuthorString($author)
4742 {
4743 if (preg_match('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P<email>.+?)>$/u', $author, $match)) {
4744 if ($this->isValidEmail($match['email'])) {
4745 return array(
4746 'name' => trim($match['name']),
4747 'email' => $match['email'],
4748 );
4749 }
4750 }
4751
4752 throw new \InvalidArgumentException(
4753 'Invalid author string.  Must be in the format: '.
4754 'John Smith <john@example.com>'
4755 );
4756 }
4757
4758 protected function findPackages($name)
4759 {
4760 return $this->getRepos()->search($name);
4761 }
4762
4763 protected function getRepos()
4764 {
4765 if (!$this->repos) {
4766 $this->repos = new CompositeRepository(array_merge(
4767 array(new PlatformRepository),
4768 RepositoryFactory::defaultRepos($this->getIO())
4769 ));
4770 }
4771
4772 return $this->repos;
4773 }
4774
4775 protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable')
4776 {
4777 if ($requires) {
4778 $requires = $this->normalizeRequirements($requires);
4779 $result = array();
4780 $io = $this->getIO();
4781
4782 foreach ($requires as $requirement) {
4783 if (!isset($requirement['version'])) {
4784
4785  $version = $this->findBestVersionForPackage($input, $requirement['name'], $phpVersion, $preferredStability);
4786 $requirement['version'] = $version;
4787
4788 $io->writeError(sprintf(
4789 'Using version <info>%s</info> for <info>%s</info>',
4790 $requirement['version'],
4791 $requirement['name']
4792 ));
4793 }
4794
4795 $result[] = $requirement['name'] . ' ' . $requirement['version'];
4796 }
4797
4798 return $result;
4799 }
4800
4801 $versionParser = new VersionParser();
4802 $io = $this->getIO();
4803 while (null !== $package = $io->ask('Search for a package: ')) {
4804 $matches = $this->findPackages($package);
4805
4806 if (count($matches)) {
4807 $exactMatch = null;
4808 $choices = array();
4809 foreach ($matches as $position => $foundPackage) {
4810 $choices[] = sprintf(' <info>%5s</info> %s', "[$position]", $foundPackage['name']);
4811 if ($foundPackage['name'] === $package) {
4812 $exactMatch = true;
4813 break;
4814 }
4815 }
4816
4817
4818  if (!$exactMatch) {
4819 $io->writeError(array(
4820 '',
4821 sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
4822 '',
4823 ));
4824
4825 $io->writeError($choices);
4826 $io->writeError('');
4827
4828 $validator = function ($selection) use ($matches, $versionParser) {
4829 if ('' === $selection) {
4830 return false;
4831 }
4832
4833 if (is_numeric($selection) && isset($matches[(int) $selection])) {
4834 $package = $matches[(int) $selection];
4835
4836 return $package['name'];
4837 }
4838
4839 if (preg_match('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
4840 if (isset($packageMatches['version'])) {
4841
4842
4843
4844  $versionParser->parseConstraints($packageMatches['version']);
4845
4846 return $packageMatches['name'].' '.$packageMatches['version'];
4847 }
4848
4849
4850  return $packageMatches['name'];
4851 }
4852
4853 throw new \Exception('Not a valid selection');
4854 };
4855
4856 $package = $io->askAndValidate(
4857 'Enter package # to add, or the complete package name if it is not listed: ',
4858 $validator,
4859 3,
4860 false
4861 );
4862 }
4863
4864
4865  if (false !== $package && false === strpos($package, ' ')) {
4866 $validator = function ($input) {
4867 $input = trim($input);
4868
4869 return $input ?: false;
4870 };
4871
4872 $constraint = $io->askAndValidate(
4873 'Enter the version constraint to require (or leave blank to use the latest version): ',
4874 $validator,
4875 3,
4876 false
4877 );
4878
4879 if (false === $constraint) {
4880 $constraint = $this->findBestVersionForPackage($input, $package, $phpVersion, $preferredStability);
4881
4882 $io->writeError(sprintf(
4883 'Using version <info>%s</info> for <info>%s</info>',
4884 $constraint,
4885 $package
4886 ));
4887 }
4888
4889 $package .= ' '.$constraint;
4890 }
4891
4892 if (false !== $package) {
4893 $requires[] = $package;
4894 }
4895 }
4896 }
4897
4898 return $requires;
4899 }
4900
4901 protected function formatAuthors($author)
4902 {
4903 return array($this->parseAuthorString($author));
4904 }
4905
4906 protected function formatRequirements(array $requirements)
4907 {
4908 $requires = array();
4909 $requirements = $this->normalizeRequirements($requirements);
4910 foreach ($requirements as $requirement) {
4911 $requires[$requirement['name']] = $requirement['version'];
4912 }
4913
4914 return $requires;
4915 }
4916
4917 protected function getGitConfig()
4918 {
4919 if (null !== $this->gitConfig) {
4920 return $this->gitConfig;
4921 }
4922
4923 $finder = new ExecutableFinder();
4924 $gitBin = $finder->find('git');
4925
4926 $cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
4927 $cmd->run();
4928
4929 if ($cmd->isSuccessful()) {
4930 $this->gitConfig = array();
4931 preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER);
4932 foreach ($matches as $match) {
4933 $this->gitConfig[$match[1]] = $match[2];
4934 }
4935
4936 return $this->gitConfig;
4937 }
4938
4939 return $this->gitConfig = array();
4940 }
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958 protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
4959 {
4960 if (!file_exists($ignoreFile)) {
4961 return false;
4962 }
4963
4964 $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
4965
4966 $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES);
4967 foreach ($lines as $line) {
4968 if (preg_match($pattern, $line)) {
4969 return true;
4970 }
4971 }
4972
4973 return false;
4974 }
4975
4976 protected function normalizeRequirements(array $requirements)
4977 {
4978 $parser = new VersionParser();
4979
4980 return $parser->parseNameVersionPairs($requirements);
4981 }
4982
4983 protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
4984 {
4985 $contents = "";
4986 if (file_exists($ignoreFile)) {
4987 $contents = file_get_contents($ignoreFile);
4988
4989 if ("\n" !== substr($contents, 0, -1)) {
4990 $contents .= "\n";
4991 }
4992 }
4993
4994 file_put_contents($ignoreFile, $contents . $vendor. "\n");
4995 }
4996
4997 protected function isValidEmail($email)
4998 {
4999
5000  if (!function_exists('filter_var')) {
5001 return true;
5002 }
5003
5004
5005  if (PHP_VERSION_ID < 50303) {
5006 return true;
5007 }
5008
5009 return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
5010 }
5011
5012 private function getPool(InputInterface $input)
5013 {
5014 if (!$this->pool) {
5015 $this->pool = new Pool($this->getMinimumStability($input));
5016 $this->pool->addRepository($this->getRepos());
5017 }
5018
5019 return $this->pool;
5020 }
5021
5022 private function getMinimumStability(InputInterface $input)
5023 {
5024 if ($input->hasOption('stability')) {
5025 return $input->getOption('stability') ?: 'stable';
5026 }
5027
5028 $file = Factory::getComposerFile();
5029 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
5030 if (!empty($composer['minimum-stability'])) {
5031 return $composer['minimum-stability'];
5032 }
5033 }
5034
5035 return 'stable';
5036 }
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050 private function findBestVersionForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable')
5051 {
5052
5053  $versionSelector = new VersionSelector($this->getPool($input));
5054 $package = $versionSelector->findBestCandidate($name, null, $phpVersion, $preferredStability);
5055
5056 if (!$package) {
5057
5058  if ($phpVersion && $versionSelector->findBestCandidate($name)) {
5059 throw new \InvalidArgumentException(sprintf(
5060 'Could not find package %s at any version matching your PHP version %s', $name, $phpVersion
5061 ));
5062 }
5063 throw new \InvalidArgumentException(sprintf(
5064 'Could not find package %s at any version for your minimum-stability (%s). Check the package spelling or your minimum-stability',
5065 $name,
5066 $this->getMinimumStability($input)
5067 ));
5068 }
5069
5070 return $versionSelector->findRecommendedRequireVersion($package);
5071 }
5072 }
5073 <?php
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085 namespace Composer\Command;
5086
5087 use Composer\Installer;
5088 use Composer\Plugin\CommandEvent;
5089 use Composer\Plugin\PluginEvents;
5090 use Symfony\Component\Console\Input\InputInterface;
5091 use Symfony\Component\Console\Input\InputOption;
5092 use Symfony\Component\Console\Input\InputArgument;
5093 use Symfony\Component\Console\Output\OutputInterface;
5094
5095
5096
5097
5098
5099
5100
5101 class InstallCommand extends BaseCommand
5102 {
5103 protected function configure()
5104 {
5105 $this
5106 ->setName('install')
5107 ->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
5108 ->setDefinition(array(
5109 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5110 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5111 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
5112 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
5113 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
5114 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
5115 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
5116 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5117 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5118 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5119 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
5120 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5121 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5122 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5123 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5124 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
5125 ))
5126 ->setHelp(<<<EOT
5127 The <info>install</info> command reads the composer.lock file from
5128 the current directory, processes it, and downloads and installs all the
5129 libraries and dependencies outlined in that file. If the file does not
5130 exist it will look for composer.json and do the same.
5131
5132 <info>php composer.phar install</info>
5133
5134 EOT
5135 )
5136 ;
5137 }
5138
5139 protected function execute(InputInterface $input, OutputInterface $output)
5140 {
5141 $io = $this->getIO();
5142 if ($args = $input->getArgument('packages')) {
5143 $io->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
5144
5145 return 1;
5146 }
5147
5148 if ($input->getOption('no-custom-installers')) {
5149 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
5150 $input->setOption('no-plugins', true);
5151 }
5152
5153 if ($input->getOption('dev')) {
5154 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
5155 }
5156
5157 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5158 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5159
5160 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
5161 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5162
5163 $install = Installer::create($io, $composer);
5164
5165 $config = $composer->getConfig();
5166 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
5167
5168 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
5169 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
5170 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
5171
5172 $install
5173 ->setDryRun($input->getOption('dry-run'))
5174 ->setVerbose($input->getOption('verbose'))
5175 ->setPreferSource($preferSource)
5176 ->setPreferDist($preferDist)
5177 ->setDevMode(!$input->getOption('no-dev'))
5178 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
5179 ->setRunScripts(!$input->getOption('no-scripts'))
5180 ->setSkipSuggest($input->getOption('no-suggest'))
5181 ->setOptimizeAutoloader($optimize)
5182 ->setClassMapAuthoritative($authoritative)
5183 ->setApcuAutoloader($apcu)
5184 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5185 ;
5186
5187 if ($input->getOption('no-plugins')) {
5188 $install->disablePlugins();
5189 }
5190
5191 return $install->run();
5192 }
5193 }
5194 <?php
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206 namespace Composer\Command;
5207
5208 use Composer\Json\JsonFile;
5209 use Composer\Plugin\CommandEvent;
5210 use Composer\Plugin\PluginEvents;
5211 use Composer\Package\PackageInterface;
5212 use Composer\Repository\RepositoryInterface;
5213 use Symfony\Component\Console\Helper\Table;
5214 use Symfony\Component\Console\Input\InputInterface;
5215 use Symfony\Component\Console\Input\InputOption;
5216 use Symfony\Component\Console\Output\OutputInterface;
5217
5218
5219
5220
5221 class LicensesCommand extends BaseCommand
5222 {
5223 protected function configure()
5224 {
5225 $this
5226 ->setName('licenses')
5227 ->setDescription('Shows information about licenses of dependencies.')
5228 ->setDefinition(array(
5229 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5230 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
5231 ))
5232 ->setHelp(<<<EOT
5233 The license command displays detailed information about the licenses of
5234 the installed dependencies.
5235
5236 EOT
5237 )
5238 ;
5239 }
5240
5241 protected function execute(InputInterface $input, OutputInterface $output)
5242 {
5243 $composer = $this->getComposer();
5244
5245 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
5246 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5247
5248 $root = $composer->getPackage();
5249 $repo = $composer->getRepositoryManager()->getLocalRepository();
5250
5251 if ($input->getOption('no-dev')) {
5252 $packages = $this->filterRequiredPackages($repo, $root);
5253 } else {
5254 $packages = $this->appendPackages($repo->getPackages(), array());
5255 }
5256
5257 ksort($packages);
5258 $io = $this->getIO();
5259
5260 switch ($format = $input->getOption('format')) {
5261 case 'text':
5262 $io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
5263 $io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
5264 $io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
5265 $io->write('Dependencies:');
5266 $io->write('');
5267
5268 $table = new Table($output);
5269 $table->setStyle('compact');
5270 $table->getStyle()->setVerticalBorderChar('');
5271 $table->getStyle()->setCellRowContentFormat('%s  ');
5272 $table->setHeaders(array('Name', 'Version', 'License'));
5273 foreach ($packages as $package) {
5274 $table->addRow(array(
5275 $package->getPrettyName(),
5276 $package->getFullPrettyVersion(),
5277 implode(', ', $package->getLicense()) ?: 'none',
5278 ));
5279 }
5280 $table->render();
5281 break;
5282
5283 case 'json':
5284 $dependencies = array();
5285 foreach ($packages as $package) {
5286 $dependencies[$package->getPrettyName()] = array(
5287 'version' => $package->getFullPrettyVersion(),
5288 'license' => $package->getLicense(),
5289 );
5290 }
5291
5292 $io->write(JsonFile::encode(array(
5293 'name' => $root->getPrettyName(),
5294 'version' => $root->getFullPrettyVersion(),
5295 'license' => $root->getLicense(),
5296 'dependencies' => $dependencies,
5297 )));
5298 break;
5299
5300 default:
5301 throw new \RuntimeException(sprintf('Unsupported format "%s".  See help for supported formats.', $format));
5302 }
5303 }
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313 private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
5314 {
5315 $requires = array_keys($package->getRequires());
5316
5317 $packageListNames = array_keys($bucket);
5318 $packages = array_filter(
5319 $repo->getPackages(),
5320 function ($package) use ($requires, $packageListNames) {
5321 return in_array($package->getName(), $requires) && !in_array($package->getName(), $packageListNames);
5322 }
5323 );
5324
5325 $bucket = $this->appendPackages($packages, $bucket);
5326
5327 foreach ($packages as $package) {
5328 $bucket = $this->filterRequiredPackages($repo, $package, $bucket);
5329 }
5330
5331 return $bucket;
5332 }
5333
5334
5335
5336
5337
5338
5339
5340
5341 public function appendPackages(array $packages, array $bucket)
5342 {
5343 foreach ($packages as $package) {
5344 $bucket[$package->getName()] = $package;
5345 }
5346
5347 return $bucket;
5348 }
5349 }
5350 <?php
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362 namespace Composer\Command;
5363
5364 use Symfony\Component\Console\Input\InputInterface;
5365 use Symfony\Component\Console\Input\InputArgument;
5366 use Symfony\Component\Console\Input\ArrayInput;
5367 use Symfony\Component\Console\Input\InputOption;
5368 use Symfony\Component\Console\Output\OutputInterface;
5369
5370
5371
5372
5373 class OutdatedCommand extends ShowCommand
5374 {
5375 protected function configure()
5376 {
5377 $this
5378 ->setName('outdated')
5379 ->setDescription('Shows a list of installed packages that have updates available, including their latest version.')
5380 ->setDefinition(array(
5381 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
5382 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'),
5383 new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'),
5384 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
5385 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
5386 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
5387 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5388 ))
5389 ->setHelp(<<<EOT
5390 The outdated command is just a proxy for `composer show -l`
5391
5392 The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:
5393
5394 - <info>green</info> (=): Dependency is in the latest version and is up to date.
5395 - <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
5396   compatibility breaks according to semver, so upgrade when you can but it
5397   may involve work.
5398 - <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
5399
5400
5401 EOT
5402 )
5403 ;
5404 }
5405
5406 protected function execute(InputInterface $input, OutputInterface $output)
5407 {
5408 $args = array(
5409 'show',
5410 '--latest' => true,
5411 );
5412 if (!$input->getOption('all')) {
5413 $args['--outdated'] = true;
5414 }
5415 if ($input->getOption('direct')) {
5416 $args['--direct'] = true;
5417 }
5418 if ($input->getArgument('package')) {
5419 $args['package'] = $input->getArgument('package');
5420 }
5421 if ($input->getOption('strict')) {
5422 $args['--strict'] = true;
5423 }
5424 if ($input->getOption('minor-only')) {
5425 $args['--minor-only'] = true;
5426 }
5427 $args['--format'] = $input->getOption('format');
5428
5429 $input = new ArrayInput($args);
5430
5431 return $this->getApplication()->run($input, $output);
5432 }
5433
5434
5435
5436
5437 public function isProxyCommand()
5438 {
5439 return true;
5440 }
5441 }
5442 <?php
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454 namespace Composer\Command;
5455
5456 use Symfony\Component\Console\Input\InputInterface;
5457 use Symfony\Component\Console\Output\OutputInterface;
5458
5459
5460
5461
5462 class ProhibitsCommand extends BaseDependencyCommand
5463 {
5464
5465
5466
5467 protected function configure()
5468 {
5469 parent::configure();
5470
5471 $this
5472 ->setName('prohibits')
5473 ->setAliases(array('why-not'))
5474 ->setDescription('Shows which packages prevent the given package from being installed.')
5475 ->setHelp(<<<EOT
5476 Displays detailed information about why a package cannot be installed.
5477
5478 <info>php composer.phar prohibits composer/composer</info>
5479
5480 EOT
5481 )
5482 ;
5483 }
5484
5485
5486
5487
5488
5489
5490
5491
5492 protected function execute(InputInterface $input, OutputInterface $output)
5493 {
5494 return parent::doExecute($input, $output, true);
5495 }
5496 }
5497 <?php
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509 namespace Composer\Command;
5510
5511 use Composer\Config\JsonConfigSource;
5512 use Composer\Installer;
5513 use Composer\Plugin\CommandEvent;
5514 use Composer\Plugin\PluginEvents;
5515 use Composer\Json\JsonFile;
5516 use Composer\Factory;
5517 use Symfony\Component\Console\Input\InputInterface;
5518 use Symfony\Component\Console\Input\InputOption;
5519 use Symfony\Component\Console\Input\InputArgument;
5520 use Symfony\Component\Console\Output\OutputInterface;
5521
5522
5523
5524
5525
5526 class RemoveCommand extends BaseCommand
5527 {
5528 protected function configure()
5529 {
5530 $this
5531 ->setName('remove')
5532 ->setDescription('Removes a package from the require or require-dev.')
5533 ->setDefinition(array(
5534 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
5535 new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
5536 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5537 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
5538 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5539 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
5540 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
5541 new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
5542 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5543 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5544 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5545 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5546 ))
5547 ->setHelp(<<<EOT
5548 The <info>remove</info> command removes a package from the current
5549 list of installed packages
5550
5551 <info>php composer.phar remove</info>
5552
5553 EOT
5554 )
5555 ;
5556 }
5557
5558 protected function execute(InputInterface $input, OutputInterface $output)
5559 {
5560 $packages = $input->getArgument('packages');
5561 $packages = array_map('strtolower', $packages);
5562
5563 $file = Factory::getComposerFile();
5564
5565 $jsonFile = new JsonFile($file);
5566 $composer = $jsonFile->read();
5567 $composerBackup = file_get_contents($jsonFile->getPath());
5568
5569 $json = new JsonConfigSource($jsonFile);
5570
5571 $type = $input->getOption('dev') ? 'require-dev' : 'require';
5572 $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
5573 $io = $this->getIO();
5574
5575 if ($input->getOption('update-with-dependencies')) {
5576 $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>');
5577 }
5578
5579
5580  foreach (array('require', 'require-dev') as $linkType) {
5581 if (isset($composer[$linkType])) {
5582 foreach ($composer[$linkType] as $name => $version) {
5583 $composer[$linkType][strtolower($name)] = $name;
5584 }
5585 }
5586 }
5587
5588 foreach ($packages as $package) {
5589 if (isset($composer[$type][$package])) {
5590 $json->removeLink($type, $composer[$type][$package]);
5591 } elseif (isset($composer[$altType][$package])) {
5592 $io->writeError('<warning>'.$composer[$altType][$package].' could not be found in '.$type.' but it is present in '.$altType.'</warning>');
5593 if ($io->isInteractive()) {
5594 if ($io->askConfirmation('Do you want to remove it from '.$altType.' [<comment>yes</comment>]? ', true)) {
5595 $json->removeLink($altType, $composer[$altType][$package]);
5596 }
5597 }
5598 } else {
5599 $io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
5600 }
5601 }
5602
5603 if ($input->getOption('no-update')) {
5604 return 0;
5605 }
5606
5607
5608  $this->resetComposer();
5609 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5610 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5611
5612 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
5613 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5614
5615 $install = Installer::create($io, $composer);
5616
5617 $updateDevMode = !$input->getOption('update-no-dev');
5618 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
5619 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
5620 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
5621
5622 $install
5623 ->setVerbose($input->getOption('verbose'))
5624 ->setDevMode($updateDevMode)
5625 ->setOptimizeAutoloader($optimize)
5626 ->setClassMapAuthoritative($authoritative)
5627 ->setApcuAutoloader($apcu)
5628 ->setUpdate(true)
5629 ->setUpdateWhitelist($packages)
5630 ->setWhitelistDependencies(!$input->getOption('no-update-with-dependencies'))
5631 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5632 ->setRunScripts(!$input->getOption('no-scripts'))
5633 ;
5634
5635 $exception = null;
5636 try {
5637 $status = $install->run();
5638 } catch (\Exception $exception) {
5639 $status = 1;
5640 }
5641 if ($status !== 0) {
5642 $io->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
5643 file_put_contents($jsonFile->getPath(), $composerBackup);
5644 }
5645 if ($exception) {
5646 throw $exception;
5647 }
5648
5649 return $status;
5650 }
5651 }
5652 <?php
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664 namespace Composer\Command;
5665
5666 use Symfony\Component\Console\Input\InputInterface;
5667 use Symfony\Component\Console\Input\InputArgument;
5668 use Symfony\Component\Console\Input\InputOption;
5669 use Symfony\Component\Console\Output\OutputInterface;
5670 use Composer\Factory;
5671 use Composer\Installer;
5672 use Composer\Json\JsonFile;
5673 use Composer\Json\JsonManipulator;
5674 use Composer\Package\Version\VersionParser;
5675 use Composer\Plugin\CommandEvent;
5676 use Composer\Plugin\PluginEvents;
5677 use Composer\Repository\CompositeRepository;
5678 use Composer\Repository\PlatformRepository;
5679
5680
5681
5682
5683
5684 class RequireCommand extends InitCommand
5685 {
5686 protected function configure()
5687 {
5688 $this
5689 ->setName('require')
5690 ->setDescription('Adds required packages to your composer.json and installs them.')
5691 ->setDefinition(array(
5692 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Required package name optionally including 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"'),
5693 new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
5694 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5695 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5696 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5697 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5698 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
5699 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5700 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
5701 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies.'),
5702 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5703 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
5704 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
5705 new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
5706 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5707 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5708 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5709 ))
5710 ->setHelp(<<<EOT
5711 The require command adds required packages to your composer.json and installs them.
5712
5713 If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.
5714
5715 If you do not want to install the new dependencies immediately you can call it with --no-update
5716
5717 EOT
5718 )
5719 ;
5720 }
5721
5722 protected function execute(InputInterface $input, OutputInterface $output)
5723 {
5724 $file = Factory::getComposerFile();
5725 $io = $this->getIO();
5726
5727 $newlyCreated = !file_exists($file);
5728 if ($newlyCreated && !file_put_contents($file, "{\n}\n")) {
5729 $io->writeError('<error>'.$file.' could not be created.</error>');
5730
5731 return 1;
5732 }
5733 if (!is_readable($file)) {
5734 $io->writeError('<error>'.$file.' is not readable.</error>');
5735
5736 return 1;
5737 }
5738 if (!is_writable($file)) {
5739 $io->writeError('<error>'.$file.' is not writable.</error>');
5740
5741 return 1;
5742 }
5743
5744 if (filesize($file) === 0) {
5745 file_put_contents($file, "{\n}\n");
5746 }
5747
5748 $json = new JsonFile($file);
5749 $composerBackup = file_get_contents($json->getPath());
5750
5751 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5752 $repos = $composer->getRepositoryManager()->getRepositories();
5753
5754 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
5755
5756  $this->repos = new CompositeRepository(array_merge(
5757 array(new PlatformRepository(array(), $platformOverrides)),
5758 $repos
5759 ));
5760
5761 if ($composer->getPackage()->getPreferStable()) {
5762 $preferredStability = 'stable';
5763 } else {
5764 $preferredStability = $composer->getPackage()->getMinimumStability();
5765 }
5766
5767 $phpVersion = $this->repos->findPackage('php', '*')->getVersion();
5768 $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability);
5769
5770 $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
5771 $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
5772 $requirements = $this->formatRequirements($requirements);
5773
5774
5775  $versionParser = new VersionParser();
5776 foreach ($requirements as $constraint) {
5777 $versionParser->parseConstraints($constraint);
5778 }
5779
5780 $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
5781
5782 if (!$this->updateFileCleanly($json, $requirements, $requireKey, $removeKey, $sortPackages)) {
5783 $composerDefinition = $json->read();
5784 foreach ($requirements as $package => $version) {
5785 $composerDefinition[$requireKey][$package] = $version;
5786 unset($composerDefinition[$removeKey][$package]);
5787 }
5788 $json->write($composerDefinition);
5789 }
5790
5791 $io->writeError('<info>'.$file.' has been '.($newlyCreated ? 'created' : 'updated').'</info>');
5792
5793 if ($input->getOption('no-update')) {
5794 return 0;
5795 }
5796 $updateDevMode = !$input->getOption('update-no-dev');
5797 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
5798 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
5799 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
5800
5801
5802  $this->resetComposer();
5803 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5804 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5805
5806 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
5807 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5808
5809 $install = Installer::create($io, $composer);
5810
5811 $install
5812 ->setVerbose($input->getOption('verbose'))
5813 ->setPreferSource($input->getOption('prefer-source'))
5814 ->setPreferDist($input->getOption('prefer-dist'))
5815 ->setDevMode($updateDevMode)
5816 ->setRunScripts(!$input->getOption('no-scripts'))
5817 ->setSkipSuggest($input->getOption('no-suggest'))
5818 ->setOptimizeAutoloader($optimize)
5819 ->setClassMapAuthoritative($authoritative)
5820 ->setApcuAutoloader($apcu)
5821 ->setUpdate(true)
5822 ->setUpdateWhitelist(array_keys($requirements))
5823 ->setWhitelistDependencies($input->getOption('update-with-dependencies'))
5824 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5825 ->setPreferStable($input->getOption('prefer-stable'))
5826 ->setPreferLowest($input->getOption('prefer-lowest'))
5827 ;
5828
5829 $exception = null;
5830 try {
5831 $status = $install->run();
5832 } catch (\Exception $exception) {
5833 $status = 1;
5834 }
5835 if ($status !== 0) {
5836 if ($newlyCreated) {
5837 $io->writeError("\n".'<error>Installation failed, deleting '.$file.'.</error>');
5838 unlink($json->getPath());
5839 } else {
5840 $io->writeError("\n".'<error>Installation failed, reverting '.$file.' to its original content.</error>');
5841 file_put_contents($json->getPath(), $composerBackup);
5842 }
5843 }
5844 if ($exception) {
5845 throw $exception;
5846 }
5847
5848 return $status;
5849 }
5850
5851 private function updateFileCleanly($json, array $new, $requireKey, $removeKey, $sortPackages)
5852 {
5853 $contents = file_get_contents($json->getPath());
5854
5855 $manipulator = new JsonManipulator($contents);
5856
5857 foreach ($new as $package => $constraint) {
5858 if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
5859 return false;
5860 }
5861 if (!$manipulator->removeSubNode($removeKey, $package)) {
5862 return false;
5863 }
5864 }
5865
5866 file_put_contents($json->getPath(), $manipulator->getContents());
5867
5868 return true;
5869 }
5870
5871 protected function interact(InputInterface $input, OutputInterface $output)
5872 {
5873 return;
5874 }
5875 }
5876 <?php
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888 namespace Composer\Command;
5889
5890 use Composer\Script\Event as ScriptEvent;
5891 use Composer\Script\ScriptEvents;
5892 use Composer\Util\ProcessExecutor;
5893 use Symfony\Component\Console\Input\InputInterface;
5894 use Symfony\Component\Console\Input\InputOption;
5895 use Symfony\Component\Console\Input\InputArgument;
5896 use Symfony\Component\Console\Output\OutputInterface;
5897
5898
5899
5900
5901 class RunScriptCommand extends BaseCommand
5902 {
5903
5904
5905
5906 protected $scriptEvents = array(
5907 ScriptEvents::PRE_INSTALL_CMD,
5908 ScriptEvents::POST_INSTALL_CMD,
5909 ScriptEvents::PRE_UPDATE_CMD,
5910 ScriptEvents::POST_UPDATE_CMD,
5911 ScriptEvents::PRE_STATUS_CMD,
5912 ScriptEvents::POST_STATUS_CMD,
5913 ScriptEvents::POST_ROOT_PACKAGE_INSTALL,
5914 ScriptEvents::POST_CREATE_PROJECT_CMD,
5915 ScriptEvents::PRE_ARCHIVE_CMD,
5916 ScriptEvents::POST_ARCHIVE_CMD,
5917 ScriptEvents::PRE_AUTOLOAD_DUMP,
5918 ScriptEvents::POST_AUTOLOAD_DUMP,
5919 );
5920
5921 protected function configure()
5922 {
5923 $this
5924 ->setName('run-script')
5925 ->setDescription('Runs the scripts defined in composer.json.')
5926 ->setDefinition(array(
5927 new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),
5928 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
5929 new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'),
5930 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
5931 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
5932 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.'),
5933 ))
5934 ->setHelp(<<<EOT
5935 The <info>run-script</info> command runs scripts defined in composer.json:
5936
5937 <info>php composer.phar run-script post-update-cmd</info>
5938 EOT
5939 )
5940 ;
5941 }
5942
5943 protected function execute(InputInterface $input, OutputInterface $output)
5944 {
5945 if ($input->getOption('list')) {
5946 return $this->listScripts();
5947 } elseif (!$input->getArgument('script')) {
5948 throw new \RuntimeException('Missing required argument "script"');
5949 }
5950
5951 $script = $input->getArgument('script');
5952 if (!in_array($script, $this->scriptEvents)) {
5953 if (defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
5954 throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
5955 }
5956 }
5957
5958 $composer = $this->getComposer();
5959 $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
5960 $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode);
5961 $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event);
5962 if (!$hasListeners) {
5963 throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
5964 }
5965
5966 $args = $input->getArgument('args');
5967
5968 if (!is_null($timeout = $input->getOption('timeout'))) {
5969 if (!ctype_digit($timeout)) {
5970 throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever');
5971 }
5972
5973  ProcessExecutor::setTimeout((int) $timeout);
5974 }
5975
5976 return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
5977 }
5978
5979 protected function listScripts()
5980 {
5981 $scripts = $this->getComposer()->getPackage()->getScripts();
5982
5983 if (!count($scripts)) {
5984 return 0;
5985 }
5986
5987 $io = $this->getIO();
5988 $io->writeError('<info>scripts:</info>');
5989 foreach ($scripts as $name => $script) {
5990 $io->write('  ' . $name);
5991 }
5992
5993 return 0;
5994 }
5995 }
5996 <?php
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008 namespace Composer\Command;
6009
6010 use Symfony\Component\Console\Input\InputInterface;
6011 use Symfony\Component\Console\Input\InputOption;
6012 use Symfony\Component\Console\Input\InputArgument;
6013 use Symfony\Component\Console\Output\OutputInterface;
6014
6015
6016
6017
6018 class ScriptAliasCommand extends BaseCommand
6019 {
6020 private $script;
6021
6022 public function __construct($script)
6023 {
6024 $this->script = $script;
6025
6026 parent::__construct();
6027 }
6028
6029 protected function configure()
6030 {
6031 $this
6032 ->setName($this->script)
6033 ->setDescription('Runs the '.$this->script.' script as defined in composer.json.')
6034 ->setDefinition(array(
6035 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6036 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6037 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6038 ))
6039 ->setHelp(<<<EOT
6040 The <info>run-script</info> command runs scripts defined in composer.json:
6041
6042 <info>php composer.phar run-script post-update-cmd</info>
6043 EOT
6044 )
6045 ;
6046 }
6047
6048 protected function execute(InputInterface $input, OutputInterface $output)
6049 {
6050 $composer = $this->getComposer();
6051
6052 $args = $input->getArguments();
6053
6054 return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args']);
6055 }
6056 }
6057 <?php
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069 namespace Composer\Command;
6070
6071 use Composer\Factory;
6072 use Symfony\Component\Console\Input\InputInterface;
6073 use Symfony\Component\Console\Input\InputArgument;
6074 use Symfony\Component\Console\Input\InputOption;
6075 use Symfony\Component\Console\Output\OutputInterface;
6076 use Composer\Repository\CompositeRepository;
6077 use Composer\Repository\PlatformRepository;
6078 use Composer\Repository\RepositoryInterface;
6079 use Composer\Plugin\CommandEvent;
6080 use Composer\Plugin\PluginEvents;
6081
6082
6083
6084
6085 class SearchCommand extends BaseCommand
6086 {
6087 protected $matches;
6088 protected $lowMatches = array();
6089 protected $tokens;
6090 protected $output;
6091 protected $onlyName;
6092
6093 protected function configure()
6094 {
6095 $this
6096 ->setName('search')
6097 ->setDescription('Searches for packages.')
6098 ->setDefinition(array(
6099 new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
6100 new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
6101 new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
6102 ))
6103 ->setHelp(<<<EOT
6104 The search command searches for packages by its name
6105 <info>php composer.phar search symfony composer</info>
6106
6107 EOT
6108 )
6109 ;
6110 }
6111
6112 protected function execute(InputInterface $input, OutputInterface $output)
6113 {
6114
6115  $platformRepo = new PlatformRepository;
6116 $io = $this->getIO();
6117 if (!($composer = $this->getComposer(false))) {
6118 $composer = Factory::create($this->getIO(), array());
6119 }
6120 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6121 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6122 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6123
6124 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
6125 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6126
6127 $onlyName = $input->getOption('only-name');
6128 $type = $input->getOption('type') ?: null;
6129
6130 $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
6131 $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
6132
6133 foreach ($results as $result) {
6134 $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
6135 }
6136 }
6137 }
6138 <?php
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150 namespace Composer\Command;
6151
6152 use Composer\Composer;
6153 use Composer\Factory;
6154 use Composer\Config;
6155 use Composer\Util\Filesystem;
6156 use Composer\SelfUpdate\Keys;
6157 use Composer\SelfUpdate\Versions;
6158 use Composer\IO\IOInterface;
6159 use Composer\Downloader\FilesystemException;
6160 use Symfony\Component\Console\Input\InputInterface;
6161 use Symfony\Component\Console\Input\InputOption;
6162 use Symfony\Component\Console\Input\InputArgument;
6163 use Symfony\Component\Console\Output\OutputInterface;
6164 use Symfony\Component\Finder\Finder;
6165
6166
6167
6168
6169
6170
6171 class SelfUpdateCommand extends BaseCommand
6172 {
6173 const HOMEPAGE = 'getcomposer.org';
6174 const OLD_INSTALL_EXT = '-old.phar';
6175
6176 protected function configure()
6177 {
6178 $this
6179 ->setName('self-update')
6180 ->setAliases(array('selfupdate'))
6181 ->setDescription('Updates composer.phar to the latest version.')
6182 ->setDefinition(array(
6183 new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'),
6184 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'),
6185 new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'),
6186 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6187 new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'),
6188 new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'),
6189 new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'),
6190 new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'),
6191 new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit'),
6192 ))
6193 ->setHelp(<<<EOT
6194 The <info>self-update</info> command checks getcomposer.org for newer
6195 versions of composer and if found, installs the latest.
6196
6197 <info>php composer.phar self-update</info>
6198
6199 EOT
6200 )
6201 ;
6202 }
6203
6204 protected function execute(InputInterface $input, OutputInterface $output)
6205 {
6206 $config = Factory::createConfig();
6207
6208 if ($config->get('disable-tls') === true) {
6209 $baseUrl = 'http://' . self::HOMEPAGE;
6210 } else {
6211 $baseUrl = 'https://' . self::HOMEPAGE;
6212 }
6213
6214 $io = $this->getIO();
6215 $remoteFilesystem = Factory::createRemoteFilesystem($io, $config);
6216
6217 $versionsUtil = new Versions($config, $remoteFilesystem);
6218
6219
6220  foreach (array('stable', 'preview', 'snapshot') as $channel) {
6221 if ($input->getOption($channel)) {
6222 $versionsUtil->setChannel($channel);
6223 }
6224 }
6225
6226 if ($input->getOption('set-channel-only')) {
6227 return 0;
6228 }
6229
6230 $cacheDir = $config->get('cache-dir');
6231 $rollbackDir = $config->get('data-dir');
6232 $home = $config->get('home');
6233 $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
6234
6235 if ($input->getOption('update-keys')) {
6236 return $this->fetchKeys($io, $config);
6237 }
6238
6239
6240  $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
6241
6242
6243  if (!is_writable($tmpDir)) {
6244 throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written');
6245 }
6246
6247 if ($input->getOption('rollback')) {
6248 return $this->rollback($output, $rollbackDir, $localFilename);
6249 }
6250
6251 $latest = $versionsUtil->getLatest();
6252 $latestVersion = $latest['version'];
6253 $updateVersion = $input->getArgument('version') ?: $latestVersion;
6254
6255 if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
6256 $io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
6257
6258 return 1;
6259 }
6260
6261 if (Composer::VERSION === $updateVersion) {
6262 $io->writeError(sprintf('<info>You are already using composer version %s (%s channel).</info>', $updateVersion, $versionsUtil->getChannel()));
6263
6264
6265  if ($input->getOption('clean-backups')) {
6266 $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir));
6267 }
6268
6269 return 0;
6270 }
6271
6272 $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar';
6273 $backupFile = sprintf(
6274 '%s/%s-%s%s',
6275 $rollbackDir,
6276 strtr(Composer::RELEASE_DATE, ' :', '_-'),
6277 preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION),
6278 self::OLD_INSTALL_EXT
6279 );
6280
6281 $updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion);
6282
6283 $io->write(sprintf("Updating to version <info>%s</info> (%s channel).", $updateVersion, $versionsUtil->getChannel()));
6284 $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
6285 $signature = $remoteFilesystem->getContents(self::HOMEPAGE, $remoteFilename.'.sig', false);
6286 $io->writeError('   ', false);
6287 $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
6288 $io->writeError('');
6289
6290 if (!file_exists($tempFilename) || !$signature) {
6291 $io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
6292
6293 return 1;
6294 }
6295
6296
6297  if (!extension_loaded('openssl') && $config->get('disable-tls')) {
6298 $io->writeError('<warning>Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls</warning>');
6299 } else {
6300 if (!extension_loaded('openssl')) {
6301 throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. '
6302 . '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.');
6303 }
6304
6305 $sigFile = 'file://'.$home.'/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub');
6306 if (!file_exists($sigFile)) {
6307 file_put_contents($home.'/keys.dev.pub', <<<DEVPUBKEY
6308 -----BEGIN PUBLIC KEY-----
6309 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f
6310 FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi
6311 i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A
6312 hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f
6313 o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk
6314 8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn
6315 8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf
6316 TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9
6317 pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72
6318 8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4
6319 r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE
6320 wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ==
6321 -----END PUBLIC KEY-----
6322 DEVPUBKEY
6323 );
6324 file_put_contents($home.'/keys.tags.pub', <<<TAGSPUBKEY
6325 -----BEGIN PUBLIC KEY-----
6326 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2
6327 MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh
6328 vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO
6329 bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M
6330 mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf
6331 noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM
6332 nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ
6333 rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr
6334 RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK
6335 tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e
6336 TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95
6337 RGv89BPD+2DLnJysngsvVaUCAwEAAQ==
6338 -----END PUBLIC KEY-----
6339 TAGSPUBKEY
6340 );
6341 }
6342
6343 $pubkeyid = openssl_pkey_get_public($sigFile);
6344 $algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384';
6345 if (!in_array('SHA384', openssl_get_md_methods())) {
6346 throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
6347 }
6348 $signature = json_decode($signature, true);
6349 $signature = base64_decode($signature['sha384']);
6350 $verified = 1 === openssl_verify(file_get_contents($tempFilename), $signature, $pubkeyid, $algo);
6351 openssl_free_key($pubkeyid);
6352 if (!$verified) {
6353 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');
6354 }
6355 }
6356
6357
6358  if ($input->getOption('clean-backups')) {
6359 $this->cleanBackups($rollbackDir);
6360 }
6361
6362 if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
6363 @unlink($tempFilename);
6364 $io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
6365 $io->writeError('<error>Please re-run the self-update command to try again.</error>');
6366
6367 return 1;
6368 }
6369
6370 if (file_exists($backupFile)) {
6371 $io->writeError('Use <info>composer self-update --rollback</info> to return to version '.Composer::VERSION);
6372 } else {
6373 $io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
6374 }
6375 }
6376
6377 protected function fetchKeys(IOInterface $io, Config $config)
6378 {
6379 if (!$io->isInteractive()) {
6380 throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
6381 }
6382
6383 $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
6384
6385 $validator = function ($value) {
6386 if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
6387 throw new \UnexpectedValueException('Invalid input');
6388 }
6389
6390 return trim($value)."\n";
6391 };
6392
6393 $devKey = '';
6394 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
6395 $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
6396 while ($line = $io->ask('')) {
6397 $devKey .= trim($line)."\n";
6398 if (trim($line) === '-----END PUBLIC KEY-----') {
6399 break;
6400 }
6401 }
6402 }
6403 file_put_contents($keyPath = $config->get('home').'/keys.dev.pub', $match[0]);
6404 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6405
6406 $tagsKey = '';
6407 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
6408 $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
6409 while ($line = $io->ask('')) {
6410 $tagsKey .= trim($line)."\n";
6411 if (trim($line) === '-----END PUBLIC KEY-----') {
6412 break;
6413 }
6414 }
6415 }
6416 file_put_contents($keyPath = $config->get('home').'/keys.tags.pub', $match[0]);
6417 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6418
6419 $io->write('Public keys stored in '.$config->get('home'));
6420 }
6421
6422 protected function rollback(OutputInterface $output, $rollbackDir, $localFilename)
6423 {
6424 $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
6425 if (!$rollbackVersion) {
6426 throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"');
6427 }
6428
6429 $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
6430
6431 if (!is_file($oldFile)) {
6432 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
6433 }
6434 if (!is_readable($oldFile)) {
6435 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
6436 }
6437
6438 $io = $this->getIO();
6439 $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
6440 if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
6441 $io->writeError('<error>The backup file was corrupted ('.$err->getMessage().').</error>');
6442
6443 return 1;
6444 }
6445
6446 return 0;
6447 }
6448
6449
6450
6451
6452
6453
6454
6455
6456 protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
6457 {
6458 try {
6459 @chmod($newFilename, fileperms($localFilename));
6460 if (!ini_get('phar.readonly')) {
6461
6462  $phar = new \Phar($newFilename);
6463
6464  unset($phar);
6465 }
6466
6467
6468  if ($backupTarget && file_exists($localFilename)) {
6469 @copy($localFilename, $backupTarget);
6470 }
6471
6472 rename($newFilename, $localFilename);
6473
6474 return null;
6475 } catch (\Exception $e) {
6476 if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
6477 throw $e;
6478 }
6479
6480 return $e;
6481 }
6482 }
6483
6484 protected function cleanBackups($rollbackDir, $except = null)
6485 {
6486 $finder = $this->getOldInstallationFinder($rollbackDir);
6487 $io = $this->getIO();
6488 $fs = new Filesystem;
6489
6490 foreach ($finder as $file) {
6491 if ($except && $file->getBasename(self::OLD_INSTALL_EXT) === $except) {
6492 continue;
6493 }
6494 $file = (string) $file;
6495 $io->writeError('<info>Removing: '.$file.'</info>');
6496 $fs->remove($file);
6497 }
6498 }
6499
6500 protected function getLastBackupVersion($rollbackDir)
6501 {
6502 $finder = $this->getOldInstallationFinder($rollbackDir);
6503 $finder->sortByName();
6504 $files = iterator_to_array($finder);
6505
6506 if (count($files)) {
6507 return basename(end($files), self::OLD_INSTALL_EXT);
6508 }
6509
6510 return false;
6511 }
6512
6513 protected function getOldInstallationFinder($rollbackDir)
6514 {
6515 $finder = Finder::create()
6516 ->depth(0)
6517 ->files()
6518 ->name('*' . self::OLD_INSTALL_EXT)
6519 ->in($rollbackDir);
6520
6521 return $finder;
6522 }
6523 }
6524 <?php
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536 namespace Composer\Command;
6537
6538 use Composer\DependencyResolver\Pool;
6539 use Composer\DependencyResolver\DefaultPolicy;
6540 use Composer\Json\JsonFile;
6541 use Composer\Package\CompletePackageInterface;
6542 use Composer\Package\Version\VersionParser;
6543 use Composer\Package\BasePackage;
6544 use Composer\Package\Version\VersionSelector;
6545 use Composer\Plugin\CommandEvent;
6546 use Composer\Plugin\PluginEvents;
6547 use Composer\Package\PackageInterface;
6548 use Composer\Semver\Constraint\ConstraintInterface;
6549 use Composer\Util\Platform;
6550 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
6551 use Symfony\Component\Console\Input\InputInterface;
6552 use Symfony\Component\Console\Input\InputArgument;
6553 use Symfony\Component\Console\Input\InputOption;
6554 use Symfony\Component\Console\Output\OutputInterface;
6555 use Composer\Repository\ArrayRepository;
6556 use Composer\Repository\CompositeRepository;
6557 use Composer\Repository\ComposerRepository;
6558 use Composer\Repository\PlatformRepository;
6559 use Composer\Repository\RepositoryInterface;
6560 use Composer\Repository\RepositoryFactory;
6561 use Composer\Spdx\SpdxLicenses;
6562 use Composer\Composer;
6563 use Composer\Semver\Semver;
6564
6565
6566
6567
6568
6569
6570 class ShowCommand extends BaseCommand
6571 {
6572
6573 protected $versionParser;
6574 protected $colors;
6575
6576
6577 private $pool;
6578
6579 protected function configure()
6580 {
6581 $this
6582 ->setName('show')
6583 ->setAliases(array('info'))
6584 ->setDescription('Shows information about packages.')
6585 ->setDefinition(array(
6586 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
6587 new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
6588 new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'),
6589 new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'),
6590 new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
6591 new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
6592 new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
6593 new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
6594 new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
6595 new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
6596 new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'),
6597 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'),
6598 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
6599 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
6600 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
6601 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
6602 ))
6603 ->setHelp(<<<EOT
6604 The show command displays detailed information about a package, or
6605 lists all packages available.
6606
6607 EOT
6608 )
6609 ;
6610 }
6611
6612 protected function execute(InputInterface $input, OutputInterface $output)
6613 {
6614 $this->versionParser = new VersionParser;
6615 if ($input->getOption('tree')) {
6616 $this->initStyles($output);
6617 }
6618
6619 $composer = $this->getComposer(false);
6620 $io = $this->getIO();
6621
6622 if ($input->getOption('installed')) {
6623 $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>');
6624 }
6625
6626 if ($input->getOption('outdated')) {
6627 $input->setOption('latest', true);
6628 }
6629
6630 if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) {
6631 $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)');
6632
6633 return 1;
6634 }
6635
6636 if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) {
6637 $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)');
6638
6639 return 1;
6640 }
6641
6642 $format = $input->getOption('format');
6643 if (!in_array($format, array('text', 'json'))) {
6644 $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
6645
6646 return 1;
6647 }
6648
6649
6650  $platformOverrides = array();
6651 if ($composer) {
6652 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6653 }
6654 $platformRepo = new PlatformRepository(array(), $platformOverrides);
6655 $phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
6656
6657 if ($input->getOption('self')) {
6658 $package = $this->getComposer()->getPackage();
6659 $repos = $installedRepo = new ArrayRepository(array($package));
6660 } elseif ($input->getOption('platform')) {
6661 $repos = $installedRepo = $platformRepo;
6662 } elseif ($input->getOption('available')) {
6663 $installedRepo = $platformRepo;
6664 if ($composer) {
6665 $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
6666 } else {
6667 $defaultRepos = RepositoryFactory::defaultRepos($io);
6668 $repos = new CompositeRepository($defaultRepos);
6669 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
6670 }
6671 } elseif ($input->getOption('all') && $composer) {
6672 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6673 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6674 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6675 } elseif ($input->getOption('all')) {
6676 $defaultRepos = RepositoryFactory::defaultRepos($io);
6677 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
6678 $installedRepo = $platformRepo;
6679 $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
6680 } else {
6681 $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
6682 }
6683
6684 if ($composer) {
6685 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
6686 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6687 }
6688
6689 if ($input->getOption('latest') && null === $composer) {
6690 $io->writeError('No composer.json found in the current directory, disabling "latest" option');
6691 $input->setOption('latest', false);
6692 }
6693
6694 $packageFilter = $input->getArgument('package');
6695
6696
6697  if (($packageFilter && false === strpos($packageFilter, '*')) || !empty($package)) {
6698 if ('json' === $format) {
6699 $io->writeError('Format "json" is only supported for package listings, falling back to format "text"');
6700 }
6701 if (empty($package)) {
6702 list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version'));
6703
6704 if (empty($package)) {
6705 $options = $input->getOptions();
6706 if (!isset($options['working-dir']) || !file_exists('composer.json')) {
6707 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found');
6708 }
6709
6710 $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
6711
6712 return 1;
6713 }
6714 } else {
6715 $versions = array($package->getPrettyVersion() => $package->getVersion());
6716 }
6717
6718 if ($input->getOption('tree')) {
6719 $this->displayPackageTree($package, $installedRepo, $repos);
6720 } else {
6721 $latestPackage = null;
6722 if ($input->getOption('latest')) {
6723 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion);
6724 }
6725 $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
6726 $this->printLinks($package, 'requires');
6727 $this->printLinks($package, 'devRequires', 'requires (dev)');
6728 if ($package->getSuggests()) {
6729 $io->write("\n<info>suggests</info>");
6730 foreach ($package->getSuggests() as $suggested => $reason) {
6731 $io->write($suggested . ' <comment>' . $reason . '</comment>');
6732 }
6733 }
6734 $this->printLinks($package, 'provides');
6735 $this->printLinks($package, 'conflicts');
6736 $this->printLinks($package, 'replaces');
6737 }
6738
6739 return;
6740 }
6741
6742
6743  if ($input->getOption('tree')) {
6744 if ('json' === $format) {
6745 $io->writeError('Format "json" is only supported for package listings, falling back to format "text"');
6746 }
6747 $rootRequires = $this->getRootRequires();
6748 foreach ($installedRepo->getPackages() as $package) {
6749 if (in_array($package->getName(), $rootRequires, true)) {
6750 $this->displayPackageTree($package, $installedRepo, $repos);
6751 }
6752 }
6753
6754 return 0;
6755 }
6756
6757 if ($repos instanceof CompositeRepository) {
6758 $repos = $repos->getRepositories();
6759 } elseif (!is_array($repos)) {
6760 $repos = array($repos);
6761 }
6762
6763
6764  $packages = array();
6765 if (null !== $packageFilter) {
6766 $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
6767 }
6768
6769 $packageListFilter = array();
6770 if ($input->getOption('direct')) {
6771 $packageListFilter = $this->getRootRequires();
6772 }
6773
6774 list($width) = $this->getApplication()->getTerminalDimensions();
6775 if (null === $width) {
6776
6777  
6778  $width = PHP_INT_MAX;
6779 }
6780 if (Platform::isWindows()) {
6781 $width--;
6782 } else {
6783 $width = max(80, $width);
6784 }
6785
6786 if ($input->getOption('path') && null === $composer) {
6787 $io->writeError('No composer.json found in the current directory, disabling "path" option');
6788 $input->setOption('path', false);
6789 }
6790
6791 foreach ($repos as $repo) {
6792 if ($repo === $platformRepo) {
6793 $type = 'platform';
6794 } elseif (
6795 $repo === $installedRepo
6796 || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
6797 ) {
6798 $type = 'installed';
6799 } else {
6800 $type = 'available';
6801 }
6802 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
6803 foreach ($repo->getProviderNames() as $name) {
6804 if (!$packageFilter || preg_match($packageFilter, $name)) {
6805 $packages[$type][$name] = $name;
6806 }
6807 }
6808 } else {
6809 foreach ($repo->getPackages() as $package) {
6810 if (!isset($packages[$type][$package->getName()])
6811 || !is_object($packages[$type][$package->getName()])
6812 || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
6813 ) {
6814 if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
6815 if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
6816 $packages[$type][$package->getName()] = $package;
6817 }
6818 }
6819 }
6820 }
6821 }
6822 }
6823
6824 $showAllTypes = $input->getOption('all');
6825 $showLatest = $input->getOption('latest');
6826 $showMinorOnly = $input->getOption('minor-only');
6827 $indent = $showAllTypes ? '  ' : '';
6828 $latestPackages = array();
6829 $exitCode = 0;
6830 $viewData = array();
6831 $viewMetaData = array();
6832 foreach (array('platform' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
6833 if (isset($packages[$type])) {
6834 ksort($packages[$type]);
6835
6836 $nameLength = $versionLength = $latestLength = 0;
6837 foreach ($packages[$type] as $package) {
6838 if (is_object($package)) {
6839 $nameLength = max($nameLength, strlen($package->getPrettyName()));
6840 if ($showVersion) {
6841 $versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
6842 if ($showLatest) {
6843 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion, $showMinorOnly);
6844 if ($latestPackage === false) {
6845 continue;
6846 }
6847
6848 $latestPackages[$package->getPrettyName()] = $latestPackage;
6849 $latestLength = max($latestLength, strlen($latestPackage->getFullPrettyVersion()));
6850 }
6851 }
6852 } else {
6853 $nameLength = max($nameLength, strlen($package));
6854 }
6855 }
6856
6857 $writePath = !$input->getOption('name-only') && $input->getOption('path');
6858 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
6859 $writeLatest = $writeVersion && $showLatest;
6860 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
6861
6862 $hasOutdatedPackages = false;
6863
6864 $viewData[$type] = array();
6865 $viewMetaData[$type] = array(
6866 'nameLength' => $nameLength,
6867 'versionLength' => $versionLength,
6868 'latestLength' => $latestLength,
6869 );
6870 foreach ($packages[$type] as $package) {
6871 $packageViewData = array();
6872 if (is_object($package)) {
6873 $latestPackage = null;
6874 if ($showLatest && isset($latestPackages[$package->getPrettyName()])) {
6875 $latestPackage = $latestPackages[$package->getPrettyName()];
6876 }
6877 if ($input->getOption('outdated') && $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
6878 continue;
6879 } elseif ($input->getOption('outdated') || $input->getOption('strict')) {
6880 $hasOutdatedPackages = true;
6881 }
6882
6883 $packageViewData['name'] = $package->getPrettyName();
6884 if ($writeVersion) {
6885 $packageViewData['version'] = $package->getFullPrettyVersion();
6886 }
6887 if ($writeLatest && $latestPackage) {
6888 $packageViewData['latest'] = $latestPackage->getFullPrettyVersion();
6889 $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
6890 }
6891 if ($writeDescription) {
6892 $packageViewData['description'] = $package->getDescription();
6893 }
6894 if ($writePath) {
6895 $packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
6896 }
6897
6898 if ($latestPackage && $latestPackage->isAbandoned()) {
6899 $replacement = (is_string($latestPackage->getReplacementPackage()))
6900 ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead'
6901 : 'No replacement was suggested';
6902 $packageWarning = sprintf(
6903 'Package %s is abandoned, you should avoid using it. %s.',
6904 $package->getPrettyName(),
6905 $replacement
6906 );
6907 $packageViewData['warning'] = $packageWarning;
6908 }
6909 } else {
6910 $packageViewData['name'] = $package;
6911 }
6912 $viewData[$type][] = $packageViewData;
6913 }
6914 if ($input->getOption('strict') && $hasOutdatedPackages) {
6915 $exitCode = 1;
6916 break;
6917 }
6918 }
6919 }
6920
6921 if ('json' === $format) {
6922 $io->write(JsonFile::encode($viewData));
6923 } else {
6924 foreach ($viewData as $type => $packages) {
6925 $nameLength = $viewMetaData[$type]['nameLength'];
6926 $versionLength = $viewMetaData[$type]['versionLength'];
6927 $latestLength = $viewMetaData[$type]['latestLength'];
6928
6929 $writeVersion = $nameLength + $versionLength + 3 <= $width;
6930 $writeLatest = $nameLength + $versionLength + $latestLength + 3 <= $width;
6931 $writeDescription = $nameLength + $versionLength + $latestLength + 24 <= $width;
6932
6933 if ($writeLatest && !$io->isDecorated()) {
6934 $latestLength += 2;
6935 }
6936
6937 if ($showAllTypes) {
6938 if ('available' === $type) {
6939 $io->write('<comment>' . $type . '</comment>:');
6940 } else {
6941 $io->write('<info>' . $type . '</info>:');
6942 }
6943 }
6944
6945 foreach ($packages as $package) {
6946 $io->write($indent . str_pad($package['name'], $nameLength, ' '), false);
6947 if (isset($package['version']) && $writeVersion) {
6948 $io->write(' ' . str_pad($package['version'], $versionLength, ' '), false);
6949 }
6950 if (isset($package['latest']) && $writeLatest) {
6951 $latestVersion = $package['latest'];
6952 $updateStatus = $package['latest-status'];
6953 $style = $this->updateStatusToVersionStyle($updateStatus);
6954 if (!$io->isDecorated()) {
6955 $latestVersion = str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('=', '!', '~'), $updateStatus) . ' ' . $latestVersion;
6956 }
6957 $io->write(' <' . $style . '>' . str_pad($latestVersion, $latestLength, ' ') . '</' . $style . '>', false);
6958 }
6959 if (isset($package['description']) && $writeDescription) {
6960 $description = strtok($package['description'], "\r\n");
6961 $remaining = $width - $nameLength - $versionLength - 4;
6962 if ($writeLatest) {
6963 $remaining -= $latestLength;
6964 }
6965 if (strlen($description) > $remaining) {
6966 $description = substr($description, 0, $remaining - 3) . '...';
6967 }
6968 $io->write(' ' . $description, false);
6969 }
6970 if (isset($package['path'])) {
6971 $io->write(' ' . $package['path'], false);
6972 }
6973 $io->write('');
6974 if (isset($package['warning'])) {
6975 $io->write('<warning>' . $package['warning'] . '</warning>');
6976 }
6977 }
6978
6979 if ($showAllTypes) {
6980 $io->write('');
6981 }
6982 }
6983 }
6984
6985 return $exitCode;
6986 }
6987
6988 protected function getRootRequires()
6989 {
6990 $rootPackage = $this->getComposer()->getPackage();
6991
6992 return array_map(
6993 'strtolower',
6994 array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))
6995 );
6996 }
6997
6998 protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package)
6999 {
7000 return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package));
7001 }
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013 protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
7014 {
7015 $name = strtolower($name);
7016 $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
7017
7018 $policy = new DefaultPolicy();
7019 $pool = new Pool('dev');
7020 $pool->addRepository($repos);
7021
7022 $matchedPackage = null;
7023 $versions = array();
7024 $matches = $pool->whatProvides($name, $constraint);
7025 foreach ($matches as $index => $package) {
7026
7027  if ($package->getName() !== $name) {
7028 unset($matches[$index]);
7029 continue;
7030 }
7031
7032
7033  if (null === $version && $installedRepo->hasPackage($package)) {
7034 $matchedPackage = $package;
7035 }
7036
7037 $versions[$package->getPrettyVersion()] = $package->getVersion();
7038 $matches[$index] = $package->getId();
7039 }
7040
7041
7042  if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
7043 $matchedPackage = $pool->literalToPackage($preferred[0]);
7044 }
7045
7046 return array($matchedPackage, $versions);
7047 }
7048
7049
7050
7051
7052
7053
7054
7055
7056 protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
7057 {
7058 $io = $this->getIO();
7059 $io->write('<info>name</info>     : ' . $package->getPrettyName());
7060 $io->write('<info>descrip.</info> : ' . $package->getDescription());
7061 $io->write('<info>keywords</info> : ' . implode(', ', $package->getKeywords() ?: array()));
7062 $this->printVersions($package, $versions, $installedRepo);
7063 if ($latestPackage) {
7064 $style = $this->getVersionStyle($latestPackage, $package);
7065 $io->write('<info>latest</info>   : <'.$style.'>' . $latestPackage->getPrettyVersion() . '</'.$style.'>');
7066 } else {
7067 $latestPackage = $package;
7068 }
7069 $io->write('<info>type</info>     : ' . $package->getType());
7070 $this->printLicenses($package);
7071 $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
7072 $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
7073 $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
7074
7075 if ($latestPackage->isAbandoned()) {
7076 $replacement = ($latestPackage->getReplacementPackage() !== null)
7077 ? ' The author suggests using the ' . $latestPackage->getReplacementPackage(). ' package instead.'
7078 : null;
7079
7080 $io->writeError(
7081 sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
7082 );
7083 }
7084
7085 if ($package->getSupport()) {
7086 $io->write("\n<info>support</info>");
7087 foreach ($package->getSupport() as $type => $value) {
7088 $io->write('<comment>' . $type . '</comment> : '.$value);
7089 }
7090 }
7091
7092 if ($package->getAutoload()) {
7093 $io->write("\n<info>autoload</info>");
7094 foreach ($package->getAutoload() as $type => $autoloads) {
7095 $io->write('<comment>' . $type . '</comment>');
7096
7097 if ($type === 'psr-0') {
7098 foreach ($autoloads as $name => $path) {
7099 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7100 }
7101 } elseif ($type === 'psr-4') {
7102 foreach ($autoloads as $name => $path) {
7103 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7104 }
7105 } elseif ($type === 'classmap') {
7106 $io->write(implode(', ', $autoloads));
7107 }
7108 }
7109 if ($package->getIncludePaths()) {
7110 $io->write('<comment>include-path</comment>');
7111 $io->write(implode(', ', $package->getIncludePaths()));
7112 }
7113 }
7114 }
7115
7116
7117
7118
7119
7120
7121
7122
7123 protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
7124 {
7125 uasort($versions, 'version_compare');
7126 $versions = array_keys(array_reverse($versions));
7127
7128
7129  if ($installedRepo->hasPackage($package)) {
7130 $installedVersion = $package->getPrettyVersion();
7131 $key = array_search($installedVersion, $versions);
7132 if (false !== $key) {
7133 $versions[$key] = '<info>* ' . $installedVersion . '</info>';
7134 }
7135 }
7136
7137 $versions = implode(', ', $versions);
7138
7139 $this->getIO()->write('<info>versions</info> : ' . $versions);
7140 }
7141
7142
7143
7144
7145
7146
7147
7148
7149 protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
7150 {
7151 $title = $title ?: $linkType;
7152 $io = $this->getIO();
7153 if ($links = $package->{'get'.ucfirst($linkType)}()) {
7154 $io->write("\n<info>" . $title . "</info>");
7155
7156 foreach ($links as $link) {
7157 $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
7158 }
7159 }
7160 }
7161
7162
7163
7164
7165
7166
7167 protected function printLicenses(CompletePackageInterface $package)
7168 {
7169 $spdxLicenses = new SpdxLicenses();
7170
7171 $licenses = $package->getLicense();
7172 $io = $this->getIO();
7173
7174 foreach ($licenses as $licenseId) {
7175 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
7176
7177 if (!$license) {
7178 $out = $licenseId;
7179 } else {
7180
7181  if ($license[1] === true) {
7182 $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
7183 } else {
7184 $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
7185 }
7186 }
7187
7188 $io->write('<info>license</info>  : ' . $out);
7189 }
7190 }
7191
7192
7193
7194
7195
7196
7197 protected function initStyles(OutputInterface $output)
7198 {
7199 $this->colors = array(
7200 'green',
7201 'yellow',
7202 'cyan',
7203 'magenta',
7204 'blue',
7205 );
7206
7207 foreach ($this->colors as $color) {
7208 $style = new OutputFormatterStyle($color);
7209 $output->getFormatter()->setStyle($color, $style);
7210 }
7211 }
7212
7213
7214
7215
7216
7217
7218
7219
7220 protected function displayPackageTree(PackageInterface $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos)
7221 {
7222 $io = $this->getIO();
7223 $io->write(sprintf('<info>%s</info>', $package->getPrettyName()), false);
7224 $io->write(' ' . $package->getPrettyVersion(), false);
7225 $io->write(' ' . strtok($package->getDescription(), "\r\n"));
7226
7227 if (is_object($package)) {
7228 $requires = $package->getRequires();
7229 $treeBar = '├';
7230 $j = 0;
7231 $total = count($requires);
7232 foreach ($requires as $requireName => $require) {
7233 $j++;
7234 if ($j == 0) {
7235 $this->writeTreeLine($treeBar);
7236 }
7237 if ($j == $total) {
7238 $treeBar = '└';
7239 }
7240 $level = 1;
7241 $color = $this->colors[$level];
7242 $info = sprintf('%s──<%s>%s</%s> %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint());
7243 $this->writeTreeLine($info);
7244
7245 $treeBar = str_replace('└', ' ', $treeBar);
7246 $packagesInTree = array($package->getName(), $requireName);
7247
7248 $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree, $treeBar, $level + 1);
7249 }
7250 }
7251 }
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264 protected function displayTree($name, $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos, array $packagesInTree, $previousTreeBar = '├', $level = 1)
7265 {
7266 $previousTreeBar = str_replace('├', '│', $previousTreeBar);
7267 list($package, $versions) = $this->getPackage($installedRepo, $distantRepos, $name, $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint());
7268 if (is_object($package)) {
7269 $requires = $package->getRequires();
7270 $treeBar = $previousTreeBar . '  ├';
7271 $i = 0;
7272 $total = count($requires);
7273 foreach ($requires as $requireName => $require) {
7274 $currentTree = $packagesInTree;
7275 $i++;
7276 if ($i == $total) {
7277 $treeBar = $previousTreeBar . '  └';
7278 }
7279 $colorIdent = $level % count($this->colors);
7280 $color = $this->colors[$colorIdent];
7281
7282 $circularWarn = in_array($requireName, $currentTree) ? '(circular dependency aborted here)' : '';
7283 $info = rtrim(sprintf('%s──<%s>%s</%s> %s %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint(), $circularWarn));
7284 $this->writeTreeLine($info);
7285
7286 $treeBar = str_replace('└', ' ', $treeBar);
7287 if (!in_array($requireName, $currentTree)) {
7288 $currentTree[] = $requireName;
7289 $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $currentTree, $treeBar, $level + 1);
7290 }
7291 }
7292 }
7293 }
7294
7295 private function updateStatusToVersionStyle($updateStatus)
7296 {
7297
7298  
7299  
7300  return str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('info', 'highlight', 'comment'), $updateStatus);
7301 }
7302
7303 private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package)
7304 {
7305 if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) {
7306 return 'up-to-date';
7307 }
7308
7309 $constraint = $package->getVersion();
7310 if (0 !== strpos($constraint, 'dev-')) {
7311 $constraint = '^'.$constraint;
7312 }
7313 if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) {
7314
7315  return 'semver-safe-update';
7316 }
7317
7318
7319  return 'update-possible';
7320 }
7321
7322 private function writeTreeLine($line)
7323 {
7324 $io = $this->getIO();
7325 if (!$io->isDecorated()) {
7326 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
7327 }
7328
7329 $io->write($line);
7330 }
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342 private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
7343 {
7344
7345  $name = $package->getName();
7346 $versionSelector = new VersionSelector($this->getPool($composer));
7347 $stability = $composer->getPackage()->getMinimumStability();
7348 $flags = $composer->getPackage()->getStabilityFlags();
7349 if (isset($flags[$name])) {
7350 $stability = array_search($flags[$name], BasePackage::$stabilities, true);
7351 }
7352
7353 $bestStability = $stability;
7354 if ($composer->getPackage()->getPreferStable()) {
7355 $bestStability = $package->getStability();
7356 }
7357
7358 $targetVersion = null;
7359 if (0 === strpos($package->getVersion(), 'dev-')) {
7360 $targetVersion = $package->getVersion();
7361 }
7362
7363 if ($targetVersion === null && $minorOnly) {
7364 $targetVersion = '^' . $package->getVersion();
7365 }
7366
7367 return $versionSelector->findBestCandidate($name, $targetVersion, $phpVersion, $bestStability);
7368 }
7369
7370 private function getPool(Composer $composer)
7371 {
7372 if (!$this->pool) {
7373 $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
7374 $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
7375 }
7376
7377 return $this->pool;
7378 }
7379 }
7380 <?php
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392 namespace Composer\Command;
7393
7394 use Symfony\Component\Console\Input\InputInterface;
7395 use Symfony\Component\Console\Input\InputOption;
7396 use Symfony\Component\Console\Output\OutputInterface;
7397 use Composer\Downloader\ChangeReportInterface;
7398 use Composer\Downloader\DvcsDownloaderInterface;
7399 use Composer\Downloader\VcsCapableDownloaderInterface;
7400 use Composer\Package\Dumper\ArrayDumper;
7401 use Composer\Package\Version\VersionGuesser;
7402 use Composer\Package\Version\VersionParser;
7403 use Composer\Plugin\CommandEvent;
7404 use Composer\Plugin\PluginEvents;
7405 use Composer\Script\ScriptEvents;
7406 use Composer\Util\ProcessExecutor;
7407
7408
7409
7410
7411
7412 class StatusCommand extends BaseCommand
7413 {
7414 const EXIT_CODE_ERRORS = 1;
7415 const EXIT_CODE_UNPUSHED_CHANGES = 2;
7416 const EXIT_CODE_VERSION_CHANGES = 4;
7417
7418 protected function configure()
7419 {
7420 $this
7421 ->setName('status')
7422 ->setDescription('Shows a list of locally modified packages.')
7423 ->setDefinition(array(
7424 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
7425 ))
7426 ->setHelp(<<<EOT
7427 The status command displays a list of dependencies that have
7428 been modified locally.
7429
7430 EOT
7431 )
7432 ;
7433 }
7434
7435 protected function execute(InputInterface $input, OutputInterface $output)
7436 {
7437
7438  $composer = $this->getComposer();
7439
7440 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
7441 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7442
7443 $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
7444
7445 $dm = $composer->getDownloadManager();
7446 $im = $composer->getInstallationManager();
7447
7448
7449  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
7450
7451 $errors = array();
7452 $io = $this->getIO();
7453 $unpushedChanges = array();
7454 $vcsVersionChanges = array();
7455
7456 $parser = new VersionParser;
7457 $guesser = new VersionGuesser($composer->getConfig(), new ProcessExecutor($io), $parser);
7458 $dumper = new ArrayDumper;
7459
7460
7461  foreach ($installedRepo->getCanonicalPackages() as $package) {
7462 $downloader = $dm->getDownloaderForInstalledPackage($package);
7463 $targetDir = $im->getInstallPath($package);
7464
7465 if ($downloader instanceof ChangeReportInterface) {
7466 if (is_link($targetDir)) {
7467 $errors[$targetDir] = $targetDir . ' is a symbolic link.';
7468 }
7469
7470 if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
7471 $errors[$targetDir] = $changes;
7472 }
7473 }
7474
7475 if ($downloader instanceof VcsCapableDownloaderInterface) {
7476 if ($currentRef = $downloader->getVcsReference($package, $targetDir)) {
7477 switch ($package->getInstallationSource()) {
7478 case 'source':
7479 $previousRef = $package->getSourceReference();
7480 break;
7481 case 'dist':
7482 $previousRef = $package->getDistReference();
7483 break;
7484 default:
7485 $previousRef = null;
7486 }
7487
7488 $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir);
7489
7490 if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef) {
7491 $vcsVersionChanges[$targetDir] = array(
7492 'previous' => array(
7493 'version' => $package->getPrettyVersion(),
7494 'ref' => $previousRef,
7495 ),
7496 'current' => array(
7497 'version' => $currentVersion['pretty_version'],
7498 'ref' => $currentVersion['commit'],
7499 ),
7500 );
7501 }
7502 }
7503 }
7504
7505 if ($downloader instanceof DvcsDownloaderInterface) {
7506 if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
7507 $unpushedChanges[$targetDir] = $unpushed;
7508 }
7509 }
7510 }
7511
7512
7513  if (!$errors && !$unpushedChanges && !$vcsVersionChanges) {
7514 $io->writeError('<info>No local changes</info>');
7515
7516 return 0;
7517 }
7518
7519 if ($errors) {
7520 $io->writeError('<error>You have changes in the following dependencies:</error>');
7521
7522 foreach ($errors as $path => $changes) {
7523 if ($input->getOption('verbose')) {
7524 $indentedChanges = implode("\n", array_map(function ($line) {
7525 return '    ' . ltrim($line);
7526 }, explode("\n", $changes)));
7527 $io->write('<info>'.$path.'</info>:');
7528 $io->write($indentedChanges);
7529 } else {
7530 $io->write($path);
7531 }
7532 }
7533 }
7534
7535 if ($unpushedChanges) {
7536 $io->writeError('<warning>You have unpushed changes on the current branch in the following dependencies:</warning>');
7537
7538 foreach ($unpushedChanges as $path => $changes) {
7539 if ($input->getOption('verbose')) {
7540 $indentedChanges = implode("\n", array_map(function ($line) {
7541 return '    ' . ltrim($line);
7542 }, explode("\n", $changes)));
7543 $io->write('<info>'.$path.'</info>:');
7544 $io->write($indentedChanges);
7545 } else {
7546 $io->write($path);
7547 }
7548 }
7549 }
7550
7551 if ($vcsVersionChanges) {
7552 $io->writeError('<warning>You have version variations in the following dependencies:</warning>');
7553
7554 foreach ($vcsVersionChanges as $path => $changes) {
7555 if ($input->getOption('verbose')) {
7556
7557  $currentVersion = $changes['current']['version'] ?: $changes['current']['ref'];
7558 $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref'];
7559
7560 if ($io->isVeryVerbose()) {
7561
7562  $currentVersion .= sprintf(' (%s)', $changes['current']['ref']);
7563 $previousVersion .= sprintf(' (%s)', $changes['previous']['ref']);
7564 }
7565
7566 $io->write('<info>'.$path.'</info>:');
7567 $io->write(sprintf('    From <comment>%s</comment> to <comment>%s</comment>', $previousVersion, $currentVersion));
7568 } else {
7569 $io->write($path);
7570 }
7571 }
7572 }
7573
7574 if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) {
7575 $io->writeError('Use --verbose (-v) to see a list of files');
7576 }
7577
7578
7579  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
7580
7581 return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0);
7582 }
7583 }
7584 <?php
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596 namespace Composer\Command;
7597
7598 use Composer\Repository\PlatformRepository;
7599 use Symfony\Component\Console\Input\InputArgument;
7600 use Symfony\Component\Console\Input\InputInterface;
7601 use Symfony\Component\Console\Input\InputOption;
7602 use Symfony\Component\Console\Output\OutputInterface;
7603
7604 class SuggestsCommand extends BaseCommand
7605 {
7606 protected function configure()
7607 {
7608 $this
7609 ->setName('suggests')
7610 ->setDescription('Shows package suggestions.')
7611 ->setDefinition(array(
7612 new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package'),
7613 new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'),
7614 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
7615 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
7616 ))
7617 ->setHelp(<<<EOT
7618
7619 The <info>%command.name%</info> command shows a sorted list of suggested packages.
7620
7621 Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
7622
7623 EOT
7624 )
7625 ;
7626 }
7627
7628 protected function execute(InputInterface $input, OutputInterface $output)
7629 {
7630 $lock = $this->getComposer()->getLocker()->getLockData();
7631
7632 if (empty($lock)) {
7633 throw new \RuntimeException('Lockfile seems to be empty?');
7634 }
7635
7636 $packages = $lock['packages'];
7637
7638 if (!$input->getOption('no-dev')) {
7639 $packages += $lock['packages-dev'];
7640 }
7641
7642 $filter = $input->getArgument('packages');
7643
7644
7645  $installed = array();
7646 foreach ($packages as $package) {
7647 $installed[] = $package['name'];
7648
7649 if (!empty($package['provide'])) {
7650 $installed = array_merge($installed, array_keys($package['provide']));
7651 }
7652
7653 if (!empty($package['replace'])) {
7654 $installed = array_merge($installed, array_keys($package['replace']));
7655 }
7656 }
7657
7658
7659  $installed = array_flip($installed);
7660 ksort($installed);
7661
7662
7663  $platform = new PlatformRepository(array(), $this->getComposer()->getConfig()->get('platform') ?: array());
7664
7665
7666  $suggesters = array();
7667 $suggested = array();
7668 foreach ($packages as $package) {
7669 $packageName = $package['name'];
7670 if ((!empty($filter) && !in_array($packageName, $filter)) || empty($package['suggest'])) {
7671 continue;
7672 }
7673 foreach ($package['suggest'] as $suggestion => $reason) {
7674 if (false === strpos('/', $suggestion) && !is_null($platform->findPackage($suggestion, '*'))) {
7675 continue;
7676 }
7677 if (!isset($installed[$suggestion])) {
7678 $suggesters[$packageName][$suggestion] = $reason;
7679 $suggested[$suggestion][$packageName] = $reason;
7680 }
7681 }
7682 }
7683 ksort($suggesters);
7684 ksort($suggested);
7685
7686
7687  $mode = 0;
7688 $io = $this->getIO();
7689 if ($input->getOption('by-package') || $io->isVerbose()) {
7690 $mode |= 1;
7691 }
7692 if ($input->getOption('by-suggestion')) {
7693 $mode |= 2;
7694 }
7695
7696
7697  if ($mode === 0) {
7698 foreach (array_keys($suggested) as $suggestion) {
7699 $io->write(sprintf('<info>%s</info>', $suggestion));
7700 }
7701
7702 return;
7703 }
7704
7705
7706  if ($mode & 1) {
7707 foreach ($suggesters as $suggester => $suggestions) {
7708 $io->write(sprintf('<comment>%s</comment> suggests:', $suggester));
7709
7710 foreach ($suggestions as $suggestion => $reason) {
7711 $io->write(sprintf(' - <info>%s</info>: %s', $suggestion, $reason ?: '*'));
7712 }
7713 $io->write('');
7714 }
7715 }
7716
7717
7718  if ($mode & 2) {
7719
7720  if ($mode & 1) {
7721 $io->write(str_repeat('-', 78));
7722 }
7723 foreach ($suggested as $suggestion => $suggesters) {
7724 $io->write(sprintf('<comment>%s</comment> is suggested by:', $suggestion));
7725
7726 foreach ($suggesters as $suggester => $reason) {
7727 $io->write(sprintf(' - <info>%s</info>: %s', $suggester, $reason ?: '*'));
7728 }
7729 $io->write('');
7730 }
7731 }
7732 }
7733 }
7734 <?php
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746 namespace Composer\Command;
7747
7748 use Composer\Composer;
7749 use Composer\Installer;
7750 use Composer\IO\IOInterface;
7751 use Composer\Plugin\CommandEvent;
7752 use Composer\Plugin\PluginEvents;
7753 use Symfony\Component\Console\Helper\Table;
7754 use Symfony\Component\Console\Input\InputInterface;
7755 use Symfony\Component\Console\Input\InputOption;
7756 use Symfony\Component\Console\Input\InputArgument;
7757 use Symfony\Component\Console\Output\OutputInterface;
7758 use Symfony\Component\Console\Question\Question;
7759
7760
7761
7762
7763
7764 class UpdateCommand extends BaseCommand
7765 {
7766 protected function configure()
7767 {
7768 $this
7769 ->setName('update')
7770 ->setDescription('Updates your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
7771 ->setDefinition(array(
7772 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
7773 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
7774 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
7775 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
7776 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
7777 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
7778 new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
7779 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
7780 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
7781 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
7782 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
7783 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
7784 new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'),
7785 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
7786 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
7787 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
7788 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
7789 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
7790 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
7791 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
7792 new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
7793 new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
7794 ))
7795 ->setHelp(<<<EOT
7796 The <info>update</info> command reads the composer.json file from the
7797 current directory, processes it, and updates, removes or installs all the
7798 dependencies.
7799
7800 <info>php composer.phar update</info>
7801
7802 To limit the update operation to a few packages, you can list the package(s)
7803 you want to update as such:
7804
7805 <info>php composer.phar update vendor/package1 foo/mypackage [...]</info>
7806
7807 You may also use an asterisk (*) pattern to limit the update operation to package(s)
7808 from a specific vendor:
7809
7810 <info>php composer.phar update vendor/package1 foo/* [...]</info>
7811
7812 To select packages names interactively with auto-completion use <info>-i</info>.
7813
7814 EOT
7815 )
7816 ;
7817 }
7818
7819 protected function execute(InputInterface $input, OutputInterface $output)
7820 {
7821 $io = $this->getIO();
7822 if ($input->getOption('no-custom-installers')) {
7823 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
7824 $input->setOption('no-plugins', true);
7825 }
7826
7827 if ($input->getOption('dev')) {
7828 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
7829 }
7830
7831 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
7832
7833 $packages = $input->getArgument('packages');
7834
7835 if ($input->getOption('interactive')) {
7836 $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
7837 }
7838
7839 if ($input->getOption('root-reqs')) {
7840 $require = array_keys($composer->getPackage()->getRequires());
7841 if (!$input->getOption('no-dev')) {
7842 $requireDev = array_keys($composer->getPackage()->getDevRequires());
7843 $require = array_merge($require, $requireDev);
7844 }
7845
7846 if (!empty($packages)) {
7847 $packages = array_intersect($packages, $require);
7848 } else {
7849 $packages = $require;
7850 }
7851 }
7852
7853 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
7854
7855 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
7856 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7857
7858 $install = Installer::create($io, $composer);
7859
7860 $config = $composer->getConfig();
7861 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
7862
7863 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
7864 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
7865 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
7866
7867 $install
7868 ->setDryRun($input->getOption('dry-run'))
7869 ->setVerbose($input->getOption('verbose'))
7870 ->setPreferSource($preferSource)
7871 ->setPreferDist($preferDist)
7872 ->setDevMode(!$input->getOption('no-dev'))
7873 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
7874 ->setRunScripts(!$input->getOption('no-scripts'))
7875 ->setSkipSuggest($input->getOption('no-suggest'))
7876 ->setOptimizeAutoloader($optimize)
7877 ->setClassMapAuthoritative($authoritative)
7878 ->setApcuAutoloader($apcu)
7879 ->setUpdate(true)
7880 ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages)
7881 ->setWhitelistDependencies($input->getOption('with-dependencies'))
7882 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
7883 ->setPreferStable($input->getOption('prefer-stable'))
7884 ->setPreferLowest($input->getOption('prefer-lowest'))
7885 ;
7886
7887 if ($input->getOption('no-plugins')) {
7888 $install->disablePlugins();
7889 }
7890
7891 return $install->run();
7892 }
7893
7894 private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages)
7895 {
7896 if (!$input->isInteractive()) {
7897 throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
7898 }
7899
7900 $requires = array_merge(
7901 $composer->getPackage()->getRequires(),
7902 $composer->getPackage()->getDevRequires()
7903 );
7904 $autocompleterValues = array();
7905 foreach ($requires as $require) {
7906 $autocompleterValues[strtolower($require->getTarget())] = $require->getTarget();
7907 }
7908
7909 $installedPackages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
7910 foreach ($installedPackages as $package) {
7911 $autocompleterValues[$package->getName()] = $package->getPrettyName();
7912 }
7913
7914 $helper = $this->getHelper('question');
7915 $question = new Question('<comment>Enter package name: </comment>', null);
7916
7917 $io->writeError('<info>Press enter without value to end submission</info>');
7918
7919 do {
7920 $autocompleterValues = array_diff($autocompleterValues, $packages);
7921 $question->setAutocompleterValues($autocompleterValues);
7922 $addedPackage = $helper->ask($input, $output, $question);
7923
7924 if (!is_string($addedPackage) || empty($addedPackage)) {
7925 break;
7926 }
7927
7928 $addedPackage = strtolower($addedPackage);
7929 if (!in_array($addedPackage, $packages)) {
7930 $packages[] = $addedPackage;
7931 }
7932 } while (true);
7933
7934 $packages = array_filter($packages);
7935 if (!$packages) {
7936 throw new \InvalidArgumentException('You must enter minimum one package.');
7937 }
7938
7939 $table = new Table($output);
7940 $table->setHeaders(array('Selected packages'));
7941 foreach ($packages as $package) {
7942 $table->addRow(array($package));
7943 }
7944 $table->render();
7945
7946 if ($io->askConfirmation(sprintf(
7947 'Would you like to continue and update the above package%s [<comment>yes</comment>]? ',
7948 1 === count($packages) ? '' : 's'
7949 ), true)) {
7950 return $packages;
7951 }
7952
7953 throw new \RuntimeException('Installation aborted.');
7954 }
7955 }
7956 <?php
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968 namespace Composer\Command;
7969
7970 use Composer\Factory;
7971 use Composer\Package\Loader\ValidatingArrayLoader;
7972 use Composer\Plugin\CommandEvent;
7973 use Composer\Plugin\PluginEvents;
7974 use Composer\Util\ConfigValidator;
7975 use Symfony\Component\Console\Input\InputArgument;
7976 use Symfony\Component\Console\Input\InputInterface;
7977 use Symfony\Component\Console\Input\InputOption;
7978 use Symfony\Component\Console\Output\OutputInterface;
7979
7980
7981
7982
7983
7984
7985
7986 class ValidateCommand extends BaseCommand
7987 {
7988
7989
7990
7991 protected function configure()
7992 {
7993 $this
7994 ->setName('validate')
7995 ->setDescription('Validates a composer.json and composer.lock.')
7996 ->setDefinition(array(
7997 new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'),
7998 new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
7999 new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
8000 new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
8001 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
8002 new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json'),
8003 ))
8004 ->setHelp(<<<EOT
8005 The validate command validates a given composer.json and composer.lock
8006
8007 Exit codes in case of errors are:
8008 1 validation warning(s), only when --strict is given
8009 2 validation error(s)
8010 3 file unreadable or missing
8011
8012 EOT
8013 );
8014 }
8015
8016
8017
8018
8019
8020
8021
8022 protected function execute(InputInterface $input, OutputInterface $output)
8023 {
8024 $file = $input->getArgument('file');
8025 $io = $this->getIO();
8026
8027 if (!file_exists($file)) {
8028 $io->writeError('<error>' . $file . ' not found.</error>');
8029
8030 return 3;
8031 }
8032 if (!is_readable($file)) {
8033 $io->writeError('<error>' . $file . ' is not readable.</error>');
8034
8035 return 3;
8036 }
8037
8038 $validator = new ConfigValidator($io);
8039 $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
8040 $checkPublish = !$input->getOption('no-check-publish');
8041 $checkLock = !$input->getOption('no-check-lock');
8042 $isStrict = $input->getOption('strict');
8043 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8044
8045 $lockErrors = array();
8046 $composer = Factory::create($io, $file);
8047 $locker = $composer->getLocker();
8048 if ($locker->isLocked() && !$locker->isFresh()) {
8049 $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update`.';
8050 }
8051
8052 $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true);
8053
8054 $exitCode = $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 2 : ($isStrict && $warnings ? 1 : 0);
8055
8056 if ($input->getOption('with-dependencies')) {
8057 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
8058 foreach ($localRepo->getPackages() as $package) {
8059 $path = $composer->getInstallationManager()->getInstallPath($package);
8060 $file = $path . '/composer.json';
8061 if (is_dir($path) && file_exists($file)) {
8062 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8063 $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
8064
8065 $depCode = $errors || ($publishErrors && $checkPublish) ? 2 : ($isStrict && $warnings ? 1 : 0);
8066 $exitCode = max($depCode, $exitCode);
8067 }
8068 }
8069 }
8070
8071 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
8072 $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8073 $exitCode = max($eventCode, $exitCode);
8074
8075 return $exitCode;
8076 }
8077
8078 private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false)
8079 {
8080 if (!$errors && !$publishErrors && !$warnings) {
8081 $io->write('<info>' . $name . ' is valid</info>');
8082 } elseif (!$errors && !$publishErrors) {
8083 $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
8084 if ($printSchemaUrl) {
8085 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8086 }
8087 } elseif (!$errors) {
8088 $io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
8089 $io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
8090 if ($printSchemaUrl) {
8091 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8092 }
8093 } else {
8094 $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
8095 }
8096
8097
8098  if ($checkPublish) {
8099 $errors = array_merge($errors, $publishErrors);
8100 } else {
8101 $warnings = array_merge($warnings, $publishErrors);
8102 }
8103
8104
8105  if ($checkLock) {
8106 $errors = array_merge($errors, $lockErrors);
8107 } else {
8108 $warnings = array_merge($warnings, $lockErrors);
8109 }
8110
8111 $messages = array(
8112 'error' => $errors,
8113 'warning' => $warnings,
8114 );
8115
8116 foreach ($messages as $style => $msgs) {
8117 foreach ($msgs as $msg) {
8118 $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
8119 }
8120 }
8121 }
8122 }
8123 <?php
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135 namespace Composer;
8136
8137 use Composer\Package\RootPackageInterface;
8138 use Composer\Package\Locker;
8139 use Composer\Repository\RepositoryManager;
8140 use Composer\Installer\InstallationManager;
8141 use Composer\Plugin\PluginManager;
8142 use Composer\Downloader\DownloadManager;
8143 use Composer\EventDispatcher\EventDispatcher;
8144 use Composer\Autoload\AutoloadGenerator;
8145 use Composer\Package\Archiver\ArchiveManager;
8146
8147
8148
8149
8150
8151
8152 class Composer
8153 {
8154 const VERSION = '1.5.1';
8155 const BRANCH_ALIAS_VERSION = '';
8156 const RELEASE_DATE = '2017-08-09 16:07:22';
8157
8158
8159
8160
8161 private $package;
8162
8163
8164
8165
8166 private $locker;
8167
8168
8169
8170
8171 private $repositoryManager;
8172
8173
8174
8175
8176 private $downloadManager;
8177
8178
8179
8180
8181 private $installationManager;
8182
8183
8184
8185
8186 private $pluginManager;
8187
8188
8189
8190
8191 private $config;
8192
8193
8194
8195
8196 private $eventDispatcher;
8197
8198
8199
8200
8201 private $autoloadGenerator;
8202
8203
8204
8205
8206 private $archiveManager;
8207
8208
8209
8210
8211
8212 public function setPackage(RootPackageInterface $package)
8213 {
8214 $this->package = $package;
8215 }
8216
8217
8218
8219
8220 public function getPackage()
8221 {
8222 return $this->package;
8223 }
8224
8225
8226
8227
8228 public function setConfig(Config $config)
8229 {
8230 $this->config = $config;
8231 }
8232
8233
8234
8235
8236 public function getConfig()
8237 {
8238 return $this->config;
8239 }
8240
8241
8242
8243
8244 public function setLocker(Locker $locker)
8245 {
8246 $this->locker = $locker;
8247 }
8248
8249
8250
8251
8252 public function getLocker()
8253 {
8254 return $this->locker;
8255 }
8256
8257
8258
8259
8260 public function setRepositoryManager(RepositoryManager $manager)
8261 {
8262 $this->repositoryManager = $manager;
8263 }
8264
8265
8266
8267
8268 public function getRepositoryManager()
8269 {
8270 return $this->repositoryManager;
8271 }
8272
8273
8274
8275
8276 public function setDownloadManager(DownloadManager $manager)
8277 {
8278 $this->downloadManager = $manager;
8279 }
8280
8281
8282
8283
8284 public function getDownloadManager()
8285 {
8286 return $this->downloadManager;
8287 }
8288
8289
8290
8291
8292 public function setArchiveManager(ArchiveManager $manager)
8293 {
8294 $this->archiveManager = $manager;
8295 }
8296
8297
8298
8299
8300 public function getArchiveManager()
8301 {
8302 return $this->archiveManager;
8303 }
8304
8305
8306
8307
8308 public function setInstallationManager(InstallationManager $manager)
8309 {
8310 $this->installationManager = $manager;
8311 }
8312
8313
8314
8315
8316 public function getInstallationManager()
8317 {
8318 return $this->installationManager;
8319 }
8320
8321
8322
8323
8324 public function setPluginManager(PluginManager $manager)
8325 {
8326 $this->pluginManager = $manager;
8327 }
8328
8329
8330
8331
8332 public function getPluginManager()
8333 {
8334 return $this->pluginManager;
8335 }
8336
8337
8338
8339
8340 public function setEventDispatcher(EventDispatcher $eventDispatcher)
8341 {
8342 $this->eventDispatcher = $eventDispatcher;
8343 }
8344
8345
8346
8347
8348 public function getEventDispatcher()
8349 {
8350 return $this->eventDispatcher;
8351 }
8352
8353
8354
8355
8356 public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
8357 {
8358 $this->autoloadGenerator = $autoloadGenerator;
8359 }
8360
8361
8362
8363
8364 public function getAutoloadGenerator()
8365 {
8366 return $this->autoloadGenerator;
8367 }
8368 }
8369 <?php
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381 namespace Composer;
8382
8383 use Composer\Config\ConfigSourceInterface;
8384 use Composer\Downloader\TransportException;
8385 use Composer\IO\IOInterface;
8386 use Composer\Util\Platform;
8387
8388
8389
8390
8391 class Config
8392 {
8393 const RELATIVE_PATHS = 1;
8394
8395 public static $defaultConfig = array(
8396 'process-timeout' => 300,
8397 'use-include-path' => false,
8398 'preferred-install' => 'auto',
8399 'notify-on-install' => true,
8400 'github-protocols' => array('https', 'ssh', 'git'),
8401 'vendor-dir' => 'vendor',
8402 'bin-dir' => '{$vendor-dir}/bin',
8403 'cache-dir' => '{$home}/cache',
8404 'data-dir' => '{$home}',
8405 'cache-files-dir' => '{$cache-dir}/files',
8406 'cache-repo-dir' => '{$cache-dir}/repo',
8407 'cache-vcs-dir' => '{$cache-dir}/vcs',
8408 'cache-ttl' => 15552000, 
8409  'cache-files-ttl' => null, 
8410  'cache-files-maxsize' => '300MiB',
8411 'bin-compat' => 'auto',
8412 'discard-changes' => false,
8413 'autoloader-suffix' => null,
8414 'sort-packages' => false,
8415 'optimize-autoloader' => false,
8416 'classmap-authoritative' => false,
8417 'apcu-autoloader' => false,
8418 'prepend-autoloader' => true,
8419 'github-domains' => array('github.com'),
8420 'bitbucket-expose-hostname' => true,
8421 'disable-tls' => false,
8422 'secure-http' => true,
8423 'cafile' => null,
8424 'capath' => null,
8425 'github-expose-hostname' => true,
8426 'gitlab-domains' => array('gitlab.com'),
8427 'store-auths' => 'prompt',
8428 'platform' => array(),
8429 'archive-format' => 'tar',
8430 'archive-dir' => '.',
8431 'htaccess-protect' => true,
8432
8433  
8434  
8435  
8436  
8437  
8438  );
8439
8440 public static $defaultRepositories = array(
8441 'packagist.org' => array(
8442 'type' => 'composer',
8443 'url' => 'https?://packagist.org',
8444 'allow_ssl_downgrade' => true,
8445 ),
8446 );
8447
8448 private $config;
8449 private $baseDir;
8450 private $repositories;
8451
8452 private $configSource;
8453
8454 private $authConfigSource;
8455 private $useEnvironment;
8456 private $warnedHosts = array();
8457
8458
8459
8460
8461
8462 public function __construct($useEnvironment = true, $baseDir = null)
8463 {
8464
8465  $this->config = static::$defaultConfig;
8466 $this->repositories = static::$defaultRepositories;
8467 $this->useEnvironment = (bool) $useEnvironment;
8468 $this->baseDir = $baseDir;
8469 }
8470
8471 public function setConfigSource(ConfigSourceInterface $source)
8472 {
8473 $this->configSource = $source;
8474 }
8475
8476 public function getConfigSource()
8477 {
8478 return $this->configSource;
8479 }
8480
8481 public function setAuthConfigSource(ConfigSourceInterface $source)
8482 {
8483 $this->authConfigSource = $source;
8484 }
8485
8486 public function getAuthConfigSource()
8487 {
8488 return $this->authConfigSource;
8489 }
8490
8491
8492
8493
8494
8495
8496 public function merge($config)
8497 {
8498
8499  if (!empty($config['config']) && is_array($config['config'])) {
8500 foreach ($config['config'] as $key => $val) {
8501 if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic')) && isset($this->config[$key])) {
8502 $this->config[$key] = array_merge($this->config[$key], $val);
8503 } elseif ('preferred-install' === $key && isset($this->config[$key])) {
8504 if (is_array($val) || is_array($this->config[$key])) {
8505 if (is_string($val)) {
8506 $val = array('*' => $val);
8507 }
8508 if (is_string($this->config[$key])) {
8509 $this->config[$key] = array('*' => $this->config[$key]);
8510 }
8511 $this->config[$key] = array_merge($this->config[$key], $val);
8512
8513  if (isset($this->config[$key]['*'])) {
8514 $wildcard = $this->config[$key]['*'];
8515 unset($this->config[$key]['*']);
8516 $this->config[$key]['*'] = $wildcard;
8517 }
8518 } else {
8519 $this->config[$key] = $val;
8520 }
8521 } else {
8522 $this->config[$key] = $val;
8523 }
8524 }
8525 }
8526
8527 if (!empty($config['repositories']) && is_array($config['repositories'])) {
8528 $this->repositories = array_reverse($this->repositories, true);
8529 $newRepos = array_reverse($config['repositories'], true);
8530 foreach ($newRepos as $name => $repository) {
8531
8532  if (false === $repository) {
8533 $this->disableRepoByName($name);
8534 continue;
8535 }
8536
8537
8538  if (is_array($repository) && 1 === count($repository) && false === current($repository)) {
8539 $this->disableRepoByName(key($repository));
8540 continue;
8541 }
8542
8543
8544  if (is_int($name)) {
8545 $this->repositories[] = $repository;
8546 } else {
8547 if ($name === 'packagist') { 
8548  $this->repositories[$name . '.org'] = $repository;
8549 } else {
8550 $this->repositories[$name] = $repository;
8551 }
8552 }
8553 }
8554 $this->repositories = array_reverse($this->repositories, true);
8555 }
8556 }
8557
8558
8559
8560
8561 public function getRepositories()
8562 {
8563 return $this->repositories;
8564 }
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574 public function get($key, $flags = 0)
8575 {
8576 switch ($key) {
8577 case 'vendor-dir':
8578 case 'bin-dir':
8579 case 'process-timeout':
8580 case 'data-dir':
8581 case 'cache-dir':
8582 case 'cache-files-dir':
8583 case 'cache-repo-dir':
8584 case 'cache-vcs-dir':
8585 case 'cafile':
8586 case 'capath':
8587 case 'htaccess-protect':
8588
8589  $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
8590
8591 $val = $this->getComposerEnv($env);
8592 $val = rtrim((string) $this->process(false !== $val ? $val : $this->config[$key], $flags), '/\\');
8593 $val = Platform::expandPath($val);
8594
8595 if (substr($key, -4) !== '-dir') {
8596 return $val;
8597 }
8598
8599 return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
8600
8601 case 'cache-ttl':
8602 return (int) $this->config[$key];
8603
8604 case 'cache-files-maxsize':
8605 if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
8606 throw new \RuntimeException(
8607 "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
8608 );
8609 }
8610 $size = $matches[1];
8611 if (isset($matches[2])) {
8612 switch (strtolower($matches[2])) {
8613 case 'g':
8614 $size *= 1024;
8615
8616  case 'm':
8617 $size *= 1024;
8618
8619  case 'k':
8620 $size *= 1024;
8621 break;
8622 }
8623 }
8624
8625 return $size;
8626
8627 case 'cache-files-ttl':
8628 if (isset($this->config[$key])) {
8629 return (int) $this->config[$key];
8630 }
8631
8632 return (int) $this->config['cache-ttl'];
8633
8634 case 'home':
8635 $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $this->config[$key]);
8636
8637 return rtrim($this->process($val, $flags), '/\\');
8638
8639 case 'bin-compat':
8640 $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
8641
8642 if (!in_array($value, array('auto', 'full'))) {
8643 throw new \RuntimeException(
8644 "Invalid value for 'bin-compat': {$value}. Expected auto, full"
8645 );
8646 }
8647
8648 return $value;
8649
8650 case 'discard-changes':
8651 if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
8652 if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
8653 throw new \RuntimeException(
8654 "Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"
8655 );
8656 }
8657 if ('stash' === $env) {
8658 return 'stash';
8659 }
8660
8661
8662  return $env !== 'false' && (bool) $env;
8663 }
8664
8665 if (!in_array($this->config[$key], array(true, false, 'stash'), true)) {
8666 throw new \RuntimeException(
8667 "Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"
8668 );
8669 }
8670
8671 return $this->config[$key];
8672
8673 case 'github-protocols':
8674 $protos = $this->config['github-protocols'];
8675 if ($this->config['secure-http'] && false !== ($index = array_search('git', $protos))) {
8676 unset($protos[$index]);
8677 }
8678 if (reset($protos) === 'http') {
8679 throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
8680 }
8681
8682 return $protos;
8683
8684 case 'disable-tls':
8685 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
8686
8687 case 'secure-http':
8688 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
8689
8690 default:
8691 if (!isset($this->config[$key])) {
8692 return null;
8693 }
8694
8695 return $this->process($this->config[$key], $flags);
8696 }
8697 }
8698
8699 public function all($flags = 0)
8700 {
8701 $all = array(
8702 'repositories' => $this->getRepositories(),
8703 );
8704 foreach (array_keys($this->config) as $key) {
8705 $all['config'][$key] = $this->get($key, $flags);
8706 }
8707
8708 return $all;
8709 }
8710
8711 public function raw()
8712 {
8713 return array(
8714 'repositories' => $this->getRepositories(),
8715 'config' => $this->config,
8716 );
8717 }
8718
8719
8720
8721
8722
8723
8724
8725 public function has($key)
8726 {
8727 return array_key_exists($key, $this->config);
8728 }
8729
8730
8731
8732
8733
8734
8735
8736
8737 private function process($value, $flags)
8738 {
8739 $config = $this;
8740
8741 if (!is_string($value)) {
8742 return $value;
8743 }
8744
8745 return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
8746 return $config->get($match[1], $flags);
8747 }, $value);
8748 }
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758 private function realpath($path)
8759 {
8760 if (preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) {
8761 return $path;
8762 }
8763
8764 return $this->baseDir . '/' . $path;
8765 }
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776 private function getComposerEnv($var)
8777 {
8778 if ($this->useEnvironment) {
8779 return getenv($var);
8780 }
8781
8782 return false;
8783 }
8784
8785 private function disableRepoByName($name)
8786 {
8787 if (isset($this->repositories[$name])) {
8788 unset($this->repositories[$name]);
8789 } elseif ($name === 'packagist') { 
8790  unset($this->repositories['packagist.org']);
8791 }
8792 }
8793
8794
8795
8796
8797
8798
8799
8800 public function prohibitUrlByConfig($url, IOInterface $io = null)
8801 {
8802
8803  if (false === filter_var($url, FILTER_VALIDATE_URL)) {
8804 return;
8805 }
8806
8807
8808  $scheme = parse_url($url, PHP_URL_SCHEME);
8809 if (in_array($scheme, array('http', 'git', 'ftp', 'svn'))) {
8810 if ($this->get('secure-http')) {
8811 throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
8812 } elseif ($io) {
8813 $host = parse_url($url, PHP_URL_HOST);
8814 if (!isset($this->warnedHosts[$host])) {
8815 $io->writeError("<warning>Warning: Accessing $host over $scheme which is an insecure protocol.</warning>");
8816 }
8817 $this->warnedHosts[$host] = true;
8818 }
8819 }
8820 }
8821 }
8822 <?php
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834 namespace Composer\Config;
8835
8836
8837
8838
8839
8840
8841
8842 interface ConfigSourceInterface
8843 {
8844
8845
8846
8847
8848
8849
8850 public function addRepository($name, $config);
8851
8852
8853
8854
8855
8856
8857 public function removeRepository($name);
8858
8859
8860
8861
8862
8863
8864
8865 public function addConfigSetting($name, $value);
8866
8867
8868
8869
8870
8871
8872 public function removeConfigSetting($name);
8873
8874
8875
8876
8877
8878
8879
8880 public function addProperty($name, $value);
8881
8882
8883
8884
8885
8886
8887 public function removeProperty($name);
8888
8889
8890
8891
8892
8893
8894
8895
8896 public function addLink($type, $name, $value);
8897
8898
8899
8900
8901
8902
8903
8904 public function removeLink($type, $name);
8905
8906
8907
8908
8909
8910
8911 public function getName();
8912 }
8913 <?php
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925 namespace Composer\Config;
8926
8927 use Composer\Json\JsonFile;
8928 use Composer\Json\JsonManipulator;
8929 use Composer\Util\Silencer;
8930
8931
8932
8933
8934
8935
8936
8937 class JsonConfigSource implements ConfigSourceInterface
8938 {
8939
8940
8941
8942 private $file;
8943
8944
8945
8946
8947 private $authConfig;
8948
8949
8950
8951
8952
8953
8954
8955 public function __construct(JsonFile $file, $authConfig = false)
8956 {
8957 $this->file = $file;
8958 $this->authConfig = $authConfig;
8959 }
8960
8961
8962
8963
8964 public function getName()
8965 {
8966 return $this->file->getPath();
8967 }
8968
8969
8970
8971
8972 public function addRepository($name, $config)
8973 {
8974 $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
8975
8976  
8977  if (isset($config['repositories'])) {
8978 foreach ($config['repositories'] as $index => $val) {
8979 if ($index === $repo) {
8980 continue;
8981 }
8982 if (is_numeric($index) && ($val === array('packagist' => false) || $val === array('packagist.org' => false))) {
8983 unset($config['repositories'][$index]);
8984 $config['repositories']['packagist.org'] = false;
8985 break;
8986 }
8987 }
8988 }
8989
8990 $config['repositories'][$repo] = $repoConfig;
8991 });
8992 }
8993
8994
8995
8996
8997 public function removeRepository($name)
8998 {
8999 $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
9000 unset($config['repositories'][$repo]);
9001 });
9002 }
9003
9004
9005
9006
9007 public function addConfigSetting($name, $value)
9008 {
9009 $authConfig = $this->authConfig;
9010 $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) {
9011 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9012 list($key, $host) = explode('.', $key, 2);
9013 if ($authConfig) {
9014 $config[$key][$host] = $val;
9015 } else {
9016 $config['config'][$key][$host] = $val;
9017 }
9018 } else {
9019 $config['config'][$key] = $val;
9020 }
9021 });
9022 }
9023
9024
9025
9026
9027 public function removeConfigSetting($name)
9028 {
9029 $authConfig = $this->authConfig;
9030 $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) {
9031 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9032 list($key, $host) = explode('.', $key, 2);
9033 if ($authConfig) {
9034 unset($config[$key][$host]);
9035 } else {
9036 unset($config['config'][$key][$host]);
9037 }
9038 } else {
9039 unset($config['config'][$key]);
9040 }
9041 });
9042 }
9043
9044
9045
9046
9047 public function addProperty($name, $value)
9048 {
9049 $this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) {
9050 if (substr($key, 0, 6) === 'extra.') {
9051 $bits = explode('.', $key);
9052 $last = array_pop($bits);
9053 $arr = &$config['extra'];
9054 foreach ($bits as $bit) {
9055 if (!isset($arr[$bit])) {
9056 $arr[$bit] = array();
9057 }
9058 $arr = &$arr[$bit];
9059 }
9060 $arr[$last] = $val;
9061 } else {
9062 $config[$key] = $val;
9063 }
9064 });
9065 }
9066
9067
9068
9069
9070 public function removeProperty($name)
9071 {
9072 $authConfig = $this->authConfig;
9073 $this->manipulateJson('removeProperty', $name, function (&$config, $key) {
9074 if (substr($key, 0, 6) === 'extra.') {
9075 $bits = explode('.', $key);
9076 $last = array_pop($bits);
9077 $arr = &$config['extra'];
9078 foreach ($bits as $bit) {
9079 if (!isset($arr[$bit])) {
9080 return;
9081 }
9082 $arr = &$arr[$bit];
9083 }
9084 unset($arr[$last]);
9085 } else {
9086 unset($config[$key]);
9087 }
9088 });
9089 }
9090
9091
9092
9093
9094 public function addLink($type, $name, $value)
9095 {
9096 $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
9097 $config[$type][$name] = $value;
9098 });
9099 }
9100
9101
9102
9103
9104 public function removeLink($type, $name)
9105 {
9106 $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
9107 unset($config[$type][$name]);
9108 });
9109 }
9110
9111 protected function manipulateJson($method, $args, $fallback)
9112 {
9113 $args = func_get_args();
9114
9115  array_shift($args);
9116 $fallback = array_pop($args);
9117
9118 if ($this->file->exists()) {
9119 if (!is_writable($this->file->getPath())) {
9120 throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
9121 }
9122
9123 if (!is_readable($this->file->getPath())) {
9124 throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
9125 }
9126
9127 $contents = file_get_contents($this->file->getPath());
9128 } elseif ($this->authConfig) {
9129 $contents = "{\n}\n";
9130 } else {
9131 $contents = "{\n    \"config\": {\n    }\n}\n";
9132 }
9133
9134 $manipulator = new JsonManipulator($contents);
9135
9136 $newFile = !$this->file->exists();
9137
9138
9139  if ($this->authConfig && $method === 'addConfigSetting') {
9140 $method = 'addSubNode';
9141 list($mainNode, $name) = explode('.', $args[0], 2);
9142 $args = array($mainNode, $name, $args[1]);
9143 } elseif ($this->authConfig && $method === 'removeConfigSetting') {
9144 $method = 'removeSubNode';
9145 list($mainNode, $name) = explode('.', $args[0], 2);
9146 $args = array($mainNode, $name);
9147 }
9148
9149
9150  if (call_user_func_array(array($manipulator, $method), $args)) {
9151 file_put_contents($this->file->getPath(), $manipulator->getContents());
9152 } else {
9153
9154  $config = $this->file->read();
9155 $this->arrayUnshiftRef($args, $config);
9156 call_user_func_array($fallback, $args);
9157 $this->file->write($config);
9158 }
9159
9160 if ($newFile) {
9161 Silencer::call('chmod', $this->file->getPath(), 0600);
9162 }
9163 }
9164
9165
9166
9167
9168
9169
9170
9171
9172 private function arrayUnshiftRef(&$array, &$value)
9173 {
9174 $return = array_unshift($array, '');
9175 $array[0] = &$value;
9176
9177 return $return;
9178 }
9179 }
9180 <?php
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
9191
9192 namespace Composer\Console;
9193
9194 use Composer\Util\Platform;
9195 use Composer\Util\Silencer;
9196 use Symfony\Component\Console\Application as BaseApplication;
9197 use Symfony\Component\Console\Input\InputInterface;
9198 use Symfony\Component\Console\Input\InputOption;
9199 use Symfony\Component\Console\Output\OutputInterface;
9200 use Composer\Command;
9201 use Composer\Composer;
9202 use Composer\Factory;
9203 use Composer\IO\IOInterface;
9204 use Composer\IO\ConsoleIO;
9205 use Composer\Json\JsonValidationException;
9206 use Composer\Util\ErrorHandler;
9207 use Composer\EventDispatcher\ScriptExecutionException;
9208 use Composer\Exception\NoSslException;
9209
9210
9211
9212
9213
9214
9215
9216
9217 class Application extends BaseApplication
9218 {
9219
9220
9221
9222 protected $composer;
9223
9224
9225
9226
9227 protected $io;
9228
9229 private static $logo = '   ______
9230   / ____/___  ____ ___  ____  ____  ________  _____
9231  / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
9232 / /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
9233 \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
9234                     /_/
9235 ';
9236
9237 private $hasPluginCommands = false;
9238 private $disablePluginsByDefault = false;
9239
9240 public function __construct()
9241 {
9242 static $shutdownRegistered = false;
9243
9244 if (function_exists('ini_set') && extension_loaded('xdebug')) {
9245 ini_set('xdebug.show_exception_trace', false);
9246 ini_set('xdebug.scream', false);
9247 }
9248
9249 if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
9250 date_default_timezone_set(Silencer::call('date_default_timezone_get'));
9251 }
9252
9253 if (!$shutdownRegistered) {
9254 $shutdownRegistered = true;
9255
9256 register_shutdown_function(function () {
9257 $lastError = error_get_last();
9258
9259 if ($lastError && $lastError['message'] &&
9260 (strpos($lastError['message'], 'Allowed memory') !== false  ||
9261 strpos($lastError['message'], 'exceeded memory') !== false )) {
9262 echo "\n". 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
9263 }
9264 });
9265 }
9266
9267 parent::__construct('Composer', Composer::VERSION);
9268 }
9269
9270
9271
9272
9273 public function run(InputInterface $input = null, OutputInterface $output = null)
9274 {
9275 if (null === $output) {
9276 $output = Factory::createOutput();
9277 }
9278
9279 return parent::run($input, $output);
9280 }
9281
9282
9283
9284
9285 public function doRun(InputInterface $input, OutputInterface $output)
9286 {
9287 $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
9288
9289 $io = $this->io = new ConsoleIO($input, $output, $this->getHelperSet());
9290 ErrorHandler::register($io);
9291
9292
9293  if ($newWorkDir = $this->getNewWorkingDir($input)) {
9294 $oldWorkingDir = getcwd();
9295 chdir($newWorkDir);
9296 $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
9297 }
9298
9299
9300  $commandName = '';
9301 if ($name = $this->getCommandName($input)) {
9302 try {
9303 $commandName = $this->find($name)->getName();
9304 } catch (\InvalidArgumentException $e) {
9305 }
9306 }
9307
9308
9309  if ($io->isInteractive() && !in_array($commandName, array('init', 'about', 'help', 'diagnose', 'self-update', 'global'), true) && !file_exists(Factory::getComposerFile())) {
9310 $dir = dirname(getcwd());
9311 $home = realpath(getenv('HOME') ?: getenv('USERPROFILE') ?: '/');
9312
9313
9314  while (dirname($dir) !== $dir && $dir !== $home) {
9315 if (file_exists($dir.'/'.Factory::getComposerFile())) {
9316 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)) {
9317 $oldWorkingDir = getcwd();
9318 chdir($dir);
9319 }
9320 break;
9321 }
9322 $dir = dirname($dir);
9323 }
9324 }
9325
9326 if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
9327 try {
9328 foreach ($this->getPluginCommands() as $command) {
9329 if ($this->has($command->getName())) {
9330 $io->writeError('<warning>Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped</warning>');
9331 } else {
9332 $this->add($command);
9333 }
9334 }
9335 } catch (NoSslException $e) {
9336
9337  }
9338
9339 $this->hasPluginCommands = true;
9340 }
9341
9342
9343  $isProxyCommand = false;
9344 if ($name = $this->getCommandName($input)) {
9345 try {
9346 $command = $this->find($name);
9347 $commandName = $command->getName();
9348 $isProxyCommand = ($command instanceof Command\BaseCommand && $command->isProxyCommand());
9349 } catch (\InvalidArgumentException $e) {
9350 }
9351 }
9352
9353 if (!$isProxyCommand) {
9354 $io->writeError(sprintf(
9355 'Running %s (%s) with %s on %s',
9356 Composer::VERSION,
9357 Composer::RELEASE_DATE,
9358 defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
9359 function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
9360 ), true, IOInterface::DEBUG);
9361
9362 if (PHP_VERSION_ID < 50302) {
9363 $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>');
9364 }
9365
9366 if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
9367 $io->writeError('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
9368 }
9369
9370 if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
9371 $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']));
9372 }
9373
9374 if (getenv('COMPOSER_NO_INTERACTION')) {
9375 $input->setInteractive(false);
9376 }
9377
9378 if (!Platform::isWindows() && function_exists('exec') && !getenv('COMPOSER_ALLOW_SUPERUSER')) {
9379 if (function_exists('posix_getuid') && posix_getuid() === 0) {
9380 if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
9381 $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
9382 }
9383 if ($uid = (int) getenv('SUDO_UID')) {
9384
9385  
9386  Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
9387 }
9388 }
9389
9390  Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
9391 }
9392
9393
9394  Silencer::call(function () use ($io) {
9395 $tempfile = sys_get_temp_dir() . '/temp-' . md5(microtime());
9396 if (!(file_put_contents($tempfile, __FILE__) && (file_get_contents($tempfile) == __FILE__) && unlink($tempfile) && !file_exists($tempfile))) {
9397 $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()));
9398 }
9399 });
9400
9401
9402  $file = Factory::getComposerFile();
9403 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
9404 if (isset($composer['scripts']) && is_array($composer['scripts'])) {
9405 foreach ($composer['scripts'] as $script => $dummy) {
9406 if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
9407 if ($this->has($script)) {
9408 $io->writeError('<warning>A script named '.$script.' would override a Composer command and has been skipped</warning>');
9409 } else {
9410 $this->add(new Command\ScriptAliasCommand($script));
9411 }
9412 }
9413 }
9414 }
9415 }
9416 }
9417
9418 try {
9419 if ($input->hasParameterOption('--profile')) {
9420 $startTime = microtime(true);
9421 $this->io->enableDebugging($startTime);
9422 }
9423
9424 $result = parent::doRun($input, $output);
9425
9426 if (isset($oldWorkingDir)) {
9427 chdir($oldWorkingDir);
9428 }
9429
9430 if (isset($startTime)) {
9431 $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');
9432 }
9433
9434 restore_error_handler();
9435
9436 return $result;
9437 } catch (ScriptExecutionException $e) {
9438 return $e->getCode();
9439 } catch (\Exception $e) {
9440 $this->hintCommonErrors($e);
9441 restore_error_handler();
9442 throw $e;
9443 }
9444 }
9445
9446
9447
9448
9449
9450
9451 private function getNewWorkingDir(InputInterface $input)
9452 {
9453 $workingDir = $input->getParameterOption(array('--working-dir', '-d'));
9454 if (false !== $workingDir && !is_dir($workingDir)) {
9455 throw new \RuntimeException('Invalid working directory specified, '.$workingDir.' does not exist.');
9456 }
9457
9458 return $workingDir;
9459 }
9460
9461
9462
9463
9464 private function hintCommonErrors($exception)
9465 {
9466 $io = $this->getIO();
9467
9468 Silencer::suppress();
9469 try {
9470 $composer = $this->getComposer(false, true);
9471 if ($composer) {
9472 $config = $composer->getConfig();
9473
9474 $minSpaceFree = 1024 * 1024;
9475 if ((($df = disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
9476 || (($df = disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
9477 || (($df = disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
9478 ) {
9479 $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>', true, IOInterface::QUIET);
9480 }
9481 }
9482 } catch (\Exception $e) {
9483 }
9484 Silencer::restore();
9485
9486 if (Platform::isWindows() && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
9487 $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', true, IOInterface::QUIET);
9488 $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);
9489 }
9490
9491 if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
9492 $io->writeError('<error>The following exception is caused by a lack of memory or swap, or not having swap configured</error>', true, IOInterface::QUIET);
9493 $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
9494 }
9495 }
9496
9497
9498
9499
9500
9501
9502
9503 public function getComposer($required = true, $disablePlugins = null)
9504 {
9505 if (null === $disablePlugins) {
9506 $disablePlugins = $this->disablePluginsByDefault;
9507 }
9508
9509 if (null === $this->composer) {
9510 try {
9511 $this->composer = Factory::create($this->io, null, $disablePlugins);
9512 } catch (\InvalidArgumentException $e) {
9513 if ($required) {
9514 $this->io->writeError($e->getMessage());
9515 exit(1);
9516 }
9517 } catch (JsonValidationException $e) {
9518 $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
9519 $message = $e->getMessage() . ':' . PHP_EOL . $errors;
9520 throw new JsonValidationException($message);
9521 }
9522 }
9523
9524 return $this->composer;
9525 }
9526
9527
9528
9529
9530 public function resetComposer()
9531 {
9532 $this->composer = null;
9533 }
9534
9535
9536
9537
9538 public function getIO()
9539 {
9540 return $this->io;
9541 }
9542
9543 public function getHelp()
9544 {
9545 return self::$logo . parent::getHelp();
9546 }
9547
9548
9549
9550
9551 protected function getDefaultCommands()
9552 {
9553 $commands = array_merge(parent::getDefaultCommands(), array(
9554 new Command\AboutCommand(),
9555 new Command\ConfigCommand(),
9556 new Command\DependsCommand(),
9557 new Command\ProhibitsCommand(),
9558 new Command\InitCommand(),
9559 new Command\InstallCommand(),
9560 new Command\CreateProjectCommand(),
9561 new Command\UpdateCommand(),
9562 new Command\SearchCommand(),
9563 new Command\ValidateCommand(),
9564 new Command\ShowCommand(),
9565 new Command\SuggestsCommand(),
9566 new Command\RequireCommand(),
9567 new Command\DumpAutoloadCommand(),
9568 new Command\StatusCommand(),
9569 new Command\ArchiveCommand(),
9570 new Command\DiagnoseCommand(),
9571 new Command\RunScriptCommand(),
9572 new Command\LicensesCommand(),
9573 new Command\GlobalCommand(),
9574 new Command\ClearCacheCommand(),
9575 new Command\RemoveCommand(),
9576 new Command\HomeCommand(),
9577 new Command\ExecCommand(),
9578 new Command\OutdatedCommand(),
9579 ));
9580
9581 if ('phar:' === substr(__FILE__, 0, 5)) {
9582 $commands[] = new Command\SelfUpdateCommand();
9583 }
9584
9585 return $commands;
9586 }
9587
9588
9589
9590
9591 public function getLongVersion()
9592 {
9593 if (Composer::BRANCH_ALIAS_VERSION) {
9594 return sprintf(
9595 '<info>%s</info> version <comment>%s (%s)</comment> %s',
9596 $this->getName(),
9597 Composer::BRANCH_ALIAS_VERSION,
9598 $this->getVersion(),
9599 Composer::RELEASE_DATE
9600 );
9601 }
9602
9603 return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE;
9604 }
9605
9606
9607
9608
9609 protected function getDefaultInputDefinition()
9610 {
9611 $definition = parent::getDefaultInputDefinition();
9612 $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
9613 $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'));
9614 $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
9615
9616 return $definition;
9617 }
9618
9619 private function getPluginCommands()
9620 {
9621 $commands = array();
9622
9623 $composer = $this->getComposer(false, false);
9624 if (null === $composer) {
9625 $composer = Factory::createGlobal($this->io, false);
9626 }
9627
9628 if (null !== $composer) {
9629 $pm = $composer->getPluginManager();
9630 foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $composer, 'io' => $this->io)) as $capability) {
9631 $newCommands = $capability->getCommands();
9632 if (!is_array($newCommands)) {
9633 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands');
9634 }
9635 foreach ($newCommands as $command) {
9636 if (!$command instanceof Command\BaseCommand) {
9637 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects');
9638 }
9639 }
9640 $commands = array_merge($commands, $newCommands);
9641 }
9642 }
9643
9644 return $commands;
9645 }
9646 }
9647 <?php
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659 namespace Composer\Console;
9660
9661 use Symfony\Component\Console\Formatter\OutputFormatter;
9662
9663
9664
9665
9666 class HtmlOutputFormatter extends OutputFormatter
9667 {
9668 private static $availableForegroundColors = array(
9669 30 => 'black',
9670 31 => 'red',
9671 32 => 'green',
9672 33 => 'yellow',
9673 34 => 'blue',
9674 35 => 'magenta',
9675 36 => 'cyan',
9676 37 => 'white',
9677 );
9678 private static $availableBackgroundColors = array(
9679 40 => 'black',
9680 41 => 'red',
9681 42 => 'green',
9682 43 => 'yellow',
9683 44 => 'blue',
9684 45 => 'magenta',
9685 46 => 'cyan',
9686 47 => 'white',
9687 );
9688 private static $availableOptions = array(
9689 1 => 'bold',
9690 4 => 'underscore',
9691
9692  
9693  
9694  );
9695
9696
9697
9698
9699 public function __construct(array $styles = array())
9700 {
9701 parent::__construct(true, $styles);
9702 }
9703
9704 public function format($message)
9705 {
9706 $formatted = parent::format($message);
9707
9708 $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
9709
9710 return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted);
9711 }
9712
9713 private function formatHtml($matches)
9714 {
9715 $out = '<span style="';
9716 foreach (explode(';', $matches[1]) as $code) {
9717 if (isset(self::$availableForegroundColors[$code])) {
9718 $out .= 'color:'.self::$availableForegroundColors[$code].';';
9719 } elseif (isset(self::$availableBackgroundColors[$code])) {
9720 $out .= 'background-color:'.self::$availableBackgroundColors[$code].';';
9721 } elseif (isset(self::$availableOptions[$code])) {
9722 switch (self::$availableOptions[$code]) {
9723 case 'bold':
9724 $out .= 'font-weight:bold;';
9725 break;
9726
9727 case 'underscore':
9728 $out .= 'text-decoration:underline;';
9729 break;
9730 }
9731 }
9732 }
9733
9734 return $out.'">'.$matches[2].'</span>';
9735 }
9736 }
9737 <?php
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749 namespace Composer\DependencyResolver;
9750
9751
9752
9753
9754
9755
9756 class Decisions implements \Iterator, \Countable
9757 {
9758 const DECISION_LITERAL = 0;
9759 const DECISION_REASON = 1;
9760
9761 protected $pool;
9762 protected $decisionMap;
9763 protected $decisionQueue = array();
9764
9765 public function __construct($pool)
9766 {
9767 $this->pool = $pool;
9768 $this->decisionMap = array();
9769 }
9770
9771 public function decide($literal, $level, $why)
9772 {
9773 $this->addDecision($literal, $level);
9774 $this->decisionQueue[] = array(
9775 self::DECISION_LITERAL => $literal,
9776 self::DECISION_REASON => $why,
9777 );
9778 }
9779
9780 public function satisfy($literal)
9781 {
9782 $packageId = abs($literal);
9783
9784 return (
9785 $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 ||
9786 $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0
9787 );
9788 }
9789
9790 public function conflict($literal)
9791 {
9792 $packageId = abs($literal);
9793
9794 return (
9795 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0) ||
9796 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0)
9797 );
9798 }
9799
9800 public function decided($literalOrPackageId)
9801 {
9802 return !empty($this->decisionMap[abs($literalOrPackageId)]);
9803 }
9804
9805 public function undecided($literalOrPackageId)
9806 {
9807 return empty($this->decisionMap[abs($literalOrPackageId)]);
9808 }
9809
9810 public function decidedInstall($literalOrPackageId)
9811 {
9812 $packageId = abs($literalOrPackageId);
9813
9814 return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
9815 }
9816
9817 public function decisionLevel($literalOrPackageId)
9818 {
9819 $packageId = abs($literalOrPackageId);
9820 if (isset($this->decisionMap[$packageId])) {
9821 return abs($this->decisionMap[$packageId]);
9822 }
9823
9824 return 0;
9825 }
9826
9827 public function decisionRule($literalOrPackageId)
9828 {
9829 $packageId = abs($literalOrPackageId);
9830
9831 foreach ($this->decisionQueue as $i => $decision) {
9832 if ($packageId === abs($decision[self::DECISION_LITERAL])) {
9833 return $decision[self::DECISION_REASON];
9834 }
9835 }
9836
9837 return null;
9838 }
9839
9840 public function atOffset($queueOffset)
9841 {
9842 return $this->decisionQueue[$queueOffset];
9843 }
9844
9845 public function validOffset($queueOffset)
9846 {
9847 return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
9848 }
9849
9850 public function lastReason()
9851 {
9852 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
9853 }
9854
9855 public function lastLiteral()
9856 {
9857 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
9858 }
9859
9860 public function reset()
9861 {
9862 while ($decision = array_pop($this->decisionQueue)) {
9863 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
9864 }
9865 }
9866
9867 public function resetToOffset($offset)
9868 {
9869 while (count($this->decisionQueue) > $offset + 1) {
9870 $decision = array_pop($this->decisionQueue);
9871 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
9872 }
9873 }
9874
9875 public function revertLast()
9876 {
9877 $this->decisionMap[abs($this->lastLiteral())] = 0;
9878 array_pop($this->decisionQueue);
9879 }
9880
9881 public function count()
9882 {
9883 return count($this->decisionQueue);
9884 }
9885
9886 public function rewind()
9887 {
9888 end($this->decisionQueue);
9889 }
9890
9891 public function current()
9892 {
9893 return current($this->decisionQueue);
9894 }
9895
9896 public function key()
9897 {
9898 return key($this->decisionQueue);
9899 }
9900
9901 public function next()
9902 {
9903 return prev($this->decisionQueue);
9904 }
9905
9906 public function valid()
9907 {
9908 return false !== current($this->decisionQueue);
9909 }
9910
9911 public function isEmpty()
9912 {
9913 return count($this->decisionQueue) === 0;
9914 }
9915
9916 protected function addDecision($literal, $level)
9917 {
9918 $packageId = abs($literal);
9919
9920 $previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
9921 if ($previousDecision != 0) {
9922 $literalString = $this->pool->literalToString($literal);
9923 $package = $this->pool->literalToPackage($literal);
9924 throw new SolverBugException(
9925 "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
9926 );
9927 }
9928
9929 if ($literal > 0) {
9930 $this->decisionMap[$packageId] = $level;
9931 } else {
9932 $this->decisionMap[$packageId] = -$level;
9933 }
9934 }
9935 }
9936 <?php
9937
9938
9939
9940
9941
9942
9943
9944
9945
9946
9947
9948 namespace Composer\DependencyResolver;
9949
9950 use Composer\Package\PackageInterface;
9951 use Composer\Package\AliasPackage;
9952 use Composer\Package\BasePackage;
9953 use Composer\Semver\Constraint\Constraint;
9954
9955
9956
9957
9958
9959 class DefaultPolicy implements PolicyInterface
9960 {
9961 private $preferStable;
9962 private $preferLowest;
9963
9964 public function __construct($preferStable = false, $preferLowest = false)
9965 {
9966 $this->preferStable = $preferStable;
9967 $this->preferLowest = $preferLowest;
9968 }
9969
9970 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
9971 {
9972 if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
9973 return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
9974 }
9975
9976 $constraint = new Constraint($operator, $b->getVersion());
9977 $version = new Constraint('==', $a->getVersion());
9978
9979 return $constraint->matchSpecific($version, true);
9980 }
9981
9982 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
9983 {
9984 $packages = array();
9985
9986 foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
9987 if ($candidate !== $package) {
9988 $packages[] = $candidate;
9989 }
9990 }
9991
9992 return $packages;
9993 }
9994
9995 public function getPriority(Pool $pool, PackageInterface $package)
9996 {
9997 return $pool->getPriority($package->getRepository());
9998 }
9999
10000 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
10001 {
10002 $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
10003
10004 foreach ($packages as &$literals) {
10005 $policy = $this;
10006 usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10007 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
10008 });
10009 }
10010
10011 foreach ($packages as &$literals) {
10012 $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
10013
10014 $literals = $this->pruneToBestVersion($pool, $literals);
10015
10016 $literals = $this->pruneRemoteAliases($pool, $literals);
10017 }
10018
10019 $selected = call_user_func_array('array_merge', $packages);
10020
10021
10022  usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10023 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
10024 });
10025
10026 return $selected;
10027 }
10028
10029 protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
10030 {
10031 $packages = array();
10032 foreach ($literals as $literal) {
10033 $packageName = $pool->literalToPackage($literal)->getName();
10034
10035 if (!isset($packages[$packageName])) {
10036 $packages[$packageName] = array();
10037 }
10038
10039 if (isset($installedMap[abs($literal)])) {
10040 array_unshift($packages[$packageName], $literal);
10041 } else {
10042 $packages[$packageName][] = $literal;
10043 }
10044 }
10045
10046 return $packages;
10047 }
10048
10049
10050
10051
10052 public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
10053 {
10054 if ($a->getRepository() === $b->getRepository()) {
10055
10056  if ($a->getName() === $b->getName()) {
10057 $aAliased = $a instanceof AliasPackage;
10058 $bAliased = $b instanceof AliasPackage;
10059 if ($aAliased && !$bAliased) {
10060 return -1; 
10061  }
10062 if (!$aAliased && $bAliased) {
10063 return 1; 
10064  }
10065 }
10066
10067 if (!$ignoreReplace) {
10068
10069  if ($this->replaces($a, $b)) {
10070 return 1; 
10071  }
10072 if ($this->replaces($b, $a)) {
10073 return -1; 
10074  }
10075
10076
10077  
10078  if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
10079 $requiredVendor = substr($requiredPackage, 0, $pos);
10080
10081 $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
10082 $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
10083
10084 if ($bIsSameVendor !== $aIsSameVendor) {
10085 return $aIsSameVendor ? -1 : 1;
10086 }
10087 }
10088 }
10089
10090
10091  if ($a->id === $b->id) {
10092 return 0;
10093 }
10094
10095 return ($a->id < $b->id) ? -1 : 1;
10096 }
10097
10098 if (isset($installedMap[$a->id])) {
10099 return -1;
10100 }
10101
10102 if (isset($installedMap[$b->id])) {
10103 return 1;
10104 }
10105
10106 return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
10107 }
10108
10109
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119 protected function replaces(PackageInterface $source, PackageInterface $target)
10120 {
10121 foreach ($source->getReplaces() as $link) {
10122 if ($link->getTarget() === $target->getName()
10123
10124
10125  ) {
10126 return true;
10127 }
10128 }
10129
10130 return false;
10131 }
10132
10133 protected function pruneToBestVersion(Pool $pool, $literals)
10134 {
10135 $operator = $this->preferLowest ? '<' : '>';
10136 $bestLiterals = array($literals[0]);
10137 $bestPackage = $pool->literalToPackage($literals[0]);
10138 foreach ($literals as $i => $literal) {
10139 if (0 === $i) {
10140 continue;
10141 }
10142
10143 $package = $pool->literalToPackage($literal);
10144
10145 if ($this->versionCompare($package, $bestPackage, $operator)) {
10146 $bestPackage = $package;
10147 $bestLiterals = array($literal);
10148 } elseif ($this->versionCompare($package, $bestPackage, '==')) {
10149 $bestLiterals[] = $literal;
10150 }
10151 }
10152
10153 return $bestLiterals;
10154 }
10155
10156
10157
10158
10159 protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
10160 {
10161 $selected = array();
10162
10163 $priority = null;
10164
10165 foreach ($literals as $literal) {
10166 $package = $pool->literalToPackage($literal);
10167
10168 if (isset($installedMap[$package->id])) {
10169 $selected[] = $literal;
10170 continue;
10171 }
10172
10173 if (null === $priority) {
10174 $priority = $this->getPriority($pool, $package);
10175 }
10176
10177 if ($this->getPriority($pool, $package) != $priority) {
10178 break;
10179 }
10180
10181 $selected[] = $literal;
10182 }
10183
10184 return $selected;
10185 }
10186
10187
10188
10189
10190
10191
10192 protected function pruneRemoteAliases(Pool $pool, array $literals)
10193 {
10194 $hasLocalAlias = false;
10195
10196 foreach ($literals as $literal) {
10197 $package = $pool->literalToPackage($literal);
10198
10199 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10200 $hasLocalAlias = true;
10201 break;
10202 }
10203 }
10204
10205 if (!$hasLocalAlias) {
10206 return $literals;
10207 }
10208
10209 $selected = array();
10210 foreach ($literals as $literal) {
10211 $package = $pool->literalToPackage($literal);
10212
10213 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10214 $selected[] = $literal;
10215 }
10216 }
10217
10218 return $selected;
10219 }
10220 }
10221 <?php
10222
10223
10224
10225
10226
10227
10228
10229
10230
10231
10232
10233 namespace Composer\DependencyResolver;
10234
10235 use Composer\Package\PackageInterface;
10236 use Composer\Package\Link;
10237
10238
10239
10240
10241 class GenericRule extends Rule
10242 {
10243 protected $literals;
10244
10245
10246
10247
10248
10249
10250
10251 public function __construct(array $literals, $reason, $reasonData, $job = null)
10252 {
10253 parent::__construct($reason, $reasonData, $job);
10254
10255
10256  sort($literals);
10257
10258 $this->literals = $literals;
10259 }
10260
10261 public function getLiterals()
10262 {
10263 return $this->literals;
10264 }
10265
10266 public function getHash()
10267 {
10268 $data = unpack('ihash', md5(implode(',', $this->literals), true));
10269
10270 return $data['hash'];
10271 }
10272
10273
10274
10275
10276
10277
10278
10279
10280
10281 public function equals(Rule $rule)
10282 {
10283 return $this->literals === $rule->getLiterals();
10284 }
10285
10286 public function isAssertion()
10287 {
10288 return 1 === count($this->literals);
10289 }
10290
10291
10292
10293
10294
10295
10296 public function __toString()
10297 {
10298 $result = ($this->isDisabled()) ? 'disabled(' : '(';
10299
10300 foreach ($this->literals as $i => $literal) {
10301 if ($i != 0) {
10302 $result .= '|';
10303 }
10304 $result .= $literal;
10305 }
10306
10307 $result .= ')';
10308
10309 return $result;
10310 }
10311 }
10312 <?php
10313
10314
10315
10316
10317
10318
10319
10320
10321
10322
10323
10324 namespace Composer\DependencyResolver\Operation;
10325
10326 use Composer\Package\PackageInterface;
10327
10328
10329
10330
10331
10332
10333 class InstallOperation extends SolverOperation
10334 {
10335 protected $package;
10336
10337
10338
10339
10340
10341
10342
10343 public function __construct(PackageInterface $package, $reason = null)
10344 {
10345 parent::__construct($reason);
10346
10347 $this->package = $package;
10348 }
10349
10350
10351
10352
10353
10354
10355 public function getPackage()
10356 {
10357 return $this->package;
10358 }
10359
10360
10361
10362
10363
10364
10365 public function getJobType()
10366 {
10367 return 'install';
10368 }
10369
10370
10371
10372
10373 public function __toString()
10374 {
10375 return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
10376 }
10377 }
10378 <?php
10379
10380
10381
10382
10383
10384
10385
10386
10387
10388
10389
10390 namespace Composer\DependencyResolver\Operation;
10391
10392 use Composer\Package\AliasPackage;
10393 use Composer\Package\PackageInterface;
10394
10395
10396
10397
10398
10399
10400 class MarkAliasInstalledOperation extends SolverOperation
10401 {
10402 protected $package;
10403
10404
10405
10406
10407
10408
10409
10410 public function __construct(AliasPackage $package, $reason = null)
10411 {
10412 parent::__construct($reason);
10413
10414 $this->package = $package;
10415 }
10416
10417
10418
10419
10420
10421
10422 public function getPackage()
10423 {
10424 return $this->package;
10425 }
10426
10427
10428
10429
10430
10431
10432 public function getJobType()
10433 {
10434 return 'markAliasInstalled';
10435 }
10436
10437
10438
10439
10440 public function __toString()
10441 {
10442 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
10443 }
10444 }
10445 <?php
10446
10447
10448
10449
10450
10451
10452
10453
10454
10455
10456
10457 namespace Composer\DependencyResolver\Operation;
10458
10459 use Composer\Package\AliasPackage;
10460 use Composer\Package\PackageInterface;
10461
10462
10463
10464
10465
10466
10467 class MarkAliasUninstalledOperation extends SolverOperation
10468 {
10469 protected $package;
10470
10471
10472
10473
10474
10475
10476
10477 public function __construct(AliasPackage $package, $reason = null)
10478 {
10479 parent::__construct($reason);
10480
10481 $this->package = $package;
10482 }
10483
10484
10485
10486
10487
10488
10489 public function getPackage()
10490 {
10491 return $this->package;
10492 }
10493
10494
10495
10496
10497
10498
10499 public function getJobType()
10500 {
10501 return 'markAliasUninstalled';
10502 }
10503
10504
10505
10506
10507 public function __toString()
10508 {
10509 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
10510 }
10511 }
10512 <?php
10513
10514
10515
10516
10517
10518
10519
10520
10521
10522
10523
10524 namespace Composer\DependencyResolver\Operation;
10525
10526
10527
10528
10529
10530
10531 interface OperationInterface
10532 {
10533
10534
10535
10536
10537
10538 public function getJobType();
10539
10540
10541
10542
10543
10544
10545 public function getReason();
10546
10547
10548
10549
10550
10551
10552 public function __toString();
10553 }
10554 <?php
10555
10556
10557
10558
10559
10560
10561
10562
10563
10564
10565
10566 namespace Composer\DependencyResolver\Operation;
10567
10568 use Composer\Package\PackageInterface;
10569
10570
10571
10572
10573
10574
10575 abstract class SolverOperation implements OperationInterface
10576 {
10577 protected $reason;
10578
10579
10580
10581
10582
10583
10584 public function __construct($reason = null)
10585 {
10586 $this->reason = $reason;
10587 }
10588
10589
10590
10591
10592
10593
10594 public function getReason()
10595 {
10596 return $this->reason;
10597 }
10598
10599 protected function formatVersion(PackageInterface $package)
10600 {
10601 return $package->getFullPrettyVersion();
10602 }
10603 }
10604 <?php
10605
10606
10607
10608
10609
10610
10611
10612
10613
10614
10615
10616 namespace Composer\DependencyResolver\Operation;
10617
10618 use Composer\Package\PackageInterface;
10619
10620
10621
10622
10623
10624
10625 class UninstallOperation extends SolverOperation
10626 {
10627 protected $package;
10628
10629
10630
10631
10632
10633
10634
10635 public function __construct(PackageInterface $package, $reason = null)
10636 {
10637 parent::__construct($reason);
10638
10639 $this->package = $package;
10640 }
10641
10642
10643
10644
10645
10646
10647 public function getPackage()
10648 {
10649 return $this->package;
10650 }
10651
10652
10653
10654
10655
10656
10657 public function getJobType()
10658 {
10659 return 'uninstall';
10660 }
10661
10662
10663
10664
10665 public function __toString()
10666 {
10667 return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
10668 }
10669 }
10670 <?php
10671
10672
10673
10674
10675
10676
10677
10678
10679
10680
10681
10682 namespace Composer\DependencyResolver\Operation;
10683
10684 use Composer\Package\PackageInterface;
10685
10686
10687
10688
10689
10690
10691 class UpdateOperation extends SolverOperation
10692 {
10693 protected $initialPackage;
10694 protected $targetPackage;
10695
10696
10697
10698
10699
10700
10701
10702
10703 public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
10704 {
10705 parent::__construct($reason);
10706
10707 $this->initialPackage = $initial;
10708 $this->targetPackage = $target;
10709 }
10710
10711
10712
10713
10714
10715
10716 public function getInitialPackage()
10717 {
10718 return $this->initialPackage;
10719 }
10720
10721
10722
10723
10724
10725
10726 public function getTargetPackage()
10727 {
10728 return $this->targetPackage;
10729 }
10730
10731
10732
10733
10734
10735
10736 public function getJobType()
10737 {
10738 return 'update';
10739 }
10740
10741
10742
10743
10744 public function __toString()
10745 {
10746 return 'Updating '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
10747 $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
10748 }
10749 }
10750 <?php
10751
10752
10753
10754
10755
10756
10757
10758
10759
10760
10761
10762 namespace Composer\DependencyResolver;
10763
10764 use Composer\Package\PackageInterface;
10765
10766
10767
10768
10769 interface PolicyInterface
10770 {
10771 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
10772
10773 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
10774
10775 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null);
10776 }
10777 <?php
10778
10779
10780
10781
10782
10783
10784
10785
10786
10787
10788
10789 namespace Composer\DependencyResolver;
10790
10791 use Composer\Package\BasePackage;
10792 use Composer\Package\AliasPackage;
10793 use Composer\Package\Version\VersionParser;
10794 use Composer\Semver\Constraint\ConstraintInterface;
10795 use Composer\Semver\Constraint\Constraint;
10796 use Composer\Semver\Constraint\EmptyConstraint;
10797 use Composer\Repository\RepositoryInterface;
10798 use Composer\Repository\CompositeRepository;
10799 use Composer\Repository\ComposerRepository;
10800 use Composer\Repository\InstalledRepositoryInterface;
10801 use Composer\Repository\PlatformRepository;
10802 use Composer\Package\PackageInterface;
10803
10804
10805
10806
10807
10808
10809
10810 class Pool implements \Countable
10811 {
10812 const MATCH_NAME = -1;
10813 const MATCH_NONE = 0;
10814 const MATCH = 1;
10815 const MATCH_PROVIDE = 2;
10816 const MATCH_REPLACE = 3;
10817 const MATCH_FILTERED = 4;
10818
10819 protected $repositories = array();
10820 protected $providerRepos = array();
10821 protected $packages = array();
10822 protected $packageByName = array();
10823 protected $packageByExactName = array();
10824 protected $acceptableStabilities;
10825 protected $stabilityFlags;
10826 protected $versionParser;
10827 protected $providerCache = array();
10828 protected $filterRequires;
10829 protected $whitelist = null;
10830 protected $id = 1;
10831
10832 public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
10833 {
10834 $this->versionParser = new VersionParser;
10835 $this->acceptableStabilities = array();
10836 foreach (BasePackage::$stabilities as $stability => $value) {
10837 if ($value <= BasePackage::$stabilities[$minimumStability]) {
10838 $this->acceptableStabilities[$stability] = $value;
10839 }
10840 }
10841 $this->stabilityFlags = $stabilityFlags;
10842 $this->filterRequires = $filterRequires;
10843 foreach ($filterRequires as $name => $constraint) {
10844 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
10845 unset($this->filterRequires[$name]);
10846 }
10847 }
10848 }
10849
10850 public function setWhitelist($whitelist)
10851 {
10852 $this->whitelist = $whitelist;
10853 $this->providerCache = array();
10854 }
10855
10856
10857
10858
10859
10860
10861
10862 public function addRepository(RepositoryInterface $repo, $rootAliases = array())
10863 {
10864 if ($repo instanceof CompositeRepository) {
10865 $repos = $repo->getRepositories();
10866 } else {
10867 $repos = array($repo);
10868 }
10869
10870 foreach ($repos as $repo) {
10871 $this->repositories[] = $repo;
10872
10873 $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
10874
10875 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
10876 $this->providerRepos[] = $repo;
10877 $repo->setRootAliases($rootAliases);
10878 $repo->resetPackageIds();
10879 } else {
10880 foreach ($repo->getPackages() as $package) {
10881 $names = $package->getNames();
10882 $stability = $package->getStability();
10883 if ($exempt || $this->isPackageAcceptable($names, $stability)) {
10884 $package->setId($this->id++);
10885 $this->packages[] = $package;
10886 $this->packageByExactName[$package->getName()][$package->id] = $package;
10887
10888 foreach ($names as $provided) {
10889 $this->packageByName[$provided][] = $package;
10890 }
10891
10892
10893  $name = $package->getName();
10894 if (isset($rootAliases[$name][$package->getVersion()])) {
10895 $alias = $rootAliases[$name][$package->getVersion()];
10896 if ($package instanceof AliasPackage) {
10897 $package = $package->getAliasOf();
10898 }
10899 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
10900 $aliasPackage->setRootPackageAlias(true);
10901 $aliasPackage->setId($this->id++);
10902
10903 $package->getRepository()->addPackage($aliasPackage);
10904 $this->packages[] = $aliasPackage;
10905 $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
10906
10907 foreach ($aliasPackage->getNames() as $name) {
10908 $this->packageByName[$name][] = $aliasPackage;
10909 }
10910 }
10911 }
10912 }
10913 }
10914 }
10915 }
10916
10917 public function getPriority(RepositoryInterface $repo)
10918 {
10919 $priority = array_search($repo, $this->repositories, true);
10920
10921 if (false === $priority) {
10922 throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
10923 }
10924
10925 return -$priority;
10926 }
10927
10928
10929
10930
10931
10932
10933
10934 public function packageById($id)
10935 {
10936 return $this->packages[$id - 1];
10937 }
10938
10939
10940
10941
10942 public function count()
10943 {
10944 return count($this->packages);
10945 }
10946
10947
10948
10949
10950
10951
10952
10953
10954
10955
10956
10957
10958 public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
10959 {
10960 if ($bypassFilters) {
10961 return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
10962 }
10963
10964 $key = ((int) $mustMatchName).$constraint;
10965 if (isset($this->providerCache[$name][$key])) {
10966 return $this->providerCache[$name][$key];
10967 }
10968
10969 return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
10970 }
10971
10972
10973
10974
10975 private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
10976 {
10977 $candidates = array();
10978
10979 foreach ($this->providerRepos as $repo) {
10980 foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
10981 $candidates[] = $candidate;
10982 if ($candidate->id < 1) {
10983 $candidate->setId($this->id++);
10984 $this->packages[$this->id - 2] = $candidate;
10985 }
10986 }
10987 }
10988
10989 if ($mustMatchName) {
10990 $candidates = array_filter($candidates, function ($candidate) use ($name) {
10991 return $candidate->getName() == $name;
10992 });
10993 if (isset($this->packageByExactName[$name])) {
10994 $candidates = array_merge($candidates, $this->packageByExactName[$name]);
10995 }
10996 } elseif (isset($this->packageByName[$name])) {
10997 $candidates = array_merge($candidates, $this->packageByName[$name]);
10998 }
10999
11000 $matches = $provideMatches = array();
11001 $nameMatch = false;
11002
11003 foreach ($candidates as $candidate) {
11004 $aliasOfCandidate = null;
11005
11006
11007  
11008  if ($candidate instanceof AliasPackage) {
11009 $aliasOfCandidate = $candidate->getAliasOf();
11010 }
11011
11012 if ($this->whitelist !== null && !$bypassFilters && (
11013 (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
11014 ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
11015 )) {
11016 continue;
11017 }
11018 switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
11019 case self::MATCH_NONE:
11020 break;
11021
11022 case self::MATCH_NAME:
11023 $nameMatch = true;
11024 break;
11025
11026 case self::MATCH:
11027 $nameMatch = true;
11028 $matches[] = $candidate;
11029 break;
11030
11031 case self::MATCH_PROVIDE:
11032 $provideMatches[] = $candidate;
11033 break;
11034
11035 case self::MATCH_REPLACE:
11036 $matches[] = $candidate;
11037 break;
11038
11039 case self::MATCH_FILTERED:
11040 break;
11041
11042 default:
11043 throw new \UnexpectedValueException('Unexpected match type');
11044 }
11045 }
11046
11047
11048  if ($nameMatch) {
11049 return $matches;
11050 }
11051
11052 return array_merge($matches, $provideMatches);
11053 }
11054
11055 public function literalToPackage($literal)
11056 {
11057 $packageId = abs($literal);
11058
11059 return $this->packageById($packageId);
11060 }
11061
11062 public function literalToPrettyString($literal, $installedMap)
11063 {
11064 $package = $this->literalToPackage($literal);
11065
11066 if (isset($installedMap[$package->id])) {
11067 $prefix = ($literal > 0 ? 'keep' : 'remove');
11068 } else {
11069 $prefix = ($literal > 0 ? 'install' : 'don\'t install');
11070 }
11071
11072 return $prefix.' '.$package->getPrettyString();
11073 }
11074
11075 public function isPackageAcceptable($name, $stability)
11076 {
11077 foreach ((array) $name as $n) {
11078
11079  if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
11080 return true;
11081 }
11082
11083
11084  if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
11085 return true;
11086 }
11087 }
11088
11089 return false;
11090 }
11091
11092
11093
11094
11095
11096
11097
11098
11099
11100
11101 private function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
11102 {
11103 $candidateName = $candidate->getName();
11104 $candidateVersion = $candidate->getVersion();
11105 $isDev = $candidate->getStability() === 'dev';
11106 $isAlias = $candidate instanceof AliasPackage;
11107
11108 if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
11109 $requireFilter = $this->filterRequires[$name];
11110 } else {
11111 $requireFilter = new EmptyConstraint;
11112 }
11113
11114 if ($candidateName === $name) {
11115 $pkgConstraint = new Constraint('==', $candidateVersion);
11116
11117 if ($constraint === null || $constraint->matches($pkgConstraint)) {
11118 return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
11119 }
11120
11121 return self::MATCH_NAME;
11122 }
11123
11124 $provides = $candidate->getProvides();
11125 $replaces = $candidate->getReplaces();
11126
11127
11128  if (isset($replaces[0]) || isset($provides[0])) {
11129 foreach ($provides as $link) {
11130 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11131 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11132 }
11133 }
11134
11135 foreach ($replaces as $link) {
11136 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11137 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11138 }
11139 }
11140
11141 return self::MATCH_NONE;
11142 }
11143
11144 if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
11145 return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11146 }
11147
11148 if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
11149 return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11150 }
11151
11152 return self::MATCH_NONE;
11153 }
11154 }
11155 <?php
11156
11157
11158
11159
11160
11161
11162
11163
11164
11165
11166
11167 namespace Composer\DependencyResolver;
11168
11169
11170
11171
11172
11173
11174 class Problem
11175 {
11176
11177
11178
11179
11180 protected $reasonSeen;
11181
11182
11183
11184
11185
11186 protected $reasons = array();
11187
11188 protected $section = 0;
11189
11190 protected $pool;
11191
11192 public function __construct(Pool $pool)
11193 {
11194 $this->pool = $pool;
11195 }
11196
11197
11198
11199
11200
11201
11202 public function addRule(Rule $rule)
11203 {
11204 $this->addReason(spl_object_hash($rule), array(
11205 'rule' => $rule,
11206 'job' => $rule->getJob(),
11207 ));
11208 }
11209
11210
11211
11212
11213
11214
11215 public function getReasons()
11216 {
11217 return $this->reasons;
11218 }
11219
11220
11221
11222
11223
11224
11225
11226 public function getPrettyString(array $installedMap = array())
11227 {
11228 $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
11229
11230 if (count($reasons) === 1) {
11231 reset($reasons);
11232 $reason = current($reasons);
11233
11234 $rule = $reason['rule'];
11235 $job = $reason['job'];
11236
11237 if (isset($job['constraint'])) {
11238 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11239 } else {
11240 $packages = array();
11241 }
11242
11243 if ($job && $job['cmd'] === 'install' && empty($packages)) {
11244
11245
11246  if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') {
11247 $available = $this->pool->whatProvides($job['packageName']);
11248 $version = count($available) ? $available[0]->getPrettyVersion() : phpversion();
11249
11250 $msg = "\n    - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but ';
11251
11252 if (defined('HHVM_VERSION')) {
11253 return $msg . 'your HHVM version does not satisfy that requirement.';
11254 }
11255
11256 if ($job['packageName'] === 'hhvm') {
11257 return $msg . 'you are running this with PHP and not HHVM.';
11258 }
11259
11260 return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
11261 }
11262
11263
11264  if (0 === stripos($job['packageName'], 'ext-')) {
11265 $ext = substr($job['packageName'], 4);
11266 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
11267
11268 return "\n    - The requested PHP extension ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
11269 }
11270
11271
11272  if (0 === stripos($job['packageName'], 'lib-')) {
11273 if (strtolower($job['packageName']) === 'lib-icu') {
11274 $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.';
11275
11276 return "\n    - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error;
11277 }
11278
11279 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.';
11280 }
11281
11282 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $job['packageName'])) {
11283 $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $job['packageName']);
11284
11285 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.';
11286 }
11287
11288 if ($providers = $this->pool->whatProvides($job['packageName'], $job['constraint'], true, true)) {
11289 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.';
11290 }
11291
11292 if ($providers = $this->pool->whatProvides($job['packageName'], null, true, true)) {
11293 return "\n    - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
11294 }
11295
11296 return "\n    - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.';
11297 }
11298 }
11299
11300 $messages = array();
11301
11302 foreach ($reasons as $reason) {
11303 $rule = $reason['rule'];
11304 $job = $reason['job'];
11305
11306 if ($job) {
11307 $messages[] = $this->jobToText($job);
11308 } elseif ($rule) {
11309 if ($rule instanceof Rule) {
11310 $messages[] = $rule->getPrettyString($this->pool, $installedMap);
11311 }
11312 }
11313 }
11314
11315 return "\n    - ".implode("\n    - ", $messages);
11316 }
11317
11318
11319
11320
11321
11322
11323
11324 protected function addReason($id, $reason)
11325 {
11326 if (!isset($this->reasonSeen[$id])) {
11327 $this->reasonSeen[$id] = true;
11328 $this->reasons[$this->section][] = $reason;
11329 }
11330 }
11331
11332 public function nextSection()
11333 {
11334 $this->section++;
11335 }
11336
11337
11338
11339
11340
11341
11342
11343 protected function jobToText($job)
11344 {
11345 switch ($job['cmd']) {
11346 case 'install':
11347 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11348 if (!$packages) {
11349 return 'No package found to satisfy install request for '.$job['packageName'].$this->constraintToText($job['constraint']);
11350 }
11351
11352 return 'Installation request for '.$job['packageName'].$this->constraintToText($job['constraint']).' -> satisfiable by '.$this->getPackageList($packages).'.';
11353 case 'update':
11354 return 'Update request for '.$job['packageName'].$this->constraintToText($job['constraint']).'.';
11355 case 'remove':
11356 return 'Removal request for '.$job['packageName'].$this->constraintToText($job['constraint']).'';
11357 }
11358
11359 if (isset($job['constraint'])) {
11360 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11361 } else {
11362 $packages = array();
11363 }
11364
11365 return 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.$this->getPackageList($packages).'])';
11366 }
11367
11368 protected function getPackageList($packages)
11369 {
11370 $prepared = array();
11371 foreach ($packages as $package) {
11372 $prepared[$package->getName()]['name'] = $package->getPrettyName();
11373 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
11374 }
11375 foreach ($prepared as $name => $package) {
11376 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
11377 }
11378
11379 return implode(', ', $prepared);
11380 }
11381
11382
11383
11384
11385
11386
11387
11388 protected function constraintToText($constraint)
11389 {
11390 return ($constraint) ? ' '.$constraint->getPrettyString() : '';
11391 }
11392 }
11393 <?php
11394
11395
11396
11397
11398
11399
11400
11401
11402
11403
11404
11405 namespace Composer\DependencyResolver;
11406
11407 use Composer\Semver\Constraint\ConstraintInterface;
11408
11409
11410
11411
11412 class Request
11413 {
11414 protected $jobs;
11415
11416 public function __construct()
11417 {
11418 $this->jobs = array();
11419 }
11420
11421 public function install($packageName, ConstraintInterface $constraint = null)
11422 {
11423 $this->addJob($packageName, 'install', $constraint);
11424 }
11425
11426 public function update($packageName, ConstraintInterface $constraint = null)
11427 {
11428 $this->addJob($packageName, 'update', $constraint);
11429 }
11430
11431 public function remove($packageName, ConstraintInterface $constraint = null)
11432 {
11433 $this->addJob($packageName, 'remove', $constraint);
11434 }
11435
11436
11437
11438
11439
11440
11441
11442
11443
11444 public function fix($packageName, ConstraintInterface $constraint = null)
11445 {
11446 $this->addJob($packageName, 'install', $constraint, true);
11447 }
11448
11449 protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
11450 {
11451 $packageName = strtolower($packageName);
11452
11453 $this->jobs[] = array(
11454 'cmd' => $cmd,
11455 'packageName' => $packageName,
11456 'constraint' => $constraint,
11457 'fixed' => $fixed,
11458 );
11459 }
11460
11461 public function updateAll()
11462 {
11463 $this->jobs[] = array('cmd' => 'update-all');
11464 }
11465
11466 public function getJobs()
11467 {
11468 return $this->jobs;
11469 }
11470 }
11471 <?php
11472
11473
11474
11475
11476
11477
11478
11479
11480
11481
11482
11483 namespace Composer\DependencyResolver;
11484
11485 use Composer\Package\CompletePackage;
11486 use Composer\Package\Link;
11487 use Composer\Package\PackageInterface;
11488
11489
11490
11491
11492
11493 abstract class Rule
11494 {
11495
11496  const RULE_INTERNAL_ALLOW_UPDATE = 1;
11497 const RULE_JOB_INSTALL = 2;
11498 const RULE_JOB_REMOVE = 3;
11499 const RULE_PACKAGE_CONFLICT = 6;
11500 const RULE_PACKAGE_REQUIRES = 7;
11501 const RULE_PACKAGE_OBSOLETES = 8;
11502 const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
11503 const RULE_PACKAGE_SAME_NAME = 10;
11504 const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
11505 const RULE_LEARNED = 12;
11506 const RULE_PACKAGE_ALIAS = 13;
11507
11508
11509  const BITFIELD_TYPE = 0;
11510 const BITFIELD_REASON = 8;
11511 const BITFIELD_DISABLED = 16;
11512
11513 protected $bitfield;
11514 protected $reasonData;
11515
11516
11517
11518
11519
11520
11521 public function __construct($reason, $reasonData, $job = null)
11522 {
11523 $this->reasonData = $reasonData;
11524
11525 if ($job) {
11526 $this->job = $job;
11527 }
11528
11529 $this->bitfield = (0 << self::BITFIELD_DISABLED) |
11530 ($reason << self::BITFIELD_REASON) |
11531 (255 << self::BITFIELD_TYPE);
11532 }
11533
11534 abstract public function getLiterals();
11535
11536 abstract public function getHash();
11537
11538 public function getJob()
11539 {
11540 return isset($this->job) ? $this->job : null;
11541 }
11542
11543 abstract public function equals(Rule $rule);
11544
11545 public function getReason()
11546 {
11547 return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
11548 }
11549
11550 public function getReasonData()
11551 {
11552 return $this->reasonData;
11553 }
11554
11555 public function getRequiredPackage()
11556 {
11557 if ($this->getReason() === self::RULE_JOB_INSTALL) {
11558 return $this->reasonData;
11559 }
11560
11561 if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
11562 return $this->reasonData->getTarget();
11563 }
11564 }
11565
11566 public function setType($type)
11567 {
11568 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
11569 }
11570
11571 public function getType()
11572 {
11573 return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
11574 }
11575
11576 public function disable()
11577 {
11578 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
11579 }
11580
11581 public function enable()
11582 {
11583 $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED);
11584 }
11585
11586 public function isDisabled()
11587 {
11588 return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
11589 }
11590
11591 public function isEnabled()
11592 {
11593 return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
11594 }
11595
11596 abstract public function isAssertion();
11597
11598 public function getPrettyString(Pool $pool, array $installedMap = array())
11599 {
11600 $literals = $this->getLiterals();
11601
11602 $ruleText = '';
11603 foreach ($literals as $i => $literal) {
11604 if ($i != 0) {
11605 $ruleText .= '|';
11606 }
11607 $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
11608 }
11609
11610 switch ($this->getReason()) {
11611 case self::RULE_INTERNAL_ALLOW_UPDATE:
11612 return $ruleText;
11613
11614 case self::RULE_JOB_INSTALL:
11615 return "Install command rule ($ruleText)";
11616
11617 case self::RULE_JOB_REMOVE:
11618 return "Remove command rule ($ruleText)";
11619
11620 case self::RULE_PACKAGE_CONFLICT:
11621 $package1 = $pool->literalToPackage($literals[0]);
11622 $package2 = $pool->literalToPackage($literals[1]);
11623
11624 return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
11625
11626 case self::RULE_PACKAGE_REQUIRES:
11627 $sourceLiteral = array_shift($literals);
11628 $sourcePackage = $pool->literalToPackage($sourceLiteral);
11629
11630 $requires = array();
11631 foreach ($literals as $literal) {
11632 $requires[] = $pool->literalToPackage($literal);
11633 }
11634
11635 $text = $this->reasonData->getPrettyString($sourcePackage);
11636 if ($requires) {
11637 $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
11638 } else {
11639 $targetName = $this->reasonData->getTarget();
11640
11641 if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
11642
11643  if (defined('HHVM_VERSION')) {
11644 return $text . ' -> your HHVM version does not satisfy that requirement.';
11645 }
11646
11647 if ($targetName === 'hhvm') {
11648 return $text . ' -> you are running this with PHP and not HHVM.';
11649 }
11650
11651 $packages = $pool->whatProvides($targetName);
11652 $package = count($packages) ? current($packages) : phpversion();
11653
11654 if (!($package instanceof CompletePackage)) {
11655 return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
11656 }
11657
11658 $extra = $package->getExtra();
11659
11660 if (!empty($extra['config.platform'])) {
11661 $text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
11662 } else {
11663 $text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
11664 }
11665
11666 return $text;
11667 }
11668
11669 if (0 === strpos($targetName, 'ext-')) {
11670
11671  $ext = substr($targetName, 4);
11672 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
11673
11674 return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
11675 }
11676
11677 if (0 === strpos($targetName, 'lib-')) {
11678
11679  $lib = substr($targetName, 4);
11680
11681 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.';
11682 }
11683
11684 if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
11685 return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
11686 }
11687
11688 return $text . ' -> no matching package found.';
11689 }
11690
11691 return $text;
11692
11693 case self::RULE_PACKAGE_OBSOLETES:
11694 return $ruleText;
11695 case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
11696 return $ruleText;
11697 case self::RULE_PACKAGE_SAME_NAME:
11698 return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $literals) . '.';
11699 case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
11700 return $ruleText;
11701 case self::RULE_LEARNED:
11702 return 'Conclusion: '.$ruleText;
11703 case self::RULE_PACKAGE_ALIAS:
11704 return $ruleText;
11705 default:
11706 return '('.$ruleText.')';
11707 }
11708 }
11709
11710
11711
11712
11713
11714
11715
11716 protected function formatPackagesUnique($pool, array $packages)
11717 {
11718 $prepared = array();
11719 foreach ($packages as $package) {
11720 if (!is_object($package)) {
11721 $package = $pool->literalToPackage($package);
11722 }
11723 $prepared[$package->getName()]['name'] = $package->getPrettyName();
11724 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
11725 }
11726 foreach ($prepared as $name => $package) {
11727 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
11728 }
11729
11730 return implode(', ', $prepared);
11731 }
11732 }
11733 <?php
11734
11735
11736
11737
11738
11739
11740
11741
11742
11743
11744
11745 namespace Composer\DependencyResolver;
11746
11747 use Composer\Package\PackageInterface;
11748 use Composer\Package\Link;
11749
11750
11751
11752
11753 class Rule2Literals extends Rule
11754 {
11755 protected $literal1;
11756 protected $literal2;
11757
11758
11759
11760
11761
11762
11763
11764
11765 public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
11766 {
11767 parent::__construct($reason, $reasonData, $job);
11768
11769 if ($literal1 < $literal2) {
11770 $this->literal1 = $literal1;
11771 $this->literal2 = $literal2;
11772 } else {
11773 $this->literal1 = $literal2;
11774 $this->literal2 = $literal1;
11775 }
11776 }
11777
11778 public function getLiterals()
11779 {
11780 return array($this->literal1, $this->literal2);
11781 }
11782
11783 public function getHash()
11784 {
11785 $data = unpack('ihash', md5($this->literal1.','.$this->literal2, true));
11786
11787 return $data['hash'];
11788 }
11789
11790
11791
11792
11793
11794
11795
11796
11797
11798 public function equals(Rule $rule)
11799 {
11800 $literals = $rule->getLiterals();
11801 if (2 != count($literals)) {
11802 return false;
11803 }
11804
11805 if ($this->literal1 !== $literals[0]) {
11806 return false;
11807 }
11808
11809 if ($this->literal2 !== $literals[1]) {
11810 return false;
11811 }
11812
11813 return true;
11814 }
11815
11816 public function isAssertion()
11817 {
11818 return false;
11819 }
11820
11821
11822
11823
11824
11825
11826 public function __toString()
11827 {
11828 $result = ($this->isDisabled()) ? 'disabled(' : '(';
11829
11830 $result .= $this->literal1 . '|' . $this->literal2 . ')';
11831
11832 return $result;
11833 }
11834 }
11835 <?php
11836
11837
11838
11839
11840
11841
11842
11843
11844
11845
11846
11847 namespace Composer\DependencyResolver;
11848
11849
11850
11851
11852 class RuleSet implements \IteratorAggregate, \Countable
11853 {
11854
11855  const TYPE_PACKAGE = 0;
11856 const TYPE_JOB = 1;
11857 const TYPE_LEARNED = 4;
11858
11859
11860
11861
11862
11863
11864 public $ruleById;
11865
11866 protected static $types = array(
11867 255 => 'UNKNOWN',
11868 self::TYPE_PACKAGE => 'PACKAGE',
11869 self::TYPE_JOB => 'JOB',
11870 self::TYPE_LEARNED => 'LEARNED',
11871 );
11872
11873 protected $rules;
11874 protected $nextRuleId;
11875
11876 protected $rulesByHash;
11877
11878 public function __construct()
11879 {
11880 $this->nextRuleId = 0;
11881
11882 foreach ($this->getTypes() as $type) {
11883 $this->rules[$type] = array();
11884 }
11885
11886 $this->rulesByHash = array();
11887 }
11888
11889 public function add(Rule $rule, $type)
11890 {
11891 if (!isset(self::$types[$type])) {
11892 throw new \OutOfBoundsException('Unknown rule type: ' . $type);
11893 }
11894
11895 $hash = $rule->getHash();
11896
11897
11898  if (isset($this->rulesByHash[$hash])) {
11899 $potentialDuplicates = $this->rulesByHash[$hash];
11900 if (is_array($potentialDuplicates)) {
11901 foreach ($potentialDuplicates as $potentialDuplicate) {
11902 if ($rule->equals($potentialDuplicate)) {
11903 return;
11904 }
11905 }
11906 } else {
11907 if ($rule->equals($potentialDuplicates)) {
11908 return;
11909 }
11910 }
11911 }
11912
11913 if (!isset($this->rules[$type])) {
11914 $this->rules[$type] = array();
11915 }
11916
11917 $this->rules[$type][] = $rule;
11918 $this->ruleById[$this->nextRuleId] = $rule;
11919 $rule->setType($type);
11920
11921 $this->nextRuleId++;
11922
11923 if (!isset($this->rulesByHash[$hash])) {
11924 $this->rulesByHash[$hash] = $rule;
11925 } elseif (is_array($this->rulesByHash[$hash])) {
11926 $this->rulesByHash[$hash][] = $rule;
11927 } else {
11928 $originalRule = $this->rulesByHash[$hash];
11929 $this->rulesByHash[$hash] = array($originalRule, $rule);
11930 }
11931 }
11932
11933 public function count()
11934 {
11935 return $this->nextRuleId;
11936 }
11937
11938 public function ruleById($id)
11939 {
11940 return $this->ruleById[$id];
11941 }
11942
11943 public function getRules()
11944 {
11945 return $this->rules;
11946 }
11947
11948 public function getIterator()
11949 {
11950 return new RuleSetIterator($this->getRules());
11951 }
11952
11953 public function getIteratorFor($types)
11954 {
11955 if (!is_array($types)) {
11956 $types = array($types);
11957 }
11958
11959 $allRules = $this->getRules();
11960 $rules = array();
11961
11962 foreach ($types as $type) {
11963 $rules[$type] = $allRules[$type];
11964 }
11965
11966 return new RuleSetIterator($rules);
11967 }
11968
11969 public function getIteratorWithout($types)
11970 {
11971 if (!is_array($types)) {
11972 $types = array($types);
11973 }
11974
11975 $rules = $this->getRules();
11976
11977 foreach ($types as $type) {
11978 unset($rules[$type]);
11979 }
11980
11981 return new RuleSetIterator($rules);
11982 }
11983
11984 public function getTypes()
11985 {
11986 $types = self::$types;
11987 unset($types[255]);
11988
11989 return array_keys($types);
11990 }
11991
11992 public function getPrettyString(Pool $pool = null)
11993 {
11994 $string = "\n";
11995 foreach ($this->rules as $type => $rules) {
11996 $string .= str_pad(self::$types[$type], 8, ' ') . ": ";
11997 foreach ($rules as $rule) {
11998 $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
11999 }
12000 $string .= "\n\n";
12001 }
12002
12003 return $string;
12004 }
12005
12006 public function __toString()
12007 {
12008 return $this->getPrettyString(null);
12009 }
12010 }
12011 <?php
12012
12013
12014
12015
12016
12017
12018
12019
12020
12021
12022
12023 namespace Composer\DependencyResolver;
12024
12025 use Composer\Package\PackageInterface;
12026 use Composer\Package\AliasPackage;
12027 use Composer\Repository\PlatformRepository;
12028
12029
12030
12031
12032 class RuleSetGenerator
12033 {
12034 protected $policy;
12035 protected $pool;
12036 protected $rules;
12037 protected $jobs;
12038 protected $installedMap;
12039 protected $whitelistedMap;
12040 protected $addedMap;
12041
12042 public function __construct(PolicyInterface $policy, Pool $pool)
12043 {
12044 $this->policy = $policy;
12045 $this->pool = $pool;
12046 }
12047
12048
12049
12050
12051
12052
12053
12054
12055
12056
12057
12058
12059
12060
12061
12062 protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
12063 {
12064 $literals = array(-$package->id);
12065
12066 foreach ($providers as $provider) {
12067
12068  if ($provider === $package) {
12069 return null;
12070 }
12071 $literals[] = $provider->id;
12072 }
12073
12074 return new GenericRule($literals, $reason, $reasonData);
12075 }
12076
12077
12078
12079
12080
12081
12082
12083
12084
12085
12086
12087
12088
12089 protected function createInstallOneOfRule(array $packages, $reason, $job)
12090 {
12091 $literals = array();
12092 foreach ($packages as $package) {
12093 $literals[] = $package->id;
12094 }
12095
12096 return new GenericRule($literals, $reason, $job['packageName'], $job);
12097 }
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107
12108
12109
12110 protected function createRemoveRule(PackageInterface $package, $reason, $job)
12111 {
12112 return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
12113 }
12114
12115
12116
12117
12118
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128
12129 protected function createRule2Literals(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
12130 {
12131
12132  if ($issuer === $provider) {
12133 return null;
12134 }
12135
12136 return new Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
12137 }
12138
12139
12140
12141
12142
12143
12144
12145
12146
12147
12148 private function addRule($type, Rule $newRule = null)
12149 {
12150 if (!$newRule) {
12151 return;
12152 }
12153
12154 $this->rules->add($newRule, $type);
12155 }
12156
12157 protected function whitelistFromPackage(PackageInterface $package)
12158 {
12159 $workQueue = new \SplQueue;
12160 $workQueue->enqueue($package);
12161
12162 while (!$workQueue->isEmpty()) {
12163 $package = $workQueue->dequeue();
12164 if (isset($this->whitelistedMap[$package->id])) {
12165 continue;
12166 }
12167
12168 $this->whitelistedMap[$package->id] = true;
12169
12170 foreach ($package->getRequires() as $link) {
12171 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
12172
12173 foreach ($possibleRequires as $require) {
12174 $workQueue->enqueue($require);
12175 }
12176 }
12177
12178 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
12179
12180 foreach ($obsoleteProviders as $provider) {
12181 if ($provider === $package) {
12182 continue;
12183 }
12184
12185 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12186 $workQueue->enqueue($provider);
12187 }
12188 }
12189 }
12190 }
12191
12192 protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
12193 {
12194 $workQueue = new \SplQueue;
12195 $workQueue->enqueue($package);
12196
12197 while (!$workQueue->isEmpty()) {
12198 $package = $workQueue->dequeue();
12199 if (isset($this->addedMap[$package->id])) {
12200 continue;
12201 }
12202
12203 $this->addedMap[$package->id] = true;
12204
12205 foreach ($package->getRequires() as $link) {
12206 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
12207 continue;
12208 }
12209
12210 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12211
12212 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
12213
12214 foreach ($possibleRequires as $require) {
12215 $workQueue->enqueue($require);
12216 }
12217 }
12218
12219 foreach ($package->getConflicts() as $link) {
12220 $possibleConflicts = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12221
12222 foreach ($possibleConflicts as $conflict) {
12223 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $conflict, Rule::RULE_PACKAGE_CONFLICT, $link));
12224 }
12225 }
12226
12227
12228  $isInstalled = (isset($this->installedMap[$package->id]));
12229
12230 foreach ($package->getReplaces() as $link) {
12231 $obsoleteProviders = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12232
12233 foreach ($obsoleteProviders as $provider) {
12234 if ($provider === $package) {
12235 continue;
12236 }
12237
12238 if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12239 $reason = ($isInstalled) ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
12240 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $link));
12241 }
12242 }
12243 }
12244
12245 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null);
12246
12247 foreach ($obsoleteProviders as $provider) {
12248 if ($provider === $package) {
12249 continue;
12250 }
12251
12252 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12253 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
12254 } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12255 $reason = ($package->getName() == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
12256 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRule2Literals($package, $provider, $reason, $package));
12257 }
12258 }
12259 }
12260 }
12261
12262 protected function obsoleteImpossibleForAlias($package, $provider)
12263 {
12264 $packageIsAlias = $package instanceof AliasPackage;
12265 $providerIsAlias = $provider instanceof AliasPackage;
12266
12267 $impossible = (
12268 ($packageIsAlias && $package->getAliasOf() === $provider) ||
12269 ($providerIsAlias && $provider->getAliasOf() === $package) ||
12270 ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
12271 );
12272
12273 return $impossible;
12274 }
12275
12276 protected function whitelistFromJobs()
12277 {
12278 foreach ($this->jobs as $job) {
12279 switch ($job['cmd']) {
12280 case 'install':
12281 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
12282 foreach ($packages as $package) {
12283 $this->whitelistFromPackage($package);
12284 }
12285 break;
12286 }
12287 }
12288 }
12289
12290 protected function addRulesForJobs($ignorePlatformReqs)
12291 {
12292 foreach ($this->jobs as $job) {
12293 switch ($job['cmd']) {
12294 case 'install':
12295 if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
12296 continue;
12297 }
12298
12299 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12300 if ($packages) {
12301 foreach ($packages as $package) {
12302 if (!isset($this->installedMap[$package->id])) {
12303 $this->addRulesForPackage($package, $ignorePlatformReqs);
12304 }
12305 }
12306
12307 $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
12308 $this->addRule(RuleSet::TYPE_JOB, $rule);
12309 }
12310 break;
12311 case 'remove':
12312
12313  
12314  $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12315 foreach ($packages as $package) {
12316 $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
12317 $this->addRule(RuleSet::TYPE_JOB, $rule);
12318 }
12319 break;
12320 }
12321 }
12322 }
12323
12324 public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
12325 {
12326 $this->jobs = $jobs;
12327 $this->rules = new RuleSet;
12328 $this->installedMap = $installedMap;
12329
12330 $this->whitelistedMap = array();
12331 foreach ($this->installedMap as $package) {
12332 $this->whitelistFromPackage($package);
12333 }
12334 $this->whitelistFromJobs();
12335
12336 $this->pool->setWhitelist($this->whitelistedMap);
12337
12338 $this->addedMap = array();
12339 foreach ($this->installedMap as $package) {
12340 $this->addRulesForPackage($package, $ignorePlatformReqs);
12341 }
12342
12343 $this->addRulesForJobs($ignorePlatformReqs);
12344
12345 return $this->rules;
12346 }
12347 }
12348 <?php
12349
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360 namespace Composer\DependencyResolver;
12361
12362
12363
12364
12365 class RuleSetIterator implements \Iterator
12366 {
12367 protected $rules;
12368 protected $types;
12369
12370 protected $currentOffset;
12371 protected $currentType;
12372 protected $currentTypeOffset;
12373
12374 public function __construct(array $rules)
12375 {
12376 $this->rules = $rules;
12377 $this->types = array_keys($rules);
12378 sort($this->types);
12379
12380 $this->rewind();
12381 }
12382
12383 public function current()
12384 {
12385 return $this->rules[$this->currentType][$this->currentOffset];
12386 }
12387
12388 public function key()
12389 {
12390 return $this->currentType;
12391 }
12392
12393 public function next()
12394 {
12395 $this->currentOffset++;
12396
12397 if (!isset($this->rules[$this->currentType])) {
12398 return;
12399 }
12400
12401 if ($this->currentOffset >= sizeof($this->rules[$this->currentType])) {
12402 $this->currentOffset = 0;
12403
12404 do {
12405 $this->currentTypeOffset++;
12406
12407 if (!isset($this->types[$this->currentTypeOffset])) {
12408 $this->currentType = -1;
12409 break;
12410 }
12411
12412 $this->currentType = $this->types[$this->currentTypeOffset];
12413 } while (isset($this->types[$this->currentTypeOffset]) && !sizeof($this->rules[$this->currentType]));
12414 }
12415 }
12416
12417 public function rewind()
12418 {
12419 $this->currentOffset = 0;
12420
12421 $this->currentTypeOffset = -1;
12422 $this->currentType = -1;
12423
12424 do {
12425 $this->currentTypeOffset++;
12426
12427 if (!isset($this->types[$this->currentTypeOffset])) {
12428 $this->currentType = -1;
12429 break;
12430 }
12431
12432 $this->currentType = $this->types[$this->currentTypeOffset];
12433 } while (isset($this->types[$this->currentTypeOffset]) && !sizeof($this->rules[$this->currentType]));
12434 }
12435
12436 public function valid()
12437 {
12438 return isset($this->rules[$this->currentType])
12439 && isset($this->rules[$this->currentType][$this->currentOffset]);
12440 }
12441 }
12442 <?php
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454 namespace Composer\DependencyResolver;
12455
12456
12457
12458
12459
12460
12461
12462
12463
12464 class RuleWatchChain extends \SplDoublyLinkedList
12465 {
12466 protected $offset = 0;
12467
12468
12469
12470
12471
12472
12473 public function seek($offset)
12474 {
12475 $this->rewind();
12476 for ($i = 0; $i < $offset; $i++, $this->next());
12477 }
12478
12479
12480
12481
12482
12483
12484
12485
12486
12487 public function remove()
12488 {
12489 $offset = $this->key();
12490 $this->offsetUnset($offset);
12491 $this->seek($offset);
12492 }
12493 }
12494 <?php
12495
12496
12497
12498
12499
12500
12501
12502
12503
12504
12505
12506 namespace Composer\DependencyResolver;
12507
12508
12509
12510
12511
12512
12513
12514
12515
12516
12517
12518 class RuleWatchGraph
12519 {
12520 protected $watchChains = array();
12521
12522
12523
12524
12525
12526
12527
12528
12529
12530
12531
12532
12533
12534 public function insert(RuleWatchNode $node)
12535 {
12536 if ($node->getRule()->isAssertion()) {
12537 return;
12538 }
12539
12540 foreach (array($node->watch1, $node->watch2) as $literal) {
12541 if (!isset($this->watchChains[$literal])) {
12542 $this->watchChains[$literal] = new RuleWatchChain;
12543 }
12544
12545 $this->watchChains[$literal]->unshift($node);
12546 }
12547 }
12548
12549
12550
12551
12552
12553
12554
12555
12556
12557
12558
12559
12560
12561
12562
12563
12564
12565
12566
12567
12568
12569
12570
12571
12572 public function propagateLiteral($decidedLiteral, $level, $decisions)
12573 {
12574
12575  
12576  
12577  $literal = -$decidedLiteral;
12578
12579 if (!isset($this->watchChains[$literal])) {
12580 return null;
12581 }
12582
12583 $chain = $this->watchChains[$literal];
12584
12585 $chain->rewind();
12586 while ($chain->valid()) {
12587 $node = $chain->current();
12588 $otherWatch = $node->getOtherWatch($literal);
12589
12590 if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
12591 $ruleLiterals = $node->getRule()->getLiterals();
12592
12593 $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
12594 return $literal !== $ruleLiteral &&
12595 $otherWatch !== $ruleLiteral &&
12596 !$decisions->conflict($ruleLiteral);
12597 });
12598
12599 if ($alternativeLiterals) {
12600 reset($alternativeLiterals);
12601 $this->moveWatch($literal, current($alternativeLiterals), $node);
12602 continue;
12603 }
12604
12605 if ($decisions->conflict($otherWatch)) {
12606 return $node->getRule();
12607 }
12608
12609 $decisions->decide($otherWatch, $level, $node->getRule());
12610 }
12611
12612 $chain->next();
12613 }
12614
12615 return null;
12616 }
12617
12618
12619
12620
12621
12622
12623
12624
12625
12626
12627 protected function moveWatch($fromLiteral, $toLiteral, $node)
12628 {
12629 if (!isset($this->watchChains[$toLiteral])) {
12630 $this->watchChains[$toLiteral] = new RuleWatchChain;
12631 }
12632
12633 $node->moveWatch($fromLiteral, $toLiteral);
12634 $this->watchChains[$fromLiteral]->remove();
12635 $this->watchChains[$toLiteral]->unshift($node);
12636 }
12637 }
12638 <?php
12639
12640
12641
12642
12643
12644
12645
12646
12647
12648
12649
12650 namespace Composer\DependencyResolver;
12651
12652
12653
12654
12655
12656
12657
12658
12659 class RuleWatchNode
12660 {
12661 public $watch1;
12662 public $watch2;
12663
12664 protected $rule;
12665
12666
12667
12668
12669
12670
12671 public function __construct($rule)
12672 {
12673 $this->rule = $rule;
12674
12675 $literals = $rule->getLiterals();
12676
12677 $this->watch1 = count($literals) > 0 ? $literals[0] : 0;
12678 $this->watch2 = count($literals) > 1 ? $literals[1] : 0;
12679 }
12680
12681
12682
12683
12684
12685
12686
12687
12688
12689 public function watch2OnHighest(Decisions $decisions)
12690 {
12691 $literals = $this->rule->getLiterals();
12692
12693
12694  if (count($literals) < 3) {
12695 return;
12696 }
12697
12698 $watchLevel = 0;
12699
12700 foreach ($literals as $literal) {
12701 $level = $decisions->decisionLevel($literal);
12702
12703 if ($level > $watchLevel) {
12704 $this->watch2 = $literal;
12705 $watchLevel = $level;
12706 }
12707 }
12708 }
12709
12710
12711
12712
12713
12714
12715 public function getRule()
12716 {
12717 return $this->rule;
12718 }
12719
12720
12721
12722
12723
12724
12725
12726 public function getOtherWatch($literal)
12727 {
12728 if ($this->watch1 == $literal) {
12729 return $this->watch2;
12730 } else {
12731 return $this->watch1;
12732 }
12733 }
12734
12735
12736
12737
12738
12739
12740
12741 public function moveWatch($from, $to)
12742 {
12743 if ($this->watch1 == $from) {
12744 $this->watch1 = $to;
12745 } else {
12746 $this->watch2 = $to;
12747 }
12748 }
12749 }
12750 <?php
12751
12752
12753
12754
12755
12756
12757
12758
12759
12760
12761
12762 namespace Composer\DependencyResolver;
12763
12764 use Composer\IO\IOInterface;
12765 use Composer\Repository\RepositoryInterface;
12766 use Composer\Repository\PlatformRepository;
12767
12768
12769
12770
12771 class Solver
12772 {
12773 const BRANCH_LITERALS = 0;
12774 const BRANCH_LEVEL = 1;
12775
12776
12777 protected $policy;
12778
12779 protected $pool;
12780
12781 protected $installed;
12782
12783 protected $rules;
12784
12785 protected $ruleSetGenerator;
12786
12787 protected $jobs;
12788
12789
12790 protected $updateMap = array();
12791
12792 protected $watchGraph;
12793
12794 protected $decisions;
12795
12796 protected $installedMap;
12797
12798
12799 protected $propagateIndex;
12800
12801 protected $branches = array();
12802
12803 protected $problems = array();
12804
12805 protected $learnedPool = array();
12806
12807 protected $learnedWhy = array();
12808
12809
12810 protected $io;
12811
12812
12813
12814
12815
12816
12817
12818 public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
12819 {
12820 $this->io = $io;
12821 $this->policy = $policy;
12822 $this->pool = $pool;
12823 $this->installed = $installed;
12824 $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
12825 }
12826
12827
12828
12829
12830 public function getRuleSetSize()
12831 {
12832 return count($this->rules);
12833 }
12834
12835
12836
12837 private function makeAssertionRuleDecisions()
12838 {
12839 $decisionStart = count($this->decisions) - 1;
12840
12841 $rulesCount = count($this->rules);
12842 for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
12843 $rule = $this->rules->ruleById[$ruleIndex];
12844
12845 if (!$rule->isAssertion() || $rule->isDisabled()) {
12846 continue;
12847 }
12848
12849 $literals = $rule->getLiterals();
12850 $literal = $literals[0];
12851
12852 if (!$this->decisions->decided(abs($literal))) {
12853 $this->decisions->decide($literal, 1, $rule);
12854 continue;
12855 }
12856
12857 if ($this->decisions->satisfy($literal)) {
12858 continue;
12859 }
12860
12861
12862  if (RuleSet::TYPE_LEARNED === $rule->getType()) {
12863 $rule->disable();
12864 continue;
12865 }
12866
12867 $conflict = $this->decisions->decisionRule($literal);
12868
12869 if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
12870 $problem = new Problem($this->pool);
12871
12872 $problem->addRule($rule);
12873 $problem->addRule($conflict);
12874 $this->disableProblem($rule);
12875 $this->problems[] = $problem;
12876 continue;
12877 }
12878
12879
12880  $problem = new Problem($this->pool);
12881 $problem->addRule($rule);
12882 $problem->addRule($conflict);
12883
12884
12885  
12886  foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
12887 if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
12888 continue;
12889 }
12890
12891 $assertRuleLiterals = $assertRule->getLiterals();
12892 $assertRuleLiteral = $assertRuleLiterals[0];
12893
12894 if (abs($literal) !== abs($assertRuleLiteral)) {
12895 continue;
12896 }
12897
12898 $problem->addRule($assertRule);
12899 $this->disableProblem($assertRule);
12900 }
12901 $this->problems[] = $problem;
12902
12903 $this->decisions->resetToOffset($decisionStart);
12904 $ruleIndex = -1;
12905 }
12906 }
12907
12908 protected function setupInstalledMap()
12909 {
12910 $this->installedMap = array();
12911 foreach ($this->installed->getPackages() as $package) {
12912 $this->installedMap[$package->id] = $package;
12913 }
12914 }
12915
12916
12917
12918
12919 protected function checkForRootRequireProblems($ignorePlatformReqs)
12920 {
12921 foreach ($this->jobs as $job) {
12922 switch ($job['cmd']) {
12923 case 'update':
12924 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12925 foreach ($packages as $package) {
12926 if (isset($this->installedMap[$package->id])) {
12927 $this->updateMap[$package->id] = true;
12928 }
12929 }
12930 break;
12931
12932 case 'update-all':
12933 foreach ($this->installedMap as $package) {
12934 $this->updateMap[$package->id] = true;
12935 }
12936 break;
12937
12938 case 'install':
12939 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
12940 break;
12941 }
12942
12943 if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
12944 $problem = new Problem($this->pool);
12945 $problem->addRule(new GenericRule(array(), null, null, $job));
12946 $this->problems[] = $problem;
12947 }
12948 break;
12949 }
12950 }
12951 }
12952
12953
12954
12955
12956
12957
12958 public function solve(Request $request, $ignorePlatformReqs = false)
12959 {
12960 $this->jobs = $request->getJobs();
12961
12962 $this->setupInstalledMap();
12963 $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
12964 $this->checkForRootRequireProblems($ignorePlatformReqs);
12965 $this->decisions = new Decisions($this->pool);
12966 $this->watchGraph = new RuleWatchGraph;
12967
12968 foreach ($this->rules as $rule) {
12969 $this->watchGraph->insert(new RuleWatchNode($rule));
12970 }
12971
12972
12973 $this->makeAssertionRuleDecisions();
12974
12975 $this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
12976 $before = microtime(true);
12977 $this->runSat(true);
12978 $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
12979
12980
12981  foreach ($this->installedMap as $packageId => $void) {
12982 if ($this->decisions->undecided($packageId)) {
12983 $this->decisions->decide(-$packageId, 1, null);
12984 }
12985 }
12986
12987 if ($this->problems) {
12988 throw new SolverProblemsException($this->problems, $this->installedMap);
12989 }
12990
12991 $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
12992
12993 return $transaction->getOperations();
12994 }
12995
12996
12997
12998
12999
13000
13001
13002
13003
13004
13005 protected function propagate($level)
13006 {
13007 while ($this->decisions->validOffset($this->propagateIndex)) {
13008 $decision = $this->decisions->atOffset($this->propagateIndex);
13009
13010 $conflict = $this->watchGraph->propagateLiteral(
13011 $decision[Decisions::DECISION_LITERAL],
13012 $level,
13013 $this->decisions
13014 );
13015
13016 $this->propagateIndex++;
13017
13018 if ($conflict) {
13019 return $conflict;
13020 }
13021 }
13022
13023 return null;
13024 }
13025
13026
13027
13028
13029
13030
13031 private function revert($level)
13032 {
13033 while (!$this->decisions->isEmpty()) {
13034 $literal = $this->decisions->lastLiteral();
13035
13036 if ($this->decisions->undecided($literal)) {
13037 break;
13038 }
13039
13040 $decisionLevel = $this->decisions->decisionLevel($literal);
13041
13042 if ($decisionLevel <= $level) {
13043 break;
13044 }
13045
13046 $this->decisions->revertLast();
13047 $this->propagateIndex = count($this->decisions);
13048 }
13049
13050 while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
13051 array_pop($this->branches);
13052 }
13053 }
13054
13055
13056
13057
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13069
13070
13071
13072
13073
13074 private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
13075 {
13076 $level++;
13077
13078 $this->decisions->decide($literal, $level, $rule);
13079
13080 while (true) {
13081 $rule = $this->propagate($level);
13082
13083 if (!$rule) {
13084 break;
13085 }
13086
13087 if ($level == 1) {
13088 return $this->analyzeUnsolvable($rule, $disableRules);
13089 }
13090
13091
13092  list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
13093
13094 if ($newLevel <= 0 || $newLevel >= $level) {
13095 throw new SolverBugException(
13096 "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
13097 );
13098 } elseif (!$newRule) {
13099 throw new SolverBugException(
13100 "No rule was learned from analyzing $rule at level $level."
13101 );
13102 }
13103
13104 $level = $newLevel;
13105
13106 $this->revert($level);
13107
13108 $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
13109
13110 $this->learnedWhy[spl_object_hash($newRule)] = $why;
13111
13112 $ruleNode = new RuleWatchNode($newRule);
13113 $ruleNode->watch2OnHighest($this->decisions);
13114 $this->watchGraph->insert($ruleNode);
13115
13116 $this->decisions->decide($learnLiteral, $level, $newRule);
13117 }
13118
13119 return $level;
13120 }
13121
13122
13123
13124
13125
13126
13127
13128
13129 private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
13130 {
13131
13132  $literals = $this->policy->selectPreferredPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
13133
13134 $selectedLiteral = array_shift($literals);
13135
13136
13137  if (count($literals)) {
13138 $this->branches[] = array($literals, $level);
13139 }
13140
13141 return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
13142 }
13143
13144
13145
13146
13147
13148
13149 protected function analyze($level, Rule $rule)
13150 {
13151 $analyzedRule = $rule;
13152 $ruleLevel = 1;
13153 $num = 0;
13154 $l1num = 0;
13155 $seen = array();
13156 $learnedLiterals = array(null);
13157
13158 $decisionId = count($this->decisions);
13159
13160 $this->learnedPool[] = array();
13161
13162 while (true) {
13163 $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
13164
13165 foreach ($rule->getLiterals() as $literal) {
13166
13167  if ($this->decisions->satisfy($literal)) {
13168 continue;
13169 }
13170
13171 if (isset($seen[abs($literal)])) {
13172 continue;
13173 }
13174 $seen[abs($literal)] = true;
13175
13176 $l = $this->decisions->decisionLevel($literal);
13177
13178 if (1 === $l) {
13179 $l1num++;
13180 } elseif ($level === $l) {
13181 $num++;
13182 } else {
13183
13184  $learnedLiterals[] = $literal;
13185
13186 if ($l > $ruleLevel) {
13187 $ruleLevel = $l;
13188 }
13189 }
13190 }
13191
13192 $l1retry = true;
13193 while ($l1retry) {
13194 $l1retry = false;
13195
13196 if (!$num && !--$l1num) {
13197
13198  break 2;
13199 }
13200
13201 while (true) {
13202 if ($decisionId <= 0) {
13203 throw new SolverBugException(
13204 "Reached invalid decision id $decisionId while looking through $rule for a literal present in the analyzed rule $analyzedRule."
13205 );
13206 }
13207
13208 $decisionId--;
13209
13210 $decision = $this->decisions->atOffset($decisionId);
13211 $literal = $decision[Decisions::DECISION_LITERAL];
13212
13213 if (isset($seen[abs($literal)])) {
13214 break;
13215 }
13216 }
13217
13218 unset($seen[abs($literal)]);
13219
13220 if ($num && 0 === --$num) {
13221 $learnedLiterals[0] = -abs($literal);
13222
13223 if (!$l1num) {
13224 break 2;
13225 }
13226
13227 foreach ($learnedLiterals as $i => $learnedLiteral) {
13228 if ($i !== 0) {
13229 unset($seen[abs($learnedLiteral)]);
13230 }
13231 }
13232
13233  $l1num++;
13234 $l1retry = true;
13235 }
13236 }
13237
13238 $decision = $this->decisions->atOffset($decisionId);
13239 $rule = $decision[Decisions::DECISION_REASON];
13240 }
13241
13242 $why = count($this->learnedPool) - 1;
13243
13244 if (!$learnedLiterals[0]) {
13245 throw new SolverBugException(
13246 "Did not find a learnable literal in analyzed rule $analyzedRule."
13247 );
13248 }
13249
13250 $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why);
13251
13252 return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
13253 }
13254
13255
13256
13257
13258
13259 private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule)
13260 {
13261 $why = spl_object_hash($conflictRule);
13262
13263 if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
13264 $learnedWhy = $this->learnedWhy[$why];
13265 $problemRules = $this->learnedPool[$learnedWhy];
13266
13267 foreach ($problemRules as $problemRule) {
13268 $this->analyzeUnsolvableRule($problem, $problemRule);
13269 }
13270
13271 return;
13272 }
13273
13274 if ($conflictRule->getType() == RuleSet::TYPE_PACKAGE) {
13275
13276  return;
13277 }
13278
13279 $problem->nextSection();
13280 $problem->addRule($conflictRule);
13281 }
13282
13283
13284
13285
13286
13287
13288 private function analyzeUnsolvable(Rule $conflictRule, $disableRules)
13289 {
13290 $problem = new Problem($this->pool);
13291 $problem->addRule($conflictRule);
13292
13293 $this->analyzeUnsolvableRule($problem, $conflictRule);
13294
13295 $this->problems[] = $problem;
13296
13297 $seen = array();
13298 $literals = $conflictRule->getLiterals();
13299
13300 foreach ($literals as $literal) {
13301
13302  if ($this->decisions->satisfy($literal)) {
13303 continue;
13304 }
13305 $seen[abs($literal)] = true;
13306 }
13307
13308 foreach ($this->decisions as $decision) {
13309 $literal = $decision[Decisions::DECISION_LITERAL];
13310
13311
13312  if (!isset($seen[abs($literal)])) {
13313 continue;
13314 }
13315
13316 $why = $decision[Decisions::DECISION_REASON];
13317
13318 $problem->addRule($why);
13319 $this->analyzeUnsolvableRule($problem, $why);
13320
13321 $literals = $why->getLiterals();
13322
13323 foreach ($literals as $literal) {
13324
13325  if ($this->decisions->satisfy($literal)) {
13326 continue;
13327 }
13328 $seen[abs($literal)] = true;
13329 }
13330 }
13331
13332 if ($disableRules) {
13333 foreach ($this->problems[count($this->problems) - 1] as $reason) {
13334 $this->disableProblem($reason['rule']);
13335 }
13336
13337 $this->resetSolver();
13338
13339 return 1;
13340 }
13341
13342 return 0;
13343 }
13344
13345
13346
13347
13348 private function disableProblem(Rule $why)
13349 {
13350 $job = $why->getJob();
13351
13352 if (!$job) {
13353 $why->disable();
13354
13355 return;
13356 }
13357
13358
13359  foreach ($this->rules as $rule) {
13360
13361 if ($job === $rule->getJob()) {
13362 $rule->disable();
13363 }
13364 }
13365 }
13366
13367 private function resetSolver()
13368 {
13369 $this->decisions->reset();
13370
13371 $this->propagateIndex = 0;
13372 $this->branches = array();
13373
13374 $this->enableDisableLearnedRules();
13375 $this->makeAssertionRuleDecisions();
13376 }
13377
13378
13379
13380
13381
13382
13383
13384
13385 private function enableDisableLearnedRules()
13386 {
13387 foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
13388 $why = $this->learnedWhy[spl_object_hash($rule)];
13389 $problemRules = $this->learnedPool[$why];
13390
13391 $foundDisabled = false;
13392 foreach ($problemRules as $problemRule) {
13393 if ($problemRule->isDisabled()) {
13394 $foundDisabled = true;
13395 break;
13396 }
13397 }
13398
13399 if ($foundDisabled && $rule->isEnabled()) {
13400 $rule->disable();
13401 } elseif (!$foundDisabled && $rule->isDisabled()) {
13402 $rule->enable();
13403 }
13404 }
13405 }
13406
13407
13408
13409
13410 private function runSat($disableRules = true)
13411 {
13412 $this->propagateIndex = 0;
13413
13414
13415
13416
13417
13418
13419
13420
13421
13422
13423
13424 $decisionQueue = array();
13425 $decisionSupplementQueue = array();
13426
13427
13428
13429 $disableRules = array();
13430
13431 $level = 1;
13432 $systemLevel = $level + 1;
13433 $installedPos = 0;
13434
13435 while (true) {
13436 if (1 === $level) {
13437 $conflictRule = $this->propagate($level);
13438 if (null !== $conflictRule) {
13439 if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
13440 continue;
13441 }
13442
13443 return;
13444 }
13445 }
13446
13447
13448  if ($level < $systemLevel) {
13449 $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
13450 foreach ($iterator as $rule) {
13451 if ($rule->isEnabled()) {
13452 $decisionQueue = array();
13453 $noneSatisfied = true;
13454
13455 foreach ($rule->getLiterals() as $literal) {
13456 if ($this->decisions->satisfy($literal)) {
13457 $noneSatisfied = false;
13458 break;
13459 }
13460 if ($literal > 0 && $this->decisions->undecided($literal)) {
13461 $decisionQueue[] = $literal;
13462 }
13463 }
13464
13465 if ($noneSatisfied && count($decisionQueue)) {
13466
13467  
13468  if (count($this->installed) != count($this->updateMap)) {
13469 $prunedQueue = array();
13470 foreach ($decisionQueue as $literal) {
13471 if (isset($this->installedMap[abs($literal)])) {
13472 $prunedQueue[] = $literal;
13473 if (isset($this->updateMap[abs($literal)])) {
13474 $prunedQueue = $decisionQueue;
13475 break;
13476 }
13477 }
13478 }
13479 $decisionQueue = $prunedQueue;
13480 }
13481 }
13482
13483 if ($noneSatisfied && count($decisionQueue)) {
13484 $oLevel = $level;
13485 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
13486
13487 if (0 === $level) {
13488 return;
13489 }
13490 if ($level <= $oLevel) {
13491 break;
13492 }
13493 }
13494 }
13495 }
13496
13497 $systemLevel = $level + 1;
13498
13499
13500  $iterator->next();
13501 if ($iterator->valid()) {
13502 continue;
13503 }
13504 }
13505
13506 if ($level < $systemLevel) {
13507 $systemLevel = $level;
13508 }
13509
13510 $rulesCount = count($this->rules);
13511
13512 for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
13513 if ($i == $rulesCount) {
13514 $i = 0;
13515 }
13516
13517 $rule = $this->rules->ruleById[$i];
13518 $literals = $rule->getLiterals();
13519
13520 if ($rule->isDisabled()) {
13521 continue;
13522 }
13523
13524 $decisionQueue = array();
13525
13526
13527  
13528  
13529  
13530  
13531  
13532  foreach ($literals as $literal) {
13533 if ($literal <= 0) {
13534 if (!$this->decisions->decidedInstall(abs($literal))) {
13535 continue 2; 
13536  }
13537 } else {
13538 if ($this->decisions->decidedInstall(abs($literal))) {
13539 continue 2; 
13540  }
13541 if ($this->decisions->undecided(abs($literal))) {
13542 $decisionQueue[] = $literal;
13543 }
13544 }
13545 }
13546
13547
13548  if (count($decisionQueue) < 2) {
13549 continue;
13550 }
13551
13552 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
13553
13554 if (0 === $level) {
13555 return;
13556 }
13557
13558
13559  $rulesCount = count($this->rules);
13560 $n = -1;
13561 }
13562
13563 if ($level < $systemLevel) {
13564 continue;
13565 }
13566
13567
13568  if (count($this->branches)) {
13569 $lastLiteral = null;
13570 $lastLevel = null;
13571 $lastBranchIndex = 0;
13572 $lastBranchOffset = 0;
13573
13574 for ($i = count($this->branches) - 1; $i >= 0; $i--) {
13575 list($literals, $l) = $this->branches[$i];
13576
13577 foreach ($literals as $offset => $literal) {
13578 if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
13579 $lastLiteral = $literal;
13580 $lastBranchIndex = $i;
13581 $lastBranchOffset = $offset;
13582 $lastLevel = $l;
13583 }
13584 }
13585 }
13586
13587 if ($lastLiteral) {
13588 unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
13589
13590 $level = $lastLevel;
13591 $this->revert($level);
13592
13593 $why = $this->decisions->lastReason();
13594
13595 $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
13596
13597 if ($level == 0) {
13598 return;
13599 }
13600
13601 continue;
13602 }
13603 }
13604
13605 break;
13606 }
13607 }
13608 }
13609 <?php
13610
13611
13612
13613
13614
13615
13616
13617
13618
13619
13620
13621 namespace Composer\DependencyResolver;
13622
13623
13624
13625
13626 class SolverBugException extends \RuntimeException
13627 {
13628 public function __construct($message)
13629 {
13630 parent::__construct(
13631 $message."\nThis exception was most likely caused by a bug in Composer.\n".
13632 "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");
13633 }
13634 }
13635 <?php
13636
13637
13638
13639
13640
13641
13642
13643
13644
13645
13646
13647 namespace Composer\DependencyResolver;
13648
13649 use Composer\Util\IniHelper;
13650
13651
13652
13653
13654 class SolverProblemsException extends \RuntimeException
13655 {
13656 protected $problems;
13657 protected $installedMap;
13658
13659 public function __construct(array $problems, array $installedMap)
13660 {
13661 $this->problems = $problems;
13662 $this->installedMap = $installedMap;
13663
13664 parent::__construct($this->createMessage(), 2);
13665 }
13666
13667 protected function createMessage()
13668 {
13669 $text = "\n";
13670 $hasExtensionProblems = false;
13671 foreach ($this->problems as $i => $problem) {
13672 $text .= "  Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
13673
13674 if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
13675 $hasExtensionProblems = true;
13676 }
13677 }
13678
13679 if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
13680 $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\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
13681 }
13682
13683 if ($hasExtensionProblems) {
13684 $text .= $this->createExtensionHint();
13685 }
13686
13687 return $text;
13688 }
13689
13690 public function getProblems()
13691 {
13692 return $this->problems;
13693 }
13694
13695 private function createExtensionHint()
13696 {
13697 $paths = IniHelper::getAll();
13698
13699 if (count($paths) === 1 && empty($paths[0])) {
13700 return '';
13701 }
13702
13703 $text = "\n  To enable extensions, verify that they are enabled in your .ini files:\n    - ";
13704 $text .= implode("\n    - ", $paths);
13705 $text .= "\n  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
13706
13707 return $text;
13708 }
13709
13710 private function hasExtensionProblems(array $reasonSets)
13711 {
13712 foreach ($reasonSets as $reasonSet) {
13713 foreach ($reasonSet as $reason) {
13714 if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
13715 return true;
13716 }
13717 }
13718 }
13719
13720 return false;
13721 }
13722 }
13723 <?php
13724
13725
13726
13727
13728
13729
13730
13731
13732
13733
13734
13735 namespace Composer\DependencyResolver;
13736
13737 use Composer\Package\AliasPackage;
13738
13739
13740
13741
13742 class Transaction
13743 {
13744 protected $policy;
13745 protected $pool;
13746 protected $installedMap;
13747 protected $decisions;
13748 protected $transaction;
13749
13750 public function __construct($policy, $pool, $installedMap, $decisions)
13751 {
13752 $this->policy = $policy;
13753 $this->pool = $pool;
13754 $this->installedMap = $installedMap;
13755 $this->decisions = $decisions;
13756 $this->transaction = array();
13757 }
13758
13759 public function getOperations()
13760 {
13761 $installMeansUpdateMap = $this->findUpdates();
13762
13763 $updateMap = array();
13764 $installMap = array();
13765 $uninstallMap = array();
13766
13767 foreach ($this->decisions as $i => $decision) {
13768 $literal = $decision[Decisions::DECISION_LITERAL];
13769 $reason = $decision[Decisions::DECISION_REASON];
13770
13771 $package = $this->pool->literalToPackage($literal);
13772
13773
13774  if (($literal > 0) == (isset($this->installedMap[$package->id]))) {
13775 continue;
13776 }
13777
13778 if ($literal > 0) {
13779 if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
13780 $source = $installMeansUpdateMap[abs($literal)];
13781
13782 $updateMap[$package->id] = array(
13783 'package' => $package,
13784 'source' => $source,
13785 'reason' => $reason,
13786 );
13787
13788
13789  unset($installMeansUpdateMap[abs($literal)]);
13790 $ignoreRemove[$source->id] = true;
13791 } else {
13792 $installMap[$package->id] = array(
13793 'package' => $package,
13794 'reason' => $reason,
13795 );
13796 }
13797 }
13798 }
13799
13800 foreach ($this->decisions as $i => $decision) {
13801 $literal = $decision[Decisions::DECISION_LITERAL];
13802 $reason = $decision[Decisions::DECISION_REASON];
13803 $package = $this->pool->literalToPackage($literal);
13804
13805 if ($literal <= 0 &&
13806 isset($this->installedMap[$package->id]) &&
13807 !isset($ignoreRemove[$package->id])) {
13808 $uninstallMap[$package->id] = array(
13809 'package' => $package,
13810 'reason' => $reason,
13811 );
13812 }
13813 }
13814
13815 $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
13816
13817 return $this->transaction;
13818 }
13819
13820 protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
13821 {
13822 $queue = array_map(
13823 function ($operation) {
13824 return $operation['package'];
13825 },
13826 $this->findRootPackages($installMap, $updateMap)
13827 );
13828
13829 $visited = array();
13830
13831 while (!empty($queue)) {
13832 $package = array_pop($queue);
13833 $packageId = $package->id;
13834
13835 if (!isset($visited[$packageId])) {
13836 array_push($queue, $package);
13837
13838 if ($package instanceof AliasPackage) {
13839 array_push($queue, $package->getAliasOf());
13840 } else {
13841 foreach ($package->getRequires() as $link) {
13842 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
13843
13844 foreach ($possibleRequires as $require) {
13845 array_push($queue, $require);
13846 }
13847 }
13848 }
13849
13850 $visited[$package->id] = true;
13851 } else {
13852 if (isset($installMap[$packageId])) {
13853 $this->install(
13854 $installMap[$packageId]['package'],
13855 $installMap[$packageId]['reason']
13856 );
13857 unset($installMap[$packageId]);
13858 }
13859 if (isset($updateMap[$packageId])) {
13860 $this->update(
13861 $updateMap[$packageId]['source'],
13862 $updateMap[$packageId]['package'],
13863 $updateMap[$packageId]['reason']
13864 );
13865 unset($updateMap[$packageId]);
13866 }
13867 }
13868 }
13869
13870 foreach ($uninstallMap as $uninstall) {
13871 $this->uninstall($uninstall['package'], $uninstall['reason']);
13872 }
13873 }
13874
13875 protected function findRootPackages($installMap, $updateMap)
13876 {
13877 $packages = $installMap + $updateMap;
13878 $roots = $packages;
13879
13880 foreach ($packages as $packageId => $operation) {
13881 $package = $operation['package'];
13882
13883 if (!isset($roots[$packageId])) {
13884 continue;
13885 }
13886
13887 foreach ($package->getRequires() as $link) {
13888 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
13889
13890 foreach ($possibleRequires as $require) {
13891 if ($require !== $package) {
13892 unset($roots[$require->id]);
13893 }
13894 }
13895 }
13896 }
13897
13898 return $roots;
13899 }
13900
13901 protected function findUpdates()
13902 {
13903 $installMeansUpdateMap = array();
13904
13905 foreach ($this->decisions as $i => $decision) {
13906 $literal = $decision[Decisions::DECISION_LITERAL];
13907 $package = $this->pool->literalToPackage($literal);
13908
13909 if ($package instanceof AliasPackage) {
13910 continue;
13911 }
13912
13913
13914  if ($literal <= 0 && isset($this->installedMap[$package->id])) {
13915 $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
13916
13917 $literals = array($package->id);
13918
13919 foreach ($updates as $update) {
13920 $literals[] = $update->id;
13921 }
13922
13923 foreach ($literals as $updateLiteral) {
13924 if ($updateLiteral !== $literal) {
13925 $installMeansUpdateMap[abs($updateLiteral)] = $package;
13926 }
13927 }
13928 }
13929 }
13930
13931 return $installMeansUpdateMap;
13932 }
13933
13934 protected function install($package, $reason)
13935 {
13936 if ($package instanceof AliasPackage) {
13937 return $this->markAliasInstalled($package, $reason);
13938 }
13939
13940 $this->transaction[] = new Operation\InstallOperation($package, $reason);
13941 }
13942
13943 protected function update($from, $to, $reason)
13944 {
13945 $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
13946 }
13947
13948 protected function uninstall($package, $reason)
13949 {
13950 if ($package instanceof AliasPackage) {
13951 return $this->markAliasUninstalled($package, $reason);
13952 }
13953
13954 $this->transaction[] = new Operation\UninstallOperation($package, $reason);
13955 }
13956
13957 protected function markAliasInstalled($package, $reason)
13958 {
13959 $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
13960 }
13961
13962 protected function markAliasUninstalled($package, $reason)
13963 {
13964 $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
13965 }
13966 }
13967 <?php
13968
13969
13970
13971
13972
13973
13974
13975
13976
13977
13978
13979 namespace Composer\Downloader;
13980
13981 use Composer\Package\PackageInterface;
13982 use Symfony\Component\Finder\Finder;
13983 use Composer\IO\IOInterface;
13984
13985
13986
13987
13988
13989
13990
13991
13992 abstract class ArchiveDownloader extends FileDownloader
13993 {
13994
13995
13996
13997 public function download(PackageInterface $package, $path, $output = true)
13998 {
13999 $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
14000 $retries = 3;
14001 while ($retries--) {
14002 $fileName = parent::download($package, $path, $output);
14003
14004 $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
14005
14006 try {
14007 $this->filesystem->ensureDirectoryExists($temporaryDir);
14008 try {
14009 $this->extract($fileName, $temporaryDir);
14010 } catch (\Exception $e) {
14011
14012  parent::clearLastCacheWrite($package);
14013 throw $e;
14014 }
14015
14016 $this->filesystem->unlink($fileName);
14017
14018 $contentDir = $this->getFolderContent($temporaryDir);
14019
14020
14021  if (1 === count($contentDir) && is_dir(reset($contentDir))) {
14022 $contentDir = $this->getFolderContent((string) reset($contentDir));
14023 }
14024
14025
14026  foreach ($contentDir as $file) {
14027 $file = (string) $file;
14028 $this->filesystem->rename($file, $path . '/' . basename($file));
14029 }
14030
14031 $this->filesystem->removeDirectory($temporaryDir);
14032 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
14033 $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
14034 }
14035 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
14036 $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
14037 }
14038 } catch (\Exception $e) {
14039
14040  $this->filesystem->removeDirectory($path);
14041 $this->filesystem->removeDirectory($temporaryDir);
14042
14043
14044  if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
14045 $this->io->writeError('');
14046 if ($this->io->isDebug()) {
14047 $this->io->writeError('    Invalid zip file ('.$e->getMessage().'), retrying...');
14048 } else {
14049 $this->io->writeError('    Invalid zip file, retrying...');
14050 }
14051 usleep(500000);
14052 continue;
14053 }
14054
14055 throw $e;
14056 }
14057
14058 break;
14059 }
14060 }
14061
14062
14063
14064
14065 protected function getFileName(PackageInterface $package, $path)
14066 {
14067 return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
14068 }
14069
14070
14071
14072
14073 protected function processUrl(PackageInterface $package, $url)
14074 {
14075 if ($package->getDistReference() && strpos($url, 'github.com')) {
14076 if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
14077
14078  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
14079 } elseif ($package->getDistReference() && preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
14080
14081  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
14082 } elseif ($package->getDistReference() && preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
14083
14084  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
14085 }
14086 } elseif ($package->getDistReference() && strpos($url, 'bitbucket.org')) {
14087 if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
14088
14089  $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $package->getDistReference() . '.' . $match[4];
14090 }
14091 }
14092
14093 return parent::processUrl($package, $url);
14094 }
14095
14096
14097
14098
14099
14100
14101
14102
14103
14104 abstract protected function extract($file, $path);
14105
14106
14107
14108
14109
14110
14111
14112 private function getFolderContent($dir)
14113 {
14114 $finder = Finder::create()
14115 ->ignoreVCS(false)
14116 ->ignoreDotFiles(false)
14117 ->depth(0)
14118 ->in($dir);
14119
14120 return iterator_to_array($finder);
14121 }
14122 }
14123 <?php
14124
14125
14126
14127
14128
14129
14130
14131
14132
14133
14134
14135 namespace Composer\Downloader;
14136
14137 use Composer\Package\PackageInterface;
14138
14139
14140
14141
14142
14143
14144 interface ChangeReportInterface
14145 {
14146
14147
14148
14149
14150
14151
14152
14153 public function getLocalChanges(PackageInterface $package, $path);
14154 }
14155 <?php
14156
14157
14158
14159
14160
14161
14162
14163
14164
14165
14166
14167 namespace Composer\Downloader;
14168
14169 use Composer\Package\PackageInterface;
14170 use Composer\IO\IOInterface;
14171 use Composer\Util\Filesystem;
14172
14173
14174
14175
14176
14177
14178 class DownloadManager
14179 {
14180 private $io;
14181 private $preferDist = false;
14182 private $preferSource = false;
14183 private $packagePreferences = array();
14184 private $filesystem;
14185 private $downloaders = array();
14186
14187
14188
14189
14190
14191
14192
14193
14194 public function __construct(IOInterface $io, $preferSource = false, Filesystem $filesystem = null)
14195 {
14196 $this->io = $io;
14197 $this->preferSource = $preferSource;
14198 $this->filesystem = $filesystem ?: new Filesystem();
14199 }
14200
14201
14202
14203
14204
14205
14206
14207 public function setPreferSource($preferSource)
14208 {
14209 $this->preferSource = $preferSource;
14210
14211 return $this;
14212 }
14213
14214
14215
14216
14217
14218
14219
14220 public function setPreferDist($preferDist)
14221 {
14222 $this->preferDist = $preferDist;
14223
14224 return $this;
14225 }
14226
14227
14228
14229
14230
14231
14232
14233 public function setPreferences(array $preferences)
14234 {
14235 $this->packagePreferences = $preferences;
14236
14237 return $this;
14238 }
14239
14240
14241
14242
14243
14244
14245
14246
14247 public function setOutputProgress($outputProgress)
14248 {
14249 foreach ($this->downloaders as $downloader) {
14250 $downloader->setOutputProgress($outputProgress);
14251 }
14252
14253 return $this;
14254 }
14255
14256
14257
14258
14259
14260
14261
14262
14263 public function setDownloader($type, DownloaderInterface $downloader)
14264 {
14265 $type = strtolower($type);
14266 $this->downloaders[$type] = $downloader;
14267
14268 return $this;
14269 }
14270
14271
14272
14273
14274
14275
14276
14277
14278 public function getDownloader($type)
14279 {
14280 $type = strtolower($type);
14281 if (!isset($this->downloaders[$type])) {
14282 throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
14283 }
14284
14285 return $this->downloaders[$type];
14286 }
14287
14288
14289
14290
14291
14292
14293
14294
14295
14296
14297 public function getDownloaderForInstalledPackage(PackageInterface $package)
14298 {
14299 $installationSource = $package->getInstallationSource();
14300
14301 if ('metapackage' === $package->getType()) {
14302 return;
14303 }
14304
14305 if ('dist' === $installationSource) {
14306 $downloader = $this->getDownloader($package->getDistType());
14307 } elseif ('source' === $installationSource) {
14308 $downloader = $this->getDownloader($package->getSourceType());
14309 } else {
14310 throw new \InvalidArgumentException(
14311 'Package '.$package.' seems not been installed properly'
14312 );
14313 }
14314
14315 if ($installationSource !== $downloader->getInstallationSource()) {
14316 throw new \LogicException(sprintf(
14317 'Downloader "%s" is a %s type downloader and can not be used to download %s',
14318 get_class($downloader), $downloader->getInstallationSource(), $installationSource
14319 ));
14320 }
14321
14322 return $downloader;
14323 }
14324
14325
14326
14327
14328
14329
14330
14331
14332
14333
14334
14335 public function download(PackageInterface $package, $targetDir, $preferSource = null)
14336 {
14337 $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
14338 $sourceType = $package->getSourceType();
14339 $distType = $package->getDistType();
14340
14341 $sources = array();
14342 if ($sourceType) {
14343 $sources[] = 'source';
14344 }
14345 if ($distType) {
14346 $sources[] = 'dist';
14347 }
14348
14349 if (empty($sources)) {
14350 throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
14351 }
14352
14353 if (!$preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
14354 $sources = array_reverse($sources);
14355 }
14356
14357 $this->filesystem->ensureDirectoryExists($targetDir);
14358
14359 foreach ($sources as $i => $source) {
14360 if (isset($e)) {
14361 $this->io->writeError('    <warning>Now trying to download from ' . $source . '</warning>');
14362 }
14363 $package->setInstallationSource($source);
14364 try {
14365 $downloader = $this->getDownloaderForInstalledPackage($package);
14366 if ($downloader) {
14367 $downloader->download($package, $targetDir);
14368 }
14369 break;
14370 } catch (\RuntimeException $e) {
14371 if ($i === count($sources) - 1) {
14372 throw $e;
14373 }
14374
14375 $this->io->writeError(
14376 '    <warning>Failed to download '.
14377 $package->getPrettyName().
14378 ' from ' . $source . ': '.
14379 $e->getMessage().'</warning>'
14380 );
14381 }
14382 }
14383 }
14384
14385
14386
14387
14388
14389
14390
14391
14392
14393
14394 public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
14395 {
14396 $downloader = $this->getDownloaderForInstalledPackage($initial);
14397 if (!$downloader) {
14398 return;
14399 }
14400
14401 $installationSource = $initial->getInstallationSource();
14402
14403 if ('dist' === $installationSource) {
14404 $initialType = $initial->getDistType();
14405 $targetType = $target->getDistType();
14406 } else {
14407 $initialType = $initial->getSourceType();
14408 $targetType = $target->getSourceType();
14409 }
14410
14411
14412  if ($target->isDev() && 'dist' === $installationSource) {
14413 $downloader->remove($initial, $targetDir);
14414 $this->download($target, $targetDir);
14415
14416 return;
14417 }
14418
14419 if ($initialType === $targetType) {
14420 $target->setInstallationSource($installationSource);
14421 try {
14422 $downloader->update($initial, $target, $targetDir);
14423
14424 return;
14425 } catch (\RuntimeException $e) {
14426 if (!$this->io->isInteractive()) {
14427 throw $e;
14428 }
14429 $this->io->writeError('<error>    Update failed ('.$e->getMessage().')</error>');
14430 if (!$this->io->askConfirmation('    Would you like to try reinstalling the package instead [<comment>yes</comment>]? ', true)) {
14431 throw $e;
14432 }
14433 }
14434 }
14435
14436 $downloader->remove($initial, $targetDir);
14437 $this->download($target, $targetDir, 'source' === $installationSource);
14438 }
14439
14440
14441
14442
14443
14444
14445
14446 public function remove(PackageInterface $package, $targetDir)
14447 {
14448 $downloader = $this->getDownloaderForInstalledPackage($package);
14449 if ($downloader) {
14450 $downloader->remove($package, $targetDir);
14451 }
14452 }
14453
14454
14455
14456
14457
14458
14459
14460
14461 protected function resolvePackageInstallPreference(PackageInterface $package)
14462 {
14463 foreach ($this->packagePreferences as $pattern => $preference) {
14464 $pattern = '{^'.str_replace('\\*', '.*', preg_quote($pattern)).'$}i';
14465 if (preg_match($pattern, $package->getName())) {
14466 if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) {
14467 return 'dist';
14468 }
14469
14470 return 'source';
14471 }
14472 }
14473
14474 return $package->isDev() ? 'source' : 'dist';
14475 }
14476 }
14477 <?php
14478
14479
14480
14481
14482
14483
14484
14485
14486
14487
14488
14489 namespace Composer\Downloader;
14490
14491 use Composer\Package\PackageInterface;
14492
14493
14494
14495
14496
14497
14498
14499 interface DownloaderInterface
14500 {
14501
14502
14503
14504
14505
14506 public function getInstallationSource();
14507
14508
14509
14510
14511
14512
14513
14514 public function download(PackageInterface $package, $path);
14515
14516
14517
14518
14519
14520
14521
14522
14523 public function update(PackageInterface $initial, PackageInterface $target, $path);
14524
14525
14526
14527
14528
14529
14530
14531 public function remove(PackageInterface $package, $path);
14532
14533
14534
14535
14536
14537
14538
14539 public function setOutputProgress($outputProgress);
14540 }
14541 <?php
14542
14543
14544
14545
14546
14547
14548
14549
14550
14551
14552
14553 namespace Composer\Downloader;
14554
14555 use Composer\Package\PackageInterface;
14556
14557
14558
14559
14560
14561
14562 interface DvcsDownloaderInterface
14563 {
14564
14565
14566
14567
14568
14569
14570
14571 public function getUnpushedChanges(PackageInterface $package, $path);
14572 }
14573 <?php
14574
14575
14576
14577
14578
14579
14580
14581
14582
14583
14584
14585 namespace Composer\Downloader;
14586
14587 use Composer\Config;
14588 use Composer\Cache;
14589 use Composer\Factory;
14590 use Composer\IO\IOInterface;
14591 use Composer\Package\PackageInterface;
14592 use Composer\Plugin\PluginEvents;
14593 use Composer\Plugin\PreFileDownloadEvent;
14594 use Composer\EventDispatcher\EventDispatcher;
14595 use Composer\Util\Filesystem;
14596 use Composer\Util\RemoteFilesystem;
14597
14598
14599
14600
14601
14602
14603
14604
14605
14606 class FileDownloader implements DownloaderInterface
14607 {
14608 protected $io;
14609 protected $config;
14610 protected $rfs;
14611 protected $filesystem;
14612 protected $cache;
14613 protected $outputProgress = true;
14614 private $lastCacheWrites = array();
14615 private $eventDispatcher;
14616
14617
14618
14619
14620
14621
14622
14623
14624
14625
14626
14627 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
14628 {
14629 $this->io = $io;
14630 $this->config = $config;
14631 $this->eventDispatcher = $eventDispatcher;
14632 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
14633 $this->filesystem = $filesystem ?: new Filesystem();
14634 $this->cache = $cache;
14635
14636 if ($this->cache && $this->cache->gcIsNecessary()) {
14637 $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
14638 }
14639 }
14640
14641
14642
14643
14644 public function getInstallationSource()
14645 {
14646 return 'dist';
14647 }
14648
14649
14650
14651
14652 public function download(PackageInterface $package, $path, $output = true)
14653 {
14654 if (!$package->getDistUrl()) {
14655 throw new \InvalidArgumentException('The given package is missing url information');
14656 }
14657
14658 if ($output) {
14659 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
14660 }
14661
14662 $urls = $package->getDistUrls();
14663 while ($url = array_shift($urls)) {
14664 try {
14665 $fileName = $this->doDownload($package, $path, $url);
14666 break;
14667 } catch (\Exception $e) {
14668 if ($this->io->isDebug()) {
14669 $this->io->writeError('');
14670 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
14671 } elseif (count($urls)) {
14672 $this->io->writeError('');
14673 $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
14674 }
14675
14676 if (!count($urls)) {
14677 throw $e;
14678 }
14679 }
14680 }
14681
14682 if ($output) {
14683 $this->io->writeError('');
14684 }
14685
14686 return $fileName;
14687 }
14688
14689 protected function doDownload(PackageInterface $package, $path, $url)
14690 {
14691 $this->filesystem->emptyDirectory($path);
14692
14693 $fileName = $this->getFileName($package, $path);
14694
14695 $processedUrl = $this->processUrl($package, $url);
14696 $hostname = parse_url($processedUrl, PHP_URL_HOST);
14697
14698 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
14699 if ($this->eventDispatcher) {
14700 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
14701 }
14702 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
14703
14704 try {
14705 $checksum = $package->getDistSha1Checksum();
14706 $cacheKey = $this->getCacheKey($package, $processedUrl);
14707
14708
14709  if (!$this->cache || ($checksum && $checksum !== $this->cache->sha1($cacheKey)) || !$this->cache->copyTo($cacheKey, $fileName)) {
14710 if (!$this->outputProgress) {
14711 $this->io->writeError('Downloading', false);
14712 }
14713
14714
14715  $retries = 3;
14716 while ($retries--) {
14717 try {
14718 $rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
14719 break;
14720 } catch (TransportException $e) {
14721
14722  if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
14723 throw $e;
14724 }
14725 $this->io->writeError('');
14726 $this->io->writeError('    Download failed, retrying...', true, IOInterface::VERBOSE);
14727 usleep(500000);
14728 }
14729 }
14730
14731 if (!$this->outputProgress) {
14732 $this->io->writeError(' (<comment>100%</comment>)', false);
14733 }
14734
14735 if ($this->cache) {
14736 $this->lastCacheWrites[$package->getName()] = $cacheKey;
14737 $this->cache->copyFrom($cacheKey, $fileName);
14738 }
14739 } else {
14740 $this->io->writeError('Loading from cache', false);
14741 }
14742
14743 if (!file_exists($fileName)) {
14744 throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
14745 .' directory is writable and you have internet connectivity');
14746 }
14747
14748 if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
14749 throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
14750 }
14751 } catch (\Exception $e) {
14752
14753  $this->filesystem->removeDirectory($path);
14754 $this->clearLastCacheWrite($package);
14755 throw $e;
14756 }
14757
14758 return $fileName;
14759 }
14760
14761
14762
14763
14764 public function setOutputProgress($outputProgress)
14765 {
14766 $this->outputProgress = $outputProgress;
14767
14768 return $this;
14769 }
14770
14771 protected function clearLastCacheWrite(PackageInterface $package)
14772 {
14773 if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
14774 $this->cache->remove($this->lastCacheWrites[$package->getName()]);
14775 unset($this->lastCacheWrites[$package->getName()]);
14776 }
14777 }
14778
14779
14780
14781
14782 public function update(PackageInterface $initial, PackageInterface $target, $path)
14783 {
14784 $name = $target->getName();
14785 $from = $initial->getPrettyVersion();
14786 $to = $target->getPrettyVersion();
14787
14788 $this->io->writeError("  - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
14789
14790 $this->remove($initial, $path, false);
14791 $this->download($target, $path, false);
14792
14793 $this->io->writeError('');
14794 }
14795
14796
14797
14798
14799 public function remove(PackageInterface $package, $path, $output = true)
14800 {
14801 if ($output) {
14802 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
14803 }
14804 if (!$this->filesystem->removeDirectory($path)) {
14805 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
14806 }
14807 }
14808
14809
14810
14811
14812
14813
14814
14815
14816 protected function getFileName(PackageInterface $package, $path)
14817 {
14818 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
14819 }
14820
14821
14822
14823
14824
14825
14826
14827
14828
14829 protected function processUrl(PackageInterface $package, $url)
14830 {
14831 if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
14832 throw new \RuntimeException('You must enable the openssl extension to download files via https');
14833 }
14834
14835 return $url;
14836 }
14837
14838 private function getCacheKey(PackageInterface $package, $processedUrl)
14839 {
14840
14841  
14842  
14843  
14844  $cacheKey = sha1($processedUrl);
14845
14846 return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
14847 }
14848 }
14849 <?php
14850
14851
14852
14853
14854
14855
14856
14857
14858
14859
14860
14861 namespace Composer\Downloader;
14862
14863
14864
14865
14866
14867
14868 class FilesystemException extends \Exception
14869 {
14870 public function __construct($message = '', $code = 0, \Exception $previous = null)
14871 {
14872 parent::__construct("Filesystem exception: \n".$message, $code, $previous);
14873 }
14874 }
14875 <?php
14876
14877
14878
14879
14880
14881
14882
14883
14884
14885
14886
14887 namespace Composer\Downloader;
14888
14889 use Composer\Package\PackageInterface;
14890 use Composer\Util\ProcessExecutor;
14891
14892
14893
14894
14895 class FossilDownloader extends VcsDownloader
14896 {
14897
14898
14899
14900 public function doDownload(PackageInterface $package, $path, $url)
14901 {
14902
14903  $this->config->prohibitUrlByConfig($url, $this->io);
14904
14905 $url = ProcessExecutor::escape($url);
14906 $ref = ProcessExecutor::escape($package->getSourceReference());
14907 $repoFile = $path . '.fossil';
14908 $this->io->writeError("Cloning ".$package->getSourceReference());
14909 $command = sprintf('fossil clone %s %s', $url, ProcessExecutor::escape($repoFile));
14910 if (0 !== $this->process->execute($command, $ignoredOutput)) {
14911 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14912 }
14913 $command = sprintf('fossil open %s', ProcessExecutor::escape($repoFile));
14914 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
14915 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14916 }
14917 $command = sprintf('fossil update %s', $ref);
14918 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
14919 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14920 }
14921 }
14922
14923
14924
14925
14926 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
14927 {
14928
14929  $this->config->prohibitUrlByConfig($url, $this->io);
14930
14931 $url = ProcessExecutor::escape($url);
14932 $ref = ProcessExecutor::escape($target->getSourceReference());
14933 $this->io->writeError(" Updating to ".$target->getSourceReference());
14934
14935 if (!$this->hasMetadataRepository($path)) {
14936 throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
14937 }
14938
14939 $command = sprintf('fossil pull && fossil up %s', $ref);
14940 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
14941 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14942 }
14943 }
14944
14945
14946
14947
14948 public function getLocalChanges(PackageInterface $package, $path)
14949 {
14950 if (!$this->hasMetadataRepository($path)) {
14951 return null;
14952 }
14953
14954 $this->process->execute('fossil changes', $output, realpath($path));
14955
14956 return trim($output) ?: null;
14957 }
14958
14959
14960
14961
14962 protected function getCommitLogs($fromReference, $toReference, $path)
14963 {
14964 $command = sprintf('fossil timeline -t ci -W 0 -n 0 before %s', $toReference);
14965
14966 if (0 !== $this->process->execute($command, $output, realpath($path))) {
14967 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14968 }
14969
14970 $log = '';
14971 $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
14972
14973 foreach ($this->process->splitLines($output) as $line) {
14974 if (preg_match($match, $line)) {
14975 break;
14976 }
14977 $log .= $line;
14978 }
14979
14980 return $log;
14981 }
14982
14983
14984
14985
14986 protected function hasMetadataRepository($path)
14987 {
14988 return is_file($path . '/.fslckout') || is_file($path . '/_FOSSIL_');
14989 }
14990 }
14991 <?php
14992
14993
14994
14995
14996
14997
14998
14999
15000
15001
15002
15003 namespace Composer\Downloader;
15004
15005 use Composer\Package\PackageInterface;
15006 use Composer\Util\Git as GitUtil;
15007 use Composer\Util\Platform;
15008 use Composer\Util\ProcessExecutor;
15009 use Composer\IO\IOInterface;
15010 use Composer\Util\Filesystem;
15011 use Composer\Config;
15012
15013
15014
15015
15016 class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
15017 {
15018 private $hasStashedChanges = false;
15019 private $hasDiscardedChanges = false;
15020 private $gitUtil;
15021
15022 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
15023 {
15024 parent::__construct($io, $config, $process, $fs);
15025 $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
15026 }
15027
15028
15029
15030
15031 public function doDownload(PackageInterface $package, $path, $url)
15032 {
15033 GitUtil::cleanEnv();
15034 $path = $this->normalizePath($path);
15035 $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
15036 $cacheOptions = '';
15037 $ref = $package->getSourceReference();
15038 $flag = Platform::isWindows() ? '/D ' : '';
15039
15040
15041  $gitVersion = $this->gitUtil->getVersion();
15042 $msg = "Cloning ".$this->getShortHash($ref);
15043 if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=')) {
15044 $this->io->writeError('', true, IOInterface::DEBUG);
15045 $this->io->writeError(sprintf('    Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
15046 try {
15047 $this->gitUtil->syncMirror($url, $cachePath);
15048 if (is_dir($cachePath)) {
15049 $cacheOptions = sprintf('--dissociate --reference %s ', ProcessExecutor::escape($cachePath));
15050 $msg = "Cloning ".$this->getShortHash($ref).' from cache';
15051 }
15052 } catch (\RuntimeException $e) {
15053 }
15054 }
15055 $command = 'git clone --no-checkout %s %s '.$cacheOptions.'&& cd '.$flag.'%2$s && git remote add composer %1$s && git fetch composer';
15056 $this->io->writeError($msg);
15057
15058 $commandCallable = function ($url) use ($ref, $path, $command) {
15059 return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($path), ProcessExecutor::escape($ref));
15060 };
15061
15062 $this->gitUtil->runCommand($commandCallable, $url, $path, true);
15063 if ($url !== $package->getSourceUrl()) {
15064 $this->updateOriginUrl($path, $package->getSourceUrl());
15065 } else {
15066 $this->setPushUrl($path, $url);
15067 }
15068
15069 if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
15070 if ($package->getDistReference() === $package->getSourceReference()) {
15071 $package->setDistReference($newRef);
15072 }
15073 $package->setSourceReference($newRef);
15074 }
15075 }
15076
15077
15078
15079
15080 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15081 {
15082 GitUtil::cleanEnv();
15083 if (!$this->hasMetadataRepository($path)) {
15084 throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15085 }
15086
15087 $updateOriginUrl = false;
15088 if (
15089 0 === $this->process->execute('git remote -v', $output, $path)
15090 && preg_match('{^origin\s+(?P<url>\S+)}m', $output, $originMatch)
15091 && preg_match('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)
15092 ) {
15093 if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
15094 $updateOriginUrl = true;
15095 }
15096 }
15097
15098 $ref = $target->getSourceReference();
15099 $this->io->writeError(" Checking out ".$this->getShortHash($ref));
15100 $command = 'git remote set-url composer %s && git rev-parse --quiet --verify %s^{commit} || (git fetch composer && git fetch --tags composer)';
15101
15102 $commandCallable = function ($url) use ($command, $ref) {
15103 return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($ref));
15104 };
15105
15106 $this->gitUtil->runCommand($commandCallable, $url, $path);
15107 if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
15108 if ($target->getDistReference() === $target->getSourceReference()) {
15109 $target->setDistReference($newRef);
15110 }
15111 $target->setSourceReference($newRef);
15112 }
15113
15114 if ($updateOriginUrl) {
15115 $this->updateOriginUrl($path, $target->getSourceUrl());
15116 }
15117 }
15118
15119
15120
15121
15122 public function getLocalChanges(PackageInterface $package, $path)
15123 {
15124 GitUtil::cleanEnv();
15125 if (!$this->hasMetadataRepository($path)) {
15126 return;
15127 }
15128
15129 $command = 'git status --porcelain --untracked-files=no';
15130 if (0 !== $this->process->execute($command, $output, $path)) {
15131 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15132 }
15133
15134 return trim($output) ?: null;
15135 }
15136
15137 public function getUnpushedChanges(PackageInterface $package, $path)
15138 {
15139 GitUtil::cleanEnv();
15140 $path = $this->normalizePath($path);
15141 if (!$this->hasMetadataRepository($path)) {
15142 return;
15143 }
15144
15145 $command = 'git show-ref --head -d';
15146 if (0 !== $this->process->execute($command, $output, $path)) {
15147 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15148 }
15149
15150 $refs = trim($output);
15151 if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
15152
15153  return;
15154 }
15155
15156 $headRef = $match[1];
15157 if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
15158
15159  return;
15160 }
15161
15162
15163  $branch = $matches[1][0];
15164 $unpushedChanges = null;
15165
15166
15167  for ($i = 0; $i <= 1; $i++) {
15168
15169  foreach ($matches[1] as $candidate) {
15170 if (preg_match('{^[a-f0-9]+ refs/remotes/((?:composer|origin)/'.preg_quote($candidate).')$}mi', $refs, $match)) {
15171 $branch = $candidate;
15172 $remoteBranch = $match[1];
15173 break;
15174 }
15175 }
15176
15177
15178  
15179  
15180  if (!isset($remoteBranch)) {
15181 $unpushedChanges = 'Branch ' . $branch . ' could not be found on the origin remote and appears to be unpushed';
15182 } else {
15183 $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
15184 if (0 !== $this->process->execute($command, $output, $path)) {
15185 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15186 }
15187
15188 $unpushedChanges = trim($output) ?: null;
15189 }
15190
15191
15192  
15193  if ($unpushedChanges && $i === 0) {
15194 $this->process->execute('git fetch composer && git fetch origin', $output, $path);
15195 }
15196
15197
15198  if (!$unpushedChanges) {
15199 break;
15200 }
15201 }
15202
15203 return $unpushedChanges;
15204 }
15205
15206
15207
15208
15209 protected function cleanChanges(PackageInterface $package, $path, $update)
15210 {
15211 GitUtil::cleanEnv();
15212 $path = $this->normalizePath($path);
15213
15214 $unpushed = $this->getUnpushedChanges($package, $path);
15215 if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== true)) {
15216 throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: '."\n".$unpushed);
15217 }
15218
15219 if (!$changes = $this->getLocalChanges($package, $path)) {
15220 return;
15221 }
15222
15223 if (!$this->io->isInteractive()) {
15224 $discardChanges = $this->config->get('discard-changes');
15225 if (true === $discardChanges) {
15226 return $this->discardChanges($path);
15227 }
15228 if ('stash' === $discardChanges) {
15229 if (!$update) {
15230 return parent::cleanChanges($package, $path, $update);
15231 }
15232
15233 return $this->stashChanges($path);
15234 }
15235
15236 return parent::cleanChanges($package, $path, $update);
15237 }
15238
15239 $changes = array_map(function ($elem) {
15240 return '    '.$elem;
15241 }, preg_split('{\s*\r?\n\s*}', $changes));
15242 $this->io->writeError('    <error>The package has modified files:</error>');
15243 $this->io->writeError(array_slice($changes, 0, 10));
15244 if (count($changes) > 10) {
15245 $this->io->writeError('    <info>' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list</info>');
15246 }
15247
15248 while (true) {
15249 switch ($this->io->ask('    <info>Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]?</info> ', '?')) {
15250 case 'y':
15251 $this->discardChanges($path);
15252 break 2;
15253
15254 case 's':
15255 if (!$update) {
15256 goto help;
15257 }
15258
15259 $this->stashChanges($path);
15260 break 2;
15261
15262 case 'n':
15263 throw new \RuntimeException('Update aborted');
15264
15265 case 'v':
15266 $this->io->writeError($changes);
15267 break;
15268
15269 case 'd':
15270 $this->viewDiff($path);
15271 break;
15272
15273 case '?':
15274 default:
15275 help:
15276 $this->io->writeError(array(
15277 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
15278 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
15279 '    v - view modified files',
15280 '    d - view local modifications (diff)',
15281 ));
15282 if ($update) {
15283 $this->io->writeError('    s - stash changes and try to reapply them after the update');
15284 }
15285 $this->io->writeError('    ? - print help');
15286 break;
15287 }
15288 }
15289 }
15290
15291
15292
15293
15294 protected function reapplyChanges($path)
15295 {
15296 $path = $this->normalizePath($path);
15297 if ($this->hasStashedChanges) {
15298 $this->hasStashedChanges = false;
15299 $this->io->writeError('    <info>Re-applying stashed changes</info>');
15300 if (0 !== $this->process->execute('git stash pop', $output, $path)) {
15301 throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
15302 }
15303 }
15304
15305 $this->hasDiscardedChanges = false;
15306 }
15307
15308
15309
15310
15311
15312
15313
15314
15315
15316
15317
15318 protected function updateToCommit($path, $reference, $branch, $date)
15319 {
15320 $force = $this->hasDiscardedChanges || $this->hasStashedChanges ? '-f ' : '';
15321
15322
15323  
15324  
15325  
15326  
15327  $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
15328 $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);
15329
15330 $branches = null;
15331 if (0 === $this->process->execute('git branch -r', $output, $path)) {
15332 $branches = $output;
15333 }
15334
15335
15336  $gitRef = $reference;
15337 if (!preg_match('{^[a-f0-9]{40}$}', $reference)
15338 && $branches
15339 && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
15340 ) {
15341 $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
15342 if (0 === $this->process->execute($command, $output, $path)) {
15343 return;
15344 }
15345 }
15346
15347
15348  if (preg_match('{^[a-f0-9]{40}$}', $reference)) {
15349
15350  if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) {
15351 $branch = 'v' . $branch;
15352 }
15353
15354 $command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
15355 $fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
15356 if (0 === $this->process->execute($command, $output, $path)
15357 || 0 === $this->process->execute($fallbackCommand, $output, $path)
15358 ) {
15359 $command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
15360 if (0 === $this->process->execute($command, $output, $path)) {
15361 return;
15362 }
15363 }
15364 }
15365
15366 $command = sprintf($template, ProcessExecutor::escape($gitRef));
15367 if (0 === $this->process->execute($command, $output, $path)) {
15368 return;
15369 }
15370
15371
15372  if (false !== strpos($this->process->getErrorOutput(), $reference)) {
15373 $this->io->writeError('    <warning>'.$reference.' is gone (history was rewritten?)</warning>');
15374 }
15375
15376 throw new \RuntimeException(GitUtil::sanitizeUrl('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
15377 }
15378
15379 protected function updateOriginUrl($path, $url)
15380 {
15381 $this->process->execute(sprintf('git remote set-url origin %s', ProcessExecutor::escape($url)), $output, $path);
15382 $this->setPushUrl($path, $url);
15383 }
15384
15385 protected function setPushUrl($path, $url)
15386 {
15387
15388  if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
15389 $protocols = $this->config->get('github-protocols');
15390 $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git';
15391 if (!in_array('ssh', $protocols, true)) {
15392 $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
15393 }
15394 $cmd = sprintf('git remote set-url --push origin %s', ProcessExecutor::escape($pushUrl));
15395 $this->process->execute($cmd, $ignoredOutput, $path);
15396 }
15397 }
15398
15399
15400
15401
15402 protected function getCommitLogs($fromReference, $toReference, $path)
15403 {
15404 $path = $this->normalizePath($path);
15405 $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', $fromReference, $toReference);
15406
15407 if (0 !== $this->process->execute($command, $output, $path)) {
15408 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15409 }
15410
15411 return $output;
15412 }
15413
15414
15415
15416
15417
15418 protected function discardChanges($path)
15419 {
15420 $path = $this->normalizePath($path);
15421 if (0 !== $this->process->execute('git reset --hard', $output, $path)) {
15422 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
15423 }
15424
15425 $this->hasDiscardedChanges = true;
15426 }
15427
15428
15429
15430
15431
15432 protected function stashChanges($path)
15433 {
15434 $path = $this->normalizePath($path);
15435 if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
15436 throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
15437 }
15438
15439 $this->hasStashedChanges = true;
15440 }
15441
15442
15443
15444
15445
15446 protected function viewDiff($path)
15447 {
15448 $path = $this->normalizePath($path);
15449 if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
15450 throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
15451 }
15452
15453 $this->io->writeError($output);
15454 }
15455
15456 protected function normalizePath($path)
15457 {
15458 if (Platform::isWindows() && strlen($path) > 0) {
15459 $basePath = $path;
15460 $removed = array();
15461
15462 while (!is_dir($basePath) && $basePath !== '\\') {
15463 array_unshift($removed, basename($basePath));
15464 $basePath = dirname($basePath);
15465 }
15466
15467 if ($basePath === '\\') {
15468 return $path;
15469 }
15470
15471 $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
15472 }
15473
15474 return $path;
15475 }
15476
15477
15478
15479
15480 protected function hasMetadataRepository($path)
15481 {
15482 $path = $this->normalizePath($path);
15483
15484 return is_dir($path.'/.git');
15485 }
15486
15487 protected function getShortHash($reference)
15488 {
15489 if (!$this->io->isVerbose() && preg_match('{^[0-9a-f]{40}$}', $reference)) {
15490 return substr($reference, 0, 10);
15491 }
15492
15493 return $reference;
15494 }
15495 }
15496 <?php
15497
15498
15499
15500
15501
15502
15503
15504
15505
15506
15507
15508 namespace Composer\Downloader;
15509
15510 use Composer\Config;
15511 use Composer\Cache;
15512 use Composer\EventDispatcher\EventDispatcher;
15513 use Composer\Package\PackageInterface;
15514 use Composer\Util\Platform;
15515 use Composer\Util\ProcessExecutor;
15516 use Composer\Util\RemoteFilesystem;
15517 use Composer\IO\IOInterface;
15518
15519
15520
15521
15522
15523
15524 class GzipDownloader extends ArchiveDownloader
15525 {
15526 protected $process;
15527
15528 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
15529 {
15530 $this->process = $process ?: new ProcessExecutor($io);
15531 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
15532 }
15533
15534 protected function extract($file, $path)
15535 {
15536 $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
15537
15538
15539  if (!Platform::isWindows()) {
15540 $command = 'gzip -cd ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
15541
15542 if (0 === $this->process->execute($command, $ignoredOutput)) {
15543 return;
15544 }
15545
15546 if (extension_loaded('zlib')) {
15547
15548  $this->extractUsingExt($file, $targetFilepath);
15549
15550 return;
15551 }
15552
15553 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
15554 throw new \RuntimeException($processError);
15555 }
15556
15557
15558  $this->extractUsingExt($file, $targetFilepath);
15559 }
15560
15561
15562
15563
15564 protected function getFileName(PackageInterface $package, $path)
15565 {
15566 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
15567 }
15568
15569 private function extractUsingExt($file, $targetFilepath)
15570 {
15571 $archiveFile = gzopen($file, 'rb');
15572 $targetFile = fopen($targetFilepath, 'wb');
15573 while ($string = gzread($archiveFile, 4096)) {
15574 fwrite($targetFile, $string, Platform::strlen($string));
15575 }
15576 gzclose($archiveFile);
15577 fclose($targetFile);
15578 }
15579 }
15580 <?php
15581
15582
15583
15584
15585
15586
15587
15588
15589
15590
15591
15592 namespace Composer\Downloader;
15593
15594 use Composer\Package\PackageInterface;
15595 use Composer\Util\ProcessExecutor;
15596
15597
15598
15599
15600 class HgDownloader extends VcsDownloader
15601 {
15602
15603
15604
15605 public function doDownload(PackageInterface $package, $path, $url)
15606 {
15607
15608  $this->config->prohibitUrlByConfig($url, $this->io);
15609
15610 $url = ProcessExecutor::escape($url);
15611 $ref = ProcessExecutor::escape($package->getSourceReference());
15612 $this->io->writeError("Cloning ".$package->getSourceReference());
15613 $command = sprintf('hg clone %s %s', $url, ProcessExecutor::escape($path));
15614 if (0 !== $this->process->execute($command, $ignoredOutput)) {
15615 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15616 }
15617 $command = sprintf('hg up %s', $ref);
15618 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15619 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15620 }
15621 }
15622
15623
15624
15625
15626 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15627 {
15628
15629  $this->config->prohibitUrlByConfig($url, $this->io);
15630
15631 $url = ProcessExecutor::escape($url);
15632 $ref = ProcessExecutor::escape($target->getSourceReference());
15633 $this->io->writeError(" Updating to ".$target->getSourceReference());
15634
15635 if (!$this->hasMetadataRepository($path)) {
15636 throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15637 }
15638
15639 $command = sprintf('hg pull %s && hg up %s', $url, $ref);
15640 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15641 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15642 }
15643 }
15644
15645
15646
15647
15648 public function getLocalChanges(PackageInterface $package, $path)
15649 {
15650 if (!is_dir($path.'/.hg')) {
15651 return null;
15652 }
15653
15654 $this->process->execute('hg st', $output, realpath($path));
15655
15656 return trim($output) ?: null;
15657 }
15658
15659
15660
15661
15662 protected function getCommitLogs($fromReference, $toReference, $path)
15663 {
15664 $command = sprintf('hg log -r %s:%s --style compact', $fromReference, $toReference);
15665
15666 if (0 !== $this->process->execute($command, $output, realpath($path))) {
15667 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15668 }
15669
15670 return $output;
15671 }
15672
15673
15674
15675
15676 protected function hasMetadataRepository($path)
15677 {
15678 return is_dir($path . '/.hg');
15679 }
15680 }
15681 <?php
15682
15683
15684
15685
15686
15687
15688
15689
15690
15691
15692
15693 namespace Composer\Downloader;
15694
15695 use Composer\Package\Dumper\ArrayDumper;
15696 use Composer\Package\PackageInterface;
15697 use Composer\Package\Version\VersionGuesser;
15698 use Composer\Package\Version\VersionParser;
15699 use Composer\Util\Platform;
15700 use Composer\Util\ProcessExecutor;
15701 use Symfony\Component\Filesystem\Exception\IOException;
15702 use Symfony\Component\Filesystem\Filesystem;
15703
15704
15705
15706
15707
15708
15709
15710 class PathDownloader extends FileDownloader implements VcsCapableDownloaderInterface
15711 {
15712 const STRATEGY_SYMLINK = 10;
15713 const STRATEGY_MIRROR = 20;
15714
15715
15716
15717
15718 public function download(PackageInterface $package, $path, $output = true)
15719 {
15720 $url = $package->getDistUrl();
15721 $realUrl = realpath($url);
15722 if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
15723 throw new \RuntimeException(sprintf(
15724 'Source path "%s" is not found for package %s', $url, $package->getName()
15725 ));
15726 }
15727
15728 if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
15729
15730  
15731  
15732  
15733  throw new \RuntimeException(sprintf(
15734 'Package %s cannot install to "%s" inside its source at "%s"',
15735 $package->getName(), realpath($path), $realUrl
15736 ));
15737 }
15738
15739
15740  $transportOptions = $package->getTransportOptions() + array('symlink' => null);
15741
15742
15743  $currentStrategy = self::STRATEGY_SYMLINK;
15744 $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
15745
15746 $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
15747 if ($mirrorPathRepos) {
15748 $currentStrategy = self::STRATEGY_MIRROR;
15749 }
15750
15751 if (true === $transportOptions['symlink']) {
15752 $currentStrategy = self::STRATEGY_SYMLINK;
15753 $allowedStrategies = array(self::STRATEGY_SYMLINK);
15754 } elseif (false === $transportOptions['symlink']) {
15755 $currentStrategy = self::STRATEGY_MIRROR;
15756 $allowedStrategies = array(self::STRATEGY_MIRROR);
15757 }
15758
15759 $fileSystem = new Filesystem();
15760 $this->filesystem->removeDirectory($path);
15761
15762 if ($output) {
15763 $this->io->writeError(sprintf(
15764 '  - Installing <info>%s</info> (<comment>%s</comment>): ',
15765 $package->getName(),
15766 $package->getFullPrettyVersion()
15767 ), false);
15768 }
15769
15770 $isFallback = false;
15771 if (self::STRATEGY_SYMLINK == $currentStrategy) {
15772 try {
15773 if (Platform::isWindows()) {
15774
15775  $this->io->writeError(sprintf('Junctioning from %s', $url), false);
15776 $this->filesystem->junction($realUrl, $path);
15777 } else {
15778 $absolutePath = $path;
15779 if (!$this->filesystem->isAbsolutePath($absolutePath)) {
15780 $absolutePath = getcwd() . DIRECTORY_SEPARATOR . $path;
15781 }
15782 $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
15783 $path = rtrim($path, "/");
15784 $this->io->writeError(sprintf('Symlinking from %s', $url), false);
15785 $fileSystem->symlink($shortestPath, $path);
15786 }
15787 } catch (IOException $e) {
15788 if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
15789 $this->io->writeError('');
15790 $this->io->writeError('    <error>Symlink failed, fallback to use mirroring!</error>');
15791 $currentStrategy = self::STRATEGY_MIRROR;
15792 $isFallback = true;
15793 } else {
15794 throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
15795 }
15796 }
15797 }
15798
15799
15800  if (self::STRATEGY_MIRROR == $currentStrategy) {
15801 $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? '    ' : '', $url), false);
15802 $fileSystem->mirror($realUrl, $path);
15803 }
15804
15805 $this->io->writeError('');
15806 }
15807
15808
15809
15810
15811 public function remove(PackageInterface $package, $path, $output = true)
15812 {
15813
15814
15815
15816
15817
15818 if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
15819 if ($output) {
15820 $this->io->writeError("  - Removing junction for <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
15821 }
15822 if (!$this->filesystem->removeJunction($path)) {
15823 $this->io->writeError("    <warn>Could not remove junction at " . $path . " - is another process locking it?</warn>");
15824 throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
15825 }
15826 } else {
15827 parent::remove($package, $path, $output);
15828 }
15829 }
15830
15831
15832
15833
15834 public function getVcsReference(PackageInterface $package, $path)
15835 {
15836 $parser = new VersionParser;
15837 $guesser = new VersionGuesser($this->config, new ProcessExecutor($this->io), $parser);
15838 $dumper = new ArrayDumper;
15839
15840 $packageConfig = $dumper->dump($package);
15841 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
15842 return $packageVersion['commit'];
15843 }
15844 }
15845 }
15846 <?php
15847
15848
15849
15850
15851
15852
15853
15854
15855
15856
15857
15858 namespace Composer\Downloader;
15859
15860 use Composer\Util\Filesystem;
15861
15862
15863
15864
15865
15866
15867
15868
15869
15870
15871 class PearPackageExtractor
15872 {
15873 private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
15874
15875 private $filesystem;
15876 private $file;
15877
15878 public function __construct($file)
15879 {
15880 if (!is_file($file)) {
15881 throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
15882 }
15883
15884 $this->filesystem = new Filesystem();
15885 $this->file = $file;
15886 }
15887
15888
15889
15890
15891
15892
15893
15894
15895
15896
15897 public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
15898 {
15899 $extractionPath = $target.'/tarball';
15900
15901 try {
15902 $archive = new \PharData($this->file);
15903 $archive->extractTo($extractionPath, null, true);
15904
15905 if (!is_file($this->combine($extractionPath, '/package.xml'))) {
15906 throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
15907 }
15908
15909 $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
15910 $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
15911 $this->filesystem->removeDirectory($extractionPath);
15912 } catch (\Exception $exception) {
15913 throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
15914 }
15915 }
15916
15917
15918
15919
15920
15921
15922
15923
15924
15925
15926 private function copyFiles($files, $source, $target, $roles, $vars)
15927 {
15928 foreach ($files as $file) {
15929 $from = $this->combine($source, $file['from']);
15930 $to = $this->combine($target, $roles[$file['role']]);
15931 $to = $this->combine($to, $file['to']);
15932 $tasks = $file['tasks'];
15933 $this->copyFile($from, $to, $tasks, $vars);
15934 }
15935 }
15936
15937 private function copyFile($from, $to, $tasks, $vars)
15938 {
15939 if (!is_file($from)) {
15940 throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
15941 }
15942
15943 $this->filesystem->ensureDirectoryExists(dirname($to));
15944
15945 if (0 == count($tasks)) {
15946 $copied = copy($from, $to);
15947 } else {
15948 $content = file_get_contents($from);
15949 $replacements = array();
15950 foreach ($tasks as $task) {
15951 $pattern = $task['from'];
15952 $varName = $task['to'];
15953 if (isset($vars[$varName])) {
15954 if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
15955 $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
15956 } else {
15957 $replacements[$pattern] = $vars[$varName];
15958 }
15959 }
15960 }
15961 $content = strtr($content, $replacements);
15962
15963 $copied = file_put_contents($to, $content);
15964 }
15965
15966 if (false === $copied) {
15967 throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
15968 }
15969 }
15970
15971
15972
15973
15974
15975
15976
15977
15978
15979
15980
15981 private function buildCopyActions($source, array $roles, $vars)
15982 {
15983
15984 $package = simplexml_load_string(file_get_contents($this->combine($source, 'package.xml')));
15985 if (false === $package) {
15986 throw new \RuntimeException('Package definition file is not valid.');
15987 }
15988
15989 $packageSchemaVersion = $package['version'];
15990 if ('1.0' == $packageSchemaVersion) {
15991 $children = $package->release->filelist->children();
15992 $packageName = (string) $package->name;
15993 $packageVersion = (string) $package->release->version;
15994 $sourceDir = $packageName . '-' . $packageVersion;
15995 $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
15996 } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
15997 $children = $package->contents->children();
15998 $packageName = (string) $package->name;
15999 $packageVersion = (string) $package->version->release;
16000 $sourceDir = $packageName . '-' . $packageVersion;
16001 $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
16002
16003 $namespaces = $package->getNamespaces();
16004 $package->registerXPathNamespace('ns', $namespaces['']);
16005 $releaseNodes = $package->xpath('ns:phprelease');
16006 $this->applyRelease($result, $releaseNodes, $vars);
16007 } else {
16008 throw new \RuntimeException('Unsupported schema version of package definition file.');
16009 }
16010
16011 return $result;
16012 }
16013
16014 private function applyRelease(&$actions, $releaseNodes, $vars)
16015 {
16016 foreach ($releaseNodes as $releaseNode) {
16017 $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
16018 if ($requiredOs && $vars['os'] != $requiredOs) {
16019 continue;
16020 }
16021
16022 if ($releaseNode->filelist) {
16023 foreach ($releaseNode->filelist->children() as $action) {
16024 if ('install' == $action->getName()) {
16025 $name = (string) $action['name'];
16026 $as = (string) $action['as'];
16027 if (isset($actions[$name])) {
16028 $actions[$name]['to'] = $as;
16029 }
16030 } elseif ('ignore' == $action->getName()) {
16031 $name = (string) $action['name'];
16032 unset($actions[$name]);
16033 } else {
16034
16035  }
16036 }
16037 }
16038 break;
16039 }
16040 }
16041
16042 private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
16043 {
16044 $result = array();
16045
16046
16047  foreach ($children as $child) {
16048
16049 if ($child->getName() == 'dir') {
16050 $dirSource = $this->combine($source, (string) $child['name']);
16051 $dirTarget = $child['baseinstalldir'] ?: $target;
16052 $dirRole = $child['role'] ?: $role;
16053 $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16054 $result = array_merge($result, $dirFiles);
16055 } elseif ($child->getName() == 'file') {
16056 $fileRole = (string) $child['role'] ?: $role;
16057 if (isset($targetRoles[$fileRole])) {
16058 $fileName = (string) ($child['name'] ?: $child[0]); 
16059  $fileSource = $this->combine($source, $fileName);
16060 $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
16061 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16062 $fileTarget = $packageName . '/' . $fileTarget;
16063 }
16064 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
16065 }
16066 }
16067 }
16068
16069 return $result;
16070 }
16071
16072 private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
16073 {
16074 $result = array();
16075
16076
16077  foreach ($children as $child) {
16078
16079 if ('dir' == $child->getName()) {
16080 $dirSource = $this->combine($source, $child['name']);
16081 $dirTarget = $child['baseinstalldir'] ?: $target;
16082 $dirRole = $child['role'] ?: $role;
16083 $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16084 $result = array_merge($result, $dirFiles);
16085 } elseif ('file' == $child->getName()) {
16086 $fileRole = (string) $child['role'] ?: $role;
16087 if (isset($targetRoles[$fileRole])) {
16088 $fileSource = $this->combine($source, (string) $child['name']);
16089 $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
16090 $fileTasks = array();
16091 foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
16092 if ('replace' == $taskNode->getName()) {
16093 $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
16094 }
16095 }
16096 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16097 $fileTarget = $packageName . '/' . $fileTarget;
16098 }
16099 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
16100 }
16101 }
16102 }
16103
16104 return $result;
16105 }
16106
16107 private function combine($left, $right)
16108 {
16109 return rtrim($left, '/') . '/' . ltrim($right, '/');
16110 }
16111 }
16112 <?php
16113
16114
16115
16116
16117
16118
16119
16120
16121
16122
16123
16124 namespace Composer\Downloader;
16125
16126 use Composer\Package\PackageInterface;
16127 use Composer\Repository\VcsRepository;
16128 use Composer\Util\Perforce;
16129
16130
16131
16132
16133 class PerforceDownloader extends VcsDownloader
16134 {
16135
16136 protected $perforce;
16137
16138
16139
16140
16141 public function doDownload(PackageInterface $package, $path, $url)
16142 {
16143 $ref = $package->getSourceReference();
16144 $label = $this->getLabelFromSourceReference($ref);
16145
16146 $this->io->writeError('Cloning ' . $ref);
16147 $this->initPerforce($package, $path, $url);
16148 $this->perforce->setStream($ref);
16149 $this->perforce->p4Login();
16150 $this->perforce->writeP4ClientSpec();
16151 $this->perforce->connectClient();
16152 $this->perforce->syncCodeBase($label);
16153 $this->perforce->cleanupClientSpec();
16154 }
16155
16156 private function getLabelFromSourceReference($ref)
16157 {
16158 $pos = strpos($ref, '@');
16159 if (false !== $pos) {
16160 return substr($ref, $pos + 1);
16161 }
16162
16163 return null;
16164 }
16165
16166 public function initPerforce(PackageInterface $package, $path, $url)
16167 {
16168 if (!empty($this->perforce)) {
16169 $this->perforce->initializePath($path);
16170
16171 return;
16172 }
16173
16174 $repository = $package->getRepository();
16175 $repoConfig = null;
16176 if ($repository instanceof VcsRepository) {
16177 $repoConfig = $this->getRepoConfig($repository);
16178 }
16179 $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
16180 }
16181
16182 private function getRepoConfig(VcsRepository $repository)
16183 {
16184 return $repository->getRepoConfig();
16185 }
16186
16187
16188
16189
16190 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16191 {
16192 $this->doDownload($target, $path, $url);
16193 }
16194
16195
16196
16197
16198 public function getLocalChanges(PackageInterface $package, $path)
16199 {
16200 $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
16201
16202 return;
16203 }
16204
16205
16206
16207
16208 protected function getCommitLogs($fromReference, $toReference, $path)
16209 {
16210 $commitLogs = $this->perforce->getCommitLogs($fromReference, $toReference);
16211
16212 return $commitLogs;
16213 }
16214
16215 public function setPerforce($perforce)
16216 {
16217 $this->perforce = $perforce;
16218 }
16219
16220
16221
16222
16223 protected function hasMetadataRepository($path)
16224 {
16225 return true;
16226 }
16227 }
16228 <?php
16229
16230
16231
16232
16233
16234
16235
16236
16237
16238
16239
16240 namespace Composer\Downloader;
16241
16242
16243
16244
16245
16246
16247 class PharDownloader extends ArchiveDownloader
16248 {
16249
16250
16251
16252 protected function extract($file, $path)
16253 {
16254
16255  $archive = new \Phar($file);
16256 $archive->extractTo($path, null, true);
16257
16258
16259
16260
16261
16262 }
16263 }
16264 <?php
16265
16266
16267
16268
16269
16270
16271
16272
16273
16274
16275
16276 namespace Composer\Downloader;
16277
16278 use Composer\Config;
16279 use Composer\Cache;
16280 use Composer\EventDispatcher\EventDispatcher;
16281 use Composer\Util\IniHelper;
16282 use Composer\Util\Platform;
16283 use Composer\Util\ProcessExecutor;
16284 use Composer\Util\RemoteFilesystem;
16285 use Composer\IO\IOInterface;
16286 use RarArchive;
16287
16288
16289
16290
16291
16292
16293
16294
16295 class RarDownloader extends ArchiveDownloader
16296 {
16297 protected $process;
16298
16299 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
16300 {
16301 $this->process = $process ?: new ProcessExecutor($io);
16302 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
16303 }
16304
16305 protected function extract($file, $path)
16306 {
16307 $processError = null;
16308
16309
16310  if (!Platform::isWindows()) {
16311 $command = 'unrar x ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
16312
16313 if (0 === $this->process->execute($command, $ignoredOutput)) {
16314 return;
16315 }
16316
16317 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
16318 }
16319
16320 if (!class_exists('RarArchive')) {
16321
16322  $iniMessage = IniHelper::getMessage();
16323
16324 $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n"
16325 . $iniMessage . "\n" . $processError;
16326
16327 if (!Platform::isWindows()) {
16328 $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
16329 }
16330
16331 throw new \RuntimeException($error);
16332 }
16333
16334 $rarArchive = RarArchive::open($file);
16335
16336 if (false === $rarArchive) {
16337 throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
16338 }
16339
16340 $entries = $rarArchive->getEntries();
16341
16342 if (false === $entries) {
16343 throw new \RuntimeException('Could not retrieve RAR archive entries');
16344 }
16345
16346 foreach ($entries as $entry) {
16347 if (false === $entry->extract($path)) {
16348 throw new \RuntimeException('Could not extract entry');
16349 }
16350 }
16351
16352 $rarArchive->close();
16353 }
16354 }
16355 <?php
16356
16357
16358
16359
16360
16361
16362
16363
16364
16365
16366
16367 namespace Composer\Downloader;
16368
16369 use Composer\Package\PackageInterface;
16370 use Composer\Util\Svn as SvnUtil;
16371 use Composer\Repository\VcsRepository;
16372
16373
16374
16375
16376
16377 class SvnDownloader extends VcsDownloader
16378 {
16379 protected $cacheCredentials = true;
16380
16381
16382
16383
16384 public function doDownload(PackageInterface $package, $path, $url)
16385 {
16386 SvnUtil::cleanEnv();
16387 $ref = $package->getSourceReference();
16388
16389 $repo = $package->getRepository();
16390 if ($repo instanceof VcsRepository) {
16391 $repoConfig = $repo->getRepoConfig();
16392 if (array_key_exists('svn-cache-credentials', $repoConfig)) {
16393 $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials'];
16394 }
16395 }
16396
16397 $this->io->writeError(" Checking out ".$package->getSourceReference());
16398 $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
16399 }
16400
16401
16402
16403
16404 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16405 {
16406 SvnUtil::cleanEnv();
16407 $ref = $target->getSourceReference();
16408
16409 if (!$this->hasMetadataRepository($path)) {
16410 throw new \RuntimeException('The .svn directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16411 }
16412
16413 $flags = "";
16414 if (0 === $this->process->execute('svn --version', $output)) {
16415 if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match) && version_compare($match[1], '1.7.0', '>=')) {
16416 $flags .= ' --ignore-ancestry';
16417 }
16418 }
16419
16420 $this->io->writeError(" Checking out " . $ref);
16421 $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
16422 }
16423
16424
16425
16426
16427 public function getLocalChanges(PackageInterface $package, $path)
16428 {
16429 if (!$this->hasMetadataRepository($path)) {
16430 return null;
16431 }
16432
16433 $this->process->execute('svn status --ignore-externals', $output, $path);
16434
16435 return preg_match('{^ *[^X ] +}m', $output) ? $output : null;
16436 }
16437
16438
16439
16440
16441
16442
16443
16444
16445
16446
16447
16448
16449
16450 protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
16451 {
16452 $util = new SvnUtil($baseUrl, $this->io, $this->config);
16453 $util->setCacheCredentials($this->cacheCredentials);
16454 try {
16455 return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
16456 } catch (\RuntimeException $e) {
16457 throw new \RuntimeException(
16458 'Package could not be downloaded, '.$e->getMessage()
16459 );
16460 }
16461 }
16462
16463
16464
16465
16466 protected function cleanChanges(PackageInterface $package, $path, $update)
16467 {
16468 if (!$changes = $this->getLocalChanges($package, $path)) {
16469 return;
16470 }
16471
16472 if (!$this->io->isInteractive()) {
16473 if (true === $this->config->get('discard-changes')) {
16474 return $this->discardChanges($path);
16475 }
16476
16477 return parent::cleanChanges($package, $path, $update);
16478 }
16479
16480 $changes = array_map(function ($elem) {
16481 return '    '.$elem;
16482 }, preg_split('{\s*\r?\n\s*}', $changes));
16483 $this->io->writeError('    <error>The package has modified files:</error>');
16484 $this->io->writeError(array_slice($changes, 0, 10));
16485 if (count($changes) > 10) {
16486 $this->io->writeError('    <info>'.count($changes) - 10 . ' more files modified, choose "v" to view the full list</info>');
16487 }
16488
16489 while (true) {
16490 switch ($this->io->ask('    <info>Discard changes [y,n,v,?]?</info> ', '?')) {
16491 case 'y':
16492 $this->discardChanges($path);
16493 break 2;
16494
16495 case 'n':
16496 throw new \RuntimeException('Update aborted');
16497
16498 case 'v':
16499 $this->io->writeError($changes);
16500 break;
16501
16502 case '?':
16503 default:
16504 $this->io->writeError(array(
16505 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
16506 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
16507 '    v - view modified files',
16508 '    ? - print help',
16509 ));
16510 break;
16511 }
16512 }
16513 }
16514
16515
16516
16517
16518 protected function getCommitLogs($fromReference, $toReference, $path)
16519 {
16520 if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
16521
16522  $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
16523 $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
16524
16525 $command = sprintf('svn log -r%s:%s --incremental', $fromRevision, $toRevision);
16526
16527 if (0 !== $this->process->execute($command, $output, $path)) {
16528 throw new \RuntimeException(
16529 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
16530 );
16531 }
16532 } else {
16533 $output = "Could not retrieve changes between $fromReference and $toReference due to missing revision information";
16534 }
16535
16536 return $output;
16537 }
16538
16539 protected function discardChanges($path)
16540 {
16541 if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
16542 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
16543 }
16544 }
16545
16546
16547
16548
16549 protected function hasMetadataRepository($path)
16550 {
16551 return is_dir($path.'/.svn');
16552 }
16553 }
16554 <?php
16555
16556
16557
16558
16559
16560
16561
16562
16563
16564
16565
16566 namespace Composer\Downloader;
16567
16568
16569
16570
16571
16572
16573 class TarDownloader extends ArchiveDownloader
16574 {
16575
16576
16577
16578 protected function extract($file, $path)
16579 {
16580
16581  $archive = new \PharData($file);
16582 $archive->extractTo($path, null, true);
16583 }
16584 }
16585 <?php
16586
16587
16588
16589
16590
16591
16592
16593
16594
16595
16596
16597 namespace Composer\Downloader;
16598
16599
16600
16601
16602 class TransportException extends \RuntimeException
16603 {
16604 protected $headers;
16605 protected $response;
16606 protected $statusCode;
16607
16608 public function setHeaders($headers)
16609 {
16610 $this->headers = $headers;
16611 }
16612
16613 public function getHeaders()
16614 {
16615 return $this->headers;
16616 }
16617
16618 public function setResponse($response)
16619 {
16620 $this->response = $response;
16621 }
16622
16623 public function getResponse()
16624 {
16625 return $this->response;
16626 }
16627
16628 public function setStatusCode($statusCode)
16629 {
16630 $this->statusCode = $statusCode;
16631 }
16632
16633 public function getStatusCode()
16634 {
16635 return $this->statusCode;
16636 }
16637 }
16638 <?php
16639
16640
16641
16642
16643
16644
16645
16646
16647
16648
16649
16650 namespace Composer\Downloader;
16651
16652 use Composer\Package\PackageInterface;
16653
16654
16655
16656
16657
16658
16659 interface VcsCapableDownloaderInterface
16660 {
16661
16662
16663
16664
16665
16666
16667
16668 public function getVcsReference(PackageInterface $package, $path);
16669 }
16670 <?php
16671
16672
16673
16674
16675
16676
16677
16678
16679
16680
16681
16682 namespace Composer\Downloader;
16683
16684 use Composer\Config;
16685 use Composer\Package\Dumper\ArrayDumper;
16686 use Composer\Package\PackageInterface;
16687 use Composer\Package\Version\VersionGuesser;
16688 use Composer\Package\Version\VersionParser;
16689 use Composer\Util\ProcessExecutor;
16690 use Composer\IO\IOInterface;
16691 use Composer\Util\Filesystem;
16692
16693
16694
16695
16696 abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterface, VcsCapableDownloaderInterface
16697 {
16698
16699 protected $io;
16700
16701 protected $config;
16702
16703 protected $process;
16704
16705 protected $filesystem;
16706
16707 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
16708 {
16709 $this->io = $io;
16710 $this->config = $config;
16711 $this->process = $process ?: new ProcessExecutor($io);
16712 $this->filesystem = $fs ?: new Filesystem($this->process);
16713 }
16714
16715
16716
16717
16718 public function getInstallationSource()
16719 {
16720 return 'source';
16721 }
16722
16723
16724
16725
16726 public function download(PackageInterface $package, $path)
16727 {
16728 if (!$package->getSourceReference()) {
16729 throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
16730 }
16731
16732 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
16733 $this->filesystem->emptyDirectory($path);
16734
16735 $urls = $package->getSourceUrls();
16736 while ($url = array_shift($urls)) {
16737 try {
16738 if (Filesystem::isLocalPath($url)) {
16739
16740  
16741  $needle = 'file://';
16742 $isFileProtocol = false;
16743 if (0 === strpos($url, $needle)) {
16744 $url = substr($url, strlen($needle));
16745 $isFileProtocol = true;
16746 }
16747
16748
16749  if (false !== strpos($url, '%')) {
16750 $url = rawurldecode($url);
16751 }
16752
16753 $url = realpath($url);
16754
16755 if ($isFileProtocol) {
16756 $url = $needle . $url;
16757 }
16758 }
16759 $this->doDownload($package, $path, $url);
16760 break;
16761 } catch (\Exception $e) {
16762
16763  if ($e instanceof \PHPUnit_Framework_Exception) {
16764 throw $e;
16765 }
16766 if ($this->io->isDebug()) {
16767 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
16768 } elseif (count($urls)) {
16769 $this->io->writeError('    Failed, trying the next URL');
16770 }
16771 if (!count($urls)) {
16772 throw $e;
16773 }
16774 }
16775 }
16776 }
16777
16778
16779
16780
16781 public function update(PackageInterface $initial, PackageInterface $target, $path)
16782 {
16783 if (!$target->getSourceReference()) {
16784 throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
16785 }
16786
16787 $name = $target->getName();
16788 if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
16789 if ($target->getSourceType() === 'svn') {
16790 $from = $initial->getSourceReference();
16791 $to = $target->getSourceReference();
16792 } else {
16793 $from = substr($initial->getSourceReference(), 0, 7);
16794 $to = substr($target->getSourceReference(), 0, 7);
16795 }
16796 $name .= ' '.$initial->getPrettyVersion();
16797 } else {
16798 $from = $initial->getFullPrettyVersion();
16799 $to = $target->getFullPrettyVersion();
16800 }
16801
16802 $this->io->writeError("  - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
16803
16804 $this->cleanChanges($initial, $path, true);
16805 $urls = $target->getSourceUrls();
16806
16807 $exception = null;
16808 while ($url = array_shift($urls)) {
16809 try {
16810 if (Filesystem::isLocalPath($url)) {
16811 $url = realpath($url);
16812 }
16813 $this->doUpdate($initial, $target, $path, $url);
16814
16815 $exception = null;
16816 break;
16817 } catch (\Exception $exception) {
16818
16819  if ($exception instanceof \PHPUnit_Framework_Exception) {
16820 throw $exception;
16821 }
16822 if ($this->io->isDebug()) {
16823 $this->io->writeError('Failed: ['.get_class($exception).'] '.$exception->getMessage());
16824 } elseif (count($urls)) {
16825 $this->io->writeError('    Failed, trying the next URL');
16826 }
16827 }
16828 }
16829
16830 $this->reapplyChanges($path);
16831
16832
16833  
16834  if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
16835 $message = 'Pulling in changes:';
16836 $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
16837
16838 if (!trim($logs)) {
16839 $message = 'Rolling back changes:';
16840 $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
16841 }
16842
16843 if (trim($logs)) {
16844 $logs = implode("\n", array_map(function ($line) {
16845 return '      ' . $line;
16846 }, explode("\n", $logs)));
16847
16848
16849  $logs = str_replace('<', '\<', $logs);
16850
16851 $this->io->writeError('    '.$message);
16852 $this->io->writeError($logs);
16853 }
16854 }
16855
16856 if (!$urls && $exception) {
16857 throw $exception;
16858 }
16859 }
16860
16861
16862
16863
16864 public function remove(PackageInterface $package, $path)
16865 {
16866 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
16867 $this->cleanChanges($package, $path, false);
16868 if (!$this->filesystem->removeDirectory($path)) {
16869 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
16870 }
16871 }
16872
16873
16874
16875
16876
16877 public function setOutputProgress($outputProgress)
16878 {
16879 return $this;
16880 }
16881
16882
16883
16884
16885 public function getVcsReference(PackageInterface $package, $path)
16886 {
16887 $parser = new VersionParser;
16888 $guesser = new VersionGuesser($this->config, $this->process, $parser);
16889 $dumper = new ArrayDumper;
16890
16891 $packageConfig = $dumper->dump($package);
16892 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
16893 return $packageVersion['commit'];
16894 }
16895 }
16896
16897
16898
16899
16900
16901
16902
16903
16904
16905
16906 protected function cleanChanges(PackageInterface $package, $path, $update)
16907 {
16908
16909  if (null !== $this->getLocalChanges($package, $path)) {
16910 throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
16911 }
16912 }
16913
16914
16915
16916
16917
16918
16919
16920 protected function reapplyChanges($path)
16921 {
16922 }
16923
16924
16925
16926
16927
16928
16929
16930
16931 abstract protected function doDownload(PackageInterface $package, $path, $url);
16932
16933
16934
16935
16936
16937
16938
16939
16940
16941 abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
16942
16943
16944
16945
16946
16947
16948
16949
16950
16951 abstract protected function getCommitLogs($fromReference, $toReference, $path);
16952
16953
16954
16955
16956
16957
16958
16959
16960 abstract protected function hasMetadataRepository($path);
16961 }
16962 <?php
16963
16964
16965
16966
16967
16968
16969
16970
16971
16972
16973
16974 namespace Composer\Downloader;
16975
16976 use Composer\Config;
16977 use Composer\Cache;
16978 use Composer\EventDispatcher\EventDispatcher;
16979 use Composer\Package\PackageInterface;
16980 use Composer\Util\ProcessExecutor;
16981 use Composer\Util\RemoteFilesystem;
16982 use Composer\IO\IOInterface;
16983
16984
16985
16986
16987
16988
16989
16990 class XzDownloader extends ArchiveDownloader
16991 {
16992 protected $process;
16993
16994 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
16995 {
16996 $this->process = $process ?: new ProcessExecutor($io);
16997
16998 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
16999 }
17000
17001 protected function extract($file, $path)
17002 {
17003 $command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
17004
17005 if (0 === $this->process->execute($command, $ignoredOutput)) {
17006 return;
17007 }
17008
17009 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
17010
17011 throw new \RuntimeException($processError);
17012 }
17013
17014
17015
17016
17017 protected function getFileName(PackageInterface $package, $path)
17018 {
17019 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
17020 }
17021 }
17022 <?php
17023
17024
17025
17026
17027
17028
17029
17030
17031
17032
17033
17034 namespace Composer\Downloader;
17035
17036 use Composer\Config;
17037 use Composer\Cache;
17038 use Composer\EventDispatcher\EventDispatcher;
17039 use Composer\Package\PackageInterface;
17040 use Composer\Util\IniHelper;
17041 use Composer\Util\Platform;
17042 use Composer\Util\ProcessExecutor;
17043 use Composer\Util\RemoteFilesystem;
17044 use Composer\IO\IOInterface;
17045 use Symfony\Component\Process\ExecutableFinder;
17046 use ZipArchive;
17047
17048
17049
17050
17051 class ZipDownloader extends ArchiveDownloader
17052 {
17053 protected static $hasSystemUnzip;
17054 private static $hasZipArchive;
17055 private static $isWindows;
17056
17057 protected $process;
17058 private $zipArchiveObject;
17059
17060 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17061 {
17062 $this->process = $process ?: new ProcessExecutor($io);
17063 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17064 }
17065
17066
17067
17068
17069 public function download(PackageInterface $package, $path, $output = true)
17070 {
17071 if (null === self::$hasSystemUnzip) {
17072 $finder = new ExecutableFinder;
17073 self::$hasSystemUnzip = (bool) $finder->find('unzip');
17074 }
17075
17076 if (null === self::$hasZipArchive) {
17077 self::$hasZipArchive = class_exists('ZipArchive');
17078 }
17079
17080 if (null === self::$isWindows) {
17081 self::$isWindows = Platform::isWindows();
17082 }
17083
17084 if (!self::$hasZipArchive && !self::$hasSystemUnzip) {
17085
17086  $iniMessage = IniHelper::getMessage();
17087 $error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
17088
17089 throw new \RuntimeException($error);
17090 }
17091
17092 return parent::download($package, $path, $output);
17093 }
17094
17095
17096
17097
17098
17099
17100
17101
17102
17103 protected function extractWithSystemUnzip($file, $path, $isLastChance)
17104 {
17105 if (!self::$hasZipArchive) {
17106
17107  $isLastChance = true;
17108 }
17109
17110 if (!self::$hasSystemUnzip && !$isLastChance) {
17111
17112  
17113  return $this->extractWithZipArchive($file, $path, true);
17114 }
17115
17116 $processError = null;
17117
17118  $overwrite = $isLastChance ? '-o' : '';
17119
17120 $command = 'unzip -qq '.$overwrite.' '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
17121
17122 try {
17123 if (0 === $this->process->execute($command, $ignoredOutput)) {
17124 return true;
17125 }
17126
17127 $processError = new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17128 } catch (\Exception $e) {
17129 $processError = $e;
17130 }
17131
17132 if ($isLastChance) {
17133 throw $processError;
17134 }
17135
17136 $this->io->writeError('    '.$processError->getMessage());
17137 $this->io->writeError('    The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
17138 $this->io->writeError('    Unzip with unzip command failed, falling back to ZipArchive class');
17139
17140 return $this->extractWithZipArchive($file, $path, true);
17141 }
17142
17143
17144
17145
17146
17147
17148
17149
17150
17151 protected function extractWithZipArchive($file, $path, $isLastChance)
17152 {
17153 if (!self::$hasSystemUnzip) {
17154
17155  $isLastChance = true;
17156 }
17157
17158 if (!self::$hasZipArchive && !$isLastChance) {
17159
17160  
17161  return $this->extractWithSystemUnzip($file, $path, true);
17162 }
17163
17164 $processError = null;
17165 $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
17166
17167 try {
17168 if (true === ($retval = $zipArchive->open($file))) {
17169 $extractResult = $zipArchive->extractTo($path);
17170
17171 if (true === $extractResult) {
17172 $zipArchive->close();
17173
17174 return true;
17175 }
17176
17177 $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
17178 } else {
17179 $processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file)."\n"), $retval);
17180 }
17181 } catch (\ErrorException $e) {
17182 $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
17183 } catch (\Exception $e) {
17184 $processError = $e;
17185 }
17186
17187 if ($isLastChance) {
17188 throw $processError;
17189 }
17190
17191 $this->io->writeError('    '.$processError->getMessage());
17192 $this->io->writeError('    Unzip with ZipArchive class failed, falling back to unzip command');
17193
17194 return $this->extractWithSystemUnzip($file, $path, true);
17195 }
17196
17197
17198
17199
17200
17201
17202
17203 public function extract($file, $path)
17204 {
17205
17206  if (self::$isWindows) {
17207 $this->extractWithZipArchive($file, $path, false);
17208 } else {
17209 $this->extractWithSystemUnzip($file, $path, false);
17210 }
17211 }
17212
17213
17214
17215
17216
17217
17218
17219
17220 protected function getErrorMessage($retval, $file)
17221 {
17222 switch ($retval) {
17223 case ZipArchive::ER_EXISTS:
17224 return sprintf("File '%s' already exists.", $file);
17225 case ZipArchive::ER_INCONS:
17226 return sprintf("Zip archive '%s' is inconsistent.", $file);
17227 case ZipArchive::ER_INVAL:
17228 return sprintf("Invalid argument (%s)", $file);
17229 case ZipArchive::ER_MEMORY:
17230 return sprintf("Malloc failure (%s)", $file);
17231 case ZipArchive::ER_NOENT:
17232 return sprintf("No such zip file: '%s'", $file);
17233 case ZipArchive::ER_NOZIP:
17234 return sprintf("'%s' is not a zip archive.", $file);
17235 case ZipArchive::ER_OPEN:
17236 return sprintf("Can't open zip file: %s", $file);
17237 case ZipArchive::ER_READ:
17238 return sprintf("Zip read error (%s)", $file);
17239 case ZipArchive::ER_SEEK:
17240 return sprintf("Zip seek error (%s)", $file);
17241 default:
17242 return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
17243 }
17244 }
17245 }
17246 <?php
17247
17248
17249
17250
17251
17252
17253
17254
17255
17256
17257
17258 namespace Composer\EventDispatcher;
17259
17260
17261
17262
17263
17264
17265 class Event
17266 {
17267
17268
17269
17270 protected $name;
17271
17272
17273
17274
17275 protected $args;
17276
17277
17278
17279
17280 protected $flags;
17281
17282
17283
17284
17285 private $propagationStopped = false;
17286
17287
17288
17289
17290
17291
17292
17293
17294 public function __construct($name, array $args = array(), array $flags = array())
17295 {
17296 $this->name = $name;
17297 $this->args = $args;
17298 $this->flags = $flags;
17299 }
17300
17301
17302
17303
17304
17305
17306 public function getName()
17307 {
17308 return $this->name;
17309 }
17310
17311
17312
17313
17314
17315
17316 public function getArguments()
17317 {
17318 return $this->args;
17319 }
17320
17321
17322
17323
17324
17325
17326 public function getFlags()
17327 {
17328 return $this->flags;
17329 }
17330
17331
17332
17333
17334
17335
17336 public function isPropagationStopped()
17337 {
17338 return $this->propagationStopped;
17339 }
17340
17341
17342
17343
17344 public function stopPropagation()
17345 {
17346 $this->propagationStopped = true;
17347 }
17348 }
17349 <?php
17350
17351
17352
17353
17354
17355
17356
17357
17358
17359
17360
17361 namespace Composer\EventDispatcher;
17362
17363 use Composer\DependencyResolver\PolicyInterface;
17364 use Composer\DependencyResolver\Pool;
17365 use Composer\DependencyResolver\Request;
17366 use Composer\Installer\InstallerEvent;
17367 use Composer\IO\IOInterface;
17368 use Composer\Composer;
17369 use Composer\DependencyResolver\Operation\OperationInterface;
17370 use Composer\Repository\CompositeRepository;
17371 use Composer\Script;
17372 use Composer\Installer\PackageEvent;
17373 use Composer\Installer\BinaryInstaller;
17374 use Composer\Util\ProcessExecutor;
17375 use Composer\Script\Event as ScriptEvent;
17376 use Symfony\Component\Process\PhpExecutableFinder;
17377
17378
17379
17380
17381
17382
17383
17384
17385
17386
17387
17388
17389
17390
17391 class EventDispatcher
17392 {
17393 protected $composer;
17394 protected $io;
17395 protected $loader;
17396 protected $process;
17397 protected $listeners;
17398 private $eventStack;
17399
17400
17401
17402
17403
17404
17405
17406
17407 public function __construct(Composer $composer, IOInterface $io, ProcessExecutor $process = null)
17408 {
17409 $this->composer = $composer;
17410 $this->io = $io;
17411 $this->process = $process ?: new ProcessExecutor($io);
17412 $this->eventStack = array();
17413 }
17414
17415
17416
17417
17418
17419
17420
17421
17422
17423 public function dispatch($eventName, Event $event = null)
17424 {
17425 if (null === $event) {
17426 $event = new Event($eventName);
17427 }
17428
17429 return $this->doDispatch($event);
17430 }
17431
17432
17433
17434
17435
17436
17437
17438
17439
17440
17441
17442 public function dispatchScript($eventName, $devMode = false, $additionalArgs = array(), $flags = array())
17443 {
17444 return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
17445 }
17446
17447
17448
17449
17450
17451
17452
17453
17454
17455
17456
17457
17458
17459
17460
17461
17462 public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
17463 {
17464 return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
17465 }
17466
17467
17468
17469
17470
17471
17472
17473
17474
17475
17476
17477
17478
17479
17480
17481 public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
17482 {
17483 return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
17484 }
17485
17486
17487
17488
17489
17490
17491
17492
17493
17494 protected function doDispatch(Event $event)
17495 {
17496 $pathStr = 'PATH';
17497 if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
17498 $pathStr = 'Path';
17499 }
17500
17501
17502  $binDir = $this->composer->getConfig()->get('bin-dir');
17503 if (is_dir($binDir)) {
17504 $binDir = realpath($binDir);
17505 if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
17506 $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
17507 putenv($pathStr.'='.$_SERVER[$pathStr]);
17508 }
17509 }
17510
17511 $listeners = $this->getListeners($event);
17512
17513 $this->pushEvent($event);
17514
17515 $return = 0;
17516 foreach ($listeners as $callable) {
17517 if (!is_string($callable) && is_callable($callable)) {
17518 $event = $this->checkListenerExpectedEvent($callable, $event);
17519 $return = false === call_user_func($callable, $event) ? 1 : 0;
17520 } elseif ($this->isComposerScript($callable)) {
17521 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
17522 $scriptName = substr($callable, 1);
17523 $args = $event->getArguments();
17524 $flags = $event->getFlags();
17525 if (substr($callable, 0, 10) === '@composer ') {
17526 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
17527 if (0 !== ($exitCode = $this->process->execute($exec))) {
17528 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
17529
17530 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
17531 }
17532 } else {
17533 if (!$this->getListeners(new Event($scriptName))) {
17534 $this->io->writeError(sprintf('<warning>You made a reference to a non-existent script %s</warning>', $callable), true, IOInterface::QUIET);
17535 }
17536
17537 $return = $this->dispatch($scriptName, new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags));
17538 }
17539 } elseif ($this->isPhpScript($callable)) {
17540 $className = substr($callable, 0, strpos($callable, '::'));
17541 $methodName = substr($callable, strpos($callable, '::') + 2);
17542
17543 if (!class_exists($className)) {
17544 $this->io->writeError('<warning>Class '.$className.' is not autoloadable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
17545 continue;
17546 }
17547 if (!is_callable($callable)) {
17548 $this->io->writeError('<warning>Method '.$callable.' is not callable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
17549 continue;
17550 }
17551
17552 try {
17553 $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
17554 } catch (\Exception $e) {
17555 $message = "Script %s handling the %s event terminated with an exception";
17556 $this->io->writeError('<error>'.sprintf($message, $callable, $event->getName()).'</error>', true, IOInterface::QUIET);
17557 throw $e;
17558 }
17559 } else {
17560 $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
17561 $exec = $callable . ($args === '' ? '' : ' '.$args);
17562 if ($this->io->isVerbose()) {
17563 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
17564 } else {
17565 $this->io->writeError(sprintf('> %s', $exec));
17566 }
17567
17568 $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
17569 if ($possibleLocalBinaries) {
17570 foreach ($possibleLocalBinaries as $localExec) {
17571 if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
17572 $caller = BinaryInstaller::determineBinaryCaller($localExec);
17573 $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
17574 break;
17575 }
17576 }
17577 }
17578
17579 if (substr($exec, 0, 5) === '@php ') {
17580 $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
17581 }
17582
17583 if (0 !== ($exitCode = $this->process->execute($exec))) {
17584 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
17585
17586 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
17587 }
17588 }
17589
17590 if ($event->isPropagationStopped()) {
17591 break;
17592 }
17593 }
17594
17595 $this->popEvent();
17596
17597 return $return;
17598 }
17599
17600 protected function getPhpExecCommand()
17601 {
17602 $finder = new PhpExecutableFinder();
17603 $phpPath = $finder->find();
17604 if (!$phpPath) {
17605 throw new \RuntimeException('Failed to locate PHP binary to execute '.$scriptName);
17606 }
17607
17608 $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
17609 $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
17610 $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
17611
17612 return ProcessExecutor::escape($phpPath) . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag;
17613 }
17614
17615
17616
17617
17618
17619
17620 protected function executeEventPhpScript($className, $methodName, Event $event)
17621 {
17622 $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
17623
17624 if ($this->io->isVerbose()) {
17625 $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
17626 } else {
17627 $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
17628 }
17629
17630 return $className::$methodName($event);
17631 }
17632
17633
17634
17635
17636
17637
17638 protected function checkListenerExpectedEvent($target, Event $event)
17639 {
17640 if (in_array($event->getName(), array(
17641 'init',
17642 'command',
17643 'pre-file-download',
17644 ), true)) {
17645 return $event;
17646 }
17647
17648 try {
17649 $reflected = new \ReflectionParameter($target, 0);
17650 } catch (\Exception $e) {
17651 return $event;
17652 }
17653
17654 $typehint = $reflected->getClass();
17655
17656 if (!$typehint instanceof \ReflectionClass) {
17657 return $event;
17658 }
17659
17660 $expected = $typehint->getName();
17661
17662
17663  if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
17664 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);
17665 $event = new \Composer\Script\CommandEvent(
17666 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(), $event->getArguments()
17667 );
17668 }
17669 if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
17670 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);
17671 $event = new \Composer\Script\PackageEvent(
17672 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
17673 $event->getPolicy(), $event->getPool(), $event->getInstalledRepo(), $event->getRequest(),
17674 $event->getOperations(), $event->getOperation()
17675 );
17676 }
17677 if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
17678 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);
17679 $event = new \Composer\Script\Event(
17680 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
17681 $event->getArguments(), $event->getFlags()
17682 );
17683 }
17684
17685 return $event;
17686 }
17687
17688 private function serializeCallback($cb)
17689 {
17690 if (is_array($cb) && count($cb) === 2) {
17691 if (is_object($cb[0])) {
17692 $cb[0] = get_class($cb[0]);
17693 }
17694 if (is_string($cb[0]) && is_string($cb[1])) {
17695 $cb = implode('::', $cb);
17696 }
17697 }
17698 if (is_string($cb)) {
17699 return $cb;
17700 }
17701
17702 return var_export($cb, true);
17703 }
17704
17705
17706
17707
17708
17709
17710
17711
17712 public function addListener($eventName, $listener, $priority = 0)
17713 {
17714 $this->listeners[$eventName][$priority][] = $listener;
17715 }
17716
17717
17718
17719
17720
17721
17722
17723
17724 public function addSubscriber(EventSubscriberInterface $subscriber)
17725 {
17726 foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
17727 if (is_string($params)) {
17728 $this->addListener($eventName, array($subscriber, $params));
17729 } elseif (is_string($params[0])) {
17730 $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
17731 } else {
17732 foreach ($params as $listener) {
17733 $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
17734 }
17735 }
17736 }
17737 }
17738
17739
17740
17741
17742
17743
17744
17745 protected function getListeners(Event $event)
17746 {
17747 $scriptListeners = $this->getScriptListeners($event);
17748
17749 if (!isset($this->listeners[$event->getName()][0])) {
17750 $this->listeners[$event->getName()][0] = array();
17751 }
17752 krsort($this->listeners[$event->getName()]);
17753
17754 $listeners = $this->listeners;
17755 $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
17756
17757 return call_user_func_array('array_merge', $listeners[$event->getName()]);
17758 }
17759
17760
17761
17762
17763
17764
17765
17766 public function hasEventListeners(Event $event)
17767 {
17768 $listeners = $this->getListeners($event);
17769
17770 return count($listeners) > 0;
17771 }
17772
17773
17774
17775
17776
17777
17778
17779 protected function getScriptListeners(Event $event)
17780 {
17781 $package = $this->composer->getPackage();
17782 $scripts = $package->getScripts();
17783
17784 if (empty($scripts[$event->getName()])) {
17785 return array();
17786 }
17787
17788 if ($this->loader) {
17789 $this->loader->unregister();
17790 }
17791
17792 $generator = $this->composer->getAutoloadGenerator();
17793 if ($event instanceof ScriptEvent) {
17794 $generator->setDevMode($event->isDevMode());
17795 }
17796
17797 $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
17798 $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
17799 $map = $generator->parseAutoloads($packageMap, $package);
17800 $this->loader = $generator->createLoader($map);
17801 $this->loader->register();
17802
17803 return $scripts[$event->getName()];
17804 }
17805
17806
17807
17808
17809
17810
17811
17812 protected function isPhpScript($callable)
17813 {
17814 return false === strpos($callable, ' ') && false !== strpos($callable, '::');
17815 }
17816
17817
17818
17819
17820
17821
17822
17823 protected function isComposerScript($callable)
17824 {
17825 return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5);
17826 }
17827
17828
17829
17830
17831
17832
17833
17834
17835 protected function pushEvent(Event $event)
17836 {
17837 $eventName = $event->getName();
17838 if (in_array($eventName, $this->eventStack)) {
17839 throw new \RuntimeException(sprintf("Circular call to script handler '%s' detected", $eventName));
17840 }
17841
17842 return array_push($this->eventStack, $eventName);
17843 }
17844
17845
17846
17847
17848
17849
17850 protected function popEvent()
17851 {
17852 return array_pop($this->eventStack);
17853 }
17854 }
17855 <?php
17856
17857
17858
17859
17860
17861
17862
17863
17864
17865
17866
17867 namespace Composer\EventDispatcher;
17868
17869
17870
17871
17872
17873
17874
17875
17876
17877
17878
17879
17880
17881 interface EventSubscriberInterface
17882 {
17883
17884
17885
17886
17887
17888
17889
17890
17891
17892
17893
17894
17895
17896
17897
17898
17899
17900
17901 public static function getSubscribedEvents();
17902 }
17903 <?php
17904
17905
17906
17907
17908
17909
17910
17911
17912
17913
17914
17915 namespace Composer\EventDispatcher;
17916
17917
17918
17919
17920 class ScriptExecutionException extends \RuntimeException
17921 {
17922 }
17923 <?php
17924
17925
17926
17927
17928
17929
17930
17931
17932
17933
17934
17935 namespace Composer\Exception;
17936
17937
17938
17939
17940 class NoSslException extends \RuntimeException
17941 {
17942 }
17943 <?php
17944
17945
17946
17947
17948
17949
17950
17951
17952
17953
17954
17955 namespace Composer;
17956
17957 use Composer\Config\JsonConfigSource;
17958 use Composer\Json\JsonFile;
17959 use Composer\IO\IOInterface;
17960 use Composer\Package\Archiver;
17961 use Composer\Package\Version\VersionGuesser;
17962 use Composer\Repository\RepositoryManager;
17963 use Composer\Repository\RepositoryFactory;
17964 use Composer\Repository\WritableRepositoryInterface;
17965 use Composer\Util\Filesystem;
17966 use Composer\Util\Platform;
17967 use Composer\Util\ProcessExecutor;
17968 use Composer\Util\RemoteFilesystem;
17969 use Composer\Util\Silencer;
17970 use Composer\Plugin\PluginEvents;
17971 use Composer\EventDispatcher\Event;
17972 use Seld\JsonLint\DuplicateKeyException;
17973 use Symfony\Component\Console\Formatter\OutputFormatter;
17974 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
17975 use Symfony\Component\Console\Output\ConsoleOutput;
17976 use Composer\EventDispatcher\EventDispatcher;
17977 use Composer\Autoload\AutoloadGenerator;
17978 use Composer\Package\Version\VersionParser;
17979 use Composer\Downloader\TransportException;
17980 use Seld\JsonLint\JsonParser;
17981
17982
17983
17984
17985
17986
17987
17988
17989
17990 class Factory
17991 {
17992
17993
17994
17995
17996 protected static function getHomeDir()
17997 {
17998 $home = getenv('COMPOSER_HOME');
17999 if ($home) {
18000 return $home;
18001 }
18002
18003 if (Platform::isWindows()) {
18004 if (!getenv('APPDATA')) {
18005 throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
18006 }
18007
18008 return rtrim(strtr(getenv('APPDATA'), '\\', '/'), '/') . '/Composer';
18009 }
18010
18011 $userDir = self::getUserDir();
18012 if (is_dir($userDir . '/.composer')) {
18013 return $userDir . '/.composer';
18014 }
18015
18016 if (self::useXdg()) {
18017
18018  $xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
18019
18020 return $xdgConfig . '/composer';
18021 }
18022
18023 return $userDir . '/.composer';
18024 }
18025
18026
18027
18028
18029
18030 protected static function getCacheDir($home)
18031 {
18032 $cacheDir = getenv('COMPOSER_CACHE_DIR');
18033 if ($cacheDir) {
18034 return $cacheDir;
18035 }
18036
18037 $homeEnv = getenv('COMPOSER_HOME');
18038 if ($homeEnv) {
18039 return $homeEnv . '/cache';
18040 }
18041
18042 if (Platform::isWindows()) {
18043 if ($cacheDir = getenv('LOCALAPPDATA')) {
18044 $cacheDir .= '/Composer';
18045 } else {
18046 $cacheDir = $home . '/cache';
18047 }
18048
18049 return rtrim(strtr($cacheDir, '\\', '/'), '/');
18050 }
18051
18052 $userDir = self::getUserDir();
18053 if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
18054 return $home . '/cache';
18055 }
18056
18057 if (self::useXdg()) {
18058 $xdgCache = getenv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
18059
18060 return $xdgCache . '/composer';
18061 }
18062
18063 return $home . '/cache';
18064 }
18065
18066
18067
18068
18069
18070 protected static function getDataDir($home)
18071 {
18072 $homeEnv = getenv('COMPOSER_HOME');
18073 if ($homeEnv) {
18074 return $homeEnv;
18075 }
18076
18077 if (Platform::isWindows()) {
18078 return strtr($home, '\\', '/');
18079 }
18080
18081 $userDir = self::getUserDir();
18082 if ($home !== $userDir . '/.composer' && self::useXdg()) {
18083 $xdgData = getenv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
18084
18085 return $xdgData . '/composer';
18086 }
18087
18088 return $home;
18089 }
18090
18091
18092
18093
18094
18095 public static function createConfig(IOInterface $io = null, $cwd = null)
18096 {
18097 $cwd = $cwd ?: getcwd();
18098
18099 $config = new Config(true, $cwd);
18100
18101
18102  $home = self::getHomeDir();
18103 $config->merge(array('config' => array(
18104 'home' => $home,
18105 'cache-dir' => self::getCacheDir($home),
18106 'data-dir' => self::getDataDir($home),
18107 )));
18108
18109 $htaccessProtect = (bool) $config->get('htaccess-protect');
18110 if ($htaccessProtect) {
18111
18112  
18113  
18114  $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
18115 foreach ($dirs as $dir) {
18116 if (!file_exists($dir . '/.htaccess')) {
18117 if (!is_dir($dir)) {
18118 Silencer::call('mkdir', $dir, 0777, true);
18119 }
18120 Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
18121 }
18122 }
18123 }
18124
18125
18126  $file = new JsonFile($config->get('home').'/config.json');
18127 if ($file->exists()) {
18128 if ($io && $io->isDebug()) {
18129 $io->writeError('Loading config file ' . $file->getPath());
18130 }
18131 $config->merge($file->read());
18132 }
18133 $config->setConfigSource(new JsonConfigSource($file));
18134
18135
18136  $file = new JsonFile($config->get('home').'/auth.json');
18137 if ($file->exists()) {
18138 if ($io && $io->isDebug()) {
18139 $io->writeError('Loading config file ' . $file->getPath());
18140 }
18141 $config->merge(array('config' => $file->read()));
18142 }
18143 $config->setAuthConfigSource(new JsonConfigSource($file, true));
18144
18145
18146  if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
18147 $authData = json_decode($composerAuthEnv, true);
18148
18149 if (is_null($authData)) {
18150 throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
18151 }
18152
18153 if ($io && $io->isDebug()) {
18154 $io->writeError('Loading auth config from COMPOSER_AUTH');
18155 }
18156 $config->merge(array('config' => $authData));
18157 }
18158
18159 return $config;
18160 }
18161
18162 public static function getComposerFile()
18163 {
18164 return trim(getenv('COMPOSER')) ?: './composer.json';
18165 }
18166
18167 public static function createAdditionalStyles()
18168 {
18169 return array(
18170 'highlight' => new OutputFormatterStyle('red'),
18171 'warning' => new OutputFormatterStyle('black', 'yellow'),
18172 );
18173 }
18174
18175
18176
18177
18178
18179
18180 public static function createOutput()
18181 {
18182 $styles = self::createAdditionalStyles();
18183 $formatter = new OutputFormatter(null, $styles);
18184
18185 return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
18186 }
18187
18188
18189
18190
18191 public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
18192 {
18193 return RepositoryFactory::defaultRepos($io, $config, $rm);
18194 }
18195
18196
18197
18198
18199
18200
18201
18202
18203
18204
18205
18206
18207
18208 public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
18209 {
18210 $cwd = $cwd ?: getcwd();
18211
18212
18213  if (null === $localConfig) {
18214 $localConfig = static::getComposerFile();
18215 }
18216
18217 if (is_string($localConfig)) {
18218 $composerFile = $localConfig;
18219
18220 $file = new JsonFile($localConfig, null, $io);
18221
18222 if (!$file->exists()) {
18223 if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
18224 $message = 'Composer could not find a composer.json file in '.$cwd;
18225 } else {
18226 $message = 'Composer could not find the config file: '.$localConfig;
18227 }
18228 $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section';
18229 throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
18230 }
18231
18232 $file->validateSchema(JsonFile::LAX_SCHEMA);
18233 $jsonParser = new JsonParser;
18234 try {
18235 $jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS);
18236 } catch (DuplicateKeyException $e) {
18237 $details = $e->getDetails();
18238 $io->writeError('<warning>Key '.$details['key'].' is a duplicate in '.$localConfig.' at line '.$details['line'].'</warning>');
18239 }
18240
18241 $localConfig = $file->read();
18242 }
18243
18244
18245  $config = static::createConfig($io, $cwd);
18246 $config->merge($localConfig);
18247 if (isset($composerFile)) {
18248 $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
18249 $config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
18250
18251 $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
18252 if ($localAuthFile->exists()) {
18253 $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
18254 $config->merge(array('config' => $localAuthFile->read()));
18255 $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
18256 }
18257 }
18258
18259 $vendorDir = $config->get('vendor-dir');
18260
18261
18262  $composer = new Composer();
18263 $composer->setConfig($config);
18264
18265 if ($fullLoad) {
18266
18267  $io->loadConfiguration($config);
18268 }
18269
18270 $rfs = self::createRemoteFilesystem($io, $config);
18271
18272
18273  $dispatcher = new EventDispatcher($composer, $io);
18274 $composer->setEventDispatcher($dispatcher);
18275
18276
18277  $rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
18278 $composer->setRepositoryManager($rm);
18279
18280
18281  $this->addLocalRepository($io, $rm, $vendorDir);
18282
18283
18284  
18285  if (!$fullLoad && !isset($localConfig['version'])) {
18286 $localConfig['version'] = '1.0.0';
18287 }
18288
18289
18290  $parser = new VersionParser;
18291 $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
18292 $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser);
18293 $package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
18294 $composer->setPackage($package);
18295
18296
18297  $im = $this->createInstallationManager();
18298 $composer->setInstallationManager($im);
18299
18300 if ($fullLoad) {
18301
18302  $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
18303 $composer->setDownloadManager($dm);
18304
18305
18306  $generator = new AutoloadGenerator($dispatcher, $io);
18307 $composer->setAutoloadGenerator($generator);
18308
18309
18310  $am = $this->createArchiveManager($config, $dm);
18311 $composer->setArchiveManager($am);
18312 }
18313
18314
18315  $this->createDefaultInstallers($im, $composer, $io);
18316
18317 if ($fullLoad) {
18318 $globalComposer = null;
18319 if (realpath($config->get('home')) !== $cwd) {
18320 $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
18321 }
18322
18323 $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
18324 $composer->setPluginManager($pm);
18325
18326 $pm->loadInstalledPlugins();
18327 }
18328
18329
18330  if ($fullLoad && isset($composerFile)) {
18331 $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
18332 ? substr($composerFile, 0, -4).'lock'
18333 : $composerFile . '.lock';
18334
18335 $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile));
18336 $composer->setLocker($locker);
18337 }
18338
18339 if ($fullLoad) {
18340 $initEvent = new Event(PluginEvents::INIT);
18341 $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent);
18342
18343
18344  
18345  if ($rm->getLocalRepository()) {
18346 $this->purgePackages($rm->getLocalRepository(), $im);
18347 }
18348 }
18349
18350 return $composer;
18351 }
18352
18353
18354
18355
18356
18357
18358 public static function createGlobal(IOInterface $io, $disablePlugins = false)
18359 {
18360 $factory = new static();
18361
18362 return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, true);
18363 }
18364
18365
18366
18367
18368
18369 protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir)
18370 {
18371 $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io)));
18372 }
18373
18374
18375
18376
18377
18378 protected function createGlobalComposer(IOInterface $io, Config $config, $disablePlugins, $fullLoad = false)
18379 {
18380 $composer = null;
18381 try {
18382 $composer = self::createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad);
18383 } catch (\Exception $e) {
18384 $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
18385 }
18386
18387 return $composer;
18388 }
18389
18390
18391
18392
18393
18394
18395
18396 public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
18397 {
18398 $cache = null;
18399 if ($config->get('cache-files-ttl') > 0) {
18400 $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
18401 }
18402
18403 $dm = new Downloader\DownloadManager($io);
18404 switch ($preferred = $config->get('preferred-install')) {
18405 case 'dist':
18406 $dm->setPreferDist(true);
18407 break;
18408 case 'source':
18409 $dm->setPreferSource(true);
18410 break;
18411 case 'auto':
18412 default:
18413
18414  break;
18415 }
18416
18417 if (is_array($preferred)) {
18418 $dm->setPreferences($preferred);
18419 }
18420
18421 $executor = new ProcessExecutor($io);
18422 $fs = new Filesystem($executor);
18423
18424 $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs));
18425 $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs));
18426 $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $executor, $fs));
18427 $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs));
18428 $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
18429 $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18430 $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18431 $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18432 $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18433 $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18434 $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18435 $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18436 $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18437
18438 return $dm;
18439 }
18440
18441
18442
18443
18444
18445
18446 public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
18447 {
18448 if (null === $dm) {
18449 $io = new IO\NullIO();
18450 $io->loadConfiguration($config);
18451 $dm = $this->createDownloadManager($io, $config);
18452 }
18453
18454 $am = new Archiver\ArchiveManager($dm);
18455 $am->addArchiver(new Archiver\ZipArchiver);
18456 $am->addArchiver(new Archiver\PharArchiver);
18457
18458 return $am;
18459 }
18460
18461
18462
18463
18464
18465
18466
18467
18468 protected function createPluginManager(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
18469 {
18470 return new Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
18471 }
18472
18473
18474
18475
18476 protected function createInstallationManager()
18477 {
18478 return new Installer\InstallationManager();
18479 }
18480
18481
18482
18483
18484
18485
18486 protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
18487 {
18488 $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
18489 $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
18490 $im->addInstaller(new Installer\PluginInstaller($io, $composer));
18491 $im->addInstaller(new Installer\MetapackageInstaller($io));
18492 }
18493
18494
18495
18496
18497
18498 protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
18499 {
18500 foreach ($repo->getPackages() as $package) {
18501 if (!$im->isPackageInstalled($repo, $package)) {
18502 $repo->removePackage($package);
18503 }
18504 }
18505 }
18506
18507
18508
18509
18510
18511
18512
18513
18514 public static function create(IOInterface $io, $config = null, $disablePlugins = false)
18515 {
18516 $factory = new static();
18517
18518 return $factory->createComposer($io, $config, $disablePlugins);
18519 }
18520
18521
18522
18523
18524
18525
18526
18527 public static function createRemoteFilesystem(IOInterface $io, Config $config = null, $options = array())
18528 {
18529 static $warned = false;
18530 $disableTls = false;
18531 if ($config && $config->get('disable-tls') === true) {
18532 if (!$warned) {
18533 $io->write('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
18534 }
18535 $warned = true;
18536 $disableTls = true;
18537 } elseif (!extension_loaded('openssl')) {
18538 throw new Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. '
18539 . '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.');
18540 }
18541 $remoteFilesystemOptions = array();
18542 if ($disableTls === false) {
18543 if ($config && $config->get('cafile')) {
18544 $remoteFilesystemOptions['ssl']['cafile'] = $config->get('cafile');
18545 }
18546 if ($config && $config->get('capath')) {
18547 $remoteFilesystemOptions['ssl']['capath'] = $config->get('capath');
18548 }
18549 $remoteFilesystemOptions = array_replace_recursive($remoteFilesystemOptions, $options);
18550 }
18551 try {
18552 $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);
18553 } catch (TransportException $e) {
18554 if (false !== strpos($e->getMessage(), 'cafile')) {
18555 $io->write('<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>');
18556 $io->write('<error>A valid CA certificate file is required for SSL/TLS protection.</error>');
18557 if (PHP_VERSION_ID < 50600) {
18558 $io->write('<error>It is recommended you upgrade to PHP 5.6+ which can detect your system CA file automatically.</error>');
18559 }
18560 $io->write('<error>You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.</error>');
18561 }
18562 throw $e;
18563 }
18564
18565 return $remoteFilesystem;
18566 }
18567
18568
18569
18570
18571 private static function useXdg()
18572 {
18573 foreach (array_keys($_SERVER) as $key) {
18574 if (substr($key, 0, 4) === 'XDG_') {
18575 return true;
18576 }
18577 }
18578
18579 return false;
18580 }
18581
18582
18583
18584
18585
18586 private static function getUserDir()
18587 {
18588 $home = getenv('HOME');
18589 if (!$home) {
18590 throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
18591 }
18592
18593 return rtrim(strtr($home, '\\', '/'), '/');
18594 }
18595 }
18596 <?php
18597
18598
18599
18600
18601
18602
18603
18604
18605
18606
18607
18608 namespace Composer\IO;
18609
18610 use Composer\Config;
18611 use Composer\Util\ProcessExecutor;
18612 use Psr\Log\LoggerInterface;
18613 use Psr\Log\LogLevel;
18614
18615 abstract class BaseIO implements IOInterface, LoggerInterface
18616 {
18617 protected $authentications = array();
18618
18619
18620
18621
18622 public function getAuthentications()
18623 {
18624 return $this->authentications;
18625 }
18626
18627
18628
18629
18630 public function hasAuthentication($repositoryName)
18631 {
18632 return isset($this->authentications[$repositoryName]);
18633 }
18634
18635
18636
18637
18638 public function getAuthentication($repositoryName)
18639 {
18640 if (isset($this->authentications[$repositoryName])) {
18641 return $this->authentications[$repositoryName];
18642 }
18643
18644 return array('username' => null, 'password' => null);
18645 }
18646
18647
18648
18649
18650 public function setAuthentication($repositoryName, $username, $password = null)
18651 {
18652 $this->authentications[$repositoryName] = array('username' => $username, 'password' => $password);
18653 }
18654
18655
18656
18657
18658
18659
18660
18661
18662 protected function checkAndSetAuthentication($repositoryName, $username, $password = null)
18663 {
18664 if ($this->hasAuthentication($repositoryName)) {
18665 $auth = $this->getAuthentication($repositoryName);
18666 if ($auth['username'] === $username && $auth['password'] === $password) {
18667 return;
18668 }
18669
18670 $this->writeError(
18671 sprintf(
18672 "<warning>Warning: You should avoid overwriting already defined auth settings for %s.</warning>",
18673 $repositoryName
18674 )
18675 );
18676 }
18677 $this->setAuthentication($repositoryName, $username, $password);
18678 }
18679
18680
18681
18682
18683 public function loadConfiguration(Config $config)
18684 {
18685 $bitbucketOauth = $config->get('bitbucket-oauth') ?: array();
18686 $githubOauth = $config->get('github-oauth') ?: array();
18687 $gitlabOauth = $config->get('gitlab-oauth') ?: array();
18688 $gitlabToken = $config->get('gitlab-token') ?: array();
18689 $httpBasic = $config->get('http-basic') ?: array();
18690
18691
18692
18693 foreach ($bitbucketOauth as $domain => $cred) {
18694 $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']);
18695 }
18696
18697 foreach ($githubOauth as $domain => $token) {
18698 if (!preg_match('{^[.a-z0-9]+$}', $token)) {
18699 throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
18700 }
18701 $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic');
18702 }
18703
18704 foreach ($gitlabOauth as $domain => $token) {
18705 $this->checkAndSetAuthentication($domain, $token, 'oauth2');
18706 }
18707
18708 foreach ($gitlabToken as $domain => $token) {
18709 $this->checkAndSetAuthentication($domain, $token, 'private-token');
18710 }
18711
18712
18713  foreach ($httpBasic as $domain => $cred) {
18714 $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
18715 }
18716
18717
18718  ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
18719 }
18720
18721
18722
18723
18724
18725
18726
18727
18728 public function emergency($message, array $context = array())
18729 {
18730 return $this->log(LogLevel::EMERGENCY, $message, $context);
18731 }
18732
18733
18734
18735
18736
18737
18738
18739
18740
18741
18742
18743 public function alert($message, array $context = array())
18744 {
18745 return $this->log(LogLevel::ALERT, $message, $context);
18746 }
18747
18748
18749
18750
18751
18752
18753
18754
18755
18756
18757 public function critical($message, array $context = array())
18758 {
18759 return $this->log(LogLevel::CRITICAL, $message, $context);
18760 }
18761
18762
18763
18764
18765
18766
18767
18768
18769
18770 public function error($message, array $context = array())
18771 {
18772 return $this->log(LogLevel::ERROR, $message, $context);
18773 }
18774
18775
18776
18777
18778
18779
18780
18781
18782
18783
18784
18785 public function warning($message, array $context = array())
18786 {
18787 return $this->log(LogLevel::WARNING, $message, $context);
18788 }
18789
18790
18791
18792
18793
18794
18795
18796
18797 public function notice($message, array $context = array())
18798 {
18799 return $this->log(LogLevel::NOTICE, $message, $context);
18800 }
18801
18802
18803
18804
18805
18806
18807
18808
18809
18810
18811 public function info($message, array $context = array())
18812 {
18813 return $this->log(LogLevel::INFO, $message, $context);
18814 }
18815
18816
18817
18818
18819
18820
18821
18822
18823 public function debug($message, array $context = array())
18824 {
18825 return $this->log(LogLevel::DEBUG, $message, $context);
18826 }
18827
18828
18829
18830
18831
18832
18833
18834
18835
18836 public function log($level, $message, array $context = array())
18837 {
18838 if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
18839 $this->writeError('<error>'.$message.'</error>', true, self::NORMAL);
18840 } elseif ($level === LogLevel::WARNING) {
18841 $this->writeError('<warning>'.$message.'</warning>', true, self::NORMAL);
18842 } elseif ($level === LogLevel::NOTICE) {
18843 $this->writeError('<info>'.$message.'</info>', true, self::VERBOSE);
18844 } elseif ($level === LogLevel::INFO) {
18845 $this->writeError('<info>'.$message.'</info>', true, self::VERY_VERBOSE);
18846 } else {
18847 $this->writeError($message, true, self::DEBUG);
18848 }
18849 }
18850 }
18851 <?php
18852
18853
18854
18855
18856
18857
18858
18859
18860
18861
18862
18863 namespace Composer\IO;
18864
18865 use Symfony\Component\Console\Output\StreamOutput;
18866 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
18867 use Symfony\Component\Console\Input\StringInput;
18868 use Symfony\Component\Console\Helper\HelperSet;
18869
18870
18871
18872
18873 class BufferIO extends ConsoleIO
18874 {
18875
18876
18877
18878
18879
18880 public function __construct($input = '', $verbosity = StreamOutput::VERBOSITY_NORMAL, OutputFormatterInterface $formatter = null)
18881 {
18882 $input = new StringInput($input);
18883 $input->setInteractive(false);
18884
18885 $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
18886
18887 parent::__construct($input, $output, new HelperSet(array()));
18888 }
18889
18890 public function getOutput()
18891 {
18892 fseek($this->output->getStream(), 0);
18893
18894 $output = stream_get_contents($this->output->getStream());
18895
18896 $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) {
18897 $pre = strip_tags($matches[1]);
18898
18899 if (strlen($pre) === strlen($matches[2])) {
18900 return '';
18901 }
18902
18903
18904  return rtrim($matches[1])."\n";
18905 }, $output);
18906
18907 return $output;
18908 }
18909 }
18910 <?php
18911
18912
18913
18914
18915
18916
18917
18918
18919
18920
18921
18922 namespace Composer\IO;
18923
18924 use Symfony\Component\Console\Input\InputInterface;
18925 use Symfony\Component\Console\Output\ConsoleOutputInterface;
18926 use Symfony\Component\Console\Output\OutputInterface;
18927 use Symfony\Component\Console\Helper\HelperSet;
18928 use Composer\Question\StrictConfirmationQuestion;
18929 use Symfony\Component\Console\Question\Question;
18930
18931
18932
18933
18934
18935
18936
18937 class ConsoleIO extends BaseIO
18938 {
18939
18940 protected $input;
18941
18942 protected $output;
18943
18944 protected $helperSet;
18945
18946 protected $lastMessage;
18947
18948 protected $lastMessageErr;
18949
18950
18951 private $startTime;
18952
18953 private $verbosityMap;
18954
18955
18956
18957
18958
18959
18960
18961
18962 public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
18963 {
18964 $this->input = $input;
18965 $this->output = $output;
18966 $this->helperSet = $helperSet;
18967 $this->verbosityMap = array(
18968 self::QUIET => OutputInterface::VERBOSITY_QUIET,
18969 self::NORMAL => OutputInterface::VERBOSITY_NORMAL,
18970 self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
18971 self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
18972 self::DEBUG => OutputInterface::VERBOSITY_DEBUG,
18973 );
18974 }
18975
18976
18977
18978
18979 public function enableDebugging($startTime)
18980 {
18981 $this->startTime = $startTime;
18982 }
18983
18984
18985
18986
18987 public function isInteractive()
18988 {
18989 return $this->input->isInteractive();
18990 }
18991
18992
18993
18994
18995 public function isDecorated()
18996 {
18997 return $this->output->isDecorated();
18998 }
18999
19000
19001
19002
19003 public function isVerbose()
19004 {
19005 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
19006 }
19007
19008
19009
19010
19011 public function isVeryVerbose()
19012 {
19013 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
19014 }
19015
19016
19017
19018
19019 public function isDebug()
19020 {
19021 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
19022 }
19023
19024
19025
19026
19027 public function write($messages, $newline = true, $verbosity = self::NORMAL)
19028 {
19029 $this->doWrite($messages, $newline, false, $verbosity);
19030 }
19031
19032
19033
19034
19035 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
19036 {
19037 $this->doWrite($messages, $newline, true, $verbosity);
19038 }
19039
19040
19041
19042
19043
19044
19045
19046 private function doWrite($messages, $newline, $stderr, $verbosity)
19047 {
19048 $sfVerbosity = $this->verbosityMap[$verbosity];
19049 if ($sfVerbosity > $this->output->getVerbosity()) {
19050 return;
19051 }
19052
19053
19054  
19055  
19056  if (OutputInterface::VERBOSITY_QUIET === 0) {
19057 $sfVerbosity = OutputInterface::OUTPUT_NORMAL;
19058 }
19059
19060 if (null !== $this->startTime) {
19061 $memoryUsage = memory_get_usage() / 1024 / 1024;
19062 $timeSpent = microtime(true) - $this->startTime;
19063 $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
19064 return sprintf('[%.1fMB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
19065 }, (array) $messages);
19066 }
19067
19068 if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
19069 $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
19070 $this->lastMessageErr = implode($newline ? "\n" : '', (array) $messages);
19071
19072 return;
19073 }
19074
19075 $this->output->write($messages, $newline, $sfVerbosity);
19076 $this->lastMessage = implode($newline ? "\n" : '', (array) $messages);
19077 }
19078
19079
19080
19081
19082 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19083 {
19084 $this->doOverwrite($messages, $newline, $size, false, $verbosity);
19085 }
19086
19087
19088
19089
19090 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19091 {
19092 $this->doOverwrite($messages, $newline, $size, true, $verbosity);
19093 }
19094
19095
19096
19097
19098
19099
19100
19101
19102 private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
19103 {
19104
19105  $messages = implode($newline ? "\n" : '', (array) $messages);
19106
19107
19108  if (!isset($size)) {
19109
19110  $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
19111 }
19112
19113  $this->doWrite(str_repeat("\x08", $size), false, $stderr, $verbosity);
19114
19115
19116  $this->doWrite($messages, false, $stderr, $verbosity);
19117
19118
19119  
19120  
19121  $fill = $size - strlen(strip_tags($messages));
19122 if ($fill > 0) {
19123
19124  $this->doWrite(str_repeat(' ', $fill), false, $stderr, $verbosity);
19125
19126  $this->doWrite(str_repeat("\x08", $fill), false, $stderr, $verbosity);
19127 }
19128
19129 if ($newline) {
19130 $this->doWrite('', true, $stderr, $verbosity);
19131 }
19132
19133 if ($stderr) {
19134 $this->lastMessageErr = $messages;
19135 } else {
19136 $this->lastMessage = $messages;
19137 }
19138 }
19139
19140
19141
19142
19143 public function ask($question, $default = null)
19144 {
19145
19146 $helper = $this->helperSet->get('question');
19147 $question = new Question($question, $default);
19148
19149 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19150 }
19151
19152
19153
19154
19155 public function askConfirmation($question, $default = true)
19156 {
19157
19158 $helper = $this->helperSet->get('question');
19159 $question = new StrictConfirmationQuestion($question, $default);
19160
19161 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19162 }
19163
19164
19165
19166
19167 public function askAndValidate($question, $validator, $attempts = null, $default = null)
19168 {
19169
19170 $helper = $this->helperSet->get('question');
19171 $question = new Question($question, $default);
19172 $question->setValidator($validator);
19173 $question->setMaxAttempts($attempts);
19174
19175 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19176 }
19177
19178
19179
19180
19181 public function askAndHideAnswer($question)
19182 {
19183 $this->writeError($question, false);
19184
19185 return \Seld\CliPrompt\CliPrompt::hiddenPrompt(true);
19186 }
19187
19188
19189
19190
19191 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
19192 {
19193 if ($this->isInteractive()) {
19194 return $this->helperSet->get('dialog')->select($this->getErrorOutput(), $question, $choices, $default, $attempts, $errorMessage, $multiselect);
19195 }
19196
19197 return $default;
19198 }
19199
19200
19201
19202
19203 private function getErrorOutput()
19204 {
19205 if ($this->output instanceof ConsoleOutputInterface) {
19206 return $this->output->getErrorOutput();
19207 }
19208
19209 return $this->output;
19210 }
19211 }
19212 <?php
19213
19214
19215
19216
19217
19218
19219
19220
19221
19222
19223
19224 namespace Composer\IO;
19225
19226 use Composer\Config;
19227
19228
19229
19230
19231
19232
19233 interface IOInterface
19234 {
19235 const QUIET = 1;
19236 const NORMAL = 2;
19237 const VERBOSE = 4;
19238 const VERY_VERBOSE = 8;
19239 const DEBUG = 16;
19240
19241
19242
19243
19244
19245
19246 public function isInteractive();
19247
19248
19249
19250
19251
19252
19253 public function isVerbose();
19254
19255
19256
19257
19258
19259
19260 public function isVeryVerbose();
19261
19262
19263
19264
19265
19266
19267 public function isDebug();
19268
19269
19270
19271
19272
19273
19274 public function isDecorated();
19275
19276
19277
19278
19279
19280
19281
19282
19283 public function write($messages, $newline = true, $verbosity = self::NORMAL);
19284
19285
19286
19287
19288
19289
19290
19291
19292 public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
19293
19294
19295
19296
19297
19298
19299
19300
19301
19302 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
19303
19304
19305
19306
19307
19308
19309
19310
19311
19312 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
19313
19314
19315
19316
19317
19318
19319
19320
19321
19322
19323 public function ask($question, $default = null);
19324
19325
19326
19327
19328
19329
19330
19331
19332
19333
19334
19335 public function askConfirmation($question, $default = true);
19336
19337
19338
19339
19340
19341
19342
19343
19344
19345
19346
19347
19348
19349
19350
19351
19352 public function askAndValidate($question, $validator, $attempts = null, $default = null);
19353
19354
19355
19356
19357
19358
19359
19360
19361 public function askAndHideAnswer($question);
19362
19363
19364
19365
19366
19367
19368
19369
19370
19371
19372
19373
19374
19375
19376 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
19377
19378
19379
19380
19381
19382
19383 public function getAuthentications();
19384
19385
19386
19387
19388
19389
19390
19391
19392 public function hasAuthentication($repositoryName);
19393
19394
19395
19396
19397
19398
19399
19400
19401 public function getAuthentication($repositoryName);
19402
19403
19404
19405
19406
19407
19408
19409
19410 public function setAuthentication($repositoryName, $username, $password = null);
19411
19412
19413
19414
19415
19416
19417 public function loadConfiguration(Config $config);
19418 }
19419 <?php
19420
19421
19422
19423
19424
19425
19426
19427
19428
19429
19430
19431 namespace Composer\IO;
19432
19433
19434
19435
19436
19437
19438 class NullIO extends BaseIO
19439 {
19440
19441
19442
19443 public function isInteractive()
19444 {
19445 return false;
19446 }
19447
19448
19449
19450
19451 public function isVerbose()
19452 {
19453 return false;
19454 }
19455
19456
19457
19458
19459 public function isVeryVerbose()
19460 {
19461 return false;
19462 }
19463
19464
19465
19466
19467 public function isDebug()
19468 {
19469 return false;
19470 }
19471
19472
19473
19474
19475 public function isDecorated()
19476 {
19477 return false;
19478 }
19479
19480
19481
19482
19483 public function write($messages, $newline = true, $verbosity = self::NORMAL)
19484 {
19485 }
19486
19487
19488
19489
19490 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
19491 {
19492 }
19493
19494
19495
19496
19497 public function overwrite($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
19498 {
19499 }
19500
19501
19502
19503
19504 public function overwriteError($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
19505 {
19506 }
19507
19508
19509
19510
19511 public function ask($question, $default = null)
19512 {
19513 return $default;
19514 }
19515
19516
19517
19518
19519 public function askConfirmation($question, $default = true)
19520 {
19521 return $default;
19522 }
19523
19524
19525
19526
19527 public function askAndValidate($question, $validator, $attempts = false, $default = null)
19528 {
19529 return $default;
19530 }
19531
19532
19533
19534
19535 public function askAndHideAnswer($question)
19536 {
19537 return null;
19538 }
19539
19540
19541
19542
19543 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
19544 {
19545 return $default;
19546 }
19547 }
19548 <?php
19549
19550
19551
19552
19553
19554
19555
19556
19557
19558
19559
19560 namespace Composer;
19561
19562 use Composer\Autoload\AutoloadGenerator;
19563 use Composer\DependencyResolver\DefaultPolicy;
19564 use Composer\DependencyResolver\Operation\UpdateOperation;
19565 use Composer\DependencyResolver\Operation\InstallOperation;
19566 use Composer\DependencyResolver\Operation\UninstallOperation;
19567 use Composer\DependencyResolver\Operation\OperationInterface;
19568 use Composer\DependencyResolver\PolicyInterface;
19569 use Composer\DependencyResolver\Pool;
19570 use Composer\DependencyResolver\Request;
19571 use Composer\DependencyResolver\Rule;
19572 use Composer\DependencyResolver\Solver;
19573 use Composer\DependencyResolver\SolverProblemsException;
19574 use Composer\Downloader\DownloadManager;
19575 use Composer\EventDispatcher\EventDispatcher;
19576 use Composer\Installer\InstallationManager;
19577 use Composer\Installer\InstallerEvents;
19578 use Composer\Installer\NoopInstaller;
19579 use Composer\Installer\SuggestedPackagesReporter;
19580 use Composer\IO\IOInterface;
19581 use Composer\Package\AliasPackage;
19582 use Composer\Package\CompletePackage;
19583 use Composer\Package\Link;
19584 use Composer\Package\Loader\ArrayLoader;
19585 use Composer\Package\Dumper\ArrayDumper;
19586 use Composer\Semver\Constraint\Constraint;
19587 use Composer\Package\Locker;
19588 use Composer\Package\PackageInterface;
19589 use Composer\Package\RootPackageInterface;
19590 use Composer\Repository\CompositeRepository;
19591 use Composer\Repository\InstalledArrayRepository;
19592 use Composer\Repository\PlatformRepository;
19593 use Composer\Repository\RepositoryInterface;
19594 use Composer\Repository\RepositoryManager;
19595 use Composer\Repository\WritableRepositoryInterface;
19596 use Composer\Script\ScriptEvents;
19597
19598
19599
19600
19601
19602
19603
19604 class Installer
19605 {
19606
19607
19608
19609 protected $io;
19610
19611
19612
19613
19614 protected $config;
19615
19616
19617
19618
19619 protected $package;
19620
19621
19622
19623
19624 protected $downloadManager;
19625
19626
19627
19628
19629 protected $repositoryManager;
19630
19631
19632
19633
19634 protected $locker;
19635
19636
19637
19638
19639 protected $installationManager;
19640
19641
19642
19643
19644 protected $eventDispatcher;
19645
19646
19647
19648
19649 protected $autoloadGenerator;
19650
19651 protected $preferSource = false;
19652 protected $preferDist = false;
19653 protected $optimizeAutoloader = false;
19654 protected $classMapAuthoritative = false;
19655 protected $apcuAutoloader = false;
19656 protected $devMode = false;
19657 protected $dryRun = false;
19658 protected $verbose = false;
19659 protected $update = false;
19660 protected $dumpAutoloader = true;
19661 protected $runScripts = true;
19662 protected $ignorePlatformReqs = false;
19663 protected $preferStable = false;
19664 protected $preferLowest = false;
19665 protected $skipSuggest = false;
19666 protected $writeLock = true;
19667 protected $executeOperations = true;
19668
19669
19670
19671
19672
19673
19674 protected $updateWhitelist = null;
19675 protected $whitelistDependencies = false;
19676
19677
19678
19679
19680 protected $suggestedPackagesReporter;
19681
19682
19683
19684
19685 protected $additionalInstalledRepository;
19686
19687
19688
19689
19690
19691
19692
19693
19694
19695
19696
19697
19698
19699
19700 public function __construct(IOInterface $io, Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
19701 {
19702 $this->io = $io;
19703 $this->config = $config;
19704 $this->package = $package;
19705 $this->downloadManager = $downloadManager;
19706 $this->repositoryManager = $repositoryManager;
19707 $this->locker = $locker;
19708 $this->installationManager = $installationManager;
19709 $this->eventDispatcher = $eventDispatcher;
19710 $this->autoloadGenerator = $autoloadGenerator;
19711 }
19712
19713
19714
19715
19716
19717
19718
19719 public function run()
19720 {
19721
19722  
19723  
19724  
19725  gc_collect_cycles();
19726 gc_disable();
19727
19728
19729  if (!$this->update && !$this->locker->isLocked()) {
19730 $this->update = true;
19731 }
19732
19733 if ($this->dryRun) {
19734 $this->verbose = true;
19735 $this->runScripts = false;
19736 $this->executeOperations = false;
19737 $this->writeLock = false;
19738 $this->dumpAutoloader = false;
19739 $this->installationManager->addInstaller(new NoopInstaller);
19740 $this->mockLocalRepositories($this->repositoryManager);
19741 }
19742
19743 if ($this->runScripts) {
19744
19745  $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
19746 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
19747 }
19748
19749 $this->downloadManager->setPreferSource($this->preferSource);
19750 $this->downloadManager->setPreferDist($this->preferDist);
19751
19752
19753  $localRepo = $this->repositoryManager->getLocalRepository();
19754 if ($this->update) {
19755 $platformOverrides = $this->config->get('platform') ?: array();
19756 } else {
19757 $platformOverrides = $this->locker->getPlatformOverrides();
19758 }
19759 $platformRepo = new PlatformRepository(array(), $platformOverrides);
19760 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
19761
19762 $aliases = $this->getRootAliases();
19763 $this->aliasPlatformPackages($platformRepo, $aliases);
19764
19765 if (!$this->suggestedPackagesReporter) {
19766 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
19767 }
19768
19769 try {
19770 list($res, $devPackages) = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases);
19771 if ($res !== 0) {
19772 return $res;
19773 }
19774 } catch (\Exception $e) {
19775 if ($this->executeOperations) {
19776 $this->installationManager->notifyInstalls($this->io);
19777 }
19778
19779 throw $e;
19780 }
19781 if ($this->executeOperations) {
19782 $this->installationManager->notifyInstalls($this->io);
19783 }
19784
19785
19786  if ($this->devMode && !$this->skipSuggest) {
19787 $this->suggestedPackagesReporter->output($installedRepo);
19788 }
19789
19790
19791  foreach ($localRepo->getPackages() as $package) {
19792 if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
19793 continue;
19794 }
19795
19796 $replacement = (is_string($package->getReplacementPackage()))
19797 ? 'Use ' . $package->getReplacementPackage() . ' instead'
19798 : 'No replacement was suggested';
19799
19800 $this->io->writeError(
19801 sprintf(
19802 "<warning>Package %s is abandoned, you should avoid using it. %s.</warning>",
19803 $package->getPrettyName(),
19804 $replacement
19805 )
19806 );
19807 }
19808
19809
19810  if ($this->update && $this->writeLock) {
19811 $localRepo->reload();
19812
19813 $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
19814 $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires());
19815
19816 $updatedLock = $this->locker->setLockData(
19817 array_diff($localRepo->getCanonicalPackages(), $devPackages),
19818 $devPackages,
19819 $platformReqs,
19820 $platformDevReqs,
19821 $aliases,
19822 $this->package->getMinimumStability(),
19823 $this->package->getStabilityFlags(),
19824 $this->preferStable || $this->package->getPreferStable(),
19825 $this->preferLowest,
19826 $this->config->get('platform') ?: array()
19827 );
19828 if ($updatedLock) {
19829 $this->io->writeError('<info>Writing lock file</info>');
19830 }
19831 }
19832
19833 if ($this->dumpAutoloader) {
19834
19835  if ($this->optimizeAutoloader) {
19836 $this->io->writeError('<info>Generating optimized autoload files</info>');
19837 } else {
19838 $this->io->writeError('<info>Generating autoload files</info>');
19839 }
19840
19841 $this->autoloadGenerator->setDevMode($this->devMode);
19842 $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
19843 $this->autoloadGenerator->setApcu($this->apcuAutoloader);
19844 $this->autoloadGenerator->setRunScripts($this->runScripts);
19845 $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
19846 }
19847
19848 if ($this->runScripts) {
19849 $devMode = (int) $this->devMode;
19850 putenv("COMPOSER_DEV_MODE=$devMode");
19851
19852
19853  $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
19854 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
19855 }
19856
19857 if ($this->executeOperations) {
19858
19859  foreach ($localRepo->getPackages() as $package) {
19860 $this->installationManager->ensureBinariesPresence($package);
19861 }
19862
19863 $vendorDir = $this->config->get('vendor-dir');
19864 if (is_dir($vendorDir)) {
19865
19866  
19867  @touch($vendorDir);
19868 }
19869 }
19870
19871
19872  if (!defined('HHVM_VERSION')) {
19873 gc_enable();
19874 }
19875
19876 return 0;
19877 }
19878
19879
19880
19881
19882
19883
19884
19885
19886 protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases)
19887 {
19888
19889  $lockedRepository = null;
19890 $repositories = null;
19891
19892
19893  
19894  
19895  if (!$this->update || (!empty($this->updateWhitelist) && $this->locker->isLocked())) {
19896 try {
19897 $lockedRepository = $this->locker->getLockedRepository($this->devMode);
19898 } catch (\RuntimeException $e) {
19899
19900  if ($this->package->getDevRequires()) {
19901 throw $e;
19902 }
19903
19904  $lockedRepository = $this->locker->getLockedRepository();
19905 }
19906 }
19907
19908 $this->whitelistUpdateDependencies(
19909 $lockedRepository ?: $localRepo,
19910 $this->package->getRequires(),
19911 $this->package->getDevRequires()
19912 );
19913
19914 $this->io->writeError('<info>Loading composer repositories with package information</info>');
19915
19916
19917  $policy = $this->createPolicy();
19918 $pool = $this->createPool($this->update ? null : $lockedRepository);
19919 $pool->addRepository($installedRepo, $aliases);
19920 if ($this->update) {
19921 $repositories = $this->repositoryManager->getRepositories();
19922 foreach ($repositories as $repository) {
19923 $pool->addRepository($repository, $aliases);
19924 }
19925 }
19926
19927  
19928  
19929  if ($lockedRepository) {
19930 $pool->addRepository($lockedRepository, $aliases);
19931 }
19932
19933
19934  $request = $this->createRequest($this->package, $platformRepo);
19935
19936 if ($this->update) {
19937
19938  $removedUnstablePackages = array();
19939 foreach ($localRepo->getPackages() as $package) {
19940 if (
19941 !$pool->isPackageAcceptable($package->getNames(), $package->getStability())
19942 && $this->installationManager->isPackageInstalled($localRepo, $package)
19943 ) {
19944 $removedUnstablePackages[$package->getName()] = true;
19945 $request->remove($package->getName(), new Constraint('=', $package->getVersion()));
19946 }
19947 }
19948
19949 $this->io->writeError('<info>Updating dependencies'.($this->devMode ? ' (including require-dev)' : '').'</info>');
19950
19951 $request->updateAll();
19952
19953 $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
19954
19955 foreach ($links as $link) {
19956 $request->install($link->getTarget(), $link->getConstraint());
19957 }
19958
19959
19960  
19961  if ($this->updateWhitelist) {
19962 $currentPackages = $this->getCurrentPackages($installedRepo);
19963
19964
19965  $candidates = array();
19966 foreach ($links as $link) {
19967 $candidates[$link->getTarget()] = true;
19968 $rootRequires[$link->getTarget()] = $link;
19969 }
19970 foreach ($currentPackages as $package) {
19971 $candidates[$package->getName()] = true;
19972 }
19973
19974
19975  foreach ($candidates as $candidate => $dummy) {
19976 foreach ($currentPackages as $curPackage) {
19977 if ($curPackage->getName() === $candidate) {
19978 if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
19979 $constraint = new Constraint('=', $curPackage->getVersion());
19980 $description = $this->locker->isLocked() ? '(locked at' : '(installed at';
19981 $requiredAt = isset($rootRequires[$candidate]) ? ', required as ' . $rootRequires[$candidate]->getPrettyConstraint() : '';
19982 $constraint->setPrettyString($description . ' ' . $curPackage->getPrettyVersion() . $requiredAt . ')');
19983 $request->install($curPackage->getName(), $constraint);
19984 }
19985 break;
19986 }
19987 }
19988 }
19989 }
19990 } else {
19991 $this->io->writeError('<info>Installing dependencies'.($this->devMode ? ' (including require-dev)' : '').' from lock file</info>');
19992
19993 if (!$this->locker->isFresh()) {
19994 $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);
19995 }
19996
19997 foreach ($lockedRepository->getPackages() as $package) {
19998 $version = $package->getVersion();
19999 if (isset($aliases[$package->getName()][$version])) {
20000 $version = $aliases[$package->getName()][$version]['alias_normalized'];
20001 }
20002 $constraint = new Constraint('=', $version);
20003 $constraint->setPrettyString($package->getPrettyVersion());
20004 $request->install($package->getName(), $constraint);
20005 }
20006
20007 foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
20008 $request->install($link->getTarget(), $link->getConstraint());
20009 }
20010 }
20011
20012
20013  $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-links');
20014
20015
20016  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
20017 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
20018 try {
20019 $operations = $solver->solve($request, $this->ignorePlatformReqs);
20020 } catch (SolverProblemsException $e) {
20021 $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
20022 $this->io->writeError($e->getMessage());
20023 if ($this->update && !$this->devMode) {
20024 $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);
20025 }
20026
20027 return array(max(1, $e->getCode()), array());
20028 }
20029
20030
20031  $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-updates', $operations);
20032
20033 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
20034
20035 $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
20036 $this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies", true, IOInterface::VERBOSE);
20037
20038
20039  if (!$operations) {
20040 $this->io->writeError('Nothing to install or update');
20041 }
20042
20043 $operations = $this->movePluginsToFront($operations);
20044 $operations = $this->moveUninstallsToFront($operations);
20045
20046
20047  
20048  if ($this->update) {
20049 $devPackages = $this->extractDevPackages($operations, $localRepo, $platformRepo, $aliases);
20050 if (!$this->devMode) {
20051 $operations = $this->filterDevPackageOperations($devPackages, $operations, $localRepo);
20052 }
20053 } else {
20054 $devPackages = null;
20055 }
20056
20057 if ($operations) {
20058 $installs = $updates = $uninstalls = array();
20059 foreach ($operations as $operation) {
20060 if ($operation instanceof InstallOperation) {
20061 $installs[] = $operation->getPackage()->getPrettyName().':'.$operation->getPackage()->getFullPrettyVersion();
20062 } elseif ($operation instanceof UpdateOperation) {
20063 $updates[] = $operation->getTargetPackage()->getPrettyName().':'.$operation->getTargetPackage()->getFullPrettyVersion();
20064 } elseif ($operation instanceof UninstallOperation) {
20065 $uninstalls[] = $operation->getPackage()->getPrettyName();
20066 }
20067 }
20068
20069 $this->io->writeError(
20070 sprintf("<info>Package operations: %d install%s, %d update%s, %d removal%s</info>",
20071 count($installs),
20072 1 === count($installs) ? '' : 's',
20073 count($updates),
20074 1 === count($updates) ? '' : 's',
20075 count($uninstalls),
20076 1 === count($uninstalls) ? '' : 's')
20077 );
20078 if ($installs) {
20079 $this->io->writeError("Installs: ".implode(', ', $installs), true, IOInterface::VERBOSE);
20080 }
20081 if ($updates) {
20082 $this->io->writeError("Updates: ".implode(', ', $updates), true, IOInterface::VERBOSE);
20083 }
20084 if ($uninstalls) {
20085 $this->io->writeError("Removals: ".implode(', ', $uninstalls), true, IOInterface::VERBOSE);
20086 }
20087 }
20088
20089 foreach ($operations as $operation) {
20090
20091  if ('install' === $operation->getJobType()) {
20092 $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
20093 }
20094
20095
20096  if ($this->update) {
20097 $package = null;
20098 if ('update' === $operation->getJobType()) {
20099 $package = $operation->getTargetPackage();
20100 } elseif ('install' === $operation->getJobType()) {
20101 $package = $operation->getPackage();
20102 }
20103 if ($package && $package->isDev()) {
20104 $references = $this->package->getReferences();
20105 if (isset($references[$package->getName()])) {
20106 $this->updateInstallReferences($package, $references[$package->getName()]);
20107 }
20108 }
20109 if ('update' === $operation->getJobType()
20110 && $operation->getTargetPackage()->isDev()
20111 && $operation->getTargetPackage()->getVersion() === $operation->getInitialPackage()->getVersion()
20112 && (!$operation->getTargetPackage()->getSourceReference() || $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference())
20113 && (!$operation->getTargetPackage()->getDistReference() || $operation->getTargetPackage()->getDistReference() === $operation->getInitialPackage()->getDistReference())
20114 ) {
20115 $this->io->writeError('  - Skipping update of '. $operation->getTargetPackage()->getPrettyName().' to the same reference-locked version', true, IOInterface::DEBUG);
20116 $this->io->writeError('', true, IOInterface::DEBUG);
20117
20118 continue;
20119 }
20120 }
20121
20122 $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($operation->getJobType());
20123 if (defined($event) && $this->runScripts) {
20124 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20125 }
20126
20127
20128  if (!$this->executeOperations && false === strpos($operation->getJobType(), 'Alias')) {
20129 $this->io->writeError('  - ' . $operation);
20130 } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
20131 $this->io->writeError('  - ' . $operation);
20132 }
20133
20134 $this->installationManager->execute($localRepo, $operation);
20135
20136
20137  if ($this->verbose && $this->io->isVeryVerbose() && in_array($operation->getJobType(), array('install', 'update'))) {
20138 $reason = $operation->getReason();
20139 if ($reason instanceof Rule) {
20140 switch ($reason->getReason()) {
20141 case Rule::RULE_JOB_INSTALL:
20142 $this->io->writeError('    REASON: Required by the root package: '.$reason->getPrettyString($pool));
20143 $this->io->writeError('');
20144 break;
20145 case Rule::RULE_PACKAGE_REQUIRES:
20146 $this->io->writeError('    REASON: '.$reason->getPrettyString($pool));
20147 $this->io->writeError('');
20148 break;
20149 }
20150 }
20151 }
20152
20153 $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($operation->getJobType());
20154 if (defined($event) && $this->runScripts) {
20155 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20156 }
20157
20158 if ($this->executeOperations || $this->writeLock) {
20159 $localRepo->write();
20160 }
20161 }
20162
20163 if ($this->executeOperations) {
20164
20165  $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
20166 $localRepo->write();
20167 }
20168
20169 return array(0, $devPackages);
20170 }
20171
20172
20173
20174
20175
20176
20177
20178
20179
20180
20181
20182 private function extractDevPackages(array $operations, RepositoryInterface $localRepo, PlatformRepository $platformRepo, array $aliases)
20183 {
20184 if (!$this->package->getDevRequires()) {
20185 return array();
20186 }
20187
20188
20189  $tempLocalRepo = clone $localRepo;
20190 foreach ($operations as $operation) {
20191 switch ($operation->getJobType()) {
20192 case 'install':
20193 case 'markAliasInstalled':
20194 if (!$tempLocalRepo->hasPackage($operation->getPackage())) {
20195 $tempLocalRepo->addPackage(clone $operation->getPackage());
20196 }
20197 break;
20198
20199 case 'uninstall':
20200 case 'markAliasUninstalled':
20201 $tempLocalRepo->removePackage($operation->getPackage());
20202 break;
20203
20204 case 'update':
20205 $tempLocalRepo->removePackage($operation->getInitialPackage());
20206 if (!$tempLocalRepo->hasPackage($operation->getTargetPackage())) {
20207 $tempLocalRepo->addPackage(clone $operation->getTargetPackage());
20208 }
20209 break;
20210
20211 default:
20212 throw new \LogicException('Unknown type: '.$operation->getJobType());
20213 }
20214 }
20215
20216
20217  
20218  
20219  $localRepo = new InstalledArrayRepository(array());
20220 $loader = new ArrayLoader(null, true);
20221 $dumper = new ArrayDumper();
20222 foreach ($tempLocalRepo->getCanonicalPackages() as $pkg) {
20223 $localRepo->addPackage($loader->load($dumper->dump($pkg)));
20224 }
20225 unset($tempLocalRepo, $loader, $dumper);
20226
20227 $policy = $this->createPolicy();
20228 $pool = $this->createPool();
20229 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
20230 $pool->addRepository($installedRepo, $aliases);
20231
20232
20233  $request = $this->createRequest($this->package, $platformRepo);
20234 $request->updateAll();
20235 foreach ($this->package->getRequires() as $link) {
20236 $request->install($link->getTarget(), $link->getConstraint());
20237 }
20238
20239
20240  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
20241 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
20242 $ops = $solver->solve($request, $this->ignorePlatformReqs);
20243 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
20244
20245 $devPackages = array();
20246 foreach ($ops as $op) {
20247 if ($op->getJobType() === 'uninstall') {
20248 $devPackages[] = $op->getPackage();
20249 }
20250 }
20251
20252 return $devPackages;
20253 }
20254
20255
20256
20257
20258 private function filterDevPackageOperations(array $devPackages, array $operations, RepositoryInterface $localRepo)
20259 {
20260 $finalOps = array();
20261 $packagesToSkip = array();
20262 foreach ($devPackages as $pkg) {
20263 $packagesToSkip[$pkg->getName()] = true;
20264 if ($installedDevPkg = $localRepo->findPackage($pkg->getName(), '*')) {
20265 $finalOps[] = new UninstallOperation($installedDevPkg, 'non-dev install removing it');
20266 }
20267 }
20268
20269
20270  foreach ($operations as $op) {
20271 $package = $op->getJobType() === 'update' ? $op->getTargetPackage() : $op->getPackage();
20272 if (isset($packagesToSkip[$package->getName()])) {
20273 continue;
20274 }
20275
20276 $finalOps[] = $op;
20277 }
20278
20279 return $finalOps;
20280 }
20281
20282
20283
20284
20285
20286
20287
20288
20289
20290
20291
20292
20293
20294
20295 private function movePluginsToFront(array $operations)
20296 {
20297 $pluginsNoDeps = array();
20298 $pluginsWithDeps = array();
20299 $pluginRequires = array();
20300
20301 foreach (array_reverse($operations, true) as $idx => $op) {
20302 if ($op instanceof InstallOperation) {
20303 $package = $op->getPackage();
20304 } elseif ($op instanceof UpdateOperation) {
20305 $package = $op->getTargetPackage();
20306 } else {
20307 continue;
20308 }
20309
20310
20311  $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
20312
20313
20314  if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
20315
20316  $requires = array_filter(array_keys($package->getRequires()), function($req) {
20317 return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
20318 });
20319
20320
20321  if ($isPlugin && !count($requires)) {
20322
20323  array_unshift($pluginsNoDeps, $op);
20324 } else {
20325
20326  $pluginRequires = array_merge($pluginRequires, $requires);
20327
20328  array_unshift($pluginsWithDeps, $op);
20329 }
20330
20331 unset($operations[$idx]);
20332 }
20333 }
20334
20335 return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
20336 }
20337
20338
20339
20340
20341
20342
20343
20344
20345 private function moveUninstallsToFront(array $operations)
20346 {
20347 $uninstOps = array();
20348 foreach ($operations as $idx => $op) {
20349 if ($op instanceof UninstallOperation) {
20350 $uninstOps[] = $op;
20351 unset($operations[$idx]);
20352 }
20353 }
20354
20355 return array_merge($uninstOps, $operations);
20356 }
20357
20358
20359
20360
20361 private function createInstalledRepo(RepositoryInterface $localRepo, PlatformRepository $platformRepo)
20362 {
20363
20364  
20365  
20366  $installedRootPackage = clone $this->package;
20367 $installedRootPackage->setRequires(array());
20368 $installedRootPackage->setDevRequires(array());
20369
20370 $repos = array(
20371 $localRepo,
20372 new InstalledArrayRepository(array($installedRootPackage)),
20373 $platformRepo,
20374 );
20375 $installedRepo = new CompositeRepository($repos);
20376 if ($this->additionalInstalledRepository) {
20377 $installedRepo->addRepository($this->additionalInstalledRepository);
20378 }
20379
20380 return $installedRepo;
20381 }
20382
20383
20384
20385
20386
20387 private function createPool(RepositoryInterface $lockedRepository = null)
20388 {
20389 if ($this->update) {
20390 $minimumStability = $this->package->getMinimumStability();
20391 $stabilityFlags = $this->package->getStabilityFlags();
20392
20393 $requires = array_merge($this->package->getRequires(), $this->package->getDevRequires());
20394 } else {
20395 $minimumStability = $this->locker->getMinimumStability();
20396 $stabilityFlags = $this->locker->getStabilityFlags();
20397
20398 $requires = array();
20399 foreach ($lockedRepository->getPackages() as $package) {
20400 $constraint = new Constraint('=', $package->getVersion());
20401 $constraint->setPrettyString($package->getPrettyVersion());
20402 $requires[$package->getName()] = $constraint;
20403 }
20404 }
20405
20406 $rootConstraints = array();
20407 foreach ($requires as $req => $constraint) {
20408
20409  if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
20410 continue;
20411 }
20412 if ($constraint instanceof Link) {
20413 $rootConstraints[$req] = $constraint->getConstraint();
20414 } else {
20415 $rootConstraints[$req] = $constraint;
20416 }
20417 }
20418
20419 return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
20420 }
20421
20422
20423
20424
20425 private function createPolicy()
20426 {
20427 $preferStable = null;
20428 $preferLowest = null;
20429 if (!$this->update) {
20430 $preferStable = $this->locker->getPreferStable();
20431 $preferLowest = $this->locker->getPreferLowest();
20432 }
20433
20434  
20435  if (null === $preferStable) {
20436 $preferStable = $this->preferStable || $this->package->getPreferStable();
20437 }
20438 if (null === $preferLowest) {
20439 $preferLowest = $this->preferLowest;
20440 }
20441
20442 return new DefaultPolicy($preferStable, $preferLowest);
20443 }
20444
20445
20446
20447
20448
20449
20450 private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
20451 {
20452 $request = new Request();
20453
20454 $constraint = new Constraint('=', $rootPackage->getVersion());
20455 $constraint->setPrettyString($rootPackage->getPrettyVersion());
20456 $request->install($rootPackage->getName(), $constraint);
20457
20458 $fixedPackages = $platformRepo->getPackages();
20459 if ($this->additionalInstalledRepository) {
20460 $additionalFixedPackages = $this->additionalInstalledRepository->getPackages();
20461 $fixedPackages = array_merge($fixedPackages, $additionalFixedPackages);
20462 }
20463
20464
20465  
20466  $provided = $rootPackage->getProvides();
20467 foreach ($fixedPackages as $package) {
20468 $constraint = new Constraint('=', $package->getVersion());
20469 $constraint->setPrettyString($package->getPrettyVersion());
20470
20471
20472  if ($package->getRepository() !== $platformRepo
20473 || !isset($provided[$package->getName()])
20474 || !$provided[$package->getName()]->getConstraint()->matches($constraint)
20475 ) {
20476 $request->fix($package->getName(), $constraint);
20477 }
20478 }
20479
20480 return $request;
20481 }
20482
20483
20484
20485
20486
20487
20488
20489
20490
20491
20492
20493
20494 private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $task, array $operations = null)
20495 {
20496 if ($task === 'force-updates' && null === $operations) {
20497 throw new \InvalidArgumentException('Missing operations argument');
20498 }
20499 if ($task === 'force-links') {
20500 $operations = array();
20501 }
20502
20503 if ($this->update && $this->updateWhitelist) {
20504 $currentPackages = $this->getCurrentPackages($installedRepo);
20505 }
20506
20507 foreach ($localRepo->getCanonicalPackages() as $package) {
20508
20509  if (!$package->isDev()) {
20510 continue;
20511 }
20512
20513
20514  foreach ($operations as $operation) {
20515 if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
20516 || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
20517 ) {
20518 continue 2;
20519 }
20520 }
20521
20522 if ($this->update) {
20523
20524  if ($this->updateWhitelist && !$this->isUpdateable($package)) {
20525
20526  foreach ($currentPackages as $curPackage) {
20527 if ($curPackage->isDev() && $curPackage->getName() === $package->getName() && $curPackage->getVersion() === $package->getVersion()) {
20528 if ($task === 'force-links') {
20529 $package->setRequires($curPackage->getRequires());
20530 $package->setConflicts($curPackage->getConflicts());
20531 $package->setProvides($curPackage->getProvides());
20532 $package->setReplaces($curPackage->getReplaces());
20533 } elseif ($task === 'force-updates') {
20534 if (($curPackage->getSourceReference() && $curPackage->getSourceReference() !== $package->getSourceReference())
20535 || ($curPackage->getDistReference() && $curPackage->getDistReference() !== $package->getDistReference())
20536 ) {
20537 $operations[] = new UpdateOperation($package, $curPackage);
20538 }
20539 }
20540
20541 break;
20542 }
20543 }
20544
20545 continue;
20546 }
20547
20548
20549  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
20550 foreach ($matches as $index => $match) {
20551
20552  if (!in_array($match->getRepository(), $repositories, true)) {
20553 unset($matches[$index]);
20554 continue;
20555 }
20556
20557
20558  if ($match->getName() !== $package->getName()) {
20559 unset($matches[$index]);
20560 continue;
20561 }
20562
20563 $matches[$index] = $match->getId();
20564 }
20565
20566
20567  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
20568 $newPackage = $pool->literalToPackage($matches[0]);
20569
20570 if ($task === 'force-links' && $newPackage) {
20571 $package->setRequires($newPackage->getRequires());
20572 $package->setConflicts($newPackage->getConflicts());
20573 $package->setProvides($newPackage->getProvides());
20574 $package->setReplaces($newPackage->getReplaces());
20575 }
20576
20577 if ($task === 'force-updates' && $newPackage && (
20578 (($newPackage->getSourceReference() && $newPackage->getSourceReference() !== $package->getSourceReference())
20579 || ($newPackage->getDistReference() && $newPackage->getDistReference() !== $package->getDistReference())
20580 )
20581 )) {
20582 $operations[] = new UpdateOperation($package, $newPackage);
20583
20584 continue;
20585 }
20586 }
20587
20588 if ($task === 'force-updates') {
20589
20590  $references = $this->package->getReferences();
20591
20592 if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
20593
20594  $operations[] = new UpdateOperation($package, clone $package);
20595 }
20596 }
20597 } else {
20598
20599  foreach ($lockedRepository->findPackages($package->getName()) as $lockedPackage) {
20600 if ($lockedPackage->isDev() && $lockedPackage->getVersion() === $package->getVersion()) {
20601 if ($task === 'force-links') {
20602 $package->setRequires($lockedPackage->getRequires());
20603 $package->setConflicts($lockedPackage->getConflicts());
20604 $package->setProvides($lockedPackage->getProvides());
20605 $package->setReplaces($lockedPackage->getReplaces());
20606 } elseif ($task === 'force-updates') {
20607 if (($lockedPackage->getSourceReference() && $lockedPackage->getSourceReference() !== $package->getSourceReference())
20608 || ($lockedPackage->getDistReference() && $lockedPackage->getDistReference() !== $package->getDistReference())
20609 ) {
20610 $operations[] = new UpdateOperation($package, $lockedPackage);
20611 }
20612 }
20613
20614 break;
20615 }
20616 }
20617 }
20618 }
20619
20620 return $operations;
20621 }
20622
20623
20624
20625
20626
20627
20628 private function getCurrentPackages($installedRepo)
20629 {
20630 if ($this->locker->isLocked()) {
20631 try {
20632 return $this->locker->getLockedRepository(true)->getPackages();
20633 } catch (\RuntimeException $e) {
20634
20635  return $this->locker->getLockedRepository()->getPackages();
20636 }
20637 }
20638
20639 return $installedRepo->getPackages();
20640 }
20641
20642
20643
20644
20645 private function getRootAliases()
20646 {
20647 if ($this->update) {
20648 $aliases = $this->package->getAliases();
20649 } else {
20650 $aliases = $this->locker->getAliases();
20651 }
20652
20653 $normalizedAliases = array();
20654
20655 foreach ($aliases as $alias) {
20656 $normalizedAliases[$alias['package']][$alias['version']] = array(
20657 'alias' => $alias['alias'],
20658 'alias_normalized' => $alias['alias_normalized'],
20659 );
20660 }
20661
20662 return $normalizedAliases;
20663 }
20664
20665
20666
20667
20668
20669
20670
20671 private function processPackageUrls($pool, $policy, $localRepo, $repositories)
20672 {
20673 if (!$this->update) {
20674 return;
20675 }
20676
20677 $rootRefs = $this->package->getReferences();
20678
20679 foreach ($localRepo->getCanonicalPackages() as $package) {
20680
20681  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
20682 foreach ($matches as $index => $match) {
20683
20684  if (!in_array($match->getRepository(), $repositories, true)) {
20685 unset($matches[$index]);
20686 continue;
20687 }
20688
20689
20690  if ($match->getName() !== $package->getName()) {
20691 unset($matches[$index]);
20692 continue;
20693 }
20694
20695 $matches[$index] = $match->getId();
20696 }
20697
20698
20699  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
20700 $newPackage = $pool->literalToPackage($matches[0]);
20701
20702
20703  $sourceUrl = $package->getSourceUrl();
20704 $newSourceUrl = $newPackage->getSourceUrl();
20705 $newReference = $newPackage->getSourceReference();
20706
20707 if ($package->isDev() && isset($rootRefs[$package->getName()]) && $package->getSourceReference() === $rootRefs[$package->getName()]) {
20708 $newReference = $rootRefs[$package->getName()];
20709 }
20710
20711 $this->updatePackageUrl($package, $newSourceUrl, $newPackage->getSourceType(), $newReference, $newPackage->getDistUrl());
20712
20713 if ($package instanceof CompletePackage && $newPackage instanceof CompletePackage) {
20714 $package->setAbandoned($newPackage->getReplacementPackage() ?: $newPackage->isAbandoned());
20715 }
20716
20717 $package->setDistMirrors($newPackage->getDistMirrors());
20718 $package->setSourceMirrors($newPackage->getSourceMirrors());
20719 }
20720 }
20721 }
20722
20723 private function updatePackageUrl(PackageInterface $package, $sourceUrl, $sourceType, $sourceReference, $distUrl)
20724 {
20725 $oldSourceRef = $package->getSourceReference();
20726
20727 if ($package->getSourceUrl() !== $sourceUrl) {
20728 $package->setSourceType($sourceType);
20729 $package->setSourceUrl($sourceUrl);
20730 $package->setSourceReference($sourceReference);
20731 }
20732
20733
20734  
20735  if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $distUrl)) {
20736 $package->setDistUrl($distUrl);
20737 $this->updateInstallReferences($package, $sourceReference);
20738 }
20739
20740 if ($this->updateWhitelist && !$this->isUpdateable($package)) {
20741 $this->updateInstallReferences($package, $oldSourceRef);
20742 }
20743 }
20744
20745 private function updateInstallReferences(PackageInterface $package, $reference)
20746 {
20747 if (!$reference) {
20748 return;
20749 }
20750
20751 $package->setSourceReference($reference);
20752
20753 if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $package->getDistUrl())) {
20754 $package->setDistReference($reference);
20755 $package->setDistUrl(preg_replace('{(?<=/)[a-f0-9]{40}(?=/|$)}i', $reference, $package->getDistUrl()));
20756 } else if ($package->getDistReference()) { 
20757  $package->setDistReference($reference);
20758 }
20759 }
20760
20761
20762
20763
20764
20765 private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
20766 {
20767 foreach ($aliases as $package => $versions) {
20768 foreach ($versions as $version => $alias) {
20769 $packages = $platformRepo->findPackages($package, $version);
20770 foreach ($packages as $package) {
20771 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
20772 $aliasPackage->setRootPackageAlias(true);
20773 $platformRepo->addPackage($aliasPackage);
20774 }
20775 }
20776 }
20777 }
20778
20779
20780
20781
20782
20783 private function isUpdateable(PackageInterface $package)
20784 {
20785 if (!$this->updateWhitelist) {
20786 throw new \LogicException('isUpdateable should only be called when a whitelist is present');
20787 }
20788
20789 foreach ($this->updateWhitelist as $whiteListedPattern => $void) {
20790 $patternRegexp = $this->packageNameToRegexp($whiteListedPattern);
20791 if (preg_match($patternRegexp, $package->getName())) {
20792 return true;
20793 }
20794 }
20795
20796 return false;
20797 }
20798
20799
20800
20801
20802
20803
20804
20805 private function packageNameToRegexp($whiteListedPattern)
20806 {
20807 $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern));
20808
20809 return "{^" . $cleanedWhiteListedPattern . "$}i";
20810 }
20811
20812
20813
20814
20815
20816 private function extractPlatformRequirements($links)
20817 {
20818 $platformReqs = array();
20819 foreach ($links as $link) {
20820 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
20821 $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
20822 }
20823 }
20824
20825 return $platformReqs;
20826 }
20827
20828
20829
20830
20831
20832
20833
20834
20835
20836
20837
20838
20839
20840
20841 private function whitelistUpdateDependencies($localOrLockRepo, array $rootRequires, array $rootDevRequires)
20842 {
20843 if (!$this->updateWhitelist) {
20844 return;
20845 }
20846
20847 $rootRequires = array_merge($rootRequires, $rootDevRequires);
20848
20849 $requiredPackageNames = array();
20850 foreach ($rootRequires as $require) {
20851 $requiredPackageNames[] = $require->getTarget();
20852 }
20853
20854 $skipPackages = array();
20855 foreach ($rootRequires as $require) {
20856 $skipPackages[$require->getTarget()] = true;
20857 }
20858
20859 $pool = new Pool;
20860 $pool->addRepository($localOrLockRepo);
20861
20862 $seen = array();
20863
20864 $rootRequiredPackageNames = array_keys($rootRequires);
20865
20866 foreach ($this->updateWhitelist as $packageName => $void) {
20867 $packageQueue = new \SplQueue;
20868
20869 $depPackages = $pool->whatProvides($packageName);
20870
20871 $nameMatchesRequiredPackage = in_array($packageName, $requiredPackageNames, true);
20872
20873
20874  if (!$nameMatchesRequiredPackage) {
20875 $whitelistPatternRegexp = $this->packageNameToRegexp($packageName);
20876 foreach ($rootRequiredPackageNames as $rootRequiredPackageName) {
20877 if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) {
20878 $nameMatchesRequiredPackage = true;
20879 break;
20880 }
20881 }
20882 }
20883
20884 if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) {
20885 $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
20886 }
20887
20888 foreach ($depPackages as $depPackage) {
20889 $packageQueue->enqueue($depPackage);
20890 }
20891
20892 while (!$packageQueue->isEmpty()) {
20893 $package = $packageQueue->dequeue();
20894 if (isset($seen[$package->getId()])) {
20895 continue;
20896 }
20897
20898 $seen[$package->getId()] = true;
20899 $this->updateWhitelist[$package->getName()] = true;
20900
20901 if (!$this->whitelistDependencies) {
20902 continue;
20903 }
20904
20905 $requires = $package->getRequires();
20906
20907 foreach ($requires as $require) {
20908 $requirePackages = $pool->whatProvides($require->getTarget());
20909
20910 foreach ($requirePackages as $requirePackage) {
20911 if (isset($this->updateWhitelist[$requirePackage->getName()])) {
20912 continue;
20913 }
20914
20915 if (isset($skipPackages[$requirePackage->getName()])) {
20916 $this->io->writeError('<warning>Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.</warning>');
20917 continue;
20918 }
20919
20920 $packageQueue->enqueue($requirePackage);
20921 }
20922 }
20923 }
20924 }
20925 }
20926
20927
20928
20929
20930
20931
20932
20933
20934 private function mockLocalRepositories(RepositoryManager $rm)
20935 {
20936 $packages = array();
20937 foreach ($rm->getLocalRepository()->getPackages() as $package) {
20938 $packages[(string) $package] = clone $package;
20939 }
20940 foreach ($packages as $key => $package) {
20941 if ($package instanceof AliasPackage) {
20942 $alias = (string) $package->getAliasOf();
20943 $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
20944 }
20945 }
20946 $rm->setLocalRepository(
20947 new InstalledArrayRepository($packages)
20948 );
20949 }
20950
20951
20952
20953
20954
20955
20956
20957
20958 public static function create(IOInterface $io, Composer $composer)
20959 {
20960 return new static(
20961 $io,
20962 $composer->getConfig(),
20963 $composer->getPackage(),
20964 $composer->getDownloadManager(),
20965 $composer->getRepositoryManager(),
20966 $composer->getLocker(),
20967 $composer->getInstallationManager(),
20968 $composer->getEventDispatcher(),
20969 $composer->getAutoloadGenerator()
20970 );
20971 }
20972
20973
20974
20975
20976
20977 public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
20978 {
20979 $this->additionalInstalledRepository = $additionalInstalledRepository;
20980
20981 return $this;
20982 }
20983
20984
20985
20986
20987
20988
20989
20990 public function setDryRun($dryRun = true)
20991 {
20992 $this->dryRun = (bool) $dryRun;
20993
20994 return $this;
20995 }
20996
20997
20998
20999
21000
21001
21002 public function isDryRun()
21003 {
21004 return $this->dryRun;
21005 }
21006
21007
21008
21009
21010
21011
21012
21013 public function setPreferSource($preferSource = true)
21014 {
21015 $this->preferSource = (bool) $preferSource;
21016
21017 return $this;
21018 }
21019
21020
21021
21022
21023
21024
21025
21026 public function setPreferDist($preferDist = true)
21027 {
21028 $this->preferDist = (bool) $preferDist;
21029
21030 return $this;
21031 }
21032
21033
21034
21035
21036
21037
21038
21039 public function setOptimizeAutoloader($optimizeAutoloader = false)
21040 {
21041 $this->optimizeAutoloader = (bool) $optimizeAutoloader;
21042 if (!$this->optimizeAutoloader) {
21043
21044  
21045  $this->setClassMapAuthoritative(false);
21046 }
21047
21048 return $this;
21049 }
21050
21051
21052
21053
21054
21055
21056
21057
21058 public function setClassMapAuthoritative($classMapAuthoritative = false)
21059 {
21060 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
21061 if ($this->classMapAuthoritative) {
21062
21063  $this->setOptimizeAutoloader(true);
21064 }
21065
21066 return $this;
21067 }
21068
21069
21070
21071
21072
21073
21074
21075 public function setApcuAutoloader($apcuAutoloader = false)
21076 {
21077 $this->apcuAutoloader = (bool) $apcuAutoloader;
21078
21079 return $this;
21080 }
21081
21082
21083
21084
21085
21086
21087
21088 public function setUpdate($update = true)
21089 {
21090 $this->update = (bool) $update;
21091
21092 return $this;
21093 }
21094
21095
21096
21097
21098
21099
21100
21101 public function setDevMode($devMode = true)
21102 {
21103 $this->devMode = (bool) $devMode;
21104
21105 return $this;
21106 }
21107
21108
21109
21110
21111
21112
21113
21114
21115
21116 public function setDumpAutoloader($dumpAutoloader = true)
21117 {
21118 $this->dumpAutoloader = (bool) $dumpAutoloader;
21119
21120 return $this;
21121 }
21122
21123
21124
21125
21126
21127
21128
21129
21130
21131 public function setRunScripts($runScripts = true)
21132 {
21133 $this->runScripts = (bool) $runScripts;
21134
21135 return $this;
21136 }
21137
21138
21139
21140
21141
21142
21143
21144 public function setConfig(Config $config)
21145 {
21146 $this->config = $config;
21147
21148 return $this;
21149 }
21150
21151
21152
21153
21154
21155
21156
21157 public function setVerbose($verbose = true)
21158 {
21159 $this->verbose = (bool) $verbose;
21160
21161 return $this;
21162 }
21163
21164
21165
21166
21167
21168
21169 public function isVerbose()
21170 {
21171 return $this->verbose;
21172 }
21173
21174
21175
21176
21177
21178
21179
21180 public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
21181 {
21182 $this->ignorePlatformReqs = (bool) $ignorePlatformReqs;
21183
21184 return $this;
21185 }
21186
21187
21188
21189
21190
21191
21192
21193
21194 public function setUpdateWhitelist(array $packages)
21195 {
21196 $this->updateWhitelist = array_flip(array_map('strtolower', $packages));
21197
21198 return $this;
21199 }
21200
21201
21202
21203
21204
21205
21206
21207 public function setWhitelistDependencies($updateDependencies = true)
21208 {
21209 $this->whitelistDependencies = (bool) $updateDependencies;
21210
21211 return $this;
21212 }
21213
21214
21215
21216
21217
21218
21219
21220 public function setPreferStable($preferStable = true)
21221 {
21222 $this->preferStable = (bool) $preferStable;
21223
21224 return $this;
21225 }
21226
21227
21228
21229
21230
21231
21232
21233 public function setPreferLowest($preferLowest = true)
21234 {
21235 $this->preferLowest = (bool) $preferLowest;
21236
21237 return $this;
21238 }
21239
21240
21241
21242
21243
21244
21245
21246
21247
21248 public function setWriteLock($writeLock = true)
21249 {
21250 $this->writeLock = (bool) $writeLock;
21251
21252 return $this;
21253 }
21254
21255
21256
21257
21258
21259
21260
21261
21262
21263 public function setExecuteOperations($executeOperations = true)
21264 {
21265 $this->executeOperations = (bool) $executeOperations;
21266
21267 return $this;
21268 }
21269
21270
21271
21272
21273
21274
21275
21276 public function setSkipSuggest($skipSuggest = true)
21277 {
21278 $this->skipSuggest = (bool) $skipSuggest;
21279
21280 return $this;
21281 }
21282
21283
21284
21285
21286
21287
21288
21289
21290
21291
21292 public function disablePlugins()
21293 {
21294 $this->installationManager->disablePlugins();
21295
21296 return $this;
21297 }
21298
21299
21300
21301
21302
21303 public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter)
21304 {
21305 $this->suggestedPackagesReporter = $suggestedPackagesReporter;
21306
21307 return $this;
21308 }
21309 }
21310 <?php
21311
21312
21313
21314
21315
21316
21317
21318
21319
21320
21321
21322 namespace Composer\Installer;
21323
21324 use Composer\IO\IOInterface;
21325 use Composer\Package\PackageInterface;
21326 use Composer\Util\Filesystem;
21327 use Composer\Util\Platform;
21328 use Composer\Util\ProcessExecutor;
21329 use Composer\Util\Silencer;
21330
21331
21332
21333
21334
21335
21336
21337
21338 class BinaryInstaller
21339 {
21340 protected $binDir;
21341 protected $binCompat;
21342 protected $io;
21343 protected $filesystem;
21344
21345
21346
21347
21348
21349
21350
21351 public function __construct(IOInterface $io, $binDir, $binCompat, Filesystem $filesystem = null)
21352 {
21353 $this->binDir = $binDir;
21354 $this->binCompat = $binCompat;
21355 $this->io = $io;
21356 $this->filesystem = $filesystem ?: new Filesystem();
21357 }
21358
21359 public function installBinaries(PackageInterface $package, $installPath, $warnOnOverwrite = true)
21360 {
21361 $binaries = $this->getBinaries($package);
21362 if (!$binaries) {
21363 return;
21364 }
21365 foreach ($binaries as $bin) {
21366 $binPath = $installPath.'/'.$bin;
21367 if (!file_exists($binPath)) {
21368 $this->io->writeError('    <warning>Skipped installation of bin '.$bin.' for package '.$package->getName().': file not found in package</warning>');
21369 continue;
21370 }
21371
21372
21373  
21374  
21375  
21376  $binPath = realpath($binPath);
21377
21378 $this->initializeBinDir();
21379 $link = $this->binDir.'/'.basename($bin);
21380 if (file_exists($link)) {
21381 if (is_link($link)) {
21382
21383  
21384  
21385  Silencer::call('chmod', $link, 0777 & ~umask());
21386 }
21387 if ($warnOnOverwrite) {
21388 $this->io->writeError('    Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
21389 }
21390 continue;
21391 }
21392
21393 if ($this->binCompat === "auto") {
21394 if (Platform::isWindows()) {
21395 $this->installFullBinaries($binPath, $link, $bin, $package);
21396 } else {
21397 $this->installSymlinkBinaries($binPath, $link);
21398 }
21399 } elseif ($this->binCompat === "full") {
21400 $this->installFullBinaries($binPath, $link, $bin, $package);
21401 }
21402 Silencer::call('chmod', $link, 0777 & ~umask());
21403 }
21404 }
21405
21406 public function removeBinaries(PackageInterface $package)
21407 {
21408 $this->initializeBinDir();
21409
21410 $binaries = $this->getBinaries($package);
21411 if (!$binaries) {
21412 return;
21413 }
21414 foreach ($binaries as $bin) {
21415 $link = $this->binDir.'/'.basename($bin);
21416 if (is_link($link) || file_exists($link)) {
21417 $this->filesystem->unlink($link);
21418 }
21419 if (file_exists($link.'.bat')) {
21420 $this->filesystem->unlink($link.'.bat');
21421 }
21422 }
21423
21424
21425  if ((is_dir($this->binDir)) && ($this->filesystem->isDirEmpty($this->binDir))) {
21426 Silencer::call('rmdir', $this->binDir);
21427 }
21428 }
21429
21430 public static function determineBinaryCaller($bin)
21431 {
21432 if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
21433 return 'call';
21434 }
21435
21436 $handle = fopen($bin, 'r');
21437 $line = fgets($handle);
21438 fclose($handle);
21439 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
21440 return trim($match[1]);
21441 }
21442
21443 return 'php';
21444 }
21445
21446 protected function getBinaries(PackageInterface $package)
21447 {
21448 return $package->getBinaries();
21449 }
21450
21451 protected function installFullBinaries($binPath, $link, $bin, PackageInterface $package)
21452 {
21453
21454  if ('.bat' !== substr($binPath, -4)) {
21455 $this->installUnixyProxyBinaries($binPath, $link);
21456 @chmod($link, 0777 & ~umask());
21457 $link .= '.bat';
21458 if (file_exists($link)) {
21459 $this->io->writeError('    Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
21460 }
21461 }
21462 if (!file_exists($link)) {
21463 file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
21464 }
21465 }
21466
21467 protected function installSymlinkBinaries($binPath, $link)
21468 {
21469 if (!$this->filesystem->relativeSymlink($binPath, $link)) {
21470 $this->installUnixyProxyBinaries($binPath, $link);
21471 }
21472 }
21473
21474 protected function installUnixyProxyBinaries($binPath, $link)
21475 {
21476 file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
21477 }
21478
21479 protected function initializeBinDir()
21480 {
21481 $this->filesystem->ensureDirectoryExists($this->binDir);
21482 $this->binDir = realpath($this->binDir);
21483 }
21484
21485 protected function generateWindowsProxyCode($bin, $link)
21486 {
21487 $binPath = $this->filesystem->findShortestPath($link, $bin);
21488 $caller = self::determineBinaryCaller($bin);
21489
21490 return "@ECHO OFF\r\n".
21491 "setlocal DISABLEDELAYEDEXPANSION\r\n".
21492 "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"\'')."\r\n".
21493 "{$caller} \"%BIN_TARGET%\" %*\r\n";
21494 }
21495
21496 protected function generateUnixyProxyCode($bin, $link)
21497 {
21498 $binPath = $this->filesystem->findShortestPath($link, $bin);
21499
21500 $binDir = ProcessExecutor::escape(dirname($binPath));
21501 $binFile = basename($binPath);
21502
21503 $proxyCode = <<<PROXY
21504 #!/usr/bin/env sh
21505
21506 dir=$(d=\${0%[/\\\\]*}; cd "\$d" > /dev/null; cd $binDir && pwd)
21507
21508 # See if we are running in Cygwin by checking for cygpath program
21509 if command -v 'cygpath' >/dev/null 2>&1; then
21510         # Cygwin paths start with /cygdrive/ which will break windows PHP,
21511         # so we need to translate the dir path to windows format. However
21512         # we could be using cygwin PHP which does not require this, so we
21513         # test if the path to PHP starts with /cygdrive/ rather than /usr/bin
21514         if [[ $(which php) == /cygdrive/* ]]; then
21515                 dir=$(cygpath -m "\$dir");
21516         fi
21517 fi
21518
21519 dir=$(echo \$dir | sed 's/ /\ /g')
21520 "\${dir}/$binFile" "$@"
21521
21522 PROXY;
21523
21524 return $proxyCode;
21525 }
21526 }
21527 <?php
21528
21529
21530
21531
21532
21533
21534
21535
21536
21537
21538
21539 namespace Composer\Installer;
21540
21541 use Composer\Package\PackageInterface;
21542
21543
21544
21545
21546
21547
21548 interface BinaryPresenceInterface
21549 {
21550
21551
21552
21553
21554
21555 public function ensureBinariesPresence(PackageInterface $package);
21556 }
21557 <?php
21558
21559
21560
21561
21562
21563
21564
21565
21566
21567
21568
21569 namespace Composer\Installer;
21570
21571 use Composer\IO\IOInterface;
21572 use Composer\Package\PackageInterface;
21573 use Composer\Package\AliasPackage;
21574 use Composer\Repository\RepositoryInterface;
21575 use Composer\Repository\InstalledRepositoryInterface;
21576 use Composer\DependencyResolver\Operation\OperationInterface;
21577 use Composer\DependencyResolver\Operation\InstallOperation;
21578 use Composer\DependencyResolver\Operation\UpdateOperation;
21579 use Composer\DependencyResolver\Operation\UninstallOperation;
21580 use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
21581 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
21582 use Composer\Util\StreamContextFactory;
21583
21584
21585
21586
21587
21588
21589
21590
21591 class InstallationManager
21592 {
21593 private $installers = array();
21594 private $cache = array();
21595 private $notifiablePackages = array();
21596
21597 public function reset()
21598 {
21599 $this->notifiablePackages = array();
21600 }
21601
21602
21603
21604
21605
21606
21607 public function addInstaller(InstallerInterface $installer)
21608 {
21609 array_unshift($this->installers, $installer);
21610 $this->cache = array();
21611 }
21612
21613
21614
21615
21616
21617
21618 public function removeInstaller(InstallerInterface $installer)
21619 {
21620 if (false !== ($key = array_search($installer, $this->installers, true))) {
21621 array_splice($this->installers, $key, 1);
21622 $this->cache = array();
21623 }
21624 }
21625
21626
21627
21628
21629
21630
21631
21632
21633 public function disablePlugins()
21634 {
21635 foreach ($this->installers as $i => $installer) {
21636 if (!$installer instanceof PluginInstaller) {
21637 continue;
21638 }
21639
21640 unset($this->installers[$i]);
21641 }
21642 }
21643
21644
21645
21646
21647
21648
21649
21650
21651
21652 public function getInstaller($type)
21653 {
21654 $type = strtolower($type);
21655
21656 if (isset($this->cache[$type])) {
21657 return $this->cache[$type];
21658 }
21659
21660 foreach ($this->installers as $installer) {
21661 if ($installer->supports($type)) {
21662 return $this->cache[$type] = $installer;
21663 }
21664 }
21665
21666 throw new \InvalidArgumentException('Unknown installer type: '.$type);
21667 }
21668
21669
21670
21671
21672
21673
21674
21675
21676
21677 public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
21678 {
21679 if ($package instanceof AliasPackage) {
21680 return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
21681 }
21682
21683 return $this->getInstaller($package->getType())->isInstalled($repo, $package);
21684 }
21685
21686
21687
21688
21689
21690
21691
21692 public function ensureBinariesPresence(PackageInterface $package)
21693 {
21694 try {
21695 $installer = $this->getInstaller($package->getType());
21696 } catch (\InvalidArgumentException $e) {
21697
21698  return;
21699 }
21700
21701
21702  if ($installer instanceof BinaryPresenceInterface) {
21703 $installer->ensureBinariesPresence($package);
21704 }
21705 }
21706
21707
21708
21709
21710
21711
21712
21713 public function execute(RepositoryInterface $repo, OperationInterface $operation)
21714 {
21715 $method = $operation->getJobType();
21716 $this->$method($repo, $operation);
21717 }
21718
21719
21720
21721
21722
21723
21724
21725 public function install(RepositoryInterface $repo, InstallOperation $operation)
21726 {
21727 $package = $operation->getPackage();
21728 $installer = $this->getInstaller($package->getType());
21729 $installer->install($repo, $package);
21730 $this->markForNotification($package);
21731 }
21732
21733
21734
21735
21736
21737
21738
21739 public function update(RepositoryInterface $repo, UpdateOperation $operation)
21740 {
21741 $initial = $operation->getInitialPackage();
21742 $target = $operation->getTargetPackage();
21743
21744 $initialType = $initial->getType();
21745 $targetType = $target->getType();
21746
21747 if ($initialType === $targetType) {
21748 $installer = $this->getInstaller($initialType);
21749 $installer->update($repo, $initial, $target);
21750 $this->markForNotification($target);
21751 } else {
21752 $this->getInstaller($initialType)->uninstall($repo, $initial);
21753 $this->getInstaller($targetType)->install($repo, $target);
21754 }
21755 }
21756
21757
21758
21759
21760
21761
21762
21763 public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
21764 {
21765 $package = $operation->getPackage();
21766 $installer = $this->getInstaller($package->getType());
21767 $installer->uninstall($repo, $package);
21768 }
21769
21770
21771
21772
21773
21774
21775
21776 public function markAliasInstalled(RepositoryInterface $repo, MarkAliasInstalledOperation $operation)
21777 {
21778 $package = $operation->getPackage();
21779
21780 if (!$repo->hasPackage($package)) {
21781 $repo->addPackage(clone $package);
21782 }
21783 }
21784
21785
21786
21787
21788
21789
21790
21791 public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
21792 {
21793 $package = $operation->getPackage();
21794
21795 $repo->removePackage($package);
21796 }
21797
21798
21799
21800
21801
21802
21803
21804 public function getInstallPath(PackageInterface $package)
21805 {
21806 $installer = $this->getInstaller($package->getType());
21807
21808 return $installer->getInstallPath($package);
21809 }
21810
21811 public function notifyInstalls(IOInterface $io)
21812 {
21813 foreach ($this->notifiablePackages as $repoUrl => $packages) {
21814 $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
21815 if ($io->hasAuthentication($repositoryName)) {
21816 $auth = $io->getAuthentication($repositoryName);
21817 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
21818 $authHeader = 'Authorization: Basic '.$authStr;
21819 }
21820
21821
21822  if (strpos($repoUrl, '%package%')) {
21823 foreach ($packages as $package) {
21824 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
21825
21826 $params = array(
21827 'version' => $package->getPrettyVersion(),
21828 'version_normalized' => $package->getVersion(),
21829 );
21830 $opts = array('http' =>
21831 array(
21832 'method' => 'POST',
21833 'header' => array('Content-type: application/x-www-form-urlencoded'),
21834 'content' => http_build_query($params, '', '&'),
21835 'timeout' => 3,
21836 ),
21837 );
21838 if (isset($authHeader)) {
21839 $opts['http']['header'][] = $authHeader;
21840 }
21841
21842 $context = StreamContextFactory::getContext($url, $opts);
21843 @file_get_contents($url, false, $context);
21844 }
21845
21846 continue;
21847 }
21848
21849 $postData = array('downloads' => array());
21850 foreach ($packages as $package) {
21851 $postData['downloads'][] = array(
21852 'name' => $package->getPrettyName(),
21853 'version' => $package->getVersion(),
21854 );
21855 }
21856
21857 $opts = array('http' =>
21858 array(
21859 'method' => 'POST',
21860 'header' => array('Content-Type: application/json'),
21861 'content' => json_encode($postData),
21862 'timeout' => 6,
21863 ),
21864 );
21865 if (isset($authHeader)) {
21866 $opts['http']['header'][] = $authHeader;
21867 }
21868
21869 $context = StreamContextFactory::getContext($repoUrl, $opts);
21870 @file_get_contents($repoUrl, false, $context);
21871 }
21872
21873 $this->reset();
21874 }
21875
21876 private function markForNotification(PackageInterface $package)
21877 {
21878 if ($package->getNotificationUrl()) {
21879 $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
21880 }
21881 }
21882 }
21883 <?php
21884
21885
21886
21887
21888
21889
21890
21891
21892
21893
21894
21895 namespace Composer\Installer;
21896
21897 use Composer\Composer;
21898 use Composer\DependencyResolver\PolicyInterface;
21899 use Composer\DependencyResolver\Operation\OperationInterface;
21900 use Composer\DependencyResolver\Pool;
21901 use Composer\DependencyResolver\Request;
21902 use Composer\EventDispatcher\Event;
21903 use Composer\IO\IOInterface;
21904 use Composer\Repository\CompositeRepository;
21905
21906
21907
21908
21909
21910
21911 class InstallerEvent extends Event
21912 {
21913
21914
21915
21916 private $composer;
21917
21918
21919
21920
21921 private $io;
21922
21923
21924
21925
21926 private $devMode;
21927
21928
21929
21930
21931 private $policy;
21932
21933
21934
21935
21936 private $pool;
21937
21938
21939
21940
21941 private $installedRepo;
21942
21943
21944
21945
21946 private $request;
21947
21948
21949
21950
21951 private $operations;
21952
21953
21954
21955
21956
21957
21958
21959
21960
21961
21962
21963
21964
21965
21966 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
21967 {
21968 parent::__construct($eventName);
21969
21970 $this->composer = $composer;
21971 $this->io = $io;
21972 $this->devMode = $devMode;
21973 $this->policy = $policy;
21974 $this->pool = $pool;
21975 $this->installedRepo = $installedRepo;
21976 $this->request = $request;
21977 $this->operations = $operations;
21978 }
21979
21980
21981
21982
21983 public function getComposer()
21984 {
21985 return $this->composer;
21986 }
21987
21988
21989
21990
21991 public function getIO()
21992 {
21993 return $this->io;
21994 }
21995
21996
21997
21998
21999 public function isDevMode()
22000 {
22001 return $this->devMode;
22002 }
22003
22004
22005
22006
22007 public function getPolicy()
22008 {
22009 return $this->policy;
22010 }
22011
22012
22013
22014
22015 public function getPool()
22016 {
22017 return $this->pool;
22018 }
22019
22020
22021
22022
22023 public function getInstalledRepo()
22024 {
22025 return $this->installedRepo;
22026 }
22027
22028
22029
22030
22031 public function getRequest()
22032 {
22033 return $this->request;
22034 }
22035
22036
22037
22038
22039 public function getOperations()
22040 {
22041 return $this->operations;
22042 }
22043 }
22044 <?php
22045
22046
22047
22048
22049
22050
22051
22052
22053
22054
22055
22056 namespace Composer\Installer;
22057
22058
22059
22060
22061
22062
22063 class InstallerEvents
22064 {
22065
22066
22067
22068
22069
22070
22071
22072
22073
22074 const PRE_DEPENDENCIES_SOLVING = 'pre-dependencies-solving';
22075
22076
22077
22078
22079
22080
22081
22082
22083
22084
22085 const POST_DEPENDENCIES_SOLVING = 'post-dependencies-solving';
22086 }
22087 <?php
22088
22089
22090
22091
22092
22093
22094
22095
22096
22097
22098
22099 namespace Composer\Installer;
22100
22101 use Composer\Package\PackageInterface;
22102 use Composer\Repository\InstalledRepositoryInterface;
22103 use InvalidArgumentException;
22104
22105
22106
22107
22108
22109
22110
22111 interface InstallerInterface
22112 {
22113
22114
22115
22116
22117
22118
22119 public function supports($packageType);
22120
22121
22122
22123
22124
22125
22126
22127
22128
22129 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
22130
22131
22132
22133
22134
22135
22136
22137 public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
22138
22139
22140
22141
22142
22143
22144
22145
22146
22147
22148 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
22149
22150
22151
22152
22153
22154
22155
22156 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
22157
22158
22159
22160
22161
22162
22163
22164 public function getInstallPath(PackageInterface $package);
22165 }
22166 <?php
22167
22168
22169
22170
22171
22172
22173
22174
22175
22176
22177
22178 namespace Composer\Installer;
22179
22180 use Composer\Composer;
22181 use Composer\IO\IOInterface;
22182 use Composer\Repository\InstalledRepositoryInterface;
22183 use Composer\Package\PackageInterface;
22184 use Composer\Util\Filesystem;
22185 use Composer\Util\Silencer;
22186
22187
22188
22189
22190
22191
22192
22193 class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
22194 {
22195 protected $composer;
22196 protected $vendorDir;
22197 protected $binDir;
22198 protected $downloadManager;
22199 protected $io;
22200 protected $type;
22201 protected $filesystem;
22202 protected $binCompat;
22203 protected $binaryInstaller;
22204
22205
22206
22207
22208
22209
22210
22211
22212
22213
22214 public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null, BinaryInstaller $binaryInstaller = null)
22215 {
22216 $this->composer = $composer;
22217 $this->downloadManager = $composer->getDownloadManager();
22218 $this->io = $io;
22219 $this->type = $type;
22220
22221 $this->filesystem = $filesystem ?: new Filesystem();
22222 $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
22223 $this->binaryInstaller = $binaryInstaller ?: new BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem);
22224 }
22225
22226
22227
22228
22229 public function supports($packageType)
22230 {
22231 return $packageType === $this->type || null === $this->type;
22232 }
22233
22234
22235
22236
22237 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22238 {
22239 return $repo->hasPackage($package) && is_readable($this->getInstallPath($package));
22240 }
22241
22242
22243
22244
22245 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22246 {
22247 $this->initializeVendorDir();
22248 $downloadPath = $this->getInstallPath($package);
22249
22250
22251  if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
22252 $this->binaryInstaller->removeBinaries($package);
22253 }
22254
22255 $this->installCode($package);
22256 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package));
22257 if (!$repo->hasPackage($package)) {
22258 $repo->addPackage(clone $package);
22259 }
22260 }
22261
22262
22263
22264
22265 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22266 {
22267 if (!$repo->hasPackage($initial)) {
22268 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22269 }
22270
22271 $this->initializeVendorDir();
22272
22273 $this->binaryInstaller->removeBinaries($initial);
22274 $this->updateCode($initial, $target);
22275 $this->binaryInstaller->installBinaries($target, $this->getInstallPath($target));
22276 $repo->removePackage($initial);
22277 if (!$repo->hasPackage($target)) {
22278 $repo->addPackage(clone $target);
22279 }
22280 }
22281
22282
22283
22284
22285 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22286 {
22287 if (!$repo->hasPackage($package)) {
22288 throw new \InvalidArgumentException('Package is not installed: '.$package);
22289 }
22290
22291 $this->removeCode($package);
22292 $this->binaryInstaller->removeBinaries($package);
22293 $repo->removePackage($package);
22294
22295 $downloadPath = $this->getPackageBasePath($package);
22296 if (strpos($package->getName(), '/')) {
22297 $packageVendorDir = dirname($downloadPath);
22298 if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
22299 Silencer::call('rmdir', $packageVendorDir);
22300 }
22301 }
22302 }
22303
22304
22305
22306
22307 public function getInstallPath(PackageInterface $package)
22308 {
22309 $this->initializeVendorDir();
22310
22311 $basePath = ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
22312 $targetDir = $package->getTargetDir();
22313
22314 return $basePath . ($targetDir ? '/'.$targetDir : '');
22315 }
22316
22317
22318
22319
22320
22321
22322 public function ensureBinariesPresence(PackageInterface $package)
22323 {
22324 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), false);
22325 }
22326
22327
22328
22329
22330
22331
22332
22333
22334
22335
22336 protected function getPackageBasePath(PackageInterface $package)
22337 {
22338 $installPath = $this->getInstallPath($package);
22339 $targetDir = $package->getTargetDir();
22340
22341 if ($targetDir) {
22342 return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath);
22343 }
22344
22345 return $installPath;
22346 }
22347
22348 protected function installCode(PackageInterface $package)
22349 {
22350 $downloadPath = $this->getInstallPath($package);
22351 $this->downloadManager->download($package, $downloadPath);
22352 }
22353
22354 protected function updateCode(PackageInterface $initial, PackageInterface $target)
22355 {
22356 $initialDownloadPath = $this->getInstallPath($initial);
22357 $targetDownloadPath = $this->getInstallPath($target);
22358 if ($targetDownloadPath !== $initialDownloadPath) {
22359
22360  
22361  if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
22362 || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
22363 ) {
22364 $this->removeCode($initial);
22365 $this->installCode($target);
22366
22367 return;
22368 }
22369
22370 $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
22371 }
22372 $this->downloadManager->update($initial, $target, $targetDownloadPath);
22373 }
22374
22375 protected function removeCode(PackageInterface $package)
22376 {
22377 $downloadPath = $this->getPackageBasePath($package);
22378 $this->downloadManager->remove($package, $downloadPath);
22379 }
22380
22381 protected function initializeVendorDir()
22382 {
22383 $this->filesystem->ensureDirectoryExists($this->vendorDir);
22384 $this->vendorDir = realpath($this->vendorDir);
22385 }
22386 }
22387 <?php
22388
22389
22390
22391
22392
22393
22394
22395
22396
22397
22398
22399 namespace Composer\Installer;
22400
22401 use Composer\Repository\InstalledRepositoryInterface;
22402 use Composer\Package\PackageInterface;
22403
22404
22405
22406
22407
22408
22409 class MetapackageInstaller implements InstallerInterface
22410 {
22411
22412
22413
22414 public function supports($packageType)
22415 {
22416 return $packageType === 'metapackage';
22417 }
22418
22419
22420
22421
22422 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22423 {
22424 return $repo->hasPackage($package);
22425 }
22426
22427
22428
22429
22430 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22431 {
22432 $repo->addPackage(clone $package);
22433 }
22434
22435
22436
22437
22438 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22439 {
22440 if (!$repo->hasPackage($initial)) {
22441 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22442 }
22443
22444 $repo->removePackage($initial);
22445 $repo->addPackage(clone $target);
22446 }
22447
22448
22449
22450
22451 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22452 {
22453 if (!$repo->hasPackage($package)) {
22454 throw new \InvalidArgumentException('Package is not installed: '.$package);
22455 }
22456
22457 $repo->removePackage($package);
22458 }
22459
22460
22461
22462
22463 public function getInstallPath(PackageInterface $package)
22464 {
22465 return '';
22466 }
22467 }
22468 <?php
22469
22470
22471
22472
22473
22474
22475
22476
22477
22478
22479
22480 namespace Composer\Installer;
22481
22482 use Composer\Repository\InstalledRepositoryInterface;
22483 use Composer\Package\PackageInterface;
22484
22485
22486
22487
22488
22489
22490
22491
22492 class NoopInstaller implements InstallerInterface
22493 {
22494
22495
22496
22497 public function supports($packageType)
22498 {
22499 return true;
22500 }
22501
22502
22503
22504
22505 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22506 {
22507 return $repo->hasPackage($package);
22508 }
22509
22510
22511
22512
22513 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22514 {
22515 if (!$repo->hasPackage($package)) {
22516 $repo->addPackage(clone $package);
22517 }
22518 }
22519
22520
22521
22522
22523 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22524 {
22525 if (!$repo->hasPackage($initial)) {
22526 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22527 }
22528
22529 $repo->removePackage($initial);
22530 if (!$repo->hasPackage($target)) {
22531 $repo->addPackage(clone $target);
22532 }
22533 }
22534
22535
22536
22537
22538 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22539 {
22540 if (!$repo->hasPackage($package)) {
22541 throw new \InvalidArgumentException('Package is not installed: '.$package);
22542 }
22543 $repo->removePackage($package);
22544 }
22545
22546
22547
22548
22549 public function getInstallPath(PackageInterface $package)
22550 {
22551 $targetDir = $package->getTargetDir();
22552
22553 return $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
22554 }
22555 }
22556 <?php
22557
22558
22559
22560
22561
22562
22563
22564
22565
22566
22567
22568 namespace Composer\Installer;
22569
22570 use Composer\Composer;
22571 use Composer\IO\IOInterface;
22572 use Composer\DependencyResolver\Operation\OperationInterface;
22573 use Composer\DependencyResolver\PolicyInterface;
22574 use Composer\DependencyResolver\Pool;
22575 use Composer\DependencyResolver\Request;
22576 use Composer\Repository\CompositeRepository;
22577
22578
22579
22580
22581
22582
22583 class PackageEvent extends InstallerEvent
22584 {
22585
22586
22587
22588 private $operation;
22589
22590
22591
22592
22593
22594
22595
22596
22597
22598
22599
22600
22601
22602
22603
22604 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
22605 {
22606 parent::__construct($eventName, $composer, $io, $devMode, $policy, $pool, $installedRepo, $request, $operations);
22607
22608 $this->operation = $operation;
22609 }
22610
22611
22612
22613
22614
22615
22616 public function getOperation()
22617 {
22618 return $this->operation;
22619 }
22620 }
22621 <?php
22622
22623
22624
22625
22626
22627
22628
22629
22630
22631
22632
22633 namespace Composer\Installer;
22634
22635
22636
22637
22638
22639
22640 class PackageEvents
22641 {
22642
22643
22644
22645
22646
22647
22648
22649 const PRE_PACKAGE_INSTALL = 'pre-package-install';
22650
22651
22652
22653
22654
22655
22656
22657
22658 const POST_PACKAGE_INSTALL = 'post-package-install';
22659
22660
22661
22662
22663
22664
22665
22666
22667 const PRE_PACKAGE_UPDATE = 'pre-package-update';
22668
22669
22670
22671
22672
22673
22674
22675
22676 const POST_PACKAGE_UPDATE = 'post-package-update';
22677
22678
22679
22680
22681
22682
22683
22684
22685 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
22686
22687
22688
22689
22690
22691
22692
22693
22694 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
22695 }
22696 <?php
22697
22698
22699
22700
22701
22702
22703
22704
22705
22706
22707
22708 namespace Composer\Installer;
22709
22710 use Composer\IO\IOInterface;
22711 use Composer\Package\PackageInterface;
22712 use Composer\Util\Filesystem;
22713 use Composer\Util\ProcessExecutor;
22714
22715
22716
22717
22718
22719
22720 class PearBinaryInstaller extends BinaryInstaller
22721 {
22722 private $installer;
22723 private $vendorDir;
22724
22725
22726
22727
22728
22729
22730
22731
22732
22733 public function __construct(IOInterface $io, $binDir, $vendorDir, $binCompat, Filesystem $filesystem, PearInstaller $installer)
22734 {
22735 parent::__construct($io, $binDir, $binCompat, $filesystem);
22736 $this->installer = $installer;
22737 $this->vendorDir = $vendorDir;
22738 }
22739
22740 protected function getBinaries(PackageInterface $package)
22741 {
22742 $binariesPath = $this->installer->getInstallPath($package) . '/bin/';
22743 $binaries = array();
22744 if (file_exists($binariesPath)) {
22745 foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::CURRENT_AS_FILEINFO) as $fileName => $value) {
22746 if (!$value->isDir()) {
22747 $binaries[] = 'bin/'.$fileName;
22748 }
22749 }
22750 }
22751
22752 return $binaries;
22753 }
22754
22755 protected function initializeBinDir()
22756 {
22757 parent::initializeBinDir();
22758 file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode());
22759 @chmod($this->binDir.'/composer-php', 0777);
22760 file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode());
22761 @chmod($this->binDir.'/composer-php.bat', 0777);
22762 }
22763
22764 protected function generateWindowsProxyCode($bin, $link)
22765 {
22766 $binPath = $this->filesystem->findShortestPath($link, $bin);
22767 if ('.bat' === substr($bin, -4)) {
22768 $caller = 'call';
22769 } else {
22770 $handle = fopen($bin, 'r');
22771 $line = fgets($handle);
22772 fclose($handle);
22773 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
22774 $caller = trim($match[1]);
22775 } else {
22776 $caller = 'php';
22777 }
22778
22779 if ($caller === 'php') {
22780 return "@echo off\r\n".
22781 "pushd .\r\n".
22782 "cd %~dp0\r\n".
22783 "set PHP_PROXY=%CD%\\composer-php.bat\r\n".
22784 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
22785 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
22786 "popd\r\n".
22787 "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n";
22788 }
22789 }
22790
22791 return "@echo off\r\n".
22792 "pushd .\r\n".
22793 "cd %~dp0\r\n".
22794 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
22795 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
22796 "popd\r\n".
22797 $caller." \"%BIN_TARGET%\" %*\r\n";
22798 }
22799
22800 private function generateWindowsPhpProxyCode()
22801 {
22802 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
22803
22804 return
22805 "@echo off\r\n" .
22806 "setlocal enabledelayedexpansion\r\n" .
22807 "set BIN_DIR=%~dp0\r\n" .
22808 "set VENDOR_DIR=%BIN_DIR%\\".$binToVendor."\r\n" .
22809 "set DIRS=.\r\n" .
22810 "FOR /D %%V IN (%VENDOR_DIR%\\*) DO (\r\n" .
22811 "    FOR /D %%P IN (%%V\\*) DO (\r\n" .
22812 "        set DIRS=!DIRS!;%%~fP\r\n" .
22813 "    )\r\n" .
22814 ")\r\n" .
22815 "php.exe -d include_path=!DIRS! %*\r\n";
22816 }
22817
22818 private function generateUnixyPhpProxyCode()
22819 {
22820 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
22821
22822 return
22823 "#!/usr/bin/env sh\n".
22824 "SRC_DIR=`pwd`\n".
22825 "BIN_DIR=`dirname $0`\n".
22826 "VENDOR_DIR=\$BIN_DIR/".escapeshellarg($binToVendor)."\n".
22827 "DIRS=\"\"\n".
22828 "for vendor in \$VENDOR_DIR/*; do\n".
22829 "    if [ -d \"\$vendor\" ]; then\n".
22830 "        for package in \$vendor/*; do\n".
22831 "            if [ -d \"\$package\" ]; then\n".
22832 "                DIRS=\"\${DIRS}:\${package}\"\n".
22833 "            fi\n".
22834 "        done\n".
22835 "    fi\n".
22836 "done\n".
22837 "php -d include_path=\".\$DIRS\" $@\n";
22838 }
22839 }
22840 <?php
22841
22842
22843
22844
22845
22846
22847
22848
22849
22850
22851
22852 namespace Composer\Installer;
22853
22854 use Composer\IO\IOInterface;
22855 use Composer\Composer;
22856 use Composer\Downloader\PearPackageExtractor;
22857 use Composer\Repository\InstalledRepositoryInterface;
22858 use Composer\Package\PackageInterface;
22859 use Composer\Util\Platform;
22860 use Composer\Util\Filesystem;
22861
22862
22863
22864
22865
22866
22867
22868 class PearInstaller extends LibraryInstaller
22869 {
22870
22871
22872
22873
22874
22875
22876
22877 public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
22878 {
22879 $filesystem = new Filesystem();
22880 $binaryInstaller = new PearBinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), rtrim($composer->getConfig()->get('vendor-dir'), '/'), $composer->getConfig()->get('bin-compat'), $filesystem, $this);
22881
22882 parent::__construct($io, $composer, $type, $filesystem, $binaryInstaller);
22883 }
22884
22885
22886
22887
22888 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22889 {
22890 $this->uninstall($repo, $initial);
22891 $this->install($repo, $target);
22892 }
22893
22894 protected function installCode(PackageInterface $package)
22895 {
22896 parent::installCode($package);
22897
22898 $isWindows = Platform::isWindows();
22899 $php_bin = $this->binDir . ($isWindows ? '/composer-php.bat' : '/composer-php');
22900
22901 if (!$isWindows) {
22902 $php_bin = '/usr/bin/env ' . $php_bin;
22903 }
22904
22905 $installPath = $this->getInstallPath($package);
22906 $vars = array(
22907 'os' => $isWindows ? 'windows' : 'linux',
22908 'php_bin' => $php_bin,
22909 'pear_php' => $installPath,
22910 'php_dir' => $installPath,
22911 'bin_dir' => $installPath . '/bin',
22912 'data_dir' => $installPath . '/data',
22913 'version' => $package->getPrettyVersion(),
22914 );
22915
22916 $packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
22917 $pearExtractor = new PearPackageExtractor($packageArchive);
22918 $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
22919
22920 $this->io->writeError('    Cleaning up', true, IOInterface::VERBOSE);
22921 $this->filesystem->unlink($packageArchive);
22922 }
22923 }
22924 <?php
22925
22926
22927
22928
22929
22930
22931
22932
22933
22934
22935
22936 namespace Composer\Installer;
22937
22938 use Composer\Composer;
22939 use Composer\IO\IOInterface;
22940 use Composer\Repository\InstalledRepositoryInterface;
22941 use Composer\Package\PackageInterface;
22942
22943
22944
22945
22946
22947
22948
22949 class PluginInstaller extends LibraryInstaller
22950 {
22951 private $installationManager;
22952
22953
22954
22955
22956
22957
22958
22959
22960 public function __construct(IOInterface $io, Composer $composer, $type = 'library')
22961 {
22962 parent::__construct($io, $composer, 'composer-plugin');
22963 $this->installationManager = $composer->getInstallationManager();
22964 }
22965
22966
22967
22968
22969 public function supports($packageType)
22970 {
22971 return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
22972 }
22973
22974
22975
22976
22977 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22978 {
22979 $extra = $package->getExtra();
22980 if (empty($extra['class'])) {
22981 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
22982 }
22983
22984 parent::install($repo, $package);
22985 try {
22986 $this->composer->getPluginManager()->registerPackage($package, true);
22987 } catch (\Exception $e) {
22988
22989  $this->io->writeError('Plugin installation failed, rolling back');
22990 parent::uninstall($repo, $package);
22991 throw $e;
22992 }
22993 }
22994
22995
22996
22997
22998 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22999 {
23000 $extra = $target->getExtra();
23001 if (empty($extra['class'])) {
23002 throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
23003 }
23004
23005 parent::update($repo, $initial, $target);
23006 $this->composer->getPluginManager()->registerPackage($target, true);
23007 }
23008 }
23009 <?php
23010
23011
23012
23013
23014
23015
23016
23017
23018
23019
23020
23021 namespace Composer\Installer;
23022
23023 use Composer\Package\PackageInterface;
23024 use Composer\Downloader\DownloadManager;
23025 use Composer\Repository\InstalledRepositoryInterface;
23026 use Composer\Util\Filesystem;
23027
23028
23029
23030
23031
23032
23033
23034 class ProjectInstaller implements InstallerInterface
23035 {
23036 private $installPath;
23037 private $downloadManager;
23038 private $filesystem;
23039
23040 public function __construct($installPath, DownloadManager $dm)
23041 {
23042 $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/';
23043 $this->downloadManager = $dm;
23044 $this->filesystem = new Filesystem;
23045 }
23046
23047
23048
23049
23050
23051
23052
23053 public function supports($packageType)
23054 {
23055 return true;
23056 }
23057
23058
23059
23060
23061 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23062 {
23063 return false;
23064 }
23065
23066
23067
23068
23069 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23070 {
23071 $installPath = $this->installPath;
23072 if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
23073 throw new \InvalidArgumentException("Project directory $installPath is not empty.");
23074 }
23075 if (!is_dir($installPath)) {
23076 mkdir($installPath, 0777, true);
23077 }
23078 $this->downloadManager->download($package, $installPath);
23079 }
23080
23081
23082
23083
23084 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23085 {
23086 throw new \InvalidArgumentException("not supported");
23087 }
23088
23089
23090
23091
23092 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23093 {
23094 throw new \InvalidArgumentException("not supported");
23095 }
23096
23097
23098
23099
23100
23101
23102
23103 public function getInstallPath(PackageInterface $package)
23104 {
23105 return $this->installPath;
23106 }
23107 }
23108 <?php
23109
23110
23111
23112
23113
23114
23115
23116
23117
23118
23119
23120 namespace Composer\Installer;
23121
23122 use Composer\IO\IOInterface;
23123 use Composer\Package\PackageInterface;
23124 use Composer\Repository\RepositoryInterface;
23125 use Symfony\Component\Console\Formatter\OutputFormatter;
23126
23127
23128
23129
23130
23131
23132 class SuggestedPackagesReporter
23133 {
23134
23135
23136
23137 protected $suggestedPackages = array();
23138
23139
23140
23141
23142 private $io;
23143
23144 public function __construct(IOInterface $io)
23145 {
23146 $this->io = $io;
23147 }
23148
23149
23150
23151
23152 public function getPackages()
23153 {
23154 return $this->suggestedPackages;
23155 }
23156
23157
23158
23159
23160
23161
23162
23163
23164
23165
23166
23167
23168 public function addPackage($source, $target, $reason)
23169 {
23170 $this->suggestedPackages[] = array(
23171 'source' => $source,
23172 'target' => $target,
23173 'reason' => $reason,
23174 );
23175
23176 return $this;
23177 }
23178
23179
23180
23181
23182
23183
23184
23185 public function addSuggestionsFromPackage(PackageInterface $package)
23186 {
23187 $source = $package->getPrettyName();
23188 foreach ($package->getSuggests() as $target => $reason) {
23189 $this->addPackage(
23190 $source,
23191 $target,
23192 $reason
23193 );
23194 }
23195
23196 return $this;
23197 }
23198
23199
23200
23201
23202
23203
23204
23205
23206 public function output(RepositoryInterface $installedRepo = null)
23207 {
23208 $suggestedPackages = $this->getPackages();
23209 $installedPackages = array();
23210 if (null !== $installedRepo && ! empty($suggestedPackages)) {
23211 foreach ($installedRepo->getPackages() as $package) {
23212 $installedPackages = array_merge(
23213 $installedPackages,
23214 $package->getNames()
23215 );
23216 }
23217 }
23218
23219 foreach ($suggestedPackages as $suggestion) {
23220 if (in_array($suggestion['target'], $installedPackages)) {
23221 continue;
23222 }
23223
23224 $this->io->writeError(sprintf(
23225 '%s suggests installing %s (%s)',
23226 $suggestion['source'],
23227 $this->escapeOutput($suggestion['target']),
23228 $this->escapeOutput($suggestion['reason'])
23229 ));
23230 }
23231
23232 return $this;
23233 }
23234
23235
23236
23237
23238
23239 private function escapeOutput($string)
23240 {
23241 return OutputFormatter::escape(
23242 $this->removeControlCharacters($string)
23243 );
23244 }
23245
23246
23247
23248
23249
23250 private function removeControlCharacters($string)
23251 {
23252 return preg_replace(
23253 '/[[:cntrl:]]/',
23254 '',
23255 str_replace("\n", ' ', $string)
23256 );
23257 }
23258 }
23259 <?php
23260
23261
23262
23263
23264
23265
23266
23267
23268
23269
23270
23271 namespace Composer\Json;
23272
23273 use JsonSchema\Validator;
23274 use Seld\JsonLint\JsonParser;
23275 use Seld\JsonLint\ParsingException;
23276 use Composer\Util\RemoteFilesystem;
23277 use Composer\IO\IOInterface;
23278 use Composer\Downloader\TransportException;
23279
23280
23281
23282
23283
23284
23285
23286 class JsonFile
23287 {
23288 const LAX_SCHEMA = 1;
23289 const STRICT_SCHEMA = 2;
23290
23291 const JSON_UNESCAPED_SLASHES = 64;
23292 const JSON_PRETTY_PRINT = 128;
23293 const JSON_UNESCAPED_UNICODE = 256;
23294
23295 private $path;
23296 private $rfs;
23297 private $io;
23298
23299
23300
23301
23302
23303
23304
23305
23306
23307 public function __construct($path, RemoteFilesystem $rfs = null, IOInterface $io = null)
23308 {
23309 $this->path = $path;
23310
23311 if (null === $rfs && preg_match('{^https?://}i', $path)) {
23312 throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed');
23313 }
23314 $this->rfs = $rfs;
23315 $this->io = $io;
23316 }
23317
23318
23319
23320
23321 public function getPath()
23322 {
23323 return $this->path;
23324 }
23325
23326
23327
23328
23329
23330
23331 public function exists()
23332 {
23333 return is_file($this->path);
23334 }
23335
23336
23337
23338
23339
23340
23341
23342 public function read()
23343 {
23344 try {
23345 if ($this->rfs) {
23346 $json = $this->rfs->getContents($this->path, $this->path, false);
23347 } else {
23348 if ($this->io && $this->io->isDebug()) {
23349 $this->io->writeError('Reading ' . $this->path);
23350 }
23351 $json = file_get_contents($this->path);
23352 }
23353 } catch (TransportException $e) {
23354 throw new \RuntimeException($e->getMessage(), 0, $e);
23355 } catch (\Exception $e) {
23356 throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
23357 }
23358
23359 return static::parseJson($json, $this->path);
23360 }
23361
23362
23363
23364
23365
23366
23367
23368
23369 public function write(array $hash, $options = 448)
23370 {
23371 $dir = dirname($this->path);
23372 if (!is_dir($dir)) {
23373 if (file_exists($dir)) {
23374 throw new \UnexpectedValueException(
23375 $dir.' exists and is not a directory.'
23376 );
23377 }
23378 if (!@mkdir($dir, 0777, true)) {
23379 throw new \UnexpectedValueException(
23380 $dir.' does not exist and could not be created.'
23381 );
23382 }
23383 }
23384
23385 $retries = 3;
23386 while ($retries--) {
23387 try {
23388 file_put_contents($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : ''));
23389 break;
23390 } catch (\Exception $e) {
23391 if ($retries) {
23392 usleep(500000);
23393 continue;
23394 }
23395
23396 throw $e;
23397 }
23398 }
23399 }
23400
23401
23402
23403
23404
23405
23406
23407
23408 public function validateSchema($schema = self::STRICT_SCHEMA)
23409 {
23410 $content = file_get_contents($this->path);
23411 $data = json_decode($content);
23412
23413 if (null === $data && 'null' !== $content) {
23414 self::validateSyntax($content, $this->path);
23415 }
23416
23417 $schemaFile = __DIR__ . '/../../../res/composer-schema.json';
23418
23419
23420  if (false === strpos($schemaFile, '://')) {
23421 $schemaFile = 'file://' . $schemaFile;
23422 }
23423
23424 $schemaData = (object) array('$ref' => $schemaFile);
23425
23426 if ($schema === self::LAX_SCHEMA) {
23427 $schemaData->additionalProperties = true;
23428 $schemaData->required = array();
23429 }
23430
23431 $validator = new Validator();
23432 $validator->check($data, $schemaData);
23433
23434
23435
23436 if (!$validator->isValid()) {
23437 $errors = array();
23438 foreach ((array) $validator->getErrors() as $error) {
23439 $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
23440 }
23441 throw new JsonValidationException('"'.$this->path.'" does not match the expected JSON schema', $errors);
23442 }
23443
23444 return true;
23445 }
23446
23447
23448
23449
23450
23451
23452
23453
23454 public static function encode($data, $options = 448)
23455 {
23456 if (PHP_VERSION_ID >= 50400) {
23457 $json = json_encode($data, $options);
23458 if (false === $json) {
23459 self::throwEncodeError(json_last_error());
23460 }
23461
23462
23463  if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
23464 $json = preg_replace('/\[\s+\]/', '[]', $json);
23465 $json = preg_replace('/\{\s+\}/', '{}', $json);
23466 }
23467
23468 return $json;
23469 }
23470
23471 $json = json_encode($data);
23472 if (false === $json) {
23473 self::throwEncodeError(json_last_error());
23474 }
23475
23476 $prettyPrint = (bool) ($options & self::JSON_PRETTY_PRINT);
23477 $unescapeUnicode = (bool) ($options & self::JSON_UNESCAPED_UNICODE);
23478 $unescapeSlashes = (bool) ($options & self::JSON_UNESCAPED_SLASHES);
23479
23480 if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes) {
23481 return $json;
23482 }
23483
23484 $result = JsonFormatter::format($json, $unescapeUnicode, $unescapeSlashes);
23485
23486 return $result;
23487 }
23488
23489
23490
23491
23492
23493
23494
23495 private static function throwEncodeError($code)
23496 {
23497 switch ($code) {
23498 case JSON_ERROR_DEPTH:
23499 $msg = 'Maximum stack depth exceeded';
23500 break;
23501 case JSON_ERROR_STATE_MISMATCH:
23502 $msg = 'Underflow or the modes mismatch';
23503 break;
23504 case JSON_ERROR_CTRL_CHAR:
23505 $msg = 'Unexpected control character found';
23506 break;
23507 case JSON_ERROR_UTF8:
23508 $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
23509 break;
23510 default:
23511 $msg = 'Unknown error';
23512 }
23513
23514 throw new \RuntimeException('JSON encoding failed: '.$msg);
23515 }
23516
23517
23518
23519
23520
23521
23522
23523
23524
23525 public static function parseJson($json, $file = null)
23526 {
23527 if (null === $json) {
23528 return;
23529 }
23530 $data = json_decode($json, true);
23531 if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
23532 self::validateSyntax($json, $file);
23533 }
23534
23535 return $data;
23536 }
23537
23538
23539
23540
23541
23542
23543
23544
23545
23546
23547
23548 protected static function validateSyntax($json, $file = null)
23549 {
23550 $parser = new JsonParser();
23551 $result = $parser->lint($json);
23552 if (null === $result) {
23553 if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
23554 throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
23555 }
23556
23557 return true;
23558 }
23559
23560 throw new ParsingException('"'.$file.'" does not contain valid JSON'."\n".$result->getMessage(), $result->getDetails());
23561 }
23562 }
23563 <?php
23564
23565
23566
23567
23568
23569
23570
23571
23572
23573
23574
23575 namespace Composer\Json;
23576
23577
23578
23579
23580
23581
23582
23583
23584
23585 class JsonFormatter
23586 {
23587
23588
23589
23590
23591
23592
23593
23594
23595
23596
23597
23598
23599 public static function format($json, $unescapeUnicode, $unescapeSlashes)
23600 {
23601 $result = '';
23602 $pos = 0;
23603 $strLen = strlen($json);
23604 $indentStr = '    ';
23605 $newLine = "\n";
23606 $outOfQuotes = true;
23607 $buffer = '';
23608 $noescape = true;
23609
23610 for ($i = 0; $i < $strLen; $i++) {
23611
23612  $char = substr($json, $i, 1);
23613
23614
23615  if ('"' === $char && $noescape) {
23616 $outOfQuotes = !$outOfQuotes;
23617 }
23618
23619 if (!$outOfQuotes) {
23620 $buffer .= $char;
23621 $noescape = '\\' === $char ? !$noescape : true;
23622 continue;
23623 } elseif ('' !== $buffer) {
23624 if ($unescapeSlashes) {
23625 $buffer = str_replace('\\/', '/', $buffer);
23626 }
23627
23628 if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
23629
23630  $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) {
23631 $l = strlen($match[1]);
23632
23633 if ($l % 2) {
23634 return str_repeat('\\', $l - 1) . mb_convert_encoding(
23635 pack('H*', $match[2]),
23636 'UTF-8',
23637 'UCS-2BE'
23638 );
23639 }
23640
23641 return $match[0];
23642 }, $buffer);
23643 }
23644
23645 $result .= $buffer.$char;
23646 $buffer = '';
23647 continue;
23648 }
23649
23650 if (':' === $char) {
23651
23652  $char .= ' ';
23653 } elseif (('}' === $char || ']' === $char)) {
23654 $pos--;
23655 $prevChar = substr($json, $i - 1, 1);
23656
23657 if ('{' !== $prevChar && '[' !== $prevChar) {
23658
23659  
23660  $result .= $newLine;
23661 for ($j = 0; $j < $pos; $j++) {
23662 $result .= $indentStr;
23663 }
23664 } else {
23665
23666  $result = rtrim($result);
23667 }
23668 }
23669
23670 $result .= $char;
23671
23672
23673  
23674  if (',' === $char || '{' === $char || '[' === $char) {
23675 $result .= $newLine;
23676
23677 if ('{' === $char || '[' === $char) {
23678 $pos++;
23679 }
23680
23681 for ($j = 0; $j < $pos; $j++) {
23682 $result .= $indentStr;
23683 }
23684 }
23685 }
23686
23687 return $result;
23688 }
23689 }
23690 <?php
23691
23692
23693
23694
23695
23696
23697
23698
23699
23700
23701
23702 namespace Composer\Json;
23703
23704 use Composer\Repository\PlatformRepository;
23705
23706
23707
23708
23709 class JsonManipulator
23710 {
23711 private static $DEFINES = '(?(DEFINE)
23712        (?<number>   -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
23713        (?<boolean>   true | false | null )
23714        (?<string>    " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
23715        (?<array>     \[  (?:  (?&json) \s* (?: , (?&json) \s* )*  )?  \s* \] )
23716        (?<pair>      \s* (?&string) \s* : (?&json) \s* )
23717        (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
23718        (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
23719     )';
23720
23721 private $contents;
23722 private $newline;
23723 private $indent;
23724
23725 public function __construct($contents)
23726 {
23727 $contents = trim($contents);
23728 if ($contents === '') {
23729 $contents = '{}';
23730 }
23731 if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) {
23732 throw new \InvalidArgumentException('The json file must be an object ({})');
23733 }
23734 $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
23735 $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
23736 $this->detectIndenting();
23737 }
23738
23739 public function getContents()
23740 {
23741 return $this->contents . $this->newline;
23742 }
23743
23744 public function addLink($type, $package, $constraint, $sortPackages = false)
23745 {
23746 $decoded = JsonFile::parseJson($this->contents);
23747
23748
23749  if (!isset($decoded[$type])) {
23750 return $this->addMainKey($type, array($package => $constraint));
23751 }
23752
23753 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
23754 '(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
23755 if (!$this->pregMatch($regex, $this->contents, $matches)) {
23756 return false;
23757 }
23758
23759 $links = $matches['value'];
23760
23761
23762  $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
23763 $regex = '{'.self::$DEFINES.'"(?P<package>'.$packageRegex.')"(\s*:\s*)(?&string)}ix';
23764 if ($this->pregMatch($regex, $links, $packageMatches)) {
23765
23766  $existingPackage = $packageMatches['package'];
23767 $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage));
23768 $links = preg_replace_callback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P<separator>\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) {
23769 return JsonFile::encode(str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"';
23770 }, $links);
23771 } else {
23772 if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
23773
23774  $links = preg_replace(
23775 '{'.preg_quote($match[1]).'$}',
23776
23777  addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
23778 $links
23779 );
23780 } else {
23781
23782  $links = '{' . $this->newline .
23783 $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
23784 $this->indent . '}';
23785 }
23786 }
23787
23788 if (true === $sortPackages) {
23789 $requirements = json_decode($links, true);
23790 $this->sortPackages($requirements);
23791 $links = $this->format($requirements);
23792 }
23793
23794 $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end'];
23795
23796 return true;
23797 }
23798
23799
23800
23801
23802
23803
23804
23805
23806 private function sortPackages(array &$packages = array())
23807 {
23808 $prefix = function ($requirement) {
23809 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) {
23810 return preg_replace(
23811 array(
23812 '/^php/',
23813 '/^hhvm/',
23814 '/^ext/',
23815 '/^lib/',
23816 '/^\D/',
23817 ),
23818 array(
23819 '0-$0',
23820 '1-$0',
23821 '2-$0',
23822 '3-$0',
23823 '4-$0',
23824 ),
23825 $requirement
23826 );
23827 }
23828
23829 return '5-'.$requirement;
23830 };
23831
23832 uksort($packages, function ($a, $b) use ($prefix) {
23833 return strnatcmp($prefix($a), $prefix($b));
23834 });
23835 }
23836
23837 public function addRepository($name, $config)
23838 {
23839 return $this->addSubNode('repositories', $name, $config);
23840 }
23841
23842 public function removeRepository($name)
23843 {
23844 return $this->removeSubNode('repositories', $name);
23845 }
23846
23847 public function addConfigSetting($name, $value)
23848 {
23849 return $this->addSubNode('config', $name, $value);
23850 }
23851
23852 public function removeConfigSetting($name)
23853 {
23854 return $this->removeSubNode('config', $name);
23855 }
23856
23857 public function addProperty($name, $value)
23858 {
23859 if (substr($name, 0, 6) === 'extra.') {
23860 return $this->addSubNode('extra', substr($name, 6), $value);
23861 }
23862
23863 return $this->addMainKey($name, $value);
23864 }
23865
23866 public function removeProperty($name)
23867 {
23868 if (substr($name, 0, 6) === 'extra.') {
23869 return $this->removeSubNode('extra', substr($name, 6));
23870 }
23871
23872 return $this->removeMainKey($name);
23873 }
23874
23875 public function addSubNode($mainNode, $name, $value)
23876 {
23877 $decoded = JsonFile::parseJson($this->contents);
23878
23879 $subName = null;
23880 if (in_array($mainNode, array('config', 'extra')) && false !== strpos($name, '.')) {
23881 list($name, $subName) = explode('.', $name, 2);
23882 }
23883
23884
23885  if (!isset($decoded[$mainNode])) {
23886 if ($subName !== null) {
23887 $this->addMainKey($mainNode, array($name => array($subName => $value)));
23888 } else {
23889 $this->addMainKey($mainNode, array($name => $value));
23890 }
23891
23892 return true;
23893 }
23894
23895
23896  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
23897 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
23898
23899 try {
23900 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
23901 return false;
23902 }
23903 } catch (\RuntimeException $e) {
23904 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
23905 return false;
23906 }
23907 throw $e;
23908 }
23909
23910 $children = $match['content'];
23911
23912  if (!@json_decode($children)) {
23913 return false;
23914 }
23915
23916 $that = $this;
23917
23918
23919  $childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
23920 if ($this->pregMatch($childRegex, $children, $matches)) {
23921 $children = preg_replace_callback($childRegex, function ($matches) use ($name, $subName, $value, $that) {
23922 if ($subName !== null) {
23923 $curVal = json_decode($matches['content'], true);
23924 if (!is_array($curVal)) {
23925 $curVal = array();
23926 }
23927 $curVal[$subName] = $value;
23928 $value = $curVal;
23929 }
23930
23931 return $matches['start'] . $that->format($value, 1) . $matches['end'];
23932 }, $children);
23933 } else {
23934 $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
23935
23936 $whitespace = '';
23937 if (!empty($match['trailingspace'])) {
23938 $whitespace = $match['trailingspace'];
23939 }
23940
23941 if (!empty($match['content'])) {
23942 if ($subName !== null) {
23943 $value = array($subName => $value);
23944 }
23945
23946
23947  $children = preg_replace(
23948 '#'.$whitespace.'}$#',
23949 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}', '\\$'),
23950 $children
23951 );
23952 } else {
23953 if ($subName !== null) {
23954 $value = array($subName => $value);
23955 }
23956
23957
23958  $children = '{' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}';
23959 }
23960 }
23961
23962 $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) {
23963 return $m['start'] . $children . $m['end'];
23964 }, $this->contents);
23965
23966 return true;
23967 }
23968
23969 public function removeSubNode($mainNode, $name)
23970 {
23971 $decoded = JsonFile::parseJson($this->contents);
23972
23973
23974  if (empty($decoded[$mainNode])) {
23975 return true;
23976 }
23977
23978
23979  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
23980 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
23981 try {
23982 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
23983 return false;
23984 }
23985 } catch (\RuntimeException $e) {
23986 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
23987 return false;
23988 }
23989 throw $e;
23990 }
23991
23992 $children = $match['content'];
23993
23994
23995  if (!@json_decode($children, true)) {
23996 return false;
23997 }
23998
23999 $subName = null;
24000 if (in_array($mainNode, array('config', 'extra')) && false !== strpos($name, '.')) {
24001 list($name, $subName) = explode('.', $name, 2);
24002 }
24003
24004
24005  if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
24006 return true;
24007 }
24008
24009
24010  if ($this->pregMatch('{"'.preg_quote($name).'"\s*:}i', $children)) {
24011
24012  if (preg_match_all('{'.self::$DEFINES.'"'.preg_quote($name).'"\s*:\s*(?:(?&json))}x', $children, $matches)) {
24013 $bestMatch = '';
24014 foreach ($matches[0] as $match) {
24015 if (strlen($bestMatch) < strlen($match)) {
24016 $bestMatch = $match;
24017 }
24018 }
24019 $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count);
24020 if (1 !== $count) {
24021 $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count);
24022 if (1 !== $count) {
24023 return false;
24024 }
24025 }
24026 }
24027 } else {
24028 $childrenClean = $children;
24029 }
24030
24031
24032  $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $childrenClean, $match);
24033 if (empty($match['content'])) {
24034 $newline = $this->newline;
24035 $indent = $this->indent;
24036
24037 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($indent, $newline) {
24038 return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
24039 }, $this->contents);
24040
24041
24042  if ($subName !== null) {
24043 $curVal = json_decode($children, true);
24044 unset($curVal[$name][$subName]);
24045 $this->addSubNode($mainNode, $name, $curVal[$name]);
24046 }
24047
24048 return true;
24049 }
24050
24051 $that = $this;
24052 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
24053 if ($subName !== null) {
24054 $curVal = json_decode($matches['content'], true);
24055 unset($curVal[$name][$subName]);
24056 $childrenClean = $that->format($curVal, 0);
24057 }
24058
24059 return $matches['start'] . $childrenClean . $matches['end'];
24060 }, $this->contents);
24061
24062 return true;
24063 }
24064
24065 public function addMainKey($key, $content)
24066 {
24067 $decoded = JsonFile::parseJson($this->contents);
24068 $content = $this->format($content);
24069
24070
24071  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24072 '(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}sx';
24073 if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
24074
24075  if (!@json_decode('{'.$matches['key'].'}')) {
24076 return false;
24077 }
24078
24079 $this->contents = $matches['start'] . JsonFile::encode($key).': '.$content . $matches['end'];
24080
24081 return true;
24082 }
24083
24084
24085  if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
24086 $this->contents = preg_replace(
24087 '#'.$match[1].'\}$#',
24088 addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'),
24089 $this->contents
24090 );
24091
24092 return true;
24093 }
24094
24095
24096  $this->contents = preg_replace(
24097 '#\}$#',
24098 addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'),
24099 $this->contents
24100 );
24101
24102 return true;
24103 }
24104
24105 public function removeMainKey($key)
24106 {
24107 $decoded = JsonFile::parseJson($this->contents);
24108
24109 if (!isset($decoded[$key])) {
24110 return true;
24111 }
24112
24113
24114  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24115 '(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
24116 if ($this->pregMatch($regex, $this->contents, $matches)) {
24117
24118  if (!@json_decode('{'.$matches['removal'].'}')) {
24119 return false;
24120 }
24121
24122 $this->contents = $matches['start'] . $matches['end'];
24123 if (preg_match('#^\{\s*\}\s*$#', $this->contents)) {
24124 $this->contents = "{\n}";
24125 }
24126
24127 return true;
24128 }
24129
24130 return false;
24131 }
24132
24133 public function format($data, $depth = 0)
24134 {
24135 if (is_array($data)) {
24136 reset($data);
24137
24138 if (is_numeric(key($data))) {
24139 foreach ($data as $key => $val) {
24140 $data[$key] = $this->format($val, $depth + 1);
24141 }
24142
24143 return '['.implode(', ', $data).']';
24144 }
24145
24146 $out = '{' . $this->newline;
24147 $elems = array();
24148 foreach ($data as $key => $val) {
24149 $elems[] = str_repeat($this->indent, $depth + 2) . JsonFile::encode($key). ': '.$this->format($val, $depth + 1);
24150 }
24151
24152 return $out . implode(','.$this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
24153 }
24154
24155 return JsonFile::encode($data);
24156 }
24157
24158 protected function detectIndenting()
24159 {
24160 if ($this->pregMatch('{^([ \t]+)"}m', $this->contents, $match)) {
24161 $this->indent = $match[1];
24162 } else {
24163 $this->indent = '    ';
24164 }
24165 }
24166
24167 protected function pregMatch($re, $str, &$matches = array())
24168 {
24169 $count = preg_match($re, $str, $matches);
24170
24171 if ($count === false) {
24172 switch (preg_last_error()) {
24173 case PREG_NO_ERROR:
24174 throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR);
24175 case PREG_INTERNAL_ERROR:
24176 throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR);
24177 case PREG_BACKTRACK_LIMIT_ERROR:
24178 throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR);
24179 case PREG_RECURSION_LIMIT_ERROR:
24180 throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR);
24181 case PREG_BAD_UTF8_ERROR:
24182 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR);
24183 case PREG_BAD_UTF8_OFFSET_ERROR:
24184 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR);
24185 case 6: 
24186  if (PHP_VERSION_ID > 70000) {
24187 throw new \RuntimeException('Failed to execute regex: PREG_JIT_STACKLIMIT_ERROR', 6);
24188 }
24189
24190
24191 default:
24192 throw new \RuntimeException('Failed to execute regex: Unknown error');
24193 }
24194 }
24195
24196 return $count;
24197 }
24198 }
24199 <?php
24200
24201
24202
24203
24204
24205
24206
24207
24208
24209
24210
24211 namespace Composer\Json;
24212
24213 use Exception;
24214
24215
24216
24217
24218 class JsonValidationException extends Exception
24219 {
24220 protected $errors;
24221
24222 public function __construct($message, $errors = array(), Exception $previous = null)
24223 {
24224 $this->errors = $errors;
24225 parent::__construct($message, 0, $previous);
24226 }
24227
24228 public function getErrors()
24229 {
24230 return $this->errors;
24231 }
24232 }
24233 <?php
24234
24235
24236
24237
24238
24239
24240
24241
24242
24243
24244
24245 namespace Composer\Package;
24246
24247 use Composer\Semver\Constraint\Constraint;
24248 use Composer\Package\Version\VersionParser;
24249
24250
24251
24252
24253 class AliasPackage extends BasePackage implements CompletePackageInterface
24254 {
24255 protected $version;
24256 protected $prettyVersion;
24257 protected $dev;
24258 protected $rootPackageAlias = false;
24259 protected $stability;
24260
24261
24262 protected $aliasOf;
24263
24264 protected $requires;
24265
24266 protected $devRequires;
24267
24268 protected $conflicts;
24269
24270 protected $provides;
24271
24272 protected $replaces;
24273
24274
24275
24276
24277
24278
24279
24280
24281 public function __construct(PackageInterface $aliasOf, $version, $prettyVersion)
24282 {
24283 parent::__construct($aliasOf->getName());
24284
24285 $this->version = $version;
24286 $this->prettyVersion = $prettyVersion;
24287 $this->aliasOf = $aliasOf;
24288 $this->stability = VersionParser::parseStability($version);
24289 $this->dev = $this->stability === 'dev';
24290
24291 foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) {
24292 $links = $aliasOf->{'get' . ucfirst($type)}();
24293 $this->$type = $this->replaceSelfVersionDependencies($links, $type);
24294 }
24295 }
24296
24297
24298
24299
24300 public function getAliasOf()
24301 {
24302 return $this->aliasOf;
24303 }
24304
24305
24306
24307
24308 public function getVersion()
24309 {
24310 return $this->version;
24311 }
24312
24313
24314
24315
24316 public function getStability()
24317 {
24318 return $this->stability;
24319 }
24320
24321
24322
24323
24324 public function getPrettyVersion()
24325 {
24326 return $this->prettyVersion;
24327 }
24328
24329
24330
24331
24332 public function isDev()
24333 {
24334 return $this->dev;
24335 }
24336
24337
24338
24339
24340 public function getRequires()
24341 {
24342 return $this->requires;
24343 }
24344
24345
24346
24347
24348 public function getConflicts()
24349 {
24350 return $this->conflicts;
24351 }
24352
24353
24354
24355
24356 public function getProvides()
24357 {
24358 return $this->provides;
24359 }
24360
24361
24362
24363
24364 public function getReplaces()
24365 {
24366 return $this->replaces;
24367 }
24368
24369
24370
24371
24372 public function getDevRequires()
24373 {
24374 return $this->devRequires;
24375 }
24376
24377
24378
24379
24380
24381
24382
24383
24384
24385
24386 public function setRootPackageAlias($value)
24387 {
24388 return $this->rootPackageAlias = $value;
24389 }
24390
24391
24392
24393
24394
24395 public function isRootPackageAlias()
24396 {
24397 return $this->rootPackageAlias;
24398 }
24399
24400
24401
24402
24403
24404
24405
24406 protected function replaceSelfVersionDependencies(array $links, $linkType)
24407 {
24408 if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
24409 $newLinks = array();
24410 foreach ($links as $link) {
24411
24412  if ('self.version' === $link->getPrettyConstraint()) {
24413 $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
24414 }
24415 }
24416 $links = array_merge($links, $newLinks);
24417 } else {
24418 foreach ($links as $index => $link) {
24419 if ('self.version' === $link->getPrettyConstraint()) {
24420 $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
24421 }
24422 }
24423 }
24424
24425 return $links;
24426 }
24427
24428
24429
24430
24431
24432 public function getType()
24433 {
24434 return $this->aliasOf->getType();
24435 }
24436
24437 public function getTargetDir()
24438 {
24439 return $this->aliasOf->getTargetDir();
24440 }
24441
24442 public function getExtra()
24443 {
24444 return $this->aliasOf->getExtra();
24445 }
24446
24447 public function setInstallationSource($type)
24448 {
24449 $this->aliasOf->setInstallationSource($type);
24450 }
24451
24452 public function getInstallationSource()
24453 {
24454 return $this->aliasOf->getInstallationSource();
24455 }
24456
24457 public function getSourceType()
24458 {
24459 return $this->aliasOf->getSourceType();
24460 }
24461
24462 public function getSourceUrl()
24463 {
24464 return $this->aliasOf->getSourceUrl();
24465 }
24466
24467 public function getSourceUrls()
24468 {
24469 return $this->aliasOf->getSourceUrls();
24470 }
24471
24472 public function getSourceReference()
24473 {
24474 return $this->aliasOf->getSourceReference();
24475 }
24476
24477 public function setSourceReference($reference)
24478 {
24479 return $this->aliasOf->setSourceReference($reference);
24480 }
24481
24482 public function setSourceMirrors($mirrors)
24483 {
24484 return $this->aliasOf->setSourceMirrors($mirrors);
24485 }
24486
24487 public function getSourceMirrors()
24488 {
24489 return $this->aliasOf->getSourceMirrors();
24490 }
24491
24492 public function getDistType()
24493 {
24494 return $this->aliasOf->getDistType();
24495 }
24496
24497 public function getDistUrl()
24498 {
24499 return $this->aliasOf->getDistUrl();
24500 }
24501
24502 public function getDistUrls()
24503 {
24504 return $this->aliasOf->getDistUrls();
24505 }
24506
24507 public function getDistReference()
24508 {
24509 return $this->aliasOf->getDistReference();
24510 }
24511
24512 public function setDistReference($reference)
24513 {
24514 return $this->aliasOf->setDistReference($reference);
24515 }
24516
24517 public function getDistSha1Checksum()
24518 {
24519 return $this->aliasOf->getDistSha1Checksum();
24520 }
24521
24522 public function setTransportOptions(array $options)
24523 {
24524 return $this->aliasOf->setTransportOptions($options);
24525 }
24526
24527 public function getTransportOptions()
24528 {
24529 return $this->aliasOf->getTransportOptions();
24530 }
24531
24532 public function setDistMirrors($mirrors)
24533 {
24534 return $this->aliasOf->setDistMirrors($mirrors);
24535 }
24536
24537 public function getDistMirrors()
24538 {
24539 return $this->aliasOf->getDistMirrors();
24540 }
24541
24542 public function getScripts()
24543 {
24544 return $this->aliasOf->getScripts();
24545 }
24546
24547 public function getLicense()
24548 {
24549 return $this->aliasOf->getLicense();
24550 }
24551
24552 public function getAutoload()
24553 {
24554 return $this->aliasOf->getAutoload();
24555 }
24556
24557 public function getDevAutoload()
24558 {
24559 return $this->aliasOf->getDevAutoload();
24560 }
24561
24562 public function getIncludePaths()
24563 {
24564 return $this->aliasOf->getIncludePaths();
24565 }
24566
24567 public function getRepositories()
24568 {
24569 return $this->aliasOf->getRepositories();
24570 }
24571
24572 public function getReleaseDate()
24573 {
24574 return $this->aliasOf->getReleaseDate();
24575 }
24576
24577 public function getBinaries()
24578 {
24579 return $this->aliasOf->getBinaries();
24580 }
24581
24582 public function getKeywords()
24583 {
24584 return $this->aliasOf->getKeywords();
24585 }
24586
24587 public function getDescription()
24588 {
24589 return $this->aliasOf->getDescription();
24590 }
24591
24592 public function getHomepage()
24593 {
24594 return $this->aliasOf->getHomepage();
24595 }
24596
24597 public function getSuggests()
24598 {
24599 return $this->aliasOf->getSuggests();
24600 }
24601
24602 public function getAuthors()
24603 {
24604 return $this->aliasOf->getAuthors();
24605 }
24606
24607 public function getSupport()
24608 {
24609 return $this->aliasOf->getSupport();
24610 }
24611
24612 public function getNotificationUrl()
24613 {
24614 return $this->aliasOf->getNotificationUrl();
24615 }
24616
24617 public function getArchiveExcludes()
24618 {
24619 return $this->aliasOf->getArchiveExcludes();
24620 }
24621
24622 public function isAbandoned()
24623 {
24624 return $this->aliasOf->isAbandoned();
24625 }
24626
24627 public function getReplacementPackage()
24628 {
24629 return $this->aliasOf->getReplacementPackage();
24630 }
24631
24632 public function __toString()
24633 {
24634 return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
24635 }
24636 }
24637 <?php
24638
24639
24640
24641
24642
24643
24644
24645
24646
24647
24648
24649 namespace Composer\Package\Archiver;
24650
24651 use FilterIterator;
24652 use PharData;
24653
24654 class ArchivableFilesFilter extends FilterIterator
24655 {
24656 private $dirs = array();
24657
24658
24659
24660
24661 public function accept()
24662 {
24663 $file = $this->getInnerIterator()->current();
24664 if ($file->isDir()) {
24665 $this->dirs[] = (string) $file;
24666
24667 return false;
24668 }
24669
24670 return true;
24671 }
24672
24673 public function addEmptyDir(PharData $phar, $sources)
24674 {
24675 foreach ($this->dirs as $filepath) {
24676 $localname = str_replace($sources . "/", '', $filepath);
24677 $phar->addEmptyDir($localname);
24678 }
24679 }
24680 }
24681 <?php
24682
24683
24684
24685
24686
24687
24688
24689
24690
24691
24692
24693 namespace Composer\Package\Archiver;
24694
24695 use Composer\Util\Filesystem;
24696 use FilesystemIterator;
24697 use Symfony\Component\Finder\Finder;
24698 use Symfony\Component\Finder\SplFileInfo;
24699
24700
24701
24702
24703
24704
24705
24706
24707
24708 class ArchivableFilesFinder extends \FilterIterator
24709 {
24710
24711
24712
24713 protected $finder;
24714
24715
24716
24717
24718
24719
24720
24721
24722 public function __construct($sources, array $excludes, $ignoreFilters = false)
24723 {
24724 $fs = new Filesystem();
24725
24726 $sources = $fs->normalizePath($sources);
24727
24728 if ($ignoreFilters) {
24729 $filters = array();
24730 } else {
24731 $filters = array(
24732 new HgExcludeFilter($sources),
24733 new GitExcludeFilter($sources),
24734 new ComposerExcludeFilter($sources, $excludes),
24735 );
24736 }
24737
24738 $this->finder = new Finder();
24739
24740 $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
24741 if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) {
24742 return false;
24743 }
24744
24745 $relativePath = preg_replace(
24746 '#^'.preg_quote($sources, '#').'#',
24747 '',
24748 $fs->normalizePath($file->getRealPath())
24749 );
24750
24751 $exclude = false;
24752 foreach ($filters as $filter) {
24753 $exclude = $filter->filter($relativePath, $exclude);
24754 }
24755
24756 return !$exclude;
24757 };
24758
24759 if (method_exists($filter, 'bindTo')) {
24760 $filter = $filter->bindTo(null);
24761 }
24762
24763 $this->finder
24764 ->in($sources)
24765 ->filter($filter)
24766 ->ignoreVCS(true)
24767 ->ignoreDotFiles(false);
24768
24769 parent::__construct($this->finder->getIterator());
24770 }
24771
24772 public function accept()
24773 {
24774
24775 $current = $this->getInnerIterator()->current();
24776
24777 if (!$current->isDir()) {
24778 return true;
24779 }
24780
24781 $iterator = new FilesystemIterator($current, FilesystemIterator::SKIP_DOTS);
24782
24783 return !$iterator->valid();
24784 }
24785 }
24786 <?php
24787
24788
24789
24790
24791
24792
24793
24794
24795
24796
24797
24798 namespace Composer\Package\Archiver;
24799
24800 use Composer\Downloader\DownloadManager;
24801 use Composer\Package\PackageInterface;
24802 use Composer\Package\RootPackageInterface;
24803 use Composer\Util\Filesystem;
24804 use Composer\Json\JsonFile;
24805
24806
24807
24808
24809
24810 class ArchiveManager
24811 {
24812 protected $downloadManager;
24813
24814 protected $archivers = array();
24815
24816
24817
24818
24819 protected $overwriteFiles = true;
24820
24821
24822
24823
24824 public function __construct(DownloadManager $downloadManager)
24825 {
24826 $this->downloadManager = $downloadManager;
24827 }
24828
24829
24830
24831
24832 public function addArchiver(ArchiverInterface $archiver)
24833 {
24834 $this->archivers[] = $archiver;
24835 }
24836
24837
24838
24839
24840
24841
24842
24843
24844 public function setOverwriteFiles($overwriteFiles)
24845 {
24846 $this->overwriteFiles = $overwriteFiles;
24847
24848 return $this;
24849 }
24850
24851
24852
24853
24854
24855
24856
24857
24858 public function getPackageFilename(PackageInterface $package)
24859 {
24860 $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
24861
24862 if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
24863 $nameParts = array_merge($nameParts, array($package->getDistReference(), $package->getDistType()));
24864 } else {
24865 $nameParts = array_merge($nameParts, array($package->getPrettyVersion(), $package->getDistReference()));
24866 }
24867
24868 if ($package->getSourceReference()) {
24869 $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
24870 }
24871
24872 $name = implode('-', array_filter($nameParts, function ($p) {
24873 return !empty($p);
24874 }));
24875
24876 return str_replace('/', '-', $name);
24877 }
24878
24879
24880
24881
24882
24883
24884
24885
24886
24887
24888
24889
24890
24891
24892 public function archive(PackageInterface $package, $format, $targetDir, $fileName = null, $ignoreFilters = false)
24893 {
24894 if (empty($format)) {
24895 throw new \InvalidArgumentException('Format must be specified');
24896 }
24897
24898
24899  $usableArchiver = null;
24900 foreach ($this->archivers as $archiver) {
24901 if ($archiver->supports($format, $package->getSourceType())) {
24902 $usableArchiver = $archiver;
24903 break;
24904 }
24905 }
24906
24907
24908  if (null === $usableArchiver) {
24909 throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
24910 }
24911
24912 $filesystem = new Filesystem();
24913 if (null === $fileName) {
24914 $packageName = $this->getPackageFilename($package);
24915 } else {
24916 $packageName = $fileName;
24917 }
24918
24919
24920  $filesystem->ensureDirectoryExists($targetDir);
24921 $target = realpath($targetDir).'/'.$packageName.'.'.$format;
24922 $filesystem->ensureDirectoryExists(dirname($target));
24923
24924 if (!$this->overwriteFiles && file_exists($target)) {
24925 return $target;
24926 }
24927
24928 if ($package instanceof RootPackageInterface) {
24929 $sourcePath = realpath('.');
24930 } else {
24931
24932  $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
24933 $filesystem->ensureDirectoryExists($sourcePath);
24934
24935
24936  $this->downloadManager->download($package, $sourcePath);
24937
24938
24939  if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
24940 $jsonFile = new JsonFile($composerJsonPath);
24941 $jsonData = $jsonFile->read();
24942 if (!empty($jsonData['archive']['exclude'])) {
24943 $package->setArchiveExcludes($jsonData['archive']['exclude']);
24944 }
24945 }
24946 }
24947
24948
24949  $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
24950 $filesystem->ensureDirectoryExists(dirname($tempTarget));
24951
24952 $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes(), $ignoreFilters);
24953 $filesystem->rename($archivePath, $target);
24954
24955
24956  if (!$package instanceof RootPackageInterface) {
24957 $filesystem->removeDirectory($sourcePath);
24958 }
24959 $filesystem->remove($tempTarget);
24960
24961 return $target;
24962 }
24963 }
24964 <?php
24965
24966
24967
24968
24969
24970
24971
24972
24973
24974
24975
24976 namespace Composer\Package\Archiver;
24977
24978
24979
24980
24981
24982
24983 interface ArchiverInterface
24984 {
24985
24986
24987
24988
24989
24990
24991
24992
24993
24994
24995 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false);
24996
24997
24998
24999
25000
25001
25002
25003
25004
25005 public function supports($format, $sourceType);
25006 }
25007 <?php
25008
25009
25010
25011
25012
25013
25014
25015
25016
25017
25018
25019 namespace Composer\Package\Archiver;
25020
25021 use Symfony\Component\Finder;
25022
25023
25024
25025
25026 abstract class BaseExcludeFilter
25027 {
25028
25029
25030
25031 protected $sourcePath;
25032
25033
25034
25035
25036 protected $excludePatterns;
25037
25038
25039
25040
25041 public function __construct($sourcePath)
25042 {
25043 $this->sourcePath = $sourcePath;
25044 $this->excludePatterns = array();
25045 }
25046
25047
25048
25049
25050
25051
25052
25053
25054
25055
25056
25057 public function filter($relativePath, $exclude)
25058 {
25059 foreach ($this->excludePatterns as $patternData) {
25060 list($pattern, $negate, $stripLeadingSlash) = $patternData;
25061
25062 if ($stripLeadingSlash) {
25063 $path = substr($relativePath, 1);
25064 } else {
25065 $path = $relativePath;
25066 }
25067
25068 if (preg_match($pattern, $path)) {
25069 $exclude = !$negate;
25070 }
25071 }
25072
25073 return $exclude;
25074 }
25075
25076
25077
25078
25079
25080
25081
25082
25083
25084 protected function parseLines(array $lines, $lineParser)
25085 {
25086 return array_filter(
25087 array_map(
25088 function ($line) use ($lineParser) {
25089 $line = trim($line);
25090
25091 if (!$line || 0 === strpos($line, '#')) {
25092 return null;
25093 }
25094
25095 return call_user_func($lineParser, $line);
25096 },
25097 $lines
25098 ),
25099 function ($pattern) {
25100 return $pattern !== null;
25101 }
25102 );
25103 }
25104
25105
25106
25107
25108
25109
25110
25111
25112 protected function generatePatterns($rules)
25113 {
25114 $patterns = array();
25115 foreach ($rules as $rule) {
25116 $patterns[] = $this->generatePattern($rule);
25117 }
25118
25119 return $patterns;
25120 }
25121
25122
25123
25124
25125
25126
25127
25128
25129 protected function generatePattern($rule)
25130 {
25131 $negate = false;
25132 $pattern = '{';
25133
25134 if (strlen($rule) && $rule[0] === '!') {
25135 $negate = true;
25136 $rule = substr($rule, 1);
25137 }
25138
25139 if (strlen($rule) && $rule[0] === '/') {
25140 $pattern .= '^/';
25141 $rule = substr($rule, 1);
25142 } elseif (strlen($rule) - 1 === strpos($rule, '/')) {
25143 $pattern .= '/';
25144 $rule = substr($rule, 0, -1);
25145 } elseif (false === strpos($rule, '/')) {
25146 $pattern .= '/';
25147 }
25148
25149
25150  $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
25151
25152 return array($pattern . '}', $negate, false);
25153 }
25154 }
25155 <?php
25156
25157
25158
25159
25160
25161
25162
25163
25164
25165
25166
25167 namespace Composer\Package\Archiver;
25168
25169
25170
25171
25172
25173
25174 class ComposerExcludeFilter extends BaseExcludeFilter
25175 {
25176
25177
25178
25179
25180 public function __construct($sourcePath, array $excludeRules)
25181 {
25182 parent::__construct($sourcePath);
25183 $this->excludePatterns = $this->generatePatterns($excludeRules);
25184 }
25185 }
25186 <?php
25187
25188
25189
25190
25191
25192
25193
25194
25195
25196
25197
25198 namespace Composer\Package\Archiver;
25199
25200
25201
25202
25203
25204
25205
25206
25207 class GitExcludeFilter extends BaseExcludeFilter
25208 {
25209
25210
25211
25212
25213
25214 public function __construct($sourcePath)
25215 {
25216 parent::__construct($sourcePath);
25217
25218 if (file_exists($sourcePath.'/.gitignore')) {
25219 $this->excludePatterns = $this->parseLines(
25220 file($sourcePath.'/.gitignore'),
25221 array($this, 'parseGitIgnoreLine')
25222 );
25223 }
25224 if (file_exists($sourcePath.'/.gitattributes')) {
25225 $this->excludePatterns = array_merge(
25226 $this->excludePatterns,
25227 $this->parseLines(
25228 file($sourcePath.'/.gitattributes'),
25229 array($this, 'parseGitAttributesLine')
25230 ));
25231 }
25232 }
25233
25234
25235
25236
25237
25238
25239
25240
25241 public function parseGitIgnoreLine($line)
25242 {
25243 return $this->generatePattern($line);
25244 }
25245
25246
25247
25248
25249
25250
25251
25252
25253 public function parseGitAttributesLine($line)
25254 {
25255 $parts = preg_split('#\s+#', $line);
25256
25257 if (count($parts) == 2 && $parts[1] === 'export-ignore') {
25258 return $this->generatePattern($parts[0]);
25259 }
25260
25261 return null;
25262 }
25263 }
25264 <?php
25265
25266
25267
25268
25269
25270
25271
25272
25273
25274
25275
25276 namespace Composer\Package\Archiver;
25277
25278 use Symfony\Component\Finder;
25279
25280
25281
25282
25283
25284
25285 class HgExcludeFilter extends BaseExcludeFilter
25286 {
25287 const HG_IGNORE_REGEX = 1;
25288 const HG_IGNORE_GLOB = 2;
25289
25290
25291
25292
25293
25294 protected $patternMode;
25295
25296
25297
25298
25299
25300
25301 public function __construct($sourcePath)
25302 {
25303 parent::__construct($sourcePath);
25304
25305 $this->patternMode = self::HG_IGNORE_REGEX;
25306
25307 if (file_exists($sourcePath.'/.hgignore')) {
25308 $this->excludePatterns = $this->parseLines(
25309 file($sourcePath.'/.hgignore'),
25310 array($this, 'parseHgIgnoreLine')
25311 );
25312 }
25313 }
25314
25315
25316
25317
25318
25319
25320
25321
25322 public function parseHgIgnoreLine($line)
25323 {
25324 if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) {
25325 if ($matches[1] === 'glob') {
25326 $this->patternMode = self::HG_IGNORE_GLOB;
25327 } else {
25328 $this->patternMode = self::HG_IGNORE_REGEX;
25329 }
25330
25331 return null;
25332 }
25333
25334 if ($this->patternMode == self::HG_IGNORE_GLOB) {
25335 return $this->patternFromGlob($line);
25336 } else {
25337 return $this->patternFromRegex($line);
25338 }
25339 }
25340
25341
25342
25343
25344
25345
25346
25347
25348 protected function patternFromGlob($line)
25349 {
25350 $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#';
25351 $pattern = str_replace('[^/]*', '.*', $pattern);
25352
25353 return array($pattern, false, true);
25354 }
25355
25356
25357
25358
25359
25360
25361
25362
25363 public function patternFromRegex($line)
25364 {
25365
25366  $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#';
25367
25368 return array($pattern, false, true);
25369 }
25370 }
25371 <?php
25372
25373
25374
25375
25376
25377
25378
25379
25380
25381
25382
25383 namespace Composer\Package\Archiver;
25384
25385
25386
25387
25388
25389
25390 class PharArchiver implements ArchiverInterface
25391 {
25392 protected static $formats = array(
25393 'zip' => \Phar::ZIP,
25394 'tar' => \Phar::TAR,
25395 'tar.gz' => \Phar::TAR,
25396 'tar.bz2' => \Phar::TAR,
25397 );
25398
25399 protected static $compressFormats = array(
25400 'tar.gz' => \Phar::GZ,
25401 'tar.bz2' => \Phar::BZ2,
25402 );
25403
25404
25405
25406
25407 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
25408 {
25409 $sources = realpath($sources);
25410
25411
25412  if (file_exists($target)) {
25413 unlink($target);
25414 }
25415
25416 try {
25417 $filename = substr($target, 0, strrpos($target, $format) - 1);
25418
25419
25420  if (isset(static::$compressFormats[$format])) {
25421
25422  $target = $filename . '.tar';
25423 }
25424
25425 $phar = new \PharData($target, null, null, static::$formats[$format]);
25426 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
25427 $filesOnly = new ArchivableFilesFilter($files);
25428 $phar->buildFromIterator($filesOnly, $sources);
25429 $filesOnly->addEmptyDir($phar, $sources);
25430
25431 if (isset(static::$compressFormats[$format])) {
25432
25433  if (!$phar->canCompress(static::$compressFormats[$format])) {
25434 throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
25435 }
25436
25437
25438  unlink($target);
25439
25440
25441  $phar->compress(static::$compressFormats[$format]);
25442
25443
25444  $target = $filename . '.' . $format;
25445 }
25446
25447 return $target;
25448 } catch (\UnexpectedValueException $e) {
25449 $message = sprintf("Could not create archive '%s' from '%s': %s",
25450 $target,
25451 $sources,
25452 $e->getMessage()
25453 );
25454
25455 throw new \RuntimeException($message, $e->getCode(), $e);
25456 }
25457 }
25458
25459
25460
25461
25462 public function supports($format, $sourceType)
25463 {
25464 return isset(static::$formats[$format]);
25465 }
25466 }
25467 <?php
25468
25469
25470
25471
25472
25473
25474
25475
25476
25477
25478
25479 namespace Composer\Package\Archiver;
25480
25481 use ZipArchive;
25482 use Composer\Util\Filesystem;
25483
25484
25485
25486
25487 class ZipArchiver implements ArchiverInterface
25488 {
25489 protected static $formats = array(
25490 'zip' => 1,
25491 );
25492
25493
25494
25495
25496 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
25497 {
25498 $fs = new Filesystem();
25499 $sources = $fs->normalizePath($sources);
25500
25501 $zip = new ZipArchive();
25502 $res = $zip->open($target, ZipArchive::CREATE);
25503 if ($res === true) {
25504 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
25505 foreach ($files as $file) {
25506
25507 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
25508 $localname = str_replace($sources.'/', '', $filepath);
25509 if ($file->isDir()) {
25510 $zip->addEmptyDir($localname);
25511 } else {
25512 $zip->addFile($filepath, $localname);
25513 }
25514 }
25515 if ($zip->close()) {
25516 return $target;
25517 }
25518 }
25519 $message = sprintf("Could not create archive '%s' from '%s': %s",
25520 $target,
25521 $sources,
25522 $zip->getStatusString()
25523 );
25524 throw new \RuntimeException($message);
25525 }
25526
25527
25528
25529
25530 public function supports($format, $sourceType)
25531 {
25532 return isset(static::$formats[$format]) && $this->compressionAvailable();
25533 }
25534
25535 private function compressionAvailable()
25536 {
25537 return class_exists('ZipArchive');
25538 }
25539 }
25540 <?php
25541
25542
25543
25544
25545
25546
25547
25548
25549
25550
25551
25552 namespace Composer\Package;
25553
25554 use Composer\Repository\RepositoryInterface;
25555 use Composer\Repository\PlatformRepository;
25556
25557
25558
25559
25560
25561
25562 abstract class BasePackage implements PackageInterface
25563 {
25564 public static $supportedLinkTypes = array(
25565 'require' => array('description' => 'requires', 'method' => 'requires'),
25566 'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
25567 'provide' => array('description' => 'provides', 'method' => 'provides'),
25568 'replace' => array('description' => 'replaces', 'method' => 'replaces'),
25569 'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
25570 );
25571
25572 const STABILITY_STABLE = 0;
25573 const STABILITY_RC = 5;
25574 const STABILITY_BETA = 10;
25575 const STABILITY_ALPHA = 15;
25576 const STABILITY_DEV = 20;
25577
25578 public static $stabilities = array(
25579 'stable' => self::STABILITY_STABLE,
25580 'RC' => self::STABILITY_RC,
25581 'beta' => self::STABILITY_BETA,
25582 'alpha' => self::STABILITY_ALPHA,
25583 'dev' => self::STABILITY_DEV,
25584 );
25585
25586
25587
25588
25589
25590 public $id;
25591
25592 protected $name;
25593
25594 protected $prettyName;
25595
25596 protected $repository;
25597
25598 protected $transportOptions = array();
25599
25600
25601
25602
25603
25604
25605 public function __construct($name)
25606 {
25607 $this->prettyName = $name;
25608 $this->name = strtolower($name);
25609 $this->id = -1;
25610 }
25611
25612
25613
25614
25615 public function getName()
25616 {
25617 return $this->name;
25618 }
25619
25620
25621
25622
25623 public function getPrettyName()
25624 {
25625 return $this->prettyName;
25626 }
25627
25628
25629
25630
25631 public function getNames()
25632 {
25633 $names = array(
25634 $this->getName() => true,
25635 );
25636
25637 foreach ($this->getProvides() as $link) {
25638 $names[$link->getTarget()] = true;
25639 }
25640
25641 foreach ($this->getReplaces() as $link) {
25642 $names[$link->getTarget()] = true;
25643 }
25644
25645 return array_keys($names);
25646 }
25647
25648
25649
25650
25651 public function setId($id)
25652 {
25653 $this->id = $id;
25654 }
25655
25656
25657
25658
25659 public function getId()
25660 {
25661 return $this->id;
25662 }
25663
25664
25665
25666
25667 public function setRepository(RepositoryInterface $repository)
25668 {
25669 if ($this->repository && $repository !== $this->repository) {
25670 throw new \LogicException('A package can only be added to one repository');
25671 }
25672 $this->repository = $repository;
25673 }
25674
25675
25676
25677
25678 public function getRepository()
25679 {
25680 return $this->repository;
25681 }
25682
25683
25684
25685
25686 public function getTransportOptions()
25687 {
25688 return $this->transportOptions;
25689 }
25690
25691
25692
25693
25694
25695
25696 public function setTransportOptions(array $options)
25697 {
25698 $this->transportOptions = $options;
25699 }
25700
25701
25702
25703
25704
25705
25706 public function isPlatform()
25707 {
25708 return $this->getRepository() instanceof PlatformRepository;
25709 }
25710
25711
25712
25713
25714
25715
25716 public function getUniqueName()
25717 {
25718 return $this->getName().'-'.$this->getVersion();
25719 }
25720
25721 public function equals(PackageInterface $package)
25722 {
25723 $self = $this;
25724 if ($this instanceof AliasPackage) {
25725 $self = $this->getAliasOf();
25726 }
25727 if ($package instanceof AliasPackage) {
25728 $package = $package->getAliasOf();
25729 }
25730
25731 return $package === $self;
25732 }
25733
25734
25735
25736
25737
25738
25739 public function __toString()
25740 {
25741 return $this->getUniqueName();
25742 }
25743
25744 public function getPrettyString()
25745 {
25746 return $this->getPrettyName().' '.$this->getPrettyVersion();
25747 }
25748
25749
25750
25751
25752 public function getFullPrettyVersion($truncate = true)
25753 {
25754 if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
25755 return $this->getPrettyVersion();
25756 }
25757
25758
25759  if ($truncate && strlen($this->getSourceReference()) === 40) {
25760 return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
25761 }
25762
25763 return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
25764 }
25765
25766 public function getStabilityPriority()
25767 {
25768 return self::$stabilities[$this->getStability()];
25769 }
25770
25771 public function __clone()
25772 {
25773 $this->repository = null;
25774 $this->id = -1;
25775 }
25776 }
25777 <?php
25778
25779
25780
25781
25782
25783
25784
25785
25786
25787
25788
25789 namespace Composer\Package;
25790
25791
25792
25793
25794
25795
25796 class CompletePackage extends Package implements CompletePackageInterface
25797 {
25798 protected $repositories;
25799 protected $license = array();
25800 protected $keywords;
25801 protected $authors;
25802 protected $description;
25803 protected $homepage;
25804 protected $scripts = array();
25805 protected $support = array();
25806 protected $abandoned = false;
25807
25808
25809
25810
25811 public function setScripts(array $scripts)
25812 {
25813 $this->scripts = $scripts;
25814 }
25815
25816
25817
25818
25819 public function getScripts()
25820 {
25821 return $this->scripts;
25822 }
25823
25824
25825
25826
25827
25828
25829 public function setRepositories($repositories)
25830 {
25831 $this->repositories = $repositories;
25832 }
25833
25834
25835
25836
25837 public function getRepositories()
25838 {
25839 return $this->repositories;
25840 }
25841
25842
25843
25844
25845
25846
25847 public function setLicense(array $license)
25848 {
25849 $this->license = $license;
25850 }
25851
25852
25853
25854
25855 public function getLicense()
25856 {
25857 return $this->license;
25858 }
25859
25860
25861
25862
25863
25864
25865 public function setKeywords(array $keywords)
25866 {
25867 $this->keywords = $keywords;
25868 }
25869
25870
25871
25872
25873 public function getKeywords()
25874 {
25875 return $this->keywords;
25876 }
25877
25878
25879
25880
25881
25882
25883 public function setAuthors(array $authors)
25884 {
25885 $this->authors = $authors;
25886 }
25887
25888
25889
25890
25891 public function getAuthors()
25892 {
25893 return $this->authors;
25894 }
25895
25896
25897
25898
25899
25900
25901 public function setDescription($description)
25902 {
25903 $this->description = $description;
25904 }
25905
25906
25907
25908
25909 public function getDescription()
25910 {
25911 return $this->description;
25912 }
25913
25914
25915
25916
25917
25918
25919 public function setHomepage($homepage)
25920 {
25921 $this->homepage = $homepage;
25922 }
25923
25924
25925
25926
25927 public function getHomepage()
25928 {
25929 return $this->homepage;
25930 }
25931
25932
25933
25934
25935
25936
25937 public function setSupport(array $support)
25938 {
25939 $this->support = $support;
25940 }
25941
25942
25943
25944
25945 public function getSupport()
25946 {
25947 return $this->support;
25948 }
25949
25950
25951
25952
25953 public function isAbandoned()
25954 {
25955 return (bool) $this->abandoned;
25956 }
25957
25958
25959
25960
25961 public function setAbandoned($abandoned)
25962 {
25963 $this->abandoned = $abandoned;
25964 }
25965
25966
25967
25968
25969
25970
25971 public function getReplacementPackage()
25972 {
25973 return is_string($this->abandoned) ? $this->abandoned : null;
25974 }
25975 }
25976 <?php
25977
25978
25979
25980
25981
25982
25983
25984
25985
25986
25987
25988 namespace Composer\Package;
25989
25990
25991
25992
25993
25994
25995 interface CompletePackageInterface extends PackageInterface
25996 {
25997
25998
25999
26000
26001
26002 public function getScripts();
26003
26004
26005
26006
26007
26008
26009
26010
26011 public function getRepositories();
26012
26013
26014
26015
26016
26017
26018 public function getLicense();
26019
26020
26021
26022
26023
26024
26025 public function getKeywords();
26026
26027
26028
26029
26030
26031
26032 public function getDescription();
26033
26034
26035
26036
26037
26038
26039 public function getHomepage();
26040
26041
26042
26043
26044
26045
26046
26047
26048 public function getAuthors();
26049
26050
26051
26052
26053
26054
26055 public function getSupport();
26056
26057
26058
26059
26060
26061
26062 public function isAbandoned();
26063
26064
26065
26066
26067
26068
26069 public function getReplacementPackage();
26070 }
26071 <?php
26072
26073
26074
26075
26076
26077
26078
26079
26080
26081
26082
26083 namespace Composer\Package\Dumper;
26084
26085 use Composer\Package\BasePackage;
26086 use Composer\Package\PackageInterface;
26087 use Composer\Package\CompletePackageInterface;
26088 use Composer\Package\RootPackageInterface;
26089
26090
26091
26092
26093
26094 class ArrayDumper
26095 {
26096 public function dump(PackageInterface $package)
26097 {
26098 $keys = array(
26099 'binaries' => 'bin',
26100 'type',
26101 'extra',
26102 'installationSource' => 'installation-source',
26103 'autoload',
26104 'devAutoload' => 'autoload-dev',
26105 'notificationUrl' => 'notification-url',
26106 'includePaths' => 'include-path',
26107 );
26108
26109 $data = array();
26110 $data['name'] = $package->getPrettyName();
26111 $data['version'] = $package->getPrettyVersion();
26112 $data['version_normalized'] = $package->getVersion();
26113
26114 if ($package->getTargetDir()) {
26115 $data['target-dir'] = $package->getTargetDir();
26116 }
26117
26118 if ($package->getSourceType()) {
26119 $data['source']['type'] = $package->getSourceType();
26120 $data['source']['url'] = $package->getSourceUrl();
26121 $data['source']['reference'] = $package->getSourceReference();
26122 if ($mirrors = $package->getSourceMirrors()) {
26123 $data['source']['mirrors'] = $mirrors;
26124 }
26125 }
26126
26127 if ($package->getDistType()) {
26128 $data['dist']['type'] = $package->getDistType();
26129 $data['dist']['url'] = $package->getDistUrl();
26130 $data['dist']['reference'] = $package->getDistReference();
26131 $data['dist']['shasum'] = $package->getDistSha1Checksum();
26132 if ($mirrors = $package->getDistMirrors()) {
26133 $data['dist']['mirrors'] = $mirrors;
26134 }
26135 }
26136
26137 if ($package->getArchiveExcludes()) {
26138 $data['archive']['exclude'] = $package->getArchiveExcludes();
26139 }
26140
26141 foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
26142 if ($links = $package->{'get'.ucfirst($opts['method'])}()) {
26143 foreach ($links as $link) {
26144 $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
26145 }
26146 ksort($data[$type]);
26147 }
26148 }
26149
26150 if ($packages = $package->getSuggests()) {
26151 ksort($packages);
26152 $data['suggest'] = $packages;
26153 }
26154
26155 if ($package->getReleaseDate()) {
26156 $data['time'] = $package->getReleaseDate()->format(DATE_RFC3339);
26157 }
26158
26159 $data = $this->dumpValues($package, $keys, $data);
26160
26161 if ($package instanceof CompletePackageInterface) {
26162 $keys = array(
26163 'scripts',
26164 'license',
26165 'authors',
26166 'description',
26167 'homepage',
26168 'keywords',
26169 'repositories',
26170 'support',
26171 );
26172
26173 $data = $this->dumpValues($package, $keys, $data);
26174
26175 if (isset($data['keywords']) && is_array($data['keywords'])) {
26176 sort($data['keywords']);
26177 }
26178
26179 if ($package->isAbandoned()) {
26180 $data['abandoned'] = $package->getReplacementPackage() ?: true;
26181 }
26182 }
26183
26184 if ($package instanceof RootPackageInterface) {
26185 $minimumStability = $package->getMinimumStability();
26186 if ($minimumStability) {
26187 $data['minimum-stability'] = $minimumStability;
26188 }
26189 }
26190
26191 if (count($package->getTransportOptions()) > 0) {
26192 $data['transport-options'] = $package->getTransportOptions();
26193 }
26194
26195 return $data;
26196 }
26197
26198 private function dumpValues(PackageInterface $package, array $keys, array $data)
26199 {
26200 foreach ($keys as $method => $key) {
26201 if (is_numeric($method)) {
26202 $method = $key;
26203 }
26204
26205 $getter = 'get'.ucfirst($method);
26206 $value = $package->$getter();
26207
26208 if (null !== $value && !(is_array($value) && 0 === count($value))) {
26209 $data[$key] = $value;
26210 }
26211 }
26212
26213 return $data;
26214 }
26215 }
26216 <?php
26217
26218
26219
26220
26221
26222
26223
26224
26225
26226
26227
26228 namespace Composer\Package;
26229
26230 use Composer\Semver\Constraint\ConstraintInterface;
26231
26232
26233
26234
26235
26236
26237 class Link
26238 {
26239
26240
26241
26242 protected $source;
26243
26244
26245
26246
26247 protected $target;
26248
26249
26250
26251
26252 protected $constraint;
26253
26254
26255
26256
26257 protected $description;
26258
26259
26260
26261
26262 protected $prettyConstraint;
26263
26264
26265
26266
26267
26268
26269
26270
26271
26272
26273 public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
26274 {
26275 $this->source = strtolower($source);
26276 $this->target = strtolower($target);
26277 $this->constraint = $constraint;
26278 $this->description = $description;
26279 $this->prettyConstraint = $prettyConstraint;
26280 }
26281
26282
26283
26284
26285 public function getDescription()
26286 {
26287 return $this->description;
26288 }
26289
26290
26291
26292
26293 public function getSource()
26294 {
26295 return $this->source;
26296 }
26297
26298
26299
26300
26301 public function getTarget()
26302 {
26303 return $this->target;
26304 }
26305
26306
26307
26308
26309 public function getConstraint()
26310 {
26311 return $this->constraint;
26312 }
26313
26314
26315
26316
26317
26318 public function getPrettyConstraint()
26319 {
26320 if (null === $this->prettyConstraint) {
26321 throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
26322 }
26323
26324 return $this->prettyConstraint;
26325 }
26326
26327
26328
26329
26330 public function __toString()
26331 {
26332 return $this->source.' '.$this->description.' '.$this->target.' ('.$this->constraint.')';
26333 }
26334
26335
26336
26337
26338
26339 public function getPrettyString(PackageInterface $sourcePackage)
26340 {
26341 return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
26342 }
26343 }
26344 <?php
26345
26346
26347
26348
26349
26350
26351
26352
26353
26354
26355
26356 namespace Composer\Package\LinkConstraint;
26357
26358 use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint;
26359
26360 trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
26361
26362
26363
26364
26365 class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
26366 {
26367 }
26368 <?php
26369
26370
26371
26372
26373
26374
26375
26376
26377
26378
26379
26380 namespace Composer\Package\LinkConstraint;
26381
26382 use Composer\Semver\Constraint\ConstraintInterface;
26383
26384 trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
26385
26386
26387
26388
26389 interface LinkConstraintInterface extends ConstraintInterface
26390 {
26391 }
26392 <?php
26393
26394
26395
26396
26397
26398
26399
26400
26401
26402
26403
26404 namespace Composer\Package\LinkConstraint;
26405
26406 use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint;
26407
26408 trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
26409
26410
26411
26412
26413 class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface
26414 {
26415 }
26416 <?php
26417
26418
26419
26420
26421
26422
26423
26424
26425
26426
26427
26428 namespace Composer\Package\LinkConstraint;
26429
26430 use Composer\Semver\Constraint\AbstractConstraint;
26431
26432 trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, there is no replacement for it.', E_USER_DEPRECATED);
26433
26434
26435
26436
26437 abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
26438 {
26439 }
26440 <?php
26441
26442
26443
26444
26445
26446
26447
26448
26449
26450
26451
26452 namespace Composer\Package\LinkConstraint;
26453
26454 use Composer\Semver\Constraint\Constraint;
26455
26456 trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
26457
26458
26459
26460
26461 class VersionConstraint extends Constraint implements LinkConstraintInterface
26462 {
26463 }
26464 <?php
26465
26466
26467
26468
26469
26470
26471
26472
26473
26474
26475
26476 namespace Composer\Package\Loader;
26477
26478 use Composer\Package;
26479 use Composer\Package\AliasPackage;
26480 use Composer\Package\Link;
26481 use Composer\Package\RootAliasPackage;
26482 use Composer\Package\RootPackageInterface;
26483 use Composer\Package\Version\VersionParser;
26484 use Composer\Semver\VersionParser as SemverVersionParser;
26485
26486
26487
26488
26489
26490 class ArrayLoader implements LoaderInterface
26491 {
26492 protected $versionParser;
26493 protected $loadOptions;
26494
26495 public function __construct(SemverVersionParser $parser = null, $loadOptions = false)
26496 {
26497 if (!$parser) {
26498 $parser = new VersionParser;
26499 }
26500 $this->versionParser = $parser;
26501 $this->loadOptions = $loadOptions;
26502 }
26503
26504 public function load(array $config, $class = 'Composer\Package\CompletePackage')
26505 {
26506 if (!isset($config['name'])) {
26507 throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
26508 }
26509 if (!isset($config['version'])) {
26510 throw new \UnexpectedValueException('Package '.$config['name'].' has no version defined.');
26511 }
26512
26513
26514  if (isset($config['version_normalized'])) {
26515 $version = $config['version_normalized'];
26516 } else {
26517 $version = $this->versionParser->normalize($config['version']);
26518 }
26519 $package = new $class($config['name'], $version, $config['version']);
26520 $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
26521
26522 if (isset($config['target-dir'])) {
26523 $package->setTargetDir($config['target-dir']);
26524 }
26525
26526 if (isset($config['extra']) && is_array($config['extra'])) {
26527 $package->setExtra($config['extra']);
26528 }
26529
26530 if (isset($config['bin'])) {
26531 if (!is_array($config['bin'])) {
26532 throw new \UnexpectedValueException('Package '.$config['name'].'\'s bin key should be an array, '.gettype($config['bin']).' given.');
26533 }
26534 foreach ($config['bin'] as $key => $bin) {
26535 $config['bin'][$key] = ltrim($bin, '/');
26536 }
26537 $package->setBinaries($config['bin']);
26538 }
26539
26540 if (isset($config['installation-source'])) {
26541 $package->setInstallationSource($config['installation-source']);
26542 }
26543
26544 if (isset($config['source'])) {
26545 if (!isset($config['source']['type']) || !isset($config['source']['url']) || !isset($config['source']['reference'])) {
26546 throw new \UnexpectedValueException(sprintf(
26547 "Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.",
26548 $config['name'],
26549 json_encode($config['source'])
26550 ));
26551 }
26552 $package->setSourceType($config['source']['type']);
26553 $package->setSourceUrl($config['source']['url']);
26554 $package->setSourceReference($config['source']['reference']);
26555 if (isset($config['source']['mirrors'])) {
26556 $package->setSourceMirrors($config['source']['mirrors']);
26557 }
26558 }
26559
26560 if (isset($config['dist'])) {
26561 if (!isset($config['dist']['type'])
26562 || !isset($config['dist']['url'])) {
26563 throw new \UnexpectedValueException(sprintf(
26564 "Package %s's dist key should be specified as ".
26565 "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.",
26566 $config['name'],
26567 json_encode($config['dist'])
26568 ));
26569 }
26570 $package->setDistType($config['dist']['type']);
26571 $package->setDistUrl($config['dist']['url']);
26572 $package->setDistReference(isset($config['dist']['reference']) ? $config['dist']['reference'] : null);
26573 $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
26574 if (isset($config['dist']['mirrors'])) {
26575 $package->setDistMirrors($config['dist']['mirrors']);
26576 }
26577 }
26578
26579 foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
26580 if (isset($config[$type])) {
26581 $method = 'set'.ucfirst($opts['method']);
26582 $package->{$method}(
26583 $this->parseLinks(
26584 $package->getName(),
26585 $package->getPrettyVersion(),
26586 $opts['description'],
26587 $config[$type]
26588 )
26589 );
26590 }
26591 }
26592
26593 if (isset($config['suggest']) && is_array($config['suggest'])) {
26594 foreach ($config['suggest'] as $target => $reason) {
26595 if ('self.version' === trim($reason)) {
26596 $config['suggest'][$target] = $package->getPrettyVersion();
26597 }
26598 }
26599 $package->setSuggests($config['suggest']);
26600 }
26601
26602 if (isset($config['autoload'])) {
26603 $package->setAutoload($config['autoload']);
26604 }
26605
26606 if (isset($config['autoload-dev'])) {
26607 $package->setDevAutoload($config['autoload-dev']);
26608 }
26609
26610 if (isset($config['include-path'])) {
26611 $package->setIncludePaths($config['include-path']);
26612 }
26613
26614 if (!empty($config['time'])) {
26615 $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
26616
26617 try {
26618 $date = new \DateTime($time, new \DateTimeZone('UTC'));
26619 $package->setReleaseDate($date);
26620 } catch (\Exception $e) {
26621 }
26622 }
26623
26624 if (!empty($config['notification-url'])) {
26625 $package->setNotificationUrl($config['notification-url']);
26626 }
26627
26628 if (!empty($config['archive']['exclude'])) {
26629 $package->setArchiveExcludes($config['archive']['exclude']);
26630 }
26631
26632 if ($package instanceof Package\CompletePackageInterface) {
26633 if (isset($config['scripts']) && is_array($config['scripts'])) {
26634 foreach ($config['scripts'] as $event => $listeners) {
26635 $config['scripts'][$event] = (array) $listeners;
26636 }
26637 if (isset($config['scripts']['composer'])) {
26638 trigger_error('The `composer` script name is reserved for internal use, please avoid defining it', E_USER_DEPRECATED);
26639 }
26640 $package->setScripts($config['scripts']);
26641 }
26642
26643 if (!empty($config['description']) && is_string($config['description'])) {
26644 $package->setDescription($config['description']);
26645 }
26646
26647 if (!empty($config['homepage']) && is_string($config['homepage'])) {
26648 $package->setHomepage($config['homepage']);
26649 }
26650
26651 if (!empty($config['keywords']) && is_array($config['keywords'])) {
26652 $package->setKeywords($config['keywords']);
26653 }
26654
26655 if (!empty($config['license'])) {
26656 $package->setLicense(is_array($config['license']) ? $config['license'] : array($config['license']));
26657 }
26658
26659 if (!empty($config['authors']) && is_array($config['authors'])) {
26660 $package->setAuthors($config['authors']);
26661 }
26662
26663 if (isset($config['support'])) {
26664 $package->setSupport($config['support']);
26665 }
26666
26667 if (isset($config['abandoned'])) {
26668 $package->setAbandoned($config['abandoned']);
26669 }
26670 }
26671
26672 if ($aliasNormalized = $this->getBranchAlias($config)) {
26673 if ($package instanceof RootPackageInterface) {
26674 $package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
26675 } else {
26676 $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
26677 }
26678 }
26679
26680 if ($this->loadOptions && isset($config['transport-options'])) {
26681 $package->setTransportOptions($config['transport-options']);
26682 }
26683
26684 return $package;
26685 }
26686
26687
26688
26689
26690
26691
26692
26693
26694 public function parseLinks($source, $sourceVersion, $description, $links)
26695 {
26696 $res = array();
26697 foreach ($links as $target => $constraint) {
26698 if (!is_string($constraint)) {
26699 throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($constraint) . ' (' . var_export($constraint, true) . ')');
26700 }
26701 if ('self.version' === $constraint) {
26702 $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
26703 } else {
26704 $parsedConstraint = $this->versionParser->parseConstraints($constraint);
26705 }
26706
26707 $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
26708 }
26709
26710 return $res;
26711 }
26712
26713
26714
26715
26716
26717
26718
26719 public function getBranchAlias(array $config)
26720 {
26721 if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
26722 || !isset($config['extra']['branch-alias'])
26723 || !is_array($config['extra']['branch-alias'])
26724 ) {
26725 return;
26726 }
26727
26728 foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
26729
26730  if ('-dev' !== substr($targetBranch, -4)) {
26731 continue;
26732 }
26733
26734
26735  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
26736 if ('-dev' !== substr($validatedTargetBranch, -4)) {
26737 continue;
26738 }
26739
26740
26741  if (strtolower($config['version']) !== strtolower($sourceBranch)) {
26742 continue;
26743 }
26744
26745
26746  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
26747 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
26748 && (stripos($targetPrefix, $sourcePrefix) !== 0)
26749 ) {
26750 continue;
26751 }
26752
26753 return $validatedTargetBranch;
26754 }
26755 }
26756 }
26757 <?php
26758
26759
26760
26761
26762
26763
26764
26765
26766
26767
26768
26769 namespace Composer\Package\Loader;
26770
26771
26772
26773
26774 class InvalidPackageException extends \Exception
26775 {
26776 private $errors;
26777 private $warnings;
26778 private $data;
26779
26780 public function __construct(array $errors, array $warnings, array $data)
26781 {
26782 $this->errors = $errors;
26783 $this->warnings = $warnings;
26784 $this->data = $data;
26785 parent::__construct("Invalid package information: \n".implode("\n", array_merge($errors, $warnings)));
26786 }
26787
26788 public function getData()
26789 {
26790 return $this->data;
26791 }
26792
26793 public function getErrors()
26794 {
26795 return $this->errors;
26796 }
26797
26798 public function getWarnings()
26799 {
26800 return $this->warnings;
26801 }
26802 }
26803 <?php
26804
26805
26806
26807
26808
26809
26810
26811
26812
26813
26814
26815 namespace Composer\Package\Loader;
26816
26817 use Composer\Json\JsonFile;
26818
26819
26820
26821
26822 class JsonLoader
26823 {
26824 private $loader;
26825
26826 public function __construct(LoaderInterface $loader)
26827 {
26828 $this->loader = $loader;
26829 }
26830
26831
26832
26833
26834
26835 public function load($json)
26836 {
26837 if ($json instanceof JsonFile) {
26838 $config = $json->read();
26839 } elseif (file_exists($json)) {
26840 $config = JsonFile::parseJson(file_get_contents($json), $json);
26841 } elseif (is_string($json)) {
26842 $config = JsonFile::parseJson($json);
26843 }
26844
26845 return $this->loader->load($config);
26846 }
26847 }
26848 <?php
26849
26850
26851
26852
26853
26854
26855
26856
26857
26858
26859
26860 namespace Composer\Package\Loader;
26861
26862
26863
26864
26865
26866
26867 interface LoaderInterface
26868 {
26869
26870
26871
26872
26873
26874
26875
26876 public function load(array $package, $class = 'Composer\Package\CompletePackage');
26877 }
26878 <?php
26879
26880
26881
26882
26883
26884
26885
26886
26887
26888
26889
26890 namespace Composer\Package\Loader;
26891
26892 use Composer\Package\BasePackage;
26893 use Composer\Package\AliasPackage;
26894 use Composer\Config;
26895 use Composer\Package\RootPackageInterface;
26896 use Composer\Repository\RepositoryFactory;
26897 use Composer\Package\Version\VersionGuesser;
26898 use Composer\Package\Version\VersionParser;
26899 use Composer\Repository\RepositoryManager;
26900 use Composer\Util\ProcessExecutor;
26901
26902
26903
26904
26905
26906
26907
26908
26909 class RootPackageLoader extends ArrayLoader
26910 {
26911
26912
26913
26914 private $manager;
26915
26916
26917
26918
26919 private $config;
26920
26921
26922
26923
26924 private $versionGuesser;
26925
26926 public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null)
26927 {
26928 parent::__construct($parser);
26929
26930 $this->manager = $manager;
26931 $this->config = $config;
26932 $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
26933 }
26934
26935
26936
26937
26938
26939
26940
26941 public function load(array $config, $class = 'Composer\Package\RootPackage', $cwd = null)
26942 {
26943 if (!isset($config['name'])) {
26944 $config['name'] = '__root__';
26945 }
26946 $autoVersioned = false;
26947 if (!isset($config['version'])) {
26948
26949  if (getenv('COMPOSER_ROOT_VERSION')) {
26950 $version = getenv('COMPOSER_ROOT_VERSION');
26951 $commit = null;
26952 } else {
26953 $versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
26954 $version = $versionData['version'];
26955 $commit = $versionData['commit'];
26956 }
26957
26958 if (!$version) {
26959 $version = '1.0.0';
26960 $autoVersioned = true;
26961 }
26962
26963 $config['version'] = $version;
26964 if ($commit) {
26965 $config['source'] = array(
26966 'type' => '',
26967 'url' => '',
26968 'reference' => $commit,
26969 );
26970 $config['dist'] = array(
26971 'type' => '',
26972 'url' => '',
26973 'reference' => $commit,
26974 );
26975 }
26976 }
26977
26978 $realPackage = $package = parent::load($config, $class);
26979 if ($realPackage instanceof AliasPackage) {
26980 $realPackage = $package->getAliasOf();
26981 }
26982
26983 if ($autoVersioned) {
26984 $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
26985 }
26986
26987 if (isset($config['minimum-stability'])) {
26988 $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
26989 }
26990
26991 $aliases = array();
26992 $stabilityFlags = array();
26993 $references = array();
26994 foreach (array('require', 'require-dev') as $linkType) {
26995 if (isset($config[$linkType])) {
26996 $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
26997 $method = 'get'.ucfirst($linkInfo['method']);
26998 $links = array();
26999 foreach ($realPackage->$method() as $link) {
27000 $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
27001 }
27002 $aliases = $this->extractAliases($links, $aliases);
27003 $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
27004 $references = $this->extractReferences($links, $references);
27005 }
27006 }
27007
27008 if (isset($links[$config['name']])) {
27009 throw new \InvalidArgumentException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL .
27010 'Did you accidentally name your root package after an external package?', $config['name']));
27011 }
27012
27013 $realPackage->setAliases($aliases);
27014 $realPackage->setStabilityFlags($stabilityFlags);
27015 $realPackage->setReferences($references);
27016
27017 if (isset($config['prefer-stable'])) {
27018 $realPackage->setPreferStable((bool) $config['prefer-stable']);
27019 }
27020
27021 if (isset($config['config'])) {
27022 $realPackage->setConfig($config['config']);
27023 }
27024
27025 $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
27026 foreach ($repos as $repo) {
27027 $this->manager->addRepository($repo);
27028 }
27029 $realPackage->setRepositories($this->config->getRepositories());
27030
27031 return $package;
27032 }
27033
27034 private function extractAliases(array $requires, array $aliases)
27035 {
27036 foreach ($requires as $reqName => $reqVersion) {
27037 if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
27038 $aliases[] = array(
27039 'package' => strtolower($reqName),
27040 'version' => $this->versionParser->normalize($match[1], $reqVersion),
27041 'alias' => $match[2],
27042 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
27043 );
27044 }
27045 }
27046
27047 return $aliases;
27048 }
27049
27050 private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
27051 {
27052 $stabilities = BasePackage::$stabilities;
27053 $minimumStability = $stabilities[$minimumStability];
27054 foreach ($requires as $reqName => $reqVersion) {
27055 $constraints = array();
27056
27057
27058  $orSplit = preg_split('{\s*\|\|?\s*}', trim($reqVersion));
27059 foreach ($orSplit as $orConstraint) {
27060 $andSplit = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
27061 foreach ($andSplit as $andConstraint) {
27062 $constraints[] = $andConstraint;
27063 }
27064 }
27065
27066
27067  $match = false;
27068 foreach ($constraints as $constraint) {
27069 if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
27070 $name = strtolower($reqName);
27071 $stability = $stabilities[VersionParser::normalizeStability($match[1])];
27072
27073 if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
27074 continue;
27075 }
27076 $stabilityFlags[$name] = $stability;
27077 $match = true;
27078 }
27079 }
27080
27081 if ($match) {
27082 continue;
27083 }
27084
27085 foreach ($constraints as $constraint) {
27086
27087  
27088  $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
27089 if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
27090 $name = strtolower($reqName);
27091 $stability = $stabilities[$stabilityName];
27092 if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
27093 continue;
27094 }
27095 $stabilityFlags[$name] = $stability;
27096 }
27097 }
27098 }
27099
27100 return $stabilityFlags;
27101 }
27102
27103 private function extractReferences(array $requires, array $references)
27104 {
27105 foreach ($requires as $reqName => $reqVersion) {
27106 $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
27107 if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === ($stabilityName = VersionParser::parseStability($reqVersion))) {
27108 $name = strtolower($reqName);
27109 $references[$name] = $match[1];
27110 }
27111 }
27112
27113 return $references;
27114 }
27115 }
27116 <?php
27117
27118
27119
27120
27121
27122
27123
27124
27125
27126
27127
27128 namespace Composer\Package\Loader;
27129
27130 use Composer\Package;
27131 use Composer\Package\BasePackage;
27132 use Composer\Semver\Constraint\Constraint;
27133 use Composer\Package\Version\VersionParser;
27134 use Composer\Repository\PlatformRepository;
27135
27136
27137
27138
27139 class ValidatingArrayLoader implements LoaderInterface
27140 {
27141 const CHECK_ALL = 3;
27142 const CHECK_UNBOUND_CONSTRAINTS = 1;
27143 const CHECK_STRICT_CONSTRAINTS = 2;
27144
27145 private $loader;
27146 private $versionParser;
27147 private $errors;
27148 private $warnings;
27149 private $config;
27150 private $strictName;
27151 private $flags;
27152
27153 public function __construct(LoaderInterface $loader, $strictName = true, VersionParser $parser = null, $flags = 0)
27154 {
27155 $this->loader = $loader;
27156 $this->versionParser = $parser ?: new VersionParser();
27157 $this->strictName = $strictName;
27158 $this->flags = $flags;
27159 }
27160
27161 public function load(array $config, $class = 'Composer\Package\CompletePackage')
27162 {
27163 $this->errors = array();
27164 $this->warnings = array();
27165 $this->config = $config;
27166
27167 if ($this->strictName) {
27168 $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
27169 } else {
27170 $this->validateString('name', true);
27171 }
27172
27173 if (!empty($this->config['version'])) {
27174 try {
27175 $this->versionParser->normalize($this->config['version']);
27176 } catch (\Exception $e) {
27177 $this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
27178 unset($this->config['version']);
27179 }
27180 }
27181
27182 if (!empty($this->config['config']['platform'])) {
27183 foreach ((array) $this->config['config']['platform'] as $key => $platform) {
27184 try {
27185 $this->versionParser->normalize($platform);
27186 } catch (\Exception $e) {
27187 $this->errors[] = 'config.platform.' . $key . ' : invalid value ('.$platform.'): '.$e->getMessage();
27188 }
27189 }
27190 }
27191
27192 $this->validateRegex('type', '[A-Za-z0-9-]+');
27193 $this->validateString('target-dir');
27194 $this->validateArray('extra');
27195 $this->validateFlatArray('bin');
27196 $this->validateArray('scripts'); 
27197  $this->validateString('description');
27198 $this->validateUrl('homepage');
27199 $this->validateFlatArray('keywords', '[\p{N}\p{L} ._-]+');
27200
27201 if (isset($this->config['license'])) {
27202 if (is_string($this->config['license'])) {
27203 $this->validateRegex('license', '[A-Za-z0-9+. ()-]+');
27204 } else {
27205 $this->validateFlatArray('license', '[A-Za-z0-9+. ()-]+');
27206 }
27207 }
27208
27209 $this->validateString('time');
27210 if (!empty($this->config['time'])) {
27211 try {
27212 $date = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
27213 } catch (\Exception $e) {
27214 $this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
27215 unset($this->config['time']);
27216 }
27217 }
27218
27219 if ($this->validateArray('authors') && !empty($this->config['authors'])) {
27220 foreach ($this->config['authors'] as $key => $author) {
27221 if (!is_array($author)) {
27222 $this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
27223 unset($this->config['authors'][$key]);
27224 continue;
27225 }
27226 foreach (array('homepage', 'email', 'name', 'role') as $authorData) {
27227 if (isset($author[$authorData]) && !is_string($author[$authorData])) {
27228 $this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
27229 unset($this->config['authors'][$key][$authorData]);
27230 }
27231 }
27232 if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
27233 $this->warnings[] = 'authors.'.$key.'.homepage : invalid value ('.$author['homepage'].'), must be an http/https URL';
27234 unset($this->config['authors'][$key]['homepage']);
27235 }
27236 if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
27237 $this->warnings[] = 'authors.'.$key.'.email : invalid value ('.$author['email'].'), must be a valid email address';
27238 unset($this->config['authors'][$key]['email']);
27239 }
27240 if (empty($this->config['authors'][$key])) {
27241 unset($this->config['authors'][$key]);
27242 }
27243 }
27244 if (empty($this->config['authors'])) {
27245 unset($this->config['authors']);
27246 }
27247 }
27248
27249 if ($this->validateArray('support') && !empty($this->config['support'])) {
27250 foreach (array('issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss') as $key) {
27251 if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
27252 $this->errors[] = 'support.'.$key.' : invalid value, must be a string';
27253 unset($this->config['support'][$key]);
27254 }
27255 }
27256
27257 if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], FILTER_VALIDATE_EMAIL)) {
27258 $this->warnings[] = 'support.email : invalid value ('.$this->config['support']['email'].'), must be a valid email address';
27259 unset($this->config['support']['email']);
27260 }
27261
27262 if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) {
27263 $this->warnings[] = 'support.irc : invalid value ('.$this->config['support']['irc'].'), must be a irc://<server>/<channel> URL';
27264 unset($this->config['support']['irc']);
27265 }
27266
27267 foreach (array('issues', 'forum', 'wiki', 'source', 'docs') as $key) {
27268 if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
27269 $this->warnings[] = 'support.'.$key.' : invalid value ('.$this->config['support'][$key].'), must be an http/https URL';
27270 unset($this->config['support'][$key]);
27271 }
27272 }
27273 if (empty($this->config['support'])) {
27274 unset($this->config['support']);
27275 }
27276 }
27277
27278 $unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master'));
27279 $stableConstraint = new Constraint('=', '1.0.0');
27280
27281 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
27282 if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
27283 foreach ($this->config[$linkType] as $package => $constraint) {
27284 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
27285 $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
27286 }
27287 if (!is_string($constraint)) {
27288 $this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
27289 unset($this->config[$linkType][$package]);
27290 } elseif ('self.version' !== $constraint) {
27291 try {
27292 $linkConstraint = $this->versionParser->parseConstraints($constraint);
27293 } catch (\Exception $e) {
27294 $this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
27295 unset($this->config[$linkType][$package]);
27296 continue;
27297 }
27298
27299
27300  if (
27301 ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS)
27302 && 'require' === $linkType
27303 && $linkConstraint->matches($unboundConstraint)
27304 && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $package)
27305 ) {
27306 $this->warnings[] = $linkType.'.'.$package.' : unbound version constraints ('.$constraint.') should be avoided';
27307 } elseif (
27308
27309  ($this->flags & self::CHECK_STRICT_CONSTRAINTS)
27310 && 'require' === $linkType
27311 && substr($linkConstraint, 0, 1) === '='
27312 && $stableConstraint->versionCompare($stableConstraint, $linkConstraint, '<=')
27313 ) {
27314 $this->warnings[] = $linkType.'.'.$package.' : exact version constraints ('.$constraint.') should be avoided if the package follows semantic versioning';
27315 }
27316 }
27317 }
27318 }
27319 }
27320
27321 if ($this->validateArray('suggest') && !empty($this->config['suggest'])) {
27322 foreach ($this->config['suggest'] as $package => $description) {
27323 if (!is_string($description)) {
27324 $this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
27325 unset($this->config['suggest'][$package]);
27326 }
27327 }
27328 }
27329
27330 if ($this->validateString('minimum-stability') && !empty($this->config['minimum-stability'])) {
27331 if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
27332 $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
27333 unset($this->config['minimum-stability']);
27334 }
27335 }
27336
27337 if ($this->validateArray('autoload') && !empty($this->config['autoload'])) {
27338 $types = array('psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap');
27339 foreach ($this->config['autoload'] as $type => $typeConfig) {
27340 if (!in_array($type, $types)) {
27341 $this->errors[] = 'autoload : invalid value ('.$type.'), must be one of '.implode(', ', $types);
27342 unset($this->config['autoload'][$type]);
27343 }
27344 if ($type === 'psr-4') {
27345 foreach ($typeConfig as $namespace => $dirs) {
27346 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
27347 $this->errors[] = 'autoload.psr-4 : invalid value ('.$namespace.'), namespaces must end with a namespace separator, should be '.$namespace.'\\\\';
27348 }
27349 }
27350 }
27351 }
27352 }
27353
27354 if (!empty($this->config['autoload']['psr-4']) && !empty($this->config['target-dir'])) {
27355 $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
27356
27357  
27358  unset($this->config['autoload']['psr-4']);
27359 }
27360
27361
27362  
27363
27364
27365  
27366
27367 $this->validateFlatArray('include-path');
27368 $this->validateArray('transport-options');
27369
27370
27371  if (isset($this->config['extra']['branch-alias'])) {
27372 if (!is_array($this->config['extra']['branch-alias'])) {
27373 $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
27374 } else {
27375 foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
27376
27377  if ('-dev' !== substr($targetBranch, -4)) {
27378 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must end in -dev';
27379 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27380
27381 continue;
27382 }
27383
27384
27385  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
27386 if ('-dev' !== substr($validatedTargetBranch, -4)) {
27387 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
27388 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27389
27390 continue;
27391 }
27392
27393
27394  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
27395 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
27396 && (stripos($targetPrefix, $sourcePrefix) !== 0)
27397 ) {
27398 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
27399 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27400 }
27401 }
27402 }
27403 }
27404
27405 if ($this->errors) {
27406 throw new InvalidPackageException($this->errors, $this->warnings, $config);
27407 }
27408
27409 $package = $this->loader->load($this->config, $class);
27410 $this->config = null;
27411
27412 return $package;
27413 }
27414
27415 public function getWarnings()
27416 {
27417 return $this->warnings;
27418 }
27419
27420 public function getErrors()
27421 {
27422 return $this->errors;
27423 }
27424
27425 private function validateRegex($property, $regex, $mandatory = false)
27426 {
27427 if (!$this->validateString($property, $mandatory)) {
27428 return false;
27429 }
27430
27431 if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) {
27432 $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex;
27433 if ($mandatory) {
27434 $this->errors[] = $message;
27435 } else {
27436 $this->warnings[] = $message;
27437 }
27438 unset($this->config[$property]);
27439
27440 return false;
27441 }
27442
27443 return true;
27444 }
27445
27446 private function validateString($property, $mandatory = false)
27447 {
27448 if (isset($this->config[$property]) && !is_string($this->config[$property])) {
27449 $this->errors[] = $property.' : should be a string, '.gettype($this->config[$property]).' given';
27450 unset($this->config[$property]);
27451
27452 return false;
27453 }
27454
27455 if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
27456 if ($mandatory) {
27457 $this->errors[] = $property.' : must be present';
27458 }
27459 unset($this->config[$property]);
27460
27461 return false;
27462 }
27463
27464 return true;
27465 }
27466
27467 private function validateArray($property, $mandatory = false)
27468 {
27469 if (isset($this->config[$property]) && !is_array($this->config[$property])) {
27470 $this->errors[] = $property.' : should be an array, '.gettype($this->config[$property]).' given';
27471 unset($this->config[$property]);
27472
27473 return false;
27474 }
27475
27476 if (!isset($this->config[$property]) || !count($this->config[$property])) {
27477 if ($mandatory) {
27478 $this->errors[] = $property.' : must be present and contain at least one element';
27479 }
27480 unset($this->config[$property]);
27481
27482 return false;
27483 }
27484
27485 return true;
27486 }
27487
27488 private function validateFlatArray($property, $regex = null, $mandatory = false)
27489 {
27490 if (!$this->validateArray($property, $mandatory)) {
27491 return false;
27492 }
27493
27494 $pass = true;
27495 foreach ($this->config[$property] as $key => $value) {
27496 if (!is_string($value) && !is_numeric($value)) {
27497 $this->errors[] = $property.'.'.$key.' : must be a string or int, '.gettype($value).' given';
27498 unset($this->config[$property][$key]);
27499 $pass = false;
27500
27501 continue;
27502 }
27503
27504 if ($regex && !preg_match('{^'.$regex.'$}u', $value)) {
27505 $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex;
27506 unset($this->config[$property][$key]);
27507 $pass = false;
27508 }
27509 }
27510
27511 return $pass;
27512 }
27513
27514 private function validateUrl($property, $mandatory = false)
27515 {
27516 if (!$this->validateString($property, $mandatory)) {
27517 return false;
27518 }
27519
27520 if (!$this->filterUrl($this->config[$property])) {
27521 $this->warnings[] = $property.' : invalid value ('.$this->config[$property].'), must be an http/https URL';
27522 unset($this->config[$property]);
27523
27524 return false;
27525 }
27526
27527 return true;
27528 }
27529
27530 private function filterUrl($value, array $schemes = array('http', 'https'))
27531 {
27532 if ($value === '') {
27533 return true;
27534 }
27535
27536 $bits = parse_url($value);
27537 if (empty($bits['scheme']) || empty($bits['host'])) {
27538 return false;
27539 }
27540
27541 if (!in_array($bits['scheme'], $schemes, true)) {
27542 return false;
27543 }
27544
27545 return true;
27546 }
27547 }
27548 <?php
27549
27550
27551
27552
27553
27554
27555
27556
27557
27558
27559
27560 namespace Composer\Package;
27561
27562 use Composer\Json\JsonFile;
27563 use Composer\Installer\InstallationManager;
27564 use Composer\Repository\RepositoryManager;
27565 use Composer\Util\ProcessExecutor;
27566 use Composer\Repository\ArrayRepository;
27567 use Composer\Package\Dumper\ArrayDumper;
27568 use Composer\Package\Loader\ArrayLoader;
27569 use Composer\Util\Git as GitUtil;
27570 use Composer\IO\IOInterface;
27571 use Seld\JsonLint\ParsingException;
27572
27573
27574
27575
27576
27577
27578
27579 class Locker
27580 {
27581 private $lockFile;
27582 private $repositoryManager;
27583 private $installationManager;
27584 private $hash;
27585 private $contentHash;
27586 private $loader;
27587 private $dumper;
27588 private $process;
27589 private $lockDataCache;
27590
27591
27592
27593
27594
27595
27596
27597
27598
27599
27600 public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
27601 {
27602 $this->lockFile = $lockFile;
27603 $this->repositoryManager = $repositoryManager;
27604 $this->installationManager = $installationManager;
27605 $this->hash = md5($composerFileContents);
27606 $this->contentHash = self::getContentHash($composerFileContents);
27607 $this->loader = new ArrayLoader(null, true);
27608 $this->dumper = new ArrayDumper();
27609 $this->process = new ProcessExecutor($io);
27610 }
27611
27612
27613
27614
27615
27616
27617
27618
27619 public static function getContentHash($composerFileContents)
27620 {
27621 $content = json_decode($composerFileContents, true);
27622
27623 $relevantKeys = array(
27624 'name',
27625 'version',
27626 'require',
27627 'require-dev',
27628 'conflict',
27629 'replace',
27630 'provide',
27631 'minimum-stability',
27632 'prefer-stable',
27633 'repositories',
27634 'extra',
27635 );
27636
27637 $relevantContent = array();
27638
27639 foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
27640 $relevantContent[$key] = $content[$key];
27641 }
27642 if (isset($content['config']['platform'])) {
27643 $relevantContent['config']['platform'] = $content['config']['platform'];
27644 }
27645
27646 ksort($relevantContent);
27647
27648 return md5(json_encode($relevantContent));
27649 }
27650
27651
27652
27653
27654
27655
27656 public function isLocked()
27657 {
27658 if (!$this->lockFile->exists()) {
27659 return false;
27660 }
27661
27662 $data = $this->getLockData();
27663
27664 return isset($data['packages']);
27665 }
27666
27667
27668
27669
27670
27671
27672 public function isFresh()
27673 {
27674 $lock = $this->lockFile->read();
27675
27676 if (!empty($lock['content-hash'])) {
27677
27678  return $this->contentHash === $lock['content-hash'];
27679 }
27680
27681
27682  if (!empty($lock['hash'])) {
27683 return $this->hash === $lock['hash'];
27684 }
27685
27686
27687  return false;
27688 }
27689
27690
27691
27692
27693
27694
27695
27696
27697 public function getLockedRepository($withDevReqs = false)
27698 {
27699 $lockData = $this->getLockData();
27700 $packages = new ArrayRepository();
27701
27702 $lockedPackages = $lockData['packages'];
27703 if ($withDevReqs) {
27704 if (isset($lockData['packages-dev'])) {
27705 $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
27706 } else {
27707 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.');
27708 }
27709 }
27710
27711 if (empty($lockedPackages)) {
27712 return $packages;
27713 }
27714
27715 if (isset($lockedPackages[0]['name'])) {
27716 foreach ($lockedPackages as $info) {
27717 $packages->addPackage($this->loader->load($info));
27718 }
27719
27720 return $packages;
27721 }
27722
27723 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.');
27724 }
27725
27726
27727
27728
27729
27730
27731
27732 public function getPlatformRequirements($withDevReqs = false)
27733 {
27734 $lockData = $this->getLockData();
27735 $requirements = array();
27736
27737 if (!empty($lockData['platform'])) {
27738 $requirements = $this->loader->parseLinks(
27739 '__ROOT__',
27740 '1.0.0',
27741 'requires',
27742 isset($lockData['platform']) ? $lockData['platform'] : array()
27743 );
27744 }
27745
27746 if ($withDevReqs && !empty($lockData['platform-dev'])) {
27747 $devRequirements = $this->loader->parseLinks(
27748 '__ROOT__',
27749 '1.0.0',
27750 'requires',
27751 isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
27752 );
27753
27754 $requirements = array_merge($requirements, $devRequirements);
27755 }
27756
27757 return $requirements;
27758 }
27759
27760 public function getMinimumStability()
27761 {
27762 $lockData = $this->getLockData();
27763
27764 return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'stable';
27765 }
27766
27767 public function getStabilityFlags()
27768 {
27769 $lockData = $this->getLockData();
27770
27771 return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
27772 }
27773
27774 public function getPreferStable()
27775 {
27776 $lockData = $this->getLockData();
27777
27778
27779  
27780  return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null;
27781 }
27782
27783 public function getPreferLowest()
27784 {
27785 $lockData = $this->getLockData();
27786
27787
27788  
27789  return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
27790 }
27791
27792 public function getPlatformOverrides()
27793 {
27794 $lockData = $this->getLockData();
27795
27796 return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
27797 }
27798
27799 public function getAliases()
27800 {
27801 $lockData = $this->getLockData();
27802
27803 return isset($lockData['aliases']) ? $lockData['aliases'] : array();
27804 }
27805
27806 public function getLockData()
27807 {
27808 if (null !== $this->lockDataCache) {
27809 return $this->lockDataCache;
27810 }
27811
27812 if (!$this->lockFile->exists()) {
27813 throw new \LogicException('No lockfile found. Unable to read locked packages');
27814 }
27815
27816 return $this->lockDataCache = $this->lockFile->read();
27817 }
27818
27819
27820
27821
27822
27823
27824
27825
27826
27827
27828
27829
27830
27831
27832
27833
27834
27835 public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest, array $platformOverrides)
27836 {
27837 $lock = array(
27838 '_readme' => array('This file locks the dependencies of your project to a known state',
27839 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file',
27840 'This file is @gener'.'ated automatically', ),
27841 'content-hash' => $this->contentHash,
27842 'packages' => null,
27843 'packages-dev' => null,
27844 'aliases' => array(),
27845 'minimum-stability' => $minimumStability,
27846 'stability-flags' => $stabilityFlags,
27847 'prefer-stable' => $preferStable,
27848 'prefer-lowest' => $preferLowest,
27849 );
27850
27851 foreach ($aliases as $package => $versions) {
27852 foreach ($versions as $version => $alias) {
27853 $lock['aliases'][] = array(
27854 'alias' => $alias['alias'],
27855 'alias_normalized' => $alias['alias_normalized'],
27856 'version' => $version,
27857 'package' => $package,
27858 );
27859 }
27860 }
27861
27862 $lock['packages'] = $this->lockPackages($packages);
27863 if (null !== $devPackages) {
27864 $lock['packages-dev'] = $this->lockPackages($devPackages);
27865 }
27866
27867 $lock['platform'] = $platformReqs;
27868 $lock['platform-dev'] = $platformDevReqs;
27869 if ($platformOverrides) {
27870 $lock['platform-overrides'] = $platformOverrides;
27871 }
27872
27873 if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
27874 if ($this->lockFile->exists()) {
27875 unlink($this->lockFile->getPath());
27876 }
27877
27878 return false;
27879 }
27880
27881 try {
27882 $isLocked = $this->isLocked();
27883 } catch (ParsingException $e) {
27884 $isLocked = false;
27885 }
27886 if (!$isLocked || $lock !== $this->getLockData()) {
27887 $this->lockFile->write($lock);
27888 $this->lockDataCache = null;
27889
27890 return true;
27891 }
27892
27893 return false;
27894 }
27895
27896 private function lockPackages(array $packages)
27897 {
27898 $locked = array();
27899
27900 foreach ($packages as $package) {
27901 if ($package instanceof AliasPackage) {
27902 continue;
27903 }
27904
27905 $name = $package->getPrettyName();
27906 $version = $package->getPrettyVersion();
27907
27908 if (!$name || !$version) {
27909 throw new \LogicException(sprintf(
27910 'Package "%s" has no version or name and can not be locked', $package
27911 ));
27912 }
27913
27914 $spec = $this->dumper->dump($package);
27915 unset($spec['version_normalized']);
27916
27917
27918  $time = isset($spec['time']) ? $spec['time'] : null;
27919 unset($spec['time']);
27920 if ($package->isDev() && $package->getInstallationSource() === 'source') {
27921
27922  $time = $this->getPackageTime($package) ?: $time;
27923 }
27924 if (null !== $time) {
27925 $spec['time'] = $time;
27926 }
27927
27928 unset($spec['installation-source']);
27929
27930 $locked[] = $spec;
27931 }
27932
27933 usort($locked, function ($a, $b) {
27934 $comparison = strcmp($a['name'], $b['name']);
27935
27936 if (0 !== $comparison) {
27937 return $comparison;
27938 }
27939
27940
27941  return strcmp($a['version'], $b['version']);
27942 });
27943
27944 return $locked;
27945 }
27946
27947
27948
27949
27950
27951
27952
27953 private function getPackageTime(PackageInterface $package)
27954 {
27955 if (!function_exists('proc_open')) {
27956 return null;
27957 }
27958
27959 $path = realpath($this->installationManager->getInstallPath($package));
27960 $sourceType = $package->getSourceType();
27961 $datetime = null;
27962
27963 if ($path && in_array($sourceType, array('git', 'hg'))) {
27964 $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
27965 switch ($sourceType) {
27966 case 'git':
27967 GitUtil::cleanEnv();
27968
27969 if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
27970 $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
27971 }
27972 break;
27973
27974 case 'hg':
27975 if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
27976 $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
27977 }
27978 break;
27979 }
27980 }
27981
27982 return $datetime ? $datetime->format(DATE_RFC3339) : null;
27983 }
27984 }
27985 <?php
27986
27987
27988
27989
27990
27991
27992
27993
27994
27995
27996
27997 namespace Composer\Package;
27998
27999 use Composer\Package\Version\VersionParser;
28000 use Composer\Util\ComposerMirror;
28001
28002
28003
28004
28005
28006
28007 class Package extends BasePackage
28008 {
28009 protected $type;
28010 protected $targetDir;
28011 protected $installationSource;
28012 protected $sourceType;
28013 protected $sourceUrl;
28014 protected $sourceReference;
28015 protected $sourceMirrors;
28016 protected $distType;
28017 protected $distUrl;
28018 protected $distReference;
28019 protected $distSha1Checksum;
28020 protected $distMirrors;
28021 protected $version;
28022 protected $prettyVersion;
28023 protected $releaseDate;
28024 protected $extra = array();
28025 protected $binaries = array();
28026 protected $dev;
28027 protected $stability;
28028 protected $notificationUrl;
28029
28030
28031 protected $requires = array();
28032
28033 protected $conflicts = array();
28034
28035 protected $provides = array();
28036
28037 protected $replaces = array();
28038
28039 protected $devRequires = array();
28040 protected $suggests = array();
28041 protected $autoload = array();
28042 protected $devAutoload = array();
28043 protected $includePaths = array();
28044 protected $archiveExcludes = array();
28045
28046
28047
28048
28049
28050
28051
28052
28053 public function __construct($name, $version, $prettyVersion)
28054 {
28055 parent::__construct($name);
28056
28057 $this->version = $version;
28058 $this->prettyVersion = $prettyVersion;
28059
28060 $this->stability = VersionParser::parseStability($version);
28061 $this->dev = $this->stability === 'dev';
28062 }
28063
28064
28065
28066
28067 public function isDev()
28068 {
28069 return $this->dev;
28070 }
28071
28072
28073
28074
28075 public function setType($type)
28076 {
28077 $this->type = $type;
28078 }
28079
28080
28081
28082
28083 public function getType()
28084 {
28085 return $this->type ?: 'library';
28086 }
28087
28088
28089
28090
28091 public function getStability()
28092 {
28093 return $this->stability;
28094 }
28095
28096
28097
28098
28099 public function setTargetDir($targetDir)
28100 {
28101 $this->targetDir = $targetDir;
28102 }
28103
28104
28105
28106
28107 public function getTargetDir()
28108 {
28109 if (null === $this->targetDir) {
28110 return;
28111 }
28112
28113 return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
28114 }
28115
28116
28117
28118
28119 public function setExtra(array $extra)
28120 {
28121 $this->extra = $extra;
28122 }
28123
28124
28125
28126
28127 public function getExtra()
28128 {
28129 return $this->extra;
28130 }
28131
28132
28133
28134
28135 public function setBinaries(array $binaries)
28136 {
28137 $this->binaries = $binaries;
28138 }
28139
28140
28141
28142
28143 public function getBinaries()
28144 {
28145 return $this->binaries;
28146 }
28147
28148
28149
28150
28151 public function setInstallationSource($type)
28152 {
28153 $this->installationSource = $type;
28154 }
28155
28156
28157
28158
28159 public function getInstallationSource()
28160 {
28161 return $this->installationSource;
28162 }
28163
28164
28165
28166
28167 public function setSourceType($type)
28168 {
28169 $this->sourceType = $type;
28170 }
28171
28172
28173
28174
28175 public function getSourceType()
28176 {
28177 return $this->sourceType;
28178 }
28179
28180
28181
28182
28183 public function setSourceUrl($url)
28184 {
28185 $this->sourceUrl = $url;
28186 }
28187
28188
28189
28190
28191 public function getSourceUrl()
28192 {
28193 return $this->sourceUrl;
28194 }
28195
28196
28197
28198
28199 public function setSourceReference($reference)
28200 {
28201 $this->sourceReference = $reference;
28202 }
28203
28204
28205
28206
28207 public function getSourceReference()
28208 {
28209 return $this->sourceReference;
28210 }
28211
28212
28213
28214
28215 public function setSourceMirrors($mirrors)
28216 {
28217 $this->sourceMirrors = $mirrors;
28218 }
28219
28220
28221
28222
28223 public function getSourceMirrors()
28224 {
28225 return $this->sourceMirrors;
28226 }
28227
28228
28229
28230
28231 public function getSourceUrls()
28232 {
28233 return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
28234 }
28235
28236
28237
28238
28239 public function setDistType($type)
28240 {
28241 $this->distType = $type;
28242 }
28243
28244
28245
28246
28247 public function getDistType()
28248 {
28249 return $this->distType;
28250 }
28251
28252
28253
28254
28255 public function setDistUrl($url)
28256 {
28257 $this->distUrl = $url;
28258 }
28259
28260
28261
28262
28263 public function getDistUrl()
28264 {
28265 return $this->distUrl;
28266 }
28267
28268
28269
28270
28271 public function setDistReference($reference)
28272 {
28273 $this->distReference = $reference;
28274 }
28275
28276
28277
28278
28279 public function getDistReference()
28280 {
28281 return $this->distReference;
28282 }
28283
28284
28285
28286
28287 public function setDistSha1Checksum($sha1checksum)
28288 {
28289 $this->distSha1Checksum = $sha1checksum;
28290 }
28291
28292
28293
28294
28295 public function getDistSha1Checksum()
28296 {
28297 return $this->distSha1Checksum;
28298 }
28299
28300
28301
28302
28303 public function setDistMirrors($mirrors)
28304 {
28305 $this->distMirrors = $mirrors;
28306 }
28307
28308
28309
28310
28311 public function getDistMirrors()
28312 {
28313 return $this->distMirrors;
28314 }
28315
28316
28317
28318
28319 public function getDistUrls()
28320 {
28321 return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
28322 }
28323
28324
28325
28326
28327 public function getVersion()
28328 {
28329 return $this->version;
28330 }
28331
28332
28333
28334
28335 public function getPrettyVersion()
28336 {
28337 return $this->prettyVersion;
28338 }
28339
28340
28341
28342
28343
28344
28345 public function setReleaseDate(\DateTime $releaseDate)
28346 {
28347 $this->releaseDate = $releaseDate;
28348 }
28349
28350
28351
28352
28353 public function getReleaseDate()
28354 {
28355 return $this->releaseDate;
28356 }
28357
28358
28359
28360
28361
28362
28363 public function setRequires(array $requires)
28364 {
28365 $this->requires = $requires;
28366 }
28367
28368
28369
28370
28371 public function getRequires()
28372 {
28373 return $this->requires;
28374 }
28375
28376
28377
28378
28379
28380
28381 public function setConflicts(array $conflicts)
28382 {
28383 $this->conflicts = $conflicts;
28384 }
28385
28386
28387
28388
28389 public function getConflicts()
28390 {
28391 return $this->conflicts;
28392 }
28393
28394
28395
28396
28397
28398
28399 public function setProvides(array $provides)
28400 {
28401 $this->provides = $provides;
28402 }
28403
28404
28405
28406
28407 public function getProvides()
28408 {
28409 return $this->provides;
28410 }
28411
28412
28413
28414
28415
28416
28417 public function setReplaces(array $replaces)
28418 {
28419 $this->replaces = $replaces;
28420 }
28421
28422
28423
28424
28425 public function getReplaces()
28426 {
28427 return $this->replaces;
28428 }
28429
28430
28431
28432
28433
28434
28435 public function setDevRequires(array $devRequires)
28436 {
28437 $this->devRequires = $devRequires;
28438 }
28439
28440
28441
28442
28443 public function getDevRequires()
28444 {
28445 return $this->devRequires;
28446 }
28447
28448
28449
28450
28451
28452
28453 public function setSuggests(array $suggests)
28454 {
28455 $this->suggests = $suggests;
28456 }
28457
28458
28459
28460
28461 public function getSuggests()
28462 {
28463 return $this->suggests;
28464 }
28465
28466
28467
28468
28469
28470
28471 public function setAutoload(array $autoload)
28472 {
28473 $this->autoload = $autoload;
28474 }
28475
28476
28477
28478
28479 public function getAutoload()
28480 {
28481 return $this->autoload;
28482 }
28483
28484
28485
28486
28487
28488
28489 public function setDevAutoload(array $devAutoload)
28490 {
28491 $this->devAutoload = $devAutoload;
28492 }
28493
28494
28495
28496
28497 public function getDevAutoload()
28498 {
28499 return $this->devAutoload;
28500 }
28501
28502
28503
28504
28505
28506
28507 public function setIncludePaths(array $includePaths)
28508 {
28509 $this->includePaths = $includePaths;
28510 }
28511
28512
28513
28514
28515 public function getIncludePaths()
28516 {
28517 return $this->includePaths;
28518 }
28519
28520
28521
28522
28523
28524
28525 public function setNotificationUrl($notificationUrl)
28526 {
28527 $this->notificationUrl = $notificationUrl;
28528 }
28529
28530
28531
28532
28533 public function getNotificationUrl()
28534 {
28535 return $this->notificationUrl;
28536 }
28537
28538
28539
28540
28541
28542
28543 public function setArchiveExcludes(array $excludes)
28544 {
28545 $this->archiveExcludes = $excludes;
28546 }
28547
28548
28549
28550
28551 public function getArchiveExcludes()
28552 {
28553 return $this->archiveExcludes;
28554 }
28555
28556
28557
28558
28559
28560
28561
28562
28563 public function replaceVersion($version, $prettyVersion)
28564 {
28565 $this->version = $version;
28566 $this->prettyVersion = $prettyVersion;
28567
28568 $this->stability = VersionParser::parseStability($version);
28569 $this->dev = $this->stability === 'dev';
28570 }
28571
28572 protected function getUrls($url, $mirrors, $ref, $type, $urlType)
28573 {
28574 if (!$url) {
28575 return array();
28576 }
28577 $urls = array($url);
28578 if ($mirrors) {
28579 foreach ($mirrors as $mirror) {
28580 if ($urlType === 'dist') {
28581 $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type);
28582 } elseif ($urlType === 'source' && $type === 'git') {
28583 $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
28584 } elseif ($urlType === 'source' && $type === 'hg') {
28585 $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
28586 }
28587 if (!in_array($mirrorUrl, $urls)) {
28588 $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
28589 $func($urls, $mirrorUrl);
28590 }
28591 }
28592 }
28593
28594 return $urls;
28595 }
28596 }
28597 <?php
28598
28599
28600
28601
28602
28603
28604
28605
28606
28607
28608
28609 namespace Composer\Package;
28610
28611 use Composer\Repository\RepositoryInterface;
28612
28613
28614
28615
28616
28617
28618 interface PackageInterface
28619 {
28620
28621
28622
28623
28624
28625 public function getName();
28626
28627
28628
28629
28630
28631
28632 public function getPrettyName();
28633
28634
28635
28636
28637
28638
28639
28640
28641
28642 public function getNames();
28643
28644
28645
28646
28647
28648
28649 public function setId($id);
28650
28651
28652
28653
28654
28655
28656 public function getId();
28657
28658
28659
28660
28661
28662
28663 public function isDev();
28664
28665
28666
28667
28668
28669
28670 public function getType();
28671
28672
28673
28674
28675
28676
28677 public function getTargetDir();
28678
28679
28680
28681
28682
28683
28684 public function getExtra();
28685
28686
28687
28688
28689
28690
28691 public function setInstallationSource($type);
28692
28693
28694
28695
28696
28697
28698 public function getInstallationSource();
28699
28700
28701
28702
28703
28704
28705 public function getSourceType();
28706
28707
28708
28709
28710
28711
28712 public function getSourceUrl();
28713
28714
28715
28716
28717
28718
28719 public function getSourceUrls();
28720
28721
28722
28723
28724
28725
28726 public function getSourceReference();
28727
28728
28729
28730
28731
28732
28733 public function getSourceMirrors();
28734
28735
28736
28737
28738
28739
28740 public function getDistType();
28741
28742
28743
28744
28745
28746
28747 public function getDistUrl();
28748
28749
28750
28751
28752
28753
28754 public function getDistUrls();
28755
28756
28757
28758
28759
28760
28761 public function getDistReference();
28762
28763
28764
28765
28766
28767
28768 public function getDistSha1Checksum();
28769
28770
28771
28772
28773
28774
28775 public function getDistMirrors();
28776
28777
28778
28779
28780
28781
28782 public function getVersion();
28783
28784
28785
28786
28787
28788
28789 public function getPrettyVersion();
28790
28791
28792
28793
28794
28795
28796
28797
28798
28799 public function getFullPrettyVersion($truncate = true);
28800
28801
28802
28803
28804
28805
28806 public function getReleaseDate();
28807
28808
28809
28810
28811
28812
28813 public function getStability();
28814
28815
28816
28817
28818
28819
28820
28821 public function getRequires();
28822
28823
28824
28825
28826
28827
28828
28829 public function getConflicts();
28830
28831
28832
28833
28834
28835
28836
28837 public function getProvides();
28838
28839
28840
28841
28842
28843
28844
28845 public function getReplaces();
28846
28847
28848
28849
28850
28851
28852
28853 public function getDevRequires();
28854
28855
28856
28857
28858
28859
28860
28861 public function getSuggests();
28862
28863
28864
28865
28866
28867
28868
28869
28870
28871
28872
28873 public function getAutoload();
28874
28875
28876
28877
28878
28879
28880
28881
28882
28883
28884
28885 public function getDevAutoload();
28886
28887
28888
28889
28890
28891
28892
28893 public function getIncludePaths();
28894
28895
28896
28897
28898
28899
28900 public function setRepository(RepositoryInterface $repository);
28901
28902
28903
28904
28905
28906
28907 public function getRepository();
28908
28909
28910
28911
28912
28913
28914 public function getBinaries();
28915
28916
28917
28918
28919
28920
28921 public function getUniqueName();
28922
28923
28924
28925
28926
28927
28928 public function getNotificationUrl();
28929
28930
28931
28932
28933
28934
28935 public function __toString();
28936
28937
28938
28939
28940
28941
28942 public function getPrettyString();
28943
28944
28945
28946
28947
28948
28949 public function getArchiveExcludes();
28950
28951
28952
28953
28954
28955
28956 public function getTransportOptions();
28957 }
28958 <?php
28959
28960
28961
28962
28963
28964
28965
28966
28967
28968
28969
28970 namespace Composer\Package;
28971
28972
28973
28974
28975 class RootAliasPackage extends AliasPackage implements RootPackageInterface
28976 {
28977 public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
28978 {
28979 parent::__construct($aliasOf, $version, $prettyVersion);
28980 }
28981
28982
28983
28984
28985 public function getAliases()
28986 {
28987 return $this->aliasOf->getAliases();
28988 }
28989
28990
28991
28992
28993 public function getMinimumStability()
28994 {
28995 return $this->aliasOf->getMinimumStability();
28996 }
28997
28998
28999
29000
29001 public function getStabilityFlags()
29002 {
29003 return $this->aliasOf->getStabilityFlags();
29004 }
29005
29006
29007
29008
29009 public function getReferences()
29010 {
29011 return $this->aliasOf->getReferences();
29012 }
29013
29014
29015
29016
29017 public function getPreferStable()
29018 {
29019 return $this->aliasOf->getPreferStable();
29020 }
29021
29022
29023
29024
29025 public function getConfig()
29026 {
29027 return $this->aliasOf->getConfig();
29028 }
29029
29030
29031
29032
29033 public function setRequires(array $require)
29034 {
29035 $this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
29036
29037 $this->aliasOf->setRequires($require);
29038 }
29039
29040
29041
29042
29043 public function setDevRequires(array $devRequire)
29044 {
29045 $this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
29046
29047 $this->aliasOf->setDevRequires($devRequire);
29048 }
29049
29050
29051
29052
29053 public function setConflicts(array $conflicts)
29054 {
29055 $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, 'conflicts');
29056 $this->aliasOf->setConflicts($conflicts);
29057 }
29058
29059
29060
29061
29062 public function setProvides(array $provides)
29063 {
29064 $this->provides = $this->replaceSelfVersionDependencies($provides, 'provides');
29065 $this->aliasOf->setProvides($provides);
29066 }
29067
29068
29069
29070
29071 public function setReplaces(array $replaces)
29072 {
29073 $this->replaces = $this->replaceSelfVersionDependencies($replaces, 'replaces');
29074 $this->aliasOf->setReplaces($replaces);
29075 }
29076
29077
29078
29079
29080 public function setRepositories($repositories)
29081 {
29082 $this->aliasOf->setRepositories($repositories);
29083 }
29084
29085
29086
29087
29088 public function setAutoload(array $autoload)
29089 {
29090 $this->aliasOf->setAutoload($autoload);
29091 }
29092
29093
29094
29095
29096 public function setDevAutoload(array $devAutoload)
29097 {
29098 $this->aliasOf->setDevAutoload($devAutoload);
29099 }
29100
29101
29102
29103
29104 public function setStabilityFlags(array $stabilityFlags)
29105 {
29106 $this->aliasOf->setStabilityFlags($stabilityFlags);
29107 }
29108
29109
29110
29111
29112 public function setSuggests(array $suggests)
29113 {
29114 $this->aliasOf->setSuggests($suggests);
29115 }
29116
29117
29118
29119
29120 public function setExtra(array $extra)
29121 {
29122 $this->aliasOf->setExtra($extra);
29123 }
29124
29125 public function __clone()
29126 {
29127 parent::__clone();
29128 $this->aliasOf = clone $this->aliasOf;
29129 }
29130 }
29131 <?php
29132
29133
29134
29135
29136
29137
29138
29139
29140
29141
29142
29143 namespace Composer\Package;
29144
29145
29146
29147
29148
29149
29150 class RootPackage extends CompletePackage implements RootPackageInterface
29151 {
29152 protected $minimumStability = 'stable';
29153 protected $preferStable = false;
29154 protected $stabilityFlags = array();
29155 protected $config = array();
29156 protected $references = array();
29157 protected $aliases = array();
29158
29159
29160
29161
29162
29163
29164 public function setMinimumStability($minimumStability)
29165 {
29166 $this->minimumStability = $minimumStability;
29167 }
29168
29169
29170
29171
29172 public function getMinimumStability()
29173 {
29174 return $this->minimumStability;
29175 }
29176
29177
29178
29179
29180
29181
29182 public function setStabilityFlags(array $stabilityFlags)
29183 {
29184 $this->stabilityFlags = $stabilityFlags;
29185 }
29186
29187
29188
29189
29190 public function getStabilityFlags()
29191 {
29192 return $this->stabilityFlags;
29193 }
29194
29195
29196
29197
29198
29199
29200 public function setPreferStable($preferStable)
29201 {
29202 $this->preferStable = $preferStable;
29203 }
29204
29205
29206
29207
29208 public function getPreferStable()
29209 {
29210 return $this->preferStable;
29211 }
29212
29213
29214
29215
29216
29217
29218 public function setConfig(array $config)
29219 {
29220 $this->config = $config;
29221 }
29222
29223
29224
29225
29226 public function getConfig()
29227 {
29228 return $this->config;
29229 }
29230
29231
29232
29233
29234
29235
29236 public function setReferences(array $references)
29237 {
29238 $this->references = $references;
29239 }
29240
29241
29242
29243
29244 public function getReferences()
29245 {
29246 return $this->references;
29247 }
29248
29249
29250
29251
29252
29253
29254 public function setAliases(array $aliases)
29255 {
29256 $this->aliases = $aliases;
29257 }
29258
29259
29260
29261
29262 public function getAliases()
29263 {
29264 return $this->aliases;
29265 }
29266 }
29267 <?php
29268
29269
29270
29271
29272
29273
29274
29275
29276
29277
29278
29279 namespace Composer\Package;
29280
29281
29282
29283
29284
29285
29286 interface RootPackageInterface extends CompletePackageInterface
29287 {
29288
29289
29290
29291
29292
29293 public function getAliases();
29294
29295
29296
29297
29298
29299
29300 public function getMinimumStability();
29301
29302
29303
29304
29305
29306
29307
29308
29309 public function getStabilityFlags();
29310
29311
29312
29313
29314
29315
29316
29317
29318 public function getReferences();
29319
29320
29321
29322
29323
29324
29325 public function getPreferStable();
29326
29327
29328
29329
29330
29331
29332 public function getConfig();
29333
29334
29335
29336
29337
29338
29339 public function setRequires(array $requires);
29340
29341
29342
29343
29344
29345
29346 public function setDevRequires(array $devRequires);
29347
29348
29349
29350
29351
29352
29353 public function setConflicts(array $conflicts);
29354
29355
29356
29357
29358
29359
29360 public function setProvides(array $provides);
29361
29362
29363
29364
29365
29366
29367 public function setReplaces(array $replaces);
29368
29369
29370
29371
29372
29373
29374 public function setRepositories($repositories);
29375
29376
29377
29378
29379
29380
29381 public function setAutoload(array $autoload);
29382
29383
29384
29385
29386
29387
29388 public function setDevAutoload(array $devAutoload);
29389
29390
29391
29392
29393
29394
29395 public function setStabilityFlags(array $stabilityFlags);
29396
29397
29398
29399
29400
29401
29402 public function setSuggests(array $suggests);
29403
29404
29405
29406
29407 public function setExtra(array $extra);
29408 }
29409 <?php
29410
29411
29412
29413
29414
29415
29416
29417
29418
29419
29420
29421 namespace Composer\Package\Version;
29422
29423 use Composer\Config;
29424 use Composer\Repository\Vcs\HgDriver;
29425 use Composer\IO\NullIO;
29426 use Composer\Semver\VersionParser as SemverVersionParser;
29427 use Composer\Util\Git as GitUtil;
29428 use Composer\Util\ProcessExecutor;
29429 use Composer\Util\Svn as SvnUtil;
29430
29431
29432
29433
29434
29435
29436
29437 class VersionGuesser
29438 {
29439
29440
29441
29442 private $config;
29443
29444
29445
29446
29447 private $process;
29448
29449
29450
29451
29452 private $versionParser;
29453
29454
29455
29456
29457
29458
29459 public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
29460 {
29461 $this->config = $config;
29462 $this->process = $process;
29463 $this->versionParser = $versionParser;
29464 }
29465
29466
29467
29468
29469
29470
29471
29472 public function guessVersion(array $packageConfig, $path)
29473 {
29474 if (function_exists('proc_open')) {
29475 $versionData = $this->guessGitVersion($packageConfig, $path);
29476 if (null !== $versionData && null !== $versionData['version']) {
29477 return $versionData;
29478 }
29479
29480 $versionData = $this->guessHgVersion($packageConfig, $path);
29481 if (null !== $versionData && null !== $versionData['version']) {
29482 return $versionData;
29483 }
29484
29485 $versionData = $this->guessFossilVersion($packageConfig, $path);
29486 if (null !== $versionData && null !== $versionData['version']) {
29487 return $versionData;
29488 }
29489
29490 return $this->guessSvnVersion($packageConfig, $path);
29491 }
29492 }
29493
29494 private function guessGitVersion(array $packageConfig, $path)
29495 {
29496 GitUtil::cleanEnv();
29497 $commit = null;
29498 $version = null;
29499 $prettyVersion = null;
29500 $isDetached = false;
29501
29502
29503  if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
29504 $branches = array();
29505 $isFeatureBranch = false;
29506
29507
29508  foreach ($this->process->splitLines($output) as $branch) {
29509 if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
29510 if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ' || substr($match[1], 0, 17) === '(HEAD detached at') {
29511 $version = 'dev-' . $match[2];
29512 $prettyVersion = $version;
29513 $isFeatureBranch = true;
29514 $isDetached = true;
29515 } else {
29516 $version = $this->versionParser->normalizeBranch($match[1]);
29517 $prettyVersion = 'dev-' . $match[1];
29518 $isFeatureBranch = 0 === strpos($version, 'dev-');
29519 if ('9999999-dev' === $version) {
29520 $version = $prettyVersion;
29521 }
29522 }
29523
29524 if ($match[2]) {
29525 $commit = $match[2];
29526 }
29527 }
29528
29529 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
29530 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
29531 $branches[] = $match[1];
29532 }
29533 }
29534 }
29535
29536 if ($isFeatureBranch) {
29537
29538  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
29539 $version = $result['version'];
29540 $prettyVersion = $result['pretty_version'];
29541 }
29542 }
29543
29544 if (!$version || $isDetached) {
29545 $result = $this->versionFromGitTags($path);
29546 if ($result) {
29547 $version = $result['version'];
29548 $prettyVersion = $result['pretty_version'];
29549 }
29550 }
29551
29552 if (!$commit) {
29553 $command = 'git log --pretty="%H" -n1 HEAD';
29554 if (0 === $this->process->execute($command, $output, $path)) {
29555 $commit = trim($output) ?: null;
29556 }
29557 }
29558
29559 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion);
29560 }
29561
29562 private function versionFromGitTags($path)
29563 {
29564
29565  if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
29566 try {
29567 $version = $this->versionParser->normalize(trim($output));
29568
29569 return array('version' => $version, 'pretty_version' => trim($output));
29570 } catch (\Exception $e) {
29571 }
29572 }
29573
29574 return null;
29575 }
29576
29577 private function guessHgVersion(array $packageConfig, $path)
29578 {
29579
29580  if (0 === $this->process->execute('hg branch', $output, $path)) {
29581 $branch = trim($output);
29582 $version = $this->versionParser->normalizeBranch($branch);
29583 $isFeatureBranch = 0 === strpos($version, 'dev-');
29584
29585 if ('9999999-dev' === $version) {
29586 $version = 'dev-' . $branch;
29587 }
29588
29589 if (!$isFeatureBranch) {
29590 return array('version' => $version, 'commit' => null, 'pretty_version' => $version);
29591 }
29592
29593
29594  $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process);
29595 $branches = array_keys($driver->getBranches());
29596
29597
29598  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
29599 $result['commit'] = '';
29600
29601 return $result;
29602 }
29603 }
29604
29605 private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path)
29606 {
29607 $prettyVersion = $version;
29608
29609
29610  
29611  if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version]))
29612 || strpos(json_encode($packageConfig), '"self.version"')
29613 ) {
29614 $branch = preg_replace('{^dev-}', '', $version);
29615 $length = PHP_INT_MAX;
29616
29617 $nonFeatureBranches = '';
29618 if (!empty($packageConfig['non-feature-branches'])) {
29619 $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
29620 }
29621
29622 foreach ($branches as $candidate) {
29623
29624  if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
29625 break;
29626 }
29627
29628
29629  if ($candidate === $branch || !preg_match('{^(' . $nonFeatureBranches . '|master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
29630 continue;
29631 }
29632
29633 $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
29634 if (0 !== $this->process->execute($cmdLine, $output, $path)) {
29635 continue;
29636 }
29637
29638 if (strlen($output) < $length) {
29639 $length = strlen($output);
29640 $version = $this->versionParser->normalizeBranch($candidate);
29641 $prettyVersion = 'dev-' . $match[1];
29642 if ('9999999-dev' === $version) {
29643 $version = $prettyVersion;
29644 }
29645 }
29646 }
29647 }
29648
29649 return array('version' => $version, 'pretty_version' => $prettyVersion);
29650 }
29651
29652 private function guessFossilVersion(array $packageConfig, $path)
29653 {
29654 $version = null;
29655 $prettyVersion = null;
29656
29657
29658  if (0 === $this->process->execute('fossil branch list', $output, $path)) {
29659 $branch = trim($output);
29660 $version = $this->versionParser->normalizeBranch($branch);
29661 $prettyVersion = 'dev-' . $branch;
29662
29663 if ('9999999-dev' === $version) {
29664 $version = $prettyVersion;
29665 }
29666 }
29667
29668
29669  if (0 === $this->process->execute('fossil tag list', $output, $path)) {
29670 try {
29671 $version = $this->versionParser->normalize(trim($output));
29672 $prettyVersion = trim($output);
29673 } catch (\Exception $e) {
29674 }
29675 }
29676
29677 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
29678 }
29679
29680 private function guessSvnVersion(array $packageConfig, $path)
29681 {
29682 SvnUtil::cleanEnv();
29683
29684
29685  if (0 === $this->process->execute('svn info --xml', $output, $path)) {
29686 $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
29687 $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
29688 $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
29689
29690 $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
29691
29692 if (preg_match($urlPattern, $output, $matches)) {
29693 if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
29694
29695  $version = $this->versionParser->normalizeBranch($matches[3]);
29696 $prettyVersion = 'dev-' . $matches[3];
29697 if ('9999999-dev' === $version) {
29698 $version = $prettyVersion;
29699 }
29700
29701 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
29702 }
29703
29704 $prettyVersion = trim($matches[1]);
29705 $version = $this->versionParser->normalize($prettyVersion);
29706
29707 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
29708 }
29709 }
29710 }
29711 }
29712 <?php
29713
29714
29715
29716
29717
29718
29719
29720
29721
29722
29723
29724 namespace Composer\Package\Version;
29725
29726 use Composer\Semver\VersionParser as SemverVersionParser;
29727
29728 class VersionParser extends SemverVersionParser
29729 {
29730 private static $constraints = array();
29731
29732
29733
29734
29735 public function parseConstraints($constraints)
29736 {
29737 if (!isset(self::$constraints[$constraints])) {
29738 self::$constraints[$constraints] = parent::parseConstraints($constraints);
29739 }
29740
29741 return self::$constraints[$constraints];
29742 }
29743
29744
29745
29746
29747
29748
29749
29750
29751
29752
29753
29754 public function parseNameVersionPairs(array $pairs)
29755 {
29756 $pairs = array_values($pairs);
29757 $result = array();
29758
29759 for ($i = 0, $count = count($pairs); $i < $count; $i++) {
29760 $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
29761 if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/')) {
29762 $pair .= ' '.$pairs[$i + 1];
29763 $i++;
29764 }
29765
29766 if (strpos($pair, ' ')) {
29767 list($name, $version) = explode(" ", $pair, 2);
29768 $result[] = array('name' => $name, 'version' => $version);
29769 } else {
29770 $result[] = array('name' => $pair);
29771 }
29772 }
29773
29774 return $result;
29775 }
29776 }
29777 <?php
29778
29779
29780
29781
29782
29783
29784
29785
29786
29787
29788
29789 namespace Composer\Package\Version;
29790
29791 use Composer\DependencyResolver\Pool;
29792 use Composer\Package\BasePackage;
29793 use Composer\Package\PackageInterface;
29794 use Composer\Package\Loader\ArrayLoader;
29795 use Composer\Package\Dumper\ArrayDumper;
29796 use Composer\Semver\Constraint\Constraint;
29797
29798
29799
29800
29801
29802
29803
29804 class VersionSelector
29805 {
29806 private $pool;
29807
29808 private $parser;
29809
29810 public function __construct(Pool $pool)
29811 {
29812 $this->pool = $pool;
29813 }
29814
29815
29816
29817
29818
29819
29820
29821
29822
29823
29824
29825 public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
29826 {
29827 $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
29828 $candidates = $this->pool->whatProvides(strtolower($packageName), $constraint, true);
29829
29830 if ($targetPhpVersion) {
29831 $phpConstraint = new Constraint('==', $this->getParser()->normalize($targetPhpVersion));
29832 $candidates = array_filter($candidates, function ($pkg) use ($phpConstraint) {
29833 $reqs = $pkg->getRequires();
29834
29835 return !isset($reqs['php']) || $reqs['php']->getConstraint()->matches($phpConstraint);
29836 });
29837 }
29838
29839 if (!$candidates) {
29840 return false;
29841 }
29842
29843
29844  $package = reset($candidates);
29845 $minPriority = BasePackage::$stabilities[$preferredStability];
29846 foreach ($candidates as $candidate) {
29847 $candidatePriority = $candidate->getStabilityPriority();
29848 $currentPriority = $package->getStabilityPriority();
29849
29850
29851  
29852  if ($minPriority < $candidatePriority && $currentPriority < $candidatePriority) {
29853 continue;
29854 }
29855
29856
29857  
29858  if ($minPriority < $candidatePriority && $candidatePriority < $currentPriority) {
29859 $package = $candidate;
29860 continue;
29861 }
29862
29863
29864  
29865  if ($minPriority >= $candidatePriority && $minPriority < $currentPriority) {
29866 $package = $candidate;
29867 continue;
29868 }
29869
29870
29871  if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) {
29872 $package = $candidate;
29873 }
29874 }
29875
29876 return $package;
29877 }
29878
29879
29880
29881
29882
29883
29884
29885
29886
29887
29888
29889
29890
29891
29892
29893
29894 public function findRecommendedRequireVersion(PackageInterface $package)
29895 {
29896 $version = $package->getVersion();
29897 if (!$package->isDev()) {
29898 return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
29899 }
29900
29901 $loader = new ArrayLoader($this->getParser());
29902 $dumper = new ArrayDumper();
29903 $extra = $loader->getBranchAlias($dumper->dump($package));
29904 if ($extra) {
29905 $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
29906 if ($count) {
29907 $extra = str_replace('.9999999', '.0', $extra);
29908
29909 return $this->transformVersion($extra, $extra, 'dev');
29910 }
29911 }
29912
29913 return $package->getPrettyVersion();
29914 }
29915
29916 private function transformVersion($version, $prettyVersion, $stability)
29917 {
29918
29919  
29920  $semanticVersionParts = explode('.', $version);
29921
29922
29923  if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
29924
29925  if ($semanticVersionParts[0] === '0') {
29926 unset($semanticVersionParts[3]);
29927 } else {
29928 unset($semanticVersionParts[2], $semanticVersionParts[3]);
29929 }
29930 $version = implode('.', $semanticVersionParts);
29931 } else {
29932 return $prettyVersion;
29933 }
29934
29935
29936  if ($stability != 'stable') {
29937 $version .= '@'.$stability;
29938 }
29939
29940
29941  return '^' . $version;
29942 }
29943
29944 private function getParser()
29945 {
29946 if ($this->parser === null) {
29947 $this->parser = new VersionParser();
29948 }
29949
29950 return $this->parser;
29951 }
29952 }
29953 <?php
29954
29955
29956
29957
29958
29959
29960
29961
29962
29963
29964
29965 namespace Composer\Plugin\Capability;
29966
29967
29968
29969
29970
29971
29972
29973 interface Capability
29974 {
29975 }
29976 <?php
29977
29978
29979
29980
29981
29982
29983
29984
29985
29986
29987
29988 namespace Composer\Plugin\Capability;
29989
29990
29991
29992
29993
29994
29995
29996
29997
29998
29999
30000 interface CommandProvider extends Capability
30001 {
30002
30003
30004
30005
30006
30007 public function getCommands();
30008 }
30009 <?php
30010
30011
30012
30013
30014
30015
30016
30017
30018
30019
30020
30021 namespace Composer\Plugin;
30022
30023
30024
30025
30026
30027
30028
30029
30030 interface Capable
30031 {
30032
30033
30034
30035
30036
30037
30038
30039
30040
30041
30042
30043
30044
30045
30046
30047
30048
30049
30050 public function getCapabilities();
30051 }
30052 <?php
30053
30054
30055
30056
30057
30058
30059
30060
30061
30062
30063
30064 namespace Composer\Plugin;
30065
30066 use Composer\EventDispatcher\Event;
30067 use Symfony\Component\Console\Input\InputInterface;
30068 use Symfony\Component\Console\Output\OutputInterface;
30069
30070
30071
30072
30073
30074
30075 class CommandEvent extends Event
30076 {
30077
30078
30079
30080 private $commandName;
30081
30082
30083
30084
30085 private $input;
30086
30087
30088
30089
30090 private $output;
30091
30092
30093
30094
30095
30096
30097
30098
30099
30100
30101
30102 public function __construct($name, $commandName, $input, $output, array $args = array(), array $flags = array())
30103 {
30104 parent::__construct($name, $args, $flags);
30105 $this->commandName = $commandName;
30106 $this->input = $input;
30107 $this->output = $output;
30108 }
30109
30110
30111
30112
30113
30114
30115 public function getInput()
30116 {
30117 return $this->input;
30118 }
30119
30120
30121
30122
30123
30124
30125 public function getOutput()
30126 {
30127 return $this->output;
30128 }
30129
30130
30131
30132
30133
30134
30135 public function getCommandName()
30136 {
30137 return $this->commandName;
30138 }
30139 }
30140 <?php
30141
30142
30143
30144
30145
30146
30147
30148
30149
30150
30151
30152 namespace Composer\Plugin;
30153
30154
30155
30156
30157
30158
30159 class PluginEvents
30160 {
30161
30162
30163
30164
30165
30166
30167
30168
30169 const INIT = 'init';
30170
30171
30172
30173
30174
30175
30176
30177
30178
30179 const COMMAND = 'command';
30180
30181
30182
30183
30184
30185
30186
30187
30188
30189 const PRE_FILE_DOWNLOAD = 'pre-file-download';
30190 }
30191 <?php
30192
30193
30194
30195
30196
30197
30198
30199
30200
30201
30202
30203 namespace Composer\Plugin;
30204
30205 use Composer\Composer;
30206 use Composer\IO\IOInterface;
30207
30208
30209
30210
30211
30212
30213 interface PluginInterface
30214 {
30215
30216
30217
30218
30219
30220 const PLUGIN_API_VERSION = '1.1.0';
30221
30222
30223
30224
30225
30226
30227
30228 public function activate(Composer $composer, IOInterface $io);
30229 }
30230 <?php
30231
30232
30233
30234
30235
30236
30237
30238
30239
30240
30241
30242 namespace Composer\Plugin;
30243
30244 use Composer\Composer;
30245 use Composer\EventDispatcher\EventSubscriberInterface;
30246 use Composer\IO\IOInterface;
30247 use Composer\Package\Package;
30248 use Composer\Package\Version\VersionParser;
30249 use Composer\Repository\RepositoryInterface;
30250 use Composer\Package\AliasPackage;
30251 use Composer\Package\PackageInterface;
30252 use Composer\Package\Link;
30253 use Composer\Semver\Constraint\Constraint;
30254 use Composer\DependencyResolver\Pool;
30255 use Composer\Plugin\Capability\Capability;
30256
30257
30258
30259
30260
30261
30262
30263 class PluginManager
30264 {
30265 protected $composer;
30266 protected $io;
30267 protected $globalComposer;
30268 protected $versionParser;
30269 protected $disablePlugins = false;
30270
30271 protected $plugins = array();
30272 protected $registeredPlugins = array();
30273
30274 private static $classCounter = 0;
30275
30276
30277
30278
30279
30280
30281
30282
30283
30284 public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
30285 {
30286 $this->io = $io;
30287 $this->composer = $composer;
30288 $this->globalComposer = $globalComposer;
30289 $this->versionParser = new VersionParser();
30290 $this->disablePlugins = $disablePlugins;
30291 }
30292
30293
30294
30295
30296 public function loadInstalledPlugins()
30297 {
30298 if ($this->disablePlugins) {
30299 return;
30300 }
30301
30302 $repo = $this->composer->getRepositoryManager()->getLocalRepository();
30303 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
30304 if ($repo) {
30305 $this->loadRepository($repo);
30306 }
30307 if ($globalRepo) {
30308 $this->loadRepository($globalRepo);
30309 }
30310 }
30311
30312
30313
30314
30315
30316
30317 public function getPlugins()
30318 {
30319 return $this->plugins;
30320 }
30321
30322
30323
30324
30325
30326
30327 public function getGlobalComposer()
30328 {
30329 return $this->globalComposer;
30330 }
30331
30332
30333
30334
30335
30336
30337
30338
30339
30340
30341
30342
30343 public function registerPackage(PackageInterface $package, $failOnMissingClasses = false)
30344 {
30345 if ($this->disablePlugins) {
30346 return;
30347 }
30348
30349 if ($package->getType() === 'composer-plugin') {
30350 $requiresComposer = null;
30351 foreach ($package->getRequires() as $link) { 
30352 if ('composer-plugin-api' === $link->getTarget()) {
30353 $requiresComposer = $link->getConstraint();
30354 break;
30355 }
30356 }
30357
30358 if (!$requiresComposer) {
30359 throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
30360 }
30361
30362 $currentPluginApiVersion = $this->getPluginApiVersion();
30363 $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
30364
30365 if ($requiresComposer->getPrettyString() === '1.0.0' && $this->getPluginApiVersion() === '1.0.0') {
30366 $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>');
30367 } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) {
30368 $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>');
30369
30370 return;
30371 }
30372 }
30373
30374 $oldInstallerPlugin = ($package->getType() === 'composer-installer');
30375
30376 if (in_array($package->getName(), $this->registeredPlugins)) {
30377 return;
30378 }
30379
30380 $extra = $package->getExtra();
30381 if (empty($extra['class'])) {
30382 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
30383 }
30384 $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
30385
30386 $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
30387 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
30388
30389 $pool = new Pool('dev');
30390 $pool->addRepository($localRepo);
30391 if ($globalRepo) {
30392 $pool->addRepository($globalRepo);
30393 }
30394
30395 $autoloadPackages = array($package->getName() => $package);
30396 $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package);
30397
30398 $generator = $this->composer->getAutoloadGenerator();
30399 $autoloads = array();
30400 foreach ($autoloadPackages as $autoloadPackage) {
30401 $downloadPath = $this->getInstallPath($autoloadPackage, ($globalRepo && $globalRepo->hasPackage($autoloadPackage)));
30402 $autoloads[] = array($autoloadPackage, $downloadPath);
30403 }
30404
30405 $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0'));
30406 $classLoader = $generator->createLoader($map);
30407 $classLoader->register();
30408
30409 foreach ($classes as $class) {
30410 if (class_exists($class, false)) {
30411 $class = trim($class, '\\');
30412 $path = $classLoader->findFile($class);
30413 $code = file_get_contents($path);
30414 $separatorPos = strrpos($class, '\\');
30415 $className = $class;
30416 if ($separatorPos) {
30417 $className = substr($class, $separatorPos + 1);
30418 }
30419 $code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
30420 $code = str_replace('__FILE__', var_export($path, true), $code);
30421 $code = str_replace('__DIR__', var_export(dirname($path), true), $code);
30422 $code = str_replace('__CLASS__', var_export($class, true), $code);
30423 $code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
30424 eval($code);
30425 $class .= '_composer_tmp'.self::$classCounter;
30426 self::$classCounter++;
30427 }
30428
30429 if ($oldInstallerPlugin) {
30430 $installer = new $class($this->io, $this->composer);
30431 $this->composer->getInstallationManager()->addInstaller($installer);
30432 } elseif (class_exists($class)) {
30433 $plugin = new $class();
30434 $this->addPlugin($plugin);
30435 $this->registeredPlugins[] = $package->getName();
30436 } elseif ($failOnMissingClasses) {
30437 throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
30438 }
30439 }
30440 }
30441
30442
30443
30444
30445
30446
30447 protected function getPluginApiVersion()
30448 {
30449 return PluginInterface::PLUGIN_API_VERSION;
30450 }
30451
30452
30453
30454
30455
30456
30457
30458
30459
30460
30461 public function addPlugin(PluginInterface $plugin)
30462 {
30463 $this->io->writeError('Loading plugin '.get_class($plugin), true, IOInterface::DEBUG);
30464 $this->plugins[] = $plugin;
30465 $plugin->activate($this->composer, $this->io);
30466
30467 if ($plugin instanceof EventSubscriberInterface) {
30468 $this->composer->getEventDispatcher()->addSubscriber($plugin);
30469 }
30470 }
30471
30472
30473
30474
30475
30476
30477
30478
30479
30480
30481
30482
30483 private function loadRepository(RepositoryInterface $repo)
30484 {
30485 foreach ($repo->getPackages() as $package) { 
30486 if ($package instanceof AliasPackage) {
30487 continue;
30488 }
30489 if ('composer-plugin' === $package->getType()) {
30490 $this->registerPackage($package);
30491
30492  } elseif ('composer-installer' === $package->getType()) {
30493 $this->registerPackage($package);
30494 }
30495 }
30496 }
30497
30498
30499
30500
30501
30502
30503
30504
30505
30506
30507 private function collectDependencies(Pool $pool, array $collected, PackageInterface $package)
30508 {
30509 $requires = array_merge(
30510 $package->getRequires(),
30511 $package->getDevRequires()
30512 );
30513
30514 foreach ($requires as $requireLink) {
30515 $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink);
30516 if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) {
30517 $collected[$requiredPackage->getName()] = $requiredPackage;
30518 $collected = $this->collectDependencies($pool, $collected, $requiredPackage);
30519 }
30520 }
30521
30522 return $collected;
30523 }
30524
30525
30526
30527
30528
30529
30530
30531
30532
30533
30534
30535 private function lookupInstalledPackage(Pool $pool, Link $link)
30536 {
30537 $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint());
30538
30539 return (!empty($packages)) ? $packages[0] : null;
30540 }
30541
30542
30543
30544
30545
30546
30547
30548
30549
30550 private function getInstallPath(PackageInterface $package, $global = false)
30551 {
30552 if (!$global) {
30553 return $this->composer->getInstallationManager()->getInstallPath($package);
30554 }
30555
30556 return $this->globalComposer->getInstallationManager()->getInstallPath($package);
30557 }
30558
30559
30560
30561
30562
30563
30564
30565 protected function getCapabilityImplementationClassName(PluginInterface $plugin, $capability)
30566 {
30567 if (!($plugin instanceof Capable)) {
30568 return null;
30569 }
30570
30571 $capabilities = (array) $plugin->getCapabilities();
30572
30573 if (!empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability])) {
30574 return trim($capabilities[$capability]);
30575 }
30576
30577 if (
30578 array_key_exists($capability, $capabilities)
30579 && (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))
30580 ) {
30581 throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], 1));
30582 }
30583 }
30584
30585
30586
30587
30588
30589
30590
30591
30592
30593 public function getPluginCapability(PluginInterface $plugin, $capabilityClassName, array $ctorArgs = array())
30594 {
30595 if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) {
30596 if (!class_exists($capabilityClass)) {
30597 throw new \RuntimeException("Cannot instantiate Capability, as class $capabilityClass from plugin ".get_class($plugin)." does not exist.");
30598 }
30599
30600 $ctorArgs['plugin'] = $plugin;
30601 $capabilityObj = new $capabilityClass($ctorArgs);
30602
30603
30604  if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) {
30605 throw new \RuntimeException(
30606 'Class ' . $capabilityClass . ' must implement both Composer\Plugin\Capability\Capability and '. $capabilityClassName . '.'
30607 );
30608 }
30609
30610 return $capabilityObj;
30611 }
30612 }
30613
30614
30615
30616
30617
30618
30619
30620
30621 public function getPluginCapabilities($capabilityClassName, array $ctorArgs = array())
30622 {
30623 $capabilities = array();
30624 foreach ($this->getPlugins() as $plugin) {
30625 if ($capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs)) {
30626 $capabilities[] = $capability;
30627 }
30628 }
30629
30630 return $capabilities;
30631 }
30632 }
30633 <?php
30634
30635
30636
30637
30638
30639
30640
30641
30642
30643
30644
30645 namespace Composer\Plugin;
30646
30647 use Composer\EventDispatcher\Event;
30648 use Composer\Util\RemoteFilesystem;
30649
30650
30651
30652
30653
30654
30655 class PreFileDownloadEvent extends Event
30656 {
30657
30658
30659
30660 private $rfs;
30661
30662
30663
30664
30665 private $processedUrl;
30666
30667
30668
30669
30670
30671
30672
30673
30674 public function __construct($name, RemoteFilesystem $rfs, $processedUrl)
30675 {
30676 parent::__construct($name);
30677 $this->rfs = $rfs;
30678 $this->processedUrl = $processedUrl;
30679 }
30680
30681
30682
30683
30684
30685
30686 public function getRemoteFilesystem()
30687 {
30688 return $this->rfs;
30689 }
30690
30691
30692
30693
30694
30695
30696 public function setRemoteFilesystem(RemoteFilesystem $rfs)
30697 {
30698 $this->rfs = $rfs;
30699 }
30700
30701
30702
30703
30704
30705
30706 public function getProcessedUrl()
30707 {
30708 return $this->processedUrl;
30709 }
30710 }
30711 <?php
30712
30713
30714
30715
30716
30717
30718
30719
30720
30721
30722
30723 namespace Composer\Question;
30724
30725 use Symfony\Component\Console\Exception\InvalidArgumentException;
30726 use Symfony\Component\Console\Question\Question;
30727
30728
30729
30730
30731
30732
30733
30734
30735 class StrictConfirmationQuestion extends Question
30736 {
30737 private $trueAnswerRegex;
30738 private $falseAnswerRegex;
30739
30740
30741
30742
30743
30744
30745
30746
30747
30748 public function __construct($question, $default = true, $trueAnswerRegex = '/^y(?:es)?$/i', $falseAnswerRegex = '/^no?$/i')
30749 {
30750 parent::__construct($question, (bool) $default);
30751
30752 $this->trueAnswerRegex = $trueAnswerRegex;
30753 $this->falseAnswerRegex = $falseAnswerRegex;
30754 $this->setNormalizer($this->getDefaultNormalizer());
30755 $this->setValidator($this->getDefaultValidator());
30756 }
30757
30758
30759
30760
30761
30762
30763 private function getDefaultNormalizer()
30764 {
30765 $default = $this->getDefault();
30766 $trueRegex = $this->trueAnswerRegex;
30767 $falseRegex = $this->falseAnswerRegex;
30768
30769 return function ($answer) use ($default, $trueRegex, $falseRegex) {
30770 if (is_bool($answer)) {
30771 return $answer;
30772 }
30773 if (empty($answer) && !empty($default)) {
30774 return $default;
30775 }
30776
30777 if (preg_match($trueRegex, $answer)) {
30778 return true;
30779 }
30780
30781 if (preg_match($falseRegex, $answer)) {
30782 return false;
30783 }
30784
30785 return null;
30786 };
30787 }
30788
30789
30790
30791
30792
30793
30794 private function getDefaultValidator()
30795 {
30796 return function ($answer) {
30797 if (!is_bool($answer)) {
30798 throw new InvalidArgumentException('Please answer yes, y, no, or n.');
30799 }
30800
30801 return $answer;
30802 };
30803 }
30804 }
30805 <?php
30806
30807
30808
30809
30810
30811
30812
30813
30814
30815
30816
30817 namespace Composer\Repository;
30818
30819 use Composer\Package\AliasPackage;
30820 use Composer\Package\PackageInterface;
30821 use Composer\Package\CompletePackageInterface;
30822 use Composer\Package\Version\VersionParser;
30823 use Composer\Semver\Constraint\ConstraintInterface;
30824 use Composer\Semver\Constraint\Constraint;
30825
30826
30827
30828
30829
30830
30831 class ArrayRepository extends BaseRepository
30832 {
30833
30834 protected $packages;
30835
30836 public function __construct(array $packages = array())
30837 {
30838 foreach ($packages as $package) {
30839 $this->addPackage($package);
30840 }
30841 }
30842
30843
30844
30845
30846 public function findPackage($name, $constraint)
30847 {
30848 $name = strtolower($name);
30849
30850 if (!$constraint instanceof ConstraintInterface) {
30851 $versionParser = new VersionParser();
30852 $constraint = $versionParser->parseConstraints($constraint);
30853 }
30854
30855 foreach ($this->getPackages() as $package) {
30856 if ($name === $package->getName()) {
30857 $pkgConstraint = new Constraint('==', $package->getVersion());
30858 if ($constraint->matches($pkgConstraint)) {
30859 return $package;
30860 }
30861 }
30862 }
30863
30864 return null;
30865 }
30866
30867
30868
30869
30870 public function findPackages($name, $constraint = null)
30871 {
30872
30873  $name = strtolower($name);
30874 $packages = array();
30875
30876 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
30877 $versionParser = new VersionParser();
30878 $constraint = $versionParser->parseConstraints($constraint);
30879 }
30880
30881 foreach ($this->getPackages() as $package) {
30882 if ($name === $package->getName()) {
30883 $pkgConstraint = new Constraint('==', $package->getVersion());
30884 if (null === $constraint || $constraint->matches($pkgConstraint)) {
30885 $packages[] = $package;
30886 }
30887 }
30888 }
30889
30890 return $packages;
30891 }
30892
30893
30894
30895
30896 public function search($query, $mode = 0, $type = null)
30897 {
30898 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
30899
30900 $matches = array();
30901 foreach ($this->getPackages() as $package) {
30902 $name = $package->getName();
30903 if (isset($matches[$name])) {
30904 continue;
30905 }
30906 if (preg_match($regex, $name)
30907 || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
30908 ) {
30909 if (null !== $type && $package->getType() !== $type) {
30910 continue;
30911 }
30912
30913 $matches[$name] = array(
30914 'name' => $package->getPrettyName(),
30915 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null,
30916 );
30917 }
30918 }
30919
30920 return array_values($matches);
30921 }
30922
30923
30924
30925
30926 public function hasPackage(PackageInterface $package)
30927 {
30928 $packageId = $package->getUniqueName();
30929
30930 foreach ($this->getPackages() as $repoPackage) {
30931 if ($packageId === $repoPackage->getUniqueName()) {
30932 return true;
30933 }
30934 }
30935
30936 return false;
30937 }
30938
30939
30940
30941
30942
30943
30944 public function addPackage(PackageInterface $package)
30945 {
30946 if (null === $this->packages) {
30947 $this->initialize();
30948 }
30949 $package->setRepository($this);
30950 $this->packages[] = $package;
30951
30952 if ($package instanceof AliasPackage) {
30953 $aliasedPackage = $package->getAliasOf();
30954 if (null === $aliasedPackage->getRepository()) {
30955 $this->addPackage($aliasedPackage);
30956 }
30957 }
30958 }
30959
30960 protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
30961 {
30962 return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
30963 }
30964
30965
30966
30967
30968
30969
30970 public function removePackage(PackageInterface $package)
30971 {
30972 $packageId = $package->getUniqueName();
30973
30974 foreach ($this->getPackages() as $key => $repoPackage) {
30975 if ($packageId === $repoPackage->getUniqueName()) {
30976 array_splice($this->packages, $key, 1);
30977
30978 return;
30979 }
30980 }
30981 }
30982
30983
30984
30985
30986 public function getPackages()
30987 {
30988 if (null === $this->packages) {
30989 $this->initialize();
30990 }
30991
30992 return $this->packages;
30993 }
30994
30995
30996
30997
30998
30999
31000 public function count()
31001 {
31002 return count($this->packages);
31003 }
31004
31005
31006
31007
31008 protected function initialize()
31009 {
31010 $this->packages = array();
31011 }
31012 }
31013 <?php
31014
31015
31016
31017
31018
31019
31020
31021
31022
31023
31024
31025 namespace Composer\Repository;
31026
31027 use Composer\IO\IOInterface;
31028 use Composer\Json\JsonFile;
31029 use Composer\Package\Loader\ArrayLoader;
31030 use Composer\Package\Loader\LoaderInterface;
31031
31032
31033
31034
31035 class ArtifactRepository extends ArrayRepository implements ConfigurableRepositoryInterface
31036 {
31037
31038 protected $loader;
31039
31040 protected $lookup;
31041 protected $repoConfig;
31042 private $io;
31043
31044 public function __construct(array $repoConfig, IOInterface $io)
31045 {
31046 parent::__construct();
31047 if (!extension_loaded('zip')) {
31048 throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
31049 }
31050
31051 $this->loader = new ArrayLoader();
31052 $this->lookup = $repoConfig['url'];
31053 $this->io = $io;
31054 $this->repoConfig = $repoConfig;
31055 }
31056
31057 public function getRepoConfig()
31058 {
31059 return $this->repoConfig;
31060 }
31061
31062 protected function initialize()
31063 {
31064 parent::initialize();
31065
31066 $this->scanDirectory($this->lookup);
31067 }
31068
31069 private function scanDirectory($path)
31070 {
31071 $io = $this->io;
31072
31073 $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
31074 $iterator = new \RecursiveIteratorIterator($directory);
31075 $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i');
31076 foreach ($regex as $file) {
31077
31078 if (!$file->isFile()) {
31079 continue;
31080 }
31081
31082 $package = $this->getComposerInformation($file);
31083 if (!$package) {
31084 $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", true, IOInterface::VERBOSE);
31085 continue;
31086 }
31087
31088 $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
31089 $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), true, IOInterface::VERBOSE);
31090
31091 $this->addPackage($package);
31092 }
31093 }
31094
31095
31096
31097
31098
31099
31100
31101
31102 private function locateFile(\ZipArchive $zip, $filename)
31103 {
31104 $indexOfShortestMatch = false;
31105 $lengthOfShortestMatch = -1;
31106
31107 for ($i = 0; $i < $zip->numFiles; $i++) {
31108 $stat = $zip->statIndex($i);
31109 if (strcmp(basename($stat['name']), $filename) === 0) {
31110 $directoryName = dirname($stat['name']);
31111 if ($directoryName == '.') {
31112
31113  
31114  return $i;
31115 }
31116
31117 if (strpos($directoryName, '\\') !== false ||
31118 strpos($directoryName, '/') !== false) {
31119
31120  continue;
31121 }
31122
31123 $length = strlen($stat['name']);
31124 if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) {
31125
31126  $contents = $zip->getFromIndex($i);
31127 if ($contents !== false) {
31128 $indexOfShortestMatch = $i;
31129 $lengthOfShortestMatch = $length;
31130 }
31131 }
31132 }
31133 }
31134
31135 return $indexOfShortestMatch;
31136 }
31137
31138 private function getComposerInformation(\SplFileInfo $file)
31139 {
31140 $zip = new \ZipArchive();
31141 $zip->open($file->getPathname());
31142
31143 if (0 == $zip->numFiles) {
31144 return false;
31145 }
31146
31147 $foundFileIndex = $this->locateFile($zip, 'composer.json');
31148 if (false === $foundFileIndex) {
31149 return false;
31150 }
31151
31152 $configurationFileName = $zip->getNameIndex($foundFileIndex);
31153
31154 $composerFile = "zip://{$file->getPathname()}#$configurationFileName";
31155 $json = file_get_contents($composerFile);
31156
31157 $package = JsonFile::parseJson($json, $composerFile);
31158 $package['dist'] = array(
31159 'type' => 'zip',
31160 'url' => strtr($file->getPathname(), '\\', '/'),
31161 'shasum' => sha1_file($file->getRealPath()),
31162 );
31163
31164 try {
31165 $package = $this->loader->load($package);
31166 } catch (\UnexpectedValueException $e) {
31167 throw new \UnexpectedValueException('Failed loading package in '.$file.': '.$e->getMessage(), 0, $e);
31168 }
31169
31170 return $package;
31171 }
31172 }
31173 <?php
31174
31175
31176
31177
31178
31179
31180
31181
31182
31183
31184
31185 namespace Composer\Repository;
31186
31187 use Composer\Package\RootPackageInterface;
31188 use Composer\Semver\Constraint\ConstraintInterface;
31189 use Composer\Semver\Constraint\Constraint;
31190 use Composer\Package\Link;
31191
31192
31193
31194
31195
31196
31197 abstract class BaseRepository implements RepositoryInterface
31198 {
31199
31200
31201
31202
31203
31204
31205
31206
31207
31208
31209
31210
31211
31212 public function getDependents($needle, $constraint = null, $invert = false, $recurse = true, $packagesFound = null)
31213 {
31214 $needles = (array) $needle;
31215 $results = array();
31216
31217
31218  if (null === $packagesFound) {
31219 $packagesFound = $needles;
31220 }
31221
31222
31223  $rootPackage = null;
31224 foreach ($this->getPackages() as $package) {
31225 if ($package instanceof RootPackageInterface) {
31226 $rootPackage = $package;
31227 break;
31228 }
31229 }
31230
31231
31232  foreach ($this->getPackages() as $package) {
31233 $links = $package->getRequires();
31234
31235
31236  
31237  $packagesInTree = $packagesFound;
31238
31239
31240  if (!$invert) {
31241 $links += $package->getReplaces();
31242 }
31243
31244
31245  if ($package instanceof RootPackageInterface) {
31246 $links += $package->getDevRequires();
31247 }
31248
31249
31250  foreach ($links as $link) {
31251 foreach ($needles as $needle) {
31252 if ($link->getTarget() === $needle) {
31253 if (is_null($constraint) || (($link->getConstraint()->matches($constraint) === !$invert))) {
31254
31255  if (in_array($link->getSource(), $packagesInTree)) {
31256 $results[$link->getSource()] = array($package, $link, false);
31257 continue;
31258 }
31259 $packagesInTree[] = $link->getSource();
31260 $dependents = $recurse ? $this->getDependents($link->getSource(), null, false, true, $packagesInTree) : array();
31261 $results[$link->getSource()] = array($package, $link, $dependents);
31262 }
31263 }
31264 }
31265 }
31266
31267
31268  if ($invert && in_array($package->getName(), $needles)) {
31269 foreach ($package->getConflicts() as $link) {
31270 foreach ($this->findPackages($link->getTarget()) as $pkg) {
31271 $version = new Constraint('=', $pkg->getVersion());
31272 if ($link->getConstraint()->matches($version) === $invert) {
31273 $results[] = array($package, $link, false);
31274 }
31275 }
31276 }
31277 }
31278
31279
31280  if ($invert && $constraint && in_array($package->getName(), $needles) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
31281 foreach ($package->getRequires() as $link) {
31282 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
31283 if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
31284 continue;
31285 }
31286
31287 $platformPkg = $this->findPackage($link->getTarget(), '*');
31288 $description = $platformPkg ? 'but '.$platformPkg->getPrettyVersion().' is installed' : 'but it is missing';
31289 $results[] = array($package, new Link($package->getName(), $link->getTarget(), null, 'requires', $link->getPrettyConstraint().' '.$description), false);
31290
31291 continue;
31292 }
31293
31294 foreach ($this->getPackages() as $pkg) {
31295 if (!in_array($link->getTarget(), $pkg->getNames())) {
31296 continue;
31297 }
31298
31299 $version = new Constraint('=', $pkg->getVersion());
31300 if (!$link->getConstraint()->matches($version)) {
31301
31302  
31303  if ($rootPackage) {
31304 foreach (array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) {
31305 if (in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) {
31306 $results[] = array($package, $link, false);
31307 $results[] = array($rootPackage, $rootReq, false);
31308 continue 3;
31309 }
31310 }
31311 $results[] = array($package, $link, false);
31312 $results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), null, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
31313 } else {
31314
31315  $results[] = array($package, $link, false);
31316 }
31317 }
31318
31319 continue 2;
31320 }
31321 }
31322 }
31323 }
31324
31325 ksort($results);
31326
31327 return $results;
31328 }
31329 }
31330 <?php
31331
31332
31333
31334
31335
31336
31337
31338
31339
31340
31341
31342 namespace Composer\Repository;
31343
31344 use Composer\Package\Loader\ArrayLoader;
31345 use Composer\Package\PackageInterface;
31346 use Composer\Package\AliasPackage;
31347 use Composer\Package\Version\VersionParser;
31348 use Composer\DependencyResolver\Pool;
31349 use Composer\Json\JsonFile;
31350 use Composer\Cache;
31351 use Composer\Config;
31352 use Composer\Factory;
31353 use Composer\IO\IOInterface;
31354 use Composer\Util\RemoteFilesystem;
31355 use Composer\Plugin\PluginEvents;
31356 use Composer\Plugin\PreFileDownloadEvent;
31357 use Composer\EventDispatcher\EventDispatcher;
31358 use Composer\Downloader\TransportException;
31359 use Composer\Semver\Constraint\ConstraintInterface;
31360 use Composer\Semver\Constraint\Constraint;
31361
31362
31363
31364
31365 class ComposerRepository extends ArrayRepository implements ConfigurableRepositoryInterface
31366 {
31367 protected $config;
31368 protected $repoConfig;
31369 protected $options;
31370 protected $url;
31371 protected $baseUrl;
31372 protected $io;
31373 protected $rfs;
31374 protected $cache;
31375 protected $notifyUrl;
31376 protected $searchUrl;
31377 protected $hasProviders = false;
31378 protected $providersUrl;
31379 protected $lazyProvidersUrl;
31380 protected $providerListing;
31381 protected $providers = array();
31382 protected $providersByUid = array();
31383 protected $loader;
31384 protected $rootAliases;
31385 protected $allowSslDowngrade = false;
31386 protected $eventDispatcher;
31387 protected $sourceMirrors;
31388 protected $distMirrors;
31389 private $degradedMode = false;
31390 private $rootData;
31391 private $hasPartialPackages;
31392 private $partialPackagesByName;
31393
31394 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
31395 {
31396 parent::__construct();
31397 if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) {
31398
31399  $repoConfig['url'] = 'http://'.$repoConfig['url'];
31400 }
31401 $repoConfig['url'] = rtrim($repoConfig['url'], '/');
31402
31403 if ('https?' === substr($repoConfig['url'], 0, 6)) {
31404 $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
31405 }
31406
31407 $urlBits = parse_url($repoConfig['url']);
31408 if ($urlBits === false || empty($urlBits['scheme'])) {
31409 throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
31410 }
31411
31412 if (!isset($repoConfig['options'])) {
31413 $repoConfig['options'] = array();
31414 }
31415 if (isset($repoConfig['allow_ssl_downgrade']) && true === $repoConfig['allow_ssl_downgrade']) {
31416 $this->allowSslDowngrade = true;
31417 }
31418
31419 $this->config = $config;
31420 $this->options = $repoConfig['options'];
31421 $this->url = $repoConfig['url'];
31422 $this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
31423 $this->io = $io;
31424 $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
31425 $this->loader = new ArrayLoader();
31426 if ($rfs && $this->options) {
31427 $rfs = clone $rfs;
31428 $rfs->setOptions($this->options);
31429 }
31430 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $this->config, $this->options);
31431 $this->eventDispatcher = $eventDispatcher;
31432 $this->repoConfig = $repoConfig;
31433 }
31434
31435 public function getRepoConfig()
31436 {
31437 return $this->repoConfig;
31438 }
31439
31440 public function setRootAliases(array $rootAliases)
31441 {
31442 $this->rootAliases = $rootAliases;
31443 }
31444
31445
31446
31447
31448 public function findPackage($name, $constraint)
31449 {
31450 if (!$this->hasProviders()) {
31451 return parent::findPackage($name, $constraint);
31452 }
31453
31454 $name = strtolower($name);
31455 if (!$constraint instanceof ConstraintInterface) {
31456 $versionParser = new VersionParser();
31457 $constraint = $versionParser->parseConstraints($constraint);
31458 }
31459
31460 foreach ($this->getProviderNames() as $providerName) {
31461 if ($name === $providerName) {
31462 $packages = $this->whatProvides(new Pool('dev'), $providerName);
31463 foreach ($packages as $package) {
31464 if ($name === $package->getName()) {
31465 $pkgConstraint = new Constraint('==', $package->getVersion());
31466 if ($constraint->matches($pkgConstraint)) {
31467 return $package;
31468 }
31469 }
31470 }
31471 break;
31472 }
31473 }
31474 }
31475
31476
31477
31478
31479 public function findPackages($name, $constraint = null)
31480 {
31481 if (!$this->hasProviders()) {
31482 return parent::findPackages($name, $constraint);
31483 }
31484
31485  $name = strtolower($name);
31486
31487 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
31488 $versionParser = new VersionParser();
31489 $constraint = $versionParser->parseConstraints($constraint);
31490 }
31491
31492 $packages = array();
31493
31494 foreach ($this->getProviderNames() as $providerName) {
31495 if ($name === $providerName) {
31496 $candidates = $this->whatProvides(new Pool('dev'), $providerName);
31497 foreach ($candidates as $package) {
31498 if ($name === $package->getName()) {
31499 $pkgConstraint = new Constraint('==', $package->getVersion());
31500 if (null === $constraint || $constraint->matches($pkgConstraint)) {
31501 $packages[] = $package;
31502 }
31503 }
31504 }
31505 break;
31506 }
31507 }
31508
31509 return $packages;
31510 }
31511
31512 public function getPackages()
31513 {
31514 if ($this->hasProviders()) {
31515 throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.');
31516 }
31517
31518 return parent::getPackages();
31519 }
31520
31521
31522
31523
31524 public function search($query, $mode = 0, $type = null)
31525 {
31526 $this->loadRootServerFile();
31527
31528 if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
31529 $url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl);
31530
31531 $hostname = parse_url($url, PHP_URL_HOST) ?: $url;
31532 $json = $this->rfs->getContents($hostname, $url, false);
31533 $results = JsonFile::parseJson($json, $url);
31534
31535 return $results['results'];
31536 }
31537
31538 if ($this->hasProviders()) {
31539 $results = array();
31540 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
31541
31542 foreach ($this->getProviderNames() as $name) {
31543 if (preg_match($regex, $name)) {
31544 $results[] = array('name' => $name);
31545 }
31546 }
31547
31548 return $results;
31549 }
31550
31551 return parent::search($query, $mode);
31552 }
31553
31554 public function getProviderNames()
31555 {
31556 $this->loadRootServerFile();
31557
31558 if (null === $this->providerListing) {
31559 $this->loadProviderListings($this->loadRootServerFile());
31560 }
31561
31562 if ($this->lazyProvidersUrl) {
31563
31564  return array();
31565 }
31566
31567 if ($this->providersUrl) {
31568 return array_keys($this->providerListing);
31569 }
31570
31571 return array();
31572 }
31573
31574 protected function configurePackageTransportOptions(PackageInterface $package)
31575 {
31576 foreach ($package->getDistUrls() as $url) {
31577 if (strpos($url, $this->baseUrl) === 0) {
31578 $package->setTransportOptions($this->options);
31579
31580 return;
31581 }
31582 }
31583 }
31584
31585 public function hasProviders()
31586 {
31587 $this->loadRootServerFile();
31588
31589 return $this->hasProviders;
31590 }
31591
31592 public function resetPackageIds()
31593 {
31594 foreach ($this->providersByUid as $package) {
31595 if ($package instanceof AliasPackage) {
31596 $package->getAliasOf()->setId(-1);
31597 }
31598 $package->setId(-1);
31599 }
31600 }
31601
31602
31603
31604
31605
31606
31607
31608 public function whatProvides(Pool $pool, $name, $bypassFilters = false)
31609 {
31610 if (isset($this->providers[$name]) && !$bypassFilters) {
31611 return $this->providers[$name];
31612 }
31613
31614 if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
31615 $this->initializePartialPackages();
31616 }
31617
31618 if (!$this->hasPartialPackages || !isset($this->partialPackagesByName[$name])) {
31619
31620  if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) {
31621 return array();
31622 }
31623
31624 if (null === $this->providerListing) {
31625 $this->loadProviderListings($this->loadRootServerFile());
31626 }
31627
31628 $useLastModifiedCheck = false;
31629 if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
31630 $hash = null;
31631 $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
31632 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
31633 $useLastModifiedCheck = true;
31634 } elseif ($this->providersUrl) {
31635
31636  if (!isset($this->providerListing[$name])) {
31637 return array();
31638 }
31639
31640 $hash = $this->providerListing[$name]['sha256'];
31641 $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
31642 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
31643 } else {
31644 return array();
31645 }
31646
31647 $packages = null;
31648 if ($cacheKey) {
31649 if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) {
31650 $packages = json_decode($this->cache->read($cacheKey), true);
31651 } elseif ($useLastModifiedCheck) {
31652 if ($contents = $this->cache->read($cacheKey)) {
31653 $contents = json_decode($contents, true);
31654 if (isset($contents['last-modified'])) {
31655 $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']);
31656 if (true === $response) {
31657 $packages = $contents;
31658 } elseif ($response) {
31659 $packages = $response;
31660 }
31661 }
31662 }
31663 }
31664 }
31665
31666 if (!$packages) {
31667 try {
31668 $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck);
31669 } catch (TransportException $e) {
31670
31671  if ($e->getStatusCode() === 404 && $this->lazyProvidersUrl) {
31672 $packages = array('packages' => array());
31673 } else {
31674 throw $e;
31675 }
31676 }
31677 }
31678
31679 $loadingPartialPackage = false;
31680 } else {
31681 $packages = array('packages' => array('versions' => $this->partialPackagesByName[$name]));
31682 $loadingPartialPackage = true;
31683 }
31684
31685 $this->providers[$name] = array();
31686 foreach ($packages['packages'] as $versions) {
31687 foreach ($versions as $version) {
31688 if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
31689 continue;
31690 }
31691
31692
31693  if (isset($this->providersByUid[$version['uid']])) {
31694
31695  if (!isset($this->providers[$name][$version['uid']])) {
31696
31697  if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
31698 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
31699 $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
31700 } else {
31701 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
31702 }
31703
31704  if (isset($this->providersByUid[$version['uid'].'-root'])) {
31705 $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
31706 }
31707 }
31708 } else {
31709 if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
31710 continue;
31711 }
31712
31713
31714  $package = $this->createPackage($version, 'Composer\Package\CompletePackage');
31715 $package->setRepository($this);
31716
31717 if ($package instanceof AliasPackage) {
31718 $aliased = $package->getAliasOf();
31719 $aliased->setRepository($this);
31720
31721 $this->providers[$name][$version['uid']] = $aliased;
31722 $this->providers[$name][$version['uid'].'-alias'] = $package;
31723
31724
31725  $this->providersByUid[$version['uid']] = $package;
31726 } else {
31727 $this->providers[$name][$version['uid']] = $package;
31728 $this->providersByUid[$version['uid']] = $package;
31729 }
31730
31731
31732  unset($rootAliasData);
31733
31734 if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
31735 $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
31736 } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
31737 $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
31738 }
31739
31740 if (isset($rootAliasData)) {
31741 $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
31742 $alias->setRepository($this);
31743
31744 $this->providers[$name][$version['uid'].'-root'] = $alias;
31745 $this->providersByUid[$version['uid'].'-root'] = $alias;
31746 }
31747 }
31748 }
31749 }
31750
31751 $result = $this->providers[$name];
31752
31753
31754  
31755  if ($bypassFilters) {
31756 foreach ($this->providers[$name] as $uid => $provider) {
31757 unset($this->providersByUid[$uid]);
31758 }
31759 unset($this->providers[$name]);
31760 }
31761
31762 return $result;
31763 }
31764
31765
31766
31767
31768 protected function initialize()
31769 {
31770 parent::initialize();
31771
31772 $repoData = $this->loadDataFromServer();
31773
31774 foreach ($repoData as $package) {
31775 $this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
31776 }
31777 }
31778
31779
31780
31781
31782
31783
31784 public function addPackage(PackageInterface $package)
31785 {
31786 parent::addPackage($package);
31787 $this->configurePackageTransportOptions($package);
31788 }
31789
31790 protected function loadRootServerFile()
31791 {
31792 if (null !== $this->rootData) {
31793 return $this->rootData;
31794 }
31795
31796 if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
31797 throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
31798 }
31799
31800 $jsonUrlParts = parse_url($this->url);
31801
31802 if (isset($jsonUrlParts['path']) && false !== strpos($jsonUrlParts['path'], '.json')) {
31803 $jsonUrl = $this->url;
31804 } else {
31805 $jsonUrl = $this->url . '/packages.json';
31806 }
31807
31808 $data = $this->fetchFile($jsonUrl, 'packages.json');
31809
31810 if (!empty($data['notify-batch'])) {
31811 $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
31812 } elseif (!empty($data['notify'])) {
31813 $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
31814 }
31815
31816 if (!empty($data['search'])) {
31817 $this->searchUrl = $this->canonicalizeUrl($data['search']);
31818 }
31819
31820 if (!empty($data['mirrors'])) {
31821 foreach ($data['mirrors'] as $mirror) {
31822 if (!empty($mirror['git-url'])) {
31823 $this->sourceMirrors['git'][] = array('url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred']));
31824 }
31825 if (!empty($mirror['hg-url'])) {
31826 $this->sourceMirrors['hg'][] = array('url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred']));
31827 }
31828 if (!empty($mirror['dist-url'])) {
31829 $this->distMirrors[] = array(
31830 'url' => $this->canonicalizeUrl($mirror['dist-url']),
31831 'preferred' => !empty($mirror['preferred']),
31832 );
31833 }
31834 }
31835 }
31836
31837 if (!empty($data['providers-lazy-url'])) {
31838 $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
31839 $this->hasProviders = true;
31840
31841 $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
31842 }
31843
31844 if ($this->allowSslDowngrade) {
31845 $this->url = str_replace('https://', 'http://', $this->url);
31846 $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
31847 }
31848
31849 if (!empty($data['providers-url'])) {
31850 $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
31851 $this->hasProviders = true;
31852 }
31853
31854 if (!empty($data['providers']) || !empty($data['providers-includes'])) {
31855 $this->hasProviders = true;
31856 }
31857
31858
31859  if (preg_match('{^https?://packagist.org/?$}i', $this->url) && !empty($this->repoConfig['force-lazy-providers'])) {
31860 $this->url = 'https://packagist.org';
31861 $this->baseUrl = 'https://packagist.org';
31862 $this->lazyProvidersUrl = $this->canonicalizeUrl('https://packagist.org/p/%package%.json');
31863 $this->providersUrl = null;
31864 } elseif (!empty($this->repoConfig['force-lazy-providers'])) {
31865 $this->lazyProvidersUrl = $this->canonicalizeUrl('/p/%package%.json');
31866 $this->providersUrl = null;
31867 }
31868
31869 return $this->rootData = $data;
31870 }
31871
31872 protected function canonicalizeUrl($url)
31873 {
31874 if ('/' === $url[0]) {
31875 return preg_replace('{(https?://[^/]+).*}i', '$1' . $url, $this->url);
31876 }
31877
31878 return $url;
31879 }
31880
31881 protected function loadDataFromServer()
31882 {
31883 $data = $this->loadRootServerFile();
31884
31885 return $this->loadIncludes($data);
31886 }
31887
31888 protected function loadProviderListings($data)
31889 {
31890 if (isset($data['providers'])) {
31891 if (!is_array($this->providerListing)) {
31892 $this->providerListing = array();
31893 }
31894 $this->providerListing = array_merge($this->providerListing, $data['providers']);
31895 }
31896
31897 if ($this->providersUrl && isset($data['provider-includes'])) {
31898 $includes = $data['provider-includes'];
31899 foreach ($includes as $include => $metadata) {
31900 $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
31901 $cacheKey = str_replace(array('%hash%','$'), '', $include);
31902 if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
31903 $includedData = json_decode($this->cache->read($cacheKey), true);
31904 } else {
31905 $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
31906 }
31907
31908 $this->loadProviderListings($includedData);
31909 }
31910 }
31911 }
31912
31913 protected function loadIncludes($data)
31914 {
31915 $packages = array();
31916
31917
31918  if (!isset($data['packages']) && !isset($data['includes'])) {
31919 foreach ($data as $pkg) {
31920 foreach ($pkg['versions'] as $metadata) {
31921 $packages[] = $metadata;
31922 }
31923 }
31924
31925 return $packages;
31926 }
31927
31928 if (isset($data['packages'])) {
31929 foreach ($data['packages'] as $package => $versions) {
31930 foreach ($versions as $version => $metadata) {
31931 $packages[] = $metadata;
31932 }
31933 }
31934 }
31935
31936 if (isset($data['includes'])) {
31937 foreach ($data['includes'] as $include => $metadata) {
31938 if ($this->cache->sha1($include) === $metadata['sha1']) {
31939 $includedData = json_decode($this->cache->read($include), true);
31940 } else {
31941 $includedData = $this->fetchFile($include);
31942 }
31943 $packages = array_merge($packages, $this->loadIncludes($includedData));
31944 }
31945 }
31946
31947 return $packages;
31948 }
31949
31950 protected function createPackage(array $data, $class = 'Composer\Package\CompletePackage')
31951 {
31952 try {
31953 if (!isset($data['notification-url'])) {
31954 $data['notification-url'] = $this->notifyUrl;
31955 }
31956
31957 $package = $this->loader->load($data, $class);
31958 if (isset($this->sourceMirrors[$package->getSourceType()])) {
31959 $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
31960 }
31961 $package->setDistMirrors($this->distMirrors);
31962 $this->configurePackageTransportOptions($package);
31963
31964 return $package;
31965 } catch (\Exception $e) {
31966 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);
31967 }
31968 }
31969
31970 protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)
31971 {
31972 if (null === $cacheKey) {
31973 $cacheKey = $filename;
31974 $filename = $this->baseUrl.'/'.$filename;
31975 }
31976
31977
31978  if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) {
31979 $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
31980 }
31981
31982 $retries = 3;
31983 while ($retries--) {
31984 try {
31985 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
31986 if ($this->eventDispatcher) {
31987 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
31988 }
31989
31990 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
31991 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
31992
31993 $json = $rfs->getContents($hostname, $filename, false);
31994 if ($sha256 && $sha256 !== hash('sha256', $json)) {
31995
31996  if ($this->allowSslDowngrade) {
31997 $this->url = str_replace('http://', 'https://', $this->url);
31998 $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
31999 $filename = str_replace('http://', 'https://', $filename);
32000 }
32001
32002 if ($retries) {
32003 usleep(100000);
32004
32005 continue;
32006 }
32007
32008
32009  throw new RepositorySecurityException('The contents of '.$filename.' do not match its signature. This should indicate a man-in-the-middle attack. Try running composer again and report this if you think it is a mistake.');
32010 }
32011
32012 $data = JsonFile::parseJson($json, $filename);
32013 if (!empty($data['warning'])) {
32014 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
32015 }
32016 if (!empty($data['info'])) {
32017 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
32018 }
32019
32020 if ($cacheKey) {
32021 if ($storeLastModifiedTime) {
32022 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
32023 if ($lastModifiedDate) {
32024 $data['last-modified'] = $lastModifiedDate;
32025 $json = json_encode($data);
32026 }
32027 }
32028 $this->cache->write($cacheKey, $json);
32029 }
32030
32031 break;
32032 } catch (\Exception $e) {
32033 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
32034 throw $e;
32035 }
32036
32037 if ($retries) {
32038 usleep(100000);
32039 continue;
32040 }
32041
32042 if ($e instanceof RepositorySecurityException) {
32043 throw $e;
32044 }
32045
32046 if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
32047 if (!$this->degradedMode) {
32048 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
32049 $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>');
32050 }
32051 $this->degradedMode = true;
32052 $data = JsonFile::parseJson($contents, $this->cache->getRoot().$cacheKey);
32053
32054 break;
32055 }
32056
32057 throw $e;
32058 }
32059 }
32060
32061 return $data;
32062 }
32063
32064 protected function fetchFileIfLastModified($filename, $cacheKey, $lastModifiedTime)
32065 {
32066 $retries = 3;
32067 while ($retries--) {
32068 try {
32069 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
32070 if ($this->eventDispatcher) {
32071 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
32072 }
32073
32074 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
32075 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
32076 $options = array('http' => array('header' => array('If-Modified-Since: '.$lastModifiedTime)));
32077 $json = $rfs->getContents($hostname, $filename, false, $options);
32078 if ($json === '' && $rfs->findStatusCode($rfs->getLastHeaders()) === 304) {
32079 return true;
32080 }
32081
32082 $data = JsonFile::parseJson($json, $filename);
32083 if (!empty($data['warning'])) {
32084 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
32085 }
32086 if (!empty($data['info'])) {
32087 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
32088 }
32089
32090 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
32091 if ($lastModifiedDate) {
32092 $data['last-modified'] = $lastModifiedDate;
32093 $json = json_encode($data);
32094 }
32095 $this->cache->write($cacheKey, $json);
32096
32097 return $data;
32098 } catch (\Exception $e) {
32099 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
32100 throw $e;
32101 }
32102
32103 if ($retries) {
32104 usleep(100000);
32105 continue;
32106 }
32107
32108 if (!$this->degradedMode) {
32109 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
32110 $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>');
32111 }
32112 $this->degradedMode = true;
32113
32114 return true;
32115 }
32116 }
32117 }
32118
32119
32120
32121
32122
32123
32124 private function initializePartialPackages()
32125 {
32126 $rootData = $this->loadRootServerFile();
32127
32128 $this->partialPackagesByName = array();
32129 foreach ($rootData['packages'] as $package => $versions) {
32130 $package = strtolower($package);
32131 foreach ($versions as $version) {
32132 $this->partialPackagesByName[$package][] = $version;
32133 if (!empty($version['provide']) && is_array($version['provide'])) {
32134 foreach ($version['provide'] as $provided => $providedVersion) {
32135 $this->partialPackagesByName[strtolower($provided)][] = $version;
32136 }
32137 }
32138 if (!empty($version['replace']) && is_array($version['replace'])) {
32139 foreach ($version['replace'] as $provided => $providedVersion) {
32140 $this->partialPackagesByName[strtolower($provided)][] = $version;
32141 }
32142 }
32143 }
32144 }
32145
32146
32147  $this->rootData = true;
32148 }
32149 }
32150 <?php
32151
32152
32153
32154
32155
32156
32157
32158
32159
32160
32161
32162 namespace Composer\Repository;
32163
32164 use Composer\Package\PackageInterface;
32165
32166
32167
32168
32169
32170
32171 class CompositeRepository extends BaseRepository
32172 {
32173
32174
32175
32176
32177 private $repositories;
32178
32179
32180
32181
32182
32183 public function __construct(array $repositories)
32184 {
32185 $this->repositories = array();
32186 foreach ($repositories as $repo) {
32187 $this->addRepository($repo);
32188 }
32189 }
32190
32191
32192
32193
32194
32195
32196 public function getRepositories()
32197 {
32198 return $this->repositories;
32199 }
32200
32201
32202
32203
32204 public function hasPackage(PackageInterface $package)
32205 {
32206 foreach ($this->repositories as $repository) {
32207
32208 if ($repository->hasPackage($package)) {
32209 return true;
32210 }
32211 }
32212
32213 return false;
32214 }
32215
32216
32217
32218
32219 public function findPackage($name, $constraint)
32220 {
32221 foreach ($this->repositories as $repository) {
32222
32223 $package = $repository->findPackage($name, $constraint);
32224 if (null !== $package) {
32225 return $package;
32226 }
32227 }
32228
32229 return null;
32230 }
32231
32232
32233
32234
32235 public function findPackages($name, $constraint = null)
32236 {
32237 $packages = array();
32238 foreach ($this->repositories as $repository) {
32239
32240 $packages[] = $repository->findPackages($name, $constraint);
32241 }
32242
32243 return $packages ? call_user_func_array('array_merge', $packages) : array();
32244 }
32245
32246
32247
32248
32249 public function search($query, $mode = 0, $type = null)
32250 {
32251 $matches = array();
32252 foreach ($this->repositories as $repository) {
32253
32254 $matches[] = $repository->search($query, $mode, $type);
32255 }
32256
32257 return $matches ? call_user_func_array('array_merge', $matches) : array();
32258 }
32259
32260
32261
32262
32263 public function getPackages()
32264 {
32265 $packages = array();
32266 foreach ($this->repositories as $repository) {
32267
32268 $packages[] = $repository->getPackages();
32269 }
32270
32271 return $packages ? call_user_func_array('array_merge', $packages) : array();
32272 }
32273
32274
32275
32276
32277 public function removePackage(PackageInterface $package)
32278 {
32279 foreach ($this->repositories as $repository) {
32280
32281 $repository->removePackage($package);
32282 }
32283 }
32284
32285
32286
32287
32288 public function count()
32289 {
32290 $total = 0;
32291 foreach ($this->repositories as $repository) {
32292
32293 $total += $repository->count();
32294 }
32295
32296 return $total;
32297 }
32298
32299
32300
32301
32302
32303 public function addRepository(RepositoryInterface $repository)
32304 {
32305 if ($repository instanceof self) {
32306 foreach ($repository->getRepositories() as $repo) {
32307 $this->addRepository($repo);
32308 }
32309 } else {
32310 $this->repositories[] = $repository;
32311 }
32312 }
32313 }
32314 <?php
32315
32316
32317
32318
32319
32320
32321
32322
32323
32324
32325
32326 namespace Composer\Repository;
32327
32328
32329
32330
32331
32332
32333 interface ConfigurableRepositoryInterface
32334 {
32335 public function getRepoConfig();
32336 }
32337 <?php
32338
32339
32340
32341
32342
32343
32344
32345
32346
32347
32348
32349 namespace Composer\Repository;
32350
32351 use Composer\Json\JsonFile;
32352 use Composer\Package\Loader\ArrayLoader;
32353 use Composer\Package\Dumper\ArrayDumper;
32354
32355
32356
32357
32358
32359
32360
32361 class FilesystemRepository extends WritableArrayRepository
32362 {
32363 private $file;
32364
32365
32366
32367
32368
32369
32370 public function __construct(JsonFile $repositoryFile)
32371 {
32372 parent::__construct();
32373 $this->file = $repositoryFile;
32374 }
32375
32376
32377
32378
32379 protected function initialize()
32380 {
32381 parent::initialize();
32382
32383 if (!$this->file->exists()) {
32384 return;
32385 }
32386
32387 try {
32388 $packages = $this->file->read();
32389
32390 if (!is_array($packages)) {
32391 throw new \UnexpectedValueException('Could not parse package list from the repository');
32392 }
32393 } catch (\Exception $e) {
32394 throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.get_class($e).'] '.$e->getMessage());
32395 }
32396
32397 $loader = new ArrayLoader(null, true);
32398 foreach ($packages as $packageData) {
32399 $package = $loader->load($packageData);
32400 $this->addPackage($package);
32401 }
32402 }
32403
32404 public function reload()
32405 {
32406 $this->packages = null;
32407 $this->initialize();
32408 }
32409
32410
32411
32412
32413 public function write()
32414 {
32415 $data = array();
32416 $dumper = new ArrayDumper();
32417
32418 foreach ($this->getCanonicalPackages() as $package) {
32419 $data[] = $dumper->dump($package);
32420 }
32421
32422 $this->file->write($data);
32423 }
32424 }
32425 <?php
32426
32427
32428
32429
32430
32431
32432
32433
32434
32435
32436
32437 namespace Composer\Repository;
32438
32439
32440
32441
32442
32443
32444
32445
32446 class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
32447 {
32448 }
32449 <?php
32450
32451
32452
32453
32454
32455
32456
32457
32458
32459
32460
32461 namespace Composer\Repository;
32462
32463
32464
32465
32466
32467
32468 class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
32469 {
32470 }
32471 <?php
32472
32473
32474
32475
32476
32477
32478
32479
32480
32481
32482
32483 namespace Composer\Repository;
32484
32485
32486
32487
32488
32489
32490
32491
32492 interface InstalledRepositoryInterface extends WritableRepositoryInterface
32493 {
32494 }
32495 <?php
32496
32497
32498
32499
32500
32501
32502
32503
32504
32505
32506
32507 namespace Composer\Repository;
32508
32509
32510
32511
32512
32513
32514 class InvalidRepositoryException extends \Exception
32515 {
32516 }
32517 <?php
32518
32519
32520
32521
32522
32523
32524
32525
32526
32527
32528
32529 namespace Composer\Repository;
32530
32531 use Composer\Package\Loader\ArrayLoader;
32532 use Composer\Package\Loader\ValidatingArrayLoader;
32533
32534
32535
32536
32537
32538
32539 class PackageRepository extends ArrayRepository
32540 {
32541 private $config;
32542
32543
32544
32545
32546
32547
32548 public function __construct(array $config)
32549 {
32550 parent::__construct();
32551 $this->config = $config['package'];
32552
32553
32554  if (!is_numeric(key($this->config))) {
32555 $this->config = array($this->config);
32556 }
32557 }
32558
32559
32560
32561
32562 protected function initialize()
32563 {
32564 parent::initialize();
32565
32566 $loader = new ValidatingArrayLoader(new ArrayLoader(null, true), false);
32567 foreach ($this->config as $package) {
32568 try {
32569 $package = $loader->load($package);
32570 } catch (\Exception $e) {
32571 throw new InvalidRepositoryException('A repository of type "package" contains an invalid package definition: '.$e->getMessage()."\n\nInvalid package definition:\n".json_encode($package));
32572 }
32573
32574 $this->addPackage($package);
32575 }
32576 }
32577 }
32578 <?php
32579
32580
32581
32582
32583
32584
32585
32586
32587
32588
32589
32590 namespace Composer\Repository;
32591
32592 use Composer\Config;
32593 use Composer\IO\IOInterface;
32594 use Composer\Json\JsonFile;
32595 use Composer\Package\Loader\ArrayLoader;
32596 use Composer\Package\Version\VersionGuesser;
32597 use Composer\Package\Version\VersionParser;
32598 use Composer\Util\Platform;
32599 use Composer\Util\ProcessExecutor;
32600
32601
32602
32603
32604
32605
32606
32607
32608
32609
32610
32611
32612
32613
32614
32615
32616
32617
32618
32619
32620
32621
32622
32623
32624
32625
32626
32627
32628
32629
32630
32631
32632
32633
32634
32635
32636 class PathRepository extends ArrayRepository implements ConfigurableRepositoryInterface
32637 {
32638
32639
32640
32641 private $loader;
32642
32643
32644
32645
32646 private $versionGuesser;
32647
32648
32649
32650
32651 private $url;
32652
32653
32654
32655
32656 private $repoConfig;
32657
32658
32659
32660
32661 private $process;
32662
32663
32664
32665
32666 private $options;
32667
32668
32669
32670
32671
32672
32673
32674
32675 public function __construct(array $repoConfig, IOInterface $io, Config $config)
32676 {
32677 if (!isset($repoConfig['url'])) {
32678 throw new \RuntimeException('You must specify the `url` configuration for the path repository');
32679 }
32680
32681 $this->loader = new ArrayLoader(null, true);
32682 $this->url = Platform::expandPath($repoConfig['url']);
32683 $this->process = new ProcessExecutor($io);
32684 $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
32685 $this->repoConfig = $repoConfig;
32686 $this->options = isset($repoConfig['options']) ? $repoConfig['options'] : array();
32687
32688 parent::__construct();
32689 }
32690
32691 public function getRepoConfig()
32692 {
32693 return $this->repoConfig;
32694 }
32695
32696
32697
32698
32699
32700
32701 protected function initialize()
32702 {
32703 parent::initialize();
32704
32705 foreach ($this->getUrlMatches() as $url) {
32706 $path = realpath($url) . DIRECTORY_SEPARATOR;
32707 $composerFilePath = $path.'composer.json';
32708
32709 if (!file_exists($composerFilePath)) {
32710 continue;
32711 }
32712
32713 $json = file_get_contents($composerFilePath);
32714 $package = JsonFile::parseJson($json, $composerFilePath);
32715 $package['dist'] = array(
32716 'type' => 'path',
32717 'url' => $url,
32718 'reference' => sha1($json . serialize($this->options)),
32719 );
32720 $package['transport-options'] = $this->options;
32721
32722 if (!isset($package['version'])) {
32723 $versionData = $this->versionGuesser->guessVersion($package, $path);
32724 $package['version'] = $versionData['version'] ?: 'dev-master';
32725 }
32726
32727 $output = '';
32728 if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
32729 $package['dist']['reference'] = trim($output);
32730 }
32731 $package = $this->loader->load($package);
32732 $this->addPackage($package);
32733 }
32734 }
32735
32736
32737
32738
32739
32740
32741 private function getUrlMatches()
32742 {
32743
32744  return array_map(function ($val) {
32745 return rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $val), '/');
32746 }, glob($this->url, GLOB_MARK | GLOB_ONLYDIR));
32747 }
32748 }
32749 <?php
32750
32751
32752
32753
32754
32755
32756
32757
32758
32759
32760
32761 namespace Composer\Repository\Pear;
32762
32763 use Composer\Util\RemoteFilesystem;
32764
32765
32766
32767
32768
32769
32770
32771
32772 abstract class BaseChannelReader
32773 {
32774
32775
32776
32777 const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
32778 const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
32779 const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
32780 const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
32781 const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
32782 const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
32783
32784
32785 private $rfs;
32786
32787 protected function __construct(RemoteFilesystem $rfs)
32788 {
32789 $this->rfs = $rfs;
32790 }
32791
32792
32793
32794
32795
32796
32797
32798
32799
32800 protected function requestContent($origin, $path)
32801 {
32802 $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
32803 $content = $this->rfs->getContents($origin, $url, false);
32804 if (!$content) {
32805 throw new \UnexpectedValueException('The PEAR channel at ' . $url . ' did not respond.');
32806 }
32807
32808 return str_replace('http://pear.php.net/rest/', 'https://pear.php.net/rest/', $content);
32809 }
32810
32811
32812
32813
32814
32815
32816
32817
32818
32819 protected function requestXml($origin, $path)
32820 {
32821
32822  $xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
32823
32824 if (false === $xml) {
32825 throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
32826 }
32827
32828 return $xml;
32829 }
32830 }
32831 <?php
32832
32833
32834
32835
32836
32837
32838
32839
32840
32841
32842
32843 namespace Composer\Repository\Pear;
32844
32845
32846
32847
32848
32849
32850 class ChannelInfo
32851 {
32852 private $name;
32853 private $alias;
32854 private $packages;
32855
32856
32857
32858
32859
32860
32861 public function __construct($name, $alias, array $packages)
32862 {
32863 $this->name = $name;
32864 $this->alias = $alias;
32865 $this->packages = $packages;
32866 }
32867
32868
32869
32870
32871
32872
32873 public function getName()
32874 {
32875 return $this->name;
32876 }
32877
32878
32879
32880
32881
32882
32883 public function getAlias()
32884 {
32885 return $this->alias;
32886 }
32887
32888
32889
32890
32891
32892
32893 public function getPackages()
32894 {
32895 return $this->packages;
32896 }
32897 }
32898 <?php
32899
32900
32901
32902
32903
32904
32905
32906
32907
32908
32909
32910 namespace Composer\Repository\Pear;
32911
32912 use Composer\Util\RemoteFilesystem;
32913
32914
32915
32916
32917
32918
32919
32920
32921 class ChannelReader extends BaseChannelReader
32922 {
32923
32924 private $readerMap;
32925
32926 public function __construct(RemoteFilesystem $rfs)
32927 {
32928 parent::__construct($rfs);
32929
32930 $rest10reader = new ChannelRest10Reader($rfs);
32931 $rest11reader = new ChannelRest11Reader($rfs);
32932
32933 $this->readerMap = array(
32934 'REST1.3' => $rest11reader,
32935 'REST1.2' => $rest11reader,
32936 'REST1.1' => $rest11reader,
32937 'REST1.0' => $rest10reader,
32938 );
32939 }
32940
32941
32942
32943
32944
32945
32946
32947
32948 public function read($url)
32949 {
32950 $xml = $this->requestXml($url, "/channel.xml");
32951
32952 $channelName = (string) $xml->name;
32953 $channelAlias = (string) $xml->suggestedalias;
32954
32955 $supportedVersions = array_keys($this->readerMap);
32956 $selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
32957 if (!$selectedRestVersion) {
32958 throw new \UnexpectedValueException(sprintf('PEAR repository %s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
32959 }
32960
32961 $reader = $this->readerMap[$selectedRestVersion['version']];
32962 $packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
32963
32964 return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
32965 }
32966
32967
32968
32969
32970
32971
32972
32973
32974 private function selectRestVersion($channelXml, $supportedVersions)
32975 {
32976 $channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
32977
32978 foreach ($supportedVersions as $version) {
32979 $xpathTest = "ns:servers/ns:*/ns:rest/ns:baseurl[@type='{$version}']";
32980 $testResult = $channelXml->xpath($xpathTest);
32981
32982 foreach ($testResult as $result) {
32983
32984  $result = (string) $result;
32985 if (preg_match('{^https://}i', $result)) {
32986 return array('version' => $version, 'baseUrl' => $result);
32987 }
32988 }
32989
32990
32991  if (count($testResult) > 0) {
32992 return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
32993 }
32994 }
32995
32996 return null;
32997 }
32998 }
32999 <?php
33000
33001
33002
33003
33004
33005
33006
33007
33008
33009
33010
33011 namespace Composer\Repository\Pear;
33012
33013 use Composer\Downloader\TransportException;
33014
33015
33016
33017
33018
33019
33020
33021
33022
33023
33024
33025
33026 class ChannelRest10Reader extends BaseChannelReader
33027 {
33028 private $dependencyReader;
33029
33030 public function __construct($rfs)
33031 {
33032 parent::__construct($rfs);
33033
33034 $this->dependencyReader = new PackageDependencyParser();
33035 }
33036
33037
33038
33039
33040
33041
33042
33043
33044 public function read($baseUrl)
33045 {
33046 return $this->readPackages($baseUrl);
33047 }
33048
33049
33050
33051
33052
33053
33054
33055
33056 private function readPackages($baseUrl)
33057 {
33058 $result = array();
33059
33060 $xmlPath = '/p/packages.xml';
33061 $xml = $this->requestXml($baseUrl, $xmlPath);
33062 $xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
33063 foreach ($xml->xpath('ns:p') as $node) {
33064 $packageName = (string) $node;
33065 $packageInfo = $this->readPackage($baseUrl, $packageName);
33066 $result[] = $packageInfo;
33067 }
33068
33069 return $result;
33070 }
33071
33072
33073
33074
33075
33076
33077
33078
33079
33080 private function readPackage($baseUrl, $packageName)
33081 {
33082 $xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
33083 $xml = $this->requestXml($baseUrl, $xmlPath);
33084 $xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
33085
33086 $channelName = (string) $xml->c;
33087 $packageName = (string) $xml->n;
33088 $license = (string) $xml->l;
33089 $shortDescription = (string) $xml->s;
33090 $description = (string) $xml->d;
33091
33092 return new PackageInfo(
33093 $channelName,
33094 $packageName,
33095 $license,
33096 $shortDescription,
33097 $description,
33098 $this->readPackageReleases($baseUrl, $packageName)
33099 );
33100 }
33101
33102
33103
33104
33105
33106
33107
33108
33109
33110
33111 private function readPackageReleases($baseUrl, $packageName)
33112 {
33113 $result = array();
33114
33115 try {
33116 $xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
33117 $xml = $this->requestXml($baseUrl, $xmlPath);
33118 $xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
33119 foreach ($xml->xpath('ns:r') as $node) {
33120 $releaseVersion = (string) $node->v;
33121 $releaseStability = (string) $node->s;
33122
33123 try {
33124 $result[$releaseVersion] = new ReleaseInfo(
33125 $releaseStability,
33126 $this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
33127 );
33128 } catch (TransportException $exception) {
33129 if ($exception->getCode() != 404) {
33130 throw $exception;
33131 }
33132 }
33133 }
33134 } catch (TransportException $exception) {
33135 if ($exception->getCode() != 404) {
33136 throw $exception;
33137 }
33138 }
33139
33140 return $result;
33141 }
33142
33143
33144
33145
33146
33147
33148
33149
33150
33151
33152 private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
33153 {
33154 $dependencyReader = new PackageDependencyParser();
33155
33156 $depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
33157 $content = $this->requestContent($baseUrl, $depthPath);
33158 $dependencyArray = unserialize($content);
33159 $result = $dependencyReader->buildDependencyInfo($dependencyArray);
33160
33161 return $result;
33162 }
33163 }
33164 <?php
33165
33166
33167
33168
33169
33170
33171
33172
33173
33174
33175
33176 namespace Composer\Repository\Pear;
33177
33178
33179
33180
33181
33182
33183
33184
33185
33186
33187 class ChannelRest11Reader extends BaseChannelReader
33188 {
33189 private $dependencyReader;
33190
33191 public function __construct($rfs)
33192 {
33193 parent::__construct($rfs);
33194
33195 $this->dependencyReader = new PackageDependencyParser();
33196 }
33197
33198
33199
33200
33201
33202
33203
33204
33205 public function read($baseUrl)
33206 {
33207 return $this->readChannelPackages($baseUrl);
33208 }
33209
33210
33211
33212
33213
33214
33215
33216
33217 private function readChannelPackages($baseUrl)
33218 {
33219 $result = array();
33220
33221 $xml = $this->requestXml($baseUrl, "/c/categories.xml");
33222 $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
33223 foreach ($xml->xpath('ns:c') as $node) {
33224 $categoryName = (string) $node;
33225 $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
33226 $result = array_merge($result, $categoryPackages);
33227 }
33228
33229 return $result;
33230 }
33231
33232
33233
33234
33235
33236
33237
33238
33239
33240 private function readCategoryPackages($baseUrl, $categoryName)
33241 {
33242 $result = array();
33243
33244 $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
33245 $xml = $this->requestXml($baseUrl, $categoryPath);
33246 $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
33247 foreach ($xml->xpath('ns:pi') as $node) {
33248 $packageInfo = $this->parsePackage($node);
33249 $result[] = $packageInfo;
33250 }
33251
33252 return $result;
33253 }
33254
33255
33256
33257
33258
33259
33260
33261 private function parsePackage($packageInfo)
33262 {
33263 $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
33264 $channelName = (string) $packageInfo->p->c;
33265 $packageName = (string) $packageInfo->p->n;
33266 $license = (string) $packageInfo->p->l;
33267 $shortDescription = (string) $packageInfo->p->s;
33268 $description = (string) $packageInfo->p->d;
33269
33270 $dependencies = array();
33271 foreach ($packageInfo->xpath('ns:deps') as $node) {
33272 $dependencyVersion = (string) $node->v;
33273 $dependencyArray = unserialize((string) $node->d);
33274
33275 $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
33276
33277 $dependencies[$dependencyVersion] = $dependencyInfo;
33278 }
33279
33280 $releases = array();
33281 $releasesInfo = $packageInfo->xpath('ns:a/ns:r');
33282 if ($releasesInfo) {
33283 foreach ($releasesInfo as $node) {
33284 $releaseVersion = (string) $node->v;
33285 $releaseStability = (string) $node->s;
33286 $releases[$releaseVersion] = new ReleaseInfo(
33287 $releaseStability,
33288 isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
33289 );
33290 }
33291 }
33292
33293 return new PackageInfo(
33294 $channelName,
33295 $packageName,
33296 $license,
33297 $shortDescription,
33298 $description,
33299 $releases
33300 );
33301 }
33302 }
33303 <?php
33304
33305
33306
33307
33308
33309
33310
33311
33312
33313
33314
33315 namespace Composer\Repository\Pear;
33316
33317
33318
33319
33320
33321
33322 class DependencyConstraint
33323 {
33324 private $type;
33325 private $constraint;
33326 private $channelName;
33327 private $packageName;
33328
33329
33330
33331
33332
33333
33334
33335 public function __construct($type, $constraint, $channelName, $packageName)
33336 {
33337 $this->type = $type;
33338 $this->constraint = $constraint;
33339 $this->channelName = $channelName;
33340 $this->packageName = $packageName;
33341 }
33342
33343 public function getChannelName()
33344 {
33345 return $this->channelName;
33346 }
33347
33348 public function getConstraint()
33349 {
33350 return $this->constraint;
33351 }
33352
33353 public function getPackageName()
33354 {
33355 return $this->packageName;
33356 }
33357
33358 public function getType()
33359 {
33360 return $this->type;
33361 }
33362 }
33363 <?php
33364
33365
33366
33367
33368
33369
33370
33371
33372
33373
33374
33375 namespace Composer\Repository\Pear;
33376
33377
33378
33379
33380
33381
33382 class DependencyInfo
33383 {
33384 private $requires;
33385 private $optionals;
33386
33387
33388
33389
33390
33391 public function __construct($requires, $optionals)
33392 {
33393 $this->requires = $requires;
33394 $this->optionals = $optionals;
33395 }
33396
33397
33398
33399
33400 public function getRequires()
33401 {
33402 return $this->requires;
33403 }
33404
33405
33406
33407
33408 public function getOptionals()
33409 {
33410 return $this->optionals;
33411 }
33412 }
33413 <?php
33414
33415
33416
33417
33418
33419
33420
33421
33422
33423
33424
33425 namespace Composer\Repository\Pear;
33426
33427
33428
33429
33430
33431
33432 class PackageDependencyParser
33433 {
33434
33435
33436
33437
33438
33439
33440 public function buildDependencyInfo($depArray)
33441 {
33442 if (!is_array($depArray)) {
33443 return new DependencyInfo(array(), array());
33444 }
33445 if (!$this->isHash($depArray)) {
33446 return new DependencyInfo($this->buildDependency10Info($depArray), array());
33447 }
33448
33449 return $this->buildDependency20Info($depArray);
33450 }
33451
33452
33453
33454
33455
33456
33457
33458
33459
33460
33461
33462
33463
33464 private function buildDependency10Info($depArray)
33465 {
33466 static $dep10toOperatorMap = array('has' => '==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
33467
33468 $result = array();
33469
33470 foreach ($depArray as $depItem) {
33471 if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
33472
33473  continue;
33474 }
33475
33476 $depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
33477 ? 'optional'
33478 : 'required';
33479 $depType = 'not' == $depItem['rel']
33480 ? 'conflicts'
33481 : $depType;
33482
33483 $depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
33484
33485
33486  $depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
33487 ? '*'
33488 : $dep10toOperatorMap[$depItem['rel']] . $depVersion;
33489
33490 switch ($depItem['type']) {
33491 case 'php':
33492 $depChannelName = 'php';
33493 $depPackageName = '';
33494 break;
33495 case 'pkg':
33496 $depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
33497 $depPackageName = $depItem['name'];
33498 break;
33499 case 'ext':
33500 $depChannelName = 'ext';
33501 $depPackageName = $depItem['name'];
33502 break;
33503 case 'os':
33504 case 'sapi':
33505 $depChannelName = '';
33506 $depPackageName = '';
33507 break;
33508 default:
33509 $depChannelName = '';
33510 $depPackageName = '';
33511 break;
33512 }
33513
33514 if ('' != $depChannelName) {
33515 $result[] = new DependencyConstraint(
33516 $depType,
33517 $depVersionConstraint,
33518 $depChannelName,
33519 $depPackageName
33520 );
33521 }
33522 }
33523
33524 return $result;
33525 }
33526
33527
33528
33529
33530
33531
33532
33533 private function buildDependency20Info($depArray)
33534 {
33535 $result = array();
33536 $optionals = array();
33537 $defaultOptionals = array();
33538 foreach ($depArray as $depType => $depTypeGroup) {
33539 if (!is_array($depTypeGroup)) {
33540 continue;
33541 }
33542 if ('required' == $depType || 'optional' == $depType) {
33543 foreach ($depTypeGroup as $depItemType => $depItem) {
33544 switch ($depItemType) {
33545 case 'php':
33546 $result[] = new DependencyConstraint(
33547 $depType,
33548 $this->parse20VersionConstraint($depItem),
33549 'php',
33550 ''
33551 );
33552 break;
33553 case 'package':
33554 $deps = $this->buildDepPackageConstraints($depItem, $depType);
33555 $result = array_merge($result, $deps);
33556 break;
33557 case 'extension':
33558 $deps = $this->buildDepExtensionConstraints($depItem, $depType);
33559 $result = array_merge($result, $deps);
33560 break;
33561 case 'subpackage':
33562 $deps = $this->buildDepPackageConstraints($depItem, 'replaces');
33563 $defaultOptionals += $deps;
33564 break;
33565 case 'os':
33566 case 'pearinstaller':
33567 break;
33568 default:
33569 break;
33570 }
33571 }
33572 } elseif ('group' == $depType) {
33573 if ($this->isHash($depTypeGroup)) {
33574 $depTypeGroup = array($depTypeGroup);
33575 }
33576
33577 foreach ($depTypeGroup as $depItem) {
33578 $groupName = $depItem['attribs']['name'];
33579 if (!isset($optionals[$groupName])) {
33580 $optionals[$groupName] = array();
33581 }
33582
33583 if (isset($depItem['subpackage'])) {
33584 $optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
33585 } else {
33586 $result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
33587 }
33588 }
33589 }
33590 }
33591
33592 if (count($defaultOptionals) > 0) {
33593 $optionals['*'] = $defaultOptionals;
33594 }
33595
33596 return new DependencyInfo($result, $optionals);
33597 }
33598
33599
33600
33601
33602
33603
33604
33605
33606 private function buildDepExtensionConstraints($depItem, $depType)
33607 {
33608 if ($this->isHash($depItem)) {
33609 $depItem = array($depItem);
33610 }
33611
33612 $result = array();
33613 foreach ($depItem as $subDepItem) {
33614 $depChannelName = 'ext';
33615 $depPackageName = $subDepItem['name'];
33616 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
33617
33618 $result[] = new DependencyConstraint(
33619 $depType,
33620 $depVersionConstraint,
33621 $depChannelName,
33622 $depPackageName
33623 );
33624 }
33625
33626 return $result;
33627 }
33628
33629
33630
33631
33632
33633
33634
33635
33636 private function buildDepPackageConstraints($depItem, $depType)
33637 {
33638 if ($this->isHash($depItem)) {
33639 $depItem = array($depItem);
33640 }
33641
33642 $result = array();
33643 foreach ($depItem as $subDepItem) {
33644 if (!array_key_exists('channel', $subDepItem)) {
33645 $subDepItem['channel'] = $subDepItem['uri'];
33646 }
33647 $depChannelName = $subDepItem['channel'];
33648 $depPackageName = $subDepItem['name'];
33649 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
33650 if (isset($subDepItem['conflicts'])) {
33651 $depType = 'conflicts';
33652 }
33653
33654 $result[] = new DependencyConstraint(
33655 $depType,
33656 $depVersionConstraint,
33657 $depChannelName,
33658 $depPackageName
33659 );
33660 }
33661
33662 return $result;
33663 }
33664
33665
33666
33667
33668
33669
33670
33671 private function parse20VersionConstraint(array $data)
33672 {
33673 static $dep20toOperatorMap = array('has' => '==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
33674
33675 $versions = array();
33676 $values = array_intersect_key($data, $dep20toOperatorMap);
33677 if (0 == count($values)) {
33678 return '*';
33679 }
33680 if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
33681 $versions[] = '>' . $this->parseVersion($values['min']);
33682 } elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
33683 $versions[] = '<' . $this->parseVersion($values['max']);
33684 } else {
33685 foreach ($values as $op => $version) {
33686 if ('exclude' == $op && is_array($version)) {
33687 foreach ($version as $versionPart) {
33688 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
33689 }
33690 } else {
33691 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
33692 }
33693 }
33694 }
33695
33696 return implode(',', $versions);
33697 }
33698
33699
33700
33701
33702
33703
33704
33705 private function parseVersion($version)
33706 {
33707 if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
33708 $version = $matches[1]
33709 .(!empty($matches[2]) ? $matches[2] : '.0')
33710 .(!empty($matches[3]) ? $matches[3] : '.0')
33711 .(!empty($matches[4]) ? $matches[4] : '.0');
33712
33713 return $version;
33714 }
33715
33716 return null;
33717 }
33718
33719
33720
33721
33722
33723
33724
33725 private function isHash(array $array)
33726 {
33727 return !array_key_exists(1, $array) && !array_key_exists(0, $array);
33728 }
33729 }
33730 <?php
33731
33732
33733
33734
33735
33736
33737
33738
33739
33740
33741
33742 namespace Composer\Repository\Pear;
33743
33744
33745
33746
33747
33748
33749 class PackageInfo
33750 {
33751 private $channelName;
33752 private $packageName;
33753 private $license;
33754 private $shortDescription;
33755 private $description;
33756 private $releases;
33757
33758
33759
33760
33761
33762
33763
33764
33765
33766 public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
33767 {
33768 $this->channelName = $channelName;
33769 $this->packageName = $packageName;
33770 $this->license = $license;
33771 $this->shortDescription = $shortDescription;
33772 $this->description = $description;
33773 $this->releases = $releases;
33774 }
33775
33776
33777
33778
33779 public function getChannelName()
33780 {
33781 return $this->channelName;
33782 }
33783
33784
33785
33786
33787 public function getPackageName()
33788 {
33789 return $this->packageName;
33790 }
33791
33792
33793
33794
33795 public function getDescription()
33796 {
33797 return $this->description;
33798 }
33799
33800
33801
33802
33803 public function getShortDescription()
33804 {
33805 return $this->shortDescription;
33806 }
33807
33808
33809
33810
33811 public function getLicense()
33812 {
33813 return $this->license;
33814 }
33815
33816
33817
33818
33819 public function getReleases()
33820 {
33821 return $this->releases;
33822 }
33823 }
33824 <?php
33825
33826
33827
33828
33829
33830
33831
33832
33833
33834
33835
33836 namespace Composer\Repository\Pear;
33837
33838
33839
33840
33841
33842
33843 class ReleaseInfo
33844 {
33845 private $stability;
33846 private $dependencyInfo;
33847
33848
33849
33850
33851
33852 public function __construct($stability, $dependencyInfo)
33853 {
33854 $this->stability = $stability;
33855 $this->dependencyInfo = $dependencyInfo;
33856 }
33857
33858
33859
33860
33861 public function getDependencyInfo()
33862 {
33863 return $this->dependencyInfo;
33864 }
33865
33866
33867
33868
33869 public function getStability()
33870 {
33871 return $this->stability;
33872 }
33873 }
33874 <?php
33875
33876
33877
33878
33879
33880
33881
33882
33883
33884
33885
33886 namespace Composer\Repository;
33887
33888 use Composer\IO\IOInterface;
33889 use Composer\Semver\VersionParser as SemverVersionParser;
33890 use Composer\Package\Version\VersionParser;
33891 use Composer\Repository\Pear\ChannelReader;
33892 use Composer\Package\CompletePackage;
33893 use Composer\Repository\Pear\ChannelInfo;
33894 use Composer\EventDispatcher\EventDispatcher;
33895 use Composer\Package\Link;
33896 use Composer\Semver\Constraint\Constraint;
33897 use Composer\Util\RemoteFilesystem;
33898 use Composer\Config;
33899 use Composer\Factory;
33900
33901
33902
33903
33904
33905
33906
33907
33908
33909
33910 class PearRepository extends ArrayRepository implements ConfigurableRepositoryInterface
33911 {
33912 private $url;
33913 private $io;
33914 private $rfs;
33915 private $versionParser;
33916 private $repoConfig;
33917
33918
33919
33920
33921 private $vendorAlias;
33922
33923 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null)
33924 {
33925 parent::__construct();
33926 if (!preg_match('{^https?://}', $repoConfig['url'])) {
33927 $repoConfig['url'] = 'http://'.$repoConfig['url'];
33928 }
33929
33930 $urlBits = parse_url($repoConfig['url']);
33931 if (empty($urlBits['scheme']) || empty($urlBits['host'])) {
33932 throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']);
33933 }
33934
33935 $this->url = rtrim($repoConfig['url'], '/');
33936 $this->io = $io;
33937 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
33938 $this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
33939 $this->versionParser = new VersionParser();
33940 $this->repoConfig = $repoConfig;
33941 }
33942
33943 public function getRepoConfig()
33944 {
33945 return $this->repoConfig;
33946 }
33947
33948 protected function initialize()
33949 {
33950 parent::initialize();
33951
33952 $this->io->writeError('Initializing PEAR repository '.$this->url);
33953
33954 $reader = new ChannelReader($this->rfs);
33955 try {
33956 $channelInfo = $reader->read($this->url);
33957 } catch (\Exception $e) {
33958 $this->io->writeError('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
33959
33960 return;
33961 }
33962 $packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
33963 foreach ($packages as $package) {
33964 $this->addPackage($package);
33965 }
33966 }
33967
33968
33969
33970
33971
33972
33973
33974
33975 private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
33976 {
33977 $result = array();
33978 foreach ($channelInfo->getPackages() as $packageDefinition) {
33979 foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
33980 try {
33981 $normalizedVersion = $versionParser->normalize($version);
33982 } catch (\UnexpectedValueException $e) {
33983 $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage(), true, IOInterface::VERBOSE);
33984 continue;
33985 }
33986
33987 $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
33988
33989
33990  
33991  $urlBits = parse_url($this->url);
33992 $scheme = (isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl')) ? 'https' : 'http';
33993 $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
33994
33995 $requires = array();
33996 $suggests = array();
33997 $conflicts = array();
33998 $replaces = array();
33999
34000
34001  
34002  if ($channelInfo->getName() == $packageDefinition->getChannelName()) {
34003 $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
34004 $aliasConstraint = new Constraint('==', $normalizedVersion);
34005 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
34006 }
34007
34008
34009  if (!empty($this->vendorAlias)
34010 && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())
34011 ) {
34012 $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
34013 $aliasConstraint = new Constraint('==', $normalizedVersion);
34014 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
34015 }
34016
34017 foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) {
34018 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
34019 $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
34020 $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
34021 switch ($dependencyConstraint->getType()) {
34022 case 'required':
34023 $requires[] = $link;
34024 break;
34025 case 'conflicts':
34026 $conflicts[] = $link;
34027 break;
34028 case 'replaces':
34029 $replaces[] = $link;
34030 break;
34031 }
34032 }
34033
34034 foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
34035 foreach ($dependencyConstraints as $dependencyConstraint) {
34036 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
34037 $suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
34038 }
34039 }
34040
34041 $package = new CompletePackage($composerPackageName, $normalizedVersion, $version);
34042 $package->setType('pear-library');
34043 $package->setDescription($packageDefinition->getDescription());
34044 $package->setLicense(array($packageDefinition->getLicense()));
34045 $package->setDistType('file');
34046 $package->setDistUrl($distUrl);
34047 $package->setAutoload(array('classmap' => array('')));
34048 $package->setIncludePaths(array('/'));
34049 $package->setRequires($requires);
34050 $package->setConflicts($conflicts);
34051 $package->setSuggests($suggests);
34052 $package->setReplaces($replaces);
34053 $result[] = $package;
34054 }
34055 }
34056
34057 return $result;
34058 }
34059
34060 private function buildComposerPackageName($channelName, $packageName)
34061 {
34062 if ('php' === $channelName) {
34063 return "php";
34064 }
34065 if ('ext' === $channelName) {
34066 return "ext-{$packageName}";
34067 }
34068
34069 return "pear-{$channelName}/{$packageName}";
34070 }
34071 }
34072 <?php
34073
34074
34075
34076
34077
34078
34079
34080
34081
34082
34083
34084 namespace Composer\Repository;
34085
34086 use Composer\XdebugHandler;
34087 use Composer\Package\CompletePackage;
34088 use Composer\Package\PackageInterface;
34089 use Composer\Package\Version\VersionParser;
34090 use Composer\Plugin\PluginInterface;
34091 use Composer\Util\Silencer;
34092
34093
34094
34095
34096 class PlatformRepository extends ArrayRepository
34097 {
34098 const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[^/]+)$}i';
34099
34100 private $versionParser;
34101
34102
34103
34104
34105
34106
34107
34108
34109 private $overrides = array();
34110
34111 public function __construct(array $packages = array(), array $overrides = array())
34112 {
34113 foreach ($overrides as $name => $version) {
34114 $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
34115 }
34116 parent::__construct($packages);
34117 }
34118
34119 protected function initialize()
34120 {
34121 parent::initialize();
34122
34123 $this->versionParser = new VersionParser();
34124
34125
34126  
34127  foreach ($this->overrides as $override) {
34128
34129  if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
34130 throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
34131 }
34132
34133 $this->addOverriddenPackage($override);
34134 }
34135
34136 $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
34137 $version = $this->versionParser->normalize($prettyVersion);
34138 $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
34139 $composerPluginApi->setDescription('The Composer Plugin API');
34140 $this->addPackage($composerPluginApi);
34141
34142 try {
34143 $prettyVersion = PHP_VERSION;
34144 $version = $this->versionParser->normalize($prettyVersion);
34145 } catch (\UnexpectedValueException $e) {
34146 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
34147 $version = $this->versionParser->normalize($prettyVersion);
34148 }
34149
34150 $php = new CompletePackage('php', $version, $prettyVersion);
34151 $php->setDescription('The PHP interpreter');
34152 $this->addPackage($php);
34153
34154 if (PHP_DEBUG) {
34155 $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion);
34156 $phpdebug->setDescription('The PHP interpreter, with debugging symbols');
34157 $this->addPackage($phpdebug);
34158 }
34159
34160 if (defined('PHP_ZTS') && PHP_ZTS) {
34161 $phpzts = new CompletePackage('php-zts', $version, $prettyVersion);
34162 $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety');
34163 $this->addPackage($phpzts);
34164 }
34165
34166 if (PHP_INT_SIZE === 8) {
34167 $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
34168 $php64->setDescription('The PHP interpreter, 64bit');
34169 $this->addPackage($php64);
34170 }
34171
34172
34173  
34174  if (defined('AF_INET6') || Silencer::call('inet_pton', '::') !== false) {
34175 $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion);
34176 $phpIpv6->setDescription('The PHP interpreter, with IPv6 support');
34177 $this->addPackage($phpIpv6);
34178 }
34179
34180 $loadedExtensions = get_loaded_extensions();
34181
34182
34183  foreach ($loadedExtensions as $name) {
34184 if (in_array($name, array('standard', 'Core'))) {
34185 continue;
34186 }
34187
34188 $reflExt = new \ReflectionExtension($name);
34189 $prettyVersion = $reflExt->getVersion();
34190 $this->addExtension($name, $prettyVersion);
34191 }
34192
34193
34194  if (!in_array('xdebug', $loadedExtensions, true) && ($prettyVersion = strval(getenv(XdebugHandler::ENV_VERSION)))) {
34195 $this->addExtension('xdebug', $prettyVersion);
34196 }
34197
34198
34199  
34200  
34201  foreach ($loadedExtensions as $name) {
34202 $prettyVersion = null;
34203 $description = 'The '.$name.' PHP library';
34204 switch ($name) {
34205 case 'curl':
34206 $curlVersion = curl_version();
34207 $prettyVersion = $curlVersion['version'];
34208 break;
34209
34210 case 'iconv':
34211 $prettyVersion = ICONV_VERSION;
34212 break;
34213
34214 case 'intl':
34215 $name = 'ICU';
34216 if (defined('INTL_ICU_VERSION')) {
34217 $prettyVersion = INTL_ICU_VERSION;
34218 } else {
34219 $reflector = new \ReflectionExtension('intl');
34220
34221 ob_start();
34222 $reflector->info();
34223 $output = ob_get_clean();
34224
34225 preg_match('/^ICU version => (.*)$/m', $output, $matches);
34226 $prettyVersion = $matches[1];
34227 }
34228
34229 break;
34230
34231 case 'libxml':
34232 $prettyVersion = LIBXML_DOTTED_VERSION;
34233 break;
34234
34235 case 'openssl':
34236 $prettyVersion = preg_replace_callback('{^(?:OpenSSL|LibreSSL)?\s*([0-9.]+)([a-z]*).*}i', function ($match) {
34237 if (empty($match[2])) {
34238 return $match[1];
34239 }
34240
34241
34242  
34243
34244 if (!preg_match('{^z*[a-z]$}', $match[2])) {
34245
34246  return 0;
34247 }
34248
34249 $len = strlen($match[2]);
34250 $patchVersion = ($len - 1) * 26; 
34251  $patchVersion += ord($match[2][$len - 1]) - 96;
34252
34253 return $match[1].'.'.$patchVersion;
34254 }, OPENSSL_VERSION_TEXT);
34255
34256 $description = OPENSSL_VERSION_TEXT;
34257 break;
34258
34259 case 'pcre':
34260 $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION);
34261 break;
34262
34263 case 'uuid':
34264 $prettyVersion = phpversion('uuid');
34265 break;
34266
34267 case 'xsl':
34268 $prettyVersion = LIBXSLT_DOTTED_VERSION;
34269 break;
34270
34271 default:
34272
34273  continue 2;
34274 }
34275
34276 try {
34277 $version = $this->versionParser->normalize($prettyVersion);
34278 } catch (\UnexpectedValueException $e) {
34279 continue;
34280 }
34281
34282 $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
34283 $lib->setDescription($description);
34284 $this->addPackage($lib);
34285 }
34286
34287 if (defined('HHVM_VERSION')) {
34288 try {
34289 $prettyVersion = HHVM_VERSION;
34290 $version = $this->versionParser->normalize($prettyVersion);
34291 } catch (\UnexpectedValueException $e) {
34292 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION);
34293 $version = $this->versionParser->normalize($prettyVersion);
34294 }
34295
34296 $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
34297 $hhvm->setDescription('The HHVM Runtime (64bit)');
34298 $this->addPackage($hhvm);
34299 }
34300 }
34301
34302
34303
34304
34305 public function addPackage(PackageInterface $package)
34306 {
34307
34308  if (isset($this->overrides[$package->getName()])) {
34309 $overrider = $this->findPackage($package->getName(), '*');
34310 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
34311
34312 return;
34313 }
34314
34315
34316  if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
34317 $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
34318 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
34319
34320 return;
34321 }
34322
34323 parent::addPackage($package);
34324 }
34325
34326 private function addOverriddenPackage(array $override, $name = null)
34327 {
34328 $version = $this->versionParser->normalize($override['version']);
34329 $package = new CompletePackage($name ?: $override['name'], $version, $override['version']);
34330 $package->setDescription('Package overridden via config.platform');
34331 $package->setExtra(array('config.platform' => true));
34332 parent::addPackage($package);
34333
34334 return $package;
34335 }
34336
34337
34338
34339
34340
34341
34342
34343 private function addExtension($name, $prettyVersion)
34344 {
34345 $extraDescription = null;
34346
34347 try {
34348 $version = $this->versionParser->normalize($prettyVersion);
34349 } catch (\UnexpectedValueException $e) {
34350 $extraDescription = ' (actual version: '.$prettyVersion.')';
34351 if (preg_match('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) {
34352 $prettyVersion = $match[1];
34353 } else {
34354 $prettyVersion = '0';
34355 }
34356 $version = $this->versionParser->normalize($prettyVersion);
34357 }
34358
34359 $packageName = $this->buildPackageName($name);
34360 $ext = new CompletePackage($packageName, $version, $prettyVersion);
34361 $ext->setDescription('The '.$name.' PHP extension'.$extraDescription);
34362 $this->addPackage($ext);
34363 }
34364
34365 private function buildPackageName($name)
34366 {
34367 return 'ext-' . str_replace(' ', '-', $name);
34368 }
34369 }
34370 <?php
34371
34372
34373
34374
34375
34376
34377
34378
34379
34380
34381
34382 namespace Composer\Repository;
34383
34384 use Composer\Factory;
34385 use Composer\IO\IOInterface;
34386 use Composer\Config;
34387 use Composer\EventDispatcher\EventDispatcher;
34388 use Composer\Util\RemoteFilesystem;
34389 use Composer\Json\JsonFile;
34390
34391
34392
34393
34394 class RepositoryFactory
34395 {
34396
34397
34398
34399
34400
34401
34402
34403 public static function configFromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
34404 {
34405 if (0 === strpos($repository, 'http')) {
34406 $repoConfig = array('type' => 'composer', 'url' => $repository);
34407 } elseif ("json" === pathinfo($repository, PATHINFO_EXTENSION)) {
34408 $json = new JsonFile($repository, Factory::createRemoteFilesystem($io, $config));
34409 $data = $json->read();
34410 if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
34411 $repoConfig = array('type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/'));
34412 } elseif ($allowFilesystem) {
34413 $repoConfig = array('type' => 'filesystem', 'json' => $json);
34414 } else {
34415 throw new \InvalidArgumentException("Invalid repository URL ($repository) given. This file does not contain a valid composer repository.");
34416 }
34417 } elseif ('{' === substr($repository, 0, 1)) {
34418
34419  $repoConfig = JsonFile::parseJson($repository);
34420 } else {
34421 throw new \InvalidArgumentException("Invalid repository url ($repository) given. Has to be a .json file, an http url or a JSON object.");
34422 }
34423
34424 return $repoConfig;
34425 }
34426
34427
34428
34429
34430
34431
34432
34433
34434 public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
34435 {
34436 $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
34437
34438 return static::createRepo($io, $config, $repoConfig);
34439 }
34440
34441
34442
34443
34444
34445
34446
34447 public static function createRepo(IOInterface $io, Config $config, array $repoConfig)
34448 {
34449 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
34450 $repos = static::createRepos($rm, array($repoConfig));
34451
34452 return reset($repos);
34453 }
34454
34455
34456
34457
34458
34459
34460
34461 public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
34462 {
34463 if (!$config) {
34464 $config = Factory::createConfig($io);
34465 }
34466 if (!$rm) {
34467 if (!$io) {
34468 throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
34469 }
34470 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
34471 }
34472
34473 return static::createRepos($rm, $config->getRepositories());
34474 }
34475
34476
34477
34478
34479
34480
34481
34482
34483 public static function manager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
34484 {
34485 $rm = new RepositoryManager($io, $config, $eventDispatcher, $rfs);
34486 $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
34487 $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
34488 $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
34489 $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
34490 $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
34491 $rm->setRepositoryClass('github', 'Composer\Repository\VcsRepository');
34492 $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
34493 $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
34494 $rm->setRepositoryClass('fossil', 'Composer\Repository\VcsRepository');
34495 $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
34496 $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
34497 $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
34498 $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
34499
34500 return $rm;
34501 }
34502
34503
34504
34505
34506 private static function createRepos(RepositoryManager $rm, array $repoConfigs)
34507 {
34508 $repos = array();
34509
34510 foreach ($repoConfigs as $index => $repo) {
34511 if (is_string($repo)) {
34512 throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
34513 }
34514 if (!is_array($repo)) {
34515 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') should be an array, '.gettype($repo).' given');
34516 }
34517 if (!isset($repo['type'])) {
34518 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') must have a type defined');
34519 }
34520 $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
34521 while (isset($repos[$name])) {
34522 $name .= '2';
34523 }
34524 if ($repo['type'] === 'filesystem') {
34525 $repos[$name] = new FilesystemRepository($repo['json']);
34526 } else {
34527 $repos[$name] = $rm->createRepository($repo['type'], $repo, $index);
34528 }
34529 }
34530
34531 return $repos;
34532 }
34533 }
34534 <?php
34535
34536
34537
34538
34539
34540
34541
34542
34543
34544
34545
34546 namespace Composer\Repository;
34547
34548 use Composer\Package\PackageInterface;
34549
34550
34551
34552
34553
34554
34555
34556
34557 interface RepositoryInterface extends \Countable
34558 {
34559 const SEARCH_FULLTEXT = 0;
34560 const SEARCH_NAME = 1;
34561
34562
34563
34564
34565
34566
34567
34568
34569 public function hasPackage(PackageInterface $package);
34570
34571
34572
34573
34574
34575
34576
34577
34578
34579 public function findPackage($name, $constraint);
34580
34581
34582
34583
34584
34585
34586
34587
34588
34589 public function findPackages($name, $constraint = null);
34590
34591
34592
34593
34594
34595
34596 public function getPackages();
34597
34598
34599
34600
34601
34602
34603
34604
34605
34606 public function search($query, $mode = 0);
34607 }
34608 <?php
34609
34610
34611
34612
34613
34614
34615
34616
34617
34618
34619
34620 namespace Composer\Repository;
34621
34622 use Composer\IO\IOInterface;
34623 use Composer\Config;
34624 use Composer\EventDispatcher\EventDispatcher;
34625 use Composer\Package\PackageInterface;
34626 use Composer\Util\RemoteFilesystem;
34627
34628
34629
34630
34631
34632
34633
34634
34635 class RepositoryManager
34636 {
34637 private $localRepository;
34638 private $repositories = array();
34639 private $repositoryClasses = array();
34640 private $io;
34641 private $config;
34642 private $eventDispatcher;
34643 private $rfs;
34644
34645 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
34646 {
34647 $this->io = $io;
34648 $this->config = $config;
34649 $this->eventDispatcher = $eventDispatcher;
34650 $this->rfs = $rfs;
34651 }
34652
34653
34654
34655
34656
34657
34658
34659
34660
34661 public function findPackage($name, $constraint)
34662 {
34663 foreach ($this->repositories as $repository) {
34664 if ($package = $repository->findPackage($name, $constraint)) {
34665 return $package;
34666 }
34667 }
34668
34669 return null;
34670 }
34671
34672
34673
34674
34675
34676
34677
34678
34679
34680 public function findPackages($name, $constraint)
34681 {
34682 $packages = array();
34683
34684 foreach ($this->repositories as $repository) {
34685 $packages = array_merge($packages, $repository->findPackages($name, $constraint));
34686 }
34687
34688 return $packages;
34689 }
34690
34691
34692
34693
34694
34695
34696 public function addRepository(RepositoryInterface $repository)
34697 {
34698 $this->repositories[] = $repository;
34699 }
34700
34701
34702
34703
34704
34705
34706
34707
34708 public function prependRepository(RepositoryInterface $repository)
34709 {
34710 array_unshift($this->repositories, $repository);
34711 }
34712
34713
34714
34715
34716
34717
34718
34719
34720
34721
34722 public function createRepository($type, $config, $name = null)
34723 {
34724 if (!isset($this->repositoryClasses[$type])) {
34725 throw new \InvalidArgumentException('Repository type is not registered: '.$type);
34726 }
34727
34728 if (isset($config['packagist']) && false === $config['packagist']) {
34729 $this->io->writeError('<warning>Repository "'.$name.'" ('.json_encode($config).') has a packagist key which should be in its own repository definition</warning>');
34730 }
34731
34732 $class = $this->repositoryClasses[$type];
34733
34734 $reflMethod = new \ReflectionMethod($class, '__construct');
34735 $params = $reflMethod->getParameters();
34736 if (isset($params[4]) && $params[4]->getClass() && $params[4]->getClass()->getName() === 'Composer\Util\RemoteFilesystem') {
34737 return new $class($config, $this->io, $this->config, $this->eventDispatcher, $this->rfs);
34738 }
34739
34740 return new $class($config, $this->io, $this->config, $this->eventDispatcher);
34741 }
34742
34743
34744
34745
34746
34747
34748
34749 public function setRepositoryClass($type, $class)
34750 {
34751 $this->repositoryClasses[$type] = $class;
34752 }
34753
34754
34755
34756
34757
34758
34759 public function getRepositories()
34760 {
34761 return $this->repositories;
34762 }
34763
34764
34765
34766
34767
34768
34769 public function setLocalRepository(WritableRepositoryInterface $repository)
34770 {
34771 $this->localRepository = $repository;
34772 }
34773
34774
34775
34776
34777
34778
34779 public function getLocalRepository()
34780 {
34781 return $this->localRepository;
34782 }
34783 }
34784 <?php
34785
34786
34787
34788
34789
34790
34791
34792
34793
34794
34795
34796 namespace Composer\Repository;
34797
34798
34799
34800
34801
34802
34803 class RepositorySecurityException extends \Exception
34804 {
34805 }
34806 <?php
34807
34808
34809
34810
34811
34812
34813
34814
34815
34816
34817
34818 namespace Composer\Repository\Vcs;
34819
34820 use Composer\Cache;
34821 use Composer\Downloader\TransportException;
34822 use Composer\Json\JsonFile;
34823 use Composer\Util\Bitbucket;
34824
34825 abstract class BitbucketDriver extends VcsDriver
34826 {
34827
34828 protected $cache;
34829 protected $owner;
34830 protected $repository;
34831 protected $hasIssues;
34832 protected $rootIdentifier;
34833 protected $tags;
34834 protected $branches;
34835 protected $infoCache = array();
34836 protected $branchesUrl = '';
34837 protected $tagsUrl = '';
34838 protected $homeUrl = '';
34839 protected $website = '';
34840 protected $cloneHttpsUrl = '';
34841
34842
34843
34844
34845 protected $fallbackDriver;
34846
34847 protected $vcsType;
34848
34849
34850
34851
34852 public function initialize()
34853 {
34854 preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#', $this->url, $match);
34855 $this->owner = $match[1];
34856 $this->repository = $match[2];
34857 $this->originUrl = 'bitbucket.org';
34858 $this->cache = new Cache(
34859 $this->io,
34860 implode('/', array(
34861 $this->config->get('cache-repo-dir'),
34862 $this->originUrl,
34863 $this->owner,
34864 $this->repository,
34865 ))
34866 );
34867 }
34868
34869
34870
34871
34872 public function getUrl()
34873 {
34874 if ($this->fallbackDriver) {
34875 return $this->fallbackDriver->getUrl();
34876 }
34877
34878 return $this->cloneHttpsUrl;
34879 }
34880
34881
34882
34883
34884
34885
34886
34887 protected function getRepoData()
34888 {
34889 $resource = sprintf(
34890 'https://api.bitbucket.org/2.0/repositories/%s/%s?%s',
34891 $this->owner,
34892 $this->repository,
34893 http_build_query(
34894 array('fields' => '-project,-owner'),
34895 null,
34896 '&'
34897 )
34898 );
34899
34900 $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource);
34901 if ($this->fallbackDriver) {
34902 return false;
34903 }
34904 $this->parseCloneUrls($repoData['links']['clone']);
34905
34906 $this->hasIssues = !empty($repoData['has_issues']);
34907 $this->branchesUrl = $repoData['links']['branches']['href'];
34908 $this->tagsUrl = $repoData['links']['tags']['href'];
34909 $this->homeUrl = $repoData['links']['html']['href'];
34910 $this->website = $repoData['website'];
34911 $this->vcsType = $repoData['scm'];
34912
34913 return true;
34914 }
34915
34916
34917
34918
34919 public function getComposerInformation($identifier)
34920 {
34921 if ($this->fallbackDriver) {
34922 return $this->fallbackDriver->getComposerInformation($identifier);
34923 }
34924
34925 if (!isset($this->infoCache[$identifier])) {
34926 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
34927 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
34928 }
34929
34930 $composer = $this->getBaseComposerInformation($identifier);
34931
34932
34933  if (!isset($composer['support']['source'])) {
34934 $label = array_search(
34935 $identifier,
34936 $this->getTags()
34937 ) ?: array_search(
34938 $identifier,
34939 $this->getBranches()
34940 ) ?: $identifier;
34941
34942 if (array_key_exists($label, $tags = $this->getTags())) {
34943 $hash = $tags[$label];
34944 } elseif (array_key_exists($label, $branches = $this->getBranches())) {
34945 $hash = $branches[$label];
34946 }
34947
34948 if (! isset($hash)) {
34949 $composer['support']['source'] = sprintf(
34950 'https://%s/%s/%s/src',
34951 $this->originUrl,
34952 $this->owner,
34953 $this->repository
34954 );
34955 } else {
34956 $composer['support']['source'] = sprintf(
34957 'https://%s/%s/%s/src/%s/?at=%s',
34958 $this->originUrl,
34959 $this->owner,
34960 $this->repository,
34961 $hash,
34962 $label
34963 );
34964 }
34965 }
34966 if (!isset($composer['support']['issues']) && $this->hasIssues) {
34967 $composer['support']['issues'] = sprintf(
34968 'https://%s/%s/%s/issues',
34969 $this->originUrl,
34970 $this->owner,
34971 $this->repository
34972 );
34973 }
34974 if (!isset($composer['homepage'])) {
34975 $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
34976 }
34977
34978 $this->infoCache[$identifier] = $composer;
34979
34980 if ($this->shouldCache($identifier)) {
34981 $this->cache->write($identifier, json_encode($composer));
34982 }
34983 }
34984
34985 return $this->infoCache[$identifier];
34986 }
34987
34988
34989
34990
34991 public function getFileContent($file, $identifier)
34992 {
34993 if ($this->fallbackDriver) {
34994 return $this->fallbackDriver->getFileContent($file, $identifier);
34995 }
34996
34997 $resource = sprintf(
34998 'https://api.bitbucket.org/1.0/repositories/%s/%s/raw/%s/%s',
34999 $this->owner,
35000 $this->repository,
35001 $identifier,
35002 $file
35003 );
35004
35005 return $this->getContentsWithOAuthCredentials($resource);
35006 }
35007
35008
35009
35010
35011 public function getChangeDate($identifier)
35012 {
35013 if ($this->fallbackDriver) {
35014 return $this->fallbackDriver->getChangeDate($identifier);
35015 }
35016
35017 $resource = sprintf(
35018 'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
35019 $this->owner,
35020 $this->repository,
35021 $identifier
35022 );
35023 $commit = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35024
35025 return new \DateTime($commit['date']);
35026 }
35027
35028
35029
35030
35031 public function getSource($identifier)
35032 {
35033 if ($this->fallbackDriver) {
35034 return $this->fallbackDriver->getSource($identifier);
35035 }
35036
35037 return array('type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier);
35038 }
35039
35040
35041
35042
35043 public function getDist($identifier)
35044 {
35045 if ($this->fallbackDriver) {
35046 return $this->fallbackDriver->getDist($identifier);
35047 }
35048
35049 $url = sprintf(
35050 'https://bitbucket.org/%s/%s/get/%s.zip',
35051 $this->owner,
35052 $this->repository,
35053 $identifier
35054 );
35055
35056 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
35057 }
35058
35059
35060
35061
35062 public function getTags()
35063 {
35064 if ($this->fallbackDriver) {
35065 return $this->fallbackDriver->getTags();
35066 }
35067
35068 if (null === $this->tags) {
35069 $this->tags = array();
35070 $resource = sprintf(
35071 '%s?%s',
35072 $this->tagsUrl,
35073 http_build_query(
35074 array(
35075 'pagelen' => 100,
35076 'fields' => 'values.name,values.target.hash,next',
35077 'sort' => '-target.date',
35078 ),
35079 null,
35080 '&'
35081 )
35082 );
35083 $hasNext = true;
35084 while ($hasNext) {
35085 $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35086 foreach ($tagsData['values'] as $data) {
35087 $this->tags[$data['name']] = $data['target']['hash'];
35088 }
35089 if (empty($tagsData['next'])) {
35090 $hasNext = false;
35091 } else {
35092 $resource = $tagsData['next'];
35093 }
35094 }
35095 if ($this->vcsType === 'hg') {
35096 unset($this->tags['tip']);
35097 }
35098 }
35099
35100 return $this->tags;
35101 }
35102
35103
35104
35105
35106 public function getBranches()
35107 {
35108 if ($this->fallbackDriver) {
35109 return $this->fallbackDriver->getBranches();
35110 }
35111
35112 if (null === $this->branches) {
35113 $this->branches = array();
35114 $resource = sprintf(
35115 '%s?%s',
35116 $this->branchesUrl,
35117 http_build_query(
35118 array(
35119 'pagelen' => 100,
35120 'fields' => 'values.name,values.target.hash,values.heads,next',
35121 'sort' => '-target.date',
35122 ),
35123 null,
35124 '&'
35125 )
35126 );
35127 $hasNext = true;
35128 while ($hasNext) {
35129 $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35130 foreach ($branchData['values'] as $data) {
35131
35132  if ($this->vcsType === 'hg' && empty($data['heads'])) {
35133 continue;
35134 }
35135
35136 $this->branches[$data['name']] = $data['target']['hash'];
35137 }
35138 if (empty($branchData['next'])) {
35139 $hasNext = false;
35140 } else {
35141 $resource = $branchData['next'];
35142 }
35143 }
35144 }
35145
35146 return $this->branches;
35147 }
35148
35149
35150
35151
35152
35153
35154
35155
35156
35157 protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false)
35158 {
35159 try {
35160 return parent::getContents($url);
35161 } catch (TransportException $e) {
35162 $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem);
35163
35164 if (403 === $e->getCode() || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) {
35165 if (!$this->io->hasAuthentication($this->originUrl)
35166 && $bitbucketUtil->authorizeOAuth($this->originUrl)
35167 ) {
35168 return parent::getContents($url);
35169 }
35170
35171 if (!$this->io->isInteractive() && $fetchingRepoData) {
35172 return $this->attemptCloneFallback();
35173 }
35174 }
35175
35176 throw $e;
35177 }
35178 }
35179
35180
35181
35182
35183
35184
35185 abstract protected function generateSshUrl();
35186
35187 protected function attemptCloneFallback()
35188 {
35189 try {
35190 $this->setupFallbackDriver($this->generateSshUrl());
35191 } catch (\RuntimeException $e) {
35192 $this->fallbackDriver = null;
35193
35194 $this->io->writeError(
35195 '<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode'
35196 . ' so that you can enter your Bitbucket OAuth consumer credentials</error>'
35197 );
35198 throw $e;
35199 }
35200 }
35201
35202
35203
35204
35205
35206 abstract protected function setupFallbackDriver($url);
35207
35208
35209
35210
35211
35212 protected function parseCloneUrls(array $cloneLinks)
35213 {
35214 foreach ($cloneLinks as $cloneLink) {
35215 if ($cloneLink['name'] === 'https') {
35216
35217  
35218  $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']);
35219 }
35220 }
35221 }
35222
35223
35224
35225
35226 protected function getMainBranchData()
35227 {
35228 $resource = sprintf(
35229 'https://api.bitbucket.org/1.0/repositories/%s/%s/main-branch',
35230 $this->owner,
35231 $this->repository
35232 );
35233
35234 return JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35235 }
35236 }
35237 <?php
35238
35239
35240
35241
35242
35243
35244
35245
35246
35247
35248
35249 namespace Composer\Repository\Vcs;
35250
35251 use Composer\Config;
35252 use Composer\Util\ProcessExecutor;
35253 use Composer\Util\Filesystem;
35254 use Composer\IO\IOInterface;
35255
35256
35257
35258
35259 class FossilDriver extends VcsDriver
35260 {
35261 protected $tags;
35262 protected $branches;
35263 protected $rootIdentifier;
35264 protected $repoFile;
35265 protected $checkoutDir;
35266 protected $infoCache = array();
35267
35268
35269
35270
35271 public function initialize()
35272 {
35273 if (Filesystem::isLocalPath($this->url)) {
35274 $this->checkoutDir = $this->url;
35275 } else {
35276 $this->repoFile = $this->config->get('cache-repo-dir') . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '.fossil';
35277 $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
35278
35279 $fs = new Filesystem();
35280 $fs->ensureDirectoryExists($this->checkoutDir);
35281
35282 if (!is_writable(dirname($this->checkoutDir))) {
35283 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.');
35284 }
35285
35286
35287  $this->config->prohibitUrlByConfig($this->url, $this->io);
35288
35289
35290  if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) {
35291 if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) {
35292 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
35293 }
35294 } else {
35295
35296  $fs->removeDirectory($this->checkoutDir);
35297 $fs->remove($this->repoFile);
35298
35299 $fs->ensureDirectoryExists($this->checkoutDir);
35300
35301 if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
35302 $output = $this->process->getErrorOutput();
35303
35304 if (0 !== $this->process->execute('fossil version', $ignoredOutput)) {
35305 throw new \RuntimeException('Failed to clone '.$this->url.', fossil was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput());
35306 }
35307
35308 throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output);
35309 }
35310
35311 if (0 !== $this->process->execute(sprintf('fossil open %s', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
35312 $output = $this->process->getErrorOutput();
35313
35314 throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output);
35315 }
35316 }
35317 }
35318
35319 $this->getTags();
35320 $this->getBranches();
35321 }
35322
35323
35324
35325
35326 public function getRootIdentifier()
35327 {
35328 if (null === $this->rootIdentifier) {
35329 $this->rootIdentifier = 'trunk';
35330 }
35331
35332 return $this->rootIdentifier;
35333 }
35334
35335
35336
35337
35338 public function getUrl()
35339 {
35340 return $this->url;
35341 }
35342
35343
35344
35345
35346 public function getSource($identifier)
35347 {
35348 return array('type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier);
35349 }
35350
35351
35352
35353
35354 public function getDist($identifier)
35355 {
35356 return null;
35357 }
35358
35359
35360
35361
35362 public function getFileContent($file, $identifier)
35363 {
35364 $command = sprintf('fossil cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
35365 $this->process->execute($command, $content, $this->checkoutDir);
35366
35367 if (!trim($content)) {
35368 return null;
35369 }
35370
35371 return $content;
35372 }
35373
35374
35375
35376
35377 public function getChangeDate($identifier)
35378 {
35379 $this->process->execute(sprintf('fossil finfo composer.json | head -n 2 | tail -n 1 | awk \'{print $1}\''), $output, $this->checkoutDir);
35380
35381 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
35382 }
35383
35384
35385
35386
35387 public function getTags()
35388 {
35389 if (null === $this->tags) {
35390 $tags = array();
35391
35392 $this->process->execute('fossil tag list', $output, $this->checkoutDir);
35393 foreach ($this->process->splitLines($output) as $tag) {
35394 $tags[$tag] = $tag;
35395 }
35396
35397 $this->tags = $tags;
35398 }
35399
35400 return $this->tags;
35401 }
35402
35403
35404
35405
35406 public function getBranches()
35407 {
35408 if (null === $this->branches) {
35409 $branches = array();
35410 $bookmarks = array();
35411
35412 $this->process->execute('fossil branch list', $output, $this->checkoutDir);
35413 foreach ($this->process->splitLines($output) as $branch) {
35414 $branch = trim(preg_replace('/^\*/', '', trim($branch)));
35415 $branches[$branch] = $branch;
35416 }
35417
35418 $this->branches = $branches;
35419 }
35420
35421 return $this->branches;
35422 }
35423
35424
35425
35426
35427 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35428 {
35429 if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) {
35430 return true;
35431 }
35432
35433 if (preg_match('!/fossil/|\.fossil!', $url)) {
35434 return true;
35435 }
35436
35437
35438  if (Filesystem::isLocalPath($url)) {
35439 $url = Filesystem::getPlatformPath($url);
35440 if (!is_dir($url)) {
35441 return false;
35442 }
35443
35444 $process = new ProcessExecutor();
35445
35446  if ($process->execute('fossil info', $output, $url) === 0) {
35447 return true;
35448 }
35449 }
35450
35451 return false;
35452 }
35453 }
35454 <?php
35455
35456
35457
35458
35459
35460
35461
35462
35463
35464
35465
35466 namespace Composer\Repository\Vcs;
35467
35468 use Composer\Config;
35469 use Composer\IO\IOInterface;
35470
35471
35472
35473
35474 class GitBitbucketDriver extends BitbucketDriver
35475 {
35476
35477
35478
35479 public function getRootIdentifier()
35480 {
35481 if ($this->fallbackDriver) {
35482 return $this->fallbackDriver->getRootIdentifier();
35483 }
35484
35485 if (null === $this->rootIdentifier) {
35486 if (! $this->getRepoData()) {
35487 return $this->fallbackDriver->getRootIdentifier();
35488 }
35489
35490 if ($this->vcsType !== 'git') {
35491 throw new \RuntimeException(
35492 $this->url.' does not appear to be a git repository, use '.
35493 $this->cloneHttpsUrl.' if this is a mercurial bitbucket repository'
35494 );
35495 }
35496
35497 $mainBranchData = $this->getMainBranchData();
35498 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'master';
35499 }
35500
35501 return $this->rootIdentifier;
35502 }
35503
35504
35505
35506
35507 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35508 {
35509 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url)) {
35510 return false;
35511 }
35512
35513 if (!extension_loaded('openssl')) {
35514 $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
35515
35516 return false;
35517 }
35518
35519 return true;
35520 }
35521
35522
35523
35524
35525 protected function setupFallbackDriver($url)
35526 {
35527 $this->fallbackDriver = new GitDriver(
35528 array('url' => $url),
35529 $this->io,
35530 $this->config,
35531 $this->process,
35532 $this->remoteFilesystem
35533 );
35534 $this->fallbackDriver->initialize();
35535 }
35536
35537
35538
35539
35540 protected function generateSshUrl()
35541 {
35542 return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git';
35543 }
35544 }
35545 <?php
35546
35547
35548
35549
35550
35551
35552
35553
35554
35555
35556
35557 namespace Composer\Repository\Vcs;
35558
35559 use Composer\Util\ProcessExecutor;
35560 use Composer\Util\Filesystem;
35561 use Composer\Util\Git as GitUtil;
35562 use Composer\IO\IOInterface;
35563 use Composer\Cache;
35564 use Composer\Config;
35565
35566
35567
35568
35569 class GitDriver extends VcsDriver
35570 {
35571 protected $cache;
35572 protected $tags;
35573 protected $branches;
35574 protected $rootIdentifier;
35575 protected $repoDir;
35576 protected $infoCache = array();
35577
35578
35579
35580
35581 public function initialize()
35582 {
35583 if (Filesystem::isLocalPath($this->url)) {
35584 $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
35585 $this->repoDir = $this->url;
35586 $cacheUrl = realpath($this->url);
35587 } else {
35588 $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
35589
35590 GitUtil::cleanEnv();
35591
35592 $fs = new Filesystem();
35593 $fs->ensureDirectoryExists(dirname($this->repoDir));
35594
35595 if (!is_writable(dirname($this->repoDir))) {
35596 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
35597 }
35598
35599 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
35600 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.');
35601 }
35602
35603 $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
35604 if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
35605 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
35606 }
35607
35608 $cacheUrl = $this->url;
35609 }
35610
35611 $this->getTags();
35612 $this->getBranches();
35613
35614 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
35615 }
35616
35617
35618
35619
35620 public function getRootIdentifier()
35621 {
35622 if (null === $this->rootIdentifier) {
35623 $this->rootIdentifier = 'master';
35624
35625
35626  $this->process->execute('git branch --no-color', $output, $this->repoDir);
35627 $branches = $this->process->splitLines($output);
35628 if (!in_array('* master', $branches)) {
35629 foreach ($branches as $branch) {
35630 if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) {
35631 $this->rootIdentifier = $match[1];
35632 break;
35633 }
35634 }
35635 }
35636 }
35637
35638 return $this->rootIdentifier;
35639 }
35640
35641
35642
35643
35644 public function getUrl()
35645 {
35646 return $this->url;
35647 }
35648
35649
35650
35651
35652 public function getSource($identifier)
35653 {
35654 return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
35655 }
35656
35657
35658
35659
35660 public function getDist($identifier)
35661 {
35662 return null;
35663 }
35664
35665
35666
35667
35668 public function getFileContent($file, $identifier)
35669 {
35670 $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
35671 $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir);
35672
35673 if (!trim($content)) {
35674 return null;
35675 }
35676
35677 return $content;
35678 }
35679
35680
35681
35682
35683 public function getChangeDate($identifier)
35684 {
35685 $this->process->execute(sprintf(
35686 'git log -1 --format=%%at %s',
35687 ProcessExecutor::escape($identifier)
35688 ), $output, $this->repoDir);
35689
35690 return new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
35691 }
35692
35693
35694
35695
35696 public function getTags()
35697 {
35698 if (null === $this->tags) {
35699 $this->tags = array();
35700
35701 $this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir);
35702 foreach ($output = $this->process->splitLines($output) as $tag) {
35703 if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
35704 $this->tags[$match[2]] = $match[1];
35705 }
35706 }
35707 }
35708
35709 return $this->tags;
35710 }
35711
35712
35713
35714
35715 public function getBranches()
35716 {
35717 if (null === $this->branches) {
35718 $branches = array();
35719
35720 $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
35721 foreach ($this->process->splitLines($output) as $branch) {
35722 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
35723 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) {
35724 $branches[$match[1]] = $match[2];
35725 }
35726 }
35727 }
35728
35729 $this->branches = $branches;
35730 }
35731
35732 return $this->branches;
35733 }
35734
35735
35736
35737
35738 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35739 {
35740 if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
35741 return true;
35742 }
35743
35744
35745  if (Filesystem::isLocalPath($url)) {
35746 $url = Filesystem::getPlatformPath($url);
35747 if (!is_dir($url)) {
35748 return false;
35749 }
35750
35751 $process = new ProcessExecutor($io);
35752
35753  if ($process->execute('git tag', $output, $url) === 0) {
35754 return true;
35755 }
35756 }
35757
35758 if (!$deep) {
35759 return false;
35760 }
35761
35762 $process = new ProcessExecutor($io);
35763 if ($process->execute('git ls-remote --heads ' . ProcessExecutor::escape($url), $output) === 0) {
35764 return true;
35765 }
35766
35767 return false;
35768 }
35769 }
35770 <?php
35771
35772
35773
35774
35775
35776
35777
35778
35779
35780
35781
35782 namespace Composer\Repository\Vcs;
35783
35784 use Composer\Config;
35785 use Composer\Downloader\TransportException;
35786 use Composer\Json\JsonFile;
35787 use Composer\Cache;
35788 use Composer\IO\IOInterface;
35789 use Composer\Util\GitHub;
35790
35791
35792
35793
35794 class GitHubDriver extends VcsDriver
35795 {
35796 protected $cache;
35797 protected $owner;
35798 protected $repository;
35799 protected $tags;
35800 protected $branches;
35801 protected $rootIdentifier;
35802 protected $repoData;
35803 protected $hasIssues;
35804 protected $infoCache = array();
35805 protected $isPrivate = false;
35806
35807
35808
35809
35810
35811
35812 protected $gitDriver;
35813
35814
35815
35816
35817 public function initialize()
35818 {
35819 preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
35820 $this->owner = $match[3];
35821 $this->repository = $match[4];
35822 $this->originUrl = !empty($match[1]) ? $match[1] : $match[2];
35823 if ($this->originUrl === 'www.github.com') {
35824 $this->originUrl = 'github.com';
35825 }
35826 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
35827
35828 if (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api']) {
35829 $this->setupGitDriver($this->url);
35830
35831 return;
35832 }
35833
35834 $this->fetchRootIdentifier();
35835 }
35836
35837 public function getRepositoryUrl()
35838 {
35839 return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
35840 }
35841
35842
35843
35844
35845 public function getRootIdentifier()
35846 {
35847 if ($this->gitDriver) {
35848 return $this->gitDriver->getRootIdentifier();
35849 }
35850
35851 return $this->rootIdentifier;
35852 }
35853
35854
35855
35856
35857 public function getUrl()
35858 {
35859 if ($this->gitDriver) {
35860 return $this->gitDriver->getUrl();
35861 }
35862
35863 return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
35864 }
35865
35866
35867
35868
35869 protected function getApiUrl()
35870 {
35871 if ('github.com' === $this->originUrl) {
35872 $apiUrl = 'api.github.com';
35873 } else {
35874 $apiUrl = $this->originUrl . '/api/v3';
35875 }
35876
35877 return 'https://' . $apiUrl;
35878 }
35879
35880
35881
35882
35883 public function getSource($identifier)
35884 {
35885 if ($this->gitDriver) {
35886 return $this->gitDriver->getSource($identifier);
35887 }
35888 if ($this->isPrivate) {
35889
35890  
35891  $url = $this->generateSshUrl();
35892 } else {
35893 $url = $this->getUrl();
35894 }
35895
35896 return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
35897 }
35898
35899
35900
35901
35902 public function getDist($identifier)
35903 {
35904 $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
35905
35906 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
35907 }
35908
35909
35910
35911
35912 public function getComposerInformation($identifier)
35913 {
35914 if ($this->gitDriver) {
35915 return $this->gitDriver->getComposerInformation($identifier);
35916 }
35917
35918 if (!isset($this->infoCache[$identifier])) {
35919 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
35920 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
35921 }
35922
35923 $composer = $this->getBaseComposerInformation($identifier);
35924 if ($composer) {
35925
35926
35927  if (!isset($composer['support']['source'])) {
35928 $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
35929 $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
35930 }
35931 if (!isset($composer['support']['issues']) && $this->hasIssues) {
35932 $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
35933 }
35934 }
35935
35936 if ($this->shouldCache($identifier)) {
35937 $this->cache->write($identifier, json_encode($composer));
35938 }
35939
35940 $this->infoCache[$identifier] = $composer;
35941 }
35942
35943 return $this->infoCache[$identifier];
35944 }
35945
35946
35947
35948
35949 public function getFileContent($file, $identifier)
35950 {
35951 if ($this->gitDriver) {
35952 return $this->gitDriver->getFileContent($file, $identifier);
35953 }
35954
35955 $notFoundRetries = 2;
35956 while ($notFoundRetries) {
35957 try {
35958 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
35959 $resource = JsonFile::parseJson($this->getContents($resource));
35960 if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
35961 throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
35962 }
35963
35964 return $content;
35965 } catch (TransportException $e) {
35966 if (404 !== $e->getCode()) {
35967 throw $e;
35968 }
35969
35970
35971  
35972  $notFoundRetries--;
35973
35974 return null;
35975 }
35976 }
35977
35978 return null;
35979 }
35980
35981
35982
35983
35984 public function getChangeDate($identifier)
35985 {
35986 if ($this->gitDriver) {
35987 return $this->gitDriver->getChangeDate($identifier);
35988 }
35989
35990 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
35991 $commit = JsonFile::parseJson($this->getContents($resource), $resource);
35992
35993 return new \DateTime($commit['commit']['committer']['date']);
35994 }
35995
35996
35997
35998
35999 public function getTags()
36000 {
36001 if ($this->gitDriver) {
36002 return $this->gitDriver->getTags();
36003 }
36004 if (null === $this->tags) {
36005 $this->tags = array();
36006 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
36007
36008 do {
36009 $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
36010 foreach ($tagsData as $tag) {
36011 $this->tags[$tag['name']] = $tag['commit']['sha'];
36012 }
36013
36014 $resource = $this->getNextPage();
36015 } while ($resource);
36016 }
36017
36018 return $this->tags;
36019 }
36020
36021
36022
36023
36024 public function getBranches()
36025 {
36026 if ($this->gitDriver) {
36027 return $this->gitDriver->getBranches();
36028 }
36029 if (null === $this->branches) {
36030 $this->branches = array();
36031 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
36032
36033 $branchBlacklist = array('gh-pages');
36034
36035 do {
36036 $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
36037 foreach ($branchData as $branch) {
36038 $name = substr($branch['ref'], 11);
36039 if (!in_array($name, $branchBlacklist)) {
36040 $this->branches[$name] = $branch['object']['sha'];
36041 }
36042 }
36043
36044 $resource = $this->getNextPage();
36045 } while ($resource);
36046 }
36047
36048 return $this->branches;
36049 }
36050
36051
36052
36053
36054 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36055 {
36056 if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
36057 return false;
36058 }
36059
36060 $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
36061 if (!in_array(preg_replace('{^www\.}i', '', $originUrl), $config->get('github-domains'))) {
36062 return false;
36063 }
36064
36065 if (!extension_loaded('openssl')) {
36066 $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36067
36068 return false;
36069 }
36070
36071 return true;
36072 }
36073
36074
36075
36076
36077
36078
36079 public function getRepoData()
36080 {
36081 $this->fetchRootIdentifier();
36082
36083 return $this->repoData;
36084 }
36085
36086
36087
36088
36089
36090
36091 protected function generateSshUrl()
36092 {
36093 return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
36094 }
36095
36096
36097
36098
36099 protected function getContents($url, $fetchingRepoData = false)
36100 {
36101 try {
36102 return parent::getContents($url);
36103 } catch (TransportException $e) {
36104 $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
36105
36106 switch ($e->getCode()) {
36107 case 401:
36108 case 404:
36109
36110  if (!$fetchingRepoData) {
36111 throw $e;
36112 }
36113
36114 if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
36115 return parent::getContents($url);
36116 }
36117
36118 if (!$this->io->isInteractive()) {
36119 return $this->attemptCloneFallback();
36120 }
36121
36122 $scopesIssued = array();
36123 $scopesNeeded = array();
36124 if ($headers = $e->getHeaders()) {
36125 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-OAuth-Scopes')) {
36126 $scopesIssued = explode(' ', $scopes);
36127 }
36128 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
36129 $scopesNeeded = explode(' ', $scopes);
36130 }
36131 }
36132 $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
36133 if (!$headers || count($scopesFailed)) {
36134 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
36135 }
36136
36137 return parent::getContents($url);
36138
36139 case 403:
36140 if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
36141 return parent::getContents($url);
36142 }
36143
36144 if (!$this->io->isInteractive() && $fetchingRepoData) {
36145 return $this->attemptCloneFallback();
36146 }
36147
36148 $rateLimited = false;
36149 foreach ($e->getHeaders() as $header) {
36150 if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
36151 $rateLimited = true;
36152 }
36153 }
36154
36155 if (!$this->io->hasAuthentication($this->originUrl)) {
36156 if (!$this->io->isInteractive()) {
36157 $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>');
36158 throw $e;
36159 }
36160
36161 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>'.$this->url.'</info>)');
36162
36163 return parent::getContents($url);
36164 }
36165
36166 if ($rateLimited) {
36167 $rateLimit = $this->getRateLimit($e->getHeaders());
36168 $this->io->writeError(sprintf(
36169 '<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>',
36170 $rateLimit['limit'],
36171 $rateLimit['reset']
36172 ));
36173 }
36174
36175 throw $e;
36176
36177 default:
36178 throw $e;
36179 }
36180 }
36181 }
36182
36183
36184
36185
36186
36187
36188
36189
36190 protected function getRateLimit(array $headers)
36191 {
36192 $rateLimit = array(
36193 'limit' => '?',
36194 'reset' => '?',
36195 );
36196
36197 foreach ($headers as $header) {
36198 $header = trim($header);
36199 if (false === strpos($header, 'X-RateLimit-')) {
36200 continue;
36201 }
36202 list($type, $value) = explode(':', $header, 2);
36203 switch ($type) {
36204 case 'X-RateLimit-Limit':
36205 $rateLimit['limit'] = (int) trim($value);
36206 break;
36207 case 'X-RateLimit-Reset':
36208 $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
36209 break;
36210 }
36211 }
36212
36213 return $rateLimit;
36214 }
36215
36216
36217
36218
36219
36220
36221 protected function fetchRootIdentifier()
36222 {
36223 if ($this->repoData) {
36224 return;
36225 }
36226
36227 $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
36228
36229 $this->repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
36230 if (null === $this->repoData && null !== $this->gitDriver) {
36231 return;
36232 }
36233
36234 $this->owner = $this->repoData['owner']['login'];
36235 $this->repository = $this->repoData['name'];
36236
36237 $this->isPrivate = !empty($this->repoData['private']);
36238 if (isset($this->repoData['default_branch'])) {
36239 $this->rootIdentifier = $this->repoData['default_branch'];
36240 } elseif (isset($this->repoData['master_branch'])) {
36241 $this->rootIdentifier = $this->repoData['master_branch'];
36242 } else {
36243 $this->rootIdentifier = 'master';
36244 }
36245 $this->hasIssues = !empty($this->repoData['has_issues']);
36246 }
36247
36248 protected function attemptCloneFallback()
36249 {
36250 $this->isPrivate = true;
36251
36252 try {
36253
36254  
36255  
36256  
36257  $this->setupGitDriver($this->generateSshUrl());
36258
36259 return;
36260 } catch (\RuntimeException $e) {
36261 $this->gitDriver = null;
36262
36263 $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>');
36264 throw $e;
36265 }
36266 }
36267
36268 protected function setupGitDriver($url)
36269 {
36270 $this->gitDriver = new GitDriver(
36271 array('url' => $url),
36272 $this->io,
36273 $this->config,
36274 $this->process,
36275 $this->remoteFilesystem
36276 );
36277 $this->gitDriver->initialize();
36278 }
36279
36280 protected function getNextPage()
36281 {
36282 $headers = $this->remoteFilesystem->getLastHeaders();
36283 foreach ($headers as $header) {
36284 if (substr($header, 0, 5) === 'Link:') {
36285 $links = explode(',', substr($header, 5));
36286 foreach ($links as $link) {
36287 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
36288 return $match[1];
36289 }
36290 }
36291 }
36292 }
36293 }
36294 }
36295 <?php
36296
36297
36298
36299
36300
36301
36302
36303
36304
36305
36306
36307 namespace Composer\Repository\Vcs;
36308
36309 use Composer\Config;
36310 use Composer\Cache;
36311 use Composer\IO\IOInterface;
36312 use Composer\Json\JsonFile;
36313 use Composer\Downloader\TransportException;
36314 use Composer\Util\RemoteFilesystem;
36315 use Composer\Util\GitLab;
36316
36317
36318
36319
36320
36321
36322
36323 class GitLabDriver extends VcsDriver
36324 {
36325 private $scheme;
36326 private $namespace;
36327 private $repository;
36328
36329
36330
36331
36332 private $project;
36333
36334
36335
36336
36337 private $commits = array();
36338
36339
36340
36341
36342 private $tags;
36343
36344
36345
36346
36347 private $branches;
36348
36349
36350
36351
36352
36353
36354 protected $gitDriver;
36355
36356
36357
36358
36359
36360
36361 private $isPrivate = true;
36362
36363 const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
36364
36365
36366
36367
36368
36369
36370
36371
36372 public function initialize()
36373 {
36374 if (!preg_match(self::URL_REGEX, $this->url, $match)) {
36375 throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
36376 }
36377
36378 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
36379 $configuredDomains = $this->config->get('gitlab-domains');
36380 $urlParts = explode('/', $match['parts']);
36381
36382 $this->scheme = !empty($match['scheme'])
36383 ? $match['scheme']
36384 : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https')
36385 ;
36386 $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts);
36387 $this->namespace = implode('/', $urlParts);
36388 $this->repository = preg_replace('#(\.git)$#', '', $match['repo']);
36389
36390 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository);
36391
36392 $this->fetchProject();
36393 }
36394
36395
36396
36397
36398
36399
36400
36401 public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
36402 {
36403 $this->remoteFilesystem = $remoteFilesystem;
36404 }
36405
36406
36407
36408
36409 public function getFileContent($file, $identifier)
36410 {
36411 if ($this->gitDriver) {
36412 return $this->gitDriver->getFileContent($file, $identifier);
36413 }
36414
36415
36416  if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
36417 $branches = $this->getBranches();
36418 if (isset($branches[$identifier])) {
36419 $identifier = $branches[$identifier];
36420 }
36421 }
36422
36423 $resource = $this->getApiUrl().'/repository/files/'.$this->urlEncodeAll($file).'/raw?ref='.$identifier;
36424
36425 try {
36426 $content = $this->getContents($resource);
36427 } catch (TransportException $e) {
36428 if ($e->getCode() !== 404) {
36429 throw $e;
36430 }
36431
36432 return null;
36433 }
36434
36435 return $content;
36436 }
36437
36438
36439
36440
36441 public function getChangeDate($identifier)
36442 {
36443 if ($this->gitDriver) {
36444 return $this->gitDriver->getChangeDate($identifier);
36445 }
36446
36447 if (isset($this->commits[$identifier])) {
36448 return new \DateTime($this->commits[$identifier]['committed_date']);
36449 }
36450
36451 return new \DateTime();
36452 }
36453
36454
36455
36456
36457 public function getRepositoryUrl()
36458 {
36459 return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
36460 }
36461
36462
36463
36464
36465 public function getUrl()
36466 {
36467 if ($this->gitDriver) {
36468 return $this->gitDriver->getUrl();
36469 }
36470
36471 return $this->project['web_url'];
36472 }
36473
36474
36475
36476
36477 public function getDist($identifier)
36478 {
36479 $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
36480
36481 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
36482 }
36483
36484
36485
36486
36487 public function getSource($identifier)
36488 {
36489 if ($this->gitDriver) {
36490 return $this->gitDriver->getSource($identifier);
36491 }
36492
36493 return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
36494 }
36495
36496
36497
36498
36499 public function getRootIdentifier()
36500 {
36501 if ($this->gitDriver) {
36502 return $this->gitDriver->getRootIdentifier();
36503 }
36504
36505 return $this->project['default_branch'];
36506 }
36507
36508
36509
36510
36511 public function getBranches()
36512 {
36513 if ($this->gitDriver) {
36514 return $this->gitDriver->getBranches();
36515 }
36516
36517 if (!$this->branches) {
36518 $this->branches = $this->getReferences('branches');
36519 }
36520
36521 return $this->branches;
36522 }
36523
36524
36525
36526
36527 public function getTags()
36528 {
36529 if ($this->gitDriver) {
36530 return $this->gitDriver->getTags();
36531 }
36532
36533 if (!$this->tags) {
36534 $this->tags = $this->getReferences('tags');
36535 }
36536
36537 return $this->tags;
36538 }
36539
36540
36541
36542
36543 public function getApiUrl()
36544 {
36545 return $this->scheme.'://'.$this->originUrl.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository);
36546 }
36547
36548
36549
36550
36551
36552
36553
36554 private function urlEncodeAll($string)
36555 {
36556 $encoded = '';
36557 for ($i = 0; isset($string[$i]); $i++) {
36558 $character = $string[$i];
36559 if (!ctype_alnum($character) && !in_array($character, array('-', '_'), true)) {
36560 $character = '%' . sprintf('%02X', ord($character));
36561 }
36562 $encoded .= $character;
36563 }
36564
36565 return $encoded;
36566 }
36567
36568
36569
36570
36571
36572
36573 protected function getReferences($type)
36574 {
36575 $resource = $this->getApiUrl().'/repository/'.$type.'?per_page=100';
36576
36577 $references = array();
36578 do {
36579 $data = JsonFile::parseJson($this->getContents($resource), $resource);
36580
36581 foreach ($data as $datum) {
36582 $references[$datum['name']] = $datum['commit']['id'];
36583
36584
36585  
36586  $this->commits[$datum['commit']['id']] = $datum['commit'];
36587 }
36588 $resource = $this->getNextPage();
36589 } while ($resource);
36590
36591 return $references;
36592 }
36593
36594 protected function fetchProject()
36595 {
36596
36597  $resource = $this->getApiUrl();
36598 $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
36599 $this->isPrivate = $this->project['visibility'] !== 'public';
36600 }
36601
36602 protected function attemptCloneFallback()
36603 {
36604 try {
36605 if ($this->isPrivate === false) {
36606 $url = $this->generatePublicUrl();
36607 } else {
36608 $url = $this->generateSshUrl();
36609 }
36610
36611
36612  
36613  
36614  $this->setupGitDriver($url);
36615
36616 return;
36617 } catch (\RuntimeException $e) {
36618 $this->gitDriver = null;
36619
36620 $this->io->writeError('<error>Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials</error>');
36621 throw $e;
36622 }
36623 }
36624
36625
36626
36627
36628
36629
36630 protected function generateSshUrl()
36631 {
36632 return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git';
36633 }
36634
36635 protected function generatePublicUrl()
36636 {
36637 return 'https://' . $this->originUrl . '/'.$this->namespace.'/'.$this->repository.'.git';
36638 }
36639
36640 protected function setupGitDriver($url)
36641 {
36642 $this->gitDriver = new GitDriver(
36643 array('url' => $url),
36644 $this->io,
36645 $this->config,
36646 $this->process,
36647 $this->remoteFilesystem
36648 );
36649 $this->gitDriver->initialize();
36650 }
36651
36652
36653
36654
36655 protected function getContents($url, $fetchingRepoData = false)
36656 {
36657 try {
36658 $res = parent::getContents($url);
36659
36660 if ($fetchingRepoData) {
36661 $json = JsonFile::parseJson($res, $url);
36662
36663
36664  if (!isset($json['default_branch'])) {
36665 if (!empty($json['id'])) {
36666 $this->isPrivate = false;
36667 }
36668
36669 throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
36670 }
36671 }
36672
36673 return $res;
36674 } catch (TransportException $e) {
36675 $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);
36676
36677 switch ($e->getCode()) {
36678 case 401:
36679 case 404:
36680
36681  if (!$fetchingRepoData) {
36682 throw $e;
36683 }
36684
36685 if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
36686 return parent::getContents($url);
36687 }
36688
36689 if (!$this->io->isInteractive()) {
36690 return $this->attemptCloneFallback();
36691 }
36692 $this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
36693 $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
36694
36695 return parent::getContents($url);
36696
36697 case 403:
36698 if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
36699 return parent::getContents($url);
36700 }
36701
36702 if (!$this->io->isInteractive() && $fetchingRepoData) {
36703 return $this->attemptCloneFallback();
36704 }
36705
36706 throw $e;
36707
36708 default:
36709 throw $e;
36710 }
36711 }
36712 }
36713
36714
36715
36716
36717
36718
36719
36720 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36721 {
36722 if (!preg_match(self::URL_REGEX, $url, $match)) {
36723 return false;
36724 }
36725
36726 $scheme = !empty($match['scheme']) ? $match['scheme'] : null;
36727 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
36728 $urlParts = explode('/', $match['parts']);
36729
36730 if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts)) {
36731 return false;
36732 }
36733
36734 if ('https' === $scheme && !extension_loaded('openssl')) {
36735 $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36736
36737 return false;
36738 }
36739
36740 return true;
36741 }
36742
36743 private function getNextPage()
36744 {
36745 $headers = $this->remoteFilesystem->getLastHeaders();
36746 foreach ($headers as $header) {
36747 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
36748 $links = explode(',', $match[1]);
36749 foreach ($links as $link) {
36750 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
36751 return $match[1];
36752 }
36753 }
36754 }
36755 }
36756 }
36757
36758
36759
36760
36761
36762
36763
36764 private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts)
36765 {
36766 if (in_array($guessedDomain, $configuredDomains)) {
36767 return $guessedDomain;
36768 }
36769
36770 while (null !== ($part = array_shift($urlParts))) {
36771 $guessedDomain .= '/' . $part;
36772
36773 if (in_array($guessedDomain, $configuredDomains)) {
36774 return $guessedDomain;
36775 }
36776 }
36777
36778 return false;
36779 }
36780 }
36781 <?php
36782
36783
36784
36785
36786
36787
36788
36789
36790
36791
36792
36793 namespace Composer\Repository\Vcs;
36794
36795 use Composer\Config;
36796 use Composer\IO\IOInterface;
36797
36798
36799
36800
36801 class HgBitbucketDriver extends BitbucketDriver
36802 {
36803
36804
36805
36806 public function getRootIdentifier()
36807 {
36808 if ($this->fallbackDriver) {
36809 return $this->fallbackDriver->getRootIdentifier();
36810 }
36811
36812 if (null === $this->rootIdentifier) {
36813 if (! $this->getRepoData()) {
36814 return $this->fallbackDriver->getRootIdentifier();
36815 }
36816
36817 if ($this->vcsType !== 'hg') {
36818 throw new \RuntimeException(
36819 $this->url.' does not appear to be a mercurial repository, use '.
36820 $this->cloneHttpsUrl.' if this is a git bitbucket repository'
36821 );
36822 }
36823
36824 $mainBranchData = $this->getMainBranchData();
36825 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'default';
36826 }
36827
36828 return $this->rootIdentifier;
36829 }
36830
36831
36832
36833
36834 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36835 {
36836 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url)) {
36837 return false;
36838 }
36839
36840 if (!extension_loaded('openssl')) {
36841 $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36842
36843 return false;
36844 }
36845
36846 return true;
36847 }
36848
36849
36850
36851
36852 protected function setupFallbackDriver($url)
36853 {
36854 $this->fallbackDriver = new HgDriver(
36855 array('url' => $url),
36856 $this->io,
36857 $this->config,
36858 $this->process,
36859 $this->remoteFilesystem
36860 );
36861 $this->fallbackDriver->initialize();
36862 }
36863
36864
36865
36866
36867 protected function generateSshUrl()
36868 {
36869 return 'ssh://hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository;
36870 }
36871 }
36872 <?php
36873
36874
36875
36876
36877
36878
36879
36880
36881
36882
36883
36884 namespace Composer\Repository\Vcs;
36885
36886 use Composer\Config;
36887 use Composer\Util\ProcessExecutor;
36888 use Composer\Util\Filesystem;
36889 use Composer\IO\IOInterface;
36890
36891
36892
36893
36894 class HgDriver extends VcsDriver
36895 {
36896 protected $tags;
36897 protected $branches;
36898 protected $rootIdentifier;
36899 protected $repoDir;
36900 protected $infoCache = array();
36901
36902
36903
36904
36905 public function initialize()
36906 {
36907 if (Filesystem::isLocalPath($this->url)) {
36908 $this->repoDir = $this->url;
36909 } else {
36910 $cacheDir = $this->config->get('cache-vcs-dir');
36911 $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
36912
36913 $fs = new Filesystem();
36914 $fs->ensureDirectoryExists($cacheDir);
36915
36916 if (!is_writable(dirname($this->repoDir))) {
36917 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.');
36918 }
36919
36920
36921  $this->config->prohibitUrlByConfig($this->url, $this->io);
36922
36923
36924  if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) {
36925 if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) {
36926 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
36927 }
36928 } else {
36929
36930  $fs->removeDirectory($this->repoDir);
36931
36932 if (0 !== $this->process->execute(sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoDir)), $output, $cacheDir)) {
36933 $output = $this->process->getErrorOutput();
36934
36935 if (0 !== $this->process->execute('hg --version', $ignoredOutput)) {
36936 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());
36937 }
36938
36939 throw new \RuntimeException('Failed to clone '.$this->url.', could not read packages from it' . "\n\n" .$output);
36940 }
36941 }
36942 }
36943
36944 $this->getTags();
36945 $this->getBranches();
36946 }
36947
36948
36949
36950
36951 public function getRootIdentifier()
36952 {
36953 if (null === $this->rootIdentifier) {
36954 $this->process->execute(sprintf('hg tip --template "{node}"'), $output, $this->repoDir);
36955 $output = $this->process->splitLines($output);
36956 $this->rootIdentifier = $output[0];
36957 }
36958
36959 return $this->rootIdentifier;
36960 }
36961
36962
36963
36964
36965 public function getUrl()
36966 {
36967 return $this->url;
36968 }
36969
36970
36971
36972
36973 public function getSource($identifier)
36974 {
36975 return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
36976 }
36977
36978
36979
36980
36981 public function getDist($identifier)
36982 {
36983 return null;
36984 }
36985
36986
36987
36988
36989 public function getFileContent($file, $identifier)
36990 {
36991 $resource = sprintf('hg cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
36992 $this->process->execute($resource, $content, $this->repoDir);
36993
36994 if (!trim($content)) {
36995 return;
36996 }
36997
36998 return $content;
36999 }
37000
37001
37002
37003
37004 public function getChangeDate($identifier)
37005 {
37006 $this->process->execute(
37007 sprintf(
37008 'hg log --template "{date|rfc3339date}" -r %s',
37009 ProcessExecutor::escape($identifier)
37010 ),
37011 $output,
37012 $this->repoDir
37013 );
37014
37015 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
37016 }
37017
37018
37019
37020
37021 public function getTags()
37022 {
37023 if (null === $this->tags) {
37024 $tags = array();
37025
37026 $this->process->execute('hg tags', $output, $this->repoDir);
37027 foreach ($this->process->splitLines($output) as $tag) {
37028 if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
37029 $tags[$match[1]] = $match[2];
37030 }
37031 }
37032 unset($tags['tip']);
37033
37034 $this->tags = $tags;
37035 }
37036
37037 return $this->tags;
37038 }
37039
37040
37041
37042
37043 public function getBranches()
37044 {
37045 if (null === $this->branches) {
37046 $branches = array();
37047 $bookmarks = array();
37048
37049 $this->process->execute('hg branches', $output, $this->repoDir);
37050 foreach ($this->process->splitLines($output) as $branch) {
37051 if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) {
37052 $branches[$match[1]] = $match[2];
37053 }
37054 }
37055
37056 $this->process->execute('hg bookmarks', $output, $this->repoDir);
37057 foreach ($this->process->splitLines($output) as $branch) {
37058 if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) {
37059 $bookmarks[$match[1]] = $match[2];
37060 }
37061 }
37062
37063
37064  $this->branches = array_merge($bookmarks, $branches);
37065 }
37066
37067 return $this->branches;
37068 }
37069
37070
37071
37072
37073 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37074 {
37075 if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
37076 return true;
37077 }
37078
37079
37080  if (Filesystem::isLocalPath($url)) {
37081 $url = Filesystem::getPlatformPath($url);
37082 if (!is_dir($url)) {
37083 return false;
37084 }
37085
37086 $process = new ProcessExecutor();
37087
37088  if ($process->execute('hg summary', $output, $url) === 0) {
37089 return true;
37090 }
37091 }
37092
37093 if (!$deep) {
37094 return false;
37095 }
37096
37097 $processExecutor = new ProcessExecutor();
37098 $exit = $processExecutor->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);
37099
37100 return $exit === 0;
37101 }
37102 }
37103 <?php
37104
37105
37106
37107
37108
37109
37110
37111
37112
37113
37114
37115 namespace Composer\Repository\Vcs;
37116
37117 use Composer\Config;
37118 use Composer\IO\IOInterface;
37119 use Composer\Util\ProcessExecutor;
37120 use Composer\Util\Perforce;
37121
37122
37123
37124
37125 class PerforceDriver extends VcsDriver
37126 {
37127 protected $depot;
37128 protected $branch;
37129
37130 protected $perforce;
37131
37132
37133
37134
37135 public function initialize()
37136 {
37137 $this->depot = $this->repoConfig['depot'];
37138 $this->branch = '';
37139 if (!empty($this->repoConfig['branch'])) {
37140 $this->branch = $this->repoConfig['branch'];
37141 }
37142
37143 $this->initPerforce($this->repoConfig);
37144 $this->perforce->p4Login();
37145 $this->perforce->checkStream();
37146
37147 $this->perforce->writeP4ClientSpec();
37148 $this->perforce->connectClient();
37149
37150 return true;
37151 }
37152
37153 private function initPerforce($repoConfig)
37154 {
37155 if (!empty($this->perforce)) {
37156 return;
37157 }
37158
37159 $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
37160 $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
37161 }
37162
37163
37164
37165
37166 public function getFileContent($file, $identifier)
37167 {
37168 return $this->perforce->getFileContent($file, $identifier);
37169 }
37170
37171
37172
37173
37174 public function getChangeDate($identifier)
37175 {
37176 return null;
37177 }
37178
37179
37180
37181
37182 public function getRootIdentifier()
37183 {
37184 return $this->branch;
37185 }
37186
37187
37188
37189
37190 public function getBranches()
37191 {
37192 $branches = $this->perforce->getBranches();
37193
37194 return $branches;
37195 }
37196
37197
37198
37199
37200 public function getTags()
37201 {
37202 $tags = $this->perforce->getTags();
37203
37204 return $tags;
37205 }
37206
37207
37208
37209
37210 public function getDist($identifier)
37211 {
37212 return null;
37213 }
37214
37215
37216
37217
37218 public function getSource($identifier)
37219 {
37220 $source = array(
37221 'type' => 'perforce',
37222 'url' => $this->repoConfig['url'],
37223 'reference' => $identifier,
37224 'p4user' => $this->perforce->getUser(),
37225 );
37226
37227 return $source;
37228 }
37229
37230
37231
37232
37233 public function getUrl()
37234 {
37235 return $this->url;
37236 }
37237
37238
37239
37240
37241 public function hasComposerFile($identifier)
37242 {
37243 $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
37244 $composerInfoIdentifier = $identifier;
37245
37246 return !empty($composerInfo);
37247 }
37248
37249
37250
37251
37252 public function getContents($url)
37253 {
37254 return false;
37255 }
37256
37257
37258
37259
37260 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37261 {
37262 if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) {
37263 return Perforce::checkServerExists($url, new ProcessExecutor($io));
37264 }
37265
37266 return false;
37267 }
37268
37269
37270
37271
37272 public function cleanup()
37273 {
37274 $this->perforce->cleanupClientSpec();
37275 $this->perforce = null;
37276 }
37277
37278 public function getDepot()
37279 {
37280 return $this->depot;
37281 }
37282
37283 public function getBranch()
37284 {
37285 return $this->branch;
37286 }
37287 }
37288 <?php
37289
37290
37291
37292
37293
37294
37295
37296
37297
37298
37299
37300 namespace Composer\Repository\Vcs;
37301
37302 use Composer\Cache;
37303 use Composer\Config;
37304 use Composer\Json\JsonFile;
37305 use Composer\Util\ProcessExecutor;
37306 use Composer\Util\Filesystem;
37307 use Composer\Util\Svn as SvnUtil;
37308 use Composer\IO\IOInterface;
37309 use Composer\Downloader\TransportException;
37310
37311
37312
37313
37314
37315 class SvnDriver extends VcsDriver
37316 {
37317
37318
37319
37320 protected $cache;
37321 protected $baseUrl;
37322 protected $tags;
37323 protected $branches;
37324 protected $rootIdentifier;
37325 protected $infoCache = array();
37326
37327 protected $trunkPath = 'trunk';
37328 protected $branchesPath = 'branches';
37329 protected $tagsPath = 'tags';
37330 protected $packagePath = '';
37331 protected $cacheCredentials = true;
37332
37333
37334
37335
37336 private $util;
37337
37338
37339
37340
37341 public function initialize()
37342 {
37343 $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
37344
37345 SvnUtil::cleanEnv();
37346
37347 if (isset($this->repoConfig['trunk-path'])) {
37348 $this->trunkPath = $this->repoConfig['trunk-path'];
37349 }
37350 if (isset($this->repoConfig['branches-path'])) {
37351 $this->branchesPath = $this->repoConfig['branches-path'];
37352 }
37353 if (isset($this->repoConfig['tags-path'])) {
37354 $this->tagsPath = $this->repoConfig['tags-path'];
37355 }
37356 if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
37357 $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
37358 }
37359 if (isset($this->repoConfig['package-path'])) {
37360 $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
37361 }
37362
37363 if (false !== ($pos = strrpos($this->url, '/' . $this->trunkPath))) {
37364 $this->baseUrl = substr($this->url, 0, $pos);
37365 }
37366
37367 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl));
37368
37369 $this->getBranches();
37370 $this->getTags();
37371 }
37372
37373
37374
37375
37376 public function getRootIdentifier()
37377 {
37378 return $this->rootIdentifier ?: $this->trunkPath;
37379 }
37380
37381
37382
37383
37384 public function getUrl()
37385 {
37386 return $this->url;
37387 }
37388
37389
37390
37391
37392 public function getSource($identifier)
37393 {
37394 return array('type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier);
37395 }
37396
37397
37398
37399
37400 public function getDist($identifier)
37401 {
37402 return null;
37403 }
37404
37405
37406
37407
37408 public function getComposerInformation($identifier)
37409 {
37410 if (!isset($this->infoCache[$identifier])) {
37411 if ($res = $this->cache->read($identifier.'.json')) {
37412 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37413 }
37414
37415 $composer = $this->getBaseComposerInformation($identifier);
37416
37417 $this->cache->write($identifier.'.json', json_encode($composer));
37418
37419 $this->infoCache[$identifier] = $composer;
37420 }
37421
37422 return $this->infoCache[$identifier];
37423 }
37424
37425
37426
37427
37428
37429 public function getFileContent($file, $identifier)
37430 {
37431 $identifier = '/' . trim($identifier, '/') . '/';
37432
37433 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
37434 if (!empty($match[2])) {
37435 $path = $match[1];
37436 $rev = $match[2];
37437 } else {
37438 $path = $identifier;
37439 $rev = '';
37440 }
37441
37442 try {
37443 $resource = $path.$file;
37444 $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
37445 if (!trim($output)) {
37446 return null;
37447 }
37448 } catch (\RuntimeException $e) {
37449 throw new TransportException($e->getMessage());
37450 }
37451
37452 return $output;
37453 }
37454
37455
37456
37457
37458 public function getChangeDate($identifier)
37459 {
37460 $identifier = '/' . trim($identifier, '/') . '/';
37461
37462 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
37463 if (!empty($match[2])) {
37464 $path = $match[1];
37465 $rev = $match[2];
37466 } else {
37467 $path = $identifier;
37468 $rev = '';
37469 }
37470
37471 $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
37472 foreach ($this->process->splitLines($output) as $line) {
37473 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
37474 return new \DateTime($match[1], new \DateTimeZone('UTC'));
37475 }
37476 }
37477
37478 return null;
37479 }
37480
37481
37482
37483
37484 public function getTags()
37485 {
37486 if (null === $this->tags) {
37487 $this->tags = array();
37488
37489 if ($this->tagsPath !== false) {
37490 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
37491 if ($output) {
37492 foreach ($this->process->splitLines($output) as $line) {
37493 $line = trim($line);
37494 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37495 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
37496 $this->tags[rtrim($match[2], '/')] = $this->buildIdentifier(
37497 '/' . $this->tagsPath . '/' . $match[2],
37498 $match[1]
37499 );
37500 }
37501 }
37502 }
37503 }
37504 }
37505 }
37506
37507 return $this->tags;
37508 }
37509
37510
37511
37512
37513 public function getBranches()
37514 {
37515 if (null === $this->branches) {
37516 $this->branches = array();
37517
37518 if (false === $this->trunkPath) {
37519 $trunkParent = $this->baseUrl . '/';
37520 } else {
37521 $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
37522 }
37523
37524 $output = $this->execute('svn ls --verbose', $trunkParent);
37525 if ($output) {
37526 foreach ($this->process->splitLines($output) as $line) {
37527 $line = trim($line);
37528 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37529 if (isset($match[1]) && isset($match[2]) && $match[2] === './') {
37530 $this->branches['trunk'] = $this->buildIdentifier(
37531 '/' . $this->trunkPath,
37532 $match[1]
37533 );
37534 $this->rootIdentifier = $this->branches['trunk'];
37535 break;
37536 }
37537 }
37538 }
37539 }
37540 unset($output);
37541
37542 if ($this->branchesPath !== false) {
37543 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
37544 if ($output) {
37545 foreach ($this->process->splitLines(trim($output)) as $line) {
37546 $line = trim($line);
37547 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37548 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
37549 $this->branches[rtrim($match[2], '/')] = $this->buildIdentifier(
37550 '/' . $this->branchesPath . '/' . $match[2],
37551 $match[1]
37552 );
37553 }
37554 }
37555 }
37556 }
37557 }
37558 }
37559
37560 return $this->branches;
37561 }
37562
37563
37564
37565
37566 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37567 {
37568 $url = self::normalizeUrl($url);
37569 if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
37570 return true;
37571 }
37572
37573
37574  if (!$deep && !Filesystem::isLocalPath($url)) {
37575 return false;
37576 }
37577
37578 $processExecutor = new ProcessExecutor();
37579
37580 $exit = $processExecutor->execute(
37581 "svn info --non-interactive {$url}",
37582 $ignoredOutput
37583 );
37584
37585 if ($exit === 0) {
37586
37587  return true;
37588 }
37589
37590
37591  if (false !== stripos($processExecutor->getErrorOutput(), 'authorization failed:')) {
37592
37593  
37594  return true;
37595 }
37596
37597
37598  if (false !== stripos($processExecutor->getErrorOutput(), 'Authentication failed')) {
37599
37600  
37601  return true;
37602 }
37603
37604 return false;
37605 }
37606
37607
37608
37609
37610
37611
37612
37613
37614 protected static function normalizeUrl($url)
37615 {
37616 $fs = new Filesystem();
37617 if ($fs->isAbsolutePath($url)) {
37618 return 'file://' . strtr($url, '\\', '/');
37619 }
37620
37621 return $url;
37622 }
37623
37624
37625
37626
37627
37628
37629
37630
37631
37632
37633 protected function execute($command, $url)
37634 {
37635 if (null === $this->util) {
37636 $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
37637 $this->util->setCacheCredentials($this->cacheCredentials);
37638 }
37639
37640 try {
37641 return $this->util->execute($command, $url);
37642 } catch (\RuntimeException $e) {
37643 if (0 !== $this->process->execute('svn --version', $ignoredOutput)) {
37644 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());
37645 }
37646
37647 throw new \RuntimeException(
37648 'Repository '.$this->url.' could not be processed, '.$e->getMessage()
37649 );
37650 }
37651 }
37652
37653
37654
37655
37656
37657
37658
37659
37660
37661 protected function buildIdentifier($baseDir, $revision)
37662 {
37663 return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
37664 }
37665 }
37666 <?php
37667
37668
37669
37670
37671
37672
37673
37674
37675
37676
37677
37678 namespace Composer\Repository\Vcs;
37679
37680 use Composer\Cache;
37681 use Composer\Downloader\TransportException;
37682 use Composer\Config;
37683 use Composer\Factory;
37684 use Composer\IO\IOInterface;
37685 use Composer\Json\JsonFile;
37686 use Composer\Util\ProcessExecutor;
37687 use Composer\Util\RemoteFilesystem;
37688 use Composer\Util\Filesystem;
37689
37690
37691
37692
37693
37694
37695 abstract class VcsDriver implements VcsDriverInterface
37696 {
37697
37698 protected $url;
37699
37700 protected $originUrl;
37701
37702 protected $repoConfig;
37703
37704 protected $io;
37705
37706 protected $config;
37707
37708 protected $process;
37709
37710 protected $remoteFilesystem;
37711
37712 protected $infoCache = array();
37713
37714 protected $cache;
37715
37716
37717
37718
37719
37720
37721
37722
37723
37724
37725 final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
37726 {
37727 if (Filesystem::isLocalPath($repoConfig['url'])) {
37728 $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
37729 }
37730
37731 $this->url = $repoConfig['url'];
37732 $this->originUrl = $repoConfig['url'];
37733 $this->repoConfig = $repoConfig;
37734 $this->io = $io;
37735 $this->config = $config;
37736 $this->process = $process ?: new ProcessExecutor($io);
37737 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
37738 }
37739
37740
37741
37742
37743
37744
37745
37746 protected function shouldCache($identifier)
37747 {
37748 return $this->cache && preg_match('{[a-f0-9]{40}}i', $identifier);
37749 }
37750
37751
37752
37753
37754 public function getComposerInformation($identifier)
37755 {
37756 if (!isset($this->infoCache[$identifier])) {
37757 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
37758 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37759 }
37760
37761 $composer = $this->getBaseComposerInformation($identifier);
37762
37763 if ($this->shouldCache($identifier)) {
37764 $this->cache->write($identifier, json_encode($composer));
37765 }
37766
37767 $this->infoCache[$identifier] = $composer;
37768 }
37769
37770 return $this->infoCache[$identifier];
37771 }
37772
37773 protected function getBaseComposerInformation($identifier)
37774 {
37775 $composerFileContent = $this->getFileContent('composer.json', $identifier);
37776
37777 if (!$composerFileContent) {
37778 return null;
37779 }
37780
37781 $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json');
37782
37783 if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) {
37784 $composer['time'] = $changeDate->format(DATE_RFC3339);
37785 }
37786
37787 return $composer;
37788 }
37789
37790
37791
37792
37793 public function hasComposerFile($identifier)
37794 {
37795 try {
37796 return (bool) $this->getComposerInformation($identifier);
37797 } catch (TransportException $e) {
37798 }
37799
37800 return false;
37801 }
37802
37803
37804
37805
37806
37807
37808
37809
37810 protected function getScheme()
37811 {
37812 if (extension_loaded('openssl')) {
37813 return 'https';
37814 }
37815
37816 return 'http';
37817 }
37818
37819
37820
37821
37822
37823
37824
37825
37826 protected function getContents($url)
37827 {
37828 $options = isset($this->repoConfig['options']) ? $this->repoConfig['options'] : array();
37829
37830 return $this->remoteFilesystem->getContents($this->originUrl, $url, false, $options);
37831 }
37832
37833
37834
37835
37836 public function cleanup()
37837 {
37838 return;
37839 }
37840 }
37841 <?php
37842
37843
37844
37845
37846
37847
37848
37849
37850
37851
37852
37853 namespace Composer\Repository\Vcs;
37854
37855 use Composer\Config;
37856 use Composer\IO\IOInterface;
37857
37858
37859
37860
37861 interface VcsDriverInterface
37862 {
37863
37864
37865
37866 public function initialize();
37867
37868
37869
37870
37871
37872
37873
37874 public function getComposerInformation($identifier);
37875
37876
37877
37878
37879
37880
37881
37882
37883 public function getFileContent($file, $identifier);
37884
37885
37886
37887
37888
37889
37890
37891 public function getChangeDate($identifier);
37892
37893
37894
37895
37896
37897
37898 public function getRootIdentifier();
37899
37900
37901
37902
37903
37904
37905 public function getBranches();
37906
37907
37908
37909
37910
37911
37912 public function getTags();
37913
37914
37915
37916
37917
37918 public function getDist($identifier);
37919
37920
37921
37922
37923
37924 public function getSource($identifier);
37925
37926
37927
37928
37929
37930
37931 public function getUrl();
37932
37933
37934
37935
37936
37937
37938
37939
37940 public function hasComposerFile($identifier);
37941
37942
37943
37944
37945 public function cleanup();
37946
37947
37948
37949
37950
37951
37952
37953
37954
37955
37956 public static function supports(IOInterface $io, Config $config, $url, $deep = false);
37957 }
37958 <?php
37959
37960
37961
37962
37963
37964
37965
37966
37967
37968
37969
37970 namespace Composer\Repository;
37971
37972 use Composer\Downloader\TransportException;
37973 use Composer\Repository\Vcs\VcsDriverInterface;
37974 use Composer\Package\Version\VersionParser;
37975 use Composer\Package\Loader\ArrayLoader;
37976 use Composer\Package\Loader\ValidatingArrayLoader;
37977 use Composer\Package\Loader\InvalidPackageException;
37978 use Composer\Package\Loader\LoaderInterface;
37979 use Composer\EventDispatcher\EventDispatcher;
37980 use Composer\IO\IOInterface;
37981 use Composer\Config;
37982
37983
37984
37985
37986 class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInterface
37987 {
37988 protected $url;
37989 protected $packageName;
37990 protected $verbose;
37991 protected $io;
37992 protected $config;
37993 protected $versionParser;
37994 protected $type;
37995 protected $loader;
37996 protected $repoConfig;
37997 protected $branchErrorOccurred = false;
37998 private $drivers;
37999
38000 private $driver;
38001
38002 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null)
38003 {
38004 parent::__construct();
38005 $this->drivers = $drivers ?: array(
38006 'github' => 'Composer\Repository\Vcs\GitHubDriver',
38007 'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
38008 'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
38009 'git' => 'Composer\Repository\Vcs\GitDriver',
38010 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver',
38011 'hg' => 'Composer\Repository\Vcs\HgDriver',
38012 'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
38013 'fossil' => 'Composer\Repository\Vcs\FossilDriver',
38014
38015  'svn' => 'Composer\Repository\Vcs\SvnDriver',
38016 );
38017
38018 $this->url = $repoConfig['url'];
38019 $this->io = $io;
38020 $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
38021 $this->verbose = $io->isVeryVerbose();
38022 $this->config = $config;
38023 $this->repoConfig = $repoConfig;
38024 }
38025
38026 public function getRepoConfig()
38027 {
38028 return $this->repoConfig;
38029 }
38030
38031 public function setLoader(LoaderInterface $loader)
38032 {
38033 $this->loader = $loader;
38034 }
38035
38036 public function getDriver()
38037 {
38038 if ($this->driver) {
38039 return $this->driver;
38040 }
38041
38042 if (isset($this->drivers[$this->type])) {
38043 $class = $this->drivers[$this->type];
38044 $this->driver = new $class($this->repoConfig, $this->io, $this->config);
38045 $this->driver->initialize();
38046
38047 return $this->driver;
38048 }
38049
38050 foreach ($this->drivers as $driver) {
38051 if ($driver::supports($this->io, $this->config, $this->url)) {
38052 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
38053 $this->driver->initialize();
38054
38055 return $this->driver;
38056 }
38057 }
38058
38059 foreach ($this->drivers as $driver) {
38060 if ($driver::supports($this->io, $this->config, $this->url, true)) {
38061 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
38062 $this->driver->initialize();
38063
38064 return $this->driver;
38065 }
38066 }
38067 }
38068
38069 public function hadInvalidBranches()
38070 {
38071 return $this->branchErrorOccurred;
38072 }
38073
38074 protected function initialize()
38075 {
38076 parent::initialize();
38077
38078 $verbose = $this->verbose;
38079
38080 $driver = $this->getDriver();
38081 if (!$driver) {
38082 throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url);
38083 }
38084
38085 $this->versionParser = new VersionParser;
38086 if (!$this->loader) {
38087 $this->loader = new ArrayLoader($this->versionParser);
38088 }
38089
38090 try {
38091 if ($driver->hasComposerFile($driver->getRootIdentifier())) {
38092 $data = $driver->getComposerInformation($driver->getRootIdentifier());
38093 $this->packageName = !empty($data['name']) ? $data['name'] : null;
38094 }
38095 } catch (\Exception $e) {
38096 if ($verbose) {
38097 $this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
38098 }
38099 }
38100
38101 foreach ($driver->getTags() as $tag => $identifier) {
38102 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
38103 if ($verbose) {
38104 $this->io->writeError($msg);
38105 } else {
38106 $this->io->overwriteError($msg, false);
38107 }
38108
38109
38110  $tag = str_replace('release-', '', $tag);
38111
38112 if (!$parsedTag = $this->validateTag($tag)) {
38113 if ($verbose) {
38114 $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
38115 }
38116 continue;
38117 }
38118
38119 try {
38120 if (!$data = $driver->getComposerInformation($identifier)) {
38121 if ($verbose) {
38122 $this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
38123 }
38124 continue;
38125 }
38126
38127
38128  if (isset($data['version'])) {
38129 $data['version_normalized'] = $this->versionParser->normalize($data['version']);
38130 } else {
38131
38132  $data['version'] = $tag;
38133 $data['version_normalized'] = $parsedTag;
38134 }
38135
38136
38137  $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']);
38138 $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
38139
38140
38141  if ($data['version_normalized'] !== $parsedTag) {
38142 if ($verbose) {
38143 $this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
38144 }
38145 continue;
38146 }
38147
38148 if ($verbose) {
38149 $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
38150 }
38151
38152 $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
38153 } catch (\Exception $e) {
38154 if ($verbose) {
38155 $this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
38156 }
38157 continue;
38158 }
38159 }
38160
38161 if (!$verbose) {
38162 $this->io->overwriteError('', false);
38163 }
38164
38165 foreach ($driver->getBranches() as $branch => $identifier) {
38166 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
38167 if ($verbose) {
38168 $this->io->writeError($msg);
38169 } else {
38170 $this->io->overwriteError($msg, false);
38171 }
38172
38173 if (!$parsedBranch = $this->validateBranch($branch)) {
38174 if ($verbose) {
38175 $this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
38176 }
38177 continue;
38178 }
38179
38180 try {
38181 if (!$data = $driver->getComposerInformation($identifier)) {
38182 if ($verbose) {
38183 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
38184 }
38185 continue;
38186 }
38187
38188
38189  $data['version'] = $branch;
38190 $data['version_normalized'] = $parsedBranch;
38191
38192
38193  if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
38194 $data['version'] = 'dev-' . $data['version'];
38195 } else {
38196 $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
38197 $data['version'] = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
38198 }
38199
38200 if ($verbose) {
38201 $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
38202 }
38203
38204 $packageData = $this->preProcess($driver, $data, $identifier);
38205 $package = $this->loader->load($packageData);
38206 if ($this->loader instanceof ValidatingArrayLoader && $this->loader->getWarnings()) {
38207 throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
38208 }
38209 $this->addPackage($package);
38210 } catch (TransportException $e) {
38211 if ($verbose) {
38212 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
38213 }
38214 continue;
38215 } catch (\Exception $e) {
38216 if (!$verbose) {
38217 $this->io->writeError('');
38218 }
38219 $this->branchErrorOccurred = true;
38220 $this->io->writeError('<error>Skipped branch '.$branch.', '.$e->getMessage().'</error>');
38221 $this->io->writeError('');
38222 continue;
38223 }
38224 }
38225 $driver->cleanup();
38226
38227 if (!$verbose) {
38228 $this->io->overwriteError('', false);
38229 }
38230
38231 if (!$this->getPackages()) {
38232 throw new InvalidRepositoryException('No valid composer.json was found in any branch or tag of '.$this->url.', could not load a package from it.');
38233 }
38234 }
38235
38236 protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
38237 {
38238
38239  $data['name'] = $this->packageName ?: $data['name'];
38240
38241 if (!isset($data['dist'])) {
38242 $data['dist'] = $driver->getDist($identifier);
38243 }
38244 if (!isset($data['source'])) {
38245 $data['source'] = $driver->getSource($identifier);
38246 }
38247
38248 return $data;
38249 }
38250
38251 private function validateBranch($branch)
38252 {
38253 try {
38254 return $this->versionParser->normalizeBranch($branch);
38255 } catch (\Exception $e) {
38256 }
38257
38258 return false;
38259 }
38260
38261 private function validateTag($version)
38262 {
38263 try {
38264 return $this->versionParser->normalize($version);
38265 } catch (\Exception $e) {
38266 }
38267
38268 return false;
38269 }
38270 }
38271 <?php
38272
38273
38274
38275
38276
38277
38278
38279
38280
38281
38282
38283 namespace Composer\Repository;
38284
38285 use Composer\Package\AliasPackage;
38286
38287
38288
38289
38290
38291
38292 class WritableArrayRepository extends ArrayRepository implements WritableRepositoryInterface
38293 {
38294
38295
38296
38297 public function write()
38298 {
38299 }
38300
38301
38302
38303
38304 public function reload()
38305 {
38306 }
38307
38308
38309
38310
38311 public function getCanonicalPackages()
38312 {
38313 $packages = $this->getPackages();
38314
38315
38316  $packagesByName = array();
38317 foreach ($packages as $package) {
38318 if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
38319 $packagesByName[$package->getName()] = $package;
38320 }
38321 }
38322
38323 $canonicalPackages = array();
38324
38325
38326  foreach ($packagesByName as $package) {
38327 while ($package instanceof AliasPackage) {
38328 $package = $package->getAliasOf();
38329 }
38330
38331 $canonicalPackages[] = $package;
38332 }
38333
38334 return $canonicalPackages;
38335 }
38336 }
38337 <?php
38338
38339
38340
38341
38342
38343
38344
38345
38346
38347
38348
38349 namespace Composer\Repository;
38350
38351 use Composer\Package\PackageInterface;
38352
38353
38354
38355
38356
38357
38358 interface WritableRepositoryInterface extends RepositoryInterface
38359 {
38360
38361
38362
38363 public function write();
38364
38365
38366
38367
38368
38369
38370 public function addPackage(PackageInterface $package);
38371
38372
38373
38374
38375
38376
38377 public function removePackage(PackageInterface $package);
38378
38379
38380
38381
38382
38383
38384 public function getCanonicalPackages();
38385
38386
38387
38388
38389 public function reload();
38390 }
38391 <?php
38392
38393
38394
38395
38396
38397
38398
38399
38400
38401
38402
38403 namespace Composer\Script;
38404
38405
38406
38407
38408
38409
38410 class CommandEvent extends Event
38411 {
38412 }
38413 <?php
38414
38415
38416
38417
38418
38419
38420
38421
38422
38423
38424
38425 namespace Composer\Script;
38426
38427 use Composer\Composer;
38428 use Composer\IO\IOInterface;
38429 use Composer\EventDispatcher\Event as BaseEvent;
38430
38431
38432
38433
38434
38435
38436
38437 class Event extends BaseEvent
38438 {
38439
38440
38441
38442 private $composer;
38443
38444
38445
38446
38447 private $io;
38448
38449
38450
38451
38452 private $devMode;
38453
38454
38455
38456
38457
38458
38459
38460
38461
38462
38463
38464 public function __construct($name, Composer $composer, IOInterface $io, $devMode = false, array $args = array(), array $flags = array())
38465 {
38466 parent::__construct($name, $args, $flags);
38467 $this->composer = $composer;
38468 $this->io = $io;
38469 $this->devMode = $devMode;
38470 }
38471
38472
38473
38474
38475
38476
38477 public function getComposer()
38478 {
38479 return $this->composer;
38480 }
38481
38482
38483
38484
38485
38486
38487 public function getIO()
38488 {
38489 return $this->io;
38490 }
38491
38492
38493
38494
38495
38496
38497 public function isDevMode()
38498 {
38499 return $this->devMode;
38500 }
38501 }
38502 <?php
38503
38504
38505
38506
38507
38508
38509
38510
38511
38512
38513
38514 namespace Composer\Script;
38515
38516 use Composer\Installer\PackageEvent as BasePackageEvent;
38517
38518
38519
38520
38521
38522
38523 class PackageEvent extends BasePackageEvent
38524 {
38525 }
38526 <?php
38527
38528
38529
38530
38531
38532
38533
38534
38535
38536
38537
38538 namespace Composer\Script;
38539
38540
38541
38542
38543
38544
38545
38546 class ScriptEvents
38547 {
38548
38549
38550
38551
38552
38553
38554
38555 const PRE_INSTALL_CMD = 'pre-install-cmd';
38556
38557
38558
38559
38560
38561
38562
38563
38564 const POST_INSTALL_CMD = 'post-install-cmd';
38565
38566
38567
38568
38569
38570
38571
38572
38573 const PRE_UPDATE_CMD = 'pre-update-cmd';
38574
38575
38576
38577
38578
38579
38580
38581
38582 const POST_UPDATE_CMD = 'post-update-cmd';
38583
38584
38585
38586
38587
38588
38589
38590
38591 const PRE_STATUS_CMD = 'pre-status-cmd';
38592
38593
38594
38595
38596
38597
38598
38599
38600 const POST_STATUS_CMD = 'post-status-cmd';
38601
38602
38603
38604
38605
38606
38607
38608
38609 const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
38610
38611
38612
38613
38614
38615
38616
38617
38618 const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
38619
38620
38621
38622
38623
38624
38625
38626
38627 const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
38628
38629
38630
38631
38632
38633
38634
38635
38636
38637 const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
38638
38639
38640
38641
38642
38643
38644
38645
38646 const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
38647
38648
38649
38650
38651
38652
38653
38654
38655 const POST_ARCHIVE_CMD = 'post-archive-cmd';
38656
38657
38658
38659
38660
38661
38662
38663
38664
38665
38666
38667 const PRE_PACKAGE_INSTALL = 'pre-package-install';
38668
38669
38670
38671
38672
38673
38674
38675
38676
38677 const POST_PACKAGE_INSTALL = 'post-package-install';
38678
38679
38680
38681
38682
38683
38684
38685
38686
38687 const PRE_PACKAGE_UPDATE = 'pre-package-update';
38688
38689
38690
38691
38692
38693
38694
38695
38696
38697 const POST_PACKAGE_UPDATE = 'post-package-update';
38698
38699
38700
38701
38702
38703
38704
38705
38706
38707 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
38708
38709
38710
38711
38712
38713
38714
38715
38716
38717 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
38718 }
38719 <?php
38720
38721
38722
38723
38724
38725
38726
38727
38728
38729
38730
38731 namespace Composer\SelfUpdate;
38732
38733
38734
38735
38736 class Keys
38737 {
38738 public static function fingerprint($path)
38739 {
38740 $hash = strtoupper(hash('sha256', preg_replace('{\s}', '', file_get_contents($path))));
38741
38742 return implode(' ', array(
38743 substr($hash, 0, 8),
38744 substr($hash, 8, 8),
38745 substr($hash, 16, 8),
38746 substr($hash, 24, 8),
38747 '', 
38748  substr($hash, 32, 8),
38749 substr($hash, 40, 8),
38750 substr($hash, 48, 8),
38751 substr($hash, 56, 8),
38752 ));
38753 }
38754 }
38755 <?php
38756
38757
38758
38759
38760
38761
38762
38763
38764
38765
38766
38767 namespace Composer\SelfUpdate;
38768
38769 use Composer\Util\RemoteFilesystem;
38770 use Composer\Config;
38771 use Composer\Json\JsonFile;
38772
38773
38774
38775
38776 class Versions
38777 {
38778 private $rfs;
38779 private $config;
38780 private $channel;
38781
38782 public function __construct(Config $config, RemoteFilesystem $rfs)
38783 {
38784 $this->rfs = $rfs;
38785 $this->config = $config;
38786 }
38787
38788 public function getChannel()
38789 {
38790 if ($this->channel) {
38791 return $this->channel;
38792 }
38793
38794 $channelFile = $this->config->get('home').'/update-channel';
38795 if (file_exists($channelFile)) {
38796 $channel = trim(file_get_contents($channelFile));
38797 if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
38798 return $this->channel = $channel;
38799 }
38800 }
38801
38802 return $this->channel = 'stable';
38803 }
38804
38805 public function setChannel($channel)
38806 {
38807 if (!in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
38808 throw new \InvalidArgumentException('Invalid channel '.$channel.', must be one of: stable, preview, snapshot');
38809 }
38810
38811 $channelFile = $this->config->get('home').'/update-channel';
38812 $this->channel = $channel;
38813 file_put_contents($channelFile, $channel.PHP_EOL);
38814 }
38815
38816 public function getLatest()
38817 {
38818 $protocol = extension_loaded('openssl') ? 'https' : 'http';
38819 $versions = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false));
38820
38821 foreach ($versions[$this->getChannel()] as $version) {
38822 if ($version['min-php'] <= PHP_VERSION_ID) {
38823 return $version;
38824 }
38825 }
38826
38827 throw new \LogicException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')');
38828 }
38829 }
38830 <?php
38831
38832
38833
38834
38835
38836
38837
38838
38839
38840
38841
38842 namespace Composer\Util;
38843
38844 use Composer\Config;
38845 use Composer\IO\IOInterface;
38846
38847
38848
38849
38850 class AuthHelper
38851 {
38852 protected $io;
38853 protected $config;
38854
38855 public function __construct(IOInterface $io, Config $config)
38856 {
38857 $this->io = $io;
38858 $this->config = $config;
38859 }
38860
38861 public function storeAuth($originUrl, $storeAuth)
38862 {
38863 $store = false;
38864 $configSource = $this->config->getAuthConfigSource();
38865 if ($storeAuth === true) {
38866 $store = $configSource;
38867 } elseif ($storeAuth === 'prompt') {
38868 $answer = $this->io->askAndValidate(
38869 'Do you want to store credentials for '.$originUrl.' in '.$configSource->getName().' ? [Yn] ',
38870 function ($value) {
38871 $input = strtolower(substr(trim($value), 0, 1));
38872 if (in_array($input, array('y','n'))) {
38873 return $input;
38874 }
38875 throw new \RuntimeException('Please answer (y)es or (n)o');
38876 },
38877 null,
38878 'y'
38879 );
38880
38881 if ($answer === 'y') {
38882 $store = $configSource;
38883 }
38884 }
38885 if ($store) {
38886 $store->addConfigSetting(
38887 'http-basic.'.$originUrl,
38888 $this->io->getAuthentication($originUrl)
38889 );
38890 }
38891 }
38892 }
38893 <?php
38894
38895
38896
38897
38898
38899
38900
38901
38902
38903
38904
38905 namespace Composer\Util;
38906
38907 use Composer\Factory;
38908 use Composer\IO\IOInterface;
38909 use Composer\Config;
38910 use Composer\Downloader\TransportException;
38911
38912
38913
38914
38915 class Bitbucket
38916 {
38917 private $io;
38918 private $config;
38919 private $process;
38920 private $remoteFilesystem;
38921 private $token = array();
38922 private $time;
38923
38924 const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
38925
38926
38927
38928
38929
38930
38931
38932
38933
38934
38935 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null, $time = null)
38936 {
38937 $this->io = $io;
38938 $this->config = $config;
38939 $this->process = $process ?: new ProcessExecutor;
38940 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
38941 $this->time = $time;
38942 }
38943
38944
38945
38946
38947 public function getToken()
38948 {
38949 if (!isset($this->token['access_token'])) {
38950 return '';
38951 }
38952
38953 return $this->token['access_token'];
38954 }
38955
38956
38957
38958
38959
38960
38961
38962 public function authorizeOAuth($originUrl)
38963 {
38964 if ($originUrl !== 'bitbucket.org') {
38965 return false;
38966 }
38967
38968
38969  if (0 === $this->process->execute('git config bitbucket.accesstoken', $output)) {
38970 $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));
38971
38972 return true;
38973 }
38974
38975 return false;
38976 }
38977
38978
38979
38980
38981
38982 private function requestAccessToken($originUrl)
38983 {
38984 try {
38985 $json = $this->remoteFilesystem->getContents($originUrl, self::OAUTH2_ACCESS_TOKEN_URL, false, array(
38986 'retry-auth-failure' => false,
38987 'http' => array(
38988 'method' => 'POST',
38989 'content' => 'grant_type=client_credentials',
38990 ),
38991 ));
38992
38993 $this->token = json_decode($json, true);
38994 } catch (TransportException $e) {
38995 if ($e->getCode() === 400) {
38996 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
38997 $this->io->writeError('This can have two reasons:');
38998 $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
38999 $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
39000
39001 return false;
39002 } elseif (in_array($e->getCode(), array(403, 401))) {
39003 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
39004 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39005
39006 return false;
39007 }
39008
39009 throw $e;
39010 }
39011
39012 return true;
39013 }
39014
39015
39016
39017
39018
39019
39020
39021
39022
39023
39024 public function authorizeOAuthInteractively($originUrl, $message = null)
39025 {
39026 if ($message) {
39027 $this->io->writeError($message);
39028 }
39029
39030 $url = 'https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html';
39031 $this->io->writeError(sprintf('Follow the instructions on %s', $url));
39032 $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
39033 $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)');
39034
39035 $consumerKey = trim($this->io->askAndHideAnswer('Consumer Key (hidden): '));
39036
39037 if (!$consumerKey) {
39038 $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
39039 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39040
39041 return false;
39042 }
39043
39044 $consumerSecret = trim($this->io->askAndHideAnswer('Consumer Secret (hidden): '));
39045
39046 if (!$consumerSecret) {
39047 $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
39048 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39049
39050 return false;
39051 }
39052
39053 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
39054
39055 if (!$this->requestAccessToken($originUrl)) {
39056 return false;
39057 }
39058
39059
39060  $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
39061
39062
39063  $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
39064
39065 $this->io->writeError('<info>Consumer stored successfully.</info>');
39066
39067 return true;
39068 }
39069
39070
39071
39072
39073
39074
39075
39076
39077
39078 public function requestToken($originUrl, $consumerKey, $consumerSecret)
39079 {
39080 if (!empty($this->token) || $this->getTokenFromConfig($originUrl)) {
39081 return $this->token['access_token'];
39082 }
39083
39084 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
39085 if (!$this->requestAccessToken($originUrl)) {
39086 return '';
39087 }
39088
39089 $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
39090
39091 return $this->token['access_token'];
39092 }
39093
39094
39095
39096
39097
39098
39099
39100 private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret)
39101 {
39102 $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
39103
39104 $time = null === $this->time ? time() : $this->time;
39105 $consumer = array(
39106 "consumer-key" => $consumerKey,
39107 "consumer-secret" => $consumerSecret,
39108 "access-token" => $this->token['access_token'],
39109 "access-token-expiration" => $time + $this->token['expires_in'],
39110 );
39111
39112 $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.'.$originUrl, $consumer);
39113 }
39114
39115
39116
39117
39118
39119 private function getTokenFromConfig($originUrl)
39120 {
39121 $authConfig = $this->config->get('bitbucket-oauth');
39122
39123 if (
39124 !isset($authConfig[$originUrl]['access-token'])
39125 || !isset($authConfig[$originUrl]['access-token-expiration'])
39126 || time() > $authConfig[$originUrl]['access-token-expiration']
39127 ) {
39128 return false;
39129 }
39130
39131 $this->token = array(
39132 'access_token' => $authConfig[$originUrl]['access-token'],
39133 );
39134
39135 return true;
39136 }
39137 }
39138 <?php
39139
39140
39141
39142
39143
39144
39145
39146
39147
39148
39149
39150 namespace Composer\Util;
39151
39152
39153
39154
39155
39156
39157 class ComposerMirror
39158 {
39159 public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type)
39160 {
39161 if ($reference) {
39162 $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference);
39163 }
39164 $version = strpos($version, '/') === false ? $version : md5($version);
39165
39166 return str_replace(
39167 array('%package%', '%version%', '%reference%', '%type%'),
39168 array($packageName, $version, $reference, $type),
39169 $mirrorUrl
39170 );
39171 }
39172
39173 public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
39174 {
39175 if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
39176 $url = 'gh-'.$match[1].'/'.$match[2];
39177 } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
39178 $url = 'bb-'.$match[1].'/'.$match[2];
39179 } else {
39180 $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
39181 }
39182
39183 return str_replace(
39184 array('%package%', '%normalizedUrl%', '%type%'),
39185 array($packageName, $url, $type),
39186 $mirrorUrl
39187 );
39188 }
39189
39190 public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
39191 {
39192 return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
39193 }
39194 }
39195 <?php
39196
39197
39198
39199
39200
39201
39202
39203
39204
39205
39206
39207 namespace Composer\Util;
39208
39209 use Composer\Package\Loader\ArrayLoader;
39210 use Composer\Package\Loader\ValidatingArrayLoader;
39211 use Composer\Package\Loader\InvalidPackageException;
39212 use Composer\Json\JsonValidationException;
39213 use Composer\IO\IOInterface;
39214 use Composer\Json\JsonFile;
39215 use Composer\Spdx\SpdxLicenses;
39216
39217
39218
39219
39220
39221
39222
39223 class ConfigValidator
39224 {
39225 private $io;
39226
39227 public function __construct(IOInterface $io)
39228 {
39229 $this->io = $io;
39230 }
39231
39232
39233
39234
39235
39236
39237
39238
39239
39240 public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL)
39241 {
39242 $errors = array();
39243 $publishErrors = array();
39244 $warnings = array();
39245
39246
39247  $laxValid = false;
39248 try {
39249 $json = new JsonFile($file, null, $this->io);
39250 $manifest = $json->read();
39251
39252 $json->validateSchema(JsonFile::LAX_SCHEMA);
39253 $laxValid = true;
39254 $json->validateSchema();
39255 } catch (JsonValidationException $e) {
39256 foreach ($e->getErrors() as $message) {
39257 if ($laxValid) {
39258 $publishErrors[] = $message;
39259 } else {
39260 $errors[] = $message;
39261 }
39262 }
39263 } catch (\Exception $e) {
39264 $errors[] = $e->getMessage();
39265
39266 return array($errors, $publishErrors, $warnings);
39267 }
39268
39269
39270  if (!empty($manifest['license'])) {
39271
39272  if (is_array($manifest['license'])) {
39273 foreach ($manifest['license'] as $key => $license) {
39274 if ('proprietary' === $license) {
39275 unset($manifest['license'][$key]);
39276 }
39277 }
39278 }
39279
39280 $licenseValidator = new SpdxLicenses();
39281 if ('proprietary' !== $manifest['license'] && array() !== $manifest['license'] && !$licenseValidator->validate($manifest['license']) && $licenseValidator->validate(trim($manifest['license']))) {
39282 $warnings[] = sprintf(
39283 'License %s must not contain extra spaces, make sure to trim it.',
39284 json_encode($manifest['license'])
39285 );
39286 } elseif ('proprietary' !== $manifest['license'] && array() !== $manifest['license'] && !$licenseValidator->validate($manifest['license'])) {
39287 $warnings[] = sprintf(
39288 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.'
39289 . PHP_EOL .
39290 'If the software is closed-source, you may use "proprietary" as license.',
39291 json_encode($manifest['license'])
39292 );
39293 }
39294 } else {
39295 $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
39296 }
39297
39298 if (isset($manifest['version'])) {
39299 $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
39300 }
39301
39302 if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) {
39303 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']);
39304 $suggestName = strtolower($suggestName);
39305
39306 $publishErrors[] = sprintf(
39307 '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.',
39308 $manifest['name'],
39309 $suggestName
39310 );
39311 }
39312
39313 if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') {
39314 $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.";
39315 }
39316
39317
39318  if (isset($manifest['require']) && isset($manifest['require-dev'])) {
39319 $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
39320
39321 if (!empty($requireOverrides)) {
39322 $plural = (count($requireOverrides) > 1) ? 'are' : 'is';
39323 $warnings[] = implode(', ', array_keys($requireOverrides)). " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
39324 }
39325 }
39326
39327
39328  $require = isset($manifest['require']) ? $manifest['require'] : array();
39329 $requireDev = isset($manifest['require-dev']) ? $manifest['require-dev'] : array();
39330 $packages = array_merge($require, $requireDev);
39331 foreach ($packages as $package => $version) {
39332 if (preg_match('/#/', $version) === 1) {
39333 $warnings[] = sprintf(
39334 'The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.',
39335 $package
39336 );
39337 }
39338 }
39339
39340
39341  if (isset($manifest['autoload']['psr-0'][''])) {
39342 $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
39343 }
39344 if (isset($manifest['autoload']['psr-4'][''])) {
39345 $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
39346 }
39347
39348 try {
39349 $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags);
39350 if (!isset($manifest['version'])) {
39351 $manifest['version'] = '1.0.0';
39352 }
39353 if (!isset($manifest['name'])) {
39354 $manifest['name'] = 'dummy/dummy';
39355 }
39356 $loader->load($manifest);
39357 } catch (InvalidPackageException $e) {
39358 $errors = array_merge($errors, $e->getErrors());
39359 }
39360
39361 $warnings = array_merge($warnings, $loader->getWarnings());
39362
39363 return array($errors, $publishErrors, $warnings);
39364 }
39365 }
39366 <?php
39367
39368
39369
39370
39371
39372
39373
39374
39375
39376
39377
39378 namespace Composer\Util;
39379
39380 use Composer\IO\IOInterface;
39381
39382
39383
39384
39385
39386
39387 class ErrorHandler
39388 {
39389 private static $io;
39390
39391
39392
39393
39394
39395
39396
39397
39398
39399
39400
39401
39402 public static function handle($level, $message, $file, $line)
39403 {
39404
39405  if (!(error_reporting() & $level)) {
39406 return;
39407 }
39408
39409 if (ini_get('xdebug.scream')) {
39410 $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
39411 "\na legitimately suppressed error that you were not supposed to see.";
39412 }
39413
39414 if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
39415 throw new \ErrorException($message, 0, $level, $file, $line);
39416 }
39417
39418 if (self::$io) {
39419 self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
39420 if (self::$io->isVerbose()) {
39421 self::$io->writeError('<warning>Stack trace:</warning>');
39422 self::$io->writeError(array_filter(array_map(function ($a) {
39423 if (isset($a['line'], $a['file'])) {
39424 return '<warning> '.$a['file'].':'.$a['line'].'</warning>';
39425 }
39426
39427 return null;
39428 }, array_slice(debug_backtrace(), 2))));
39429 }
39430 }
39431 }
39432
39433
39434
39435
39436
39437
39438 public static function register(IOInterface $io = null)
39439 {
39440 set_error_handler(array(__CLASS__, 'handle'));
39441 error_reporting(E_ALL | E_STRICT);
39442 self::$io = $io;
39443 }
39444 }
39445 <?php
39446
39447
39448
39449
39450
39451
39452
39453
39454
39455
39456
39457 namespace Composer\Util;
39458
39459 use RecursiveDirectoryIterator;
39460 use RecursiveIteratorIterator;
39461 use Symfony\Component\Filesystem\Exception\IOException;
39462 use Symfony\Component\Finder\Finder;
39463
39464
39465
39466
39467
39468 class Filesystem
39469 {
39470 private $processExecutor;
39471
39472 public function __construct(ProcessExecutor $executor = null)
39473 {
39474 $this->processExecutor = $executor ?: new ProcessExecutor();
39475 }
39476
39477 public function remove($file)
39478 {
39479 if (is_dir($file)) {
39480 return $this->removeDirectory($file);
39481 }
39482
39483 if (file_exists($file)) {
39484 return $this->unlink($file);
39485 }
39486
39487 return false;
39488 }
39489
39490
39491
39492
39493
39494
39495
39496 public function isDirEmpty($dir)
39497 {
39498 $finder = Finder::create()
39499 ->ignoreVCS(false)
39500 ->ignoreDotFiles(false)
39501 ->depth(0)
39502 ->in($dir);
39503
39504 return count($finder) === 0;
39505 }
39506
39507 public function emptyDirectory($dir, $ensureDirectoryExists = true)
39508 {
39509 if (file_exists($dir) && is_link($dir)) {
39510 $this->unlink($dir);
39511 }
39512
39513 if ($ensureDirectoryExists) {
39514 $this->ensureDirectoryExists($dir);
39515 }
39516
39517 if (is_dir($dir)) {
39518 $finder = Finder::create()
39519 ->ignoreVCS(false)
39520 ->ignoreDotFiles(false)
39521 ->depth(0)
39522 ->in($dir);
39523
39524 foreach ($finder as $path) {
39525 $this->remove((string) $path);
39526 }
39527 }
39528 }
39529
39530
39531
39532
39533
39534
39535
39536
39537
39538
39539
39540 public function removeDirectory($directory)
39541 {
39542 if ($this->isSymlinkedDirectory($directory)) {
39543 return $this->unlinkSymlinkedDirectory($directory);
39544 }
39545
39546 if ($this->isJunction($directory)) {
39547 return $this->removeJunction($directory);
39548 }
39549
39550 if (!file_exists($directory) || !is_dir($directory)) {
39551 return true;
39552 }
39553
39554 if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
39555 throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.');
39556 }
39557
39558 if (!function_exists('proc_open')) {
39559 return $this->removeDirectoryPhp($directory);
39560 }
39561
39562 if (Platform::isWindows()) {
39563 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape(realpath($directory)));
39564 } else {
39565 $cmd = sprintf('rm -rf %s', ProcessExecutor::escape($directory));
39566 }
39567
39568 $result = $this->getProcess()->execute($cmd, $output) === 0;
39569
39570
39571  clearstatcache();
39572
39573 if ($result && !file_exists($directory)) {
39574 return true;
39575 }
39576
39577 return $this->removeDirectoryPhp($directory);
39578 }
39579
39580
39581
39582
39583
39584
39585
39586
39587
39588
39589
39590 public function removeDirectoryPhp($directory)
39591 {
39592 try {
39593 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
39594 } catch (\UnexpectedValueException $e) {
39595
39596  
39597  clearstatcache();
39598 usleep(100000);
39599 if (!is_dir($directory)) {
39600 return true;
39601 }
39602 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
39603 }
39604 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
39605
39606 foreach ($ri as $file) {
39607 if ($file->isDir()) {
39608 $this->rmdir($file->getPathname());
39609 } else {
39610 $this->unlink($file->getPathname());
39611 }
39612 }
39613
39614 return $this->rmdir($directory);
39615 }
39616
39617 public function ensureDirectoryExists($directory)
39618 {
39619 if (!is_dir($directory)) {
39620 if (file_exists($directory)) {
39621 throw new \RuntimeException(
39622 $directory.' exists and is not a directory.'
39623 );
39624 }
39625 if (!@mkdir($directory, 0777, true)) {
39626 throw new \RuntimeException(
39627 $directory.' does not exist and could not be created.'
39628 );
39629 }
39630 }
39631 }
39632
39633
39634
39635
39636
39637
39638
39639
39640 public function unlink($path)
39641 {
39642 if (!@$this->unlinkImplementation($path)) {
39643
39644  if (!Platform::isWindows() || (usleep(350000) && !@$this->unlinkImplementation($path))) {
39645 $error = error_get_last();
39646 $message = 'Could not delete '.$path.': ' . @$error['message'];
39647 if (Platform::isWindows()) {
39648 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
39649 }
39650
39651 throw new \RuntimeException($message);
39652 }
39653 }
39654
39655 return true;
39656 }
39657
39658
39659
39660
39661
39662
39663
39664
39665 public function rmdir($path)
39666 {
39667 if (!@rmdir($path)) {
39668
39669  if (!Platform::isWindows() || (usleep(350000) && !@rmdir($path))) {
39670 $error = error_get_last();
39671 $message = 'Could not delete '.$path.': ' . @$error['message'];
39672 if (Platform::isWindows()) {
39673 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
39674 }
39675
39676 throw new \RuntimeException($message);
39677 }
39678 }
39679
39680 return true;
39681 }
39682
39683
39684
39685
39686
39687
39688
39689
39690
39691
39692 public function copyThenRemove($source, $target)
39693 {
39694 if (!is_dir($source)) {
39695 copy($source, $target);
39696 $this->unlink($source);
39697
39698 return;
39699 }
39700
39701 $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
39702 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
39703 $this->ensureDirectoryExists($target);
39704
39705 foreach ($ri as $file) {
39706 $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
39707 if ($file->isDir()) {
39708 $this->ensureDirectoryExists($targetPath);
39709 } else {
39710 copy($file->getPathname(), $targetPath);
39711 }
39712 }
39713
39714 $this->removeDirectoryPhp($source);
39715 }
39716
39717 public function rename($source, $target)
39718 {
39719 if (true === @rename($source, $target)) {
39720 return;
39721 }
39722
39723 if (!function_exists('proc_open')) {
39724 return $this->copyThenRemove($source, $target);
39725 }
39726
39727 if (Platform::isWindows()) {
39728
39729  $command = sprintf('xcopy %s %s /E /I /Q /Y', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
39730 $result = $this->processExecutor->execute($command, $output);
39731
39732
39733  clearstatcache();
39734
39735 if (0 === $result) {
39736 $this->remove($source);
39737
39738 return;
39739 }
39740 } else {
39741
39742  
39743  $command = sprintf('mv %s %s', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
39744 $result = $this->processExecutor->execute($command, $output);
39745
39746
39747  clearstatcache();
39748
39749 if (0 === $result) {
39750 return;
39751 }
39752 }
39753
39754 return $this->copyThenRemove($source, $target);
39755 }
39756
39757
39758
39759
39760
39761
39762
39763
39764
39765
39766 public function findShortestPath($from, $to, $directories = false)
39767 {
39768 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
39769 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
39770 }
39771
39772 $from = lcfirst($this->normalizePath($from));
39773 $to = lcfirst($this->normalizePath($to));
39774
39775 if ($directories) {
39776 $from = rtrim($from, '/') . '/dummy_file';
39777 }
39778
39779 if (dirname($from) === dirname($to)) {
39780 return './'.basename($to);
39781 }
39782
39783 $commonPath = $to;
39784 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) {
39785 $commonPath = strtr(dirname($commonPath), '\\', '/');
39786 }
39787
39788 if (0 !== strpos($from, $commonPath) || '/' === $commonPath) {
39789 return $to;
39790 }
39791
39792 $commonPath = rtrim($commonPath, '/') . '/';
39793 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/');
39794 $commonPathCode = str_repeat('../', $sourcePathDepth);
39795
39796 return ($commonPathCode . substr($to, strlen($commonPath))) ?: './';
39797 }
39798
39799
39800
39801
39802
39803
39804
39805
39806
39807
39808
39809 public function findShortestPathCode($from, $to, $directories = false, $staticCode = false)
39810 {
39811 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
39812 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
39813 }
39814
39815 $from = lcfirst($this->normalizePath($from));
39816 $to = lcfirst($this->normalizePath($to));
39817
39818 if ($from === $to) {
39819 return $directories ? '__DIR__' : '__FILE__';
39820 }
39821
39822 $commonPath = $to;
39823 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) {
39824 $commonPath = strtr(dirname($commonPath), '\\', '/');
39825 }
39826
39827 if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) {
39828 return var_export($to, true);
39829 }
39830
39831 $commonPath = rtrim($commonPath, '/') . '/';
39832 if (strpos($to, $from.'/') === 0) {
39833 return '__DIR__ . '.var_export(substr($to, strlen($from)), true);
39834 }
39835 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/') + $directories;
39836 if ($staticCode) {
39837 $commonPathCode = "__DIR__ . '".str_repeat('/..', $sourcePathDepth)."'";
39838 } else {
39839 $commonPathCode = str_repeat('dirname(', $sourcePathDepth).'__DIR__'.str_repeat(')', $sourcePathDepth);
39840 }
39841 $relTarget = substr($to, strlen($commonPath));
39842
39843 return $commonPathCode . (strlen($relTarget) ? '.' . var_export('/' . $relTarget, true) : '');
39844 }
39845
39846
39847
39848
39849
39850
39851
39852 public function isAbsolutePath($path)
39853 {
39854 return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':';
39855 }
39856
39857
39858
39859
39860
39861
39862
39863
39864
39865 public function size($path)
39866 {
39867 if (!file_exists($path)) {
39868 throw new \RuntimeException("$path does not exist.");
39869 }
39870 if (is_dir($path)) {
39871 return $this->directorySize($path);
39872 }
39873
39874 return filesize($path);
39875 }
39876
39877
39878
39879
39880
39881
39882
39883
39884 public function normalizePath($path)
39885 {
39886 $parts = array();
39887 $path = strtr($path, '\\', '/');
39888 $prefix = '';
39889 $absolute = false;
39890
39891
39892  if (preg_match('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
39893 $prefix = $match[1];
39894 $path = substr($path, strlen($prefix));
39895 }
39896
39897 if (substr($path, 0, 1) === '/') {
39898 $absolute = true;
39899 $path = substr($path, 1);
39900 }
39901
39902 $up = false;
39903 foreach (explode('/', $path) as $chunk) {
39904 if ('..' === $chunk && ($absolute || $up)) {
39905 array_pop($parts);
39906 $up = !(empty($parts) || '..' === end($parts));
39907 } elseif ('.' !== $chunk && '' !== $chunk) {
39908 $parts[] = $chunk;
39909 $up = '..' !== $chunk;
39910 }
39911 }
39912
39913 return $prefix.($absolute ? '/' : '').implode('/', $parts);
39914 }
39915
39916
39917
39918
39919
39920
39921
39922 public static function isLocalPath($path)
39923 {
39924 return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
39925 }
39926
39927 public static function getPlatformPath($path)
39928 {
39929 if (Platform::isWindows()) {
39930 $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
39931 }
39932
39933 return preg_replace('{^file://}i', '', $path);
39934 }
39935
39936 protected function directorySize($directory)
39937 {
39938 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
39939 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
39940
39941 $size = 0;
39942 foreach ($ri as $file) {
39943 if ($file->isFile()) {
39944 $size += $file->getSize();
39945 }
39946 }
39947
39948 return $size;
39949 }
39950
39951 protected function getProcess()
39952 {
39953 return new ProcessExecutor;
39954 }
39955
39956
39957
39958
39959
39960
39961
39962
39963
39964
39965 private function unlinkImplementation($path)
39966 {
39967 if (Platform::isWindows() && is_dir($path) && is_link($path)) {
39968 return rmdir($path);
39969 }
39970
39971 return unlink($path);
39972 }
39973
39974
39975
39976
39977
39978
39979
39980
39981 public function relativeSymlink($target, $link)
39982 {
39983 $cwd = getcwd();
39984
39985 $relativePath = $this->findShortestPath($link, $target);
39986 chdir(dirname($link));
39987 $result = @symlink($relativePath, $link);
39988
39989 chdir($cwd);
39990
39991 return (bool) $result;
39992 }
39993
39994
39995
39996
39997
39998
39999
40000
40001 public function isSymlinkedDirectory($directory)
40002 {
40003 if (!is_dir($directory)) {
40004 return false;
40005 }
40006
40007 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
40008
40009 return is_link($resolved);
40010 }
40011
40012
40013
40014
40015
40016
40017 private function unlinkSymlinkedDirectory($directory)
40018 {
40019 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
40020
40021 return $this->unlink($resolved);
40022 }
40023
40024
40025
40026
40027
40028
40029
40030
40031 private function resolveSymlinkedDirectorySymlink($pathname)
40032 {
40033 if (!is_dir($pathname)) {
40034 return $pathname;
40035 }
40036
40037 $resolved = rtrim($pathname, '/');
40038
40039 if (!strlen($resolved)) {
40040 return $pathname;
40041 }
40042
40043 return $resolved;
40044 }
40045
40046
40047
40048
40049
40050
40051
40052 public function junction($target, $junction)
40053 {
40054 if (!Platform::isWindows()) {
40055 throw new \LogicException(sprintf('Function %s is not available on non-Windows platform', __CLASS__));
40056 }
40057 if (!is_dir($target)) {
40058 throw new IOException(sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target);
40059 }
40060 $cmd = sprintf('mklink /J %s %s',
40061 ProcessExecutor::escape(str_replace('/', DIRECTORY_SEPARATOR, $junction)),
40062 ProcessExecutor::escape(realpath($target)));
40063 if ($this->getProcess()->execute($cmd, $output) !== 0) {
40064 throw new IOException(sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target);
40065 }
40066 clearstatcache(true, $junction);
40067 }
40068
40069
40070
40071
40072
40073
40074
40075 public function isJunction($junction)
40076 {
40077 if (!Platform::isWindows()) {
40078 return false;
40079 }
40080 if (!is_dir($junction) || is_link($junction)) {
40081 return false;
40082 }
40083
40084
40085
40086
40087
40088
40089
40090
40091
40092
40093
40094 clearstatcache(true, $junction);
40095 $stat = lstat($junction);
40096
40097 return !($stat['mode'] & 0xC000);
40098 }
40099
40100
40101
40102
40103
40104
40105
40106 public function removeJunction($junction)
40107 {
40108 if (!Platform::isWindows()) {
40109 return false;
40110 }
40111 $junction = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $junction), DIRECTORY_SEPARATOR);
40112 if (!$this->isJunction($junction)) {
40113 throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
40114 }
40115 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape($junction));
40116 clearstatcache(true, $junction);
40117
40118 return ($this->getProcess()->execute($cmd, $output) === 0);
40119 }
40120 }
40121 <?php
40122
40123
40124
40125
40126
40127
40128
40129
40130
40131
40132
40133 namespace Composer\Util;
40134
40135 use Composer\Config;
40136 use Composer\IO\IOInterface;
40137
40138
40139
40140
40141 class Git
40142 {
40143 private static $version;
40144
40145
40146 protected $io;
40147
40148 protected $config;
40149
40150 protected $process;
40151
40152 protected $filesystem;
40153
40154 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process, Filesystem $fs)
40155 {
40156 $this->io = $io;
40157 $this->config = $config;
40158 $this->process = $process;
40159 $this->filesystem = $fs;
40160 }
40161
40162 public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
40163 {
40164
40165  $this->config->prohibitUrlByConfig($url, $this->io);
40166
40167 if ($initialClone) {
40168 $origCwd = $cwd;
40169 $cwd = null;
40170 }
40171
40172 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
40173 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.');
40174 }
40175
40176 if (!$initialClone) {
40177
40178  $this->process->execute('git remote -v', $output, $cwd);
40179 if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match)) {
40180 $this->io->setAuthentication($match[3], urldecode($match[1]), urldecode($match[2]));
40181 }
40182 }
40183
40184 $protocols = $this->config->get('github-protocols');
40185 if (!is_array($protocols)) {
40186 throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols));
40187 }
40188
40189  if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
40190 $messages = array();
40191 foreach ($protocols as $protocol) {
40192 if ('ssh' === $protocol) {
40193 $protoUrl = "git@" . $match[1] . ":" . $match[2];
40194 } else {
40195 $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
40196 }
40197
40198 if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) {
40199 return;
40200 }
40201 $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', '  ', $this->process->getErrorOutput());
40202 if ($initialClone) {
40203 $this->filesystem->removeDirectory($origCwd);
40204 }
40205 }
40206
40207
40208  $this->throwException('Failed to clone ' . $url . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
40209 }
40210
40211
40212  $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
40213
40214 $command = call_user_func($commandCallable, $url);
40215
40216 $auth = null;
40217 if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
40218
40219  if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)) {
40220 if (!$this->io->hasAuthentication($match[1])) {
40221 $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
40222 $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
40223
40224 if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
40225 $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
40226 }
40227 }
40228
40229 if ($this->io->hasAuthentication($match[1])) {
40230 $auth = $this->io->getAuthentication($match[1]);
40231 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
40232 $command = call_user_func($commandCallable, $authUrl);
40233 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40234 return;
40235 }
40236 }
40237 } elseif (preg_match('{^https://(bitbucket\.org)/(.*)(\.git)?$}U', $url, $match)) { 
40238  $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process);
40239
40240 if (!$this->io->hasAuthentication($match[1])) {
40241 $message = 'Enter your Bitbucket credentials to access private repos';
40242
40243 if (!$bitbucketUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
40244 $bitbucketUtil->authorizeOAuthInteractively($match[1], $message);
40245 $accessToken = $bitbucketUtil->getToken();
40246 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
40247 }
40248 } else { 
40249  $auth = $this->io->getAuthentication($match[1]);
40250
40251
40252  if ($auth['username'] !== 'x-token-auth') {
40253 $accessToken = $bitbucketUtil->requestToken($match[1], $auth['username'], $auth['password']);
40254 if (! empty($accessToken)) {
40255 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
40256 }
40257 }
40258 }
40259
40260 if ($this->io->hasAuthentication($match[1])) {
40261 $auth = $this->io->getAuthentication($match[1]);
40262 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
40263
40264 $command = call_user_func($commandCallable, $authUrl);
40265 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40266 return;
40267 }
40268 } else { 
40269  $sshUrl = 'git@bitbucket.org:' . $match[2] . '.git';
40270 $this->io->writeError('    No bitbucket authentication configured. Falling back to ssh.');
40271 $command = call_user_func($commandCallable, $sshUrl);
40272 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40273 return;
40274 }
40275 }
40276 } elseif ($this->isAuthenticationFailure($url, $match)) { 
40277  if (strpos($match[2], '@')) {
40278 list($authParts, $match[2]) = explode('@', $match[2], 2);
40279 }
40280
40281 $storeAuth = false;
40282 if ($this->io->hasAuthentication($match[2])) {
40283 $auth = $this->io->getAuthentication($match[2]);
40284 } elseif ($this->io->isInteractive()) {
40285 $defaultUsername = null;
40286 if (isset($authParts) && $authParts) {
40287 if (false !== strpos($authParts, ':')) {
40288 list($defaultUsername, ) = explode(':', $authParts, 2);
40289 } else {
40290 $defaultUsername = $authParts;
40291 }
40292 }
40293
40294 $this->io->writeError('    Authentication required (<info>' . parse_url($url, PHP_URL_HOST) . '</info>):');
40295 $auth = array(
40296 'username' => $this->io->ask('      Username: ', $defaultUsername),
40297 'password' => $this->io->askAndHideAnswer('      Password: '),
40298 );
40299 $storeAuth = $this->config->get('store-auths');
40300 }
40301
40302 if ($auth) {
40303 $authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
40304
40305 $command = call_user_func($commandCallable, $authUrl);
40306 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40307 $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
40308 $authHelper = new AuthHelper($this->io, $this->config);
40309 $authHelper->storeAuth($match[2], $storeAuth);
40310
40311 return;
40312 }
40313 }
40314 }
40315
40316 if ($initialClone) {
40317 $this->filesystem->removeDirectory($origCwd);
40318 }
40319 $this->throwException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput(), $url);
40320 }
40321 }
40322
40323 public function syncMirror($url, $dir)
40324 {
40325
40326  if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
40327 try {
40328 $commandCallable = function ($url) {
40329 return sprintf('git remote set-url origin %s && git remote update --prune origin', ProcessExecutor::escape($url));
40330 };
40331 $this->runCommand($commandCallable, $url, $dir);
40332 } catch (\Exception $e) {
40333 return false;
40334 }
40335
40336 return true;
40337 }
40338
40339
40340  $this->filesystem->removeDirectory($dir);
40341
40342 $commandCallable = function ($url) use ($dir) {
40343 return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
40344 };
40345
40346 $this->runCommand($commandCallable, $url, $dir, true);
40347
40348 return true;
40349 }
40350
40351 private function isAuthenticationFailure($url, &$match)
40352 {
40353 if (!preg_match('{(https?://)([^/]+)(.*)$}i', $url, $match)) {
40354 return false;
40355 }
40356
40357 $authFailures = array(
40358 'fatal: Authentication failed',
40359 'remote error: Invalid username or password.',
40360 'error: 401 Unauthorized',
40361 'fatal: unable to access',
40362 );
40363
40364 foreach ($authFailures as $authFailure) {
40365 if (strpos($this->process->getErrorOutput(), $authFailure) !== false) {
40366 return true;
40367 }
40368 }
40369
40370 return false;
40371 }
40372
40373 public static function cleanEnv()
40374 {
40375 if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
40376 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');
40377 }
40378
40379
40380  if (getenv('GIT_ASKPASS') !== 'echo') {
40381 putenv('GIT_ASKPASS=echo');
40382 unset($_SERVER['GIT_ASKPASS']);
40383 }
40384
40385
40386  if (getenv('GIT_DIR')) {
40387 putenv('GIT_DIR');
40388 unset($_SERVER['GIT_DIR']);
40389 }
40390 if (getenv('GIT_WORK_TREE')) {
40391 putenv('GIT_WORK_TREE');
40392 unset($_SERVER['GIT_WORK_TREE']);
40393 }
40394
40395
40396  if (getenv('LANGUAGE') !== 'C') {
40397 putenv('LANGUAGE=C');
40398 }
40399
40400
40401  putenv("DYLD_LIBRARY_PATH");
40402 unset($_SERVER['DYLD_LIBRARY_PATH']);
40403 }
40404
40405 public static function getGitHubDomainsRegex(Config $config)
40406 {
40407 return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
40408 }
40409
40410 public static function sanitizeUrl($message)
40411 {
40412 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
40413 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
40414 return '://***:***@';
40415 }
40416
40417 return '://' . $m[1] . ':***@';
40418 }, $message);
40419 }
40420
40421 private function throwException($message, $url)
40422 {
40423
40424  clearstatcache();
40425
40426 if (0 !== $this->process->execute('git --version', $ignoredOutput)) {
40427 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()));
40428 }
40429
40430 throw new \RuntimeException(self::sanitizeUrl($message));
40431 }
40432
40433
40434
40435
40436
40437
40438 public function getVersion()
40439 {
40440 if (isset(self::$version)) {
40441 return self::$version;
40442 }
40443 if (0 !== $this->process->execute('git --version', $output)) {
40444 return;
40445 }
40446 if (preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
40447 return self::$version = $matches[1];
40448 }
40449 }
40450 }
40451 <?php
40452
40453
40454
40455
40456
40457
40458
40459
40460
40461
40462
40463 namespace Composer\Util;
40464
40465 use Composer\Factory;
40466 use Composer\IO\IOInterface;
40467 use Composer\Config;
40468 use Composer\Downloader\TransportException;
40469
40470
40471
40472
40473 class GitHub
40474 {
40475 protected $io;
40476 protected $config;
40477 protected $process;
40478 protected $remoteFilesystem;
40479
40480
40481
40482
40483
40484
40485
40486
40487
40488 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
40489 {
40490 $this->io = $io;
40491 $this->config = $config;
40492 $this->process = $process ?: new ProcessExecutor;
40493 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
40494 }
40495
40496
40497
40498
40499
40500
40501
40502 public function authorizeOAuth($originUrl)
40503 {
40504 if (!in_array($originUrl, $this->config->get('github-domains'))) {
40505 return false;
40506 }
40507
40508
40509  if (0 === $this->process->execute('git config github.accesstoken', $output)) {
40510 $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
40511
40512 return true;
40513 }
40514
40515 return false;
40516 }
40517
40518
40519
40520
40521
40522
40523
40524
40525
40526
40527 public function authorizeOAuthInteractively($originUrl, $message = null)
40528 {
40529 if ($message) {
40530 $this->io->writeError($message);
40531 }
40532
40533 $note = 'Composer';
40534 if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
40535 $note .= ' on ' . trim($output);
40536 }
40537 $note .= ' ' . date('Y-m-d Hi');
40538
40539 $url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
40540 $this->io->writeError(sprintf('Head to %s', $url));
40541 $this->io->writeError(sprintf('to retrieve a token. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
40542
40543 $token = trim($this->io->askAndHideAnswer('Token (hidden): '));
40544
40545 if (!$token) {
40546 $this->io->writeError('<warning>No token given, aborting.</warning>');
40547 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
40548
40549 return false;
40550 }
40551
40552 $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
40553
40554 try {
40555 $apiUrl = ('github.com' === $originUrl) ? 'api.github.com/' : $originUrl . '/api/v3/';
40556
40557 $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl, false, array(
40558 'retry-auth-failure' => false,
40559 ));
40560 } catch (TransportException $e) {
40561 if (in_array($e->getCode(), array(403, 401))) {
40562 $this->io->writeError('<error>Invalid token provided.</error>');
40563 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
40564
40565 return false;
40566 }
40567
40568 throw $e;
40569 }
40570
40571
40572  $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
40573 $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
40574
40575 $this->io->writeError('<info>Token stored successfully.</info>');
40576
40577 return true;
40578 }
40579 }
40580 <?php
40581
40582
40583
40584
40585
40586
40587
40588
40589
40590
40591
40592 namespace Composer\Util;
40593
40594 use Composer\IO\IOInterface;
40595 use Composer\Config;
40596 use Composer\Factory;
40597 use Composer\Downloader\TransportException;
40598 use Composer\Json\JsonFile;
40599
40600
40601
40602
40603 class GitLab
40604 {
40605 protected $io;
40606 protected $config;
40607 protected $process;
40608 protected $remoteFilesystem;
40609
40610
40611
40612
40613
40614
40615
40616
40617
40618 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
40619 {
40620 $this->io = $io;
40621 $this->config = $config;
40622 $this->process = $process ?: new ProcessExecutor();
40623 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
40624 }
40625
40626
40627
40628
40629
40630
40631
40632
40633 public function authorizeOAuth($originUrl)
40634 {
40635 if (!in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
40636 return false;
40637 }
40638
40639
40640  if (0 === $this->process->execute('git config gitlab.accesstoken', $output)) {
40641 $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
40642
40643 return true;
40644 }
40645
40646
40647  $authTokens = $this->config->get('gitlab-token');
40648
40649 if (isset($authTokens[$originUrl])) {
40650 $this->io->setAuthentication($originUrl, $authTokens[$originUrl], 'private-token');
40651
40652 return true;
40653 }
40654
40655 return false;
40656 }
40657
40658
40659
40660
40661
40662
40663
40664
40665
40666
40667
40668
40669
40670 public function authorizeOAuthInteractively($scheme, $originUrl, $message = null)
40671 {
40672 if ($message) {
40673 $this->io->writeError($message);
40674 }
40675
40676 $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
40677 $this->io->writeError('To revoke access to this token you can visit '.$originUrl.'/profile/applications');
40678
40679 $attemptCounter = 0;
40680
40681 while ($attemptCounter++ < 5) {
40682 try {
40683 $response = $this->createToken($scheme, $originUrl);
40684 } catch (TransportException $e) {
40685
40686  
40687  if (in_array($e->getCode(), array(403, 401))) {
40688 if (401 === $e->getCode()) {
40689 $this->io->writeError('Bad credentials.');
40690 } else {
40691 $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
40692 }
40693
40694 $this->io->writeError('You can also manually create a personal token at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
40695 $this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
40696
40697 continue;
40698 }
40699
40700 throw $e;
40701 }
40702
40703 $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
40704
40705
40706  $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
40707
40708 return true;
40709 }
40710
40711 throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
40712 }
40713
40714 private function createToken($scheme, $originUrl)
40715 {
40716 $username = $this->io->ask('Username: ');
40717 $password = $this->io->askAndHideAnswer('Password: ');
40718
40719 $headers = array('Content-Type: application/x-www-form-urlencoded');
40720
40721 $apiUrl = $originUrl;
40722 $data = http_build_query(array(
40723 'username' => $username,
40724 'password' => $password,
40725 'grant_type' => 'password',
40726 ), null, '&');
40727 $options = array(
40728 'retry-auth-failure' => false,
40729 'http' => array(
40730 'method' => 'POST',
40731 'header' => $headers,
40732 'content' => $data,
40733 ),
40734 );
40735
40736 $json = $this->remoteFilesystem->getContents($originUrl, $scheme.'://'.$apiUrl.'/oauth/token', false, $options);
40737
40738 $this->io->writeError('Token successfully created');
40739
40740 return JsonFile::parseJson($json);
40741 }
40742 }
40743 <?php
40744
40745
40746
40747
40748
40749
40750
40751
40752
40753
40754
40755 namespace Composer\Util;
40756
40757
40758
40759
40760
40761
40762
40763
40764 class IniHelper
40765 {
40766 const ENV_ORIGINAL = 'COMPOSER_ORIGINAL_INIS';
40767
40768
40769
40770
40771
40772
40773
40774
40775
40776 public static function getAll()
40777 {
40778 if ($env = strval(getenv(self::ENV_ORIGINAL))) {
40779 return explode(PATH_SEPARATOR, $env);
40780 }
40781
40782 $paths = array(strval(php_ini_loaded_file()));
40783
40784 if ($scanned = php_ini_scanned_files()) {
40785 $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
40786 }
40787
40788 return $paths;
40789 }
40790
40791
40792
40793
40794
40795
40796 public static function getMessage()
40797 {
40798 $paths = self::getAll();
40799
40800 if (empty($paths[0])) {
40801 return 'A php.ini file does not exist. You will have to create one.';
40802 }
40803
40804 return 'The php.ini used by your command-line PHP is: '.$paths[0];
40805 }
40806 }
40807 <?php
40808
40809
40810
40811
40812
40813
40814
40815
40816
40817
40818
40819 namespace Composer\Util;
40820
40821
40822
40823
40824 class NoProxyPattern
40825 {
40826
40827
40828
40829 protected $rules = array();
40830
40831
40832
40833
40834 public function __construct($pattern)
40835 {
40836 $this->rules = preg_split("/[\s,]+/", $pattern);
40837 }
40838
40839
40840
40841
40842
40843
40844
40845
40846 public function test($url)
40847 {
40848 $host = parse_url($url, PHP_URL_HOST);
40849 $port = parse_url($url, PHP_URL_PORT);
40850
40851 if (empty($port)) {
40852 switch (parse_url($url, PHP_URL_SCHEME)) {
40853 case 'http':
40854 $port = 80;
40855 break;
40856 case 'https':
40857 $port = 443;
40858 break;
40859 }
40860 }
40861
40862 foreach ($this->rules as $rule) {
40863 if ($rule == '*') {
40864 return true;
40865 }
40866
40867 $match = false;
40868
40869 list($ruleHost) = explode(':', $rule);
40870 list($base) = explode('/', $ruleHost);
40871
40872 if (filter_var($base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
40873
40874
40875 if (!isset($ip)) {
40876 $ip = gethostbyname($host);
40877 }
40878
40879 if (strpos($ruleHost, '/') === false) {
40880 $match = $ip === $ruleHost;
40881 } else {
40882
40883  
40884  if ($ip === $host) {
40885 $match = false;
40886 } else {
40887
40888  $match = self::inCIDRBlock($ruleHost, $ip);
40889 }
40890 }
40891 } else {
40892
40893
40894 $haystack = '.' . trim($host, '.') . '.';
40895 $needle = '.'. trim($ruleHost, '.') .'.';
40896 $match = stripos(strrev($haystack), strrev($needle)) === 0;
40897 }
40898
40899
40900  if ($match && strpos($rule, ':') !== false) {
40901 list(, $rulePort) = explode(':', $rule);
40902 if (!empty($rulePort) && $port != $rulePort) {
40903 $match = false;
40904 }
40905 }
40906
40907 if ($match) {
40908 return true;
40909 }
40910 }
40911
40912 return false;
40913 }
40914
40915
40916
40917
40918
40919
40920
40921
40922
40923
40924
40925 private static function inCIDRBlock($cidr, $ip)
40926 {
40927
40928  list($base, $bits) = explode('/', $cidr);
40929
40930
40931  list($a, $b, $c, $d) = explode('.', $base);
40932
40933
40934  $i = ($a << 24) + ($b << 16) + ($c << 8) + $d;
40935 $mask = $bits == 0 ? 0 : (~0 << (32 - $bits));
40936
40937
40938  $low = $i & $mask;
40939
40940
40941  $high = $i | (~$mask & 0xFFFFFFFF);
40942
40943
40944  list($a, $b, $c, $d) = explode('.', $ip);
40945
40946
40947  $check = ($a << 24) + ($b << 16) + ($c << 8) + $d;
40948
40949
40950  
40951  return $check >= $low && $check <= $high;
40952 }
40953 }
40954 <?php
40955
40956
40957
40958
40959
40960
40961
40962
40963
40964
40965
40966 namespace Composer\Util;
40967
40968 use Composer\IO\IOInterface;
40969 use Symfony\Component\Process\Process;
40970
40971
40972
40973
40974 class Perforce
40975 {
40976 protected $path;
40977 protected $p4Depot;
40978 protected $p4Client;
40979 protected $p4User;
40980 protected $p4Password;
40981 protected $p4Port;
40982 protected $p4Stream;
40983 protected $p4ClientSpec;
40984 protected $p4DepotType;
40985 protected $p4Branch;
40986 protected $process;
40987 protected $uniquePerforceClientName;
40988 protected $windowsFlag;
40989 protected $commandResult;
40990
40991 protected $io;
40992
40993 protected $filesystem;
40994
40995 public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
40996 {
40997 $this->windowsFlag = $isWindows;
40998 $this->p4Port = $port;
40999 $this->initializePath($path);
41000 $this->process = $process;
41001 $this->initialize($repoConfig);
41002 $this->io = $io;
41003 }
41004
41005 public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
41006 {
41007 return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io);
41008 }
41009
41010 public static function checkServerExists($url, ProcessExecutor $processExecutor)
41011 {
41012 $output = null;
41013
41014 return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s', $output);
41015 }
41016
41017 public function initialize($repoConfig)
41018 {
41019 $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
41020 if (!$repoConfig) {
41021 return;
41022 }
41023 if (isset($repoConfig['unique_perforce_client_name'])) {
41024 $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
41025 }
41026
41027 if (isset($repoConfig['depot'])) {
41028 $this->p4Depot = $repoConfig['depot'];
41029 }
41030 if (isset($repoConfig['branch'])) {
41031 $this->p4Branch = $repoConfig['branch'];
41032 }
41033 if (isset($repoConfig['p4user'])) {
41034 $this->p4User = $repoConfig['p4user'];
41035 } else {
41036 $this->p4User = $this->getP4variable('P4USER');
41037 }
41038 if (isset($repoConfig['p4password'])) {
41039 $this->p4Password = $repoConfig['p4password'];
41040 }
41041 }
41042
41043 public function initializeDepotAndBranch($depot, $branch)
41044 {
41045 if (isset($depot)) {
41046 $this->p4Depot = $depot;
41047 }
41048 if (isset($branch)) {
41049 $this->p4Branch = $branch;
41050 }
41051 }
41052
41053 public function generateUniquePerforceClientName()
41054 {
41055 return gethostname() . "_" . time();
41056 }
41057
41058 public function cleanupClientSpec()
41059 {
41060 $client = $this->getClient();
41061 $task = 'client -d ' . $client;
41062 $useP4Client = false;
41063 $command = $this->generateP4Command($task, $useP4Client);
41064 $this->executeCommand($command);
41065 $clientSpec = $this->getP4ClientSpec();
41066 $fileSystem = $this->getFilesystem();
41067 $fileSystem->remove($clientSpec);
41068 }
41069
41070 protected function executeCommand($command)
41071 {
41072 $this->commandResult = "";
41073 $exit_code = $this->process->execute($command, $this->commandResult);
41074
41075 return $exit_code;
41076 }
41077
41078 public function getClient()
41079 {
41080 if (!isset($this->p4Client)) {
41081 $cleanStreamName = str_replace('@', '', str_replace('/', '_', str_replace('//', '', $this->getStream())));
41082 $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
41083 }
41084
41085 return $this->p4Client;
41086 }
41087
41088 protected function getPath()
41089 {
41090 return $this->path;
41091 }
41092
41093 public function initializePath($path)
41094 {
41095 $this->path = $path;
41096 $fs = $this->getFilesystem();
41097 $fs->ensureDirectoryExists($path);
41098 }
41099
41100 protected function getPort()
41101 {
41102 return $this->p4Port;
41103 }
41104
41105 public function setStream($stream)
41106 {
41107 $this->p4Stream = $stream;
41108 $index = strrpos($stream, '/');
41109
41110  if ($index > 2) {
41111 $this->p4DepotType = 'stream';
41112 }
41113 }
41114
41115 public function isStream()
41116 {
41117 return (strcmp($this->p4DepotType, 'stream') === 0);
41118 }
41119
41120 public function getStream()
41121 {
41122 if (!isset($this->p4Stream)) {
41123 if ($this->isStream()) {
41124 $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
41125 } else {
41126 $this->p4Stream = '//' . $this->p4Depot;
41127 }
41128 }
41129
41130 return $this->p4Stream;
41131 }
41132
41133 public function getStreamWithoutLabel($stream)
41134 {
41135 $index = strpos($stream, '@');
41136 if ($index === false) {
41137 return $stream;
41138 }
41139
41140 return substr($stream, 0, $index);
41141 }
41142
41143 public function getP4ClientSpec()
41144 {
41145 $p4clientSpec = $this->path . '/' . $this->getClient() . '.p4.spec';
41146
41147 return $p4clientSpec;
41148 }
41149
41150 public function getUser()
41151 {
41152 return $this->p4User;
41153 }
41154
41155 public function setUser($user)
41156 {
41157 $this->p4User = $user;
41158 }
41159
41160 public function queryP4User()
41161 {
41162 $this->getUser();
41163 if (strlen($this->p4User) > 0) {
41164 return;
41165 }
41166 $this->p4User = $this->getP4variable('P4USER');
41167 if (strlen($this->p4User) > 0) {
41168 return;
41169 }
41170 $this->p4User = $this->io->ask('Enter P4 User:');
41171 if ($this->windowsFlag) {
41172 $command = 'p4 set P4USER=' . $this->p4User;
41173 } else {
41174 $command = 'export P4USER=' . $this->p4User;
41175 }
41176 $this->executeCommand($command);
41177 }
41178
41179 protected function getP4variable($name)
41180 {
41181 if ($this->windowsFlag) {
41182 $command = 'p4 set';
41183 $this->executeCommand($command);
41184 $result = trim($this->commandResult);
41185 $resArray = explode(PHP_EOL, $result);
41186 foreach ($resArray as $line) {
41187 $fields = explode('=', $line);
41188 if (strcmp($name, $fields[0]) == 0) {
41189 $index = strpos($fields[1], ' ');
41190 if ($index === false) {
41191 $value = $fields[1];
41192 } else {
41193 $value = substr($fields[1], 0, $index);
41194 }
41195 $value = trim($value);
41196
41197 return $value;
41198 }
41199 }
41200
41201 return null;
41202 } else {
41203 $command = 'echo $' . $name;
41204 $this->executeCommand($command);
41205 $result = trim($this->commandResult);
41206
41207 return $result;
41208 }
41209 }
41210
41211 public function queryP4Password()
41212 {
41213 if (isset($this->p4Password)) {
41214 return $this->p4Password;
41215 }
41216 $password = $this->getP4variable('P4PASSWD');
41217 if (strlen($password) <= 0) {
41218 $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
41219 }
41220 $this->p4Password = $password;
41221
41222 return $password;
41223 }
41224
41225 public function generateP4Command($command, $useClient = true)
41226 {
41227 $p4Command = 'p4 ';
41228 $p4Command = $p4Command . '-u ' . $this->getUser() . ' ';
41229 if ($useClient) {
41230 $p4Command = $p4Command . '-c ' . $this->getClient() . ' ';
41231 }
41232 $p4Command = $p4Command . '-p ' . $this->getPort() . ' ';
41233 $p4Command = $p4Command . $command;
41234
41235 return $p4Command;
41236 }
41237
41238 public function isLoggedIn()
41239 {
41240 $command = $this->generateP4Command('login -s', false);
41241 $exitCode = $this->executeCommand($command);
41242 if ($exitCode) {
41243 $errorOutput = $this->process->getErrorOutput();
41244 $index = strpos($errorOutput, $this->getUser());
41245 if ($index === false) {
41246 $index = strpos($errorOutput, 'p4');
41247 if ($index === false) {
41248 return false;
41249 }
41250 throw new \Exception('p4 command not found in path: ' . $errorOutput);
41251 }
41252 throw new \Exception('Invalid user name: ' . $this->getUser());
41253 }
41254
41255 return true;
41256 }
41257
41258 public function connectClient()
41259 {
41260 $p4CreateClientCommand = $this->generateP4Command(
41261 'client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())
41262 );
41263 $this->executeCommand($p4CreateClientCommand);
41264 }
41265
41266 public function syncCodeBase($sourceReference)
41267 {
41268 $prevDir = getcwd();
41269 chdir($this->path);
41270 $p4SyncCommand = $this->generateP4Command('sync -f ');
41271 if (null !== $sourceReference) {
41272 $p4SyncCommand = $p4SyncCommand . '@' . $sourceReference;
41273 }
41274 $this->executeCommand($p4SyncCommand);
41275 chdir($prevDir);
41276 }
41277
41278 public function writeClientSpecToFile($spec)
41279 {
41280 fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
41281 fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL);
41282 fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL);
41283 fwrite($spec, 'Owner:  ' . $this->getUser() . PHP_EOL . PHP_EOL);
41284 fwrite($spec, 'Description:' . PHP_EOL);
41285 fwrite($spec, '  Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL);
41286 fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL);
41287 fwrite($spec, 'Options:  noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL);
41288 fwrite($spec, 'SubmitOptions:  revertunchanged' . PHP_EOL . PHP_EOL);
41289 fwrite($spec, 'LineEnd:  local' . PHP_EOL . PHP_EOL);
41290 if ($this->isStream()) {
41291 fwrite($spec, 'Stream:' . PHP_EOL);
41292 fwrite($spec, '  ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL);
41293 } else {
41294 fwrite(
41295 $spec,
41296 'View:  ' . $this->getStream() . '/...  //' . $this->getClient() . '/... ' . PHP_EOL
41297 );
41298 }
41299 }
41300
41301 public function writeP4ClientSpec()
41302 {
41303 $clientSpec = $this->getP4ClientSpec();
41304 $spec = fopen($clientSpec, 'w');
41305 try {
41306 $this->writeClientSpecToFile($spec);
41307 } catch (\Exception $e) {
41308 fclose($spec);
41309 throw $e;
41310 }
41311 fclose($spec);
41312 }
41313
41314 protected function read($pipe, $name)
41315 {
41316 if (feof($pipe)) {
41317 return;
41318 }
41319 $line = fgets($pipe);
41320 while ($line !== false) {
41321 $line = fgets($pipe);
41322 }
41323
41324 return;
41325 }
41326
41327 public function windowsLogin($password)
41328 {
41329 $command = $this->generateP4Command(' login -a');
41330 $process = new Process($command, null, null, $password);
41331
41332 return $process->run();
41333 }
41334
41335 public function p4Login()
41336 {
41337 $this->queryP4User();
41338 if (!$this->isLoggedIn()) {
41339 $password = $this->queryP4Password();
41340 if ($this->windowsFlag) {
41341 $this->windowsLogin($password);
41342 } else {
41343 $command = 'echo ' . $password . ' | ' . $this->generateP4Command(' login -a', false);
41344 $exitCode = $this->executeCommand($command);
41345 $result = trim($this->commandResult);
41346 if ($exitCode) {
41347 throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
41348 }
41349 }
41350 }
41351 }
41352
41353 public function getComposerInformation($identifier)
41354 {
41355 $composerFileContent = $this->getFileContent('composer.json', $identifier);
41356
41357 if (!$composerFileContent) {
41358 return;
41359 }
41360
41361 return json_decode($composerFileContent, true);
41362 }
41363
41364 public function getFileContent($file, $identifier)
41365 {
41366 $path = $this->getFilePath($file, $identifier);
41367
41368 $command = $this->generateP4Command(' print ' . $path);
41369 $this->executeCommand($command);
41370 $result = $this->commandResult;
41371
41372 if (!trim($result)) {
41373 return null;
41374 }
41375
41376 return $result;
41377 }
41378
41379 public function getFilePath($file, $identifier)
41380 {
41381 $index = strpos($identifier, '@');
41382 if ($index === false) {
41383 $path = $identifier. '/' . $file;
41384
41385 return $path;
41386 } else {
41387 $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index);
41388 $command = $this->generateP4Command(' files ' . $path, false);
41389 $this->executeCommand($command);
41390 $result = $this->commandResult;
41391 $index2 = strpos($result, 'no such file(s).');
41392 if ($index2 === false) {
41393 $index3 = strpos($result, 'change');
41394 if ($index3 !== false) {
41395 $phrase = trim(substr($result, $index3));
41396 $fields = explode(' ', $phrase);
41397
41398 return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1];
41399 }
41400 }
41401 }
41402
41403 return null;
41404 }
41405
41406 public function getBranches()
41407 {
41408 $possibleBranches = array();
41409 if (!$this->isStream()) {
41410 $possibleBranches[$this->p4Branch] = $this->getStream();
41411 } else {
41412 $command = $this->generateP4Command('streams //' . $this->p4Depot . '/...');
41413 $this->executeCommand($command);
41414 $result = $this->commandResult;
41415 $resArray = explode(PHP_EOL, $result);
41416 foreach ($resArray as $line) {
41417 $resBits = explode(' ', $line);
41418 if (count($resBits) > 4) {
41419 $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
41420 $possibleBranches[$branch] = $resBits[1];
41421 }
41422 }
41423 }
41424 $command = $this->generateP4Command('changes '. $this->getStream() . '/...', false);
41425 $this->executeCommand($command);
41426 $result = $this->commandResult;
41427 $resArray = explode(PHP_EOL, $result);
41428 $lastCommit = $resArray[0];
41429 $lastCommitArr = explode(' ', $lastCommit);
41430 $lastCommitNum = $lastCommitArr[1];
41431
41432 $branches = array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
41433
41434 return $branches;
41435 }
41436
41437 public function getTags()
41438 {
41439 $command = $this->generateP4Command('labels');
41440 $this->executeCommand($command);
41441 $result = $this->commandResult;
41442 $resArray = explode(PHP_EOL, $result);
41443 $tags = array();
41444 foreach ($resArray as $line) {
41445 $index = strpos($line, 'Label');
41446 if (!($index === false)) {
41447 $fields = explode(' ', $line);
41448 $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
41449 }
41450 }
41451
41452 return $tags;
41453 }
41454
41455 public function checkStream()
41456 {
41457 $command = $this->generateP4Command('depots', false);
41458 $this->executeCommand($command);
41459 $result = $this->commandResult;
41460 $resArray = explode(PHP_EOL, $result);
41461 foreach ($resArray as $line) {
41462 $index = strpos($line, 'Depot');
41463 if (!($index === false)) {
41464 $fields = explode(' ', $line);
41465 if (strcmp($this->p4Depot, $fields[1]) === 0) {
41466 $this->p4DepotType = $fields[3];
41467
41468 return $this->isStream();
41469 }
41470 }
41471 }
41472
41473 return false;
41474 }
41475
41476
41477
41478
41479
41480 protected function getChangeList($reference)
41481 {
41482 $index = strpos($reference, '@');
41483 if ($index === false) {
41484 return null;
41485 }
41486 $label = substr($reference, $index);
41487 $command = $this->generateP4Command(' changes -m1 ' . $label);
41488 $this->executeCommand($command);
41489 $changes = $this->commandResult;
41490 if (strpos($changes, 'Change') !== 0) {
41491 return null;
41492 }
41493 $fields = explode(' ', $changes);
41494 $changeList = $fields[1];
41495
41496 return $changeList;
41497 }
41498
41499
41500
41501
41502
41503
41504 public function getCommitLogs($fromReference, $toReference)
41505 {
41506 $fromChangeList = $this->getChangeList($fromReference);
41507 if ($fromChangeList === null) {
41508 return null;
41509 }
41510 $toChangeList = $this->getChangeList($toReference);
41511 if ($toChangeList === null) {
41512 return null;
41513 }
41514 $index = strpos($fromReference, '@');
41515 $main = substr($fromReference, 0, $index) . '/...';
41516 $command = $this->generateP4Command('filelog ' . $main . '@' . $fromChangeList. ',' . $toChangeList);
41517 $this->executeCommand($command);
41518 $result = $this->commandResult;
41519
41520 return $result;
41521 }
41522
41523 public function getFilesystem()
41524 {
41525 if (empty($this->filesystem)) {
41526 $this->filesystem = new Filesystem($this->process);
41527 }
41528
41529 return $this->filesystem;
41530 }
41531
41532 public function setFilesystem(Filesystem $fs)
41533 {
41534 $this->filesystem = $fs;
41535 }
41536 }
41537 <?php
41538
41539
41540
41541
41542
41543
41544
41545
41546
41547
41548
41549 namespace Composer\Util;
41550
41551
41552
41553
41554
41555
41556 class Platform
41557 {
41558
41559
41560
41561
41562
41563
41564 public static function expandPath($path)
41565 {
41566 if (preg_match('#^~[\\/]#', $path)) {
41567 return self::getUserDirectory() . substr($path, 1);
41568 }
41569
41570 return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
41571
41572  if (Platform::isWindows() && $matches['var'] == 'HOME') {
41573 return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches['path'];
41574 }
41575
41576 return getenv($matches['var']) . $matches['path'];
41577 }, $path);
41578 }
41579
41580
41581
41582
41583
41584 public static function getUserDirectory()
41585 {
41586 if (false !== ($home = getenv('HOME'))) {
41587 return $home;
41588 }
41589
41590 if (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) {
41591 return $home;
41592 }
41593
41594 if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
41595 $info = posix_getpwuid(posix_getuid());
41596
41597 return $info['dir'];
41598 }
41599
41600 throw new \RuntimeException('Could not determine user directory');
41601 }
41602
41603
41604
41605
41606 public static function isWindows()
41607 {
41608 return defined('PHP_WINDOWS_VERSION_BUILD');
41609 }
41610
41611
41612
41613
41614
41615 public static function strlen($str)
41616 {
41617 static $useMbString = null;
41618 if (null === $useMbString) {
41619 $useMbString = function_exists('mb_strlen') && ini_get('mbstring.func_overload');
41620 }
41621
41622 if ($useMbString) {
41623 return mb_strlen($str, '8bit');
41624 }
41625
41626 return strlen($str);
41627 }
41628 }
41629 <?php
41630
41631
41632
41633
41634
41635
41636
41637
41638
41639
41640
41641 namespace Composer\Util;
41642
41643 use Symfony\Component\Process\Process;
41644 use Symfony\Component\Process\ProcessUtils;
41645 use Composer\IO\IOInterface;
41646
41647
41648
41649
41650 class ProcessExecutor
41651 {
41652 protected static $timeout = 300;
41653
41654 protected $captureOutput;
41655 protected $errorOutput;
41656 protected $io;
41657
41658 public function __construct(IOInterface $io = null)
41659 {
41660 $this->io = $io;
41661 }
41662
41663
41664
41665
41666
41667
41668
41669
41670
41671
41672 public function execute($command, &$output = null, $cwd = null)
41673 {
41674 if ($this->io && $this->io->isDebug()) {
41675 $safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
41676 if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) {
41677 return '://***:***@';
41678 }
41679
41680 return '://'.$m['user'].':***@';
41681 }, $command);
41682 $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
41683 }
41684
41685
41686  
41687  if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) {
41688 $cwd = realpath(getcwd());
41689 }
41690
41691 $this->captureOutput = count(func_get_args()) > 1;
41692 $this->errorOutput = null;
41693 $process = new Process($command, $cwd, null, null, static::getTimeout());
41694
41695 $callback = is_callable($output) ? $output : array($this, 'outputHandler');
41696 $process->run($callback);
41697
41698 if ($this->captureOutput && !is_callable($output)) {
41699 $output = $process->getOutput();
41700 }
41701
41702 $this->errorOutput = $process->getErrorOutput();
41703
41704 return $process->getExitCode();
41705 }
41706
41707 public function splitLines($output)
41708 {
41709 $output = trim($output);
41710
41711 return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output);
41712 }
41713
41714
41715
41716
41717
41718
41719 public function getErrorOutput()
41720 {
41721 return $this->errorOutput;
41722 }
41723
41724 public function outputHandler($type, $buffer)
41725 {
41726 if ($this->captureOutput) {
41727 return;
41728 }
41729
41730 if (null === $this->io) {
41731 echo $buffer;
41732
41733 return;
41734 }
41735
41736 if (Process::ERR === $type) {
41737 $this->io->writeError($buffer, false);
41738 } else {
41739 $this->io->write($buffer, false);
41740 }
41741 }
41742
41743 public static function getTimeout()
41744 {
41745 return static::$timeout;
41746 }
41747
41748 public static function setTimeout($timeout)
41749 {
41750 static::$timeout = $timeout;
41751 }
41752
41753
41754
41755
41756
41757
41758
41759
41760 public static function escape($argument)
41761 {
41762 return ProcessUtils::escapeArgument($argument);
41763 }
41764 }
41765 <?php
41766
41767
41768
41769
41770
41771
41772
41773
41774
41775
41776
41777 namespace Composer\Util;
41778
41779 use Composer\Config;
41780 use Composer\IO\IOInterface;
41781 use Composer\Downloader\TransportException;
41782 use Composer\CaBundle\CaBundle;
41783 use Psr\Log\LoggerInterface;
41784
41785
41786
41787
41788
41789
41790 class RemoteFilesystem
41791 {
41792 private $io;
41793 private $config;
41794 private $scheme;
41795 private $bytesMax;
41796 private $originUrl;
41797 private $fileUrl;
41798 private $fileName;
41799 private $retry;
41800 private $progress;
41801 private $lastProgress;
41802 private $options = array();
41803 private $peerCertificateMap = array();
41804 private $disableTls = false;
41805 private $retryAuthFailure;
41806 private $lastHeaders;
41807 private $storeAuth;
41808 private $degradedMode = false;
41809 private $redirects;
41810 private $maxRedirects = 20;
41811
41812
41813
41814
41815
41816
41817
41818
41819
41820 public function __construct(IOInterface $io, Config $config = null, array $options = array(), $disableTls = false)
41821 {
41822 $this->io = $io;
41823
41824
41825  
41826  if ($disableTls === false) {
41827 $this->options = $this->getTlsDefaults($options);
41828 } else {
41829 $this->disableTls = true;
41830 }
41831
41832
41833  $this->options = array_replace_recursive($this->options, $options);
41834 $this->config = $config;
41835 }
41836
41837
41838
41839
41840
41841
41842
41843
41844
41845
41846
41847
41848 public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array())
41849 {
41850 return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
41851 }
41852
41853
41854
41855
41856
41857
41858
41859
41860
41861
41862
41863 public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
41864 {
41865 return $this->get($originUrl, $fileUrl, $options, null, $progress);
41866 }
41867
41868
41869
41870
41871
41872
41873 public function getOptions()
41874 {
41875 return $this->options;
41876 }
41877
41878
41879
41880
41881
41882
41883 public function setOptions(array $options)
41884 {
41885 $this->options = array_replace_recursive($this->options, $options);
41886 }
41887
41888 public function isTlsDisabled()
41889 {
41890 return $this->disableTls === true;
41891 }
41892
41893
41894
41895
41896
41897
41898 public function getLastHeaders()
41899 {
41900 return $this->lastHeaders;
41901 }
41902
41903
41904
41905
41906
41907
41908 public function findHeaderValue(array $headers, $name)
41909 {
41910 $value = null;
41911 foreach ($headers as $header) {
41912 if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
41913 $value = $match[1];
41914 } elseif (preg_match('{^HTTP/}i', $header)) {
41915
41916  
41917  $value = null;
41918 }
41919 }
41920
41921 return $value;
41922 }
41923
41924
41925
41926
41927
41928 public function findStatusCode(array $headers)
41929 {
41930 $value = null;
41931 foreach ($headers as $header) {
41932 if (preg_match('{^HTTP/\S+ (\d+)}i', $header, $match)) {
41933
41934  
41935  $value = (int) $match[1];
41936 }
41937 }
41938
41939 return $value;
41940 }
41941
41942
41943
41944
41945
41946
41947
41948
41949
41950
41951
41952
41953
41954
41955
41956 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
41957 {
41958 if (strpos($originUrl, '.github.com') === (strlen($originUrl) - 11)) {
41959 $originUrl = 'github.com';
41960 }
41961
41962 $this->scheme = parse_url($fileUrl, PHP_URL_SCHEME);
41963 $this->bytesMax = 0;
41964 $this->originUrl = $originUrl;
41965 $this->fileUrl = $fileUrl;
41966 $this->fileName = $fileName;
41967 $this->progress = $progress;
41968 $this->lastProgress = null;
41969 $this->retryAuthFailure = true;
41970 $this->lastHeaders = array();
41971 $this->redirects = 1; 
41972
41973
41974  if (preg_match('{^https?://(.+):(.+)@([^/]+)}i', $fileUrl, $match)) {
41975 $this->io->setAuthentication($originUrl, urldecode($match[1]), urldecode($match[2]));
41976 }
41977
41978 $tempAdditionalOptions = $additionalOptions;
41979 if (isset($tempAdditionalOptions['retry-auth-failure'])) {
41980 $this->retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure'];
41981
41982 unset($tempAdditionalOptions['retry-auth-failure']);
41983 }
41984
41985 $isRedirect = false;
41986 if (isset($tempAdditionalOptions['redirects'])) {
41987 $this->redirects = $tempAdditionalOptions['redirects'];
41988 $isRedirect = true;
41989
41990 unset($tempAdditionalOptions['redirects']);
41991 }
41992
41993 $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions);
41994 unset($tempAdditionalOptions);
41995 $userlandFollow = isset($options['http']['follow_location']) && !$options['http']['follow_location'];
41996
41997 $origFileUrl = $fileUrl;
41998
41999 if (isset($options['github-token'])) {
42000
42001  if (preg_match('{^https?://([a-z0-9-]+\.)*github\.com/}', $fileUrl)) {
42002 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['github-token'];
42003 }
42004 unset($options['github-token']);
42005 }
42006
42007 if (isset($options['gitlab-token'])) {
42008 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['gitlab-token'];
42009 unset($options['gitlab-token']);
42010 }
42011
42012 if (isset($options['http'])) {
42013 $options['http']['ignore_errors'] = true;
42014 }
42015
42016 if ($this->degradedMode && substr($fileUrl, 0, 21) === 'http://packagist.org/') {
42017
42018  $fileUrl = 'http://' . gethostbyname('packagist.org') . substr($fileUrl, 20);
42019 $degradedPackagist = true;
42020 }
42021
42022 $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
42023
42024 $actualContextOptions = stream_context_get_options($ctx);
42025 $usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : '';
42026 $this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $origFileUrl . $usingProxy, true, IOInterface::DEBUG);
42027 unset($origFileUrl, $actualContextOptions);
42028
42029
42030  if ((substr($fileUrl, 0, 23) !== 'http://packagist.org/p/' || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist) && $this->config) {
42031 $this->config->prohibitUrlByConfig($fileUrl, $this->io);
42032 }
42033
42034 if ($this->progress && !$isRedirect) {
42035 $this->io->writeError("Downloading (<comment>connecting...</comment>)", false);
42036 }
42037
42038 $errorMessage = '';
42039 $errorCode = 0;
42040 $result = false;
42041 set_error_handler(function ($code, $msg) use (&$errorMessage) {
42042 if ($errorMessage) {
42043 $errorMessage .= "\n";
42044 }
42045 $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg);
42046 });
42047 try {
42048 $result = file_get_contents($fileUrl, false, $ctx);
42049
42050 $contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
42051 if ($contentLength && Platform::strlen($result) < $contentLength) {
42052
42053  $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength);
42054 $e->setHeaders($http_response_header);
42055 $e->setStatusCode($this->findStatusCode($http_response_header));
42056 $e->setResponse($result);
42057 $this->io->writeError('Content-Length mismatch, received '.Platform::strlen($result).' out of '.$contentLength.' bytes: (' . base64_encode($result).')', true, IOInterface::DEBUG);
42058
42059 throw $e;
42060 }
42061
42062 if (PHP_VERSION_ID < 50600 && !empty($options['ssl']['peer_fingerprint'])) {
42063
42064  $params = stream_context_get_params($ctx);
42065 $expectedPeerFingerprint = $options['ssl']['peer_fingerprint'];
42066 $peerFingerprint = TlsHelper::getCertificateFingerprint($params['options']['ssl']['peer_certificate']);
42067
42068
42069  if ($expectedPeerFingerprint !== $peerFingerprint) {
42070 throw new TransportException('Peer fingerprint did not match');
42071 }
42072 }
42073 } catch (\Exception $e) {
42074 if ($e instanceof TransportException && !empty($http_response_header[0])) {
42075 $e->setHeaders($http_response_header);
42076 $e->setStatusCode($this->findStatusCode($http_response_header));
42077 }
42078 if ($e instanceof TransportException && $result !== false) {
42079 $e->setResponse($result);
42080 }
42081 $result = false;
42082 }
42083 if ($errorMessage && !ini_get('allow_url_fopen')) {
42084 $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
42085 }
42086 restore_error_handler();
42087 if (isset($e) && !$this->retry) {
42088 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
42089 $this->degradedMode = true;
42090 $this->io->writeError('');
42091 $this->io->writeError(array(
42092 '<error>'.$e->getMessage().'</error>',
42093 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42094 ));
42095
42096 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42097 }
42098
42099 throw $e;
42100 }
42101
42102 $statusCode = null;
42103 $contentType = null;
42104 if (!empty($http_response_header[0])) {
42105 $statusCode = $this->findStatusCode($http_response_header);
42106 $contentType = $this->findHeaderValue($http_response_header, 'content-type');
42107 }
42108
42109
42110  if ($originUrl === 'bitbucket.org'
42111 && !$this->isPublicBitBucketDownload($fileUrl)
42112 && substr($fileUrl, -4) === '.zip'
42113 && $contentType && preg_match('{^text/html\b}i', $contentType)
42114 ) {
42115 $result = false;
42116 if ($this->retryAuthFailure) {
42117 $this->promptAuthAndRetry(401);
42118 }
42119 }
42120
42121
42122  $hasFollowedRedirect = false;
42123 if ($userlandFollow && $statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
42124 $hasFollowedRedirect = true;
42125 $result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
42126 }
42127
42128
42129  if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
42130 if (!$this->retry) {
42131 if ($this->progress && !$this->retry && !$isRedirect) {
42132 $this->io->overwriteError("Downloading (<error>failed</error>)", false);
42133 }
42134
42135 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $statusCode);
42136 $e->setHeaders($http_response_header);
42137 $e->setResponse($result);
42138 $e->setStatusCode($statusCode);
42139 throw $e;
42140 }
42141 $result = false;
42142 }
42143
42144 if ($this->progress && !$this->retry && !$isRedirect) {
42145 $this->io->overwriteError("Downloading (".($result === false ? '<error>failed</error>' : '<comment>100%</comment>').")", false);
42146 }
42147
42148
42149  if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) {
42150 $contentEncoding = $this->findHeaderValue($http_response_header, 'content-encoding');
42151 $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
42152
42153 if ($decode) {
42154 try {
42155 if (PHP_VERSION_ID >= 50400) {
42156 $result = zlib_decode($result);
42157 } else {
42158
42159  $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
42160 }
42161
42162 if (!$result) {
42163 throw new TransportException('Failed to decode zlib stream');
42164 }
42165 } catch (\Exception $e) {
42166 if ($this->degradedMode) {
42167 throw $e;
42168 }
42169
42170 $this->degradedMode = true;
42171 $this->io->writeError(array(
42172 '',
42173 '<error>Failed to decode response: '.$e->getMessage().'</error>',
42174 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42175 ));
42176
42177 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42178 }
42179 }
42180 }
42181
42182
42183  if (false !== $result && null !== $fileName && !$isRedirect) {
42184 if ('' === $result) {
42185 throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
42186 }
42187
42188 $errorMessage = '';
42189 set_error_handler(function ($code, $msg) use (&$errorMessage) {
42190 if ($errorMessage) {
42191 $errorMessage .= "\n";
42192 }
42193 $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg);
42194 });
42195 $result = (bool) file_put_contents($fileName, $result);
42196 restore_error_handler();
42197 if (false === $result) {
42198 throw new TransportException('The "'.$this->fileUrl.'" file could not be written to '.$fileName.': '.$errorMessage);
42199 }
42200 }
42201
42202
42203  if (false === $result && false !== strpos($errorMessage, 'Peer certificate') && PHP_VERSION_ID < 50600) {
42204
42205  
42206  
42207  
42208  
42209  
42210  
42211  
42212  
42213  
42214  
42215  
42216  
42217  
42218  
42219  
42220  if (CaBundle::isOpensslParseSafe()) {
42221 $certDetails = $this->getCertificateCnAndFp($this->fileUrl, $options);
42222
42223 if ($certDetails) {
42224 $this->peerCertificateMap[$this->getUrlAuthority($this->fileUrl)] = $certDetails;
42225
42226 $this->retry = true;
42227 }
42228 } else {
42229 $this->io->writeError('');
42230 $this->io->writeError(sprintf(
42231 '<error>Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.</error>',
42232 PHP_VERSION
42233 ));
42234 }
42235 }
42236
42237 if ($this->retry) {
42238 $this->retry = false;
42239
42240 $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42241
42242 if ($this->storeAuth && $this->config) {
42243 $authHelper = new AuthHelper($this->io, $this->config);
42244 $authHelper->storeAuth($this->originUrl, $this->storeAuth);
42245 $this->storeAuth = false;
42246 }
42247
42248 return $result;
42249 }
42250
42251 if (false === $result) {
42252 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded: '.$errorMessage, $errorCode);
42253 if (!empty($http_response_header[0])) {
42254 $e->setHeaders($http_response_header);
42255 }
42256
42257 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
42258 $this->degradedMode = true;
42259 $this->io->writeError('');
42260 $this->io->writeError(array(
42261 '<error>'.$e->getMessage().'</error>',
42262 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42263 ));
42264
42265 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42266 }
42267
42268 throw $e;
42269 }
42270
42271 if (!empty($http_response_header[0])) {
42272 $this->lastHeaders = $http_response_header;
42273 }
42274
42275 return $result;
42276 }
42277
42278
42279
42280
42281
42282
42283
42284
42285
42286
42287
42288
42289 protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
42290 {
42291 switch ($notificationCode) {
42292 case STREAM_NOTIFY_FAILURE:
42293 if (400 === $messageCode) {
42294
42295  
42296  throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
42297 }
42298
42299  
42300
42301 case STREAM_NOTIFY_AUTH_REQUIRED:
42302 if (401 === $messageCode) {
42303
42304  if (!$this->retryAuthFailure) {
42305 break;
42306 }
42307
42308 $this->promptAuthAndRetry($messageCode);
42309 }
42310 break;
42311
42312 case STREAM_NOTIFY_AUTH_RESULT:
42313 if (403 === $messageCode) {
42314
42315  if (!$this->retryAuthFailure) {
42316 break;
42317 }
42318
42319 $this->promptAuthAndRetry($messageCode, $message);
42320 }
42321 break;
42322
42323 case STREAM_NOTIFY_FILE_SIZE_IS:
42324 $this->bytesMax = $bytesMax;
42325 break;
42326
42327 case STREAM_NOTIFY_PROGRESS:
42328 if ($this->bytesMax > 0 && $this->progress) {
42329 $progression = min(100, round($bytesTransferred / $this->bytesMax * 100));
42330
42331 if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) {
42332 $this->lastProgress = $progression;
42333 $this->io->overwriteError("Downloading (<comment>$progression%</comment>)", false);
42334 }
42335 }
42336 break;
42337
42338 default:
42339 break;
42340 }
42341 }
42342
42343 protected function promptAuthAndRetry($httpStatus, $reason = null)
42344 {
42345 if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
42346 $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');
42347 $gitHubUtil = new GitHub($this->io, $this->config, null);
42348 if (!$gitHubUtil->authorizeOAuth($this->originUrl)
42349 && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($this->originUrl, $message))
42350 ) {
42351 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
42352 }
42353 } elseif ($this->config && in_array($this->originUrl, $this->config->get('gitlab-domains'), true)) {
42354 $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');
42355 $gitLabUtil = new GitLab($this->io, $this->config, null);
42356
42357 if ($this->io->hasAuthentication($this->originUrl) && ($auth = $this->io->getAuthentication($this->originUrl)) && $auth['password'] === 'private-token') {
42358 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
42359 }
42360
42361 if (!$gitLabUtil->authorizeOAuth($this->originUrl)
42362 && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, $message))
42363 ) {
42364 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
42365 }
42366 } elseif ($this->config && $this->originUrl === 'bitbucket.org') {
42367 $askForOAuthToken = true;
42368 if ($this->io->hasAuthentication($this->originUrl)) {
42369 $auth = $this->io->getAuthentication($this->originUrl);
42370 if ($auth['username'] !== 'x-token-auth') {
42371 $bitbucketUtil = new Bitbucket($this->io, $this->config);
42372 $accessToken = $bitbucketUtil->requestToken($this->originUrl, $auth['username'], $auth['password']);
42373 if (!empty($accessToken)) {
42374 $this->io->setAuthentication($this->originUrl, 'x-token-auth', $accessToken);
42375 $askForOAuthToken = false;
42376 }
42377 } else {
42378 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
42379 }
42380 }
42381
42382 if ($askForOAuthToken) {
42383 $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');
42384 $bitBucketUtil = new Bitbucket($this->io, $this->config);
42385 if (! $bitBucketUtil->authorizeOAuth($this->originUrl)
42386 && (! $this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($this->originUrl, $message))
42387 ) {
42388 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
42389 }
42390 }
42391 } else {
42392
42393  if ($httpStatus === 404) {
42394 return;
42395 }
42396
42397
42398  if (!$this->io->isInteractive()) {
42399 if ($httpStatus === 401) {
42400 $message = "The '" . $this->fileUrl . "' URL required authentication.\nYou must be using the interactive console to authenticate";
42401 }
42402 if ($httpStatus === 403) {
42403 $message = "The '" . $this->fileUrl . "' URL could not be accessed: " . $reason;
42404 }
42405
42406 throw new TransportException($message, $httpStatus);
42407 }
42408
42409  if ($this->io->hasAuthentication($this->originUrl)) {
42410 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
42411 }
42412
42413 $this->io->overwriteError('');
42414 $this->io->writeError('    Authentication required (<info>'.parse_url($this->fileUrl, PHP_URL_HOST).'</info>):');
42415 $username = $this->io->ask('      Username: ');
42416 $password = $this->io->askAndHideAnswer('      Password: ');
42417 $this->io->setAuthentication($this->originUrl, $username, $password);
42418 $this->storeAuth = $this->config->get('store-auths');
42419 }
42420
42421 $this->retry = true;
42422 throw new TransportException('RETRY');
42423 }
42424
42425 protected function getOptionsForUrl($originUrl, $additionalOptions)
42426 {
42427 $tlsOptions = array();
42428
42429
42430  if ($this->disableTls === false && PHP_VERSION_ID < 50600 && !stream_is_local($this->fileUrl)) {
42431 $host = parse_url($this->fileUrl, PHP_URL_HOST);
42432
42433 if (PHP_VERSION_ID >= 50304) {
42434
42435  
42436  $userlandFollow = true;
42437 } else {
42438
42439  
42440  
42441  
42442
42443 if ($host === 'github.com' || $host === 'api.github.com') {
42444 $host = '*.github.com';
42445 }
42446 }
42447
42448 $tlsOptions['ssl']['CN_match'] = $host;
42449 $tlsOptions['ssl']['SNI_server_name'] = $host;
42450
42451 $urlAuthority = $this->getUrlAuthority($this->fileUrl);
42452
42453 if (isset($this->peerCertificateMap[$urlAuthority])) {
42454
42455  $certMap = $this->peerCertificateMap[$urlAuthority];
42456
42457 $this->io->writeError('', true, IOInterface::DEBUG);
42458 $this->io->writeError(sprintf(
42459 'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
42460 $certMap['cn'],
42461 $urlAuthority
42462 ), true, IOInterface::DEBUG);
42463
42464 $tlsOptions['ssl']['CN_match'] = $certMap['cn'];
42465 $tlsOptions['ssl']['peer_fingerprint'] = $certMap['fp'];
42466 }
42467 }
42468
42469 $headers = array();
42470
42471 if (extension_loaded('zlib')) {
42472 $headers[] = 'Accept-Encoding: gzip';
42473 }
42474
42475 $options = array_replace_recursive($this->options, $tlsOptions, $additionalOptions);
42476 if (!$this->degradedMode) {
42477
42478  
42479  $options['http']['protocol_version'] = 1.1;
42480 $headers[] = 'Connection: close';
42481 }
42482
42483 if (isset($userlandFollow)) {
42484 $options['http']['follow_location'] = 0;
42485 }
42486
42487 if ($this->io->hasAuthentication($originUrl)) {
42488 $auth = $this->io->getAuthentication($originUrl);
42489 if ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
42490 $options['github-token'] = $auth['username'];
42491 } elseif ($this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
42492 if ($auth['password'] === 'oauth2') {
42493 $headers[] = 'Authorization: Bearer '.$auth['username'];
42494 } elseif ($auth['password'] === 'private-token') {
42495 $headers[] = 'PRIVATE-TOKEN: '.$auth['username'];
42496 }
42497 } elseif ('bitbucket.org' === $originUrl
42498 && $this->fileUrl !== Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']
42499 ) {
42500 if (!$this->isPublicBitBucketDownload($this->fileUrl)) {
42501 $headers[] = 'Authorization: Bearer ' . $auth['password'];
42502 }
42503 } else {
42504 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
42505 $headers[] = 'Authorization: Basic '.$authStr;
42506 }
42507 }
42508
42509 if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
42510 $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
42511 }
42512 foreach ($headers as $header) {
42513 $options['http']['header'][] = $header;
42514 }
42515
42516 return $options;
42517 }
42518
42519 private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
42520 {
42521 if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
42522 if (parse_url($locationHeader, PHP_URL_SCHEME)) {
42523
42524  $targetUrl = $locationHeader;
42525 } elseif (parse_url($locationHeader, PHP_URL_HOST)) {
42526
42527  $targetUrl = $this->scheme.':'.$locationHeader;
42528 } elseif ('/' === $locationHeader[0]) {
42529
42530  $urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
42531
42532
42533  $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
42534 } else {
42535
42536  
42537  $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
42538 }
42539 }
42540
42541 if (!empty($targetUrl)) {
42542 $this->redirects++;
42543
42544 $this->io->writeError('', true, IOInterface::DEBUG);
42545 $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $targetUrl), true, IOInterface::DEBUG);
42546
42547 $additionalOptions['redirects'] = $this->redirects;
42548
42549 return $this->get($this->originUrl, $targetUrl, $additionalOptions, $this->fileName, $this->progress);
42550 }
42551
42552 if (!$this->retry) {
42553 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
42554 $e->setHeaders($http_response_header);
42555 $e->setResponse($result);
42556
42557 throw $e;
42558 }
42559
42560 return false;
42561 }
42562
42563
42564
42565
42566
42567
42568 private function getTlsDefaults(array $options)
42569 {
42570 $ciphers = implode(':', array(
42571 'ECDHE-RSA-AES128-GCM-SHA256',
42572 'ECDHE-ECDSA-AES128-GCM-SHA256',
42573 'ECDHE-RSA-AES256-GCM-SHA384',
42574 'ECDHE-ECDSA-AES256-GCM-SHA384',
42575 'DHE-RSA-AES128-GCM-SHA256',
42576 'DHE-DSS-AES128-GCM-SHA256',
42577 'kEDH+AESGCM',
42578 'ECDHE-RSA-AES128-SHA256',
42579 'ECDHE-ECDSA-AES128-SHA256',
42580 'ECDHE-RSA-AES128-SHA',
42581 'ECDHE-ECDSA-AES128-SHA',
42582 'ECDHE-RSA-AES256-SHA384',
42583 'ECDHE-ECDSA-AES256-SHA384',
42584 'ECDHE-RSA-AES256-SHA',
42585 'ECDHE-ECDSA-AES256-SHA',
42586 'DHE-RSA-AES128-SHA256',
42587 'DHE-RSA-AES128-SHA',
42588 'DHE-DSS-AES128-SHA256',
42589 'DHE-RSA-AES256-SHA256',
42590 'DHE-DSS-AES256-SHA',
42591 'DHE-RSA-AES256-SHA',
42592 'AES128-GCM-SHA256',
42593 'AES256-GCM-SHA384',
42594 'AES128-SHA256',
42595 'AES256-SHA256',
42596 'AES128-SHA',
42597 'AES256-SHA',
42598 'AES',
42599 'CAMELLIA',
42600 'DES-CBC3-SHA',
42601 '!aNULL',
42602 '!eNULL',
42603 '!EXPORT',
42604 '!DES',
42605 '!RC4',
42606 '!MD5',
42607 '!PSK',
42608 '!aECDH',
42609 '!EDH-DSS-DES-CBC3-SHA',
42610 '!EDH-RSA-DES-CBC3-SHA',
42611 '!KRB5-DES-CBC3-SHA',
42612 ));
42613
42614
42615
42616
42617
42618
42619
42620 $defaults = array(
42621 'ssl' => array(
42622 'ciphers' => $ciphers,
42623 'verify_peer' => true,
42624 'verify_depth' => 7,
42625 'SNI_enabled' => true,
42626 'capture_peer_cert' => true,
42627 ),
42628 );
42629
42630 if (isset($options['ssl'])) {
42631 $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
42632 }
42633
42634 $caBundleLogger = $this->io instanceof LoggerInterface ? $this->io : null;
42635
42636
42637
42638
42639
42640 if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
42641 $result = CaBundle::getSystemCaRootBundlePath($caBundleLogger);
42642
42643 if (preg_match('{^phar://}', $result)) {
42644 $hash = hash_file('sha256', $result);
42645 $targetPath = rtrim(sys_get_temp_dir(), '\\/') . '/composer-cacert-' . $hash . '.pem';
42646
42647 if (!file_exists($targetPath) || $hash !== hash_file('sha256', $targetPath)) {
42648 $this->streamCopy($result, $targetPath);
42649 chmod($targetPath, 0666);
42650 }
42651
42652 $defaults['ssl']['cafile'] = $targetPath;
42653 } elseif (is_dir($result)) {
42654 $defaults['ssl']['capath'] = $result;
42655 } else {
42656 $defaults['ssl']['cafile'] = $result;
42657 }
42658 }
42659
42660 if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $caBundleLogger))) {
42661 throw new TransportException('The configured cafile was not valid or could not be read.');
42662 }
42663
42664 if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !is_readable($defaults['ssl']['capath']))) {
42665 throw new TransportException('The configured capath was not valid or could not be read.');
42666 }
42667
42668
42669
42670
42671 if (PHP_VERSION_ID >= 50413) {
42672 $defaults['ssl']['disable_compression'] = true;
42673 }
42674
42675 return $defaults;
42676 }
42677
42678
42679
42680
42681
42682
42683
42684 private function streamCopy($source, $target)
42685 {
42686 $source = fopen($source, 'r');
42687 $target = fopen($target, 'w+');
42688
42689 stream_copy_to_stream($source, $target);
42690 fclose($source);
42691 fclose($target);
42692
42693 unset($source, $target);
42694 }
42695
42696
42697
42698
42699
42700
42701 private function getCertificateCnAndFp($url, $options)
42702 {
42703 if (PHP_VERSION_ID >= 50600) {
42704 throw new \BadMethodCallException(sprintf(
42705 '%s must not be used on PHP >= 5.6',
42706 __METHOD__
42707 ));
42708 }
42709
42710 $context = StreamContextFactory::getContext($url, $options, array('options' => array(
42711 'ssl' => array(
42712 'capture_peer_cert' => true,
42713 'verify_peer' => false, 
42714  ), ),
42715 ));
42716
42717
42718  
42719  if (false === $handle = @fopen($url, 'rb', false, $context)) {
42720 return;
42721 }
42722
42723
42724  fclose($handle);
42725 $handle = null;
42726
42727 $params = stream_context_get_params($context);
42728
42729 if (!empty($params['options']['ssl']['peer_certificate'])) {
42730 $peerCertificate = $params['options']['ssl']['peer_certificate'];
42731
42732 if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) {
42733 return array(
42734 'cn' => $commonName,
42735 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate),
42736 );
42737 }
42738 }
42739 }
42740
42741 private function getUrlAuthority($url)
42742 {
42743 $defaultPorts = array(
42744 'ftp' => 21,
42745 'http' => 80,
42746 'https' => 443,
42747 'ssh2.sftp' => 22,
42748 'ssh2.scp' => 22,
42749 );
42750
42751 $scheme = parse_url($url, PHP_URL_SCHEME);
42752
42753 if (!isset($defaultPorts[$scheme])) {
42754 throw new \InvalidArgumentException(sprintf(
42755 'Could not get default port for unknown scheme: %s',
42756 $scheme
42757 ));
42758 }
42759
42760 $defaultPort = $defaultPorts[$scheme];
42761 $port = parse_url($url, PHP_URL_PORT) ?: $defaultPort;
42762
42763 return parse_url($url, PHP_URL_HOST).':'.$port;
42764 }
42765
42766
42767
42768
42769
42770
42771
42772
42773 private function isPublicBitBucketDownload($urlToBitBucketFile)
42774 {
42775 $domain = parse_url($urlToBitBucketFile, PHP_URL_HOST);
42776 if (strpos($domain, 'bitbucket.org') === false) {
42777
42778  
42779  return true;
42780 }
42781
42782 $path = parse_url($urlToBitBucketFile, PHP_URL_PATH);
42783
42784
42785  
42786  $pathParts = explode('/', $path);
42787 if (count($pathParts) >= 4 && $pathParts[3] == 'downloads') {
42788 return true;
42789 }
42790
42791 return false;
42792 }
42793 }
42794 <?php
42795
42796
42797
42798
42799
42800
42801
42802
42803
42804
42805
42806 namespace Composer\Util;
42807
42808
42809
42810
42811
42812
42813 class Silencer
42814 {
42815
42816
42817
42818 private static $stack = array();
42819
42820
42821
42822
42823
42824
42825
42826 public static function suppress($mask = null)
42827 {
42828 if (!isset($mask)) {
42829 $mask = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT;
42830 }
42831 $old = error_reporting();
42832 array_push(self::$stack, $old);
42833 error_reporting($old & ~$mask);
42834
42835 return $old;
42836 }
42837
42838
42839
42840
42841 public static function restore()
42842 {
42843 if (!empty(self::$stack)) {
42844 error_reporting(array_pop(self::$stack));
42845 }
42846 }
42847
42848
42849
42850
42851
42852
42853
42854
42855
42856
42857 public static function call($callable )
42858 {
42859 try {
42860 self::suppress();
42861 $result = call_user_func_array($callable, array_slice(func_get_args(), 1));
42862 self::restore();
42863
42864 return $result;
42865 } catch (\Exception $e) {
42866
42867  self::restore();
42868 throw $e;
42869 }
42870 }
42871 }
42872 <?php
42873
42874
42875
42876
42877
42878
42879
42880
42881
42882
42883
42884 namespace Composer\Util;
42885
42886 use Composer\Spdx\SpdxLicenses;
42887
42888 trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED);
42889
42890
42891
42892
42893 class SpdxLicense extends SpdxLicenses
42894 {
42895 }
42896 <?php
42897
42898
42899
42900
42901
42902
42903
42904
42905
42906
42907
42908 namespace Composer\Util;
42909
42910 use Composer\Composer;
42911
42912
42913
42914
42915
42916
42917
42918 final class StreamContextFactory
42919 {
42920
42921
42922
42923
42924
42925
42926
42927
42928
42929 public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
42930 {
42931 $options = array('http' => array(
42932
42933  'follow_location' => 1,
42934 'max_redirects' => 20,
42935 ));
42936
42937
42938  if (PHP_SAPI === 'cli' && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) {
42939 $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
42940 }
42941
42942
42943  if (!empty($_SERVER['CGI_HTTP_PROXY'])) {
42944 $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']);
42945 }
42946
42947
42948  if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
42949 $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
42950 }
42951
42952
42953  if (!empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
42954 $pattern = new NoProxyPattern($_SERVER['no_proxy']);
42955 if ($pattern->test($url)) {
42956 unset($proxy);
42957 }
42958 }
42959
42960 if (!empty($proxy)) {
42961 $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
42962 $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
42963
42964 if (isset($proxy['port'])) {
42965 $proxyURL .= ":" . $proxy['port'];
42966 } elseif ('http://' == substr($proxyURL, 0, 7)) {
42967 $proxyURL .= ":80";
42968 } elseif ('https://' == substr($proxyURL, 0, 8)) {
42969 $proxyURL .= ":443";
42970 }
42971
42972
42973  $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
42974
42975 if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) {
42976 throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
42977 }
42978
42979 $options['http']['proxy'] = $proxyURL;
42980
42981
42982  switch (parse_url($url, PHP_URL_SCHEME)) {
42983 case 'http': 
42984  $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
42985 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
42986 $options['http']['request_fulluri'] = true;
42987 }
42988 break;
42989 case 'https': 
42990  $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
42991 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
42992 $options['http']['request_fulluri'] = true;
42993 }
42994 break;
42995 }
42996
42997
42998  if ('https' === parse_url($url, PHP_URL_SCHEME)) {
42999 $options['ssl']['SNI_enabled'] = true;
43000 if (PHP_VERSION_ID < 50600) {
43001 $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST);
43002 }
43003 }
43004
43005
43006  if (isset($proxy['user'])) {
43007 $auth = urldecode($proxy['user']);
43008 if (isset($proxy['pass'])) {
43009 $auth .= ':' . urldecode($proxy['pass']);
43010 }
43011 $auth = base64_encode($auth);
43012
43013
43014  if (isset($defaultOptions['http']['header'])) {
43015 if (is_string($defaultOptions['http']['header'])) {
43016 $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
43017 }
43018 $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
43019 } else {
43020 $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
43021 }
43022 }
43023 }
43024
43025 $options = array_replace_recursive($options, $defaultOptions);
43026
43027 if (isset($options['http']['header'])) {
43028 $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
43029 }
43030
43031 if (defined('HHVM_VERSION')) {
43032 $phpVersion = 'HHVM ' . HHVM_VERSION;
43033 } else {
43034 $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
43035 }
43036
43037 if (!isset($options['http']['header']) || false === strpos(strtolower(implode('', $options['http']['header'])), 'user-agent')) {
43038 $options['http']['header'][] = sprintf(
43039 'User-Agent: Composer/%s (%s; %s; %s%s)',
43040 Composer::VERSION === '@package_version@' ? 'source' : Composer::VERSION,
43041 function_exists('php_uname') ? php_uname('s') : 'Unknown',
43042 function_exists('php_uname') ? php_uname('r') : 'Unknown',
43043 $phpVersion,
43044 getenv('CI') ? '; CI' : ''
43045 );
43046 }
43047
43048 return stream_context_create($options, $defaultParams);
43049 }
43050
43051
43052
43053
43054
43055
43056
43057
43058
43059
43060
43061 private static function fixHttpHeaderField($header)
43062 {
43063 if (!is_array($header)) {
43064 $header = explode("\r\n", $header);
43065 }
43066 uasort($header, function ($el) {
43067 return preg_match('{^content-type}i', $el) ? 1 : -1;
43068 });
43069
43070 return $header;
43071 }
43072 }
43073 <?php
43074
43075
43076
43077
43078
43079
43080
43081
43082
43083
43084
43085 namespace Composer\Util;
43086
43087 use Composer\Config;
43088 use Composer\IO\IOInterface;
43089
43090
43091
43092
43093
43094 class Svn
43095 {
43096 const MAX_QTY_AUTH_TRIES = 5;
43097
43098
43099
43100
43101 protected $credentials;
43102
43103
43104
43105
43106 protected $hasAuth;
43107
43108
43109
43110
43111 protected $io;
43112
43113
43114
43115
43116 protected $url;
43117
43118
43119
43120
43121 protected $cacheCredentials = true;
43122
43123
43124
43125
43126 protected $process;
43127
43128
43129
43130
43131 protected $qtyAuthTries = 0;
43132
43133
43134
43135
43136 protected $config;
43137
43138
43139
43140
43141
43142
43143
43144 public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null)
43145 {
43146 $this->url = $url;
43147 $this->io = $io;
43148 $this->config = $config;
43149 $this->process = $process ?: new ProcessExecutor;
43150 }
43151
43152 public static function cleanEnv()
43153 {
43154
43155  putenv("DYLD_LIBRARY_PATH");
43156 unset($_SERVER['DYLD_LIBRARY_PATH']);
43157 }
43158
43159
43160
43161
43162
43163
43164
43165
43166
43167
43168
43169
43170
43171
43172 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
43173 {
43174
43175  $this->config->prohibitUrlByConfig($url, $this->io);
43176
43177 $svnCommand = $this->getCommand($command, $url, $path);
43178 $output = null;
43179 $io = $this->io;
43180 $handler = function ($type, $buffer) use (&$output, $io, $verbose) {
43181 if ($type !== 'out') {
43182 return;
43183 }
43184 if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
43185 return;
43186 }
43187 $output .= $buffer;
43188 if ($verbose) {
43189 $io->writeError($buffer, false);
43190 }
43191 };
43192 $status = $this->process->execute($svnCommand, $handler, $cwd);
43193 if (0 === $status) {
43194 return $output;
43195 }
43196
43197 $errorOutput = $this->process->getErrorOutput();
43198 $fullOutput = implode("\n", array($output, $errorOutput));
43199
43200
43201  if (false === stripos($fullOutput, 'Could not authenticate to server:')
43202 && false === stripos($fullOutput, 'authorization failed')
43203 && false === stripos($fullOutput, 'svn: E170001:')
43204 && false === stripos($fullOutput, 'svn: E215004:')) {
43205 throw new \RuntimeException($fullOutput);
43206 }
43207
43208 if (!$this->hasAuth()) {
43209 $this->doAuthDance();
43210 }
43211
43212
43213  if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
43214
43215  return $this->execute($command, $url, $cwd, $path, $verbose);
43216 }
43217
43218 throw new \RuntimeException(
43219 'wrong credentials provided ('.$fullOutput.')'
43220 );
43221 }
43222
43223
43224
43225
43226 public function setCacheCredentials($cacheCredentials)
43227 {
43228 $this->cacheCredentials = $cacheCredentials;
43229 }
43230
43231
43232
43233
43234
43235
43236
43237 protected function doAuthDance()
43238 {
43239
43240  if (!$this->io->isInteractive()) {
43241 throw new \RuntimeException(
43242 'can not ask for authentication in non interactive mode'
43243 );
43244 }
43245
43246 $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
43247
43248 $this->hasAuth = true;
43249 $this->credentials['username'] = $this->io->ask("Username: ");
43250 $this->credentials['password'] = $this->io->askAndHideAnswer("Password: ");
43251
43252 $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ", true);
43253
43254 return $this;
43255 }
43256
43257
43258
43259
43260
43261
43262
43263
43264
43265
43266 protected function getCommand($cmd, $url, $path = null)
43267 {
43268 $cmd = sprintf('%s %s%s %s',
43269 $cmd,
43270 '--non-interactive ',
43271 $this->getCredentialString(),
43272 ProcessExecutor::escape($url)
43273 );
43274
43275 if ($path) {
43276 $cmd .= ' ' . ProcessExecutor::escape($path);
43277 }
43278
43279 return $cmd;
43280 }
43281
43282
43283
43284
43285
43286
43287
43288
43289 protected function getCredentialString()
43290 {
43291 if (!$this->hasAuth()) {
43292 return '';
43293 }
43294
43295 return sprintf(
43296 ' %s--username %s --password %s ',
43297 $this->getAuthCache(),
43298 ProcessExecutor::escape($this->getUsername()),
43299 ProcessExecutor::escape($this->getPassword())
43300 );
43301 }
43302
43303
43304
43305
43306
43307
43308
43309 protected function getPassword()
43310 {
43311 if ($this->credentials === null) {
43312 throw new \LogicException("No svn auth detected.");
43313 }
43314
43315 return isset($this->credentials['password']) ? $this->credentials['password'] : '';
43316 }
43317
43318
43319
43320
43321
43322
43323
43324 protected function getUsername()
43325 {
43326 if ($this->credentials === null) {
43327 throw new \LogicException("No svn auth detected.");
43328 }
43329
43330 return $this->credentials['username'];
43331 }
43332
43333
43334
43335
43336
43337
43338 protected function hasAuth()
43339 {
43340 if (null !== $this->hasAuth) {
43341 return $this->hasAuth;
43342 }
43343
43344 if (false === $this->createAuthFromConfig()) {
43345 $this->createAuthFromUrl();
43346 }
43347
43348 return $this->hasAuth;
43349 }
43350
43351
43352
43353
43354
43355
43356 protected function getAuthCache()
43357 {
43358 return $this->cacheCredentials ? '' : '--no-auth-cache ';
43359 }
43360
43361
43362
43363
43364
43365
43366 private function createAuthFromConfig()
43367 {
43368 if (!$this->config->has('http-basic')) {
43369 return $this->hasAuth = false;
43370 }
43371
43372 $authConfig = $this->config->get('http-basic');
43373
43374 $host = parse_url($this->url, PHP_URL_HOST);
43375 if (isset($authConfig[$host])) {
43376 $this->credentials['username'] = $authConfig[$host]['username'];
43377 $this->credentials['password'] = $authConfig[$host]['password'];
43378
43379 return $this->hasAuth = true;
43380 }
43381
43382 return $this->hasAuth = false;
43383 }
43384
43385
43386
43387
43388
43389
43390 private function createAuthFromUrl()
43391 {
43392 $uri = parse_url($this->url);
43393 if (empty($uri['user'])) {
43394 return $this->hasAuth = false;
43395 }
43396
43397 $this->credentials['username'] = $uri['user'];
43398 if (!empty($uri['pass'])) {
43399 $this->credentials['password'] = $uri['pass'];
43400 }
43401
43402 return $this->hasAuth = true;
43403 }
43404 }
43405 <?php
43406
43407
43408
43409
43410
43411
43412
43413
43414
43415
43416
43417 namespace Composer\Util;
43418
43419 use Composer\CaBundle\CaBundle;
43420
43421
43422
43423
43424 final class TlsHelper
43425 {
43426 private static $useOpensslParse;
43427
43428
43429
43430
43431
43432
43433
43434
43435
43436
43437 public static function checkCertificateHost($certificate, $hostname, &$cn = null)
43438 {
43439 $names = self::getCertificateNames($certificate);
43440
43441 if (empty($names)) {
43442 return false;
43443 }
43444
43445 $combinedNames = array_merge($names['san'], array($names['cn']));
43446 $hostname = strtolower($hostname);
43447
43448 foreach ($combinedNames as $certName) {
43449 $matcher = self::certNameMatcher($certName);
43450
43451 if ($matcher && $matcher($hostname)) {
43452 $cn = $names['cn'];
43453
43454 return true;
43455 }
43456 }
43457
43458 return false;
43459 }
43460
43461
43462
43463
43464
43465
43466
43467
43468 public static function getCertificateNames($certificate)
43469 {
43470 if (is_array($certificate)) {
43471 $info = $certificate;
43472 } elseif (CaBundle::isOpensslParseSafe()) {
43473 $info = openssl_x509_parse($certificate, false);
43474 }
43475
43476 if (!isset($info['subject']['commonName'])) {
43477 return null;
43478 }
43479
43480 $commonName = strtolower($info['subject']['commonName']);
43481 $subjectAltNames = array();
43482
43483 if (isset($info['extensions']['subjectAltName'])) {
43484 $subjectAltNames = preg_split('{\s*,\s*}', $info['extensions']['subjectAltName']);
43485 $subjectAltNames = array_filter(array_map(function ($name) {
43486 if (0 === strpos($name, 'DNS:')) {
43487 return strtolower(ltrim(substr($name, 4)));
43488 }
43489
43490 return null;
43491 }, $subjectAltNames));
43492 $subjectAltNames = array_values($subjectAltNames);
43493 }
43494
43495 return array(
43496 'cn' => $commonName,
43497 'san' => $subjectAltNames,
43498 );
43499 }
43500
43501
43502
43503
43504
43505
43506
43507
43508
43509
43510
43511
43512
43513
43514
43515
43516
43517
43518
43519
43520
43521
43522
43523
43524
43525
43526
43527
43528
43529
43530
43531
43532
43533
43534
43535
43536
43537
43538
43539
43540 public static function getCertificateFingerprint($certificate)
43541 {
43542 $pubkeydetails = openssl_pkey_get_details(openssl_get_publickey($certificate));
43543 $pubkeypem = $pubkeydetails['key'];
43544
43545  $start = '-----BEGIN PUBLIC KEY-----';
43546 $end = '-----END PUBLIC KEY-----';
43547 $pemtrim = substr($pubkeypem, (strpos($pubkeypem, $start) + strlen($start)), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
43548 $der = base64_decode($pemtrim);
43549
43550 return sha1($der);
43551 }
43552
43553
43554
43555
43556
43557
43558
43559
43560
43561 public static function isOpensslParseSafe()
43562 {
43563 return CaBundle::isOpensslParseSafe();
43564 }
43565
43566
43567
43568
43569
43570
43571
43572
43573 private static function certNameMatcher($certName)
43574 {
43575 $wildcards = substr_count($certName, '*');
43576
43577 if (0 === $wildcards) {
43578
43579  return function ($hostname) use ($certName) {
43580 return $hostname === $certName;
43581 };
43582 }
43583
43584 if (1 === $wildcards) {
43585 $components = explode('.', $certName);
43586
43587 if (3 > count($components)) {
43588
43589  return;
43590 }
43591
43592 $firstComponent = $components[0];
43593
43594
43595  if ('*' !== $firstComponent[strlen($firstComponent) - 1]) {
43596 return;
43597 }
43598
43599 $wildcardRegex = preg_quote($certName);
43600 $wildcardRegex = str_replace('\\*', '[a-z0-9-]+', $wildcardRegex);
43601 $wildcardRegex = "{^{$wildcardRegex}$}";
43602
43603 return function ($hostname) use ($wildcardRegex) {
43604 return 1 === preg_match($wildcardRegex, $hostname);
43605 };
43606 }
43607 }
43608 }
43609 <?php
43610
43611
43612
43613
43614
43615
43616
43617
43618
43619
43620
43621 namespace Composer;
43622
43623 use Composer\Util\IniHelper;
43624 use Symfony\Component\Console\Output\OutputInterface;
43625
43626
43627
43628
43629 class XdebugHandler
43630 {
43631 const ENV_ALLOW = 'COMPOSER_ALLOW_XDEBUG';
43632 const ENV_VERSION = 'COMPOSER_XDEBUG_VERSION';
43633 const RESTART_ID = 'internal';
43634
43635 private $output;
43636 private $loaded;
43637 private $envScanDir;
43638 private $version;
43639 private $tmpIni;
43640
43641
43642
43643
43644 public function __construct(OutputInterface $output)
43645 {
43646 $this->output = $output;
43647 $this->loaded = extension_loaded('xdebug');
43648 $this->envScanDir = getenv('PHP_INI_SCAN_DIR');
43649
43650 if ($this->loaded) {
43651 $ext = new \ReflectionExtension('xdebug');
43652 $this->version = strval($ext->getVersion());
43653 }
43654 }
43655
43656
43657
43658
43659
43660
43661
43662
43663
43664
43665
43666
43667
43668
43669 public function check()
43670 {
43671 $args = explode('|', strval(getenv(self::ENV_ALLOW)), 2);
43672
43673 if ($this->needsRestart($args[0])) {
43674 if ($this->prepareRestart()) {
43675 $command = $this->getCommand();
43676 $this->restart($command);
43677 }
43678
43679 return;
43680 }
43681
43682
43683  if (self::RESTART_ID === $args[0]) {
43684 putenv(self::ENV_ALLOW);
43685
43686 if (false !== $this->envScanDir) {
43687
43688  if (isset($args[1])) {
43689 putenv('PHP_INI_SCAN_DIR='.$args[1]);
43690 } else {
43691 putenv('PHP_INI_SCAN_DIR');
43692 }
43693 }
43694
43695
43696  if ($this->loaded) {
43697 putenv(self::ENV_VERSION);
43698 }
43699 }
43700 }
43701
43702
43703
43704
43705
43706
43707 protected function restart($command)
43708 {
43709 passthru($command, $exitCode);
43710
43711 if (!empty($this->tmpIni)) {
43712 @unlink($this->tmpIni);
43713 }
43714
43715 exit($exitCode);
43716 }
43717
43718
43719
43720
43721
43722
43723
43724
43725 private function needsRestart($allow)
43726 {
43727 if (PHP_SAPI !== 'cli' || !defined('PHP_BINARY')) {
43728 return false;
43729 }
43730
43731 return empty($allow) && $this->loaded;
43732 }
43733
43734
43735
43736
43737
43738
43739
43740
43741
43742
43743
43744 private function prepareRestart()
43745 {
43746 $this->tmpIni = '';
43747 $iniPaths = IniHelper::getAll();
43748 $additional = count($iniPaths) > 1;
43749
43750 if (empty($iniPaths[0])) {
43751
43752  array_shift($iniPaths);
43753 }
43754
43755 if ($this->writeTmpIni($iniPaths)) {
43756 return $this->setEnvironment($additional, $iniPaths);
43757 }
43758
43759 return false;
43760 }
43761
43762
43763
43764
43765
43766
43767
43768
43769
43770
43771 private function writeTmpIni(array $iniFiles)
43772 {
43773 if (!$this->tmpIni = tempnam(sys_get_temp_dir(), '')) {
43774 return false;
43775 }
43776
43777 $content = '';
43778 $regex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
43779
43780 foreach ($iniFiles as $file) {
43781 $data = preg_replace($regex, ';$1', file_get_contents($file));
43782 $content .= $data.PHP_EOL;
43783 }
43784
43785 $content .= 'allow_url_fopen='.ini_get('allow_url_fopen').PHP_EOL;
43786 $content .= 'disable_functions="'.ini_get('disable_functions').'"'.PHP_EOL;
43787 $content .= 'memory_limit='.ini_get('memory_limit').PHP_EOL;
43788
43789 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
43790
43791  $content .= 'opcache.enable_cli=0'.PHP_EOL;
43792 }
43793
43794 return @file_put_contents($this->tmpIni, $content);
43795 }
43796
43797
43798
43799
43800
43801
43802 private function getCommand()
43803 {
43804 $phpArgs = array(PHP_BINARY, '-c', $this->tmpIni);
43805 $params = array_merge($phpArgs, $this->getScriptArgs($_SERVER['argv']));
43806
43807 return implode(' ', array_map(array($this, 'escape'), $params));
43808 }
43809
43810
43811
43812
43813
43814
43815
43816
43817
43818 private function setEnvironment($additional, array $iniPaths)
43819 {
43820
43821  if ($additional && !putenv('PHP_INI_SCAN_DIR=')) {
43822 return false;
43823 }
43824
43825
43826  if (!putenv(IniHelper::ENV_ORIGINAL.'='.implode(PATH_SEPARATOR, $iniPaths))) {
43827 return false;
43828 }
43829
43830
43831  if (!putenv(self::ENV_VERSION.'='.$this->version)) {
43832 return false;
43833 }
43834
43835
43836  $args = array(self::RESTART_ID);
43837
43838 if (false !== $this->envScanDir) {
43839
43840  $args[] = $this->envScanDir;
43841 }
43842
43843 return putenv(self::ENV_ALLOW.'='.implode('|', $args));
43844 }
43845
43846
43847
43848
43849
43850
43851
43852
43853
43854
43855
43856 private function getScriptArgs(array $args)
43857 {
43858 if (in_array('--no-ansi', $args) || in_array('--ansi', $args)) {
43859 return $args;
43860 }
43861
43862 if ($this->output->isDecorated()) {
43863 $offset = count($args) > 1 ? 2 : 1;
43864 array_splice($args, $offset, 0, '--ansi');
43865 }
43866
43867 return $args;
43868 }
43869
43870
43871
43872
43873
43874
43875
43876
43877
43878
43879
43880
43881 private function escape($arg, $meta = true)
43882 {
43883 if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
43884 return escapeshellarg($arg);
43885 }
43886
43887 $quote = strpbrk($arg, " \t") !== false || $arg === '';
43888 $arg = preg_replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes);
43889
43890 if ($meta) {
43891 $meta = $dquotes || preg_match('/%[^%]+%/', $arg);
43892
43893 if (!$meta && !$quote) {
43894 $quote = strpbrk($arg, '^&|<>()') !== false;
43895 }
43896 }
43897
43898 if ($quote) {
43899 $arg = preg_replace('/(\\\\*)$/', '$1$1', $arg);
43900 $arg = '"'.$arg.'"';
43901 }
43902
43903 if ($meta) {
43904 $arg = preg_replace('/(["^&|<>()%])/', '^$1', $arg);
43905 }
43906
43907 return $arg;
43908 }
43909 }
43910 <?php
43911
43912
43913
43914
43915
43916
43917
43918
43919
43920
43921
43922 function includeIfExists($file)
43923 {
43924 return file_exists($file) ? include $file : false;
43925 }
43926
43927 if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
43928 echo 'You must set up the project dependencies using `composer install`'.PHP_EOL.
43929 'See https://getcomposer.org/download/ for instructions on installing Composer'.PHP_EOL;
43930 exit(1);
43931 }
43932
43933 return $loader;
43934 <?php
43935
43936 /*
43937  * This file is part of Composer.
43938  *
43939  * (c) Nils Adermann <naderman@naderman.de>
43940  *     Jordi Boggiano <j.boggiano@seld.be>
43941  *
43942  * For the full copyright and license information, please view the LICENSE
43943  * file that was distributed with this source code.
43944  */
43945
43946 namespace Composer\Autoload;
43947
43948 /**
43949  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
43950  *
43951  *     $loader = new \Composer\Autoload\ClassLoader();
43952  *
43953  *     // register classes with namespaces
43954  *     $loader->add('Symfony\Component', __DIR__.'/component');
43955  *     $loader->add('Symfony',           __DIR__.'/framework');
43956  *
43957  *     // activate the autoloader
43958  *     $loader->register();
43959  *
43960  *     // to enable searching the include path (eg. for PEAR packages)
43961  *     $loader->setUseIncludePath(true);
43962  *
43963  * In this example, if you try to use a class in the Symfony\Component
43964  * namespace or one of its children (Symfony\Component\Console for instance),
43965  * the autoloader will first look for the class under the component/
43966  * directory, and it will then fallback to the framework/ directory if not
43967  * found before giving up.
43968  *
43969  * This class is loosely based on the Symfony UniversalClassLoader.
43970  *
43971  * @author Fabien Potencier <fabien@symfony.com>
43972  * @author Jordi Boggiano <j.boggiano@seld.be>
43973  * @see    http://www.php-fig.org/psr/psr-0/
43974  * @see    http://www.php-fig.org/psr/psr-4/
43975  */
43976 class ClassLoader
43977 {
43978     // PSR-4
43979     private $prefixLengthsPsr4 = array();
43980     private $prefixDirsPsr4 = array();
43981     private $fallbackDirsPsr4 = array();
43982
43983     // PSR-0
43984     private $prefixesPsr0 = array();
43985     private $fallbackDirsPsr0 = array();
43986
43987     private $useIncludePath = false;
43988     private $classMap = array();
43989     private $classMapAuthoritative = false;
43990     private $missingClasses = array();
43991     private $apcuPrefix;
43992
43993     public function getPrefixes()
43994     {
43995         if (!empty($this->prefixesPsr0)) {
43996             return call_user_func_array('array_merge', $this->prefixesPsr0);
43997         }
43998
43999         return array();
44000     }
44001
44002     public function getPrefixesPsr4()
44003     {
44004         return $this->prefixDirsPsr4;
44005     }
44006
44007     public function getFallbackDirs()
44008     {
44009         return $this->fallbackDirsPsr0;
44010     }
44011
44012     public function getFallbackDirsPsr4()
44013     {
44014         return $this->fallbackDirsPsr4;
44015     }
44016
44017     public function getClassMap()
44018     {
44019         return $this->classMap;
44020     }
44021
44022     /**
44023      * @param array $classMap Class to filename map
44024      */
44025     public function addClassMap(array $classMap)
44026     {
44027         if ($this->classMap) {
44028             $this->classMap = array_merge($this->classMap, $classMap);
44029         } else {
44030             $this->classMap = $classMap;
44031         }
44032     }
44033
44034     /**
44035      * Registers a set of PSR-0 directories for a given prefix, either
44036      * appending or prepending to the ones previously set for this prefix.
44037      *
44038      * @param string       $prefix  The prefix
44039      * @param array|string $paths   The PSR-0 root directories
44040      * @param bool         $prepend Whether to prepend the directories
44041      */
44042     public function add($prefix, $paths, $prepend = false)
44043     {
44044         if (!$prefix) {
44045             if ($prepend) {
44046                 $this->fallbackDirsPsr0 = array_merge(
44047                     (array) $paths,
44048                     $this->fallbackDirsPsr0
44049                 );
44050             } else {
44051                 $this->fallbackDirsPsr0 = array_merge(
44052                     $this->fallbackDirsPsr0,
44053                     (array) $paths
44054                 );
44055             }
44056
44057             return;
44058         }
44059
44060         $first = $prefix[0];
44061         if (!isset($this->prefixesPsr0[$first][$prefix])) {
44062             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
44063
44064             return;
44065         }
44066         if ($prepend) {
44067             $this->prefixesPsr0[$first][$prefix] = array_merge(
44068                 (array) $paths,
44069                 $this->prefixesPsr0[$first][$prefix]
44070             );
44071         } else {
44072             $this->prefixesPsr0[$first][$prefix] = array_merge(
44073                 $this->prefixesPsr0[$first][$prefix],
44074                 (array) $paths
44075             );
44076         }
44077     }
44078
44079     /**
44080      * Registers a set of PSR-4 directories for a given namespace, either
44081      * appending or prepending to the ones previously set for this namespace.
44082      *
44083      * @param string       $prefix  The prefix/namespace, with trailing '\\'
44084      * @param array|string $paths   The PSR-4 base directories
44085      * @param bool         $prepend Whether to prepend the directories
44086      *
44087      * @throws \InvalidArgumentException
44088      */
44089     public function addPsr4($prefix, $paths, $prepend = false)
44090     {
44091         if (!$prefix) {
44092             // Register directories for the root namespace.
44093             if ($prepend) {
44094                 $this->fallbackDirsPsr4 = array_merge(
44095                     (array) $paths,
44096                     $this->fallbackDirsPsr4
44097                 );
44098             } else {
44099                 $this->fallbackDirsPsr4 = array_merge(
44100                     $this->fallbackDirsPsr4,
44101                     (array) $paths
44102                 );
44103             }
44104         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
44105             // Register directories for a new namespace.
44106             $length = strlen($prefix);
44107             if ('\\' !== $prefix[$length - 1]) {
44108                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
44109             }
44110             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
44111             $this->prefixDirsPsr4[$prefix] = (array) $paths;
44112         } elseif ($prepend) {
44113             // Prepend directories for an already registered namespace.
44114             $this->prefixDirsPsr4[$prefix] = array_merge(
44115                 (array) $paths,
44116                 $this->prefixDirsPsr4[$prefix]
44117             );
44118         } else {
44119             // Append directories for an already registered namespace.
44120             $this->prefixDirsPsr4[$prefix] = array_merge(
44121                 $this->prefixDirsPsr4[$prefix],
44122                 (array) $paths
44123             );
44124         }
44125     }
44126
44127     /**
44128      * Registers a set of PSR-0 directories for a given prefix,
44129      * replacing any others previously set for this prefix.
44130      *
44131      * @param string       $prefix The prefix
44132      * @param array|string $paths  The PSR-0 base directories
44133      */
44134     public function set($prefix, $paths)
44135     {
44136         if (!$prefix) {
44137             $this->fallbackDirsPsr0 = (array) $paths;
44138         } else {
44139             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
44140         }
44141     }
44142
44143     /**
44144      * Registers a set of PSR-4 directories for a given namespace,
44145      * replacing any others previously set for this namespace.
44146      *
44147      * @param string       $prefix The prefix/namespace, with trailing '\\'
44148      * @param array|string $paths  The PSR-4 base directories
44149      *
44150      * @throws \InvalidArgumentException
44151      */
44152     public function setPsr4($prefix, $paths)
44153     {
44154         if (!$prefix) {
44155             $this->fallbackDirsPsr4 = (array) $paths;
44156         } else {
44157             $length = strlen($prefix);
44158             if ('\\' !== $prefix[$length - 1]) {
44159                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
44160             }
44161             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
44162             $this->prefixDirsPsr4[$prefix] = (array) $paths;
44163         }
44164     }
44165
44166     /**
44167      * Turns on searching the include path for class files.
44168      *
44169      * @param bool $useIncludePath
44170      */
44171     public function setUseIncludePath($useIncludePath)
44172     {
44173         $this->useIncludePath = $useIncludePath;
44174     }
44175
44176     /**
44177      * Can be used to check if the autoloader uses the include path to check
44178      * for classes.
44179      *
44180      * @return bool
44181      */
44182     public function getUseIncludePath()
44183     {
44184         return $this->useIncludePath;
44185     }
44186
44187     /**
44188      * Turns off searching the prefix and fallback directories for classes
44189      * that have not been registered with the class map.
44190      *
44191      * @param bool $classMapAuthoritative
44192      */
44193     public function setClassMapAuthoritative($classMapAuthoritative)
44194     {
44195         $this->classMapAuthoritative = $classMapAuthoritative;
44196     }
44197
44198     /**
44199      * Should class lookup fail if not found in the current class map?
44200      *
44201      * @return bool
44202      */
44203     public function isClassMapAuthoritative()
44204     {
44205         return $this->classMapAuthoritative;
44206     }
44207
44208     /**
44209      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
44210      *
44211      * @param string|null $apcuPrefix
44212      */
44213     public function setApcuPrefix($apcuPrefix)
44214     {
44215         $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
44216     }
44217
44218     /**
44219      * The APCu prefix in use, or null if APCu caching is not enabled.
44220      *
44221      * @return string|null
44222      */
44223     public function getApcuPrefix()
44224     {
44225         return $this->apcuPrefix;
44226     }
44227
44228     /**
44229      * Registers this instance as an autoloader.
44230      *
44231      * @param bool $prepend Whether to prepend the autoloader or not
44232      */
44233     public function register($prepend = false)
44234     {
44235         spl_autoload_register(array($this, 'loadClass'), true, $prepend);
44236     }
44237
44238     /**
44239      * Unregisters this instance as an autoloader.
44240      */
44241     public function unregister()
44242     {
44243         spl_autoload_unregister(array($this, 'loadClass'));
44244     }
44245
44246     /**
44247      * Loads the given class or interface.
44248      *
44249      * @param  string    $class The name of the class
44250      * @return bool|null True if loaded, null otherwise
44251      */
44252     public function loadClass($class)
44253     {
44254         if ($file = $this->findFile($class)) {
44255             includeFile($file);
44256
44257             return true;
44258         }
44259     }
44260
44261     /**
44262      * Finds the path to the file where the class is defined.
44263      *
44264      * @param string $class The name of the class
44265      *
44266      * @return string|false The path if found, false otherwise
44267      */
44268     public function findFile($class)
44269     {
44270         // class map lookup
44271         if (isset($this->classMap[$class])) {
44272             return $this->classMap[$class];
44273         }
44274         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
44275             return false;
44276         }
44277         if (null !== $this->apcuPrefix) {
44278             $file = apcu_fetch($this->apcuPrefix.$class, $hit);
44279             if ($hit) {
44280                 return $file;
44281             }
44282         }
44283
44284         $file = $this->findFileWithExtension($class, '.php');
44285
44286         // Search for Hack files if we are running on HHVM
44287         if (false === $file && defined('HHVM_VERSION')) {
44288             $file = $this->findFileWithExtension($class, '.hh');
44289         }
44290
44291         if (null !== $this->apcuPrefix) {
44292             apcu_add($this->apcuPrefix.$class, $file);
44293         }
44294
44295         if (false === $file) {
44296             // Remember that this class does not exist.
44297             $this->missingClasses[$class] = true;
44298         }
44299
44300         return $file;
44301     }
44302
44303     private function findFileWithExtension($class, $ext)
44304     {
44305         // PSR-4 lookup
44306         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
44307
44308         $first = $class[0];
44309         if (isset($this->prefixLengthsPsr4[$first])) {
44310             $subPath = $class;
44311             while (false !== $lastPos = strrpos($subPath, '\\')) {
44312                 $subPath = substr($subPath, 0, $lastPos);
44313                 $search = $subPath.'\\';
44314                 if (isset($this->prefixDirsPsr4[$search])) {
44315                     foreach ($this->prefixDirsPsr4[$search] as $dir) {
44316                         $length = $this->prefixLengthsPsr4[$first][$search];
44317                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
44318                             return $file;
44319                         }
44320                     }
44321                 }
44322             }
44323         }
44324
44325         // PSR-4 fallback dirs
44326         foreach ($this->fallbackDirsPsr4 as $dir) {
44327             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
44328                 return $file;
44329             }
44330         }
44331
44332         // PSR-0 lookup
44333         if (false !== $pos = strrpos($class, '\\')) {
44334             // namespaced class name
44335             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
44336                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
44337         } else {
44338             // PEAR-like class name
44339             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
44340         }
44341
44342         if (isset($this->prefixesPsr0[$first])) {
44343             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
44344                 if (0 === strpos($class, $prefix)) {
44345                     foreach ($dirs as $dir) {
44346                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
44347                             return $file;
44348                         }
44349                     }
44350                 }
44351             }
44352         }
44353
44354         // PSR-0 fallback dirs
44355         foreach ($this->fallbackDirsPsr0 as $dir) {
44356             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
44357                 return $file;
44358             }
44359         }
44360
44361         // PSR-0 include paths.
44362         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
44363             return $file;
44364         }
44365
44366         return false;
44367     }
44368 }
44369
44370 /**
44371  * Scope isolated include.
44372  *
44373  * Prevents access to $this/self from included files.
44374  */
44375 function includeFile($file)
44376 {
44377     include $file;
44378 }
44379 {
44380     "$schema": "http://json-schema.org/draft-04/schema#",
44381     "description": "A representation of packages metadata.",
44382     "type": "object",
44383     "oneOf": [
44384         { "required": [ "packages" ] },
44385         { "required": [ "providers" ] },
44386         { "required": [ "provider-includes", "providers-url" ] }
44387     ],
44388     "properties": {
44389         "packages": {
44390             "type": ["object", "array"],
44391             "description": "A hashmap of package names in the form of <vendor>/<name>.",
44392             "additionalProperties": { "$ref": "#/definitions/versions" }
44393         },
44394         "providers-url": {
44395             "type": "string",
44396             "description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
44397         },
44398         "provider-includes": {
44399             "type": "object",
44400             "description": "A hashmap of provider listings.",
44401             "additionalProperties": { "$ref": "#/definitions/provider" }
44402         },
44403         "providers": {
44404             "type": "object",
44405             "description": "A hashmap of package names in the form of <vendor>/<name>.",
44406             "additionalProperties": { "$ref": "#/definitions/provider" }
44407         },
44408         "notify-batch": {
44409             "type": "string",
44410             "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
44411         },
44412         "search": {
44413             "type": "string",
44414             "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
44415         },
44416         "warning": {
44417             "type": "string",
44418             "description": "A message that will be output by Composer as a warning when this source is consulted."
44419         }
44420     },
44421     "definitions": {
44422         "versions": {
44423             "type": "object",
44424             "description": "A hashmap of versions and their metadata.",
44425             "additionalProperties": { "$ref": "#/definitions/version" }
44426         },
44427         "version": {
44428             "type": "object",
44429             "oneOf": [
44430                 { "$ref": "#/definitions/package" },
44431                 { "$ref": "#/definitions/metapackage" }
44432             ]
44433         },
44434         "package-base": {
44435             "properties": {
44436                 "name": { "type": "string" },
44437                 "type": { "type": "string" },
44438                 "version": { "type": "string" },
44439                 "version_normalized": {
44440                     "type": "string",
44441                     "description": "Normalized version, optional but can save computational time on client side."
44442                 },
44443                 "autoload": { "type": "object" },
44444                 "require": { "type": "object" },
44445                 "replace": { "type": "object" },
44446                 "conflict": { "type": "object" },
44447                 "provide": { "type": "object" },
44448                 "time": { "type": "string" }
44449             },
44450             "additionalProperties": true
44451         },
44452         "package": {
44453             "allOf": [
44454                 { "$ref": "#/definitions/package-base" },
44455                 {
44456                     "properties": {
44457                         "dist": { "type": "object" },
44458                         "source": { "type": "object" }
44459                     }
44460                 },
44461                 { "oneOf": [
44462                     { "required": [ "name", "version", "source" ] },
44463                     { "required": [ "name", "version", "dist" ] }
44464                 ] }
44465             ]
44466         },
44467         "metapackage": {
44468             "allOf": [
44469                 { "$ref": "#/definitions/package-base" },
44470                 {
44471                     "properties": {
44472                         "type": { "type": "string", "enum": [ "metapackage" ] }
44473                     },
44474                     "required": [ "name", "version", "type" ]
44475                 }
44476             ]
44477         },
44478         "provider": {
44479             "type": "object",
44480             "properties": {
44481                 "sha256": {
44482                     "type": "string",
44483                     "description": "Hash value that can be used to validate the resource."
44484                 }
44485             }
44486         }
44487     }
44488 }
44489 {
44490     "$schema": "http://json-schema.org/draft-04/schema#",
44491     "name": "Package",
44492     "type": "object",
44493     "additionalProperties": false,
44494     "required": [ "name", "description" ],
44495     "properties": {
44496         "name": {
44497             "type": "string",
44498             "description": "Package name, including 'vendor-name/' prefix."
44499         },
44500         "type": {
44501             "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.",
44502             "type": "string"
44503         },
44504         "target-dir": {
44505             "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.",
44506             "type": "string"
44507         },
44508         "description": {
44509             "type": "string",
44510             "description": "Short package description."
44511         },
44512         "keywords": {
44513             "type": "array",
44514             "items": {
44515                 "type": "string",
44516                 "description": "A tag/keyword that this package relates to."
44517             }
44518         },
44519         "homepage": {
44520             "type": "string",
44521             "description": "Homepage URL for the project.",
44522             "format": "uri"
44523         },
44524         "version": {
44525             "type": "string",
44526             "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes."
44527         },
44528         "time": {
44529             "type": "string",
44530             "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
44531         },
44532         "license": {
44533             "type": ["string", "array"],
44534             "description": "License name. Or an array of license names."
44535         },
44536         "authors": {
44537             "$ref": "#/definitions/authors"
44538         },
44539         "require": {
44540             "type": "object",
44541             "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
44542             "additionalProperties": {
44543                 "type": "string"
44544             }
44545         },
44546         "replace": {
44547             "type": "object",
44548             "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
44549             "additionalProperties": {
44550                 "type": "string"
44551             }
44552         },
44553         "conflict": {
44554             "type": "object",
44555             "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
44556             "additionalProperties": {
44557                 "type": "string"
44558             }
44559         },
44560         "provide": {
44561             "type": "object",
44562             "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
44563             "additionalProperties": {
44564                 "type": "string"
44565             }
44566         },
44567         "require-dev": {
44568             "type": "object",
44569             "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
44570             "additionalProperties": {
44571                 "type": "string"
44572             }
44573         },
44574         "suggest": {
44575             "type": "object",
44576             "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).",
44577             "additionalProperties": {
44578                 "type": "string"
44579             }
44580         },
44581         "config": {
44582             "type": "object",
44583             "description": "Composer options.",
44584             "properties": {
44585                 "process-timeout": {
44586                     "type": "integer",
44587                     "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
44588                 },
44589                 "use-include-path": {
44590                     "type": "boolean",
44591                     "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
44592                 },
44593                 "preferred-install": {
44594                     "type": ["string", "object"],
44595                     "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\"}."
44596                 },
44597                 "notify-on-install": {
44598                     "type": "boolean",
44599                     "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."
44600                 },
44601                 "github-protocols": {
44602                     "type": "array",
44603                     "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].",
44604                     "items": {
44605                         "type": "string"
44606                     }
44607                 },
44608                 "github-oauth": {
44609                     "type": "object",
44610                     "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
44611                     "additionalProperties": {
44612                         "type": "string"
44613                     }
44614                 },
44615                 "gitlab-oauth": {
44616                     "type": "object",
44617                     "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"<token>\"}.",
44618                     "additionalProperties": {
44619                         "type": "string"
44620                     }
44621                 },
44622                 "gitlab-token": {
44623                     "type": "object",
44624                     "description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}.",
44625                     "additionalProperties": true
44626                 },
44627                 "disable-tls": {
44628                     "type": "boolean",
44629                     "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."
44630                 },
44631                 "secure-http": {
44632                     "type": "boolean",
44633                     "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."
44634                 },
44635                 "cafile": {
44636                     "type": "string",
44637                     "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."
44638                 },
44639                 "capath": {
44640                     "type": "string",
44641                     "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."
44642                 },
44643                 "http-basic": {
44644                     "type": "object",
44645                     "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
44646                     "additionalProperties": {
44647                         "type": "object",
44648                         "required": ["username", "password"],
44649                         "properties": {
44650                             "username": {
44651                                 "type": "string",
44652                                 "description": "The username used for HTTP Basic authentication"
44653                             },
44654                             "password": {
44655                                 "type": "string",
44656                                 "description": "The password used for HTTP Basic authentication"
44657                             }
44658                         }
44659                     }
44660                 },
44661                 "store-auths": {
44662                     "type": ["string", "boolean"],
44663                     "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
44664                 },
44665                 "platform": {
44666                     "type": "object",
44667                     "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
44668                     "additionalProperties": {
44669                         "type": "string"
44670                     }
44671                 },
44672                 "vendor-dir": {
44673                     "type": "string",
44674                     "description": "The location where all packages are installed, defaults to \"vendor\"."
44675                 },
44676                 "bin-dir": {
44677                     "type": "string",
44678                     "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
44679                 },
44680                 "data-dir": {
44681                     "type": "string",
44682                     "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes."
44683                 },
44684                 "cache-dir": {
44685                     "type": "string",
44686                     "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
44687                 },
44688                 "cache-files-dir": {
44689                     "type": "string",
44690                     "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
44691                 },
44692                 "cache-repo-dir": {
44693                     "type": "string",
44694                     "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
44695                 },
44696                 "cache-vcs-dir": {
44697                     "type": "string",
44698                     "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
44699                 },
44700                 "cache-ttl": {
44701                     "type": "integer",
44702                     "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
44703                 },
44704                 "cache-files-ttl": {
44705                     "type": "integer",
44706                     "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
44707                 },
44708                 "cache-files-maxsize": {
44709                     "type": ["string", "integer"],
44710                     "description": "The cache max size for the files cache, defaults to \"300MiB\"."
44711                 },
44712                 "bin-compat": {
44713                     "enum": ["auto", "full"],
44714                     "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)."
44715                 },
44716                 "discard-changes": {
44717                     "type": ["string", "boolean"],
44718                     "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
44719                 },
44720                 "autoloader-suffix": {
44721                     "type": "string",
44722                     "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
44723                 },
44724                 "optimize-autoloader": {
44725                     "type": "boolean",
44726                     "description": "Always optimize when dumping the autoloader."
44727                 },
44728                 "prepend-autoloader": {
44729                     "type": "boolean",
44730                     "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
44731                 },
44732                 "classmap-authoritative": {
44733                     "type": "boolean",
44734                     "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
44735                 },
44736                 "apcu-autoloader": {
44737                     "type": "boolean",
44738                     "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."
44739                 },
44740                 "github-domains": {
44741                     "type": "array",
44742                     "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
44743                     "items": {
44744                         "type": "string"
44745                     }
44746                 },
44747                 "github-expose-hostname": {
44748                     "type": "boolean",
44749                     "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."
44750                 },
44751                 "gitlab-domains": {
44752                     "type": "array",
44753                     "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].",
44754                     "items": {
44755                         "type": "string"
44756                     }
44757                 },
44758                 "archive-format": {
44759                     "type": "string",
44760                     "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
44761                 },
44762                 "archive-dir": {
44763                     "type": "string",
44764                     "description": "The default archive path when not provided on cli, defaults to \".\"."
44765                 },
44766                 "htaccess-protect": {
44767                     "type": "boolean",
44768                     "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
44769                 }
44770             }
44771         },
44772         "extra": {
44773             "type": ["object", "array"],
44774             "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.",
44775             "additionalProperties": true
44776         },
44777         "autoload": {
44778             "$ref": "#/definitions/autoload"
44779         },
44780         "autoload-dev": {
44781             "type": "object",
44782             "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
44783             "properties": {
44784                 "psr-0": {
44785                     "type": "object",
44786                     "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.",
44787                     "additionalProperties": {
44788                         "type": ["string", "array"],
44789                         "items": {
44790                             "type": "string"
44791                         }
44792                     }
44793                 },
44794                 "psr-4": {
44795                     "type": "object",
44796                     "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.",
44797                     "additionalProperties": {
44798                         "type": ["string", "array"],
44799                         "items": {
44800                             "type": "string"
44801                         }
44802                     }
44803                 },
44804                 "classmap": {
44805                     "type": "array",
44806                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
44807                 },
44808                 "files": {
44809                     "type": "array",
44810                     "description": "This is an array of files that are always required on every request."
44811                 }
44812             }
44813         },
44814         "archive": {
44815             "type": ["object"],
44816             "description": "Options for creating package archives for distribution.",
44817             "properties": {
44818                 "exclude": {
44819                     "type": "array",
44820                     "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
44821                 }
44822             }
44823         },
44824         "repositories": {
44825             "type": ["object", "array"],
44826             "description": "A set of additional repositories where packages can be found.",
44827             "additionalProperties": {
44828                 "oneOf": [
44829                     { "$ref": "#/definitions/repository" },
44830                     { "type": "boolean", "enum": [false] }
44831                 ]
44832             },
44833             "items": {
44834                 "oneOf": [
44835                     { "$ref": "#/definitions/repository" },
44836                     {
44837                         "type": "object",
44838                         "additionalProperties": { "type": "boolean", "enum": [false] },
44839                         "minProperties": 1,
44840                         "maxProperties": 1
44841                     }
44842                 ]
44843             }
44844         },
44845         "minimum-stability": {
44846             "type": ["string"],
44847             "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
44848             "pattern": "^dev|alpha|beta|rc|RC|stable$"
44849         },
44850         "prefer-stable": {
44851             "type": ["boolean"],
44852             "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages."
44853         },
44854         "bin": {
44855             "type": ["array"],
44856             "description": "A set of files that should be treated as binaries and symlinked into bin-dir (from config).",
44857             "items": {
44858                 "type": "string"
44859             }
44860         },
44861         "include-path": {
44862             "type": ["array"],
44863             "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.",
44864             "items": {
44865                 "type": "string"
44866             }
44867         },
44868         "scripts": {
44869             "type": ["object"],
44870             "description": "Scripts listeners that will be executed before/after some events.",
44871             "properties": {
44872                 "pre-install-cmd": {
44873                     "type": ["array", "string"],
44874                     "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
44875                 },
44876                 "post-install-cmd": {
44877                     "type": ["array", "string"],
44878                     "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
44879                 },
44880                 "pre-update-cmd": {
44881                     "type": ["array", "string"],
44882                     "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
44883                 },
44884                 "post-update-cmd": {
44885                     "type": ["array", "string"],
44886                     "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
44887                 },
44888                 "pre-status-cmd": {
44889                     "type": ["array", "string"],
44890                     "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
44891                 },
44892                 "post-status-cmd": {
44893                     "type": ["array", "string"],
44894                     "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
44895                 },
44896                 "pre-package-install": {
44897                     "type": ["array", "string"],
44898                     "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
44899                 },
44900                 "post-package-install": {
44901                     "type": ["array", "string"],
44902                     "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
44903                 },
44904                 "pre-package-update": {
44905                     "type": ["array", "string"],
44906                     "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
44907                 },
44908                 "post-package-update": {
44909                     "type": ["array", "string"],
44910                     "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
44911                 },
44912                 "pre-package-uninstall": {
44913                     "type": ["array", "string"],
44914                     "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
44915                 },
44916                 "post-package-uninstall": {
44917                     "type": ["array", "string"],
44918                     "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
44919                 },
44920                 "pre-autoload-dump": {
44921                     "type": ["array", "string"],
44922                     "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
44923                 },
44924                 "post-autoload-dump": {
44925                     "type": ["array", "string"],
44926                     "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
44927                 },
44928                 "post-root-package-install": {
44929                     "type": ["array", "string"],
44930                     "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
44931                 },
44932                 "post-create-project-cmd": {
44933                     "type": ["array", "string"],
44934                     "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
44935                 }
44936             }
44937         },
44938         "support": {
44939             "type": "object",
44940             "properties": {
44941                 "email": {
44942                     "type": "string",
44943                     "description": "Email address for support.",
44944                     "format": "email"
44945                 },
44946                 "issues": {
44947                     "type": "string",
44948                     "description": "URL to the issue tracker.",
44949                     "format": "uri"
44950                 },
44951                 "forum": {
44952                     "type": "string",
44953                     "description": "URL to the forum.",
44954                     "format": "uri"
44955                 },
44956                 "wiki": {
44957                     "type": "string",
44958                     "description": "URL to the wiki.",
44959                     "format": "uri"
44960                 },
44961                 "irc": {
44962                     "type": "string",
44963                     "description": "IRC channel for support, as irc://server/channel.",
44964                     "format": "uri"
44965                 },
44966                 "source": {
44967                     "type": "string",
44968                     "description": "URL to browse or download the sources.",
44969                     "format": "uri"
44970                 },
44971                 "docs": {
44972                     "type": "string",
44973                     "description": "URL to the documentation.",
44974                     "format": "uri"
44975                 },
44976                 "rss": {
44977                     "type": "string",
44978                     "description": "URL to the RSS feed.",
44979                     "format": "uri"
44980                 }
44981             }
44982         },
44983         "non-feature-branches": {
44984             "type": ["array"],
44985             "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
44986             "items": {
44987                 "type": "string"
44988             }
44989         },
44990         "abandoned": {
44991             "type": ["boolean", "string"],
44992             "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."
44993         },
44994         "_comment": {
44995             "type": ["array", "string"],
44996             "description": "A key to store comments in"
44997         }
44998     },
44999     "definitions": {
45000         "authors": {
45001             "type": "array",
45002             "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
45003             "items": {
45004                 "type": "object",
45005                 "additionalProperties": false,
45006                 "required": [ "name"],
45007                 "properties": {
45008                     "name": {
45009                         "type": "string",
45010                         "description": "Full name of the author."
45011                     },
45012                     "email": {
45013                         "type": "string",
45014                         "description": "Email address of the author.",
45015                         "format": "email"
45016                     },
45017                     "homepage": {
45018                         "type": "string",
45019                         "description": "Homepage URL for the author.",
45020                         "format": "uri"
45021                     },
45022                     "role": {
45023                         "type": "string",
45024                         "description": "Author's role in the project."
45025                     }
45026                 }
45027             }
45028         },
45029         "autoload": {
45030             "type": "object",
45031             "description": "Description of how the package can be autoloaded.",
45032             "properties": {
45033                 "psr-0": {
45034                     "type": "object",
45035                     "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.",
45036                     "additionalProperties": {
45037                         "type": ["string", "array"],
45038                         "items": {
45039                             "type": "string"
45040                         }
45041                     }
45042                 },
45043                 "psr-4": {
45044                     "type": "object",
45045                     "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.",
45046                     "additionalProperties": {
45047                         "type": ["string", "array"],
45048                         "items": {
45049                             "type": "string"
45050                         }
45051                     }
45052                 },
45053                 "classmap": {
45054                     "type": "array",
45055                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
45056                 },
45057                 "files": {
45058                     "type": "array",
45059                     "description": "This is an array of files that are always required on every request."
45060                 },
45061                 "exclude-from-classmap": {
45062                     "type": "array",
45063                     "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
45064                 }
45065             }
45066         },
45067         "repository": {
45068             "type": "object",
45069             "oneOf": [
45070                 { "$ref": "#/definitions/composer-repository" },
45071                 { "$ref": "#/definitions/vcs-repository" },
45072                 { "$ref": "#/definitions/path-repository" },
45073                 { "$ref": "#/definitions/artifact-repository" },
45074                 { "$ref": "#/definitions/pear-repository" },
45075                 { "$ref": "#/definitions/package-repository" }
45076             ]
45077         },
45078         "composer-repository": {
45079             "type": "object",
45080             "required": ["type", "url"],
45081             "properties": {
45082                 "type": { "type": "string", "enum": ["composer"] },
45083                 "url": { "type": "string" },
45084                 "options": {
45085                     "type": "object",
45086                     "additionalProperties": true
45087                 },
45088                 "allow_ssl_downgrade": { "type": "boolean" },
45089                 "force-lazy-providers": { "type": "boolean" }
45090             }
45091         },
45092         "vcs-repository": {
45093             "type": "object",
45094             "required": ["type", "url"],
45095             "properties": {
45096                 "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] },
45097                 "url": { "type": "string" },
45098                 "no-api": { "type": "boolean" },
45099                 "secure-http": { "type": "boolean" },
45100                 "svn-cache-credentials": { "type": "boolean" },
45101                 "trunk-path": { "type": ["string", "boolean"] },
45102                 "branches-path": { "type": ["string", "boolean"] },
45103                 "tags-path": { "type": ["string", "boolean"] },
45104                 "package-path": { "type": "string" },
45105                 "depot": { "type": "string" },
45106                 "branch": { "type": "string" },
45107                 "unique_perforce_client_name": { "type": "string" },
45108                 "p4user": { "type": "string" },
45109                 "p4password": { "type": "string" }
45110             }
45111         },
45112         "path-repository": {
45113             "type": "object",
45114             "required": ["type", "url"],
45115             "properties": {
45116                 "type": { "type": "string", "enum": ["path"] },
45117                 "url": { "type": "string" },
45118                 "options": {
45119                     "type": "object",
45120                     "properties": {
45121                         "symlink": { "type": ["boolean", "null"] }
45122                     },
45123                     "additionalProperties": true
45124                 }
45125             }
45126         },
45127         "artifact-repository": {
45128             "type": "object",
45129             "required": ["type", "url"],
45130             "properties": {
45131                 "type": { "type": "string", "enum": ["artifact"] },
45132                 "url": { "type": "string" }
45133             }
45134         },
45135         "pear-repository": {
45136             "type": "object",
45137             "required": ["type", "url"],
45138             "properties": {
45139                 "type": { "type": "string", "enum": ["pear"] },
45140                 "url": { "type": "string" },
45141                 "vendor-alias": { "type": "string" }
45142             }
45143         },
45144         "package-repository": {
45145             "type": "object",
45146             "required": ["type", "package"],
45147             "properties": {
45148                 "type": { "type": "string", "enum": ["package"] },
45149                 "package": {
45150                     "oneOf": [
45151                         { "$ref": "#/definitions/inline-package" },
45152                         {
45153                             "type": "array",
45154                             "items": {
45155                                 "type": { "$ref": "#/definitions/inline-package" }
45156                             }
45157                         }
45158                     ]
45159                 }
45160             }
45161         },
45162         "inline-package": {
45163             "required": ["name", "version"],
45164             "properties": {
45165                 "name": {
45166                     "type": "string",
45167                     "description": "Package name, including 'vendor-name/' prefix."
45168                 },
45169                 "type": {
45170                     "type": "string"
45171                 },
45172                 "target-dir": {
45173                     "description": "DEPRECATED: Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.",
45174                     "type": "string"
45175                 },
45176                 "description": {
45177                     "type": "string"
45178                 },
45179                 "keywords": {
45180                     "type": "array",
45181                     "items": {
45182                         "type": "string"
45183                     }
45184                 },
45185                 "homepage": {
45186                     "type": "string",
45187                     "format": "uri"
45188                 },
45189                 "version": {
45190                     "type": "string"
45191                 },
45192                 "time": {
45193                     "type": "string"
45194                 },
45195                 "license": {
45196                     "type": [
45197                         "string",
45198                         "array"
45199                     ]
45200                 },
45201                 "authors": {
45202                     "$ref": "#/definitions/authors"
45203                 },
45204                 "require": {
45205                     "type": "object",
45206                     "additionalProperties": {
45207                         "type": "string"
45208                     }
45209                 },
45210                 "replace": {
45211                     "type": "object",
45212                     "additionalProperties": {
45213                         "type": "string"
45214                     }
45215                 },
45216                 "conflict": {
45217                     "type": "object",
45218                     "additionalProperties": {
45219                         "type": "string"
45220                     }
45221                 },
45222                 "provide": {
45223                     "type": "object",
45224                     "additionalProperties": {
45225                         "type": "string"
45226                     }
45227                 },
45228                 "require-dev": {
45229                     "type": "object",
45230                     "additionalProperties": {
45231                         "type": "string"
45232                     }
45233                 },
45234                 "suggest": {
45235                     "type": "object",
45236                     "additionalProperties": {
45237                         "type": "string"
45238                     }
45239                 },
45240                 "extra": {
45241                     "type": ["object", "array"],
45242                     "additionalProperties": true
45243                 },
45244                 "autoload": {
45245                     "$ref": "#/definitions/autoload"
45246                 },
45247                 "archive": {
45248                     "type": ["object"],
45249                     "properties": {
45250                         "exclude": {
45251                             "type": "array"
45252                         }
45253                     }
45254                 },
45255                 "bin": {
45256                     "type": ["array"],
45257                     "description": "A set of files that should be treated as binaries and symlinked into bin-dir (from config).",
45258                     "items": {
45259                         "type": "string"
45260                     }
45261                 },
45262                 "include-path": {
45263                     "type": ["array"],
45264                     "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.",
45265                     "items": {
45266                         "type": "string"
45267                     }
45268                 },
45269                 "source": {
45270                     "type": "object",
45271                     "required": ["type", "url", "reference"],
45272                     "properties": {
45273                         "type": {
45274                             "type": "string"
45275                         },
45276                         "url": {
45277                             "type": "string"
45278                         },
45279                         "reference": {
45280                             "type": "string"
45281                         },
45282                         "mirrors": {
45283                             "type": "array"
45284                         }
45285                     }
45286                 },
45287                 "dist": {
45288                     "type": "object",
45289                     "required": ["type", "url"],
45290                     "properties": {
45291                         "type": {
45292                             "type": "string"
45293                         },
45294                         "url": {
45295                             "type": "string"
45296                         },
45297                         "reference": {
45298                             "type": "string"
45299                         },
45300                         "shasum": {
45301                             "type": "string"
45302                         },
45303                         "mirrors": {
45304                             "type": "array"
45305                         }
45306                     }
45307                 }
45308             },
45309             "additionalProperties": true
45310         }
45311     }
45312 }
45313 {
45314     "389-exception": [
45315         "389 Directory Server\nException"
45316     ],
45317     "Autoconf-exception-2.0": [
45318         "Autoconf exception 2.0"
45319     ],
45320     "Autoconf-exception-3.0": [
45321         "Autoconf exception 3.0"
45322     ],
45323     "Bison-exception-2.2": [
45324         "Bison exception 2.2"
45325     ],
45326     "Classpath-exception-2.0": [
45327         "Classpath exception 2.0"
45328     ],
45329     "CLISP-exception-2.0": [
45330         "CLISP exception 2.0"
45331     ],
45332     "DigiRule-FOSS-exception": [
45333         "DigiRule FOSS License Exception"
45334     ],
45335     "eCos-exception-2.0": [
45336         "eCos exception 2.0"
45337     ],
45338     "Fawkes-Runtime-exception": [
45339         "Fawkes Runtime Exception"
45340     ],
45341     "FLTK-exception": [
45342         "FLTK exception"
45343     ],
45344     "Font-exception-2.0": [
45345         "Font exception 2.0"
45346     ],
45347     "freertos-exception-2.0": [
45348         "FreeRTOS Exception 2.0"
45349     ],
45350     "GCC-exception-2.0": [
45351         "GCC Runtime Library exception 2.0"
45352     ],
45353     "GCC-exception-3.1": [
45354         "GCC Runtime Library exception 3.1"
45355     ],
45356     "gnu-javamail-exception": [
45357         "GNU JavaMail exception"
45358     ],
45359     "i2p-gpl-java-exception": [
45360         "i2p GPL+Java Exception"
45361     ],
45362     "Libtool-exception": [
45363         "Libtool Exception"
45364     ],
45365     "LZMA-exception": [
45366         "LZMA exception"
45367     ],
45368     "mif-exception": [
45369         "Macros and Inline Functions Exception"
45370     ],
45371     "Nokia-Qt-exception-1.1": [
45372         "Nokia Qt LGPL exception 1.1"
45373     ],
45374     "OCCT-exception-1.0": [
45375         "Open CASCADE Exception 1.0"
45376     ],
45377     "openvpn-openssl-exception": [
45378         "OpenVPN OpenSSL Exception"
45379     ],
45380     "Qwt-exception-1.0": [
45381         "Qwt exception 1.0"
45382     ],
45383     "u-boot-exception-2.0": [
45384         "U-Boot exception 2.0"
45385     ],
45386     "WxWindows-exception-3.1": [
45387         "WxWindows Library Exception 3.1"
45388     ]
45389 }{
45390     "0BSD": [
45391         "BSD Zero Clause License",
45392         true
45393     ],
45394     "AAL": [
45395         "Attribution Assurance License",
45396         true
45397     ],
45398     "Abstyles": [
45399         "Abstyles License",
45400         false
45401     ],
45402     "Adobe-2006": [
45403         "Adobe Systems Incorporated Source Code License Agreement",
45404         false
45405     ],
45406     "Adobe-Glyph": [
45407         "Adobe Glyph List License",
45408         false
45409     ],
45410     "ADSL": [
45411         "Amazon Digital Services License",
45412         false
45413     ],
45414     "AFL-1.1": [
45415         "Academic Free License v1.1",
45416         true
45417     ],
45418     "AFL-1.2": [
45419         "Academic Free License v1.2",
45420         true
45421     ],
45422     "AFL-2.0": [
45423         "Academic Free License v2.0",
45424         true
45425     ],
45426     "AFL-2.1": [
45427         "Academic Free License v2.1",
45428         true
45429     ],
45430     "AFL-3.0": [
45431         "Academic Free License v3.0",
45432         true
45433     ],
45434     "Afmparse": [
45435         "Afmparse License",
45436         false
45437     ],
45438     "AGPL-1.0": [
45439         "Affero General Public License v1.0",
45440         false
45441     ],
45442     "AGPL-3.0": [
45443         "GNU Affero General Public License v3.0",
45444         true
45445     ],
45446     "Aladdin": [
45447         "Aladdin Free Public License",
45448         false
45449     ],
45450     "AMDPLPA": [
45451         "AMD's plpa_map.c License",
45452         false
45453     ],
45454     "AML": [
45455         "Apple MIT License",
45456         false
45457     ],
45458     "AMPAS": [
45459         "Academy of Motion Picture Arts and Sciences BSD",
45460         false
45461     ],
45462     "ANTLR-PD": [
45463         "ANTLR Software Rights Notice",
45464         false
45465     ],
45466     "Apache-1.0": [
45467         "Apache License 1.0",
45468         false
45469     ],
45470     "Apache-1.1": [
45471         "Apache License 1.1",
45472         true
45473     ],
45474     "Apache-2.0": [
45475         "Apache License 2.0",
45476         true
45477     ],
45478     "APAFML": [
45479         "Adobe Postscript AFM License",
45480         false
45481     ],
45482     "APL-1.0": [
45483         "Adaptive Public License 1.0",
45484         true
45485     ],
45486     "APSL-1.0": [
45487         "Apple Public Source License 1.0",
45488         true
45489     ],
45490     "APSL-1.1": [
45491         "Apple Public Source License 1.1",
45492         true
45493     ],
45494     "APSL-1.2": [
45495         "Apple Public Source License 1.2",
45496         true
45497     ],
45498     "APSL-2.0": [
45499         "Apple Public Source License 2.0",
45500         true
45501     ],
45502     "Artistic-1.0": [
45503         "Artistic License 1.0",
45504         true
45505     ],
45506     "Artistic-1.0-cl8": [
45507         "Artistic License 1.0 w/clause 8",
45508         true
45509     ],
45510     "Artistic-1.0-Perl": [
45511         "Artistic License 1.0 (Perl)",
45512         true
45513     ],
45514     "Artistic-2.0": [
45515         "Artistic License 2.0",
45516         true
45517     ],
45518     "Bahyph": [
45519         "Bahyph License",
45520         false
45521     ],
45522     "Barr": [
45523         "Barr License",
45524         false
45525     ],
45526     "Beerware": [
45527         "Beerware License",
45528         false
45529     ],
45530     "BitTorrent-1.0": [
45531         "BitTorrent Open Source License v1.0",
45532         false
45533     ],
45534     "BitTorrent-1.1": [
45535         "BitTorrent Open Source License v1.1",
45536         false
45537     ],
45538     "Borceux": [
45539         "Borceux license",
45540         false
45541     ],
45542     "BSD-2-Clause": [
45543         "BSD 2-clause \"Simplified\" License",
45544         true
45545     ],
45546     "BSD-2-Clause-FreeBSD": [
45547         "BSD 2-clause FreeBSD License",
45548         false
45549     ],
45550     "BSD-2-Clause-NetBSD": [
45551         "BSD 2-clause NetBSD License",
45552         false
45553     ],
45554     "BSD-3-Clause": [
45555         "BSD 3-clause \"New\" or \"Revised\" License",
45556         true
45557     ],
45558     "BSD-3-Clause-Attribution": [
45559         "BSD with attribution",
45560         false
45561     ],
45562     "BSD-3-Clause-Clear": [
45563         "BSD 3-clause Clear License",
45564         false
45565     ],
45566     "BSD-3-Clause-LBNL": [
45567         "Lawrence Berkeley National Labs BSD variant license",
45568         false
45569     ],
45570     "BSD-3-Clause-No-Nuclear-License": [
45571         "BSD 3-Clause No Nuclear License",
45572         false
45573     ],
45574     "BSD-3-Clause-No-Nuclear-License-2014": [
45575         "BSD 3-Clause No Nuclear License 2014",
45576         false
45577     ],
45578     "BSD-3-Clause-No-Nuclear-Warranty": [
45579         "BSD 3-Clause No Nuclear Warranty",
45580         false
45581     ],
45582     "BSD-4-Clause": [
45583         "BSD 4-clause \"Original\" or \"Old\" License",
45584         false
45585     ],
45586     "BSD-4-Clause-UC": [
45587         "BSD-4-Clause (University of California-Specific)",
45588         false
45589     ],
45590     "BSD-Protection": [
45591         "BSD Protection License",
45592         false
45593     ],
45594     "BSD-Source-Code": [
45595         "BSD Source Code Attribution",
45596         false
45597     ],
45598     "BSL-1.0": [
45599         "Boost Software License 1.0",
45600         true
45601     ],
45602     "bzip2-1.0.5": [
45603         "bzip2 and libbzip2 License v1.0.5",
45604         false
45605     ],
45606     "bzip2-1.0.6": [
45607         "bzip2 and libbzip2 License v1.0.6",
45608         false
45609     ],
45610     "Caldera": [
45611         "Caldera License",
45612         false
45613     ],
45614     "CATOSL-1.1": [
45615         "Computer Associates Trusted Open Source License 1.1",
45616         true
45617     ],
45618     "CC-BY-1.0": [
45619         "Creative Commons Attribution 1.0",
45620         false
45621     ],
45622     "CC-BY-2.0": [
45623         "Creative Commons Attribution 2.0",
45624         false
45625     ],
45626     "CC-BY-2.5": [
45627         "Creative Commons Attribution 2.5",
45628         false
45629     ],
45630     "CC-BY-3.0": [
45631         "Creative Commons Attribution 3.0",
45632         false
45633     ],
45634     "CC-BY-4.0": [
45635         "Creative Commons Attribution 4.0",
45636         false
45637     ],
45638     "CC-BY-NC-1.0": [
45639         "Creative Commons Attribution Non Commercial 1.0",
45640         false
45641     ],
45642     "CC-BY-NC-2.0": [
45643         "Creative Commons Attribution Non Commercial 2.0",
45644         false
45645     ],
45646     "CC-BY-NC-2.5": [
45647         "Creative Commons Attribution Non Commercial 2.5",
45648         false
45649     ],
45650     "CC-BY-NC-3.0": [
45651         "Creative Commons Attribution Non Commercial 3.0",
45652         false
45653     ],
45654     "CC-BY-NC-4.0": [
45655         "Creative Commons Attribution Non Commercial 4.0",
45656         false
45657     ],
45658     "CC-BY-NC-ND-1.0": [
45659         "Creative Commons Attribution Non Commercial No Derivatives 1.0",
45660         false
45661     ],
45662     "CC-BY-NC-ND-2.0": [
45663         "Creative Commons Attribution Non Commercial No Derivatives 2.0",
45664         false
45665     ],
45666     "CC-BY-NC-ND-2.5": [
45667         "Creative Commons Attribution Non Commercial No Derivatives 2.5",
45668         false
45669     ],
45670     "CC-BY-NC-ND-3.0": [
45671         "Creative Commons Attribution Non Commercial No Derivatives 3.0",
45672         false
45673     ],
45674     "CC-BY-NC-ND-4.0": [
45675         "Creative Commons Attribution Non Commercial No Derivatives 4.0",
45676         false
45677     ],
45678     "CC-BY-NC-SA-1.0": [
45679         "Creative Commons Attribution Non Commercial Share Alike 1.0",
45680         false
45681     ],
45682     "CC-BY-NC-SA-2.0": [
45683         "Creative Commons Attribution Non Commercial Share Alike 2.0",
45684         false
45685     ],
45686     "CC-BY-NC-SA-2.5": [
45687         "Creative Commons Attribution Non Commercial Share Alike 2.5",
45688         false
45689     ],
45690     "CC-BY-NC-SA-3.0": [
45691         "Creative Commons Attribution Non Commercial Share Alike 3.0",
45692         false
45693     ],
45694     "CC-BY-NC-SA-4.0": [
45695         "Creative Commons Attribution Non Commercial Share Alike 4.0",
45696         false
45697     ],
45698     "CC-BY-ND-1.0": [
45699         "Creative Commons Attribution No Derivatives 1.0",
45700         false
45701     ],
45702     "CC-BY-ND-2.0": [
45703         "Creative Commons Attribution No Derivatives 2.0",
45704         false
45705     ],
45706     "CC-BY-ND-2.5": [
45707         "Creative Commons Attribution No Derivatives 2.5",
45708         false
45709     ],
45710     "CC-BY-ND-3.0": [
45711         "Creative Commons Attribution No Derivatives 3.0",
45712         false
45713     ],
45714     "CC-BY-ND-4.0": [
45715         "Creative Commons Attribution No Derivatives 4.0",
45716         false
45717     ],
45718     "CC-BY-SA-1.0": [
45719         "Creative Commons Attribution Share Alike 1.0",
45720         false
45721     ],
45722     "CC-BY-SA-2.0": [
45723         "Creative Commons Attribution Share Alike 2.0",
45724         false
45725     ],
45726     "CC-BY-SA-2.5": [
45727         "Creative Commons Attribution Share Alike 2.5",
45728         false
45729     ],
45730     "CC-BY-SA-3.0": [
45731         "Creative Commons Attribution Share Alike 3.0",
45732         false
45733     ],
45734     "CC-BY-SA-4.0": [
45735         "Creative Commons Attribution Share Alike 4.0",
45736         false
45737     ],
45738     "CC0-1.0": [
45739         "Creative Commons Zero v1.0 Universal",
45740         false
45741     ],
45742     "CDDL-1.0": [
45743         "Common Development and Distribution License 1.0",
45744         true
45745     ],
45746     "CDDL-1.1": [
45747         "Common Development and Distribution License 1.1",
45748         false
45749     ],
45750     "CECILL-1.0": [
45751         "CeCILL Free Software License Agreement v1.0",
45752         false
45753     ],
45754     "CECILL-1.1": [
45755         "CeCILL Free Software License Agreement v1.1",
45756         false
45757     ],
45758     "CECILL-2.0": [
45759         "CeCILL Free Software License Agreement v2.0",
45760         false
45761     ],
45762     "CECILL-2.1": [
45763         "CeCILL Free Software License Agreement v2.1",
45764         true
45765     ],
45766     "CECILL-B": [
45767         "CeCILL-B Free Software License Agreement",
45768         false
45769     ],
45770     "CECILL-C": [
45771         "CeCILL-C Free Software License Agreement",
45772         false
45773     ],
45774     "ClArtistic": [
45775         "Clarified Artistic License",
45776         false
45777     ],
45778     "CNRI-Jython": [
45779         "CNRI Jython License",
45780         false
45781     ],
45782     "CNRI-Python": [
45783         "CNRI Python License",
45784         true
45785     ],
45786     "CNRI-Python-GPL-Compatible": [
45787         "CNRI Python Open Source GPL Compatible License Agreement",
45788         false
45789     ],
45790     "Condor-1.1": [
45791         "Condor Public License v1.1",
45792         false
45793     ],
45794     "CPAL-1.0": [
45795         "Common Public Attribution License 1.0",
45796         true
45797     ],
45798     "CPL-1.0": [
45799         "Common Public License 1.0",
45800         true
45801     ],
45802     "CPOL-1.02": [
45803         "Code Project Open License 1.02",
45804         false
45805     ],
45806     "Crossword": [
45807         "Crossword License",
45808         false
45809     ],
45810     "CrystalStacker": [
45811         "CrystalStacker License",
45812         false
45813     ],
45814     "CUA-OPL-1.0": [
45815         "CUA Office Public License v1.0",
45816         true
45817     ],
45818     "Cube": [
45819         "Cube License",
45820         false
45821     ],
45822     "curl": [
45823         "curl License",
45824         false
45825     ],
45826     "D-FSL-1.0": [
45827         "Deutsche Freie Software Lizenz",
45828         false
45829     ],
45830     "diffmark": [
45831         "diffmark license",
45832         false
45833     ],
45834     "DOC": [
45835         "DOC License",
45836         false
45837     ],
45838     "Dotseqn": [
45839         "Dotseqn License",
45840         false
45841     ],
45842     "DSDP": [
45843         "DSDP License",
45844         false
45845     ],
45846     "dvipdfm": [
45847         "dvipdfm License",
45848         false
45849     ],
45850     "ECL-1.0": [
45851         "Educational Community License v1.0",
45852         true
45853     ],
45854     "ECL-2.0": [
45855         "Educational Community License v2.0",
45856         true
45857     ],
45858     "EFL-1.0": [
45859         "Eiffel Forum License v1.0",
45860         true
45861     ],
45862     "EFL-2.0": [
45863         "Eiffel Forum License v2.0",
45864         true
45865     ],
45866     "eGenix": [
45867         "eGenix.com Public License 1.1.0",
45868         false
45869     ],
45870     "Entessa": [
45871         "Entessa Public License v1.0",
45872         true
45873     ],
45874     "EPL-1.0": [
45875         "Eclipse Public License 1.0",
45876         true
45877     ],
45878     "ErlPL-1.1": [
45879         "Erlang Public License v1.1",
45880         false
45881     ],
45882     "EUDatagrid": [
45883         "EU DataGrid Software License",
45884         true
45885     ],
45886     "EUPL-1.0": [
45887         "European Union Public License 1.0",
45888         false
45889     ],
45890     "EUPL-1.1": [
45891         "European Union Public License 1.1",
45892         true
45893     ],
45894     "Eurosym": [
45895         "Eurosym License",
45896         false
45897     ],
45898     "Fair": [
45899         "Fair License",
45900         true
45901     ],
45902     "Frameworx-1.0": [
45903         "Frameworx Open License 1.0",
45904         true
45905     ],
45906     "FreeImage": [
45907         "FreeImage Public License v1.0",
45908         false
45909     ],
45910     "FSFAP": [
45911         "FSF All Permissive License",
45912         false
45913     ],
45914     "FSFUL": [
45915         "FSF Unlimited License",
45916         false
45917     ],
45918     "FSFULLR": [
45919         "FSF Unlimited License (with License Retention)",
45920         false
45921     ],
45922     "FTL": [
45923         "Freetype Project License",
45924         false
45925     ],
45926     "GFDL-1.1": [
45927         "GNU Free Documentation License v1.1",
45928         false
45929     ],
45930     "GFDL-1.2": [
45931         "GNU Free Documentation License v1.2",
45932         false
45933     ],
45934     "GFDL-1.3": [
45935         "GNU Free Documentation License v1.3",
45936         false
45937     ],
45938     "Giftware": [
45939         "Giftware License",
45940         false
45941     ],
45942     "GL2PS": [
45943         "GL2PS License",
45944         false
45945     ],
45946     "Glide": [
45947         "3dfx Glide License",
45948         false
45949     ],
45950     "Glulxe": [
45951         "Glulxe License",
45952         false
45953     ],
45954     "gnuplot": [
45955         "gnuplot License",
45956         false
45957     ],
45958     "GPL-1.0": [
45959         "GNU General Public License v1.0 only",
45960         false
45961     ],
45962     "GPL-2.0": [
45963         "GNU General Public License v2.0 only",
45964         true
45965     ],
45966     "GPL-3.0": [
45967         "GNU General Public License v3.0 only",
45968         true
45969     ],
45970     "gSOAP-1.3b": [
45971         "gSOAP Public License v1.3b",
45972         false
45973     ],
45974     "HaskellReport": [
45975         "Haskell Language Report License",
45976         false
45977     ],
45978     "HPND": [
45979         "Historic Permission Notice and Disclaimer",
45980         true
45981     ],
45982     "IBM-pibs": [
45983         "IBM PowerPC Initialization and Boot Software",
45984         false
45985     ],
45986     "ICU": [
45987         "ICU License",
45988         false
45989     ],
45990     "IJG": [
45991         "Independent JPEG Group License",
45992         false
45993     ],
45994     "ImageMagick": [
45995         "ImageMagick License",
45996         false
45997     ],
45998     "iMatix": [
45999         "iMatix Standard Function Library Agreement",
46000         false
46001     ],
46002     "Imlib2": [
46003         "Imlib2 License",
46004         false
46005     ],
46006     "Info-ZIP": [
46007         "Info-ZIP License",
46008         false
46009     ],
46010     "Intel": [
46011         "Intel Open Source License",
46012         true
46013     ],
46014     "Intel-ACPI": [
46015         "Intel ACPI Software License Agreement",
46016         false
46017     ],
46018     "Interbase-1.0": [
46019         "Interbase Public License v1.0",
46020         false
46021     ],
46022     "IPA": [
46023         "IPA Font License",
46024         true
46025     ],
46026     "IPL-1.0": [
46027         "IBM Public License v1.0",
46028         true
46029     ],
46030     "ISC": [
46031         "ISC License",
46032         true
46033     ],
46034     "JasPer-2.0": [
46035         "JasPer License",
46036         false
46037     ],
46038     "JSON": [
46039         "JSON License",
46040         false
46041     ],
46042     "LAL-1.2": [
46043         "Licence Art Libre 1.2",
46044         false
46045     ],
46046     "LAL-1.3": [
46047         "Licence Art Libre 1.3",
46048         false
46049     ],
46050     "Latex2e": [
46051         "Latex2e License",
46052         false
46053     ],
46054     "Leptonica": [
46055         "Leptonica License",
46056         false
46057     ],
46058     "LGPL-2.0": [
46059         "GNU Library General Public License v2 only",
46060         true
46061     ],
46062     "LGPL-2.1": [
46063         "GNU Lesser General Public License v2.1 only",
46064         true
46065     ],
46066     "LGPL-3.0": [
46067         "GNU Lesser General Public License v3.0 only",
46068         true
46069     ],
46070     "LGPLLR": [
46071         "Lesser General Public License For Linguistic Resources",
46072         false
46073     ],
46074     "Libpng": [
46075         "libpng License",
46076         false
46077     ],
46078     "libtiff": [
46079         "libtiff License",
46080         false
46081     ],
46082     "LiLiQ-P-1.1": [
46083         "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1",
46084         true
46085     ],
46086     "LiLiQ-R-1.1": [
46087         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1",
46088         true
46089     ],
46090     "LiLiQ-Rplus-1.1": [
46091         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1",
46092         true
46093     ],
46094     "LPL-1.0": [
46095         "Lucent Public License Version 1.0",
46096         true
46097     ],
46098     "LPL-1.02": [
46099         "Lucent Public License v1.02",
46100         true
46101     ],
46102     "LPPL-1.0": [
46103         "LaTeX Project Public License v1.0",
46104         false
46105     ],
46106     "LPPL-1.1": [
46107         "LaTeX Project Public License v1.1",
46108         false
46109     ],
46110     "LPPL-1.2": [
46111         "LaTeX Project Public License v1.2",
46112         false
46113     ],
46114     "LPPL-1.3a": [
46115         "LaTeX Project Public License v1.3a",
46116         false
46117     ],
46118     "LPPL-1.3c": [
46119         "LaTeX Project Public License v1.3c",
46120         true
46121     ],
46122     "MakeIndex": [
46123         "MakeIndex License",
46124         false
46125     ],
46126     "MirOS": [
46127         "MirOS Licence",
46128         true
46129     ],
46130     "MIT": [
46131         "MIT License",
46132         true
46133     ],
46134     "MIT-advertising": [
46135         "Enlightenment License (e16)",
46136         false
46137     ],
46138     "MIT-CMU": [
46139         "CMU License",
46140         false
46141     ],
46142     "MIT-enna": [
46143         "enna License",
46144         false
46145     ],
46146     "MIT-feh": [
46147         "feh License",
46148         false
46149     ],
46150     "MITNFA": [
46151         "MIT +no-false-attribs license",
46152         false
46153     ],
46154     "Motosoto": [
46155         "Motosoto License",
46156         true
46157     ],
46158     "mpich2": [
46159         "mpich2 License",
46160         false
46161     ],
46162     "MPL-1.0": [
46163         "Mozilla Public License 1.0",
46164         true
46165     ],
46166     "MPL-1.1": [
46167         "Mozilla Public License 1.1",
46168         true
46169     ],
46170     "MPL-2.0": [
46171         "Mozilla Public License 2.0",
46172         true
46173     ],
46174     "MPL-2.0-no-copyleft-exception": [
46175         "Mozilla Public License 2.0 (no copyleft exception)",
46176         true
46177     ],
46178     "MS-PL": [
46179         "Microsoft Public License",
46180         true
46181     ],
46182     "MS-RL": [
46183         "Microsoft Reciprocal License",
46184         true
46185     ],
46186     "MTLL": [
46187         "Matrix Template Library License",
46188         false
46189     ],
46190     "Multics": [
46191         "Multics License",
46192         true
46193     ],
46194     "Mup": [
46195         "Mup License",
46196         false
46197     ],
46198     "NASA-1.3": [
46199         "NASA Open Source Agreement 1.3",
46200         true
46201     ],
46202     "Naumen": [
46203         "Naumen Public License",
46204         true
46205     ],
46206     "NBPL-1.0": [
46207         "Net Boolean Public License v1",
46208         false
46209     ],
46210     "NCSA": [
46211         "University of Illinois/NCSA Open Source License",
46212         true
46213     ],
46214     "Net-SNMP": [
46215         "Net-SNMP License",
46216         false
46217     ],
46218     "NetCDF": [
46219         "NetCDF license",
46220         false
46221     ],
46222     "Newsletr": [
46223         "Newsletr License",
46224         false
46225     ],
46226     "NGPL": [
46227         "Nethack General Public License",
46228         true
46229     ],
46230     "NLOD-1.0": [
46231         "Norwegian Licence for Open Government Data",
46232         false
46233     ],
46234     "NLPL": [
46235         "No Limit Public License",
46236         false
46237     ],
46238     "Nokia": [
46239         "Nokia Open Source License",
46240         true
46241     ],
46242     "NOSL": [
46243         "Netizen Open Source License",
46244         false
46245     ],
46246     "Noweb": [
46247         "Noweb License",
46248         false
46249     ],
46250     "NPL-1.0": [
46251         "Netscape Public License v1.0",
46252         false
46253     ],
46254     "NPL-1.1": [
46255         "Netscape Public License v1.1",
46256         false
46257     ],
46258     "NPOSL-3.0": [
46259         "Non-Profit Open Software License 3.0",
46260         true
46261     ],
46262     "NRL": [
46263         "NRL License",
46264         false
46265     ],
46266     "NTP": [
46267         "NTP License",
46268         true
46269     ],
46270     "Nunit": [
46271         "Nunit License",
46272         false
46273     ],
46274     "OCCT-PL": [
46275         "Open CASCADE Technology Public License",
46276         false
46277     ],
46278     "OCLC-2.0": [
46279         "OCLC Research Public License 2.0",
46280         true
46281     ],
46282     "ODbL-1.0": [
46283         "ODC Open Database License v1.0",
46284         false
46285     ],
46286     "OFL-1.0": [
46287         "SIL Open Font License 1.0",
46288         false
46289     ],
46290     "OFL-1.1": [
46291         "SIL Open Font License 1.1",
46292         true
46293     ],
46294     "OGTSL": [
46295         "Open Group Test Suite License",
46296         true
46297     ],
46298     "OLDAP-1.1": [
46299         "Open LDAP Public License v1.1",
46300         false
46301     ],
46302     "OLDAP-1.2": [
46303         "Open LDAP Public License v1.2",
46304         false
46305     ],
46306     "OLDAP-1.3": [
46307         "Open LDAP Public License v1.3",
46308         false
46309     ],
46310     "OLDAP-1.4": [
46311         "Open LDAP Public License v1.4",
46312         false
46313     ],
46314     "OLDAP-2.0": [
46315         "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
46316         false
46317     ],
46318     "OLDAP-2.0.1": [
46319         "Open LDAP Public License v2.0.1",
46320         false
46321     ],
46322     "OLDAP-2.1": [
46323         "Open LDAP Public License v2.1",
46324         false
46325     ],
46326     "OLDAP-2.2": [
46327         "Open LDAP Public License v2.2",
46328         false
46329     ],
46330     "OLDAP-2.2.1": [
46331         "Open LDAP Public License v2.2.1",
46332         false
46333     ],
46334     "OLDAP-2.2.2": [
46335         "Open LDAP Public License  2.2.2",
46336         false
46337     ],
46338     "OLDAP-2.3": [
46339         "Open LDAP Public License v2.3",
46340         false
46341     ],
46342     "OLDAP-2.4": [
46343         "Open LDAP Public License v2.4",
46344         false
46345     ],
46346     "OLDAP-2.5": [
46347         "Open LDAP Public License v2.5",
46348         false
46349     ],
46350     "OLDAP-2.6": [
46351         "Open LDAP Public License v2.6",
46352         false
46353     ],
46354     "OLDAP-2.7": [
46355         "Open LDAP Public License v2.7",
46356         false
46357     ],
46358     "OLDAP-2.8": [
46359         "Open LDAP Public License v2.8",
46360         false
46361     ],
46362     "OML": [
46363         "Open Market License",
46364         false
46365     ],
46366     "OpenSSL": [
46367         "OpenSSL License",
46368         false
46369     ],
46370     "OPL-1.0": [
46371         "Open Public License v1.0",
46372         false
46373     ],
46374     "OSET-PL-2.1": [
46375         "OSET Public License version 2.1",
46376         true
46377     ],
46378     "OSL-1.0": [
46379         "Open Software License 1.0",
46380         true
46381     ],
46382     "OSL-1.1": [
46383         "Open Software License 1.1",
46384         false
46385     ],
46386     "OSL-2.0": [
46387         "Open Software License 2.0",
46388         true
46389     ],
46390     "OSL-2.1": [
46391         "Open Software License 2.1",
46392         true
46393     ],
46394     "OSL-3.0": [
46395         "Open Software License 3.0",
46396         true
46397     ],
46398     "PDDL-1.0": [
46399         "ODC Public Domain Dedication & License 1.0",
46400         false
46401     ],
46402     "PHP-3.0": [
46403         "PHP License v3.0",
46404         true
46405     ],
46406     "PHP-3.01": [
46407         "PHP License v3.01",
46408         false
46409     ],
46410     "Plexus": [
46411         "Plexus Classworlds License",
46412         false
46413     ],
46414     "PostgreSQL": [
46415         "PostgreSQL License",
46416         true
46417     ],
46418     "psfrag": [
46419         "psfrag License",
46420         false
46421     ],
46422     "psutils": [
46423         "psutils License",
46424         false
46425     ],
46426     "Python-2.0": [
46427         "Python License 2.0",
46428         true
46429     ],
46430     "Qhull": [
46431         "Qhull License",
46432         false
46433     ],
46434     "QPL-1.0": [
46435         "Q Public License 1.0",
46436         true
46437     ],
46438     "Rdisc": [
46439         "Rdisc License",
46440         false
46441     ],
46442     "RHeCos-1.1": [
46443         "Red Hat eCos Public License v1.1",
46444         false
46445     ],
46446     "RPL-1.1": [
46447         "Reciprocal Public License 1.1",
46448         true
46449     ],
46450     "RPL-1.5": [
46451         "Reciprocal Public License 1.5",
46452         true
46453     ],
46454     "RPSL-1.0": [
46455         "RealNetworks Public Source License v1.0",
46456         true
46457     ],
46458     "RSA-MD": [
46459         "RSA Message-Digest License",
46460         false
46461     ],
46462     "RSCPL": [
46463         "Ricoh Source Code Public License",
46464         true
46465     ],
46466     "Ruby": [
46467         "Ruby License",
46468         false
46469     ],
46470     "SAX-PD": [
46471         "Sax Public Domain Notice",
46472         false
46473     ],
46474     "Saxpath": [
46475         "Saxpath License",
46476         false
46477     ],
46478     "SCEA": [
46479         "SCEA Shared Source License",
46480         false
46481     ],
46482     "Sendmail": [
46483         "Sendmail License",
46484         false
46485     ],
46486     "SGI-B-1.0": [
46487         "SGI Free Software License B v1.0",
46488         false
46489     ],
46490     "SGI-B-1.1": [
46491         "SGI Free Software License B v1.1",
46492         false
46493     ],
46494     "SGI-B-2.0": [
46495         "SGI Free Software License B v2.0",
46496         false
46497     ],
46498     "SimPL-2.0": [
46499         "Simple Public License 2.0",
46500         true
46501     ],
46502     "SISSL": [
46503         "Sun Industry Standards Source License v1.1",
46504         true
46505     ],
46506     "SISSL-1.2": [
46507         "Sun Industry Standards Source License v1.2",
46508         false
46509     ],
46510     "Sleepycat": [
46511         "Sleepycat License",
46512         true
46513     ],
46514     "SMLNJ": [
46515         "Standard ML of New Jersey License",
46516         false
46517     ],
46518     "SMPPL": [
46519         "Secure Messaging Protocol Public License",
46520         false
46521     ],
46522     "SNIA": [
46523         "SNIA Public License 1.1",
46524         false
46525     ],
46526     "Spencer-86": [
46527         "Spencer License 86",
46528         false
46529     ],
46530     "Spencer-94": [
46531         "Spencer License 94",
46532         false
46533     ],
46534     "Spencer-99": [
46535         "Spencer License 99",
46536         false
46537     ],
46538     "SPL-1.0": [
46539         "Sun Public License v1.0",
46540         true
46541     ],
46542     "SugarCRM-1.1.3": [
46543         "SugarCRM Public License v1.1.3",
46544         false
46545     ],
46546     "SWL": [
46547         "Scheme Widget Library (SWL) Software License Agreement",
46548         false
46549     ],
46550     "TCL": [
46551         "TCL/TK License",
46552         false
46553     ],
46554     "TCP-wrappers": [
46555         "TCP Wrappers License",
46556         false
46557     ],
46558     "TMate": [
46559         "TMate Open Source License",
46560         false
46561     ],
46562     "TORQUE-1.1": [
46563         "TORQUE v2.5+ Software License v1.1",
46564         false
46565     ],
46566     "TOSL": [
46567         "Trusster Open Source License",
46568         false
46569     ],
46570     "Unicode-DFS-2015": [
46571         "Unicode License Agreement - Data Files and Software (2015)",
46572         false
46573     ],
46574     "Unicode-DFS-2016": [
46575         "Unicode License Agreement - Data Files and Software (2016)",
46576         false
46577     ],
46578     "Unicode-TOU": [
46579         "Unicode Terms of Use",
46580         false
46581     ],
46582     "Unlicense": [
46583         "The Unlicense",
46584         false
46585     ],
46586     "UPL-1.0": [
46587         "Universal Permissive License v1.0",
46588         true
46589     ],
46590     "Vim": [
46591         "Vim License",
46592         false
46593     ],
46594     "VOSTROM": [
46595         "VOSTROM Public License for Open Source",
46596         false
46597     ],
46598     "VSL-1.0": [
46599         "Vovida Software License v1.0",
46600         true
46601     ],
46602     "W3C": [
46603         "W3C Software Notice and License (2002-12-31)",
46604         true
46605     ],
46606     "W3C-19980720": [
46607         "W3C Software Notice and License (1998-07-20)",
46608         false
46609     ],
46610     "W3C-20150513": [
46611         "W3C Software Notice and Document License (2015-05-13)",
46612         false
46613     ],
46614     "Watcom-1.0": [
46615         "Sybase Open Watcom Public License 1.0",
46616         true
46617     ],
46618     "Wsuipa": [
46619         "Wsuipa License",
46620         false
46621     ],
46622     "WTFPL": [
46623         "Do What The F*ck You Want To Public License",
46624         false
46625     ],
46626     "X11": [
46627         "X11 License",
46628         false
46629     ],
46630     "Xerox": [
46631         "Xerox License",
46632         false
46633     ],
46634     "XFree86-1.1": [
46635         "XFree86 License 1.1",
46636         false
46637     ],
46638     "xinetd": [
46639         "xinetd License",
46640         false
46641     ],
46642     "Xnet": [
46643         "X.Net License",
46644         true
46645     ],
46646     "xpp": [
46647         "XPP License",
46648         false
46649     ],
46650     "XSkat": [
46651         "XSkat License",
46652         false
46653     ],
46654     "YPL-1.0": [
46655         "Yahoo! Public License v1.0",
46656         false
46657     ],
46658     "YPL-1.1": [
46659         "Yahoo! Public License v1.1",
46660         false
46661     ],
46662     "Zed": [
46663         "Zed License",
46664         false
46665     ],
46666     "Zend-2.0": [
46667         "Zend License v2.0",
46668         false
46669     ],
46670     "Zimbra-1.3": [
46671         "Zimbra Public License v1.3",
46672         false
46673     ],
46674     "Zimbra-1.4": [
46675         "Zimbra Public License v1.4",
46676         false
46677     ],
46678     "Zlib": [
46679         "zlib License",
46680         true
46681     ],
46682     "zlib-acknowledgement": [
46683         "zlib/libpng License with Acknowledgement",
46684         false
46685     ],
46686     "ZPL-1.1": [
46687         "Zope Public License 1.1",
46688         false
46689     ],
46690     "ZPL-2.0": [
46691         "Zope Public License 2.0",
46692         true
46693     ],
46694     "ZPL-2.1": [
46695         "Zope Public License 2.1",
46696         false
46697     ]
46698 }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
46699 $\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
46700 \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
46701 \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
46702 \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
46703 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
46704 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
46705 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
46706   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">\r
46707     <security>\r
46708       <requestedPrivileges>\r
46709         <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>\r
46710       </requestedPrivileges>\r
46711     </security>\r
46712   </trustInfo>\r
46713   <dependency>\r
46714     <dependentAssembly>\r
46715       <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>\r
46716     </dependentAssembly>\r
46717   </dependency>\r
46718 </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
46719
46720
46721
46722
46723
46724
46725
46726
46727
46728
46729 namespace Symfony\Component\Console;
46730
46731 use Symfony\Component\Console\Descriptor\TextDescriptor;
46732 use Symfony\Component\Console\Descriptor\XmlDescriptor;
46733 use Symfony\Component\Console\Exception\ExceptionInterface;
46734 use Symfony\Component\Console\Formatter\OutputFormatter;
46735 use Symfony\Component\Console\Helper\DebugFormatterHelper;
46736 use Symfony\Component\Console\Helper\Helper;
46737 use Symfony\Component\Console\Helper\ProcessHelper;
46738 use Symfony\Component\Console\Helper\QuestionHelper;
46739 use Symfony\Component\Console\Input\InputInterface;
46740 use Symfony\Component\Console\Input\ArgvInput;
46741 use Symfony\Component\Console\Input\ArrayInput;
46742 use Symfony\Component\Console\Input\InputDefinition;
46743 use Symfony\Component\Console\Input\InputOption;
46744 use Symfony\Component\Console\Input\InputArgument;
46745 use Symfony\Component\Console\Input\InputAwareInterface;
46746 use Symfony\Component\Console\Output\BufferedOutput;
46747 use Symfony\Component\Console\Output\OutputInterface;
46748 use Symfony\Component\Console\Output\ConsoleOutput;
46749 use Symfony\Component\Console\Output\ConsoleOutputInterface;
46750 use Symfony\Component\Console\Command\Command;
46751 use Symfony\Component\Console\Command\HelpCommand;
46752 use Symfony\Component\Console\Command\ListCommand;
46753 use Symfony\Component\Console\Helper\HelperSet;
46754 use Symfony\Component\Console\Helper\FormatterHelper;
46755 use Symfony\Component\Console\Helper\DialogHelper;
46756 use Symfony\Component\Console\Helper\ProgressHelper;
46757 use Symfony\Component\Console\Helper\TableHelper;
46758 use Symfony\Component\Console\Event\ConsoleCommandEvent;
46759 use Symfony\Component\Console\Event\ConsoleExceptionEvent;
46760 use Symfony\Component\Console\Event\ConsoleTerminateEvent;
46761 use Symfony\Component\Console\Exception\CommandNotFoundException;
46762 use Symfony\Component\Console\Exception\LogicException;
46763 use Symfony\Component\Debug\Exception\FatalThrowableError;
46764 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
46765
46766
46767
46768
46769
46770
46771
46772
46773
46774
46775
46776
46777
46778
46779
46780
46781 class Application
46782 {
46783 private $commands = array();
46784 private $wantHelps = false;
46785 private $runningCommand;
46786 private $name;
46787 private $version;
46788 private $catchExceptions = true;
46789 private $autoExit = true;
46790 private $definition;
46791 private $helperSet;
46792 private $dispatcher;
46793 private $terminalDimensions;
46794 private $defaultCommand;
46795
46796
46797
46798
46799
46800
46801
46802 public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
46803 {
46804 $this->name = $name;
46805 $this->version = $version;
46806 $this->defaultCommand = 'list';
46807 $this->helperSet = $this->getDefaultHelperSet();
46808 $this->definition = $this->getDefaultInputDefinition();
46809
46810 foreach ($this->getDefaultCommands() as $command) {
46811 $this->add($command);
46812 }
46813 }
46814
46815 public function setDispatcher(EventDispatcherInterface $dispatcher)
46816 {
46817 $this->dispatcher = $dispatcher;
46818 }
46819
46820
46821
46822
46823
46824
46825
46826
46827
46828
46829
46830 public function run(InputInterface $input = null, OutputInterface $output = null)
46831 {
46832 if (null === $input) {
46833 $input = new ArgvInput();
46834 }
46835
46836 if (null === $output) {
46837 $output = new ConsoleOutput();
46838 }
46839
46840 $this->configureIO($input, $output);
46841
46842 try {
46843 $e = null;
46844 $exitCode = $this->doRun($input, $output);
46845 } catch (\Exception $x) {
46846 $e = $x;
46847 } catch (\Throwable $x) {
46848 $e = new FatalThrowableError($x);
46849 }
46850
46851 if (null !== $e) {
46852 if (!$this->catchExceptions || !$x instanceof \Exception) {
46853 throw $x;
46854 }
46855
46856 if ($output instanceof ConsoleOutputInterface) {
46857 $this->renderException($e, $output->getErrorOutput());
46858 } else {
46859 $this->renderException($e, $output);
46860 }
46861
46862 $exitCode = $e->getCode();
46863 if (is_numeric($exitCode)) {
46864 $exitCode = (int) $exitCode;
46865 if (0 === $exitCode) {
46866 $exitCode = 1;
46867 }
46868 } else {
46869 $exitCode = 1;
46870 }
46871 }
46872
46873 if ($this->autoExit) {
46874 if ($exitCode > 255) {
46875 $exitCode = 255;
46876 }
46877
46878 exit($exitCode);
46879 }
46880
46881 return $exitCode;
46882 }
46883
46884
46885
46886
46887
46888
46889
46890
46891
46892 public function doRun(InputInterface $input, OutputInterface $output)
46893 {
46894 if (true === $input->hasParameterOption(array('--version', '-V'))) {
46895 $output->writeln($this->getLongVersion());
46896
46897 return 0;
46898 }
46899
46900 $name = $this->getCommandName($input);
46901 if (true === $input->hasParameterOption(array('--help', '-h'))) {
46902 if (!$name) {
46903 $name = 'help';
46904 $input = new ArrayInput(array('command' => 'help'));
46905 } else {
46906 $this->wantHelps = true;
46907 }
46908 }
46909
46910 if (!$name) {
46911 $name = $this->defaultCommand;
46912 $this->definition->setArguments(array_merge(
46913 $this->definition->getArguments(),
46914 array(
46915 'command' => new InputArgument('command', InputArgument::OPTIONAL, $this->definition->getArgument('command')->getDescription(), $name),
46916 )
46917 ));
46918 }
46919
46920 $this->runningCommand = null;
46921
46922  $command = $this->find($name);
46923
46924 $this->runningCommand = $command;
46925 $exitCode = $this->doRunCommand($command, $input, $output);
46926 $this->runningCommand = null;
46927
46928 return $exitCode;
46929 }
46930
46931
46932
46933
46934
46935
46936 public function setHelperSet(HelperSet $helperSet)
46937 {
46938 $this->helperSet = $helperSet;
46939 }
46940
46941
46942
46943
46944
46945
46946 public function getHelperSet()
46947 {
46948 return $this->helperSet;
46949 }
46950
46951
46952
46953
46954
46955
46956 public function setDefinition(InputDefinition $definition)
46957 {
46958 $this->definition = $definition;
46959 }
46960
46961
46962
46963
46964
46965
46966 public function getDefinition()
46967 {
46968 return $this->definition;
46969 }
46970
46971
46972
46973
46974
46975
46976 public function getHelp()
46977 {
46978 return $this->getLongVersion();
46979 }
46980
46981
46982
46983
46984
46985
46986 public function setCatchExceptions($boolean)
46987 {
46988 $this->catchExceptions = (bool) $boolean;
46989 }
46990
46991
46992
46993
46994
46995
46996 public function setAutoExit($boolean)
46997 {
46998 $this->autoExit = (bool) $boolean;
46999 }
47000
47001
47002
47003
47004
47005
47006 public function getName()
47007 {
47008 return $this->name;
47009 }
47010
47011
47012
47013
47014
47015
47016 public function setName($name)
47017 {
47018 $this->name = $name;
47019 }
47020
47021
47022
47023
47024
47025
47026 public function getVersion()
47027 {
47028 return $this->version;
47029 }
47030
47031
47032
47033
47034
47035
47036 public function setVersion($version)
47037 {
47038 $this->version = $version;
47039 }
47040
47041
47042
47043
47044
47045
47046 public function getLongVersion()
47047 {
47048 if ('UNKNOWN' !== $this->getName()) {
47049 if ('UNKNOWN' !== $this->getVersion()) {
47050 return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
47051 }
47052
47053 return sprintf('<info>%s</info>', $this->getName());
47054 }
47055
47056 return '<info>Console Tool</info>';
47057 }
47058
47059
47060
47061
47062
47063
47064
47065
47066 public function register($name)
47067 {
47068 return $this->add(new Command($name));
47069 }
47070
47071
47072
47073
47074
47075
47076
47077
47078 public function addCommands(array $commands)
47079 {
47080 foreach ($commands as $command) {
47081 $this->add($command);
47082 }
47083 }
47084
47085
47086
47087
47088
47089
47090
47091
47092
47093
47094
47095 public function add(Command $command)
47096 {
47097 $command->setApplication($this);
47098
47099 if (!$command->isEnabled()) {
47100 $command->setApplication(null);
47101
47102 return;
47103 }
47104
47105 if (null === $command->getDefinition()) {
47106 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
47107 }
47108
47109 $this->commands[$command->getName()] = $command;
47110
47111 foreach ($command->getAliases() as $alias) {
47112 $this->commands[$alias] = $command;
47113 }
47114
47115 return $command;
47116 }
47117
47118
47119
47120
47121
47122
47123
47124
47125
47126
47127 public function get($name)
47128 {
47129 if (!isset($this->commands[$name])) {
47130 throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
47131 }
47132
47133 $command = $this->commands[$name];
47134
47135 if ($this->wantHelps) {
47136 $this->wantHelps = false;
47137
47138 $helpCommand = $this->get('help');
47139 $helpCommand->setCommand($command);
47140
47141 return $helpCommand;
47142 }
47143
47144 return $command;
47145 }
47146
47147
47148
47149
47150
47151
47152
47153
47154 public function has($name)
47155 {
47156 return isset($this->commands[$name]);
47157 }
47158
47159
47160
47161
47162
47163
47164
47165
47166 public function getNamespaces()
47167 {
47168 $namespaces = array();
47169 foreach ($this->all() as $command) {
47170 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
47171
47172 foreach ($command->getAliases() as $alias) {
47173 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
47174 }
47175 }
47176
47177 return array_values(array_unique(array_filter($namespaces)));
47178 }
47179
47180
47181
47182
47183
47184
47185
47186
47187
47188
47189 public function findNamespace($namespace)
47190 {
47191 $allNamespaces = $this->getNamespaces();
47192 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
47193 $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
47194
47195 if (empty($namespaces)) {
47196 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
47197
47198 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
47199 if (1 == count($alternatives)) {
47200 $message .= "\n\nDid you mean this?\n    ";
47201 } else {
47202 $message .= "\n\nDid you mean one of these?\n    ";
47203 }
47204
47205 $message .= implode("\n    ", $alternatives);
47206 }
47207
47208 throw new CommandNotFoundException($message, $alternatives);
47209 }
47210
47211 $exact = in_array($namespace, $namespaces, true);
47212 if (count($namespaces) > 1 && !$exact) {
47213 throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
47214 }
47215
47216 return $exact ? $namespace : reset($namespaces);
47217 }
47218
47219
47220
47221
47222
47223
47224
47225
47226
47227
47228
47229
47230
47231 public function find($name)
47232 {
47233 $allCommands = array_keys($this->commands);
47234 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
47235 $commands = preg_grep('{^'.$expr.'}', $allCommands);
47236
47237 if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
47238 if (false !== $pos = strrpos($name, ':')) {
47239
47240  $this->findNamespace(substr($name, 0, $pos));
47241 }
47242
47243 $message = sprintf('Command "%s" is not defined.', $name);
47244
47245 if ($alternatives = $this->findAlternatives($name, $allCommands)) {
47246 if (1 == count($alternatives)) {
47247 $message .= "\n\nDid you mean this?\n    ";
47248 } else {
47249 $message .= "\n\nDid you mean one of these?\n    ";
47250 }
47251 $message .= implode("\n    ", $alternatives);
47252 }
47253
47254 throw new CommandNotFoundException($message, $alternatives);
47255 }
47256
47257
47258  if (count($commands) > 1) {
47259 $commandList = $this->commands;
47260 $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
47261 $commandName = $commandList[$nameOrAlias]->getName();
47262
47263 return $commandName === $nameOrAlias || !in_array($commandName, $commands);
47264 });
47265 }
47266
47267 $exact = in_array($name, $commands, true);
47268 if (count($commands) > 1 && !$exact) {
47269 $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
47270
47271 throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
47272 }
47273
47274 return $this->get($exact ? $name : reset($commands));
47275 }
47276
47277
47278
47279
47280
47281
47282
47283
47284
47285
47286 public function all($namespace = null)
47287 {
47288 if (null === $namespace) {
47289 return $this->commands;
47290 }
47291
47292 $commands = array();
47293 foreach ($this->commands as $name => $command) {
47294 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
47295 $commands[$name] = $command;
47296 }
47297 }
47298
47299 return $commands;
47300 }
47301
47302
47303
47304
47305
47306
47307
47308
47309 public static function getAbbreviations($names)
47310 {
47311 $abbrevs = array();
47312 foreach ($names as $name) {
47313 for ($len = strlen($name); $len > 0; --$len) {
47314 $abbrev = substr($name, 0, $len);
47315 $abbrevs[$abbrev][] = $name;
47316 }
47317 }
47318
47319 return $abbrevs;
47320 }
47321
47322
47323
47324
47325
47326
47327
47328
47329
47330
47331
47332 public function asText($namespace = null, $raw = false)
47333 {
47334 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
47335
47336 $descriptor = new TextDescriptor();
47337 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
47338 $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
47339
47340 return $output->fetch();
47341 }
47342
47343
47344
47345
47346
47347
47348
47349
47350
47351
47352
47353 public function asXml($namespace = null, $asDom = false)
47354 {
47355 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
47356
47357 $descriptor = new XmlDescriptor();
47358
47359 if ($asDom) {
47360 return $descriptor->getApplicationDocument($this, $namespace);
47361 }
47362
47363 $output = new BufferedOutput();
47364 $descriptor->describe($output, $this, array('namespace' => $namespace));
47365
47366 return $output->fetch();
47367 }
47368
47369
47370
47371
47372
47373
47374
47375 public function renderException($e, $output)
47376 {
47377 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
47378
47379 do {
47380 $title = sprintf('  [%s]  ', get_class($e));
47381
47382 $len = Helper::strlen($title);
47383
47384 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
47385
47386  if (defined('HHVM_VERSION') && $width > 1 << 31) {
47387 $width = 1 << 31;
47388 }
47389 $lines = array();
47390 foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
47391 foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
47392
47393  $lineLength = Helper::strlen($line) + 4;
47394 $lines[] = array($line, $lineLength);
47395
47396 $len = max($lineLength, $len);
47397 }
47398 }
47399
47400 $messages = array();
47401 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
47402 $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
47403 foreach ($lines as $line) {
47404 $messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
47405 }
47406 $messages[] = $emptyLine;
47407 $messages[] = '';
47408
47409 $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
47410
47411 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
47412 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
47413
47414
47415  $trace = $e->getTrace();
47416 array_unshift($trace, array(
47417 'function' => '',
47418 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a',
47419 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a',
47420 'args' => array(),
47421 ));
47422
47423 for ($i = 0, $count = count($trace); $i < $count; ++$i) {
47424 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
47425 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
47426 $function = $trace[$i]['function'];
47427 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
47428 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
47429
47430 $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
47431 }
47432
47433 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
47434 }
47435 } while ($e = $e->getPrevious());
47436
47437 if (null !== $this->runningCommand) {
47438 $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
47439 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
47440 }
47441 }
47442
47443
47444
47445
47446
47447
47448 protected function getTerminalWidth()
47449 {
47450 $dimensions = $this->getTerminalDimensions();
47451
47452 return $dimensions[0];
47453 }
47454
47455
47456
47457
47458
47459
47460 protected function getTerminalHeight()
47461 {
47462 $dimensions = $this->getTerminalDimensions();
47463
47464 return $dimensions[1];
47465 }
47466
47467
47468
47469
47470
47471
47472 public function getTerminalDimensions()
47473 {
47474 if ($this->terminalDimensions) {
47475 return $this->terminalDimensions;
47476 }
47477
47478 if ('\\' === DIRECTORY_SEPARATOR) {
47479
47480  if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
47481 return array((int) $matches[1], (int) $matches[2]);
47482 }
47483
47484  if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
47485 return array((int) $matches[1], (int) $matches[2]);
47486 }
47487 }
47488
47489 if ($sttyString = $this->getSttyColumns()) {
47490
47491  if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
47492 return array((int) $matches[2], (int) $matches[1]);
47493 }
47494
47495  if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
47496 return array((int) $matches[2], (int) $matches[1]);
47497 }
47498 }
47499
47500 return array(null, null);
47501 }
47502
47503
47504
47505
47506
47507
47508
47509
47510
47511
47512
47513 public function setTerminalDimensions($width, $height)
47514 {
47515 $this->terminalDimensions = array($width, $height);
47516
47517 return $this;
47518 }
47519
47520
47521
47522
47523
47524
47525
47526 protected function configureIO(InputInterface $input, OutputInterface $output)
47527 {
47528 if (true === $input->hasParameterOption(array('--ansi'))) {
47529 $output->setDecorated(true);
47530 } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
47531 $output->setDecorated(false);
47532 }
47533
47534 if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
47535 $input->setInteractive(false);
47536 } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
47537 $inputStream = $this->getHelperSet()->get('question')->getInputStream();
47538 if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
47539 $input->setInteractive(false);
47540 }
47541 }
47542
47543 if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
47544 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
47545 $input->setInteractive(false);
47546 } else {
47547 if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
47548 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
47549 } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
47550 $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
47551 } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
47552 $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
47553 }
47554 }
47555 }
47556
47557
47558
47559
47560
47561
47562
47563
47564
47565
47566
47567
47568
47569 protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
47570 {
47571 foreach ($command->getHelperSet() as $helper) {
47572 if ($helper instanceof InputAwareInterface) {
47573 $helper->setInput($input);
47574 }
47575 }
47576
47577 if (null === $this->dispatcher) {
47578 return $command->run($input, $output);
47579 }
47580
47581
47582  try {
47583 $command->mergeApplicationDefinition();
47584 $input->bind($command->getDefinition());
47585 } catch (ExceptionInterface $e) {
47586
47587  }
47588
47589 $event = new ConsoleCommandEvent($command, $input, $output);
47590 $e = null;
47591
47592 try {
47593 $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
47594
47595 if ($event->commandShouldRun()) {
47596 $exitCode = $command->run($input, $output);
47597 } else {
47598 $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
47599 }
47600 } catch (\Exception $e) {
47601 } catch (\Throwable $e) {
47602 }
47603 if (null !== $e) {
47604 $x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
47605 $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
47606 $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
47607
47608 if ($x !== $event->getException()) {
47609 $e = $event->getException();
47610 }
47611 $exitCode = $e->getCode();
47612 }
47613
47614 $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
47615 $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
47616
47617 if (null !== $e) {
47618 throw $e;
47619 }
47620
47621 return $event->getExitCode();
47622 }
47623
47624
47625
47626
47627
47628
47629
47630
47631 protected function getCommandName(InputInterface $input)
47632 {
47633 return $input->getFirstArgument();
47634 }
47635
47636
47637
47638
47639
47640
47641 protected function getDefaultInputDefinition()
47642 {
47643 return new InputDefinition(array(
47644 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
47645
47646 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
47647 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
47648 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'),
47649 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
47650 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
47651 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
47652 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
47653 ));
47654 }
47655
47656
47657
47658
47659
47660
47661 protected function getDefaultCommands()
47662 {
47663 return array(new HelpCommand(), new ListCommand());
47664 }
47665
47666
47667
47668
47669
47670
47671 protected function getDefaultHelperSet()
47672 {
47673 return new HelperSet(array(
47674 new FormatterHelper(),
47675 new DialogHelper(false),
47676 new ProgressHelper(false),
47677 new TableHelper(false),
47678 new DebugFormatterHelper(),
47679 new ProcessHelper(),
47680 new QuestionHelper(),
47681 ));
47682 }
47683
47684
47685
47686
47687
47688
47689 private function getSttyColumns()
47690 {
47691 if (!function_exists('proc_open')) {
47692 return;
47693 }
47694
47695 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
47696 $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
47697 if (is_resource($process)) {
47698 $info = stream_get_contents($pipes[1]);
47699 fclose($pipes[1]);
47700 fclose($pipes[2]);
47701 proc_close($process);
47702
47703 return $info;
47704 }
47705 }
47706
47707
47708
47709
47710
47711
47712 private function getConsoleMode()
47713 {
47714 if (!function_exists('proc_open')) {
47715 return;
47716 }
47717
47718 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
47719 $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
47720 if (is_resource($process)) {
47721 $info = stream_get_contents($pipes[1]);
47722 fclose($pipes[1]);
47723 fclose($pipes[2]);
47724 proc_close($process);
47725
47726 if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
47727 return $matches[2].'x'.$matches[1];
47728 }
47729 }
47730 }
47731
47732
47733
47734
47735
47736
47737
47738
47739 private function getAbbreviationSuggestions($abbrevs)
47740 {
47741 return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
47742 }
47743
47744
47745
47746
47747
47748
47749
47750
47751
47752
47753
47754 public function extractNamespace($name, $limit = null)
47755 {
47756 $parts = explode(':', $name);
47757 array_pop($parts);
47758
47759 return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
47760 }
47761
47762
47763
47764
47765
47766
47767
47768
47769
47770
47771 private function findAlternatives($name, $collection)
47772 {
47773 $threshold = 1e3;
47774 $alternatives = array();
47775
47776 $collectionParts = array();
47777 foreach ($collection as $item) {
47778 $collectionParts[$item] = explode(':', $item);
47779 }
47780
47781 foreach (explode(':', $name) as $i => $subname) {
47782 foreach ($collectionParts as $collectionName => $parts) {
47783 $exists = isset($alternatives[$collectionName]);
47784 if (!isset($parts[$i]) && $exists) {
47785 $alternatives[$collectionName] += $threshold;
47786 continue;
47787 } elseif (!isset($parts[$i])) {
47788 continue;
47789 }
47790
47791 $lev = levenshtein($subname, $parts[$i]);
47792 if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
47793 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
47794 } elseif ($exists) {
47795 $alternatives[$collectionName] += $threshold;
47796 }
47797 }
47798 }
47799
47800 foreach ($collection as $item) {
47801 $lev = levenshtein($name, $item);
47802 if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
47803 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
47804 }
47805 }
47806
47807 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
47808 asort($alternatives);
47809
47810 return array_keys($alternatives);
47811 }
47812
47813
47814
47815
47816
47817
47818 public function setDefaultCommand($commandName)
47819 {
47820 $this->defaultCommand = $commandName;
47821 }
47822
47823 private function splitStringByWidth($string, $width)
47824 {
47825
47826  
47827  
47828  if (false === $encoding = mb_detect_encoding($string, null, true)) {
47829 return str_split($string, $width);
47830 }
47831
47832 $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
47833 $lines = array();
47834 $line = '';
47835 foreach (preg_split('//u', $utf8String) as $char) {
47836
47837  if (mb_strwidth($line.$char, 'utf8') <= $width) {
47838 $line .= $char;
47839 continue;
47840 }
47841
47842  $lines[] = str_pad($line, $width);
47843 $line = $char;
47844 }
47845 if ('' !== $line) {
47846 $lines[] = count($lines) ? str_pad($line, $width) : $line;
47847 }
47848
47849 mb_convert_variables($encoding, 'utf8', $lines);
47850
47851 return $lines;
47852 }
47853
47854
47855
47856
47857
47858
47859
47860
47861 private function extractAllNamespaces($name)
47862 {
47863
47864  $parts = explode(':', $name, -1);
47865 $namespaces = array();
47866
47867 foreach ($parts as $part) {
47868 if (count($namespaces)) {
47869 $namespaces[] = end($namespaces).':'.$part;
47870 } else {
47871 $namespaces[] = $part;
47872 }
47873 }
47874
47875 return $namespaces;
47876 }
47877 }
47878 <?php
47879
47880
47881
47882
47883
47884
47885
47886
47887
47888
47889 namespace Symfony\Component\Console\Command;
47890
47891 use Symfony\Component\Console\Descriptor\TextDescriptor;
47892 use Symfony\Component\Console\Descriptor\XmlDescriptor;
47893 use Symfony\Component\Console\Exception\ExceptionInterface;
47894 use Symfony\Component\Console\Input\InputDefinition;
47895 use Symfony\Component\Console\Input\InputOption;
47896 use Symfony\Component\Console\Input\InputArgument;
47897 use Symfony\Component\Console\Input\InputInterface;
47898 use Symfony\Component\Console\Output\BufferedOutput;
47899 use Symfony\Component\Console\Output\OutputInterface;
47900 use Symfony\Component\Console\Application;
47901 use Symfony\Component\Console\Helper\HelperSet;
47902 use Symfony\Component\Console\Exception\InvalidArgumentException;
47903 use Symfony\Component\Console\Exception\LogicException;
47904
47905
47906
47907
47908
47909
47910 class Command
47911 {
47912 private $application;
47913 private $name;
47914 private $processTitle;
47915 private $aliases = array();
47916 private $definition;
47917 private $help;
47918 private $description;
47919 private $ignoreValidationErrors = false;
47920 private $applicationDefinitionMerged = false;
47921 private $applicationDefinitionMergedWithArgs = false;
47922 private $code;
47923 private $synopsis = array();
47924 private $usages = array();
47925 private $helperSet;
47926
47927
47928
47929
47930
47931
47932
47933
47934 public function __construct($name = null)
47935 {
47936 $this->definition = new InputDefinition();
47937
47938 if (null !== $name) {
47939 $this->setName($name);
47940 }
47941
47942 $this->configure();
47943
47944 if (!$this->name) {
47945 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
47946 }
47947 }
47948
47949
47950
47951
47952
47953
47954 public function ignoreValidationErrors()
47955 {
47956 $this->ignoreValidationErrors = true;
47957 }
47958
47959
47960
47961
47962
47963
47964 public function setApplication(Application $application = null)
47965 {
47966 $this->application = $application;
47967 if ($application) {
47968 $this->setHelperSet($application->getHelperSet());
47969 } else {
47970 $this->helperSet = null;
47971 }
47972 }
47973
47974
47975
47976
47977
47978
47979 public function setHelperSet(HelperSet $helperSet)
47980 {
47981 $this->helperSet = $helperSet;
47982 }
47983
47984
47985
47986
47987
47988
47989 public function getHelperSet()
47990 {
47991 return $this->helperSet;
47992 }
47993
47994
47995
47996
47997
47998
47999 public function getApplication()
48000 {
48001 return $this->application;
48002 }
48003
48004
48005
48006
48007
48008
48009
48010
48011
48012 public function isEnabled()
48013 {
48014 return true;
48015 }
48016
48017
48018
48019
48020 protected function configure()
48021 {
48022 }
48023
48024
48025
48026
48027
48028
48029
48030
48031
48032
48033
48034
48035
48036
48037
48038
48039
48040
48041 protected function execute(InputInterface $input, OutputInterface $output)
48042 {
48043 throw new LogicException('You must override the execute() method in the concrete command class.');
48044 }
48045
48046
48047
48048
48049
48050
48051
48052
48053
48054
48055
48056 protected function interact(InputInterface $input, OutputInterface $output)
48057 {
48058 }
48059
48060
48061
48062
48063
48064
48065
48066
48067
48068
48069 protected function initialize(InputInterface $input, OutputInterface $output)
48070 {
48071 }
48072
48073
48074
48075
48076
48077
48078
48079
48080
48081
48082
48083
48084
48085
48086
48087
48088
48089
48090 public function run(InputInterface $input, OutputInterface $output)
48091 {
48092
48093  $this->getSynopsis(true);
48094 $this->getSynopsis(false);
48095
48096
48097  $this->mergeApplicationDefinition();
48098
48099
48100  try {
48101 $input->bind($this->definition);
48102 } catch (ExceptionInterface $e) {
48103 if (!$this->ignoreValidationErrors) {
48104 throw $e;
48105 }
48106 }
48107
48108 $this->initialize($input, $output);
48109
48110 if (null !== $this->processTitle) {
48111 if (function_exists('cli_set_process_title')) {
48112 if (false === @cli_set_process_title($this->processTitle)) {
48113 if ('Darwin' === PHP_OS) {
48114 $output->writeln('<comment>Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.</comment>');
48115 } else {
48116 $error = error_get_last();
48117 trigger_error($error['message'], E_USER_WARNING);
48118 }
48119 }
48120 } elseif (function_exists('setproctitle')) {
48121 setproctitle($this->processTitle);
48122 } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
48123 $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
48124 }
48125 }
48126
48127 if ($input->isInteractive()) {
48128 $this->interact($input, $output);
48129 }
48130
48131
48132  
48133  
48134  if ($input->hasArgument('command') && null === $input->getArgument('command')) {
48135 $input->setArgument('command', $this->getName());
48136 }
48137
48138 $input->validate();
48139
48140 if ($this->code) {
48141 $statusCode = call_user_func($this->code, $input, $output);
48142 } else {
48143 $statusCode = $this->execute($input, $output);
48144 }
48145
48146 return is_numeric($statusCode) ? (int) $statusCode : 0;
48147 }
48148
48149
48150
48151
48152
48153
48154
48155
48156
48157
48158
48159
48160
48161
48162
48163 public function setCode($code)
48164 {
48165 if (!is_callable($code)) {
48166 throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
48167 }
48168
48169 if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
48170 $r = new \ReflectionFunction($code);
48171 if (null === $r->getClosureThis()) {
48172 if (PHP_VERSION_ID < 70000) {
48173
48174  
48175  
48176  
48177  $code = @\Closure::bind($code, $this);
48178 } else {
48179 $code = \Closure::bind($code, $this);
48180 }
48181 }
48182 }
48183
48184 $this->code = $code;
48185
48186 return $this;
48187 }
48188
48189
48190
48191
48192
48193
48194
48195
48196 public function mergeApplicationDefinition($mergeArgs = true)
48197 {
48198 if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
48199 return;
48200 }
48201
48202 $this->definition->addOptions($this->application->getDefinition()->getOptions());
48203
48204 if ($mergeArgs) {
48205 $currentArguments = $this->definition->getArguments();
48206 $this->definition->setArguments($this->application->getDefinition()->getArguments());
48207 $this->definition->addArguments($currentArguments);
48208 }
48209
48210 $this->applicationDefinitionMerged = true;
48211 if ($mergeArgs) {
48212 $this->applicationDefinitionMergedWithArgs = true;
48213 }
48214 }
48215
48216
48217
48218
48219
48220
48221
48222
48223 public function setDefinition($definition)
48224 {
48225 if ($definition instanceof InputDefinition) {
48226 $this->definition = $definition;
48227 } else {
48228 $this->definition->setDefinition($definition);
48229 }
48230
48231 $this->applicationDefinitionMerged = false;
48232
48233 return $this;
48234 }
48235
48236
48237
48238
48239
48240
48241 public function getDefinition()
48242 {
48243 return $this->definition;
48244 }
48245
48246
48247
48248
48249
48250
48251
48252
48253
48254
48255
48256 public function getNativeDefinition()
48257 {
48258 return $this->getDefinition();
48259 }
48260
48261
48262
48263
48264
48265
48266
48267
48268
48269
48270
48271 public function addArgument($name, $mode = null, $description = '', $default = null)
48272 {
48273 $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
48274
48275 return $this;
48276 }
48277
48278
48279
48280
48281
48282
48283
48284
48285
48286
48287
48288
48289 public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
48290 {
48291 $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
48292
48293 return $this;
48294 }
48295
48296
48297
48298
48299
48300
48301
48302
48303
48304
48305
48306
48307
48308
48309
48310 public function setName($name)
48311 {
48312 $this->validateName($name);
48313
48314 $this->name = $name;
48315
48316 return $this;
48317 }
48318
48319
48320
48321
48322
48323
48324
48325
48326
48327
48328
48329
48330
48331 public function setProcessTitle($title)
48332 {
48333 $this->processTitle = $title;
48334
48335 return $this;
48336 }
48337
48338
48339
48340
48341
48342
48343 public function getName()
48344 {
48345 return $this->name;
48346 }
48347
48348
48349
48350
48351
48352
48353
48354
48355 public function setDescription($description)
48356 {
48357 $this->description = $description;
48358
48359 return $this;
48360 }
48361
48362
48363
48364
48365
48366
48367 public function getDescription()
48368 {
48369 return $this->description;
48370 }
48371
48372
48373
48374
48375
48376
48377
48378
48379 public function setHelp($help)
48380 {
48381 $this->help = $help;
48382
48383 return $this;
48384 }
48385
48386
48387
48388
48389
48390
48391 public function getHelp()
48392 {
48393 return $this->help;
48394 }
48395
48396
48397
48398
48399
48400
48401
48402 public function getProcessedHelp()
48403 {
48404 $name = $this->name;
48405
48406 $placeholders = array(
48407 '%command.name%',
48408 '%command.full_name%',
48409 );
48410 $replacements = array(
48411 $name,
48412 $_SERVER['PHP_SELF'].' '.$name,
48413 );
48414
48415 return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
48416 }
48417
48418
48419
48420
48421
48422
48423
48424
48425
48426
48427 public function setAliases($aliases)
48428 {
48429 if (!is_array($aliases) && !$aliases instanceof \Traversable) {
48430 throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
48431 }
48432
48433 foreach ($aliases as $alias) {
48434 $this->validateName($alias);
48435 }
48436
48437 $this->aliases = $aliases;
48438
48439 return $this;
48440 }
48441
48442
48443
48444
48445
48446
48447 public function getAliases()
48448 {
48449 return $this->aliases;
48450 }
48451
48452
48453
48454
48455
48456
48457
48458
48459 public function getSynopsis($short = false)
48460 {
48461 $key = $short ? 'short' : 'long';
48462
48463 if (!isset($this->synopsis[$key])) {
48464 $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
48465 }
48466
48467 return $this->synopsis[$key];
48468 }
48469
48470
48471
48472
48473
48474
48475
48476
48477 public function addUsage($usage)
48478 {
48479 if (0 !== strpos($usage, $this->name)) {
48480 $usage = sprintf('%s %s', $this->name, $usage);
48481 }
48482
48483 $this->usages[] = $usage;
48484
48485 return $this;
48486 }
48487
48488
48489
48490
48491
48492
48493 public function getUsages()
48494 {
48495 return $this->usages;
48496 }
48497
48498
48499
48500
48501
48502
48503
48504
48505
48506
48507
48508 public function getHelper($name)
48509 {
48510 if (null === $this->helperSet) {
48511 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));
48512 }
48513
48514 return $this->helperSet->get($name);
48515 }
48516
48517
48518
48519
48520
48521
48522
48523
48524 public function asText()
48525 {
48526 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
48527
48528 $descriptor = new TextDescriptor();
48529 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
48530 $descriptor->describe($output, $this, array('raw_output' => true));
48531
48532 return $output->fetch();
48533 }
48534
48535
48536
48537
48538
48539
48540
48541
48542
48543
48544 public function asXml($asDom = false)
48545 {
48546 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
48547
48548 $descriptor = new XmlDescriptor();
48549
48550 if ($asDom) {
48551 return $descriptor->getCommandDocument($this);
48552 }
48553
48554 $output = new BufferedOutput();
48555 $descriptor->describe($output, $this);
48556
48557 return $output->fetch();
48558 }
48559
48560
48561
48562
48563
48564
48565
48566
48567
48568
48569 private function validateName($name)
48570 {
48571 if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
48572 throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
48573 }
48574 }
48575 }
48576 <?php
48577
48578
48579
48580
48581
48582
48583
48584
48585
48586
48587 namespace Symfony\Component\Console\Command;
48588
48589 use Symfony\Component\Console\Helper\DescriptorHelper;
48590 use Symfony\Component\Console\Input\InputArgument;
48591 use Symfony\Component\Console\Input\InputOption;
48592 use Symfony\Component\Console\Input\InputInterface;
48593 use Symfony\Component\Console\Output\OutputInterface;
48594
48595
48596
48597
48598
48599
48600 class HelpCommand extends Command
48601 {
48602 private $command;
48603
48604
48605
48606
48607 protected function configure()
48608 {
48609 $this->ignoreValidationErrors();
48610
48611 $this
48612 ->setName('help')
48613 ->setDefinition(array(
48614 new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
48615 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
48616 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
48617 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
48618 ))
48619 ->setDescription('Displays help for a command')
48620 ->setHelp(<<<'EOF'
48621 The <info>%command.name%</info> command displays help for a given command:
48622
48623   <info>php %command.full_name% list</info>
48624
48625 You can also output the help in other formats by using the <comment>--format</comment> option:
48626
48627   <info>php %command.full_name% --format=xml list</info>
48628
48629 To display the list of available commands, please use the <info>list</info> command.
48630 EOF
48631 )
48632 ;
48633 }
48634
48635
48636
48637
48638
48639
48640 public function setCommand(Command $command)
48641 {
48642 $this->command = $command;
48643 }
48644
48645
48646
48647
48648 protected function execute(InputInterface $input, OutputInterface $output)
48649 {
48650 if (null === $this->command) {
48651 $this->command = $this->getApplication()->find($input->getArgument('command_name'));
48652 }
48653
48654 if ($input->getOption('xml')) {
48655 @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);
48656
48657 $input->setOption('format', 'xml');
48658 }
48659
48660 $helper = new DescriptorHelper();
48661 $helper->describe($output, $this->command, array(
48662 'format' => $input->getOption('format'),
48663 'raw_text' => $input->getOption('raw'),
48664 ));
48665
48666 $this->command = null;
48667 }
48668 }
48669 <?php
48670
48671
48672
48673
48674
48675
48676
48677
48678
48679
48680 namespace Symfony\Component\Console\Command;
48681
48682 use Symfony\Component\Console\Helper\DescriptorHelper;
48683 use Symfony\Component\Console\Input\InputArgument;
48684 use Symfony\Component\Console\Input\InputOption;
48685 use Symfony\Component\Console\Input\InputInterface;
48686 use Symfony\Component\Console\Output\OutputInterface;
48687 use Symfony\Component\Console\Input\InputDefinition;
48688
48689
48690
48691
48692
48693
48694 class ListCommand extends Command
48695 {
48696
48697
48698
48699 protected function configure()
48700 {
48701 $this
48702 ->setName('list')
48703 ->setDefinition($this->createDefinition())
48704 ->setDescription('Lists commands')
48705 ->setHelp(<<<'EOF'
48706 The <info>%command.name%</info> command lists all commands:
48707
48708   <info>php %command.full_name%</info>
48709
48710 You can also display the commands for a specific namespace:
48711
48712   <info>php %command.full_name% test</info>
48713
48714 You can also output the information in other formats by using the <comment>--format</comment> option:
48715
48716   <info>php %command.full_name% --format=xml</info>
48717
48718 It's also possible to get raw list of commands (useful for embedding command runner):
48719
48720   <info>php %command.full_name% --raw</info>
48721 EOF
48722 )
48723 ;
48724 }
48725
48726
48727
48728
48729 public function getNativeDefinition()
48730 {
48731 return $this->createDefinition();
48732 }
48733
48734
48735
48736
48737 protected function execute(InputInterface $input, OutputInterface $output)
48738 {
48739 if ($input->getOption('xml')) {
48740 @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);
48741
48742 $input->setOption('format', 'xml');
48743 }
48744
48745 $helper = new DescriptorHelper();
48746 $helper->describe($output, $this->getApplication(), array(
48747 'format' => $input->getOption('format'),
48748 'raw_text' => $input->getOption('raw'),
48749 'namespace' => $input->getArgument('namespace'),
48750 ));
48751 }
48752
48753
48754
48755
48756 private function createDefinition()
48757 {
48758 return new InputDefinition(array(
48759 new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
48760 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
48761 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
48762 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
48763 ));
48764 }
48765 }
48766 <?php
48767
48768
48769
48770
48771
48772
48773
48774
48775
48776
48777 namespace Symfony\Component\Console;
48778
48779
48780
48781
48782
48783
48784 final class ConsoleEvents
48785 {
48786
48787
48788
48789
48790
48791
48792
48793
48794
48795
48796
48797
48798 const COMMAND = 'console.command';
48799
48800
48801
48802
48803
48804
48805
48806
48807
48808
48809
48810
48811 const TERMINATE = 'console.terminate';
48812
48813
48814
48815
48816
48817
48818
48819
48820
48821
48822
48823
48824
48825 const EXCEPTION = 'console.exception';
48826 }
48827 <?php
48828
48829
48830
48831
48832
48833
48834
48835
48836
48837
48838 namespace Symfony\Component\Console\Descriptor;
48839
48840 use Symfony\Component\Console\Application;
48841 use Symfony\Component\Console\Command\Command;
48842 use Symfony\Component\Console\Exception\CommandNotFoundException;
48843
48844
48845
48846
48847
48848
48849 class ApplicationDescription
48850 {
48851 const GLOBAL_NAMESPACE = '_global';
48852
48853
48854
48855
48856 private $application;
48857
48858
48859
48860
48861 private $namespace;
48862
48863
48864
48865
48866 private $namespaces;
48867
48868
48869
48870
48871 private $commands;
48872
48873
48874
48875
48876 private $aliases;
48877
48878
48879
48880
48881
48882
48883
48884 public function __construct(Application $application, $namespace = null)
48885 {
48886 $this->application = $application;
48887 $this->namespace = $namespace;
48888 }
48889
48890
48891
48892
48893 public function getNamespaces()
48894 {
48895 if (null === $this->namespaces) {
48896 $this->inspectApplication();
48897 }
48898
48899 return $this->namespaces;
48900 }
48901
48902
48903
48904
48905 public function getCommands()
48906 {
48907 if (null === $this->commands) {
48908 $this->inspectApplication();
48909 }
48910
48911 return $this->commands;
48912 }
48913
48914
48915
48916
48917
48918
48919
48920
48921 public function getCommand($name)
48922 {
48923 if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
48924 throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
48925 }
48926
48927 return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
48928 }
48929
48930 private function inspectApplication()
48931 {
48932 $this->commands = array();
48933 $this->namespaces = array();
48934
48935 $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
48936 foreach ($this->sortCommands($all) as $namespace => $commands) {
48937 $names = array();
48938
48939
48940 foreach ($commands as $name => $command) {
48941 if (!$command->getName()) {
48942 continue;
48943 }
48944
48945 if ($command->getName() === $name) {
48946 $this->commands[$name] = $command;
48947 } else {
48948 $this->aliases[$name] = $command;
48949 }
48950
48951 $names[] = $name;
48952 }
48953
48954 $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
48955 }
48956 }
48957
48958
48959
48960
48961
48962
48963 private function sortCommands(array $commands)
48964 {
48965 $namespacedCommands = array();
48966 $globalCommands = array();
48967 foreach ($commands as $name => $command) {
48968 $key = $this->application->extractNamespace($name, 1);
48969 if (!$key) {
48970 $globalCommands['_global'][$name] = $command;
48971 } else {
48972 $namespacedCommands[$key][$name] = $command;
48973 }
48974 }
48975 ksort($namespacedCommands);
48976 $namespacedCommands = array_merge($globalCommands, $namespacedCommands);
48977
48978 foreach ($namespacedCommands as &$commandsSet) {
48979 ksort($commandsSet);
48980 }
48981
48982  unset($commandsSet);
48983
48984 return $namespacedCommands;
48985 }
48986 }
48987 <?php
48988
48989
48990
48991
48992
48993
48994
48995
48996
48997
48998 namespace Symfony\Component\Console\Descriptor;
48999
49000 use Symfony\Component\Console\Application;
49001 use Symfony\Component\Console\Command\Command;
49002 use Symfony\Component\Console\Input\InputArgument;
49003 use Symfony\Component\Console\Input\InputDefinition;
49004 use Symfony\Component\Console\Input\InputOption;
49005 use Symfony\Component\Console\Output\OutputInterface;
49006 use Symfony\Component\Console\Exception\InvalidArgumentException;
49007
49008
49009
49010
49011
49012
49013 abstract class Descriptor implements DescriptorInterface
49014 {
49015
49016
49017
49018 private $output;
49019
49020
49021
49022
49023 public function describe(OutputInterface $output, $object, array $options = array())
49024 {
49025 $this->output = $output;
49026
49027 switch (true) {
49028 case $object instanceof InputArgument:
49029 $this->describeInputArgument($object, $options);
49030 break;
49031 case $object instanceof InputOption:
49032 $this->describeInputOption($object, $options);
49033 break;
49034 case $object instanceof InputDefinition:
49035 $this->describeInputDefinition($object, $options);
49036 break;
49037 case $object instanceof Command:
49038 $this->describeCommand($object, $options);
49039 break;
49040 case $object instanceof Application:
49041 $this->describeApplication($object, $options);
49042 break;
49043 default:
49044 throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
49045 }
49046 }
49047
49048
49049
49050
49051
49052
49053
49054 protected function write($content, $decorated = false)
49055 {
49056 $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
49057 }
49058
49059
49060
49061
49062
49063
49064
49065
49066
49067 abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
49068
49069
49070
49071
49072
49073
49074
49075
49076
49077 abstract protected function describeInputOption(InputOption $option, array $options = array());
49078
49079
49080
49081
49082
49083
49084
49085
49086
49087 abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
49088
49089
49090
49091
49092
49093
49094
49095
49096
49097 abstract protected function describeCommand(Command $command, array $options = array());
49098
49099
49100
49101
49102
49103
49104
49105
49106
49107 abstract protected function describeApplication(Application $application, array $options = array());
49108 }
49109 <?php
49110
49111
49112
49113
49114
49115
49116
49117
49118
49119
49120 namespace Symfony\Component\Console\Descriptor;
49121
49122 use Symfony\Component\Console\Output\OutputInterface;
49123
49124
49125
49126
49127
49128
49129 interface DescriptorInterface
49130 {
49131
49132
49133
49134
49135
49136
49137
49138 public function describe(OutputInterface $output, $object, array $options = array());
49139 }
49140 <?php
49141
49142
49143
49144
49145
49146
49147
49148
49149
49150
49151 namespace Symfony\Component\Console\Descriptor;
49152
49153 use Symfony\Component\Console\Application;
49154 use Symfony\Component\Console\Command\Command;
49155 use Symfony\Component\Console\Input\InputArgument;
49156 use Symfony\Component\Console\Input\InputDefinition;
49157 use Symfony\Component\Console\Input\InputOption;
49158
49159
49160
49161
49162
49163
49164
49165
49166 class JsonDescriptor extends Descriptor
49167 {
49168
49169
49170
49171 protected function describeInputArgument(InputArgument $argument, array $options = array())
49172 {
49173 $this->writeData($this->getInputArgumentData($argument), $options);
49174 }
49175
49176
49177
49178
49179 protected function describeInputOption(InputOption $option, array $options = array())
49180 {
49181 $this->writeData($this->getInputOptionData($option), $options);
49182 }
49183
49184
49185
49186
49187 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
49188 {
49189 $this->writeData($this->getInputDefinitionData($definition), $options);
49190 }
49191
49192
49193
49194
49195 protected function describeCommand(Command $command, array $options = array())
49196 {
49197 $this->writeData($this->getCommandData($command), $options);
49198 }
49199
49200
49201
49202
49203 protected function describeApplication(Application $application, array $options = array())
49204 {
49205 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
49206 $description = new ApplicationDescription($application, $describedNamespace);
49207 $commands = array();
49208
49209 foreach ($description->getCommands() as $command) {
49210 $commands[] = $this->getCommandData($command);
49211 }
49212
49213 $data = $describedNamespace
49214 ? array('commands' => $commands, 'namespace' => $describedNamespace)
49215 : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
49216
49217 $this->writeData($data, $options);
49218 }
49219
49220
49221
49222
49223
49224
49225
49226
49227
49228 private function writeData(array $data, array $options)
49229 {
49230 $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
49231 }
49232
49233
49234
49235
49236
49237
49238 private function getInputArgumentData(InputArgument $argument)
49239 {
49240 return array(
49241 'name' => $argument->getName(),
49242 'is_required' => $argument->isRequired(),
49243 'is_array' => $argument->isArray(),
49244 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
49245 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
49246 );
49247 }
49248
49249
49250
49251
49252
49253
49254 private function getInputOptionData(InputOption $option)
49255 {
49256 return array(
49257 'name' => '--'.$option->getName(),
49258 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
49259 'accept_value' => $option->acceptValue(),
49260 'is_value_required' => $option->isValueRequired(),
49261 'is_multiple' => $option->isArray(),
49262 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
49263 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
49264 );
49265 }
49266
49267
49268
49269
49270
49271
49272 private function getInputDefinitionData(InputDefinition $definition)
49273 {
49274 $inputArguments = array();
49275 foreach ($definition->getArguments() as $name => $argument) {
49276 $inputArguments[$name] = $this->getInputArgumentData($argument);
49277 }
49278
49279 $inputOptions = array();
49280 foreach ($definition->getOptions() as $name => $option) {
49281 $inputOptions[$name] = $this->getInputOptionData($option);
49282 }
49283
49284 return array('arguments' => $inputArguments, 'options' => $inputOptions);
49285 }
49286
49287
49288
49289
49290
49291
49292 private function getCommandData(Command $command)
49293 {
49294 $command->getSynopsis();
49295 $command->mergeApplicationDefinition(false);
49296
49297 return array(
49298 'name' => $command->getName(),
49299 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
49300 'description' => $command->getDescription(),
49301 'help' => $command->getProcessedHelp(),
49302 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
49303 );
49304 }
49305 }
49306 <?php
49307
49308
49309
49310
49311
49312
49313
49314
49315
49316
49317 namespace Symfony\Component\Console\Descriptor;
49318
49319 use Symfony\Component\Console\Application;
49320 use Symfony\Component\Console\Command\Command;
49321 use Symfony\Component\Console\Helper\Helper;
49322 use Symfony\Component\Console\Input\InputArgument;
49323 use Symfony\Component\Console\Input\InputDefinition;
49324 use Symfony\Component\Console\Input\InputOption;
49325
49326
49327
49328
49329
49330
49331
49332
49333 class MarkdownDescriptor extends Descriptor
49334 {
49335
49336
49337
49338 protected function describeInputArgument(InputArgument $argument, array $options = array())
49339 {
49340 $this->write(
49341 '**'.$argument->getName().':**'."\n\n"
49342 .'* Name: '.($argument->getName() ?: '<none>')."\n"
49343 .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
49344 .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
49345 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $argument->getDescription() ?: '<none>')."\n"
49346 .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
49347 );
49348 }
49349
49350
49351
49352
49353 protected function describeInputOption(InputOption $option, array $options = array())
49354 {
49355 $this->write(
49356 '**'.$option->getName().':**'."\n\n"
49357 .'* Name: `--'.$option->getName().'`'."\n"
49358 .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '<none>')."\n"
49359 .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
49360 .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
49361 .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
49362 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $option->getDescription() ?: '<none>')."\n"
49363 .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
49364 );
49365 }
49366
49367
49368
49369
49370 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
49371 {
49372 if ($showArguments = count($definition->getArguments()) > 0) {
49373 $this->write('### Arguments:');
49374 foreach ($definition->getArguments() as $argument) {
49375 $this->write("\n\n");
49376 $this->write($this->describeInputArgument($argument));
49377 }
49378 }
49379
49380 if (count($definition->getOptions()) > 0) {
49381 if ($showArguments) {
49382 $this->write("\n\n");
49383 }
49384
49385 $this->write('### Options:');
49386 foreach ($definition->getOptions() as $option) {
49387 $this->write("\n\n");
49388 $this->write($this->describeInputOption($option));
49389 }
49390 }
49391 }
49392
49393
49394
49395
49396 protected function describeCommand(Command $command, array $options = array())
49397 {
49398 $command->getSynopsis();
49399 $command->mergeApplicationDefinition(false);
49400
49401 $this->write(
49402 $command->getName()."\n"
49403 .str_repeat('-', Helper::strlen($command->getName()))."\n\n"
49404 .'* Description: '.($command->getDescription() ?: '<none>')."\n"
49405 .'* Usage:'."\n\n"
49406 .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
49407 return $carry.'  * `'.$usage.'`'."\n";
49408 })
49409 );
49410
49411 if ($help = $command->getProcessedHelp()) {
49412 $this->write("\n");
49413 $this->write($help);
49414 }
49415
49416 if ($command->getNativeDefinition()) {
49417 $this->write("\n\n");
49418 $this->describeInputDefinition($command->getNativeDefinition());
49419 }
49420 }
49421
49422
49423
49424
49425 protected function describeApplication(Application $application, array $options = array())
49426 {
49427 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
49428 $description = new ApplicationDescription($application, $describedNamespace);
49429
49430 $this->write($application->getName()."\n".str_repeat('=', Helper::strlen($application->getName())));
49431
49432 foreach ($description->getNamespaces() as $namespace) {
49433 if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
49434 $this->write("\n\n");
49435 $this->write('**'.$namespace['id'].':**');
49436 }
49437
49438 $this->write("\n\n");
49439 $this->write(implode("\n", array_map(function ($commandName) {
49440 return '* '.$commandName;
49441 }, $namespace['commands'])));
49442 }
49443
49444 foreach ($description->getCommands() as $command) {
49445 $this->write("\n\n");
49446 $this->write($this->describeCommand($command));
49447 }
49448 }
49449 }
49450 <?php
49451
49452
49453
49454
49455
49456
49457
49458
49459
49460
49461 namespace Symfony\Component\Console\Descriptor;
49462
49463 use Symfony\Component\Console\Application;
49464 use Symfony\Component\Console\Command\Command;
49465 use Symfony\Component\Console\Formatter\OutputFormatter;
49466 use Symfony\Component\Console\Helper\Helper;
49467 use Symfony\Component\Console\Input\InputArgument;
49468 use Symfony\Component\Console\Input\InputDefinition;
49469 use Symfony\Component\Console\Input\InputOption;
49470
49471
49472
49473
49474
49475
49476
49477
49478 class TextDescriptor extends Descriptor
49479 {
49480
49481
49482
49483 protected function describeInputArgument(InputArgument $argument, array $options = array())
49484 {
49485 if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
49486 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
49487 } else {
49488 $default = '';
49489 }
49490
49491 $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
49492 $spacingWidth = $totalWidth - strlen($argument->getName());
49493
49494 $this->writeText(sprintf('  <info>%s</info>  %s%s%s',
49495 $argument->getName(),
49496 str_repeat(' ', $spacingWidth),
49497
49498  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
49499 $default
49500 ), $options);
49501 }
49502
49503
49504
49505
49506 protected function describeInputOption(InputOption $option, array $options = array())
49507 {
49508 if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
49509 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
49510 } else {
49511 $default = '';
49512 }
49513
49514 $value = '';
49515 if ($option->acceptValue()) {
49516 $value = '='.strtoupper($option->getName());
49517
49518 if ($option->isValueOptional()) {
49519 $value = '['.$value.']';
49520 }
49521 }
49522
49523 $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
49524 $synopsis = sprintf('%s%s',
49525 $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
49526 sprintf('--%s%s', $option->getName(), $value)
49527 );
49528
49529 $spacingWidth = $totalWidth - Helper::strlen($synopsis);
49530
49531 $this->writeText(sprintf('  <info>%s</info>  %s%s%s%s',
49532 $synopsis,
49533 str_repeat(' ', $spacingWidth),
49534
49535  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
49536 $default,
49537 $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
49538 ), $options);
49539 }
49540
49541
49542
49543
49544 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
49545 {
49546 $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
49547 foreach ($definition->getArguments() as $argument) {
49548 $totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
49549 }
49550
49551 if ($definition->getArguments()) {
49552 $this->writeText('<comment>Arguments:</comment>', $options);
49553 $this->writeText("\n");
49554 foreach ($definition->getArguments() as $argument) {
49555 $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
49556 $this->writeText("\n");
49557 }
49558 }
49559
49560 if ($definition->getArguments() && $definition->getOptions()) {
49561 $this->writeText("\n");
49562 }
49563
49564 if ($definition->getOptions()) {
49565 $laterOptions = array();
49566
49567 $this->writeText('<comment>Options:</comment>', $options);
49568 foreach ($definition->getOptions() as $option) {
49569 if (strlen($option->getShortcut()) > 1) {
49570 $laterOptions[] = $option;
49571 continue;
49572 }
49573 $this->writeText("\n");
49574 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
49575 }
49576 foreach ($laterOptions as $option) {
49577 $this->writeText("\n");
49578 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
49579 }
49580 }
49581 }
49582
49583
49584
49585
49586 protected function describeCommand(Command $command, array $options = array())
49587 {
49588 $command->getSynopsis(true);
49589 $command->getSynopsis(false);
49590 $command->mergeApplicationDefinition(false);
49591
49592 $this->writeText('<comment>Usage:</comment>', $options);
49593 foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
49594 $this->writeText("\n");
49595 $this->writeText('  '.$usage, $options);
49596 }
49597 $this->writeText("\n");
49598
49599 $definition = $command->getNativeDefinition();
49600 if ($definition->getOptions() || $definition->getArguments()) {
49601 $this->writeText("\n");
49602 $this->describeInputDefinition($definition, $options);
49603 $this->writeText("\n");
49604 }
49605
49606 if ($help = $command->getProcessedHelp()) {
49607 $this->writeText("\n");
49608 $this->writeText('<comment>Help:</comment>', $options);
49609 $this->writeText("\n");
49610 $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
49611 $this->writeText("\n");
49612 }
49613 }
49614
49615
49616
49617
49618 protected function describeApplication(Application $application, array $options = array())
49619 {
49620 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
49621 $description = new ApplicationDescription($application, $describedNamespace);
49622
49623 if (isset($options['raw_text']) && $options['raw_text']) {
49624 $width = $this->getColumnWidth($description->getCommands());
49625
49626 foreach ($description->getCommands() as $command) {
49627 $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
49628 $this->writeText("\n");
49629 }
49630 } else {
49631 if ('' != $help = $application->getHelp()) {
49632 $this->writeText("$help\n\n", $options);
49633 }
49634
49635 $this->writeText("<comment>Usage:</comment>\n", $options);
49636 $this->writeText("  command [options] [arguments]\n\n", $options);
49637
49638 $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
49639
49640 $this->writeText("\n");
49641 $this->writeText("\n");
49642
49643 $width = $this->getColumnWidth($description->getCommands());
49644
49645 if ($describedNamespace) {
49646 $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
49647 } else {
49648 $this->writeText('<comment>Available commands:</comment>', $options);
49649 }
49650
49651
49652  foreach ($description->getNamespaces() as $namespace) {
49653 if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
49654 $this->writeText("\n");
49655 $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
49656 }
49657
49658 foreach ($namespace['commands'] as $name) {
49659 $this->writeText("\n");
49660 $spacingWidth = $width - Helper::strlen($name);
49661 $this->writeText(sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
49662 }
49663 }
49664
49665 $this->writeText("\n");
49666 }
49667 }
49668
49669
49670
49671
49672 private function writeText($content, array $options = array())
49673 {
49674 $this->write(
49675 isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
49676 isset($options['raw_output']) ? !$options['raw_output'] : true
49677 );
49678 }
49679
49680
49681
49682
49683
49684
49685
49686
49687 private function formatDefaultValue($default)
49688 {
49689 if (INF === $default) {
49690 return 'INF';
49691 }
49692
49693 if (is_string($default)) {
49694 $default = OutputFormatter::escape($default);
49695 } elseif (is_array($default)) {
49696 foreach ($default as $key => $value) {
49697 if (is_string($value)) {
49698 $default[$key] = OutputFormatter::escape($value);
49699 }
49700 }
49701 }
49702
49703 if (\PHP_VERSION_ID < 50400) {
49704 return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
49705 }
49706
49707 return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
49708 }
49709
49710
49711
49712
49713
49714
49715 private function getColumnWidth(array $commands)
49716 {
49717 $widths = array();
49718
49719 foreach ($commands as $command) {
49720 $widths[] = Helper::strlen($command->getName());
49721 foreach ($command->getAliases() as $alias) {
49722 $widths[] = Helper::strlen($alias);
49723 }
49724 }
49725
49726 return max($widths) + 2;
49727 }
49728
49729
49730
49731
49732
49733
49734 private function calculateTotalWidthForOptions($options)
49735 {
49736 $totalWidth = 0;
49737 foreach ($options as $option) {
49738
49739  $nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
49740
49741 if ($option->acceptValue()) {
49742 $valueLength = 1 + Helper::strlen($option->getName()); 
49743  $valueLength += $option->isValueOptional() ? 2 : 0; 
49744
49745 $nameLength += $valueLength;
49746 }
49747 $totalWidth = max($totalWidth, $nameLength);
49748 }
49749
49750 return $totalWidth;
49751 }
49752 }
49753 <?php
49754
49755
49756
49757
49758
49759
49760
49761
49762
49763
49764 namespace Symfony\Component\Console\Descriptor;
49765
49766 use Symfony\Component\Console\Application;
49767 use Symfony\Component\Console\Command\Command;
49768 use Symfony\Component\Console\Input\InputArgument;
49769 use Symfony\Component\Console\Input\InputDefinition;
49770 use Symfony\Component\Console\Input\InputOption;
49771
49772
49773
49774
49775
49776
49777
49778
49779 class XmlDescriptor extends Descriptor
49780 {
49781
49782
49783
49784
49785
49786 public function getInputDefinitionDocument(InputDefinition $definition)
49787 {
49788 $dom = new \DOMDocument('1.0', 'UTF-8');
49789 $dom->appendChild($definitionXML = $dom->createElement('definition'));
49790
49791 $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
49792 foreach ($definition->getArguments() as $argument) {
49793 $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
49794 }
49795
49796 $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
49797 foreach ($definition->getOptions() as $option) {
49798 $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
49799 }
49800
49801 return $dom;
49802 }
49803
49804
49805
49806
49807
49808
49809 public function getCommandDocument(Command $command)
49810 {
49811 $dom = new \DOMDocument('1.0', 'UTF-8');
49812 $dom->appendChild($commandXML = $dom->createElement('command'));
49813
49814 $command->getSynopsis();
49815 $command->mergeApplicationDefinition(false);
49816
49817 $commandXML->setAttribute('id', $command->getName());
49818 $commandXML->setAttribute('name', $command->getName());
49819
49820 $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
49821
49822 foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
49823 $usagesXML->appendChild($dom->createElement('usage', $usage));
49824 }
49825
49826 $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
49827 $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
49828
49829 $commandXML->appendChild($helpXML = $dom->createElement('help'));
49830 $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
49831
49832 $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
49833 $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
49834
49835 return $dom;
49836 }
49837
49838
49839
49840
49841
49842
49843
49844 public function getApplicationDocument(Application $application, $namespace = null)
49845 {
49846 $dom = new \DOMDocument('1.0', 'UTF-8');
49847 $dom->appendChild($rootXml = $dom->createElement('symfony'));
49848
49849 if ($application->getName() !== 'UNKNOWN') {
49850 $rootXml->setAttribute('name', $application->getName());
49851 if ($application->getVersion() !== 'UNKNOWN') {
49852 $rootXml->setAttribute('version', $application->getVersion());
49853 }
49854 }
49855
49856 $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
49857
49858 $description = new ApplicationDescription($application, $namespace);
49859
49860 if ($namespace) {
49861 $commandsXML->setAttribute('namespace', $namespace);
49862 }
49863
49864 foreach ($description->getCommands() as $command) {
49865 $this->appendDocument($commandsXML, $this->getCommandDocument($command));
49866 }
49867
49868 if (!$namespace) {
49869 $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
49870
49871 foreach ($description->getNamespaces() as $namespaceDescription) {
49872 $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
49873 $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
49874
49875 foreach ($namespaceDescription['commands'] as $name) {
49876 $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
49877 $commandXML->appendChild($dom->createTextNode($name));
49878 }
49879 }
49880 }
49881
49882 return $dom;
49883 }
49884
49885
49886
49887
49888 protected function describeInputArgument(InputArgument $argument, array $options = array())
49889 {
49890 $this->writeDocument($this->getInputArgumentDocument($argument));
49891 }
49892
49893
49894
49895
49896 protected function describeInputOption(InputOption $option, array $options = array())
49897 {
49898 $this->writeDocument($this->getInputOptionDocument($option));
49899 }
49900
49901
49902
49903
49904 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
49905 {
49906 $this->writeDocument($this->getInputDefinitionDocument($definition));
49907 }
49908
49909
49910
49911
49912 protected function describeCommand(Command $command, array $options = array())
49913 {
49914 $this->writeDocument($this->getCommandDocument($command));
49915 }
49916
49917
49918
49919
49920 protected function describeApplication(Application $application, array $options = array())
49921 {
49922 $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
49923 }
49924
49925
49926
49927
49928
49929
49930
49931 private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
49932 {
49933 foreach ($importedParent->childNodes as $childNode) {
49934 $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
49935 }
49936 }
49937
49938
49939
49940
49941
49942
49943
49944
49945 private function writeDocument(\DOMDocument $dom)
49946 {
49947 $dom->formatOutput = true;
49948 $this->write($dom->saveXML());
49949 }
49950
49951
49952
49953
49954
49955
49956 private function getInputArgumentDocument(InputArgument $argument)
49957 {
49958 $dom = new \DOMDocument('1.0', 'UTF-8');
49959
49960 $dom->appendChild($objectXML = $dom->createElement('argument'));
49961 $objectXML->setAttribute('name', $argument->getName());
49962 $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
49963 $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
49964 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
49965 $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
49966
49967 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
49968 $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
49969 foreach ($defaults as $default) {
49970 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
49971 $defaultXML->appendChild($dom->createTextNode($default));
49972 }
49973
49974 return $dom;
49975 }
49976
49977
49978
49979
49980
49981
49982 private function getInputOptionDocument(InputOption $option)
49983 {
49984 $dom = new \DOMDocument('1.0', 'UTF-8');
49985
49986 $dom->appendChild($objectXML = $dom->createElement('option'));
49987 $objectXML->setAttribute('name', '--'.$option->getName());
49988 $pos = strpos($option->getShortcut(), '|');
49989 if (false !== $pos) {
49990 $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
49991 $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
49992 } else {
49993 $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
49994 }
49995 $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
49996 $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
49997 $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
49998 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
49999 $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
50000
50001 if ($option->acceptValue()) {
50002 $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
50003 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
50004
50005 if (!empty($defaults)) {
50006 foreach ($defaults as $default) {
50007 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
50008 $defaultXML->appendChild($dom->createTextNode($default));
50009 }
50010 }
50011 }
50012
50013 return $dom;
50014 }
50015 }
50016 <?php
50017
50018
50019
50020
50021
50022
50023
50024
50025
50026
50027 namespace Symfony\Component\Console\Event;
50028
50029
50030
50031
50032
50033
50034 class ConsoleCommandEvent extends ConsoleEvent
50035 {
50036
50037
50038
50039 const RETURN_CODE_DISABLED = 113;
50040
50041
50042
50043
50044
50045
50046 private $commandShouldRun = true;
50047
50048
50049
50050
50051
50052
50053 public function disableCommand()
50054 {
50055 return $this->commandShouldRun = false;
50056 }
50057
50058
50059
50060
50061
50062
50063 public function enableCommand()
50064 {
50065 return $this->commandShouldRun = true;
50066 }
50067
50068
50069
50070
50071
50072
50073 public function commandShouldRun()
50074 {
50075 return $this->commandShouldRun;
50076 }
50077 }
50078 <?php
50079
50080
50081
50082
50083
50084
50085
50086
50087
50088
50089 namespace Symfony\Component\Console\Event;
50090
50091 use Symfony\Component\Console\Command\Command;
50092 use Symfony\Component\Console\Input\InputInterface;
50093 use Symfony\Component\Console\Output\OutputInterface;
50094 use Symfony\Component\EventDispatcher\Event;
50095
50096
50097
50098
50099
50100
50101 class ConsoleEvent extends Event
50102 {
50103 protected $command;
50104
50105 private $input;
50106 private $output;
50107
50108 public function __construct(Command $command, InputInterface $input, OutputInterface $output)
50109 {
50110 $this->command = $command;
50111 $this->input = $input;
50112 $this->output = $output;
50113 }
50114
50115
50116
50117
50118
50119
50120 public function getCommand()
50121 {
50122 return $this->command;
50123 }
50124
50125
50126
50127
50128
50129
50130 public function getInput()
50131 {
50132 return $this->input;
50133 }
50134
50135
50136
50137
50138
50139
50140 public function getOutput()
50141 {
50142 return $this->output;
50143 }
50144 }
50145 <?php
50146
50147
50148
50149
50150
50151
50152
50153
50154
50155
50156 namespace Symfony\Component\Console\Event;
50157
50158 use Symfony\Component\Console\Command\Command;
50159 use Symfony\Component\Console\Input\InputInterface;
50160 use Symfony\Component\Console\Output\OutputInterface;
50161
50162
50163
50164
50165
50166
50167 class ConsoleExceptionEvent extends ConsoleEvent
50168 {
50169 private $exception;
50170 private $exitCode;
50171
50172 public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
50173 {
50174 parent::__construct($command, $input, $output);
50175
50176 $this->setException($exception);
50177 $this->exitCode = (int) $exitCode;
50178 }
50179
50180
50181
50182
50183
50184
50185 public function getException()
50186 {
50187 return $this->exception;
50188 }
50189
50190
50191
50192
50193
50194
50195
50196
50197 public function setException(\Exception $exception)
50198 {
50199 $this->exception = $exception;
50200 }
50201
50202
50203
50204
50205
50206
50207 public function getExitCode()
50208 {
50209 return $this->exitCode;
50210 }
50211 }
50212 <?php
50213
50214
50215
50216
50217
50218
50219
50220
50221
50222
50223 namespace Symfony\Component\Console\Event;
50224
50225 use Symfony\Component\Console\Command\Command;
50226 use Symfony\Component\Console\Input\InputInterface;
50227 use Symfony\Component\Console\Output\OutputInterface;
50228
50229
50230
50231
50232
50233
50234 class ConsoleTerminateEvent extends ConsoleEvent
50235 {
50236
50237
50238
50239
50240
50241 private $exitCode;
50242
50243 public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
50244 {
50245 parent::__construct($command, $input, $output);
50246
50247 $this->setExitCode($exitCode);
50248 }
50249
50250
50251
50252
50253
50254
50255 public function setExitCode($exitCode)
50256 {
50257 $this->exitCode = (int) $exitCode;
50258 }
50259
50260
50261
50262
50263
50264
50265 public function getExitCode()
50266 {
50267 return $this->exitCode;
50268 }
50269 }
50270 <?php
50271
50272
50273
50274
50275
50276
50277
50278
50279
50280
50281 namespace Symfony\Component\Console\Exception;
50282
50283
50284
50285
50286
50287
50288 class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
50289 {
50290 private $alternatives;
50291
50292
50293
50294
50295
50296
50297
50298 public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
50299 {
50300 parent::__construct($message, $code, $previous);
50301
50302 $this->alternatives = $alternatives;
50303 }
50304
50305
50306
50307
50308 public function getAlternatives()
50309 {
50310 return $this->alternatives;
50311 }
50312 }
50313 <?php
50314
50315
50316
50317
50318
50319
50320
50321
50322
50323
50324 namespace Symfony\Component\Console\Exception;
50325
50326
50327
50328
50329
50330
50331 interface ExceptionInterface
50332 {
50333 }
50334 <?php
50335
50336
50337
50338
50339
50340
50341
50342
50343
50344
50345 namespace Symfony\Component\Console\Exception;
50346
50347
50348
50349
50350 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
50351 {
50352 }
50353 <?php
50354
50355
50356
50357
50358
50359
50360
50361
50362
50363
50364 namespace Symfony\Component\Console\Exception;
50365
50366
50367
50368
50369
50370
50371 class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
50372 {
50373 }
50374 <?php
50375
50376
50377
50378
50379
50380
50381
50382
50383
50384
50385 namespace Symfony\Component\Console\Exception;
50386
50387
50388
50389
50390 class LogicException extends \LogicException implements ExceptionInterface
50391 {
50392 }
50393 <?php
50394
50395
50396
50397
50398
50399
50400
50401
50402
50403
50404 namespace Symfony\Component\Console\Exception;
50405
50406
50407
50408
50409 class RuntimeException extends \RuntimeException implements ExceptionInterface
50410 {
50411 }
50412 <?php
50413
50414
50415
50416
50417
50418
50419
50420
50421
50422
50423 namespace Symfony\Component\Console\Formatter;
50424
50425 use Symfony\Component\Console\Exception\InvalidArgumentException;
50426
50427
50428
50429
50430
50431
50432 class OutputFormatter implements OutputFormatterInterface
50433 {
50434 private $decorated;
50435 private $styles = array();
50436 private $styleStack;
50437
50438
50439
50440
50441
50442
50443
50444
50445 public static function escape($text)
50446 {
50447 $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
50448
50449 return self::escapeTrailingBackslash($text);
50450 }
50451
50452
50453
50454
50455
50456
50457
50458
50459
50460
50461 public static function escapeTrailingBackslash($text)
50462 {
50463 if ('\\' === substr($text, -1)) {
50464 $len = strlen($text);
50465 $text = rtrim($text, '\\');
50466 $text .= str_repeat('<<', $len - strlen($text));
50467 }
50468
50469 return $text;
50470 }
50471
50472
50473
50474
50475
50476
50477
50478 public function __construct($decorated = false, array $styles = array())
50479 {
50480 $this->decorated = (bool) $decorated;
50481
50482 $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
50483 $this->setStyle('info', new OutputFormatterStyle('green'));
50484 $this->setStyle('comment', new OutputFormatterStyle('yellow'));
50485 $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
50486
50487 foreach ($styles as $name => $style) {
50488 $this->setStyle($name, $style);
50489 }
50490
50491 $this->styleStack = new OutputFormatterStyleStack();
50492 }
50493
50494
50495
50496
50497 public function setDecorated($decorated)
50498 {
50499 $this->decorated = (bool) $decorated;
50500 }
50501
50502
50503
50504
50505 public function isDecorated()
50506 {
50507 return $this->decorated;
50508 }
50509
50510
50511
50512
50513 public function setStyle($name, OutputFormatterStyleInterface $style)
50514 {
50515 $this->styles[strtolower($name)] = $style;
50516 }
50517
50518
50519
50520
50521 public function hasStyle($name)
50522 {
50523 return isset($this->styles[strtolower($name)]);
50524 }
50525
50526
50527
50528
50529 public function getStyle($name)
50530 {
50531 if (!$this->hasStyle($name)) {
50532 throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
50533 }
50534
50535 return $this->styles[strtolower($name)];
50536 }
50537
50538
50539
50540
50541 public function format($message)
50542 {
50543 $message = (string) $message;
50544 $offset = 0;
50545 $output = '';
50546 $tagRegex = '[a-z][a-z0-9_=;-]*+';
50547 preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
50548 foreach ($matches[0] as $i => $match) {
50549 $pos = $match[1];
50550 $text = $match[0];
50551
50552 if (0 != $pos && '\\' == $message[$pos - 1]) {
50553 continue;
50554 }
50555
50556
50557  $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
50558 $offset = $pos + strlen($text);
50559
50560
50561  if ($open = '/' != $text[1]) {
50562 $tag = $matches[1][$i][0];
50563 } else {
50564 $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
50565 }
50566
50567 if (!$open && !$tag) {
50568
50569  $this->styleStack->pop();
50570 } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
50571 $output .= $this->applyCurrentStyle($text);
50572 } elseif ($open) {
50573 $this->styleStack->push($style);
50574 } else {
50575 $this->styleStack->pop($style);
50576 }
50577 }
50578
50579 $output .= $this->applyCurrentStyle(substr($message, $offset));
50580
50581 if (false !== strpos($output, '<<')) {
50582 return strtr($output, array('\\<' => '<', '<<' => '\\'));
50583 }
50584
50585 return str_replace('\\<', '<', $output);
50586 }
50587
50588
50589
50590
50591 public function getStyleStack()
50592 {
50593 return $this->styleStack;
50594 }
50595
50596
50597
50598
50599
50600
50601
50602
50603 private function createStyleFromString($string)
50604 {
50605 if (isset($this->styles[$string])) {
50606 return $this->styles[$string];
50607 }
50608
50609 if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
50610 return false;
50611 }
50612
50613 $style = new OutputFormatterStyle();
50614 foreach ($matches as $match) {
50615 array_shift($match);
50616
50617 if ('fg' == $match[0]) {
50618 $style->setForeground($match[1]);
50619 } elseif ('bg' == $match[0]) {
50620 $style->setBackground($match[1]);
50621 } else {
50622 try {
50623 $style->setOption($match[1]);
50624 } catch (\InvalidArgumentException $e) {
50625 return false;
50626 }
50627 }
50628 }
50629
50630 return $style;
50631 }
50632
50633
50634
50635
50636
50637
50638
50639
50640 private function applyCurrentStyle($text)
50641 {
50642 return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
50643 }
50644 }
50645 <?php
50646
50647
50648
50649
50650
50651
50652
50653
50654
50655
50656 namespace Symfony\Component\Console\Formatter;
50657
50658
50659
50660
50661
50662
50663 interface OutputFormatterInterface
50664 {
50665
50666
50667
50668
50669
50670 public function setDecorated($decorated);
50671
50672
50673
50674
50675
50676
50677 public function isDecorated();
50678
50679
50680
50681
50682
50683
50684
50685 public function setStyle($name, OutputFormatterStyleInterface $style);
50686
50687
50688
50689
50690
50691
50692
50693
50694 public function hasStyle($name);
50695
50696
50697
50698
50699
50700
50701
50702
50703
50704
50705 public function getStyle($name);
50706
50707
50708
50709
50710
50711
50712
50713
50714 public function format($message);
50715 }
50716 <?php
50717
50718
50719
50720
50721
50722
50723
50724
50725
50726
50727 namespace Symfony\Component\Console\Formatter;
50728
50729 use Symfony\Component\Console\Exception\InvalidArgumentException;
50730
50731
50732
50733
50734
50735
50736 class OutputFormatterStyle implements OutputFormatterStyleInterface
50737 {
50738 private static $availableForegroundColors = array(
50739 'black' => array('set' => 30, 'unset' => 39),
50740 'red' => array('set' => 31, 'unset' => 39),
50741 'green' => array('set' => 32, 'unset' => 39),
50742 'yellow' => array('set' => 33, 'unset' => 39),
50743 'blue' => array('set' => 34, 'unset' => 39),
50744 'magenta' => array('set' => 35, 'unset' => 39),
50745 'cyan' => array('set' => 36, 'unset' => 39),
50746 'white' => array('set' => 37, 'unset' => 39),
50747 'default' => array('set' => 39, 'unset' => 39),
50748 );
50749 private static $availableBackgroundColors = array(
50750 'black' => array('set' => 40, 'unset' => 49),
50751 'red' => array('set' => 41, 'unset' => 49),
50752 'green' => array('set' => 42, 'unset' => 49),
50753 'yellow' => array('set' => 43, 'unset' => 49),
50754 'blue' => array('set' => 44, 'unset' => 49),
50755 'magenta' => array('set' => 45, 'unset' => 49),
50756 'cyan' => array('set' => 46, 'unset' => 49),
50757 'white' => array('set' => 47, 'unset' => 49),
50758 'default' => array('set' => 49, 'unset' => 49),
50759 );
50760 private static $availableOptions = array(
50761 'bold' => array('set' => 1, 'unset' => 22),
50762 'underscore' => array('set' => 4, 'unset' => 24),
50763 'blink' => array('set' => 5, 'unset' => 25),
50764 'reverse' => array('set' => 7, 'unset' => 27),
50765 'conceal' => array('set' => 8, 'unset' => 28),
50766 );
50767
50768 private $foreground;
50769 private $background;
50770 private $options = array();
50771
50772
50773
50774
50775
50776
50777
50778
50779 public function __construct($foreground = null, $background = null, array $options = array())
50780 {
50781 if (null !== $foreground) {
50782 $this->setForeground($foreground);
50783 }
50784 if (null !== $background) {
50785 $this->setBackground($background);
50786 }
50787 if (count($options)) {
50788 $this->setOptions($options);
50789 }
50790 }
50791
50792
50793
50794
50795
50796
50797
50798
50799 public function setForeground($color = null)
50800 {
50801 if (null === $color) {
50802 $this->foreground = null;
50803
50804 return;
50805 }
50806
50807 if (!isset(static::$availableForegroundColors[$color])) {
50808 throw new InvalidArgumentException(sprintf(
50809 'Invalid foreground color specified: "%s". Expected one of (%s)',
50810 $color,
50811 implode(', ', array_keys(static::$availableForegroundColors))
50812 ));
50813 }
50814
50815 $this->foreground = static::$availableForegroundColors[$color];
50816 }
50817
50818
50819
50820
50821
50822
50823
50824
50825 public function setBackground($color = null)
50826 {
50827 if (null === $color) {
50828 $this->background = null;
50829
50830 return;
50831 }
50832
50833 if (!isset(static::$availableBackgroundColors[$color])) {
50834 throw new InvalidArgumentException(sprintf(
50835 'Invalid background color specified: "%s". Expected one of (%s)',
50836 $color,
50837 implode(', ', array_keys(static::$availableBackgroundColors))
50838 ));
50839 }
50840
50841 $this->background = static::$availableBackgroundColors[$color];
50842 }
50843
50844
50845
50846
50847
50848
50849
50850
50851 public function setOption($option)
50852 {
50853 if (!isset(static::$availableOptions[$option])) {
50854 throw new InvalidArgumentException(sprintf(
50855 'Invalid option specified: "%s". Expected one of (%s)',
50856 $option,
50857 implode(', ', array_keys(static::$availableOptions))
50858 ));
50859 }
50860
50861 if (!in_array(static::$availableOptions[$option], $this->options)) {
50862 $this->options[] = static::$availableOptions[$option];
50863 }
50864 }
50865
50866
50867
50868
50869
50870
50871
50872
50873 public function unsetOption($option)
50874 {
50875 if (!isset(static::$availableOptions[$option])) {
50876 throw new InvalidArgumentException(sprintf(
50877 'Invalid option specified: "%s". Expected one of (%s)',
50878 $option,
50879 implode(', ', array_keys(static::$availableOptions))
50880 ));
50881 }
50882
50883 $pos = array_search(static::$availableOptions[$option], $this->options);
50884 if (false !== $pos) {
50885 unset($this->options[$pos]);
50886 }
50887 }
50888
50889
50890
50891
50892
50893
50894 public function setOptions(array $options)
50895 {
50896 $this->options = array();
50897
50898 foreach ($options as $option) {
50899 $this->setOption($option);
50900 }
50901 }
50902
50903
50904
50905
50906
50907
50908
50909
50910 public function apply($text)
50911 {
50912 $setCodes = array();
50913 $unsetCodes = array();
50914
50915 if (null !== $this->foreground) {
50916 $setCodes[] = $this->foreground['set'];
50917 $unsetCodes[] = $this->foreground['unset'];
50918 }
50919 if (null !== $this->background) {
50920 $setCodes[] = $this->background['set'];
50921 $unsetCodes[] = $this->background['unset'];
50922 }
50923 if (count($this->options)) {
50924 foreach ($this->options as $option) {
50925 $setCodes[] = $option['set'];
50926 $unsetCodes[] = $option['unset'];
50927 }
50928 }
50929
50930 if (0 === count($setCodes)) {
50931 return $text;
50932 }
50933
50934 return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
50935 }
50936 }
50937 <?php
50938
50939
50940
50941
50942
50943
50944
50945
50946
50947
50948 namespace Symfony\Component\Console\Formatter;
50949
50950
50951
50952
50953
50954
50955 interface OutputFormatterStyleInterface
50956 {
50957
50958
50959
50960
50961
50962 public function setForeground($color = null);
50963
50964
50965
50966
50967
50968
50969 public function setBackground($color = null);
50970
50971
50972
50973
50974
50975
50976 public function setOption($option);
50977
50978
50979
50980
50981
50982
50983 public function unsetOption($option);
50984
50985
50986
50987
50988
50989
50990 public function setOptions(array $options);
50991
50992
50993
50994
50995
50996
50997
50998
50999 public function apply($text);
51000 }
51001 <?php
51002
51003
51004
51005
51006
51007
51008
51009
51010
51011
51012 namespace Symfony\Component\Console\Formatter;
51013
51014 use Symfony\Component\Console\Exception\InvalidArgumentException;
51015
51016
51017
51018
51019 class OutputFormatterStyleStack
51020 {
51021
51022
51023
51024 private $styles;
51025
51026
51027
51028
51029 private $emptyStyle;
51030
51031
51032
51033
51034
51035
51036 public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
51037 {
51038 $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
51039 $this->reset();
51040 }
51041
51042
51043
51044
51045 public function reset()
51046 {
51047 $this->styles = array();
51048 }
51049
51050
51051
51052
51053
51054
51055 public function push(OutputFormatterStyleInterface $style)
51056 {
51057 $this->styles[] = $style;
51058 }
51059
51060
51061
51062
51063
51064
51065
51066
51067
51068
51069 public function pop(OutputFormatterStyleInterface $style = null)
51070 {
51071 if (empty($this->styles)) {
51072 return $this->emptyStyle;
51073 }
51074
51075 if (null === $style) {
51076 return array_pop($this->styles);
51077 }
51078
51079 foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
51080 if ($style->apply('') === $stackedStyle->apply('')) {
51081 $this->styles = array_slice($this->styles, 0, $index);
51082
51083 return $stackedStyle;
51084 }
51085 }
51086
51087 throw new InvalidArgumentException('Incorrectly nested style tag found.');
51088 }
51089
51090
51091
51092
51093
51094
51095 public function getCurrent()
51096 {
51097 if (empty($this->styles)) {
51098 return $this->emptyStyle;
51099 }
51100
51101 return $this->styles[count($this->styles) - 1];
51102 }
51103
51104
51105
51106
51107
51108
51109 public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
51110 {
51111 $this->emptyStyle = $emptyStyle;
51112
51113 return $this;
51114 }
51115
51116
51117
51118
51119 public function getEmptyStyle()
51120 {
51121 return $this->emptyStyle;
51122 }
51123 }
51124 <?php
51125
51126
51127
51128
51129
51130
51131
51132
51133
51134
51135 namespace Symfony\Component\Console\Helper;
51136
51137
51138
51139
51140
51141
51142
51143
51144 class DebugFormatterHelper extends Helper
51145 {
51146 private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
51147 private $started = array();
51148 private $count = -1;
51149
51150
51151
51152
51153
51154
51155
51156
51157
51158
51159 public function start($id, $message, $prefix = 'RUN')
51160 {
51161 $this->started[$id] = array('border' => ++$this->count % count($this->colors));
51162
51163 return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
51164 }
51165
51166
51167
51168
51169
51170
51171
51172
51173
51174
51175
51176
51177 public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
51178 {
51179 $message = '';
51180
51181 if ($error) {
51182 if (isset($this->started[$id]['out'])) {
51183 $message .= "\n";
51184 unset($this->started[$id]['out']);
51185 }
51186 if (!isset($this->started[$id]['err'])) {
51187 $message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
51188 $this->started[$id]['err'] = true;
51189 }
51190
51191 $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
51192 } else {
51193 if (isset($this->started[$id]['err'])) {
51194 $message .= "\n";
51195 unset($this->started[$id]['err']);
51196 }
51197 if (!isset($this->started[$id]['out'])) {
51198 $message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
51199 $this->started[$id]['out'] = true;
51200 }
51201
51202 $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
51203 }
51204
51205 return $message;
51206 }
51207
51208
51209
51210
51211
51212
51213
51214
51215
51216
51217
51218 public function stop($id, $message, $successful, $prefix = 'RES')
51219 {
51220 $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
51221
51222 if ($successful) {
51223 return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
51224 }
51225
51226 $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
51227
51228 unset($this->started[$id]['out'], $this->started[$id]['err']);
51229
51230 return $message;
51231 }
51232
51233
51234
51235
51236
51237
51238 private function getBorder($id)
51239 {
51240 return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
51241 }
51242
51243
51244
51245
51246 public function getName()
51247 {
51248 return 'debug_formatter';
51249 }
51250 }
51251 <?php
51252
51253
51254
51255
51256
51257
51258
51259
51260
51261
51262 namespace Symfony\Component\Console\Helper;
51263
51264 use Symfony\Component\Console\Descriptor\DescriptorInterface;
51265 use Symfony\Component\Console\Descriptor\JsonDescriptor;
51266 use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
51267 use Symfony\Component\Console\Descriptor\TextDescriptor;
51268 use Symfony\Component\Console\Descriptor\XmlDescriptor;
51269 use Symfony\Component\Console\Output\OutputInterface;
51270 use Symfony\Component\Console\Exception\InvalidArgumentException;
51271
51272
51273
51274
51275
51276
51277 class DescriptorHelper extends Helper
51278 {
51279
51280
51281
51282 private $descriptors = array();
51283
51284
51285
51286
51287 public function __construct()
51288 {
51289 $this
51290 ->register('txt', new TextDescriptor())
51291 ->register('xml', new XmlDescriptor())
51292 ->register('json', new JsonDescriptor())
51293 ->register('md', new MarkdownDescriptor())
51294 ;
51295 }
51296
51297
51298
51299
51300
51301
51302
51303
51304
51305
51306
51307
51308
51309
51310 public function describe(OutputInterface $output, $object, array $options = array())
51311 {
51312 $options = array_merge(array(
51313 'raw_text' => false,
51314 'format' => 'txt',
51315 ), $options);
51316
51317 if (!isset($this->descriptors[$options['format']])) {
51318 throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
51319 }
51320
51321 $descriptor = $this->descriptors[$options['format']];
51322 $descriptor->describe($output, $object, $options);
51323 }
51324
51325
51326
51327
51328
51329
51330
51331
51332
51333 public function register($format, DescriptorInterface $descriptor)
51334 {
51335 $this->descriptors[$format] = $descriptor;
51336
51337 return $this;
51338 }
51339
51340
51341
51342
51343 public function getName()
51344 {
51345 return 'descriptor';
51346 }
51347 }
51348 <?php
51349
51350
51351
51352
51353
51354
51355
51356
51357
51358
51359 namespace Symfony\Component\Console\Helper;
51360
51361 use Symfony\Component\Console\Exception\InvalidArgumentException;
51362 use Symfony\Component\Console\Exception\RuntimeException;
51363 use Symfony\Component\Console\Output\ConsoleOutputInterface;
51364 use Symfony\Component\Console\Output\OutputInterface;
51365 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
51366
51367
51368
51369
51370
51371
51372
51373
51374
51375 class DialogHelper extends InputAwareHelper
51376 {
51377 private $inputStream;
51378 private static $shell;
51379 private static $stty;
51380
51381 public function __construct($triggerDeprecationError = true)
51382 {
51383 if ($triggerDeprecationError) {
51384 @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);
51385 }
51386 }
51387
51388
51389
51390
51391
51392
51393
51394
51395
51396
51397
51398
51399
51400
51401
51402
51403 public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
51404 {
51405 if ($output instanceof ConsoleOutputInterface) {
51406 $output = $output->getErrorOutput();
51407 }
51408
51409 $width = max(array_map('strlen', array_keys($choices)));
51410
51411 $messages = (array) $question;
51412 foreach ($choices as $key => $value) {
51413 $messages[] = sprintf("  [<info>%-{$width}s</info>] %s", $key, $value);
51414 }
51415
51416 $output->writeln($messages);
51417
51418 $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
51419
51420  $selectedChoices = str_replace(' ', '', $picked);
51421
51422 if ($multiselect) {
51423
51424  if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
51425 throw new InvalidArgumentException(sprintf($errorMessage, $picked));
51426 }
51427 $selectedChoices = explode(',', $selectedChoices);
51428 } else {
51429 $selectedChoices = array($picked);
51430 }
51431
51432 $multiselectChoices = array();
51433
51434 foreach ($selectedChoices as $value) {
51435 if (empty($choices[$value])) {
51436 throw new InvalidArgumentException(sprintf($errorMessage, $value));
51437 }
51438 $multiselectChoices[] = $value;
51439 }
51440
51441 if ($multiselect) {
51442 return $multiselectChoices;
51443 }
51444
51445 return $picked;
51446 }, $attempts, $default);
51447
51448 return $result;
51449 }
51450
51451
51452
51453
51454
51455
51456
51457
51458
51459
51460
51461
51462
51463 public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
51464 {
51465 if ($this->input && !$this->input->isInteractive()) {
51466 return $default;
51467 }
51468
51469 if ($output instanceof ConsoleOutputInterface) {
51470 $output = $output->getErrorOutput();
51471 }
51472
51473 $output->write($question);
51474
51475 $inputStream = $this->inputStream ?: STDIN;
51476
51477 if (null === $autocomplete || !$this->hasSttyAvailable()) {
51478 $ret = fgets($inputStream, 4096);
51479 if (false === $ret) {
51480 throw new RuntimeException('Aborted');
51481 }
51482 $ret = trim($ret);
51483 } else {
51484 $ret = '';
51485
51486 $i = 0;
51487 $ofs = -1;
51488 $matches = $autocomplete;
51489 $numMatches = count($matches);
51490
51491 $sttyMode = shell_exec('stty -g');
51492
51493
51494  shell_exec('stty -icanon -echo');
51495
51496
51497  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
51498
51499
51500  while (!feof($inputStream)) {
51501 $c = fread($inputStream, 1);
51502
51503
51504  if ("\177" === $c) {
51505 if (0 === $numMatches && 0 !== $i) {
51506 --$i;
51507
51508  $output->write("\033[1D");
51509 }
51510
51511 if ($i === 0) {
51512 $ofs = -1;
51513 $matches = $autocomplete;
51514 $numMatches = count($matches);
51515 } else {
51516 $numMatches = 0;
51517 }
51518
51519
51520  $ret = substr($ret, 0, $i);
51521 } elseif ("\033" === $c) {
51522
51523  $c .= fread($inputStream, 2);
51524
51525
51526  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
51527 if ('A' === $c[2] && -1 === $ofs) {
51528 $ofs = 0;
51529 }
51530
51531 if (0 === $numMatches) {
51532 continue;
51533 }
51534
51535 $ofs += ('A' === $c[2]) ? -1 : 1;
51536 $ofs = ($numMatches + $ofs) % $numMatches;
51537 }
51538 } elseif (ord($c) < 32) {
51539 if ("\t" === $c || "\n" === $c) {
51540 if ($numMatches > 0 && -1 !== $ofs) {
51541 $ret = $matches[$ofs];
51542
51543  $output->write(substr($ret, $i));
51544 $i = strlen($ret);
51545 }
51546
51547 if ("\n" === $c) {
51548 $output->write($c);
51549 break;
51550 }
51551
51552 $numMatches = 0;
51553 }
51554
51555 continue;
51556 } else {
51557 $output->write($c);
51558 $ret .= $c;
51559 ++$i;
51560
51561 $numMatches = 0;
51562 $ofs = 0;
51563
51564 foreach ($autocomplete as $value) {
51565
51566  if (0 === strpos($value, $ret) && $i !== strlen($value)) {
51567 $matches[$numMatches++] = $value;
51568 }
51569 }
51570 }
51571
51572
51573  $output->write("\033[K");
51574
51575 if ($numMatches > 0 && -1 !== $ofs) {
51576
51577  $output->write("\0337");
51578
51579  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
51580
51581  $output->write("\0338");
51582 }
51583 }
51584
51585
51586  shell_exec(sprintf('stty %s', $sttyMode));
51587 }
51588
51589 return strlen($ret) > 0 ? $ret : $default;
51590 }
51591
51592
51593
51594
51595
51596
51597
51598
51599
51600
51601
51602
51603 public function askConfirmation(OutputInterface $output, $question, $default = true)
51604 {
51605 $answer = 'z';
51606 while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
51607 $answer = $this->ask($output, $question);
51608 }
51609
51610 if (false === $default) {
51611 return $answer && 'y' == strtolower($answer[0]);
51612 }
51613
51614 return !$answer || 'y' == strtolower($answer[0]);
51615 }
51616
51617
51618
51619
51620
51621
51622
51623
51624
51625
51626
51627
51628 public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
51629 {
51630 if ($output instanceof ConsoleOutputInterface) {
51631 $output = $output->getErrorOutput();
51632 }
51633
51634 if ('\\' === DIRECTORY_SEPARATOR) {
51635 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
51636
51637
51638  if ('phar:' === substr(__FILE__, 0, 5)) {
51639 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
51640 copy($exe, $tmpExe);
51641 $exe = $tmpExe;
51642 }
51643
51644 $output->write($question);
51645 $value = rtrim(shell_exec($exe));
51646 $output->writeln('');
51647
51648 if (isset($tmpExe)) {
51649 unlink($tmpExe);
51650 }
51651
51652 return $value;
51653 }
51654
51655 if ($this->hasSttyAvailable()) {
51656 $output->write($question);
51657
51658 $sttyMode = shell_exec('stty -g');
51659
51660 shell_exec('stty -echo');
51661 $value = fgets($this->inputStream ?: STDIN, 4096);
51662 shell_exec(sprintf('stty %s', $sttyMode));
51663
51664 if (false === $value) {
51665 throw new RuntimeException('Aborted');
51666 }
51667
51668 $value = trim($value);
51669 $output->writeln('');
51670
51671 return $value;
51672 }
51673
51674 if (false !== $shell = $this->getShell()) {
51675 $output->write($question);
51676 $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
51677 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
51678 $value = rtrim(shell_exec($command));
51679 $output->writeln('');
51680
51681 return $value;
51682 }
51683
51684 if ($fallback) {
51685 return $this->ask($output, $question);
51686 }
51687
51688 throw new RuntimeException('Unable to hide the response');
51689 }
51690
51691
51692
51693
51694
51695
51696
51697
51698
51699
51700
51701
51702
51703
51704
51705
51706
51707
51708
51709 public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
51710 {
51711 $that = $this;
51712
51713 $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
51714 return $that->ask($output, $question, $default, $autocomplete);
51715 };
51716
51717 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
51718 }
51719
51720
51721
51722
51723
51724
51725
51726
51727
51728
51729
51730
51731
51732
51733
51734
51735
51736
51737
51738 public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
51739 {
51740 $that = $this;
51741
51742 $interviewer = function () use ($output, $question, $fallback, $that) {
51743 return $that->askHiddenResponse($output, $question, $fallback);
51744 };
51745
51746 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
51747 }
51748
51749
51750
51751
51752
51753
51754
51755
51756 public function setInputStream($stream)
51757 {
51758 $this->inputStream = $stream;
51759 }
51760
51761
51762
51763
51764
51765
51766 public function getInputStream()
51767 {
51768 return $this->inputStream;
51769 }
51770
51771
51772
51773
51774 public function getName()
51775 {
51776 return 'dialog';
51777 }
51778
51779
51780
51781
51782
51783
51784 private function getShell()
51785 {
51786 if (null !== self::$shell) {
51787 return self::$shell;
51788 }
51789
51790 self::$shell = false;
51791
51792 if (file_exists('/usr/bin/env')) {
51793
51794  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
51795 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
51796 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
51797 self::$shell = $sh;
51798 break;
51799 }
51800 }
51801 }
51802
51803 return self::$shell;
51804 }
51805
51806 private function hasSttyAvailable()
51807 {
51808 if (null !== self::$stty) {
51809 return self::$stty;
51810 }
51811
51812 exec('stty 2>&1', $output, $exitcode);
51813
51814 return self::$stty = $exitcode === 0;
51815 }
51816
51817
51818
51819
51820
51821
51822
51823
51824
51825
51826
51827
51828
51829 private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
51830 {
51831 if ($output instanceof ConsoleOutputInterface) {
51832 $output = $output->getErrorOutput();
51833 }
51834
51835 $e = null;
51836 while (false === $attempts || $attempts--) {
51837 if (null !== $e) {
51838 $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
51839 }
51840
51841 try {
51842 return call_user_func($validator, $interviewer());
51843 } catch (\Exception $e) {
51844 }
51845 }
51846
51847 throw $e;
51848 }
51849 }
51850 <?php
51851
51852
51853
51854
51855
51856
51857
51858
51859
51860
51861 namespace Symfony\Component\Console\Helper;
51862
51863 use Symfony\Component\Console\Formatter\OutputFormatter;
51864
51865
51866
51867
51868
51869
51870 class FormatterHelper extends Helper
51871 {
51872
51873
51874
51875
51876
51877
51878
51879
51880
51881 public function formatSection($section, $message, $style = 'info')
51882 {
51883 return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
51884 }
51885
51886
51887
51888
51889
51890
51891
51892
51893
51894
51895 public function formatBlock($messages, $style, $large = false)
51896 {
51897 if (!is_array($messages)) {
51898 $messages = array($messages);
51899 }
51900
51901 $len = 0;
51902 $lines = array();
51903 foreach ($messages as $message) {
51904 $message = OutputFormatter::escape($message);
51905 $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
51906 $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
51907 }
51908
51909 $messages = $large ? array(str_repeat(' ', $len)) : array();
51910 for ($i = 0; isset($lines[$i]); ++$i) {
51911 $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
51912 }
51913 if ($large) {
51914 $messages[] = str_repeat(' ', $len);
51915 }
51916
51917 for ($i = 0; isset($messages[$i]); ++$i) {
51918 $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
51919 }
51920
51921 return implode("\n", $messages);
51922 }
51923
51924
51925
51926
51927 public function getName()
51928 {
51929 return 'formatter';
51930 }
51931 }
51932 <?php
51933
51934
51935
51936
51937
51938
51939
51940
51941
51942
51943 namespace Symfony\Component\Console\Helper;
51944
51945 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
51946
51947
51948
51949
51950
51951
51952 abstract class Helper implements HelperInterface
51953 {
51954 protected $helperSet = null;
51955
51956
51957
51958
51959
51960
51961 public function setHelperSet(HelperSet $helperSet = null)
51962 {
51963 $this->helperSet = $helperSet;
51964 }
51965
51966
51967
51968
51969
51970
51971 public function getHelperSet()
51972 {
51973 return $this->helperSet;
51974 }
51975
51976
51977
51978
51979
51980
51981
51982
51983 public static function strlen($string)
51984 {
51985 if (false === $encoding = mb_detect_encoding($string, null, true)) {
51986 return strlen($string);
51987 }
51988
51989 return mb_strwidth($string, $encoding);
51990 }
51991
51992 public static function formatTime($secs)
51993 {
51994 static $timeFormats = array(
51995 array(0, '< 1 sec'),
51996 array(1, '1 sec'),
51997 array(2, 'secs', 1),
51998 array(60, '1 min'),
51999 array(120, 'mins', 60),
52000 array(3600, '1 hr'),
52001 array(7200, 'hrs', 3600),
52002 array(86400, '1 day'),
52003 array(172800, 'days', 86400),
52004 );
52005
52006 foreach ($timeFormats as $index => $format) {
52007 if ($secs >= $format[0]) {
52008 if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
52009 || $index == count($timeFormats) - 1
52010 ) {
52011 if (2 == count($format)) {
52012 return $format[1];
52013 }
52014
52015 return floor($secs / $format[2]).' '.$format[1];
52016 }
52017 }
52018 }
52019 }
52020
52021 public static function formatMemory($memory)
52022 {
52023 if ($memory >= 1024 * 1024 * 1024) {
52024 return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
52025 }
52026
52027 if ($memory >= 1024 * 1024) {
52028 return sprintf('%.1f MiB', $memory / 1024 / 1024);
52029 }
52030
52031 if ($memory >= 1024) {
52032 return sprintf('%d KiB', $memory / 1024);
52033 }
52034
52035 return sprintf('%d B', $memory);
52036 }
52037
52038 public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
52039 {
52040 return self::strlen(self::removeDecoration($formatter, $string));
52041 }
52042
52043 public static function removeDecoration(OutputFormatterInterface $formatter, $string)
52044 {
52045 $isDecorated = $formatter->isDecorated();
52046 $formatter->setDecorated(false);
52047
52048  $string = $formatter->format($string);
52049
52050  $string = preg_replace("/\033\[[^m]*m/", '', $string);
52051 $formatter->setDecorated($isDecorated);
52052
52053 return $string;
52054 }
52055 }
52056 <?php
52057
52058
52059
52060
52061
52062
52063
52064
52065
52066
52067 namespace Symfony\Component\Console\Helper;
52068
52069
52070
52071
52072
52073
52074 interface HelperInterface
52075 {
52076
52077
52078
52079
52080
52081 public function setHelperSet(HelperSet $helperSet = null);
52082
52083
52084
52085
52086
52087
52088 public function getHelperSet();
52089
52090
52091
52092
52093
52094
52095 public function getName();
52096 }
52097 <?php
52098
52099
52100
52101
52102
52103
52104
52105
52106
52107
52108 namespace Symfony\Component\Console\Helper;
52109
52110 use Symfony\Component\Console\Command\Command;
52111 use Symfony\Component\Console\Exception\InvalidArgumentException;
52112
52113
52114
52115
52116
52117
52118 class HelperSet implements \IteratorAggregate
52119 {
52120
52121
52122
52123 private $helpers = array();
52124 private $command;
52125
52126
52127
52128
52129
52130
52131 public function __construct(array $helpers = array())
52132 {
52133 foreach ($helpers as $alias => $helper) {
52134 $this->set($helper, is_int($alias) ? null : $alias);
52135 }
52136 }
52137
52138
52139
52140
52141
52142
52143
52144 public function set(HelperInterface $helper, $alias = null)
52145 {
52146 $this->helpers[$helper->getName()] = $helper;
52147 if (null !== $alias) {
52148 $this->helpers[$alias] = $helper;
52149 }
52150
52151 $helper->setHelperSet($this);
52152 }
52153
52154
52155
52156
52157
52158
52159
52160
52161 public function has($name)
52162 {
52163 return isset($this->helpers[$name]);
52164 }
52165
52166
52167
52168
52169
52170
52171
52172
52173
52174
52175 public function get($name)
52176 {
52177 if (!$this->has($name)) {
52178 throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
52179 }
52180
52181 if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) {
52182 @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);
52183 } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) {
52184 @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);
52185 } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) {
52186 @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);
52187 }
52188
52189 return $this->helpers[$name];
52190 }
52191
52192
52193
52194
52195
52196
52197 public function setCommand(Command $command = null)
52198 {
52199 $this->command = $command;
52200 }
52201
52202
52203
52204
52205
52206
52207 public function getCommand()
52208 {
52209 return $this->command;
52210 }
52211
52212
52213
52214
52215 public function getIterator()
52216 {
52217 return new \ArrayIterator($this->helpers);
52218 }
52219 }
52220 <?php
52221
52222
52223
52224
52225
52226
52227
52228
52229
52230
52231 namespace Symfony\Component\Console\Helper;
52232
52233 use Symfony\Component\Console\Input\InputInterface;
52234 use Symfony\Component\Console\Input\InputAwareInterface;
52235
52236
52237
52238
52239
52240
52241 abstract class InputAwareHelper extends Helper implements InputAwareInterface
52242 {
52243 protected $input;
52244
52245
52246
52247
52248 public function setInput(InputInterface $input)
52249 {
52250 $this->input = $input;
52251 }
52252 }
52253 <?php
52254
52255
52256
52257
52258
52259
52260
52261
52262
52263
52264 namespace Symfony\Component\Console\Helper;
52265
52266 use Symfony\Component\Console\Output\ConsoleOutputInterface;
52267 use Symfony\Component\Console\Output\OutputInterface;
52268 use Symfony\Component\Process\Exception\ProcessFailedException;
52269 use Symfony\Component\Process\Process;
52270 use Symfony\Component\Process\ProcessBuilder;
52271
52272
52273
52274
52275
52276
52277 class ProcessHelper extends Helper
52278 {
52279
52280
52281
52282
52283
52284
52285
52286
52287
52288
52289
52290
52291 public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
52292 {
52293 if ($output instanceof ConsoleOutputInterface) {
52294 $output = $output->getErrorOutput();
52295 }
52296
52297 $formatter = $this->getHelperSet()->get('debug_formatter');
52298
52299 if (is_array($cmd)) {
52300 $process = ProcessBuilder::create($cmd)->getProcess();
52301 } elseif ($cmd instanceof Process) {
52302 $process = $cmd;
52303 } else {
52304 $process = new Process($cmd);
52305 }
52306
52307 if ($verbosity <= $output->getVerbosity()) {
52308 $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
52309 }
52310
52311 if ($output->isDebug()) {
52312 $callback = $this->wrapCallback($output, $process, $callback);
52313 }
52314
52315 $process->run($callback);
52316
52317 if ($verbosity <= $output->getVerbosity()) {
52318 $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
52319 $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
52320 }
52321
52322 if (!$process->isSuccessful() && null !== $error) {
52323 $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
52324 }
52325
52326 return $process;
52327 }
52328
52329
52330
52331
52332
52333
52334
52335
52336
52337
52338
52339
52340
52341
52342
52343
52344
52345
52346
52347 public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
52348 {
52349 $process = $this->run($output, $cmd, $error, $callback);
52350
52351 if (!$process->isSuccessful()) {
52352 throw new ProcessFailedException($process);
52353 }
52354
52355 return $process;
52356 }
52357
52358
52359
52360
52361
52362
52363
52364
52365
52366
52367 public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
52368 {
52369 if ($output instanceof ConsoleOutputInterface) {
52370 $output = $output->getErrorOutput();
52371 }
52372
52373 $formatter = $this->getHelperSet()->get('debug_formatter');
52374
52375 $that = $this;
52376
52377 return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
52378 $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
52379
52380 if (null !== $callback) {
52381 call_user_func($callback, $type, $buffer);
52382 }
52383 };
52384 }
52385
52386
52387
52388
52389
52390
52391 public function escapeString($str)
52392 {
52393 return str_replace('<', '\\<', $str);
52394 }
52395
52396
52397
52398
52399 public function getName()
52400 {
52401 return 'process';
52402 }
52403 }
52404 <?php
52405
52406
52407
52408
52409
52410
52411
52412
52413
52414
52415 namespace Symfony\Component\Console\Helper;
52416
52417 use Symfony\Component\Console\Output\ConsoleOutputInterface;
52418 use Symfony\Component\Console\Output\OutputInterface;
52419 use Symfony\Component\Console\Exception\LogicException;
52420
52421
52422
52423
52424
52425
52426
52427 class ProgressBar
52428 {
52429
52430  private $barWidth = 28;
52431 private $barChar;
52432 private $emptyBarChar = '-';
52433 private $progressChar = '>';
52434 private $format;
52435 private $internalFormat;
52436 private $redrawFreq = 1;
52437
52438
52439
52440
52441 private $output;
52442 private $step = 0;
52443 private $max;
52444 private $startTime;
52445 private $stepWidth;
52446 private $percent = 0.0;
52447 private $formatLineCount;
52448 private $messages = array();
52449 private $overwrite = true;
52450 private $firstRun = true;
52451
52452 private static $formatters;
52453 private static $formats;
52454
52455
52456
52457
52458
52459
52460
52461 public function __construct(OutputInterface $output, $max = 0)
52462 {
52463 if ($output instanceof ConsoleOutputInterface) {
52464 $output = $output->getErrorOutput();
52465 }
52466
52467 $this->output = $output;
52468 $this->setMaxSteps($max);
52469
52470 if (!$this->output->isDecorated()) {
52471
52472  $this->overwrite = false;
52473
52474
52475  $this->setRedrawFrequency($max / 10);
52476 }
52477
52478 $this->startTime = time();
52479 }
52480
52481
52482
52483
52484
52485
52486
52487
52488
52489 public static function setPlaceholderFormatterDefinition($name, $callable)
52490 {
52491 if (!self::$formatters) {
52492 self::$formatters = self::initPlaceholderFormatters();
52493 }
52494
52495 self::$formatters[$name] = $callable;
52496 }
52497
52498
52499
52500
52501
52502
52503
52504
52505 public static function getPlaceholderFormatterDefinition($name)
52506 {
52507 if (!self::$formatters) {
52508 self::$formatters = self::initPlaceholderFormatters();
52509 }
52510
52511 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
52512 }
52513
52514
52515
52516
52517
52518
52519
52520
52521
52522 public static function setFormatDefinition($name, $format)
52523 {
52524 if (!self::$formats) {
52525 self::$formats = self::initFormats();
52526 }
52527
52528 self::$formats[$name] = $format;
52529 }
52530
52531
52532
52533
52534
52535
52536
52537
52538 public static function getFormatDefinition($name)
52539 {
52540 if (!self::$formats) {
52541 self::$formats = self::initFormats();
52542 }
52543
52544 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
52545 }
52546
52547
52548
52549
52550
52551
52552
52553
52554
52555
52556
52557 public function setMessage($message, $name = 'message')
52558 {
52559 $this->messages[$name] = $message;
52560 }
52561
52562 public function getMessage($name = 'message')
52563 {
52564 return $this->messages[$name];
52565 }
52566
52567
52568
52569
52570
52571
52572 public function getStartTime()
52573 {
52574 return $this->startTime;
52575 }
52576
52577
52578
52579
52580
52581
52582 public function getMaxSteps()
52583 {
52584 return $this->max;
52585 }
52586
52587
52588
52589
52590
52591
52592
52593
52594 public function getStep()
52595 {
52596 @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);
52597
52598 return $this->getProgress();
52599 }
52600
52601
52602
52603
52604
52605
52606 public function getProgress()
52607 {
52608 return $this->step;
52609 }
52610
52611
52612
52613
52614
52615
52616
52617
52618 public function getStepWidth()
52619 {
52620 return $this->stepWidth;
52621 }
52622
52623
52624
52625
52626
52627
52628 public function getProgressPercent()
52629 {
52630 return $this->percent;
52631 }
52632
52633
52634
52635
52636
52637
52638 public function setBarWidth($size)
52639 {
52640 $this->barWidth = (int) $size;
52641 }
52642
52643
52644
52645
52646
52647
52648 public function getBarWidth()
52649 {
52650 return $this->barWidth;
52651 }
52652
52653
52654
52655
52656
52657
52658 public function setBarCharacter($char)
52659 {
52660 $this->barChar = $char;
52661 }
52662
52663
52664
52665
52666
52667
52668 public function getBarCharacter()
52669 {
52670 if (null === $this->barChar) {
52671 return $this->max ? '=' : $this->emptyBarChar;
52672 }
52673
52674 return $this->barChar;
52675 }
52676
52677
52678
52679
52680
52681
52682 public function setEmptyBarCharacter($char)
52683 {
52684 $this->emptyBarChar = $char;
52685 }
52686
52687
52688
52689
52690
52691
52692 public function getEmptyBarCharacter()
52693 {
52694 return $this->emptyBarChar;
52695 }
52696
52697
52698
52699
52700
52701
52702 public function setProgressCharacter($char)
52703 {
52704 $this->progressChar = $char;
52705 }
52706
52707
52708
52709
52710
52711
52712 public function getProgressCharacter()
52713 {
52714 return $this->progressChar;
52715 }
52716
52717
52718
52719
52720
52721
52722 public function setFormat($format)
52723 {
52724 $this->format = null;
52725 $this->internalFormat = $format;
52726 }
52727
52728
52729
52730
52731
52732
52733 public function setRedrawFrequency($freq)
52734 {
52735 $this->redrawFreq = max((int) $freq, 1);
52736 }
52737
52738
52739
52740
52741
52742
52743 public function start($max = null)
52744 {
52745 $this->startTime = time();
52746 $this->step = 0;
52747 $this->percent = 0.0;
52748
52749 if (null !== $max) {
52750 $this->setMaxSteps($max);
52751 }
52752
52753 $this->display();
52754 }
52755
52756
52757
52758
52759
52760
52761
52762
52763 public function advance($step = 1)
52764 {
52765 $this->setProgress($this->step + $step);
52766 }
52767
52768
52769
52770
52771
52772
52773
52774
52775
52776
52777 public function setCurrent($step)
52778 {
52779 @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);
52780
52781 $this->setProgress($step);
52782 }
52783
52784
52785
52786
52787
52788
52789 public function setOverwrite($overwrite)
52790 {
52791 $this->overwrite = (bool) $overwrite;
52792 }
52793
52794
52795
52796
52797
52798
52799
52800
52801 public function setProgress($step)
52802 {
52803 $step = (int) $step;
52804 if ($step < $this->step) {
52805 throw new LogicException('You can\'t regress the progress bar.');
52806 }
52807
52808 if ($this->max && $step > $this->max) {
52809 $this->max = $step;
52810 }
52811
52812 $prevPeriod = (int) ($this->step / $this->redrawFreq);
52813 $currPeriod = (int) ($step / $this->redrawFreq);
52814 $this->step = $step;
52815 $this->percent = $this->max ? (float) $this->step / $this->max : 0;
52816 if ($prevPeriod !== $currPeriod || $this->max === $step) {
52817 $this->display();
52818 }
52819 }
52820
52821
52822
52823
52824 public function finish()
52825 {
52826 if (!$this->max) {
52827 $this->max = $this->step;
52828 }
52829
52830 if ($this->step === $this->max && !$this->overwrite) {
52831
52832  return;
52833 }
52834
52835 $this->setProgress($this->max);
52836 }
52837
52838
52839
52840
52841 public function display()
52842 {
52843 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
52844 return;
52845 }
52846
52847 if (null === $this->format) {
52848 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
52849 }
52850
52851
52852  $self = $this;
52853 $output = $this->output;
52854 $messages = $this->messages;
52855 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
52856 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
52857 $text = call_user_func($formatter, $self, $output);
52858 } elseif (isset($messages[$matches[1]])) {
52859 $text = $messages[$matches[1]];
52860 } else {
52861 return $matches[0];
52862 }
52863
52864 if (isset($matches[2])) {
52865 $text = sprintf('%'.$matches[2], $text);
52866 }
52867
52868 return $text;
52869 }, $this->format));
52870 }
52871
52872
52873
52874
52875
52876
52877
52878
52879 public function clear()
52880 {
52881 if (!$this->overwrite) {
52882 return;
52883 }
52884
52885 if (null === $this->format) {
52886 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
52887 }
52888
52889 $this->overwrite('');
52890 }
52891
52892
52893
52894
52895
52896
52897 private function setRealFormat($format)
52898 {
52899
52900  if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
52901 $this->format = self::getFormatDefinition($format.'_nomax');
52902 } elseif (null !== self::getFormatDefinition($format)) {
52903 $this->format = self::getFormatDefinition($format);
52904 } else {
52905 $this->format = $format;
52906 }
52907
52908 $this->formatLineCount = substr_count($this->format, "\n");
52909 }
52910
52911
52912
52913
52914
52915
52916 private function setMaxSteps($max)
52917 {
52918 $this->max = max(0, (int) $max);
52919 $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
52920 }
52921
52922
52923
52924
52925
52926
52927 private function overwrite($message)
52928 {
52929 if ($this->overwrite) {
52930 if (!$this->firstRun) {
52931
52932  $this->output->write("\x0D");
52933
52934
52935  $this->output->write("\x1B[2K");
52936
52937
52938  if ($this->formatLineCount > 0) {
52939 $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
52940 }
52941 }
52942 } elseif ($this->step > 0) {
52943 $this->output->writeln('');
52944 }
52945
52946 $this->firstRun = false;
52947
52948 $this->output->write($message);
52949 }
52950
52951 private function determineBestFormat()
52952 {
52953 switch ($this->output->getVerbosity()) {
52954
52955  case OutputInterface::VERBOSITY_VERBOSE:
52956 return $this->max ? 'verbose' : 'verbose_nomax';
52957 case OutputInterface::VERBOSITY_VERY_VERBOSE:
52958 return $this->max ? 'very_verbose' : 'very_verbose_nomax';
52959 case OutputInterface::VERBOSITY_DEBUG:
52960 return $this->max ? 'debug' : 'debug_nomax';
52961 default:
52962 return $this->max ? 'normal' : 'normal_nomax';
52963 }
52964 }
52965
52966 private static function initPlaceholderFormatters()
52967 {
52968 return array(
52969 'bar' => function (ProgressBar $bar, OutputInterface $output) {
52970 $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
52971 $display = str_repeat($bar->getBarCharacter(), $completeBars);
52972 if ($completeBars < $bar->getBarWidth()) {
52973 $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
52974 $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
52975 }
52976
52977 return $display;
52978 },
52979 'elapsed' => function (ProgressBar $bar) {
52980 return Helper::formatTime(time() - $bar->getStartTime());
52981 },
52982 'remaining' => function (ProgressBar $bar) {
52983 if (!$bar->getMaxSteps()) {
52984 throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
52985 }
52986
52987 if (!$bar->getProgress()) {
52988 $remaining = 0;
52989 } else {
52990 $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
52991 }
52992
52993 return Helper::formatTime($remaining);
52994 },
52995 'estimated' => function (ProgressBar $bar) {
52996 if (!$bar->getMaxSteps()) {
52997 throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
52998 }
52999
53000 if (!$bar->getProgress()) {
53001 $estimated = 0;
53002 } else {
53003 $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
53004 }
53005
53006 return Helper::formatTime($estimated);
53007 },
53008 'memory' => function (ProgressBar $bar) {
53009 return Helper::formatMemory(memory_get_usage(true));
53010 },
53011 'current' => function (ProgressBar $bar) {
53012 return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
53013 },
53014 'max' => function (ProgressBar $bar) {
53015 return $bar->getMaxSteps();
53016 },
53017 'percent' => function (ProgressBar $bar) {
53018 return floor($bar->getProgressPercent() * 100);
53019 },
53020 );
53021 }
53022
53023 private static function initFormats()
53024 {
53025 return array(
53026 'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
53027 'normal_nomax' => ' %current% [%bar%]',
53028
53029 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
53030 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
53031
53032 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
53033 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
53034
53035 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
53036 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
53037 );
53038 }
53039 }
53040 <?php
53041
53042
53043
53044
53045
53046
53047
53048
53049
53050
53051 namespace Symfony\Component\Console\Helper;
53052
53053 use Symfony\Component\Console\Output\NullOutput;
53054 use Symfony\Component\Console\Output\ConsoleOutputInterface;
53055 use Symfony\Component\Console\Output\OutputInterface;
53056 use Symfony\Component\Console\Exception\LogicException;
53057
53058
53059
53060
53061
53062
53063
53064
53065
53066
53067 class ProgressHelper extends Helper
53068 {
53069 const FORMAT_QUIET = ' %percent%%';
53070 const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
53071 const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
53072 const FORMAT_QUIET_NOMAX = ' %current%';
53073 const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
53074 const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
53075
53076
53077  private $barWidth = 28;
53078 private $barChar = '=';
53079 private $emptyBarChar = '-';
53080 private $progressChar = '>';
53081 private $format = null;
53082 private $redrawFreq = 1;
53083
53084 private $lastMessagesLength;
53085 private $barCharOriginal;
53086
53087
53088
53089
53090 private $output;
53091
53092
53093
53094
53095
53096
53097 private $current;
53098
53099
53100
53101
53102
53103
53104 private $max;
53105
53106
53107
53108
53109
53110
53111 private $startTime;
53112
53113
53114
53115
53116
53117
53118 private $defaultFormatVars = array(
53119 'current',
53120 'max',
53121 'bar',
53122 'percent',
53123 'elapsed',
53124 );
53125
53126
53127
53128
53129
53130
53131 private $formatVars;
53132
53133
53134
53135
53136
53137
53138 private $widths = array(
53139 'current' => 4,
53140 'max' => 4,
53141 'percent' => 3,
53142 'elapsed' => 6,
53143 );
53144
53145
53146
53147
53148
53149
53150 private $timeFormats = array(
53151 array(0, '???'),
53152 array(2, '1 sec'),
53153 array(59, 'secs', 1),
53154 array(60, '1 min'),
53155 array(3600, 'mins', 60),
53156 array(5400, '1 hr'),
53157 array(86400, 'hrs', 3600),
53158 array(129600, '1 day'),
53159 array(604800, 'days', 86400),
53160 );
53161
53162 public function __construct($triggerDeprecationError = true)
53163 {
53164 if ($triggerDeprecationError) {
53165 @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);
53166 }
53167 }
53168
53169
53170
53171
53172
53173
53174 public function setBarWidth($size)
53175 {
53176 $this->barWidth = (int) $size;
53177 }
53178
53179
53180
53181
53182
53183
53184 public function setBarCharacter($char)
53185 {
53186 $this->barChar = $char;
53187 }
53188
53189
53190
53191
53192
53193
53194 public function setEmptyBarCharacter($char)
53195 {
53196 $this->emptyBarChar = $char;
53197 }
53198
53199
53200
53201
53202
53203
53204 public function setProgressCharacter($char)
53205 {
53206 $this->progressChar = $char;
53207 }
53208
53209
53210
53211
53212
53213
53214 public function setFormat($format)
53215 {
53216 $this->format = $format;
53217 }
53218
53219
53220
53221
53222
53223
53224 public function setRedrawFrequency($freq)
53225 {
53226 $this->redrawFreq = (int) $freq;
53227 }
53228
53229
53230
53231
53232
53233
53234
53235 public function start(OutputInterface $output, $max = null)
53236 {
53237 if ($output instanceof ConsoleOutputInterface) {
53238 $output = $output->getErrorOutput();
53239 }
53240
53241 $this->startTime = time();
53242 $this->current = 0;
53243 $this->max = (int) $max;
53244
53245
53246  $this->output = $output->isDecorated() ? $output : new NullOutput();
53247 $this->lastMessagesLength = 0;
53248 $this->barCharOriginal = '';
53249
53250 if (null === $this->format) {
53251 switch ($output->getVerbosity()) {
53252 case OutputInterface::VERBOSITY_QUIET:
53253 $this->format = self::FORMAT_QUIET_NOMAX;
53254 if ($this->max > 0) {
53255 $this->format = self::FORMAT_QUIET;
53256 }
53257 break;
53258 case OutputInterface::VERBOSITY_VERBOSE:
53259 case OutputInterface::VERBOSITY_VERY_VERBOSE:
53260 case OutputInterface::VERBOSITY_DEBUG:
53261 $this->format = self::FORMAT_VERBOSE_NOMAX;
53262 if ($this->max > 0) {
53263 $this->format = self::FORMAT_VERBOSE;
53264 }
53265 break;
53266 default:
53267 $this->format = self::FORMAT_NORMAL_NOMAX;
53268 if ($this->max > 0) {
53269 $this->format = self::FORMAT_NORMAL;
53270 }
53271 break;
53272 }
53273 }
53274
53275 $this->initialize();
53276 }
53277
53278
53279
53280
53281
53282
53283
53284
53285
53286 public function advance($step = 1, $redraw = false)
53287 {
53288 $this->setCurrent($this->current + $step, $redraw);
53289 }
53290
53291
53292
53293
53294
53295
53296
53297
53298
53299 public function setCurrent($current, $redraw = false)
53300 {
53301 if (null === $this->startTime) {
53302 throw new LogicException('You must start the progress bar before calling setCurrent().');
53303 }
53304
53305 $current = (int) $current;
53306
53307 if ($current < $this->current) {
53308 throw new LogicException('You can\'t regress the progress bar');
53309 }
53310
53311 if (0 === $this->current) {
53312 $redraw = true;
53313 }
53314
53315 $prevPeriod = (int) ($this->current / $this->redrawFreq);
53316
53317 $this->current = $current;
53318
53319 $currPeriod = (int) ($this->current / $this->redrawFreq);
53320 if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
53321 $this->display();
53322 }
53323 }
53324
53325
53326
53327
53328
53329
53330
53331
53332 public function display($finish = false)
53333 {
53334 if (null === $this->startTime) {
53335 throw new LogicException('You must start the progress bar before calling display().');
53336 }
53337
53338 $message = $this->format;
53339 foreach ($this->generate($finish) as $name => $value) {
53340 $message = str_replace("%{$name}%", $value, $message);
53341 }
53342 $this->overwrite($this->output, $message);
53343 }
53344
53345
53346
53347
53348
53349
53350
53351
53352 public function clear()
53353 {
53354 $this->overwrite($this->output, '');
53355 }
53356
53357
53358
53359
53360 public function finish()
53361 {
53362 if (null === $this->startTime) {
53363 throw new LogicException('You must start the progress bar before calling finish().');
53364 }
53365
53366 if (null !== $this->startTime) {
53367 if (!$this->max) {
53368 $this->barChar = $this->barCharOriginal;
53369 $this->display(true);
53370 }
53371 $this->startTime = null;
53372 $this->output->writeln('');
53373 $this->output = null;
53374 }
53375 }
53376
53377
53378
53379
53380 private function initialize()
53381 {
53382 $this->formatVars = array();
53383 foreach ($this->defaultFormatVars as $var) {
53384 if (false !== strpos($this->format, "%{$var}%")) {
53385 $this->formatVars[$var] = true;
53386 }
53387 }
53388
53389 if ($this->max > 0) {
53390 $this->widths['max'] = $this->strlen($this->max);
53391 $this->widths['current'] = $this->widths['max'];
53392 } else {
53393 $this->barCharOriginal = $this->barChar;
53394 $this->barChar = $this->emptyBarChar;
53395 }
53396 }
53397
53398
53399
53400
53401
53402
53403
53404
53405 private function generate($finish = false)
53406 {
53407 $vars = array();
53408 $percent = 0;
53409 if ($this->max > 0) {
53410 $percent = (float) $this->current / $this->max;
53411 }
53412
53413 if (isset($this->formatVars['bar'])) {
53414 if ($this->max > 0) {
53415 $completeBars = floor($percent * $this->barWidth);
53416 } else {
53417 if (!$finish) {
53418 $completeBars = floor($this->current % $this->barWidth);
53419 } else {
53420 $completeBars = $this->barWidth;
53421 }
53422 }
53423
53424 $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
53425 $bar = str_repeat($this->barChar, $completeBars);
53426 if ($completeBars < $this->barWidth) {
53427 $bar .= $this->progressChar;
53428 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
53429 }
53430
53431 $vars['bar'] = $bar;
53432 }
53433
53434 if (isset($this->formatVars['elapsed'])) {
53435 $elapsed = time() - $this->startTime;
53436 $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
53437 }
53438
53439 if (isset($this->formatVars['current'])) {
53440 $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
53441 }
53442
53443 if (isset($this->formatVars['max'])) {
53444 $vars['max'] = $this->max;
53445 }
53446
53447 if (isset($this->formatVars['percent'])) {
53448 $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
53449 }
53450
53451 return $vars;
53452 }
53453
53454
53455
53456
53457
53458
53459
53460
53461 private function humaneTime($secs)
53462 {
53463 $text = '';
53464 foreach ($this->timeFormats as $format) {
53465 if ($secs < $format[0]) {
53466 if (count($format) == 2) {
53467 $text = $format[1];
53468 break;
53469 } else {
53470 $text = ceil($secs / $format[2]).' '.$format[1];
53471 break;
53472 }
53473 }
53474 }
53475
53476 return $text;
53477 }
53478
53479
53480
53481
53482
53483
53484
53485 private function overwrite(OutputInterface $output, $message)
53486 {
53487 $length = $this->strlen($message);
53488
53489
53490  if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
53491 $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
53492 }
53493
53494
53495  $output->write("\x0D");
53496 $output->write($message);
53497
53498 $this->lastMessagesLength = $this->strlen($message);
53499 }
53500
53501
53502
53503
53504 public function getName()
53505 {
53506 return 'progress';
53507 }
53508 }
53509 <?php
53510
53511
53512
53513
53514
53515
53516
53517
53518
53519
53520 namespace Symfony\Component\Console\Helper;
53521
53522 use Symfony\Component\Console\Exception\InvalidArgumentException;
53523 use Symfony\Component\Console\Exception\LogicException;
53524 use Symfony\Component\Console\Output\OutputInterface;
53525
53526
53527
53528
53529 class ProgressIndicator
53530 {
53531 private $output;
53532 private $startTime;
53533 private $format;
53534 private $message;
53535 private $indicatorValues;
53536 private $indicatorCurrent;
53537 private $indicatorChangeInterval;
53538 private $indicatorUpdateTime;
53539 private $started = false;
53540
53541 private static $formatters;
53542 private static $formats;
53543
53544
53545
53546
53547
53548
53549
53550 public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
53551 {
53552 $this->output = $output;
53553
53554 if (null === $format) {
53555 $format = $this->determineBestFormat();
53556 }
53557
53558 if (null === $indicatorValues) {
53559 $indicatorValues = array('-', '\\', '|', '/');
53560 }
53561
53562 $indicatorValues = array_values($indicatorValues);
53563
53564 if (2 > count($indicatorValues)) {
53565 throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
53566 }
53567
53568 $this->format = self::getFormatDefinition($format);
53569 $this->indicatorChangeInterval = $indicatorChangeInterval;
53570 $this->indicatorValues = $indicatorValues;
53571 $this->startTime = time();
53572 }
53573
53574
53575
53576
53577
53578
53579 public function setMessage($message)
53580 {
53581 $this->message = $message;
53582
53583 $this->display();
53584 }
53585
53586
53587
53588
53589
53590
53591
53592
53593 public function getMessage()
53594 {
53595 return $this->message;
53596 }
53597
53598
53599
53600
53601
53602
53603
53604
53605 public function getStartTime()
53606 {
53607 return $this->startTime;
53608 }
53609
53610
53611
53612
53613
53614
53615
53616
53617 public function getCurrentValue()
53618 {
53619 return $this->indicatorValues[$this->indicatorCurrent % count($this->indicatorValues)];
53620 }
53621
53622
53623
53624
53625
53626
53627 public function start($message)
53628 {
53629 if ($this->started) {
53630 throw new LogicException('Progress indicator already started.');
53631 }
53632
53633 $this->message = $message;
53634 $this->started = true;
53635 $this->startTime = time();
53636 $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
53637 $this->indicatorCurrent = 0;
53638
53639 $this->display();
53640 }
53641
53642
53643
53644
53645 public function advance()
53646 {
53647 if (!$this->started) {
53648 throw new LogicException('Progress indicator has not yet been started.');
53649 }
53650
53651 if (!$this->output->isDecorated()) {
53652 return;
53653 }
53654
53655 $currentTime = $this->getCurrentTimeInMilliseconds();
53656
53657 if ($currentTime < $this->indicatorUpdateTime) {
53658 return;
53659 }
53660
53661 $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
53662 ++$this->indicatorCurrent;
53663
53664 $this->display();
53665 }
53666
53667
53668
53669
53670
53671
53672 public function finish($message)
53673 {
53674 if (!$this->started) {
53675 throw new LogicException('Progress indicator has not yet been started.');
53676 }
53677
53678 $this->message = $message;
53679 $this->display();
53680 $this->output->writeln('');
53681 $this->started = false;
53682 }
53683
53684
53685
53686
53687
53688
53689
53690
53691 public static function getFormatDefinition($name)
53692 {
53693 if (!self::$formats) {
53694 self::$formats = self::initFormats();
53695 }
53696
53697 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
53698 }
53699
53700
53701
53702
53703
53704
53705
53706
53707
53708 public static function setPlaceholderFormatterDefinition($name, $callable)
53709 {
53710 if (!self::$formatters) {
53711 self::$formatters = self::initPlaceholderFormatters();
53712 }
53713
53714 self::$formatters[$name] = $callable;
53715 }
53716
53717
53718
53719
53720
53721
53722
53723
53724 public static function getPlaceholderFormatterDefinition($name)
53725 {
53726 if (!self::$formatters) {
53727 self::$formatters = self::initPlaceholderFormatters();
53728 }
53729
53730 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
53731 }
53732
53733 private function display()
53734 {
53735 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
53736 return;
53737 }
53738
53739 $self = $this;
53740
53741 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
53742 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
53743 return call_user_func($formatter, $self);
53744 }
53745
53746 return $matches[0];
53747 }, $this->format));
53748 }
53749
53750 private function determineBestFormat()
53751 {
53752 switch ($this->output->getVerbosity()) {
53753
53754  case OutputInterface::VERBOSITY_VERBOSE:
53755 return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
53756 case OutputInterface::VERBOSITY_VERY_VERBOSE:
53757 case OutputInterface::VERBOSITY_DEBUG:
53758 return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
53759 default:
53760 return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
53761 }
53762 }
53763
53764
53765
53766
53767
53768
53769 private function overwrite($message)
53770 {
53771 if ($this->output->isDecorated()) {
53772 $this->output->write("\x0D\x1B[2K");
53773 $this->output->write($message);
53774 } else {
53775 $this->output->writeln($message);
53776 }
53777 }
53778
53779 private function getCurrentTimeInMilliseconds()
53780 {
53781 return round(microtime(true) * 1000);
53782 }
53783
53784 private static function initPlaceholderFormatters()
53785 {
53786 return array(
53787 'indicator' => function (ProgressIndicator $indicator) {
53788 return $indicator->getCurrentValue();
53789 },
53790 'message' => function (ProgressIndicator $indicator) {
53791 return $indicator->getMessage();
53792 },
53793 'elapsed' => function (ProgressIndicator $indicator) {
53794 return Helper::formatTime(time() - $indicator->getStartTime());
53795 },
53796 'memory' => function () {
53797 return Helper::formatMemory(memory_get_usage(true));
53798 },
53799 );
53800 }
53801
53802 private static function initFormats()
53803 {
53804 return array(
53805 'normal' => ' %indicator% %message%',
53806 'normal_no_ansi' => ' %message%',
53807
53808 'verbose' => ' %indicator% %message% (%elapsed:6s%)',
53809 'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
53810
53811 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
53812 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
53813 );
53814 }
53815 }
53816 <?php
53817
53818
53819
53820
53821
53822
53823
53824
53825
53826
53827 namespace Symfony\Component\Console\Helper;
53828
53829 use Symfony\Component\Console\Exception\InvalidArgumentException;
53830 use Symfony\Component\Console\Exception\RuntimeException;
53831 use Symfony\Component\Console\Input\InputInterface;
53832 use Symfony\Component\Console\Output\ConsoleOutputInterface;
53833 use Symfony\Component\Console\Output\OutputInterface;
53834 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
53835 use Symfony\Component\Console\Question\Question;
53836 use Symfony\Component\Console\Question\ChoiceQuestion;
53837
53838
53839
53840
53841
53842
53843 class QuestionHelper extends Helper
53844 {
53845 private $inputStream;
53846 private static $shell;
53847 private static $stty;
53848
53849
53850
53851
53852
53853
53854
53855
53856
53857
53858
53859
53860 public function ask(InputInterface $input, OutputInterface $output, Question $question)
53861 {
53862 if ($output instanceof ConsoleOutputInterface) {
53863 $output = $output->getErrorOutput();
53864 }
53865
53866 if (!$input->isInteractive()) {
53867 return $question->getDefault();
53868 }
53869
53870 if (!$question->getValidator()) {
53871 return $this->doAsk($output, $question);
53872 }
53873
53874 $that = $this;
53875
53876 $interviewer = function () use ($output, $question, $that) {
53877 return $that->doAsk($output, $question);
53878 };
53879
53880 return $this->validateAttempts($interviewer, $output, $question);
53881 }
53882
53883
53884
53885
53886
53887
53888
53889
53890
53891
53892 public function setInputStream($stream)
53893 {
53894 if (!is_resource($stream)) {
53895 throw new InvalidArgumentException('Input stream must be a valid resource.');
53896 }
53897
53898 $this->inputStream = $stream;
53899 }
53900
53901
53902
53903
53904
53905
53906 public function getInputStream()
53907 {
53908 return $this->inputStream;
53909 }
53910
53911
53912
53913
53914 public function getName()
53915 {
53916 return 'question';
53917 }
53918
53919
53920
53921
53922
53923
53924
53925
53926
53927
53928
53929
53930
53931 public function doAsk(OutputInterface $output, Question $question)
53932 {
53933 $this->writePrompt($output, $question);
53934
53935 $inputStream = $this->inputStream ?: STDIN;
53936 $autocomplete = $question->getAutocompleterValues();
53937
53938 if (null === $autocomplete || !$this->hasSttyAvailable()) {
53939 $ret = false;
53940 if ($question->isHidden()) {
53941 try {
53942 $ret = trim($this->getHiddenResponse($output, $inputStream));
53943 } catch (RuntimeException $e) {
53944 if (!$question->isHiddenFallback()) {
53945 throw $e;
53946 }
53947 }
53948 }
53949
53950 if (false === $ret) {
53951 $ret = fgets($inputStream, 4096);
53952 if (false === $ret) {
53953 throw new RuntimeException('Aborted');
53954 }
53955 $ret = trim($ret);
53956 }
53957 } else {
53958 $ret = trim($this->autocomplete($output, $question, $inputStream));
53959 }
53960
53961 $ret = strlen($ret) > 0 ? $ret : $question->getDefault();
53962
53963 if ($normalizer = $question->getNormalizer()) {
53964 return $normalizer($ret);
53965 }
53966
53967 return $ret;
53968 }
53969
53970
53971
53972
53973
53974
53975
53976 protected function writePrompt(OutputInterface $output, Question $question)
53977 {
53978 $message = $question->getQuestion();
53979
53980 if ($question instanceof ChoiceQuestion) {
53981 $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
53982
53983 $messages = (array) $question->getQuestion();
53984 foreach ($question->getChoices() as $key => $value) {
53985 $width = $maxWidth - $this->strlen($key);
53986 $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
53987 }
53988
53989 $output->writeln($messages);
53990
53991 $message = $question->getPrompt();
53992 }
53993
53994 $output->write($message);
53995 }
53996
53997
53998
53999
54000
54001
54002
54003 protected function writeError(OutputInterface $output, \Exception $error)
54004 {
54005 if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
54006 $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
54007 } else {
54008 $message = '<error>'.$error->getMessage().'</error>';
54009 }
54010
54011 $output->writeln($message);
54012 }
54013
54014
54015
54016
54017
54018
54019
54020
54021
54022
54023 private function autocomplete(OutputInterface $output, Question $question, $inputStream)
54024 {
54025 $autocomplete = $question->getAutocompleterValues();
54026 $ret = '';
54027
54028 $i = 0;
54029 $ofs = -1;
54030 $matches = $autocomplete;
54031 $numMatches = count($matches);
54032
54033 $sttyMode = shell_exec('stty -g');
54034
54035
54036  shell_exec('stty -icanon -echo');
54037
54038
54039  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
54040
54041
54042  while (!feof($inputStream)) {
54043 $c = fread($inputStream, 1);
54044
54045
54046  if ("\177" === $c) {
54047 if (0 === $numMatches && 0 !== $i) {
54048 --$i;
54049
54050  $output->write("\033[1D");
54051 }
54052
54053 if ($i === 0) {
54054 $ofs = -1;
54055 $matches = $autocomplete;
54056 $numMatches = count($matches);
54057 } else {
54058 $numMatches = 0;
54059 }
54060
54061
54062  $ret = substr($ret, 0, $i);
54063 } elseif ("\033" === $c) {
54064
54065  $c .= fread($inputStream, 2);
54066
54067
54068  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
54069 if ('A' === $c[2] && -1 === $ofs) {
54070 $ofs = 0;
54071 }
54072
54073 if (0 === $numMatches) {
54074 continue;
54075 }
54076
54077 $ofs += ('A' === $c[2]) ? -1 : 1;
54078 $ofs = ($numMatches + $ofs) % $numMatches;
54079 }
54080 } elseif (ord($c) < 32) {
54081 if ("\t" === $c || "\n" === $c) {
54082 if ($numMatches > 0 && -1 !== $ofs) {
54083 $ret = $matches[$ofs];
54084
54085  $output->write(substr($ret, $i));
54086 $i = strlen($ret);
54087 }
54088
54089 if ("\n" === $c) {
54090 $output->write($c);
54091 break;
54092 }
54093
54094 $numMatches = 0;
54095 }
54096
54097 continue;
54098 } else {
54099 $output->write($c);
54100 $ret .= $c;
54101 ++$i;
54102
54103 $numMatches = 0;
54104 $ofs = 0;
54105
54106 foreach ($autocomplete as $value) {
54107
54108  if (0 === strpos($value, $ret) && $i !== strlen($value)) {
54109 $matches[$numMatches++] = $value;
54110 }
54111 }
54112 }
54113
54114
54115  $output->write("\033[K");
54116
54117 if ($numMatches > 0 && -1 !== $ofs) {
54118
54119  $output->write("\0337");
54120
54121  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
54122
54123  $output->write("\0338");
54124 }
54125 }
54126
54127
54128  shell_exec(sprintf('stty %s', $sttyMode));
54129
54130 return $ret;
54131 }
54132
54133
54134
54135
54136
54137
54138
54139
54140
54141
54142
54143 private function getHiddenResponse(OutputInterface $output, $inputStream)
54144 {
54145 if ('\\' === DIRECTORY_SEPARATOR) {
54146 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
54147
54148
54149  if ('phar:' === substr(__FILE__, 0, 5)) {
54150 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
54151 copy($exe, $tmpExe);
54152 $exe = $tmpExe;
54153 }
54154
54155 $value = rtrim(shell_exec($exe));
54156 $output->writeln('');
54157
54158 if (isset($tmpExe)) {
54159 unlink($tmpExe);
54160 }
54161
54162 return $value;
54163 }
54164
54165 if ($this->hasSttyAvailable()) {
54166 $sttyMode = shell_exec('stty -g');
54167
54168 shell_exec('stty -echo');
54169 $value = fgets($inputStream, 4096);
54170 shell_exec(sprintf('stty %s', $sttyMode));
54171
54172 if (false === $value) {
54173 throw new RuntimeException('Aborted');
54174 }
54175
54176 $value = trim($value);
54177 $output->writeln('');
54178
54179 return $value;
54180 }
54181
54182 if (false !== $shell = $this->getShell()) {
54183 $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
54184 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
54185 $value = rtrim(shell_exec($command));
54186 $output->writeln('');
54187
54188 return $value;
54189 }
54190
54191 throw new RuntimeException('Unable to hide the response.');
54192 }
54193
54194
54195
54196
54197
54198
54199
54200
54201
54202
54203
54204
54205 private function validateAttempts($interviewer, OutputInterface $output, Question $question)
54206 {
54207 $error = null;
54208 $attempts = $question->getMaxAttempts();
54209 while (null === $attempts || $attempts--) {
54210 if (null !== $error) {
54211 $this->writeError($output, $error);
54212 }
54213
54214 try {
54215 return call_user_func($question->getValidator(), $interviewer());
54216 } catch (RuntimeException $e) {
54217 throw $e;
54218 } catch (\Exception $error) {
54219 }
54220 }
54221
54222 throw $error;
54223 }
54224
54225
54226
54227
54228
54229
54230 private function getShell()
54231 {
54232 if (null !== self::$shell) {
54233 return self::$shell;
54234 }
54235
54236 self::$shell = false;
54237
54238 if (file_exists('/usr/bin/env')) {
54239
54240  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
54241 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
54242 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
54243 self::$shell = $sh;
54244 break;
54245 }
54246 }
54247 }
54248
54249 return self::$shell;
54250 }
54251
54252
54253
54254
54255
54256
54257 private function hasSttyAvailable()
54258 {
54259 if (null !== self::$stty) {
54260 return self::$stty;
54261 }
54262
54263 exec('stty 2>&1', $output, $exitcode);
54264
54265 return self::$stty = $exitcode === 0;
54266 }
54267 }
54268 <?php
54269
54270
54271
54272
54273
54274
54275
54276
54277
54278
54279 namespace Symfony\Component\Console\Helper;
54280
54281 use Symfony\Component\Console\Exception\LogicException;
54282 use Symfony\Component\Console\Input\InputInterface;
54283 use Symfony\Component\Console\Output\OutputInterface;
54284 use Symfony\Component\Console\Question\ChoiceQuestion;
54285 use Symfony\Component\Console\Question\ConfirmationQuestion;
54286 use Symfony\Component\Console\Question\Question;
54287 use Symfony\Component\Console\Style\SymfonyStyle;
54288 use Symfony\Component\Console\Formatter\OutputFormatter;
54289
54290
54291
54292
54293
54294
54295 class SymfonyQuestionHelper extends QuestionHelper
54296 {
54297
54298
54299
54300 public function ask(InputInterface $input, OutputInterface $output, Question $question)
54301 {
54302 $validator = $question->getValidator();
54303 $question->setValidator(function ($value) use ($validator) {
54304 if (null !== $validator) {
54305 $value = $validator($value);
54306 } else {
54307
54308  if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
54309 throw new LogicException('A value is required.');
54310 }
54311 }
54312
54313 return $value;
54314 });
54315
54316 return parent::ask($input, $output, $question);
54317 }
54318
54319
54320
54321
54322 protected function writePrompt(OutputInterface $output, Question $question)
54323 {
54324 $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
54325 $default = $question->getDefault();
54326
54327 switch (true) {
54328 case null === $default:
54329 $text = sprintf(' <info>%s</info>:', $text);
54330
54331 break;
54332
54333 case $question instanceof ConfirmationQuestion:
54334 $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
54335
54336 break;
54337
54338 case $question instanceof ChoiceQuestion && $question->isMultiselect():
54339 $choices = $question->getChoices();
54340 $default = explode(',', $default);
54341
54342 foreach ($default as $key => $value) {
54343 $default[$key] = $choices[trim($value)];
54344 }
54345
54346 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
54347
54348 break;
54349
54350 case $question instanceof ChoiceQuestion:
54351 $choices = $question->getChoices();
54352 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default]));
54353
54354 break;
54355
54356 default:
54357 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
54358 }
54359
54360 $output->writeln($text);
54361
54362 if ($question instanceof ChoiceQuestion) {
54363 $width = max(array_map('strlen', array_keys($question->getChoices())));
54364
54365 foreach ($question->getChoices() as $key => $value) {
54366 $output->writeln(sprintf("  [<comment>%-${width}s</comment>] %s", $key, $value));
54367 }
54368 }
54369
54370 $output->write(' > ');
54371 }
54372
54373
54374
54375
54376 protected function writeError(OutputInterface $output, \Exception $error)
54377 {
54378 if ($output instanceof SymfonyStyle) {
54379 $output->newLine();
54380 $output->error($error->getMessage());
54381
54382 return;
54383 }
54384
54385 parent::writeError($output, $error);
54386 }
54387 }
54388 <?php
54389
54390
54391
54392
54393
54394
54395
54396
54397
54398
54399 namespace Symfony\Component\Console\Helper;
54400
54401 use Symfony\Component\Console\Output\OutputInterface;
54402 use Symfony\Component\Console\Exception\InvalidArgumentException;
54403
54404
54405
54406
54407
54408
54409
54410
54411
54412 class Table
54413 {
54414
54415
54416
54417
54418
54419 private $headers = array();
54420
54421
54422
54423
54424
54425
54426 private $rows = array();
54427
54428
54429
54430
54431
54432
54433 private $columnWidths = array();
54434
54435
54436
54437
54438
54439
54440 private $numberOfColumns;
54441
54442
54443
54444
54445 private $output;
54446
54447
54448
54449
54450 private $style;
54451
54452
54453
54454
54455 private $columnStyles = array();
54456
54457 private static $styles;
54458
54459 public function __construct(OutputInterface $output)
54460 {
54461 $this->output = $output;
54462
54463 if (!self::$styles) {
54464 self::$styles = self::initStyles();
54465 }
54466
54467 $this->setStyle('default');
54468 }
54469
54470
54471
54472
54473
54474
54475
54476 public static function setStyleDefinition($name, TableStyle $style)
54477 {
54478 if (!self::$styles) {
54479 self::$styles = self::initStyles();
54480 }
54481
54482 self::$styles[$name] = $style;
54483 }
54484
54485
54486
54487
54488
54489
54490
54491
54492 public static function getStyleDefinition($name)
54493 {
54494 if (!self::$styles) {
54495 self::$styles = self::initStyles();
54496 }
54497
54498 if (isset(self::$styles[$name])) {
54499 return self::$styles[$name];
54500 }
54501
54502 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
54503 }
54504
54505
54506
54507
54508
54509
54510
54511
54512 public function setStyle($name)
54513 {
54514 $this->style = $this->resolveStyle($name);
54515
54516 return $this;
54517 }
54518
54519
54520
54521
54522
54523
54524 public function getStyle()
54525 {
54526 return $this->style;
54527 }
54528
54529
54530
54531
54532
54533
54534
54535
54536
54537 public function setColumnStyle($columnIndex, $name)
54538 {
54539 $columnIndex = (int) $columnIndex;
54540
54541 $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
54542
54543 return $this;
54544 }
54545
54546
54547
54548
54549
54550
54551
54552
54553
54554
54555 public function getColumnStyle($columnIndex)
54556 {
54557 if (isset($this->columnStyles[$columnIndex])) {
54558 return $this->columnStyles[$columnIndex];
54559 }
54560
54561 return $this->getStyle();
54562 }
54563
54564 public function setHeaders(array $headers)
54565 {
54566 $headers = array_values($headers);
54567 if (!empty($headers) && !is_array($headers[0])) {
54568 $headers = array($headers);
54569 }
54570
54571 $this->headers = $headers;
54572
54573 return $this;
54574 }
54575
54576 public function setRows(array $rows)
54577 {
54578 $this->rows = array();
54579
54580 return $this->addRows($rows);
54581 }
54582
54583 public function addRows(array $rows)
54584 {
54585 foreach ($rows as $row) {
54586 $this->addRow($row);
54587 }
54588
54589 return $this;
54590 }
54591
54592 public function addRow($row)
54593 {
54594 if ($row instanceof TableSeparator) {
54595 $this->rows[] = $row;
54596
54597 return $this;
54598 }
54599
54600 if (!is_array($row)) {
54601 throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
54602 }
54603
54604 $this->rows[] = array_values($row);
54605
54606 return $this;
54607 }
54608
54609 public function setRow($column, array $row)
54610 {
54611 $this->rows[$column] = $row;
54612
54613 return $this;
54614 }
54615
54616
54617
54618
54619
54620
54621
54622
54623
54624
54625
54626
54627
54628 public function render()
54629 {
54630 $this->calculateNumberOfColumns();
54631 $rows = $this->buildTableRows($this->rows);
54632 $headers = $this->buildTableRows($this->headers);
54633
54634 $this->calculateColumnsWidth(array_merge($headers, $rows));
54635
54636 $this->renderRowSeparator();
54637 if (!empty($headers)) {
54638 foreach ($headers as $header) {
54639 $this->renderRow($header, $this->style->getCellHeaderFormat());
54640 $this->renderRowSeparator();
54641 }
54642 }
54643 foreach ($rows as $row) {
54644 if ($row instanceof TableSeparator) {
54645 $this->renderRowSeparator();
54646 } else {
54647 $this->renderRow($row, $this->style->getCellRowFormat());
54648 }
54649 }
54650 if (!empty($rows)) {
54651 $this->renderRowSeparator();
54652 }
54653
54654 $this->cleanup();
54655 }
54656
54657
54658
54659
54660
54661
54662 private function renderRowSeparator()
54663 {
54664 if (0 === $count = $this->numberOfColumns) {
54665 return;
54666 }
54667
54668 if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
54669 return;
54670 }
54671
54672 $markup = $this->style->getCrossingChar();
54673 for ($column = 0; $column < $count; ++$column) {
54674 $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
54675 }
54676
54677 $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
54678 }
54679
54680
54681
54682
54683 private function renderColumnSeparator()
54684 {
54685 return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
54686 }
54687
54688
54689
54690
54691
54692
54693
54694
54695
54696 private function renderRow(array $row, $cellFormat)
54697 {
54698 if (empty($row)) {
54699 return;
54700 }
54701
54702 $rowContent = $this->renderColumnSeparator();
54703 foreach ($this->getRowColumns($row) as $column) {
54704 $rowContent .= $this->renderCell($row, $column, $cellFormat);
54705 $rowContent .= $this->renderColumnSeparator();
54706 }
54707 $this->output->writeln($rowContent);
54708 }
54709
54710
54711
54712
54713
54714
54715
54716
54717 private function renderCell(array $row, $column, $cellFormat)
54718 {
54719 $cell = isset($row[$column]) ? $row[$column] : '';
54720 $width = $this->columnWidths[$column];
54721 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
54722
54723  foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
54724 $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
54725 }
54726 }
54727
54728
54729  if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
54730 $width += strlen($cell) - mb_strwidth($cell, $encoding);
54731 }
54732
54733 $style = $this->getColumnStyle($column);
54734
54735 if ($cell instanceof TableSeparator) {
54736 return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
54737 }
54738
54739 $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
54740 $content = sprintf($style->getCellRowContentFormat(), $cell);
54741
54742 return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
54743 }
54744
54745
54746
54747
54748 private function calculateNumberOfColumns()
54749 {
54750 if (null !== $this->numberOfColumns) {
54751 return;
54752 }
54753
54754 $columns = array(0);
54755 foreach (array_merge($this->headers, $this->rows) as $row) {
54756 if ($row instanceof TableSeparator) {
54757 continue;
54758 }
54759
54760 $columns[] = $this->getNumberOfColumns($row);
54761 }
54762
54763 $this->numberOfColumns = max($columns);
54764 }
54765
54766 private function buildTableRows($rows)
54767 {
54768 $unmergedRows = array();
54769 for ($rowKey = 0; $rowKey < count($rows); ++$rowKey) {
54770 $rows = $this->fillNextRows($rows, $rowKey);
54771
54772
54773  foreach ($rows[$rowKey] as $column => $cell) {
54774 if (!strstr($cell, "\n")) {
54775 continue;
54776 }
54777 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
54778 foreach ($lines as $lineKey => $line) {
54779 if ($cell instanceof TableCell) {
54780 $line = new TableCell($line, array('colspan' => $cell->getColspan()));
54781 }
54782 if (0 === $lineKey) {
54783 $rows[$rowKey][$column] = $line;
54784 } else {
54785 $unmergedRows[$rowKey][$lineKey][$column] = $line;
54786 }
54787 }
54788 }
54789 }
54790
54791 $tableRows = array();
54792 foreach ($rows as $rowKey => $row) {
54793 $tableRows[] = $this->fillCells($row);
54794 if (isset($unmergedRows[$rowKey])) {
54795 $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
54796 }
54797 }
54798
54799 return $tableRows;
54800 }
54801
54802
54803
54804
54805
54806
54807
54808
54809
54810 private function fillNextRows($rows, $line)
54811 {
54812 $unmergedRows = array();
54813 foreach ($rows[$line] as $column => $cell) {
54814 if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
54815 $nbLines = $cell->getRowspan() - 1;
54816 $lines = array($cell);
54817 if (strstr($cell, "\n")) {
54818 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
54819 $nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
54820
54821 $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
54822 unset($lines[0]);
54823 }
54824
54825
54826  $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
54827 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
54828 $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
54829 $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
54830 if ($nbLines === $unmergedRowKey - $line) {
54831 break;
54832 }
54833 }
54834 }
54835 }
54836
54837 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
54838
54839  if (isset($rows[$unmergedRowKey]) && is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
54840 foreach ($unmergedRow as $cellKey => $cell) {
54841
54842  array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
54843 }
54844 } else {
54845 $row = $this->copyRow($rows, $unmergedRowKey - 1);
54846 foreach ($unmergedRow as $column => $cell) {
54847 if (!empty($cell)) {
54848 $row[$column] = $unmergedRow[$column];
54849 }
54850 }
54851 array_splice($rows, $unmergedRowKey, 0, array($row));
54852 }
54853 }
54854
54855 return $rows;
54856 }
54857
54858
54859
54860
54861
54862
54863
54864
54865 private function fillCells($row)
54866 {
54867 $newRow = array();
54868 foreach ($row as $column => $cell) {
54869 $newRow[] = $cell;
54870 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
54871 foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
54872
54873  $newRow[] = '';
54874 }
54875 }
54876 }
54877
54878 return $newRow ?: $row;
54879 }
54880
54881
54882
54883
54884
54885
54886
54887 private function copyRow($rows, $line)
54888 {
54889 $row = $rows[$line];
54890 foreach ($row as $cellKey => $cellValue) {
54891 $row[$cellKey] = '';
54892 if ($cellValue instanceof TableCell) {
54893 $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
54894 }
54895 }
54896
54897 return $row;
54898 }
54899
54900
54901
54902
54903
54904
54905
54906
54907 private function getNumberOfColumns(array $row)
54908 {
54909 $columns = count($row);
54910 foreach ($row as $column) {
54911 $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
54912 }
54913
54914 return $columns;
54915 }
54916
54917
54918
54919
54920
54921
54922
54923
54924 private function getRowColumns($row)
54925 {
54926 $columns = range(0, $this->numberOfColumns - 1);
54927 foreach ($row as $cellKey => $cell) {
54928 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
54929
54930  $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
54931 }
54932 }
54933
54934 return $columns;
54935 }
54936
54937
54938
54939
54940
54941
54942 private function calculateColumnsWidth($rows)
54943 {
54944 for ($column = 0; $column < $this->numberOfColumns; ++$column) {
54945 $lengths = array();
54946 foreach ($rows as $row) {
54947 if ($row instanceof TableSeparator) {
54948 continue;
54949 }
54950
54951 foreach ($row as $i => $cell) {
54952 if ($cell instanceof TableCell) {
54953 $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
54954 $textLength = Helper::strlen($textContent);
54955 if ($textLength > 0) {
54956 $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
54957 foreach ($contentColumns as $position => $content) {
54958 $row[$i + $position] = $content;
54959 }
54960 }
54961 }
54962 }
54963
54964 $lengths[] = $this->getCellWidth($row, $column);
54965 }
54966
54967 $this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
54968 }
54969 }
54970
54971
54972
54973
54974
54975
54976 private function getColumnSeparatorWidth()
54977 {
54978 return strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
54979 }
54980
54981
54982
54983
54984
54985
54986
54987
54988
54989 private function getCellWidth(array $row, $column)
54990 {
54991 if (isset($row[$column])) {
54992 $cell = $row[$column];
54993 $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
54994
54995 return $cellWidth;
54996 }
54997
54998 return 0;
54999 }
55000
55001
55002
55003
55004 private function cleanup()
55005 {
55006 $this->columnWidths = array();
55007 $this->numberOfColumns = null;
55008 }
55009
55010 private static function initStyles()
55011 {
55012 $borderless = new TableStyle();
55013 $borderless
55014 ->setHorizontalBorderChar('=')
55015 ->setVerticalBorderChar(' ')
55016 ->setCrossingChar(' ')
55017 ;
55018
55019 $compact = new TableStyle();
55020 $compact
55021 ->setHorizontalBorderChar('')
55022 ->setVerticalBorderChar(' ')
55023 ->setCrossingChar('')
55024 ->setCellRowContentFormat('%s')
55025 ;
55026
55027 $styleGuide = new TableStyle();
55028 $styleGuide
55029 ->setHorizontalBorderChar('-')
55030 ->setVerticalBorderChar(' ')
55031 ->setCrossingChar(' ')
55032 ->setCellHeaderFormat('%s')
55033 ;
55034
55035 return array(
55036 'default' => new TableStyle(),
55037 'borderless' => $borderless,
55038 'compact' => $compact,
55039 'symfony-style-guide' => $styleGuide,
55040 );
55041 }
55042
55043 private function resolveStyle($name)
55044 {
55045 if ($name instanceof TableStyle) {
55046 return $name;
55047 }
55048
55049 if (isset(self::$styles[$name])) {
55050 return self::$styles[$name];
55051 }
55052
55053 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
55054 }
55055 }
55056 <?php
55057
55058
55059
55060
55061
55062
55063
55064
55065
55066
55067 namespace Symfony\Component\Console\Helper;
55068
55069 use Symfony\Component\Console\Exception\InvalidArgumentException;
55070
55071
55072
55073
55074 class TableCell
55075 {
55076
55077
55078
55079 private $value;
55080
55081
55082
55083
55084 private $options = array(
55085 'rowspan' => 1,
55086 'colspan' => 1,
55087 );
55088
55089
55090
55091
55092
55093 public function __construct($value = '', array $options = array())
55094 {
55095 if (is_numeric($value) && !is_string($value)) {
55096 $value = (string) $value;
55097 }
55098
55099 $this->value = $value;
55100
55101
55102  if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
55103 throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
55104 }
55105
55106 $this->options = array_merge($this->options, $options);
55107 }
55108
55109
55110
55111
55112
55113
55114 public function __toString()
55115 {
55116 return $this->value;
55117 }
55118
55119
55120
55121
55122
55123
55124 public function getColspan()
55125 {
55126 return (int) $this->options['colspan'];
55127 }
55128
55129
55130
55131
55132
55133
55134 public function getRowspan()
55135 {
55136 return (int) $this->options['rowspan'];
55137 }
55138 }
55139 <?php
55140
55141
55142
55143
55144
55145
55146
55147
55148
55149
55150 namespace Symfony\Component\Console\Helper;
55151
55152 use Symfony\Component\Console\Output\OutputInterface;
55153 use Symfony\Component\Console\Output\NullOutput;
55154 use Symfony\Component\Console\Exception\InvalidArgumentException;
55155
55156
55157
55158
55159
55160
55161
55162
55163
55164
55165 class TableHelper extends Helper
55166 {
55167 const LAYOUT_DEFAULT = 0;
55168 const LAYOUT_BORDERLESS = 1;
55169 const LAYOUT_COMPACT = 2;
55170
55171
55172
55173
55174 private $table;
55175
55176 public function __construct($triggerDeprecationError = true)
55177 {
55178 if ($triggerDeprecationError) {
55179 @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);
55180 }
55181
55182 $this->table = new Table(new NullOutput());
55183 }
55184
55185
55186
55187
55188
55189
55190
55191
55192
55193
55194 public function setLayout($layout)
55195 {
55196 switch ($layout) {
55197 case self::LAYOUT_BORDERLESS:
55198 $this->table->setStyle('borderless');
55199 break;
55200
55201 case self::LAYOUT_COMPACT:
55202 $this->table->setStyle('compact');
55203 break;
55204
55205 case self::LAYOUT_DEFAULT:
55206 $this->table->setStyle('default');
55207 break;
55208
55209 default:
55210 throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
55211 }
55212
55213 return $this;
55214 }
55215
55216 public function setHeaders(array $headers)
55217 {
55218 $this->table->setHeaders($headers);
55219
55220 return $this;
55221 }
55222
55223 public function setRows(array $rows)
55224 {
55225 $this->table->setRows($rows);
55226
55227 return $this;
55228 }
55229
55230 public function addRows(array $rows)
55231 {
55232 $this->table->addRows($rows);
55233
55234 return $this;
55235 }
55236
55237 public function addRow(array $row)
55238 {
55239 $this->table->addRow($row);
55240
55241 return $this;
55242 }
55243
55244 public function setRow($column, array $row)
55245 {
55246 $this->table->setRow($column, $row);
55247
55248 return $this;
55249 }
55250
55251
55252
55253
55254
55255
55256
55257
55258 public function setPaddingChar($paddingChar)
55259 {
55260 $this->table->getStyle()->setPaddingChar($paddingChar);
55261
55262 return $this;
55263 }
55264
55265
55266
55267
55268
55269
55270
55271
55272 public function setHorizontalBorderChar($horizontalBorderChar)
55273 {
55274 $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
55275
55276 return $this;
55277 }
55278
55279
55280
55281
55282
55283
55284
55285
55286 public function setVerticalBorderChar($verticalBorderChar)
55287 {
55288 $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
55289
55290 return $this;
55291 }
55292
55293
55294
55295
55296
55297
55298
55299
55300 public function setCrossingChar($crossingChar)
55301 {
55302 $this->table->getStyle()->setCrossingChar($crossingChar);
55303
55304 return $this;
55305 }
55306
55307
55308
55309
55310
55311
55312
55313
55314 public function setCellHeaderFormat($cellHeaderFormat)
55315 {
55316 $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
55317
55318 return $this;
55319 }
55320
55321
55322
55323
55324
55325
55326
55327
55328 public function setCellRowFormat($cellRowFormat)
55329 {
55330 $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
55331
55332 return $this;
55333 }
55334
55335
55336
55337
55338
55339
55340
55341
55342 public function setCellRowContentFormat($cellRowContentFormat)
55343 {
55344 $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
55345
55346 return $this;
55347 }
55348
55349
55350
55351
55352
55353
55354
55355
55356 public function setBorderFormat($borderFormat)
55357 {
55358 $this->table->getStyle()->setBorderFormat($borderFormat);
55359
55360 return $this;
55361 }
55362
55363
55364
55365
55366
55367
55368
55369
55370 public function setPadType($padType)
55371 {
55372 $this->table->getStyle()->setPadType($padType);
55373
55374 return $this;
55375 }
55376
55377
55378
55379
55380
55381
55382
55383
55384
55385
55386
55387
55388
55389
55390
55391 public function render(OutputInterface $output)
55392 {
55393 $p = new \ReflectionProperty($this->table, 'output');
55394 $p->setAccessible(true);
55395 $p->setValue($this->table, $output);
55396
55397 $this->table->render();
55398 }
55399
55400
55401
55402
55403 public function getName()
55404 {
55405 return 'table';
55406 }
55407 }
55408 <?php
55409
55410
55411
55412
55413
55414
55415
55416
55417
55418
55419 namespace Symfony\Component\Console\Helper;
55420
55421
55422
55423
55424
55425
55426 class TableSeparator extends TableCell
55427 {
55428
55429
55430
55431 public function __construct(array $options = array())
55432 {
55433 parent::__construct('', $options);
55434 }
55435 }
55436 <?php
55437
55438
55439
55440
55441
55442
55443
55444
55445
55446
55447 namespace Symfony\Component\Console\Helper;
55448
55449 use Symfony\Component\Console\Exception\InvalidArgumentException;
55450 use Symfony\Component\Console\Exception\LogicException;
55451
55452
55453
55454
55455
55456
55457
55458 class TableStyle
55459 {
55460 private $paddingChar = ' ';
55461 private $horizontalBorderChar = '-';
55462 private $verticalBorderChar = '|';
55463 private $crossingChar = '+';
55464 private $cellHeaderFormat = '<info>%s</info>';
55465 private $cellRowFormat = '%s';
55466 private $cellRowContentFormat = ' %s ';
55467 private $borderFormat = '%s';
55468 private $padType = STR_PAD_RIGHT;
55469
55470
55471
55472
55473
55474
55475
55476
55477 public function setPaddingChar($paddingChar)
55478 {
55479 if (!$paddingChar) {
55480 throw new LogicException('The padding char must not be empty');
55481 }
55482
55483 $this->paddingChar = $paddingChar;
55484
55485 return $this;
55486 }
55487
55488
55489
55490
55491
55492
55493 public function getPaddingChar()
55494 {
55495 return $this->paddingChar;
55496 }
55497
55498
55499
55500
55501
55502
55503
55504
55505 public function setHorizontalBorderChar($horizontalBorderChar)
55506 {
55507 $this->horizontalBorderChar = $horizontalBorderChar;
55508
55509 return $this;
55510 }
55511
55512
55513
55514
55515
55516
55517 public function getHorizontalBorderChar()
55518 {
55519 return $this->horizontalBorderChar;
55520 }
55521
55522
55523
55524
55525
55526
55527
55528
55529 public function setVerticalBorderChar($verticalBorderChar)
55530 {
55531 $this->verticalBorderChar = $verticalBorderChar;
55532
55533 return $this;
55534 }
55535
55536
55537
55538
55539
55540
55541 public function getVerticalBorderChar()
55542 {
55543 return $this->verticalBorderChar;
55544 }
55545
55546
55547
55548
55549
55550
55551
55552
55553 public function setCrossingChar($crossingChar)
55554 {
55555 $this->crossingChar = $crossingChar;
55556
55557 return $this;
55558 }
55559
55560
55561
55562
55563
55564
55565 public function getCrossingChar()
55566 {
55567 return $this->crossingChar;
55568 }
55569
55570
55571
55572
55573
55574
55575
55576
55577 public function setCellHeaderFormat($cellHeaderFormat)
55578 {
55579 $this->cellHeaderFormat = $cellHeaderFormat;
55580
55581 return $this;
55582 }
55583
55584
55585
55586
55587
55588
55589 public function getCellHeaderFormat()
55590 {
55591 return $this->cellHeaderFormat;
55592 }
55593
55594
55595
55596
55597
55598
55599
55600
55601 public function setCellRowFormat($cellRowFormat)
55602 {
55603 $this->cellRowFormat = $cellRowFormat;
55604
55605 return $this;
55606 }
55607
55608
55609
55610
55611
55612
55613 public function getCellRowFormat()
55614 {
55615 return $this->cellRowFormat;
55616 }
55617
55618
55619
55620
55621
55622
55623
55624
55625 public function setCellRowContentFormat($cellRowContentFormat)
55626 {
55627 $this->cellRowContentFormat = $cellRowContentFormat;
55628
55629 return $this;
55630 }
55631
55632
55633
55634
55635
55636
55637 public function getCellRowContentFormat()
55638 {
55639 return $this->cellRowContentFormat;
55640 }
55641
55642
55643
55644
55645
55646
55647
55648
55649 public function setBorderFormat($borderFormat)
55650 {
55651 $this->borderFormat = $borderFormat;
55652
55653 return $this;
55654 }
55655
55656
55657
55658
55659
55660
55661 public function getBorderFormat()
55662 {
55663 return $this->borderFormat;
55664 }
55665
55666
55667
55668
55669
55670
55671
55672
55673 public function setPadType($padType)
55674 {
55675 if (!in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
55676 throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
55677 }
55678
55679 $this->padType = $padType;
55680
55681 return $this;
55682 }
55683
55684
55685
55686
55687
55688
55689 public function getPadType()
55690 {
55691 return $this->padType;
55692 }
55693 }
55694 <?php
55695
55696
55697
55698
55699
55700
55701
55702
55703
55704
55705 namespace Symfony\Component\Console\Input;
55706
55707 use Symfony\Component\Console\Exception\RuntimeException;
55708
55709
55710
55711
55712
55713
55714
55715
55716
55717
55718
55719
55720
55721
55722
55723
55724
55725
55726
55727
55728
55729
55730
55731
55732
55733
55734 class ArgvInput extends Input
55735 {
55736 private $tokens;
55737 private $parsed;
55738
55739
55740
55741
55742
55743
55744
55745 public function __construct(array $argv = null, InputDefinition $definition = null)
55746 {
55747 if (null === $argv) {
55748 $argv = $_SERVER['argv'];
55749 }
55750
55751
55752  array_shift($argv);
55753
55754 $this->tokens = $argv;
55755
55756 parent::__construct($definition);
55757 }
55758
55759 protected function setTokens(array $tokens)
55760 {
55761 $this->tokens = $tokens;
55762 }
55763
55764
55765
55766
55767 protected function parse()
55768 {
55769 $parseOptions = true;
55770 $this->parsed = $this->tokens;
55771 while (null !== $token = array_shift($this->parsed)) {
55772 if ($parseOptions && '' == $token) {
55773 $this->parseArgument($token);
55774 } elseif ($parseOptions && '--' == $token) {
55775 $parseOptions = false;
55776 } elseif ($parseOptions && 0 === strpos($token, '--')) {
55777 $this->parseLongOption($token);
55778 } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
55779 $this->parseShortOption($token);
55780 } else {
55781 $this->parseArgument($token);
55782 }
55783 }
55784 }
55785
55786
55787
55788
55789
55790
55791 private function parseShortOption($token)
55792 {
55793 $name = substr($token, 1);
55794
55795 if (strlen($name) > 1) {
55796 if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
55797
55798  $this->addShortOption($name[0], substr($name, 1));
55799 } else {
55800 $this->parseShortOptionSet($name);
55801 }
55802 } else {
55803 $this->addShortOption($name, null);
55804 }
55805 }
55806
55807
55808
55809
55810
55811
55812
55813
55814 private function parseShortOptionSet($name)
55815 {
55816 $len = strlen($name);
55817 for ($i = 0; $i < $len; ++$i) {
55818 if (!$this->definition->hasShortcut($name[$i])) {
55819 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
55820 }
55821
55822 $option = $this->definition->getOptionForShortcut($name[$i]);
55823 if ($option->acceptValue()) {
55824 $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
55825
55826 break;
55827 } else {
55828 $this->addLongOption($option->getName(), null);
55829 }
55830 }
55831 }
55832
55833
55834
55835
55836
55837
55838 private function parseLongOption($token)
55839 {
55840 $name = substr($token, 2);
55841
55842 if (false !== $pos = strpos($name, '=')) {
55843 if (0 === strlen($value = substr($name, $pos + 1))) {
55844 array_unshift($this->parsed, null);
55845 }
55846 $this->addLongOption(substr($name, 0, $pos), $value);
55847 } else {
55848 $this->addLongOption($name, null);
55849 }
55850 }
55851
55852
55853
55854
55855
55856
55857
55858
55859 private function parseArgument($token)
55860 {
55861 $c = count($this->arguments);
55862
55863
55864  if ($this->definition->hasArgument($c)) {
55865 $arg = $this->definition->getArgument($c);
55866 $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
55867
55868
55869  } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
55870 $arg = $this->definition->getArgument($c - 1);
55871 $this->arguments[$arg->getName()][] = $token;
55872
55873
55874  } else {
55875 $all = $this->definition->getArguments();
55876 if (count($all)) {
55877 throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
55878 }
55879
55880 throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
55881 }
55882 }
55883
55884
55885
55886
55887
55888
55889
55890
55891
55892 private function addShortOption($shortcut, $value)
55893 {
55894 if (!$this->definition->hasShortcut($shortcut)) {
55895 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
55896 }
55897
55898 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
55899 }
55900
55901
55902
55903
55904
55905
55906
55907
55908
55909 private function addLongOption($name, $value)
55910 {
55911 if (!$this->definition->hasOption($name)) {
55912 throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
55913 }
55914
55915 $option = $this->definition->getOption($name);
55916
55917
55918  if (!isset($value[0])) {
55919 $value = null;
55920 }
55921
55922 if (null !== $value && !$option->acceptValue()) {
55923 throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
55924 }
55925
55926 if (null === $value && $option->acceptValue() && count($this->parsed)) {
55927
55928  
55929  $next = array_shift($this->parsed);
55930 if (isset($next[0]) && '-' !== $next[0]) {
55931 $value = $next;
55932 } elseif (empty($next)) {
55933 $value = null;
55934 } else {
55935 array_unshift($this->parsed, $next);
55936 }
55937 }
55938
55939 if (null === $value) {
55940 if ($option->isValueRequired()) {
55941 throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
55942 }
55943
55944 if (!$option->isArray()) {
55945 $value = $option->isValueOptional() ? $option->getDefault() : true;
55946 }
55947 }
55948
55949 if ($option->isArray()) {
55950 $this->options[$name][] = $value;
55951 } else {
55952 $this->options[$name] = $value;
55953 }
55954 }
55955
55956
55957
55958
55959 public function getFirstArgument()
55960 {
55961 foreach ($this->tokens as $token) {
55962 if ($token && '-' === $token[0]) {
55963 continue;
55964 }
55965
55966 return $token;
55967 }
55968 }
55969
55970
55971
55972
55973 public function hasParameterOption($values)
55974 {
55975 $values = (array) $values;
55976
55977 foreach ($this->tokens as $token) {
55978 foreach ($values as $value) {
55979 if ($token === $value || 0 === strpos($token, $value.'=')) {
55980 return true;
55981 }
55982 }
55983 }
55984
55985 return false;
55986 }
55987
55988
55989
55990
55991 public function getParameterOption($values, $default = false)
55992 {
55993 $values = (array) $values;
55994 $tokens = $this->tokens;
55995
55996 while (0 < count($tokens)) {
55997 $token = array_shift($tokens);
55998
55999 foreach ($values as $value) {
56000 if ($token === $value || 0 === strpos($token, $value.'=')) {
56001 if (false !== $pos = strpos($token, '=')) {
56002 return substr($token, $pos + 1);
56003 }
56004
56005 return array_shift($tokens);
56006 }
56007 }
56008 }
56009
56010 return $default;
56011 }
56012
56013
56014
56015
56016
56017
56018 public function __toString()
56019 {
56020 $self = $this;
56021 $tokens = array_map(function ($token) use ($self) {
56022 if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
56023 return $match[1].$self->escapeToken($match[2]);
56024 }
56025
56026 if ($token && $token[0] !== '-') {
56027 return $self->escapeToken($token);
56028 }
56029
56030 return $token;
56031 }, $this->tokens);
56032
56033 return implode(' ', $tokens);
56034 }
56035 }
56036 <?php
56037
56038
56039
56040
56041
56042
56043
56044
56045
56046
56047 namespace Symfony\Component\Console\Input;
56048
56049 use Symfony\Component\Console\Exception\InvalidArgumentException;
56050 use Symfony\Component\Console\Exception\InvalidOptionException;
56051
56052
56053
56054
56055
56056
56057
56058
56059
56060
56061 class ArrayInput extends Input
56062 {
56063 private $parameters;
56064
56065
56066
56067
56068
56069
56070
56071 public function __construct(array $parameters, InputDefinition $definition = null)
56072 {
56073 $this->parameters = $parameters;
56074
56075 parent::__construct($definition);
56076 }
56077
56078
56079
56080
56081 public function getFirstArgument()
56082 {
56083 foreach ($this->parameters as $key => $value) {
56084 if ($key && '-' === $key[0]) {
56085 continue;
56086 }
56087
56088 return $value;
56089 }
56090 }
56091
56092
56093
56094
56095 public function hasParameterOption($values)
56096 {
56097 $values = (array) $values;
56098
56099 foreach ($this->parameters as $k => $v) {
56100 if (!is_int($k)) {
56101 $v = $k;
56102 }
56103
56104 if (in_array($v, $values)) {
56105 return true;
56106 }
56107 }
56108
56109 return false;
56110 }
56111
56112
56113
56114
56115 public function getParameterOption($values, $default = false)
56116 {
56117 $values = (array) $values;
56118
56119 foreach ($this->parameters as $k => $v) {
56120 if (is_int($k)) {
56121 if (in_array($v, $values)) {
56122 return true;
56123 }
56124 } elseif (in_array($k, $values)) {
56125 return $v;
56126 }
56127 }
56128
56129 return $default;
56130 }
56131
56132
56133
56134
56135
56136
56137 public function __toString()
56138 {
56139 $params = array();
56140 foreach ($this->parameters as $param => $val) {
56141 if ($param && '-' === $param[0]) {
56142 $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
56143 } else {
56144 $params[] = $this->escapeToken($val);
56145 }
56146 }
56147
56148 return implode(' ', $params);
56149 }
56150
56151
56152
56153
56154 protected function parse()
56155 {
56156 foreach ($this->parameters as $key => $value) {
56157 if (0 === strpos($key, '--')) {
56158 $this->addLongOption(substr($key, 2), $value);
56159 } elseif ('-' === $key[0]) {
56160 $this->addShortOption(substr($key, 1), $value);
56161 } else {
56162 $this->addArgument($key, $value);
56163 }
56164 }
56165 }
56166
56167
56168
56169
56170
56171
56172
56173
56174
56175 private function addShortOption($shortcut, $value)
56176 {
56177 if (!$this->definition->hasShortcut($shortcut)) {
56178 throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
56179 }
56180
56181 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
56182 }
56183
56184
56185
56186
56187
56188
56189
56190
56191
56192
56193 private function addLongOption($name, $value)
56194 {
56195 if (!$this->definition->hasOption($name)) {
56196 throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
56197 }
56198
56199 $option = $this->definition->getOption($name);
56200
56201 if (null === $value) {
56202 if ($option->isValueRequired()) {
56203 throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
56204 }
56205
56206 $value = $option->isValueOptional() ? $option->getDefault() : true;
56207 }
56208
56209 $this->options[$name] = $value;
56210 }
56211
56212
56213
56214
56215
56216
56217
56218
56219
56220 private function addArgument($name, $value)
56221 {
56222 if (!$this->definition->hasArgument($name)) {
56223 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56224 }
56225
56226 $this->arguments[$name] = $value;
56227 }
56228 }
56229 <?php
56230
56231
56232
56233
56234
56235
56236
56237
56238
56239
56240 namespace Symfony\Component\Console\Input;
56241
56242 use Symfony\Component\Console\Exception\InvalidArgumentException;
56243 use Symfony\Component\Console\Exception\RuntimeException;
56244
56245
56246
56247
56248
56249
56250
56251
56252
56253
56254
56255
56256 abstract class Input implements InputInterface
56257 {
56258
56259
56260
56261 protected $definition;
56262 protected $options = array();
56263 protected $arguments = array();
56264 protected $interactive = true;
56265
56266
56267
56268
56269
56270
56271 public function __construct(InputDefinition $definition = null)
56272 {
56273 if (null === $definition) {
56274 $this->definition = new InputDefinition();
56275 } else {
56276 $this->bind($definition);
56277 $this->validate();
56278 }
56279 }
56280
56281
56282
56283
56284 public function bind(InputDefinition $definition)
56285 {
56286 $this->arguments = array();
56287 $this->options = array();
56288 $this->definition = $definition;
56289
56290 $this->parse();
56291 }
56292
56293
56294
56295
56296 abstract protected function parse();
56297
56298
56299
56300
56301 public function validate()
56302 {
56303 $definition = $this->definition;
56304 $givenArguments = $this->arguments;
56305
56306 $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
56307 return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
56308 });
56309
56310 if (count($missingArguments) > 0) {
56311 throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
56312 }
56313 }
56314
56315
56316
56317
56318 public function isInteractive()
56319 {
56320 return $this->interactive;
56321 }
56322
56323
56324
56325
56326 public function setInteractive($interactive)
56327 {
56328 $this->interactive = (bool) $interactive;
56329 }
56330
56331
56332
56333
56334 public function getArguments()
56335 {
56336 return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
56337 }
56338
56339
56340
56341
56342 public function getArgument($name)
56343 {
56344 if (!$this->definition->hasArgument($name)) {
56345 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56346 }
56347
56348 return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
56349 }
56350
56351
56352
56353
56354 public function setArgument($name, $value)
56355 {
56356 if (!$this->definition->hasArgument($name)) {
56357 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56358 }
56359
56360 $this->arguments[$name] = $value;
56361 }
56362
56363
56364
56365
56366 public function hasArgument($name)
56367 {
56368 return $this->definition->hasArgument($name);
56369 }
56370
56371
56372
56373
56374 public function getOptions()
56375 {
56376 return array_merge($this->definition->getOptionDefaults(), $this->options);
56377 }
56378
56379
56380
56381
56382 public function getOption($name)
56383 {
56384 if (!$this->definition->hasOption($name)) {
56385 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
56386 }
56387
56388 return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
56389 }
56390
56391
56392
56393
56394 public function setOption($name, $value)
56395 {
56396 if (!$this->definition->hasOption($name)) {
56397 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
56398 }
56399
56400 $this->options[$name] = $value;
56401 }
56402
56403
56404
56405
56406 public function hasOption($name)
56407 {
56408 return $this->definition->hasOption($name);
56409 }
56410
56411
56412
56413
56414
56415
56416
56417
56418 public function escapeToken($token)
56419 {
56420 return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
56421 }
56422 }
56423 <?php
56424
56425
56426
56427
56428
56429
56430
56431
56432
56433
56434 namespace Symfony\Component\Console\Input;
56435
56436 use Symfony\Component\Console\Exception\InvalidArgumentException;
56437 use Symfony\Component\Console\Exception\LogicException;
56438
56439
56440
56441
56442
56443
56444 class InputArgument
56445 {
56446 const REQUIRED = 1;
56447 const OPTIONAL = 2;
56448 const IS_ARRAY = 4;
56449
56450 private $name;
56451 private $mode;
56452 private $default;
56453 private $description;
56454
56455
56456
56457
56458
56459
56460
56461
56462
56463
56464
56465 public function __construct($name, $mode = null, $description = '', $default = null)
56466 {
56467 if (null === $mode) {
56468 $mode = self::OPTIONAL;
56469 } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
56470 throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
56471 }
56472
56473 $this->name = $name;
56474 $this->mode = $mode;
56475 $this->description = $description;
56476
56477 $this->setDefault($default);
56478 }
56479
56480
56481
56482
56483
56484
56485 public function getName()
56486 {
56487 return $this->name;
56488 }
56489
56490
56491
56492
56493
56494
56495 public function isRequired()
56496 {
56497 return self::REQUIRED === (self::REQUIRED & $this->mode);
56498 }
56499
56500
56501
56502
56503
56504
56505 public function isArray()
56506 {
56507 return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
56508 }
56509
56510
56511
56512
56513
56514
56515
56516
56517 public function setDefault($default = null)
56518 {
56519 if (self::REQUIRED === $this->mode && null !== $default) {
56520 throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
56521 }
56522
56523 if ($this->isArray()) {
56524 if (null === $default) {
56525 $default = array();
56526 } elseif (!is_array($default)) {
56527 throw new LogicException('A default value for an array argument must be an array.');
56528 }
56529 }
56530
56531 $this->default = $default;
56532 }
56533
56534
56535
56536
56537
56538
56539 public function getDefault()
56540 {
56541 return $this->default;
56542 }
56543
56544
56545
56546
56547
56548
56549 public function getDescription()
56550 {
56551 return $this->description;
56552 }
56553 }
56554 <?php
56555
56556
56557
56558
56559
56560
56561
56562
56563
56564
56565 namespace Symfony\Component\Console\Input;
56566
56567
56568
56569
56570
56571
56572
56573 interface InputAwareInterface
56574 {
56575
56576
56577
56578
56579
56580 public function setInput(InputInterface $input);
56581 }
56582 <?php
56583
56584
56585
56586
56587
56588
56589
56590
56591
56592
56593 namespace Symfony\Component\Console\Input;
56594
56595 use Symfony\Component\Console\Descriptor\TextDescriptor;
56596 use Symfony\Component\Console\Descriptor\XmlDescriptor;
56597 use Symfony\Component\Console\Output\BufferedOutput;
56598 use Symfony\Component\Console\Exception\InvalidArgumentException;
56599 use Symfony\Component\Console\Exception\LogicException;
56600
56601
56602
56603
56604
56605
56606
56607
56608
56609
56610
56611
56612
56613 class InputDefinition
56614 {
56615 private $arguments;
56616 private $requiredCount;
56617 private $hasAnArrayArgument = false;
56618 private $hasOptional;
56619 private $options;
56620 private $shortcuts;
56621
56622
56623
56624
56625
56626
56627 public function __construct(array $definition = array())
56628 {
56629 $this->setDefinition($definition);
56630 }
56631
56632
56633
56634
56635
56636
56637 public function setDefinition(array $definition)
56638 {
56639 $arguments = array();
56640 $options = array();
56641 foreach ($definition as $item) {
56642 if ($item instanceof InputOption) {
56643 $options[] = $item;
56644 } else {
56645 $arguments[] = $item;
56646 }
56647 }
56648
56649 $this->setArguments($arguments);
56650 $this->setOptions($options);
56651 }
56652
56653
56654
56655
56656
56657
56658 public function setArguments($arguments = array())
56659 {
56660 $this->arguments = array();
56661 $this->requiredCount = 0;
56662 $this->hasOptional = false;
56663 $this->hasAnArrayArgument = false;
56664 $this->addArguments($arguments);
56665 }
56666
56667
56668
56669
56670
56671
56672 public function addArguments($arguments = array())
56673 {
56674 if (null !== $arguments) {
56675 foreach ($arguments as $argument) {
56676 $this->addArgument($argument);
56677 }
56678 }
56679 }
56680
56681
56682
56683
56684
56685
56686
56687
56688 public function addArgument(InputArgument $argument)
56689 {
56690 if (isset($this->arguments[$argument->getName()])) {
56691 throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
56692 }
56693
56694 if ($this->hasAnArrayArgument) {
56695 throw new LogicException('Cannot add an argument after an array argument.');
56696 }
56697
56698 if ($argument->isRequired() && $this->hasOptional) {
56699 throw new LogicException('Cannot add a required argument after an optional one.');
56700 }
56701
56702 if ($argument->isArray()) {
56703 $this->hasAnArrayArgument = true;
56704 }
56705
56706 if ($argument->isRequired()) {
56707 ++$this->requiredCount;
56708 } else {
56709 $this->hasOptional = true;
56710 }
56711
56712 $this->arguments[$argument->getName()] = $argument;
56713 }
56714
56715
56716
56717
56718
56719
56720
56721
56722
56723
56724 public function getArgument($name)
56725 {
56726 if (!$this->hasArgument($name)) {
56727 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56728 }
56729
56730 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
56731
56732 return $arguments[$name];
56733 }
56734
56735
56736
56737
56738
56739
56740
56741
56742 public function hasArgument($name)
56743 {
56744 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
56745
56746 return isset($arguments[$name]);
56747 }
56748
56749
56750
56751
56752
56753
56754 public function getArguments()
56755 {
56756 return $this->arguments;
56757 }
56758
56759
56760
56761
56762
56763
56764 public function getArgumentCount()
56765 {
56766 return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
56767 }
56768
56769
56770
56771
56772
56773
56774 public function getArgumentRequiredCount()
56775 {
56776 return $this->requiredCount;
56777 }
56778
56779
56780
56781
56782
56783
56784 public function getArgumentDefaults()
56785 {
56786 $values = array();
56787 foreach ($this->arguments as $argument) {
56788 $values[$argument->getName()] = $argument->getDefault();
56789 }
56790
56791 return $values;
56792 }
56793
56794
56795
56796
56797
56798
56799 public function setOptions($options = array())
56800 {
56801 $this->options = array();
56802 $this->shortcuts = array();
56803 $this->addOptions($options);
56804 }
56805
56806
56807
56808
56809
56810
56811 public function addOptions($options = array())
56812 {
56813 foreach ($options as $option) {
56814 $this->addOption($option);
56815 }
56816 }
56817
56818
56819
56820
56821
56822
56823
56824
56825 public function addOption(InputOption $option)
56826 {
56827 if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
56828 throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
56829 }
56830
56831 if ($option->getShortcut()) {
56832 foreach (explode('|', $option->getShortcut()) as $shortcut) {
56833 if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
56834 throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
56835 }
56836 }
56837 }
56838
56839 $this->options[$option->getName()] = $option;
56840 if ($option->getShortcut()) {
56841 foreach (explode('|', $option->getShortcut()) as $shortcut) {
56842 $this->shortcuts[$shortcut] = $option->getName();
56843 }
56844 }
56845 }
56846
56847
56848
56849
56850
56851
56852
56853
56854
56855
56856 public function getOption($name)
56857 {
56858 if (!$this->hasOption($name)) {
56859 throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
56860 }
56861
56862 return $this->options[$name];
56863 }
56864
56865
56866
56867
56868
56869
56870
56871
56872
56873
56874
56875 public function hasOption($name)
56876 {
56877 return isset($this->options[$name]);
56878 }
56879
56880
56881
56882
56883
56884
56885 public function getOptions()
56886 {
56887 return $this->options;
56888 }
56889
56890
56891
56892
56893
56894
56895
56896
56897 public function hasShortcut($name)
56898 {
56899 return isset($this->shortcuts[$name]);
56900 }
56901
56902
56903
56904
56905
56906
56907
56908
56909 public function getOptionForShortcut($shortcut)
56910 {
56911 return $this->getOption($this->shortcutToName($shortcut));
56912 }
56913
56914
56915
56916
56917
56918
56919 public function getOptionDefaults()
56920 {
56921 $values = array();
56922 foreach ($this->options as $option) {
56923 $values[$option->getName()] = $option->getDefault();
56924 }
56925
56926 return $values;
56927 }
56928
56929
56930
56931
56932
56933
56934
56935
56936
56937
56938 private function shortcutToName($shortcut)
56939 {
56940 if (!isset($this->shortcuts[$shortcut])) {
56941 throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
56942 }
56943
56944 return $this->shortcuts[$shortcut];
56945 }
56946
56947
56948
56949
56950
56951
56952
56953
56954 public function getSynopsis($short = false)
56955 {
56956 $elements = array();
56957
56958 if ($short && $this->getOptions()) {
56959 $elements[] = '[options]';
56960 } elseif (!$short) {
56961 foreach ($this->getOptions() as $option) {
56962 $value = '';
56963 if ($option->acceptValue()) {
56964 $value = sprintf(
56965 ' %s%s%s',
56966 $option->isValueOptional() ? '[' : '',
56967 strtoupper($option->getName()),
56968 $option->isValueOptional() ? ']' : ''
56969 );
56970 }
56971
56972 $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
56973 $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
56974 }
56975 }
56976
56977 if (count($elements) && $this->getArguments()) {
56978 $elements[] = '[--]';
56979 }
56980
56981 foreach ($this->getArguments() as $argument) {
56982 $element = '<'.$argument->getName().'>';
56983 if (!$argument->isRequired()) {
56984 $element = '['.$element.']';
56985 } elseif ($argument->isArray()) {
56986 $element = $element.' ('.$element.')';
56987 }
56988
56989 if ($argument->isArray()) {
56990 $element .= '...';
56991 }
56992
56993 $elements[] = $element;
56994 }
56995
56996 return implode(' ', $elements);
56997 }
56998
56999
57000
57001
57002
57003
57004
57005
57006 public function asText()
57007 {
57008 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
57009
57010 $descriptor = new TextDescriptor();
57011 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
57012 $descriptor->describe($output, $this, array('raw_output' => true));
57013
57014 return $output->fetch();
57015 }
57016
57017
57018
57019
57020
57021
57022
57023
57024
57025
57026 public function asXml($asDom = false)
57027 {
57028 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
57029
57030 $descriptor = new XmlDescriptor();
57031
57032 if ($asDom) {
57033 return $descriptor->getInputDefinitionDocument($this);
57034 }
57035
57036 $output = new BufferedOutput();
57037 $descriptor->describe($output, $this);
57038
57039 return $output->fetch();
57040 }
57041 }
57042 <?php
57043
57044
57045
57046
57047
57048
57049
57050
57051
57052
57053 namespace Symfony\Component\Console\Input;
57054
57055 use Symfony\Component\Console\Exception\InvalidArgumentException;
57056 use Symfony\Component\Console\Exception\RuntimeException;
57057
57058
57059
57060
57061
57062
57063 interface InputInterface
57064 {
57065
57066
57067
57068
57069
57070 public function getFirstArgument();
57071
57072
57073
57074
57075
57076
57077
57078
57079
57080
57081
57082 public function hasParameterOption($values);
57083
57084
57085
57086
57087
57088
57089
57090
57091
57092
57093
57094
57095 public function getParameterOption($values, $default = false);
57096
57097
57098
57099
57100
57101
57102 public function bind(InputDefinition $definition);
57103
57104
57105
57106
57107
57108
57109 public function validate();
57110
57111
57112
57113
57114
57115
57116 public function getArguments();
57117
57118
57119
57120
57121
57122
57123
57124
57125
57126
57127 public function getArgument($name);
57128
57129
57130
57131
57132
57133
57134
57135
57136
57137 public function setArgument($name, $value);
57138
57139
57140
57141
57142
57143
57144
57145
57146 public function hasArgument($name);
57147
57148
57149
57150
57151
57152
57153 public function getOptions();
57154
57155
57156
57157
57158
57159
57160
57161
57162
57163
57164 public function getOption($name);
57165
57166
57167
57168
57169
57170
57171
57172
57173
57174 public function setOption($name, $value);
57175
57176
57177
57178
57179
57180
57181
57182
57183 public function hasOption($name);
57184
57185
57186
57187
57188
57189
57190 public function isInteractive();
57191
57192
57193
57194
57195
57196
57197 public function setInteractive($interactive);
57198 }
57199 <?php
57200
57201
57202
57203
57204
57205
57206
57207
57208
57209
57210 namespace Symfony\Component\Console\Input;
57211
57212 use Symfony\Component\Console\Exception\InvalidArgumentException;
57213 use Symfony\Component\Console\Exception\LogicException;
57214
57215
57216
57217
57218
57219
57220 class InputOption
57221 {
57222 const VALUE_NONE = 1;
57223 const VALUE_REQUIRED = 2;
57224 const VALUE_OPTIONAL = 4;
57225 const VALUE_IS_ARRAY = 8;
57226
57227 private $name;
57228 private $shortcut;
57229 private $mode;
57230 private $default;
57231 private $description;
57232
57233
57234
57235
57236
57237
57238
57239
57240
57241
57242
57243
57244 public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
57245 {
57246 if (0 === strpos($name, '--')) {
57247 $name = substr($name, 2);
57248 }
57249
57250 if (empty($name)) {
57251 throw new InvalidArgumentException('An option name cannot be empty.');
57252 }
57253
57254 if (empty($shortcut)) {
57255 $shortcut = null;
57256 }
57257
57258 if (null !== $shortcut) {
57259 if (is_array($shortcut)) {
57260 $shortcut = implode('|', $shortcut);
57261 }
57262 $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
57263 $shortcuts = array_filter($shortcuts);
57264 $shortcut = implode('|', $shortcuts);
57265
57266 if (empty($shortcut)) {
57267 throw new InvalidArgumentException('An option shortcut cannot be empty.');
57268 }
57269 }
57270
57271 if (null === $mode) {
57272 $mode = self::VALUE_NONE;
57273 } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
57274 throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
57275 }
57276
57277 $this->name = $name;
57278 $this->shortcut = $shortcut;
57279 $this->mode = $mode;
57280 $this->description = $description;
57281
57282 if ($this->isArray() && !$this->acceptValue()) {
57283 throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
57284 }
57285
57286 $this->setDefault($default);
57287 }
57288
57289
57290
57291
57292
57293
57294 public function getShortcut()
57295 {
57296 return $this->shortcut;
57297 }
57298
57299
57300
57301
57302
57303
57304 public function getName()
57305 {
57306 return $this->name;
57307 }
57308
57309
57310
57311
57312
57313
57314 public function acceptValue()
57315 {
57316 return $this->isValueRequired() || $this->isValueOptional();
57317 }
57318
57319
57320
57321
57322
57323
57324 public function isValueRequired()
57325 {
57326 return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
57327 }
57328
57329
57330
57331
57332
57333
57334 public function isValueOptional()
57335 {
57336 return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
57337 }
57338
57339
57340
57341
57342
57343
57344 public function isArray()
57345 {
57346 return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
57347 }
57348
57349
57350
57351
57352
57353
57354
57355
57356 public function setDefault($default = null)
57357 {
57358 if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
57359 throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
57360 }
57361
57362 if ($this->isArray()) {
57363 if (null === $default) {
57364 $default = array();
57365 } elseif (!is_array($default)) {
57366 throw new LogicException('A default value for an array option must be an array.');
57367 }
57368 }
57369
57370 $this->default = $this->acceptValue() ? $default : false;
57371 }
57372
57373
57374
57375
57376
57377
57378 public function getDefault()
57379 {
57380 return $this->default;
57381 }
57382
57383
57384
57385
57386
57387
57388 public function getDescription()
57389 {
57390 return $this->description;
57391 }
57392
57393
57394
57395
57396
57397
57398
57399
57400 public function equals(InputOption $option)
57401 {
57402 return $option->getName() === $this->getName()
57403 && $option->getShortcut() === $this->getShortcut()
57404 && $option->getDefault() === $this->getDefault()
57405 && $option->isArray() === $this->isArray()
57406 && $option->isValueRequired() === $this->isValueRequired()
57407 && $option->isValueOptional() === $this->isValueOptional()
57408 ;
57409 }
57410 }
57411 <?php
57412
57413
57414
57415
57416
57417
57418
57419
57420
57421
57422 namespace Symfony\Component\Console\Input;
57423
57424 use Symfony\Component\Console\Exception\InvalidArgumentException;
57425
57426
57427
57428
57429
57430
57431
57432
57433
57434
57435 class StringInput extends ArgvInput
57436 {
57437 const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
57438 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
57439
57440
57441
57442
57443
57444
57445
57446
57447
57448 public function __construct($input, InputDefinition $definition = null)
57449 {
57450 if ($definition) {
57451 @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);
57452 }
57453
57454 parent::__construct(array(), null);
57455
57456 $this->setTokens($this->tokenize($input));
57457
57458 if (null !== $definition) {
57459 $this->bind($definition);
57460 }
57461 }
57462
57463
57464
57465
57466
57467
57468
57469
57470
57471
57472 private function tokenize($input)
57473 {
57474 $tokens = array();
57475 $length = strlen($input);
57476 $cursor = 0;
57477 while ($cursor < $length) {
57478 if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
57479 } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
57480 $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
57481 } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
57482 $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
57483 } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
57484 $tokens[] = stripcslashes($match[1]);
57485 } else {
57486
57487  throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
57488 }
57489
57490 $cursor += strlen($match[0]);
57491 }
57492
57493 return $tokens;
57494 }
57495 }
57496 Copyright (c) 2004-2017 Fabien Potencier
57497
57498 Permission is hereby granted, free of charge, to any person obtaining a copy
57499 of this software and associated documentation files (the "Software"), to deal
57500 in the Software without restriction, including without limitation the rights
57501 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57502 copies of the Software, and to permit persons to whom the Software is furnished
57503 to do so, subject to the following conditions:
57504
57505 The above copyright notice and this permission notice shall be included in all
57506 copies or substantial portions of the Software.
57507
57508 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
57509 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57510 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
57511 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
57512 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57513 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57514 THE SOFTWARE.
57515 <?php
57516
57517
57518
57519
57520
57521
57522
57523
57524
57525
57526 namespace Symfony\Component\Console\Logger;
57527
57528 use Psr\Log\AbstractLogger;
57529 use Psr\Log\InvalidArgumentException;
57530 use Psr\Log\LogLevel;
57531 use Symfony\Component\Console\Output\OutputInterface;
57532 use Symfony\Component\Console\Output\ConsoleOutputInterface;
57533
57534
57535
57536
57537
57538
57539
57540
57541 class ConsoleLogger extends AbstractLogger
57542 {
57543 const INFO = 'info';
57544 const ERROR = 'error';
57545
57546
57547
57548
57549 private $output;
57550
57551
57552
57553 private $verbosityLevelMap = array(
57554 LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
57555 LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
57556 LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
57557 LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
57558 LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
57559 LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
57560 LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
57561 LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
57562 );
57563
57564
57565
57566 private $formatLevelMap = array(
57567 LogLevel::EMERGENCY => self::ERROR,
57568 LogLevel::ALERT => self::ERROR,
57569 LogLevel::CRITICAL => self::ERROR,
57570 LogLevel::ERROR => self::ERROR,
57571 LogLevel::WARNING => self::INFO,
57572 LogLevel::NOTICE => self::INFO,
57573 LogLevel::INFO => self::INFO,
57574 LogLevel::DEBUG => self::INFO,
57575 );
57576
57577
57578
57579
57580
57581
57582 public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
57583 {
57584 $this->output = $output;
57585 $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
57586 $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
57587 }
57588
57589
57590
57591
57592 public function log($level, $message, array $context = array())
57593 {
57594 if (!isset($this->verbosityLevelMap[$level])) {
57595 throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
57596 }
57597
57598
57599  if ($this->formatLevelMap[$level] === self::ERROR && $this->output instanceof ConsoleOutputInterface) {
57600 $output = $this->output->getErrorOutput();
57601 } else {
57602 $output = $this->output;
57603 }
57604
57605 if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
57606 $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
57607 }
57608 }
57609
57610
57611
57612
57613
57614
57615
57616
57617
57618
57619
57620 private function interpolate($message, array $context)
57621 {
57622
57623  $replace = array();
57624 foreach ($context as $key => $val) {
57625 if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
57626 $replace[sprintf('{%s}', $key)] = $val;
57627 }
57628 }
57629
57630
57631  return strtr($message, $replace);
57632 }
57633 }
57634 <?php
57635
57636
57637
57638
57639
57640
57641
57642
57643
57644
57645 namespace Symfony\Component\Console\Output;
57646
57647
57648
57649
57650 class BufferedOutput extends Output
57651 {
57652
57653
57654
57655 private $buffer = '';
57656
57657
57658
57659
57660
57661
57662 public function fetch()
57663 {
57664 $content = $this->buffer;
57665 $this->buffer = '';
57666
57667 return $content;
57668 }
57669
57670
57671
57672
57673 protected function doWrite($message, $newline)
57674 {
57675 $this->buffer .= $message;
57676
57677 if ($newline) {
57678 $this->buffer .= PHP_EOL;
57679 }
57680 }
57681 }
57682 <?php
57683
57684
57685
57686
57687
57688
57689
57690
57691
57692
57693 namespace Symfony\Component\Console\Output;
57694
57695 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
57696
57697
57698
57699
57700
57701
57702
57703
57704
57705
57706
57707
57708
57709
57710 class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
57711 {
57712
57713
57714
57715 private $stderr;
57716
57717
57718
57719
57720
57721
57722
57723
57724 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
57725 {
57726 parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
57727
57728 $actualDecorated = $this->isDecorated();
57729 $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
57730
57731 if (null === $decorated) {
57732 $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
57733 }
57734 }
57735
57736
57737
57738
57739 public function setDecorated($decorated)
57740 {
57741 parent::setDecorated($decorated);
57742 $this->stderr->setDecorated($decorated);
57743 }
57744
57745
57746
57747
57748 public function setFormatter(OutputFormatterInterface $formatter)
57749 {
57750 parent::setFormatter($formatter);
57751 $this->stderr->setFormatter($formatter);
57752 }
57753
57754
57755
57756
57757 public function setVerbosity($level)
57758 {
57759 parent::setVerbosity($level);
57760 $this->stderr->setVerbosity($level);
57761 }
57762
57763
57764
57765
57766 public function getErrorOutput()
57767 {
57768 return $this->stderr;
57769 }
57770
57771
57772
57773
57774 public function setErrorOutput(OutputInterface $error)
57775 {
57776 $this->stderr = $error;
57777 }
57778
57779
57780
57781
57782
57783
57784
57785 protected function hasStdoutSupport()
57786 {
57787 return false === $this->isRunningOS400();
57788 }
57789
57790
57791
57792
57793
57794
57795
57796 protected function hasStderrSupport()
57797 {
57798 return false === $this->isRunningOS400();
57799 }
57800
57801
57802
57803
57804
57805
57806
57807 private function isRunningOS400()
57808 {
57809 $checks = array(
57810 function_exists('php_uname') ? php_uname('s') : '',
57811 getenv('OSTYPE'),
57812 PHP_OS,
57813 );
57814
57815 return false !== stripos(implode(';', $checks), 'OS400');
57816 }
57817
57818
57819
57820
57821 private function openOutputStream()
57822 {
57823 $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output';
57824
57825 return @fopen($outputStream, 'w') ?: fopen('php://output', 'w');
57826 }
57827
57828
57829
57830
57831 private function openErrorStream()
57832 {
57833 $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output';
57834
57835 return fopen($errorStream, 'w');
57836 }
57837 }
57838 <?php
57839
57840
57841
57842
57843
57844
57845
57846
57847
57848
57849 namespace Symfony\Component\Console\Output;
57850
57851
57852
57853
57854
57855
57856
57857 interface ConsoleOutputInterface extends OutputInterface
57858 {
57859
57860
57861
57862
57863
57864 public function getErrorOutput();
57865
57866
57867
57868
57869
57870
57871 public function setErrorOutput(OutputInterface $error);
57872 }
57873 <?php
57874
57875
57876
57877
57878
57879
57880
57881
57882
57883
57884 namespace Symfony\Component\Console\Output;
57885
57886 use Symfony\Component\Console\Formatter\OutputFormatter;
57887 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
57888
57889
57890
57891
57892
57893
57894
57895
57896
57897 class NullOutput implements OutputInterface
57898 {
57899
57900
57901
57902 public function setFormatter(OutputFormatterInterface $formatter)
57903 {
57904
57905  }
57906
57907
57908
57909
57910 public function getFormatter()
57911 {
57912
57913  return new OutputFormatter();
57914 }
57915
57916
57917
57918
57919 public function setDecorated($decorated)
57920 {
57921
57922  }
57923
57924
57925
57926
57927 public function isDecorated()
57928 {
57929 return false;
57930 }
57931
57932
57933
57934
57935 public function setVerbosity($level)
57936 {
57937
57938  }
57939
57940
57941
57942
57943 public function getVerbosity()
57944 {
57945 return self::VERBOSITY_QUIET;
57946 }
57947
57948
57949
57950
57951 public function isQuiet()
57952 {
57953 return true;
57954 }
57955
57956
57957
57958
57959 public function isVerbose()
57960 {
57961 return false;
57962 }
57963
57964
57965
57966
57967 public function isVeryVerbose()
57968 {
57969 return false;
57970 }
57971
57972
57973
57974
57975 public function isDebug()
57976 {
57977 return false;
57978 }
57979
57980
57981
57982
57983 public function writeln($messages, $options = self::OUTPUT_NORMAL)
57984 {
57985
57986  }
57987
57988
57989
57990
57991 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
57992 {
57993
57994  }
57995 }
57996 <?php
57997
57998
57999
58000
58001
58002
58003
58004
58005
58006
58007 namespace Symfony\Component\Console\Output;
58008
58009 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58010 use Symfony\Component\Console\Formatter\OutputFormatter;
58011
58012
58013
58014
58015
58016
58017
58018
58019
58020
58021
58022
58023
58024
58025 abstract class Output implements OutputInterface
58026 {
58027 private $verbosity;
58028 private $formatter;
58029
58030
58031
58032
58033
58034
58035
58036
58037 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
58038 {
58039 $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
58040 $this->formatter = $formatter ?: new OutputFormatter();
58041 $this->formatter->setDecorated($decorated);
58042 }
58043
58044
58045
58046
58047 public function setFormatter(OutputFormatterInterface $formatter)
58048 {
58049 $this->formatter = $formatter;
58050 }
58051
58052
58053
58054
58055 public function getFormatter()
58056 {
58057 return $this->formatter;
58058 }
58059
58060
58061
58062
58063 public function setDecorated($decorated)
58064 {
58065 $this->formatter->setDecorated($decorated);
58066 }
58067
58068
58069
58070
58071 public function isDecorated()
58072 {
58073 return $this->formatter->isDecorated();
58074 }
58075
58076
58077
58078
58079 public function setVerbosity($level)
58080 {
58081 $this->verbosity = (int) $level;
58082 }
58083
58084
58085
58086
58087 public function getVerbosity()
58088 {
58089 return $this->verbosity;
58090 }
58091
58092
58093
58094
58095 public function isQuiet()
58096 {
58097 return self::VERBOSITY_QUIET === $this->verbosity;
58098 }
58099
58100
58101
58102
58103 public function isVerbose()
58104 {
58105 return self::VERBOSITY_VERBOSE <= $this->verbosity;
58106 }
58107
58108
58109
58110
58111 public function isVeryVerbose()
58112 {
58113 return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
58114 }
58115
58116
58117
58118
58119 public function isDebug()
58120 {
58121 return self::VERBOSITY_DEBUG <= $this->verbosity;
58122 }
58123
58124
58125
58126
58127 public function writeln($messages, $options = self::OUTPUT_NORMAL)
58128 {
58129 $this->write($messages, true, $options);
58130 }
58131
58132
58133
58134
58135 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
58136 {
58137 $messages = (array) $messages;
58138
58139 $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
58140 $type = $types & $options ?: self::OUTPUT_NORMAL;
58141
58142 $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
58143 $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
58144
58145 if ($verbosity > $this->getVerbosity()) {
58146 return;
58147 }
58148
58149 foreach ($messages as $message) {
58150 switch ($type) {
58151 case OutputInterface::OUTPUT_NORMAL:
58152 $message = $this->formatter->format($message);
58153 break;
58154 case OutputInterface::OUTPUT_RAW:
58155 break;
58156 case OutputInterface::OUTPUT_PLAIN:
58157 $message = strip_tags($this->formatter->format($message));
58158 break;
58159 }
58160
58161 $this->doWrite($message, $newline);
58162 }
58163 }
58164
58165
58166
58167
58168
58169
58170
58171 abstract protected function doWrite($message, $newline);
58172 }
58173 <?php
58174
58175
58176
58177
58178
58179
58180
58181
58182
58183
58184 namespace Symfony\Component\Console\Output;
58185
58186 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58187
58188
58189
58190
58191
58192
58193 interface OutputInterface
58194 {
58195 const VERBOSITY_QUIET = 16;
58196 const VERBOSITY_NORMAL = 32;
58197 const VERBOSITY_VERBOSE = 64;
58198 const VERBOSITY_VERY_VERBOSE = 128;
58199 const VERBOSITY_DEBUG = 256;
58200
58201 const OUTPUT_NORMAL = 1;
58202 const OUTPUT_RAW = 2;
58203 const OUTPUT_PLAIN = 4;
58204
58205
58206
58207
58208
58209
58210
58211
58212 public function write($messages, $newline = false, $options = 0);
58213
58214
58215
58216
58217
58218
58219
58220 public function writeln($messages, $options = 0);
58221
58222
58223
58224
58225
58226
58227 public function setVerbosity($level);
58228
58229
58230
58231
58232
58233
58234 public function getVerbosity();
58235
58236
58237
58238
58239
58240
58241 public function setDecorated($decorated);
58242
58243
58244
58245
58246
58247
58248 public function isDecorated();
58249
58250
58251
58252
58253
58254
58255 public function setFormatter(OutputFormatterInterface $formatter);
58256
58257
58258
58259
58260
58261
58262 public function getFormatter();
58263 }
58264 <?php
58265
58266
58267
58268
58269
58270
58271
58272
58273
58274
58275 namespace Symfony\Component\Console\Output;
58276
58277 use Symfony\Component\Console\Exception\InvalidArgumentException;
58278 use Symfony\Component\Console\Exception\RuntimeException;
58279 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58280
58281
58282
58283
58284
58285
58286
58287
58288
58289
58290
58291
58292
58293
58294 class StreamOutput extends Output
58295 {
58296 private $stream;
58297
58298
58299
58300
58301
58302
58303
58304
58305
58306
58307
58308 public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
58309 {
58310 if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
58311 throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
58312 }
58313
58314 $this->stream = $stream;
58315
58316 if (null === $decorated) {
58317 $decorated = $this->hasColorSupport();
58318 }
58319
58320 parent::__construct($verbosity, $decorated, $formatter);
58321 }
58322
58323
58324
58325
58326
58327
58328 public function getStream()
58329 {
58330 return $this->stream;
58331 }
58332
58333
58334
58335
58336 protected function doWrite($message, $newline)
58337 {
58338 if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
58339
58340  throw new RuntimeException('Unable to write output.');
58341 }
58342
58343 fflush($this->stream);
58344 }
58345
58346
58347
58348
58349
58350
58351
58352
58353
58354
58355
58356 protected function hasColorSupport()
58357 {
58358 if (DIRECTORY_SEPARATOR === '\\') {
58359 return
58360 '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
58361 || false !== getenv('ANSICON')
58362 || 'ON' === getenv('ConEmuANSI')
58363 || 'xterm' === getenv('TERM');
58364 }
58365
58366 return function_exists('posix_isatty') && @posix_isatty($this->stream);
58367 }
58368 }
58369 <?php
58370
58371
58372
58373
58374
58375
58376
58377
58378
58379
58380 namespace Symfony\Component\Console\Question;
58381
58382 use Symfony\Component\Console\Exception\InvalidArgumentException;
58383
58384
58385
58386
58387
58388
58389 class ChoiceQuestion extends Question
58390 {
58391 private $choices;
58392 private $multiselect = false;
58393 private $prompt = ' > ';
58394 private $errorMessage = 'Value "%s" is invalid';
58395
58396
58397
58398
58399
58400
58401
58402
58403 public function __construct($question, array $choices, $default = null)
58404 {
58405 if (!$choices) {
58406 throw new \LogicException('Choice question must have at least 1 choice available.');
58407 }
58408
58409 parent::__construct($question, $default);
58410
58411 $this->choices = $choices;
58412 $this->setValidator($this->getDefaultValidator());
58413 $this->setAutocompleterValues($choices);
58414 }
58415
58416
58417
58418
58419
58420
58421 public function getChoices()
58422 {
58423 return $this->choices;
58424 }
58425
58426
58427
58428
58429
58430
58431
58432
58433
58434
58435 public function setMultiselect($multiselect)
58436 {
58437 $this->multiselect = $multiselect;
58438 $this->setValidator($this->getDefaultValidator());
58439
58440 return $this;
58441 }
58442
58443
58444
58445
58446
58447
58448 public function isMultiselect()
58449 {
58450 return $this->multiselect;
58451 }
58452
58453
58454
58455
58456
58457
58458 public function getPrompt()
58459 {
58460 return $this->prompt;
58461 }
58462
58463
58464
58465
58466
58467
58468
58469
58470 public function setPrompt($prompt)
58471 {
58472 $this->prompt = $prompt;
58473
58474 return $this;
58475 }
58476
58477
58478
58479
58480
58481
58482
58483
58484
58485
58486 public function setErrorMessage($errorMessage)
58487 {
58488 $this->errorMessage = $errorMessage;
58489 $this->setValidator($this->getDefaultValidator());
58490
58491 return $this;
58492 }
58493
58494
58495
58496
58497
58498
58499 private function getDefaultValidator()
58500 {
58501 $choices = $this->choices;
58502 $errorMessage = $this->errorMessage;
58503 $multiselect = $this->multiselect;
58504 $isAssoc = $this->isAssoc($choices);
58505
58506 return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
58507
58508  $selectedChoices = str_replace(' ', '', $selected);
58509
58510 if ($multiselect) {
58511
58512  if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
58513 throw new InvalidArgumentException(sprintf($errorMessage, $selected));
58514 }
58515 $selectedChoices = explode(',', $selectedChoices);
58516 } else {
58517 $selectedChoices = array($selected);
58518 }
58519
58520 $multiselectChoices = array();
58521 foreach ($selectedChoices as $value) {
58522 $results = array();
58523 foreach ($choices as $key => $choice) {
58524 if ($choice === $value) {
58525 $results[] = $key;
58526 }
58527 }
58528
58529 if (count($results) > 1) {
58530 throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
58531 }
58532
58533 $result = array_search($value, $choices);
58534
58535 if (!$isAssoc) {
58536 if (false !== $result) {
58537 $result = $choices[$result];
58538 } elseif (isset($choices[$value])) {
58539 $result = $choices[$value];
58540 }
58541 } elseif (false === $result && isset($choices[$value])) {
58542 $result = $value;
58543 }
58544
58545 if (false === $result) {
58546 throw new InvalidArgumentException(sprintf($errorMessage, $value));
58547 }
58548
58549 $multiselectChoices[] = (string) $result;
58550 }
58551
58552 if ($multiselect) {
58553 return $multiselectChoices;
58554 }
58555
58556 return current($multiselectChoices);
58557 };
58558 }
58559 }
58560 <?php
58561
58562
58563
58564
58565
58566
58567
58568
58569
58570
58571 namespace Symfony\Component\Console\Question;
58572
58573
58574
58575
58576
58577
58578 class ConfirmationQuestion extends Question
58579 {
58580 private $trueAnswerRegex;
58581
58582
58583
58584
58585
58586
58587
58588
58589 public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
58590 {
58591 parent::__construct($question, (bool) $default);
58592
58593 $this->trueAnswerRegex = $trueAnswerRegex;
58594 $this->setNormalizer($this->getDefaultNormalizer());
58595 }
58596
58597
58598
58599
58600
58601
58602 private function getDefaultNormalizer()
58603 {
58604 $default = $this->getDefault();
58605 $regex = $this->trueAnswerRegex;
58606
58607 return function ($answer) use ($default, $regex) {
58608 if (is_bool($answer)) {
58609 return $answer;
58610 }
58611
58612 $answerIsTrue = (bool) preg_match($regex, $answer);
58613 if (false === $default) {
58614 return $answer && $answerIsTrue;
58615 }
58616
58617 return !$answer || $answerIsTrue;
58618 };
58619 }
58620 }
58621 <?php
58622
58623
58624
58625
58626
58627
58628
58629
58630
58631
58632 namespace Symfony\Component\Console\Question;
58633
58634 use Symfony\Component\Console\Exception\InvalidArgumentException;
58635 use Symfony\Component\Console\Exception\LogicException;
58636
58637
58638
58639
58640
58641
58642 class Question
58643 {
58644 private $question;
58645 private $attempts;
58646 private $hidden = false;
58647 private $hiddenFallback = true;
58648 private $autocompleterValues;
58649 private $validator;
58650 private $default;
58651 private $normalizer;
58652
58653
58654
58655
58656
58657
58658
58659 public function __construct($question, $default = null)
58660 {
58661 $this->question = $question;
58662 $this->default = $default;
58663 }
58664
58665
58666
58667
58668
58669
58670 public function getQuestion()
58671 {
58672 return $this->question;
58673 }
58674
58675
58676
58677
58678
58679
58680 public function getDefault()
58681 {
58682 return $this->default;
58683 }
58684
58685
58686
58687
58688
58689
58690 public function isHidden()
58691 {
58692 return $this->hidden;
58693 }
58694
58695
58696
58697
58698
58699
58700
58701
58702
58703
58704 public function setHidden($hidden)
58705 {
58706 if ($this->autocompleterValues) {
58707 throw new LogicException('A hidden question cannot use the autocompleter.');
58708 }
58709
58710 $this->hidden = (bool) $hidden;
58711
58712 return $this;
58713 }
58714
58715
58716
58717
58718
58719
58720 public function isHiddenFallback()
58721 {
58722 return $this->hiddenFallback;
58723 }
58724
58725
58726
58727
58728
58729
58730
58731
58732 public function setHiddenFallback($fallback)
58733 {
58734 $this->hiddenFallback = (bool) $fallback;
58735
58736 return $this;
58737 }
58738
58739
58740
58741
58742
58743
58744 public function getAutocompleterValues()
58745 {
58746 return $this->autocompleterValues;
58747 }
58748
58749
58750
58751
58752
58753
58754
58755
58756
58757
58758
58759 public function setAutocompleterValues($values)
58760 {
58761 if (is_array($values)) {
58762 $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
58763 }
58764
58765 if (null !== $values && !is_array($values)) {
58766 if (!$values instanceof \Traversable || !$values instanceof \Countable) {
58767 throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.');
58768 }
58769 }
58770
58771 if ($this->hidden) {
58772 throw new LogicException('A hidden question cannot use the autocompleter.');
58773 }
58774
58775 $this->autocompleterValues = $values;
58776
58777 return $this;
58778 }
58779
58780
58781
58782
58783
58784
58785
58786
58787 public function setValidator($validator)
58788 {
58789 $this->validator = $validator;
58790
58791 return $this;
58792 }
58793
58794
58795
58796
58797
58798
58799 public function getValidator()
58800 {
58801 return $this->validator;
58802 }
58803
58804
58805
58806
58807
58808
58809
58810
58811
58812
58813
58814
58815 public function setMaxAttempts($attempts)
58816 {
58817 if (null !== $attempts && $attempts < 1) {
58818 throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
58819 }
58820
58821 $this->attempts = $attempts;
58822
58823 return $this;
58824 }
58825
58826
58827
58828
58829
58830
58831
58832
58833 public function getMaxAttempts()
58834 {
58835 return $this->attempts;
58836 }
58837
58838
58839
58840
58841
58842
58843
58844
58845
58846
58847 public function setNormalizer($normalizer)
58848 {
58849 $this->normalizer = $normalizer;
58850
58851 return $this;
58852 }
58853
58854
58855
58856
58857
58858
58859
58860
58861 public function getNormalizer()
58862 {
58863 return $this->normalizer;
58864 }
58865
58866 protected function isAssoc($array)
58867 {
58868 return (bool) count(array_filter(array_keys($array), 'is_string'));
58869 }
58870 }
58871 <?php
58872
58873
58874
58875
58876
58877
58878
58879
58880
58881
58882 namespace Symfony\Component\Console;
58883
58884 use Symfony\Component\Console\Exception\RuntimeException;
58885 use Symfony\Component\Console\Input\StringInput;
58886 use Symfony\Component\Console\Output\ConsoleOutput;
58887 use Symfony\Component\Process\ProcessBuilder;
58888 use Symfony\Component\Process\PhpExecutableFinder;
58889
58890
58891
58892
58893
58894
58895
58896
58897
58898
58899
58900
58901 class Shell
58902 {
58903 private $application;
58904 private $history;
58905 private $output;
58906 private $hasReadline;
58907 private $processIsolation = false;
58908
58909
58910
58911
58912
58913
58914
58915
58916
58917 public function __construct(Application $application)
58918 {
58919 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
58920
58921 $this->hasReadline = function_exists('readline');
58922 $this->application = $application;
58923 $this->history = getenv('HOME').'/.history_'.$application->getName();
58924 $this->output = new ConsoleOutput();
58925 }
58926
58927
58928
58929
58930 public function run()
58931 {
58932 $this->application->setAutoExit(false);
58933 $this->application->setCatchExceptions(true);
58934
58935 if ($this->hasReadline) {
58936 readline_read_history($this->history);
58937 readline_completion_function(array($this, 'autocompleter'));
58938 }
58939
58940 $this->output->writeln($this->getHeader());
58941 $php = null;
58942 if ($this->processIsolation) {
58943 $finder = new PhpExecutableFinder();
58944 $php = $finder->find();
58945 $this->output->writeln(<<<'EOF'
58946 <info>Running with process isolation, you should consider this:</info>
58947   * each command is executed as separate process,
58948   * commands don't support interactivity, all params must be passed explicitly,
58949   * commands output is not colorized.
58950
58951 EOF
58952 );
58953 }
58954
58955 while (true) {
58956 $command = $this->readline();
58957
58958 if (false === $command) {
58959 $this->output->writeln("\n");
58960
58961 break;
58962 }
58963
58964 if ($this->hasReadline) {
58965 readline_add_history($command);
58966 readline_write_history($this->history);
58967 }
58968
58969 if ($this->processIsolation) {
58970 $pb = new ProcessBuilder();
58971
58972 $process = $pb
58973 ->add($php)
58974 ->add($_SERVER['argv'][0])
58975 ->add($command)
58976 ->inheritEnvironmentVariables(true)
58977 ->getProcess()
58978 ;
58979
58980 $output = $this->output;
58981 $process->run(function ($type, $data) use ($output) {
58982 $output->writeln($data);
58983 });
58984
58985 $ret = $process->getExitCode();
58986 } else {
58987 $ret = $this->application->run(new StringInput($command), $this->output);
58988 }
58989
58990 if (0 !== $ret) {
58991 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
58992 }
58993 }
58994 }
58995
58996
58997
58998
58999
59000
59001 protected function getHeader()
59002 {
59003 return <<<EOF
59004
59005 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
59006
59007 At the prompt, type <comment>help</comment> for some help,
59008 or <comment>list</comment> to get a list of available commands.
59009
59010 To exit the shell, type <comment>^D</comment>.
59011
59012 EOF;
59013 }
59014
59015
59016
59017
59018
59019
59020 protected function getPrompt()
59021 {
59022
59023  return $this->output->getFormatter()->format($this->application->getName().' > ');
59024 }
59025
59026 protected function getOutput()
59027 {
59028 return $this->output;
59029 }
59030
59031 protected function getApplication()
59032 {
59033 return $this->application;
59034 }
59035
59036
59037
59038
59039
59040
59041
59042
59043 private function autocompleter($text)
59044 {
59045 $info = readline_info();
59046 $text = substr($info['line_buffer'], 0, $info['end']);
59047
59048 if ($info['point'] !== $info['end']) {
59049 return true;
59050 }
59051
59052
59053  if (false === strpos($text, ' ') || !$text) {
59054 return array_keys($this->application->all());
59055 }
59056
59057
59058  try {
59059 $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
59060 } catch (\Exception $e) {
59061 return true;
59062 }
59063
59064 $list = array('--help');
59065 foreach ($command->getDefinition()->getOptions() as $option) {
59066 $list[] = '--'.$option->getName();
59067 }
59068
59069 return $list;
59070 }
59071
59072
59073
59074
59075
59076
59077 private function readline()
59078 {
59079 if ($this->hasReadline) {
59080 $line = readline($this->getPrompt());
59081 } else {
59082 $this->output->write($this->getPrompt());
59083 $line = fgets(STDIN, 1024);
59084 $line = (false === $line || '' === $line) ? false : rtrim($line);
59085 }
59086
59087 return $line;
59088 }
59089
59090 public function getProcessIsolation()
59091 {
59092 return $this->processIsolation;
59093 }
59094
59095 public function setProcessIsolation($processIsolation)
59096 {
59097 $this->processIsolation = (bool) $processIsolation;
59098
59099 if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
59100 throw new RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
59101 }
59102 }
59103 }
59104 <?php
59105
59106
59107
59108
59109
59110
59111
59112
59113
59114
59115 namespace Symfony\Component\Console\Style;
59116
59117 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59118 use Symfony\Component\Console\Helper\ProgressBar;
59119 use Symfony\Component\Console\Output\OutputInterface;
59120
59121
59122
59123
59124
59125
59126 abstract class OutputStyle implements OutputInterface, StyleInterface
59127 {
59128 private $output;
59129
59130
59131
59132
59133 public function __construct(OutputInterface $output)
59134 {
59135 $this->output = $output;
59136 }
59137
59138
59139
59140
59141 public function newLine($count = 1)
59142 {
59143 $this->output->write(str_repeat(PHP_EOL, $count));
59144 }
59145
59146
59147
59148
59149
59150
59151 public function createProgressBar($max = 0)
59152 {
59153 return new ProgressBar($this->output, $max);
59154 }
59155
59156
59157
59158
59159 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
59160 {
59161 $this->output->write($messages, $newline, $type);
59162 }
59163
59164
59165
59166
59167 public function writeln($messages, $type = self::OUTPUT_NORMAL)
59168 {
59169 $this->output->writeln($messages, $type);
59170 }
59171
59172
59173
59174
59175 public function setVerbosity($level)
59176 {
59177 $this->output->setVerbosity($level);
59178 }
59179
59180
59181
59182
59183 public function getVerbosity()
59184 {
59185 return $this->output->getVerbosity();
59186 }
59187
59188
59189
59190
59191 public function setDecorated($decorated)
59192 {
59193 $this->output->setDecorated($decorated);
59194 }
59195
59196
59197
59198
59199 public function isDecorated()
59200 {
59201 return $this->output->isDecorated();
59202 }
59203
59204
59205
59206
59207 public function setFormatter(OutputFormatterInterface $formatter)
59208 {
59209 $this->output->setFormatter($formatter);
59210 }
59211
59212
59213
59214
59215 public function getFormatter()
59216 {
59217 return $this->output->getFormatter();
59218 }
59219 }
59220 <?php
59221
59222
59223
59224
59225
59226
59227
59228
59229
59230
59231 namespace Symfony\Component\Console\Style;
59232
59233
59234
59235
59236
59237
59238 interface StyleInterface
59239 {
59240
59241
59242
59243
59244
59245 public function title($message);
59246
59247
59248
59249
59250
59251
59252 public function section($message);
59253
59254
59255
59256
59257
59258
59259 public function listing(array $elements);
59260
59261
59262
59263
59264
59265
59266 public function text($message);
59267
59268
59269
59270
59271
59272
59273 public function success($message);
59274
59275
59276
59277
59278
59279
59280 public function error($message);
59281
59282
59283
59284
59285
59286
59287 public function warning($message);
59288
59289
59290
59291
59292
59293
59294 public function note($message);
59295
59296
59297
59298
59299
59300
59301 public function caution($message);
59302
59303
59304
59305
59306
59307
59308
59309 public function table(array $headers, array $rows);
59310
59311
59312
59313
59314
59315
59316
59317
59318
59319
59320 public function ask($question, $default = null, $validator = null);
59321
59322
59323
59324
59325
59326
59327
59328
59329
59330 public function askHidden($question, $validator = null);
59331
59332
59333
59334
59335
59336
59337
59338
59339
59340 public function confirm($question, $default = true);
59341
59342
59343
59344
59345
59346
59347
59348
59349
59350
59351 public function choice($question, array $choices, $default = null);
59352
59353
59354
59355
59356
59357
59358 public function newLine($count = 1);
59359
59360
59361
59362
59363
59364
59365 public function progressStart($max = 0);
59366
59367
59368
59369
59370
59371
59372 public function progressAdvance($step = 1);
59373
59374
59375
59376
59377 public function progressFinish();
59378 }
59379 <?php
59380
59381
59382
59383
59384
59385
59386
59387
59388
59389
59390 namespace Symfony\Component\Console\Style;
59391
59392 use Symfony\Component\Console\Application;
59393 use Symfony\Component\Console\Exception\RuntimeException;
59394 use Symfony\Component\Console\Formatter\OutputFormatter;
59395 use Symfony\Component\Console\Helper\Helper;
59396 use Symfony\Component\Console\Helper\ProgressBar;
59397 use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
59398 use Symfony\Component\Console\Helper\Table;
59399 use Symfony\Component\Console\Input\InputInterface;
59400 use Symfony\Component\Console\Output\BufferedOutput;
59401 use Symfony\Component\Console\Output\OutputInterface;
59402 use Symfony\Component\Console\Question\ChoiceQuestion;
59403 use Symfony\Component\Console\Question\ConfirmationQuestion;
59404 use Symfony\Component\Console\Question\Question;
59405
59406
59407
59408
59409
59410
59411 class SymfonyStyle extends OutputStyle
59412 {
59413 const MAX_LINE_LENGTH = 120;
59414
59415 private $input;
59416 private $questionHelper;
59417 private $progressBar;
59418 private $lineLength;
59419 private $bufferedOutput;
59420
59421
59422
59423
59424
59425 public function __construct(InputInterface $input, OutputInterface $output)
59426 {
59427 $this->input = $input;
59428 $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
59429
59430  $this->lineLength = min($this->getTerminalWidth() - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
59431
59432 parent::__construct($output);
59433 }
59434
59435
59436
59437
59438
59439
59440
59441
59442
59443
59444 public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
59445 {
59446 $messages = is_array($messages) ? array_values($messages) : array($messages);
59447
59448 $this->autoPrependBlock();
59449 $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, true));
59450 $this->newLine();
59451 }
59452
59453
59454
59455
59456 public function title($message)
59457 {
59458 $this->autoPrependBlock();
59459 $this->writeln(array(
59460 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
59461 sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
59462 ));
59463 $this->newLine();
59464 }
59465
59466
59467
59468
59469 public function section($message)
59470 {
59471 $this->autoPrependBlock();
59472 $this->writeln(array(
59473 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
59474 sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
59475 ));
59476 $this->newLine();
59477 }
59478
59479
59480
59481
59482 public function listing(array $elements)
59483 {
59484 $this->autoPrependText();
59485 $elements = array_map(function ($element) {
59486 return sprintf(' * %s', $element);
59487 }, $elements);
59488
59489 $this->writeln($elements);
59490 $this->newLine();
59491 }
59492
59493
59494
59495
59496 public function text($message)
59497 {
59498 $this->autoPrependText();
59499
59500 $messages = is_array($message) ? array_values($message) : array($message);
59501 foreach ($messages as $message) {
59502 $this->writeln(sprintf(' %s', $message));
59503 }
59504 }
59505
59506
59507
59508
59509
59510
59511 public function comment($message)
59512 {
59513 $messages = is_array($message) ? array_values($message) : array($message);
59514
59515 $this->autoPrependBlock();
59516 $this->writeln($this->createBlock($messages, null, null, '<fg=default;bg=default> // </>'));
59517 $this->newLine();
59518 }
59519
59520
59521
59522
59523 public function success($message)
59524 {
59525 $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
59526 }
59527
59528
59529
59530
59531 public function error($message)
59532 {
59533 $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
59534 }
59535
59536
59537
59538
59539 public function warning($message)
59540 {
59541 $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
59542 }
59543
59544
59545
59546
59547 public function note($message)
59548 {
59549 $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
59550 }
59551
59552
59553
59554
59555 public function caution($message)
59556 {
59557 $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
59558 }
59559
59560
59561
59562
59563 public function table(array $headers, array $rows)
59564 {
59565 $style = clone Table::getStyleDefinition('symfony-style-guide');
59566 $style->setCellHeaderFormat('<info>%s</info>');
59567
59568 $table = new Table($this);
59569 $table->setHeaders($headers);
59570 $table->setRows($rows);
59571 $table->setStyle($style);
59572
59573 $table->render();
59574 $this->newLine();
59575 }
59576
59577
59578
59579
59580 public function ask($question, $default = null, $validator = null)
59581 {
59582 $question = new Question($question, $default);
59583 $question->setValidator($validator);
59584
59585 return $this->askQuestion($question);
59586 }
59587
59588
59589
59590
59591 public function askHidden($question, $validator = null)
59592 {
59593 $question = new Question($question);
59594
59595 $question->setHidden(true);
59596 $question->setValidator($validator);
59597
59598 return $this->askQuestion($question);
59599 }
59600
59601
59602
59603
59604 public function confirm($question, $default = true)
59605 {
59606 return $this->askQuestion(new ConfirmationQuestion($question, $default));
59607 }
59608
59609
59610
59611
59612 public function choice($question, array $choices, $default = null)
59613 {
59614 if (null !== $default) {
59615 $values = array_flip($choices);
59616 $default = $values[$default];
59617 }
59618
59619 return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
59620 }
59621
59622
59623
59624
59625 public function progressStart($max = 0)
59626 {
59627 $this->progressBar = $this->createProgressBar($max);
59628 $this->progressBar->start();
59629 }
59630
59631
59632
59633
59634 public function progressAdvance($step = 1)
59635 {
59636 $this->getProgressBar()->advance($step);
59637 }
59638
59639
59640
59641
59642 public function progressFinish()
59643 {
59644 $this->getProgressBar()->finish();
59645 $this->newLine(2);
59646 $this->progressBar = null;
59647 }
59648
59649
59650
59651
59652 public function createProgressBar($max = 0)
59653 {
59654 $progressBar = parent::createProgressBar($max);
59655
59656 if ('\\' !== DIRECTORY_SEPARATOR) {
59657 $progressBar->setEmptyBarCharacter('░'); 
59658  $progressBar->setProgressCharacter('');
59659 $progressBar->setBarCharacter('▓'); 
59660  }
59661
59662 return $progressBar;
59663 }
59664
59665
59666
59667
59668
59669
59670 public function askQuestion(Question $question)
59671 {
59672 if ($this->input->isInteractive()) {
59673 $this->autoPrependBlock();
59674 }
59675
59676 if (!$this->questionHelper) {
59677 $this->questionHelper = new SymfonyQuestionHelper();
59678 }
59679
59680 $answer = $this->questionHelper->ask($this->input, $this, $question);
59681
59682 if ($this->input->isInteractive()) {
59683 $this->newLine();
59684 $this->bufferedOutput->write("\n");
59685 }
59686
59687 return $answer;
59688 }
59689
59690
59691
59692
59693 public function writeln($messages, $type = self::OUTPUT_NORMAL)
59694 {
59695 parent::writeln($messages, $type);
59696 $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
59697 }
59698
59699
59700
59701
59702 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
59703 {
59704 parent::write($messages, $newline, $type);
59705 $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
59706 }
59707
59708
59709
59710
59711 public function newLine($count = 1)
59712 {
59713 parent::newLine($count);
59714 $this->bufferedOutput->write(str_repeat("\n", $count));
59715 }
59716
59717
59718
59719
59720 private function getProgressBar()
59721 {
59722 if (!$this->progressBar) {
59723 throw new RuntimeException('The ProgressBar is not started.');
59724 }
59725
59726 return $this->progressBar;
59727 }
59728
59729 private function getTerminalWidth()
59730 {
59731 $application = new Application();
59732 $dimensions = $application->getTerminalDimensions();
59733
59734 return $dimensions[0] ?: self::MAX_LINE_LENGTH;
59735 }
59736
59737 private function autoPrependBlock()
59738 {
59739 $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
59740
59741 if (!isset($chars[0])) {
59742 return $this->newLine(); 
59743  }
59744
59745  $this->newLine(2 - substr_count($chars, "\n"));
59746 }
59747
59748 private function autoPrependText()
59749 {
59750 $fetched = $this->bufferedOutput->fetch();
59751
59752  if ("\n" !== substr($fetched, -1)) {
59753 $this->newLine();
59754 }
59755 }
59756
59757 private function reduceBuffer($messages)
59758 {
59759
59760  
59761  return array_map(function ($value) {
59762 return substr($value, -4);
59763 }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
59764 }
59765
59766 private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
59767 {
59768 $indentLength = 0;
59769 $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
59770 $lines = array();
59771
59772 if (null !== $type) {
59773 $type = sprintf('[%s] ', $type);
59774 $indentLength = strlen($type);
59775 $lineIndentation = str_repeat(' ', $indentLength);
59776 }
59777
59778
59779  foreach ($messages as $key => $message) {
59780 if ($escape) {
59781 $message = OutputFormatter::escape($message);
59782 }
59783
59784 $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
59785
59786 if (count($messages) > 1 && $key < count($messages) - 1) {
59787 $lines[] = '';
59788 }
59789 }
59790
59791 $firstLineIndex = 0;
59792 if ($padding && $this->isDecorated()) {
59793 $firstLineIndex = 1;
59794 array_unshift($lines, '');
59795 $lines[] = '';
59796 }
59797
59798 foreach ($lines as $i => &$line) {
59799 if (null !== $type) {
59800 $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
59801 }
59802
59803 $line = $prefix.$line;
59804 $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
59805
59806 if ($style) {
59807 $line = sprintf('<%s>%s</>', $style, $line);
59808 }
59809 }
59810
59811 return $lines;
59812 }
59813 }
59814 <?php
59815
59816
59817
59818
59819
59820
59821
59822
59823
59824
59825 namespace Symfony\Component\Console\Tester;
59826
59827 use Symfony\Component\Console\Application;
59828 use Symfony\Component\Console\Input\ArrayInput;
59829 use Symfony\Component\Console\Input\InputInterface;
59830 use Symfony\Component\Console\Output\OutputInterface;
59831 use Symfony\Component\Console\Output\StreamOutput;
59832
59833
59834
59835
59836
59837
59838
59839
59840
59841
59842
59843 class ApplicationTester
59844 {
59845 private $application;
59846 private $input;
59847 private $output;
59848 private $statusCode;
59849
59850
59851
59852
59853
59854
59855 public function __construct(Application $application)
59856 {
59857 $this->application = $application;
59858 }
59859
59860
59861
59862
59863
59864
59865
59866
59867
59868
59869
59870
59871
59872
59873
59874 public function run(array $input, $options = array())
59875 {
59876 $this->input = new ArrayInput($input);
59877 if (isset($options['interactive'])) {
59878 $this->input->setInteractive($options['interactive']);
59879 }
59880
59881 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
59882 if (isset($options['decorated'])) {
59883 $this->output->setDecorated($options['decorated']);
59884 }
59885 if (isset($options['verbosity'])) {
59886 $this->output->setVerbosity($options['verbosity']);
59887 }
59888
59889 return $this->statusCode = $this->application->run($this->input, $this->output);
59890 }
59891
59892
59893
59894
59895
59896
59897
59898
59899 public function getDisplay($normalize = false)
59900 {
59901 rewind($this->output->getStream());
59902
59903 $display = stream_get_contents($this->output->getStream());
59904
59905 if ($normalize) {
59906 $display = str_replace(PHP_EOL, "\n", $display);
59907 }
59908
59909 return $display;
59910 }
59911
59912
59913
59914
59915
59916
59917 public function getInput()
59918 {
59919 return $this->input;
59920 }
59921
59922
59923
59924
59925
59926
59927 public function getOutput()
59928 {
59929 return $this->output;
59930 }
59931
59932
59933
59934
59935
59936
59937 public function getStatusCode()
59938 {
59939 return $this->statusCode;
59940 }
59941 }
59942 <?php
59943
59944
59945
59946
59947
59948
59949
59950
59951
59952
59953 namespace Symfony\Component\Console\Tester;
59954
59955 use Symfony\Component\Console\Command\Command;
59956 use Symfony\Component\Console\Input\ArrayInput;
59957 use Symfony\Component\Console\Output\StreamOutput;
59958 use Symfony\Component\Console\Input\InputInterface;
59959 use Symfony\Component\Console\Output\OutputInterface;
59960
59961
59962
59963
59964
59965
59966 class CommandTester
59967 {
59968 private $command;
59969 private $input;
59970 private $output;
59971 private $statusCode;
59972
59973
59974
59975
59976
59977
59978 public function __construct(Command $command)
59979 {
59980 $this->command = $command;
59981 }
59982
59983
59984
59985
59986
59987
59988
59989
59990
59991
59992
59993
59994
59995
59996
59997 public function execute(array $input, array $options = array())
59998 {
59999
60000  
60001  if (!isset($input['command'])
60002 && (null !== $application = $this->command->getApplication())
60003 && $application->getDefinition()->hasArgument('command')
60004 ) {
60005 $input = array_merge(array('command' => $this->command->getName()), $input);
60006 }
60007
60008 $this->input = new ArrayInput($input);
60009 if (isset($options['interactive'])) {
60010 $this->input->setInteractive($options['interactive']);
60011 }
60012
60013 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
60014 $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
60015 if (isset($options['verbosity'])) {
60016 $this->output->setVerbosity($options['verbosity']);
60017 }
60018
60019 return $this->statusCode = $this->command->run($this->input, $this->output);
60020 }
60021
60022
60023
60024
60025
60026
60027
60028
60029 public function getDisplay($normalize = false)
60030 {
60031 rewind($this->output->getStream());
60032
60033 $display = stream_get_contents($this->output->getStream());
60034
60035 if ($normalize) {
60036 $display = str_replace(PHP_EOL, "\n", $display);
60037 }
60038
60039 return $display;
60040 }
60041
60042
60043
60044
60045
60046
60047 public function getInput()
60048 {
60049 return $this->input;
60050 }
60051
60052
60053
60054
60055
60056
60057 public function getOutput()
60058 {
60059 return $this->output;
60060 }
60061
60062
60063
60064
60065
60066
60067 public function getStatusCode()
60068 {
60069 return $this->statusCode;
60070 }
60071 }
60072 <?php
60073
60074
60075
60076
60077
60078
60079
60080
60081
60082
60083 namespace Symfony\Component\Debug;
60084
60085 use Psr\Log\AbstractLogger;
60086
60087
60088
60089
60090
60091
60092 class BufferingLogger extends AbstractLogger
60093 {
60094 private $logs = array();
60095
60096 public function log($level, $message, array $context = array())
60097 {
60098 $this->logs[] = array($level, $message, $context);
60099 }
60100
60101 public function cleanLogs()
60102 {
60103 $logs = $this->logs;
60104 $this->logs = array();
60105
60106 return $logs;
60107 }
60108 }
60109 <?php
60110
60111
60112
60113
60114
60115
60116
60117
60118
60119
60120 namespace Symfony\Component\Debug;
60121
60122
60123
60124
60125
60126
60127 class Debug
60128 {
60129 private static $enabled = false;
60130
60131
60132
60133
60134
60135
60136
60137
60138
60139
60140
60141
60142 public static function enable($errorReportingLevel = null, $displayErrors = true)
60143 {
60144 if (static::$enabled) {
60145 return;
60146 }
60147
60148 static::$enabled = true;
60149
60150 if (null !== $errorReportingLevel) {
60151 error_reporting($errorReportingLevel);
60152 } else {
60153 error_reporting(-1);
60154 }
60155
60156 if ('cli' !== PHP_SAPI) {
60157 ini_set('display_errors', 0);
60158 ExceptionHandler::register();
60159 } elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
60160
60161  ini_set('display_errors', 1);
60162 }
60163 if ($displayErrors) {
60164 ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
60165 } else {
60166 ErrorHandler::register()->throwAt(0, true);
60167 }
60168
60169 DebugClassLoader::enable();
60170 }
60171 }
60172 <?php
60173
60174
60175
60176
60177
60178
60179
60180
60181
60182
60183 namespace Symfony\Component\Debug;
60184
60185
60186
60187
60188
60189
60190
60191
60192
60193
60194
60195
60196 class DebugClassLoader
60197 {
60198 private $classLoader;
60199 private $isFinder;
60200 private $wasFinder;
60201 private static $caseCheck;
60202 private static $deprecated = array();
60203 private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
60204 private static $darwinCache = array('/' => array('/', array()));
60205
60206
60207
60208
60209
60210
60211 public function __construct($classLoader)
60212 {
60213 $this->wasFinder = is_object($classLoader) && method_exists($classLoader, 'findFile');
60214
60215 if ($this->wasFinder) {
60216 @trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
60217 $this->classLoader = array($classLoader, 'loadClass');
60218 $this->isFinder = true;
60219 } else {
60220 $this->classLoader = $classLoader;
60221 $this->isFinder = is_array($classLoader) && method_exists($classLoader[0], 'findFile');
60222 }
60223
60224 if (!isset(self::$caseCheck)) {
60225 $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR);
60226 $i = strrpos($file, DIRECTORY_SEPARATOR);
60227 $dir = substr($file, 0, 1 + $i);
60228 $file = substr($file, 1 + $i);
60229 $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
60230 $test = realpath($dir.$test);
60231
60232 if (false === $test || false === $i) {
60233
60234  self::$caseCheck = 0;
60235 } elseif (substr($test, -strlen($file)) === $file) {
60236
60237  self::$caseCheck = 1;
60238 } elseif (false !== stripos(PHP_OS, 'darwin')) {
60239
60240  self::$caseCheck = 2;
60241 } else {
60242
60243  self::$caseCheck = 0;
60244 }
60245 }
60246 }
60247
60248
60249
60250
60251
60252
60253 public function getClassLoader()
60254 {
60255 return $this->wasFinder ? $this->classLoader[0] : $this->classLoader;
60256 }
60257
60258
60259
60260
60261 public static function enable()
60262 {
60263
60264  class_exists('Symfony\Component\Debug\ErrorHandler');
60265 class_exists('Psr\Log\LogLevel');
60266
60267 if (!is_array($functions = spl_autoload_functions())) {
60268 return;
60269 }
60270
60271 foreach ($functions as $function) {
60272 spl_autoload_unregister($function);
60273 }
60274
60275 foreach ($functions as $function) {
60276 if (!is_array($function) || !$function[0] instanceof self) {
60277 $function = array(new static($function), 'loadClass');
60278 }
60279
60280 spl_autoload_register($function);
60281 }
60282 }
60283
60284
60285
60286
60287 public static function disable()
60288 {
60289 if (!is_array($functions = spl_autoload_functions())) {
60290 return;
60291 }
60292
60293 foreach ($functions as $function) {
60294 spl_autoload_unregister($function);
60295 }
60296
60297 foreach ($functions as $function) {
60298 if (is_array($function) && $function[0] instanceof self) {
60299 $function = $function[0]->getClassLoader();
60300 }
60301
60302 spl_autoload_register($function);
60303 }
60304 }
60305
60306
60307
60308
60309
60310
60311
60312
60313
60314
60315 public function findFile($class)
60316 {
60317 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
60318
60319 if ($this->wasFinder) {
60320 return $this->classLoader[0]->findFile($class);
60321 }
60322 }
60323
60324
60325
60326
60327
60328
60329
60330
60331
60332
60333 public function loadClass($class)
60334 {
60335 ErrorHandler::stackErrors();
60336
60337 try {
60338 if ($this->isFinder) {
60339 if ($file = $this->classLoader[0]->findFile($class)) {
60340 require_once $file;
60341 }
60342 } else {
60343 call_user_func($this->classLoader, $class);
60344 $file = false;
60345 }
60346 } catch (\Exception $e) {
60347 ErrorHandler::unstackErrors();
60348
60349 throw $e;
60350 } catch (\Throwable $e) {
60351 ErrorHandler::unstackErrors();
60352
60353 throw $e;
60354 }
60355
60356 ErrorHandler::unstackErrors();
60357
60358 $exists = class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
60359
60360 if ($class && '\\' === $class[0]) {
60361 $class = substr($class, 1);
60362 }
60363
60364 if ($exists) {
60365 $refl = new \ReflectionClass($class);
60366 $name = $refl->getName();
60367
60368 if ($name !== $class && 0 === strcasecmp($name, $class)) {
60369 throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name));
60370 }
60371
60372 if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
60373 @trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
60374 } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
60375 self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
60376 } else {
60377 if (2 > $len = 1 + (strpos($name, '\\', 1 + strpos($name, '\\')) ?: strpos($name, '_'))) {
60378 $len = 0;
60379 $ns = '';
60380 } else {
60381 switch ($ns = substr($name, 0, $len)) {
60382 case 'Symfony\Bridge\\':
60383 case 'Symfony\Bundle\\':
60384 case 'Symfony\Component\\':
60385 $ns = 'Symfony\\';
60386 $len = strlen($ns);
60387 break;
60388 }
60389 }
60390 $parent = get_parent_class($class);
60391
60392 if (!$parent || strncmp($ns, $parent, $len)) {
60393 if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
60394 @trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
60395 }
60396
60397 $parentInterfaces = array();
60398 $deprecatedInterfaces = array();
60399 if ($parent) {
60400 foreach (class_implements($parent) as $interface) {
60401 $parentInterfaces[$interface] = 1;
60402 }
60403 }
60404
60405 foreach ($refl->getInterfaceNames() as $interface) {
60406 if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
60407 $deprecatedInterfaces[] = $interface;
60408 }
60409 foreach (class_implements($interface) as $interface) {
60410 $parentInterfaces[$interface] = 1;
60411 }
60412 }
60413
60414 foreach ($deprecatedInterfaces as $interface) {
60415 if (!isset($parentInterfaces[$interface])) {
60416 @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);
60417 }
60418 }
60419 }
60420 }
60421 }
60422
60423 if ($file) {
60424 if (!$exists) {
60425 if (false !== strpos($class, '/')) {
60426 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));
60427 }
60428
60429 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));
60430 }
60431 if (self::$caseCheck) {
60432 $real = explode('\\', $class.strrchr($file, '.'));
60433 $tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file));
60434
60435 $i = count($tail) - 1;
60436 $j = count($real) - 1;
60437
60438 while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
60439 --$i;
60440 --$j;
60441 }
60442
60443 array_splice($tail, 0, $i + 1);
60444 }
60445 if (self::$caseCheck && $tail) {
60446 $tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail);
60447 $tailLen = strlen($tail);
60448 $real = $refl->getFileName();
60449
60450 if (2 === self::$caseCheck) {
60451
60452
60453 $i = 1 + strrpos($real, '/');
60454 $file = substr($real, $i);
60455 $real = substr($real, 0, $i);
60456
60457 if (isset(self::$darwinCache[$real])) {
60458 $kDir = $real;
60459 } else {
60460 $kDir = strtolower($real);
60461
60462 if (isset(self::$darwinCache[$kDir])) {
60463 $real = self::$darwinCache[$kDir][0];
60464 } else {
60465 $dir = getcwd();
60466 chdir($real);
60467 $real = getcwd().'/';
60468 chdir($dir);
60469
60470 $dir = $real;
60471 $k = $kDir;
60472 $i = strlen($dir) - 1;
60473 while (!isset(self::$darwinCache[$k])) {
60474 self::$darwinCache[$k] = array($dir, array());
60475 self::$darwinCache[$dir] = &self::$darwinCache[$k];
60476
60477 while ('/' !== $dir[--$i]) {
60478 }
60479 $k = substr($k, 0, ++$i);
60480 $dir = substr($dir, 0, $i--);
60481 }
60482 }
60483 }
60484
60485 $dirFiles = self::$darwinCache[$kDir][1];
60486
60487 if (isset($dirFiles[$file])) {
60488 $kFile = $file;
60489 } else {
60490 $kFile = strtolower($file);
60491
60492 if (!isset($dirFiles[$kFile])) {
60493 foreach (scandir($real, 2) as $f) {
60494 if ('.' !== $f[0]) {
60495 $dirFiles[$f] = $f;
60496 if ($f === $file) {
60497 $kFile = $k = $file;
60498 } elseif ($f !== $k = strtolower($f)) {
60499 $dirFiles[$k] = $f;
60500 }
60501 }
60502 }
60503 self::$darwinCache[$kDir][1] = $dirFiles;
60504 }
60505 }
60506
60507 $real .= $dirFiles[$kFile];
60508 }
60509
60510 if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
60511 && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
60512 ) {
60513 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)));
60514 }
60515 }
60516
60517 return true;
60518 }
60519 }
60520 }
60521 <?php
60522
60523
60524
60525
60526
60527
60528
60529
60530
60531
60532 namespace Symfony\Component\Debug;
60533
60534 use Psr\Log\LogLevel;
60535 use Psr\Log\LoggerInterface;
60536 use Symfony\Component\Debug\Exception\ContextErrorException;
60537 use Symfony\Component\Debug\Exception\FatalErrorException;
60538 use Symfony\Component\Debug\Exception\FatalThrowableError;
60539 use Symfony\Component\Debug\Exception\OutOfMemoryException;
60540 use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
60541 use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
60542 use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
60543 use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
60544
60545
60546
60547
60548
60549
60550
60551
60552
60553
60554
60555
60556
60557
60558
60559
60560
60561
60562
60563
60564
60565
60566
60567 class ErrorHandler
60568 {
60569
60570
60571
60572 const TYPE_DEPRECATION = -100;
60573
60574 private $levels = array(
60575 E_DEPRECATED => 'Deprecated',
60576 E_USER_DEPRECATED => 'User Deprecated',
60577 E_NOTICE => 'Notice',
60578 E_USER_NOTICE => 'User Notice',
60579 E_STRICT => 'Runtime Notice',
60580 E_WARNING => 'Warning',
60581 E_USER_WARNING => 'User Warning',
60582 E_COMPILE_WARNING => 'Compile Warning',
60583 E_CORE_WARNING => 'Core Warning',
60584 E_USER_ERROR => 'User Error',
60585 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
60586 E_COMPILE_ERROR => 'Compile Error',
60587 E_PARSE => 'Parse Error',
60588 E_ERROR => 'Error',
60589 E_CORE_ERROR => 'Core Error',
60590 );
60591
60592 private $loggers = array(
60593 E_DEPRECATED => array(null, LogLevel::INFO),
60594 E_USER_DEPRECATED => array(null, LogLevel::INFO),
60595 E_NOTICE => array(null, LogLevel::WARNING),
60596 E_USER_NOTICE => array(null, LogLevel::WARNING),
60597 E_STRICT => array(null, LogLevel::WARNING),
60598 E_WARNING => array(null, LogLevel::WARNING),
60599 E_USER_WARNING => array(null, LogLevel::WARNING),
60600 E_COMPILE_WARNING => array(null, LogLevel::WARNING),
60601 E_CORE_WARNING => array(null, LogLevel::WARNING),
60602 E_USER_ERROR => array(null, LogLevel::CRITICAL),
60603 E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
60604 E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
60605 E_PARSE => array(null, LogLevel::CRITICAL),
60606 E_ERROR => array(null, LogLevel::CRITICAL),
60607 E_CORE_ERROR => array(null, LogLevel::CRITICAL),
60608 );
60609
60610 private $thrownErrors = 0x1FFF; 
60611  private $scopedErrors = 0x1FFF; 
60612  private $tracedErrors = 0x77FB; 
60613  private $screamedErrors = 0x55; 
60614  private $loggedErrors = 0;
60615
60616 private $loggedTraces = array();
60617 private $isRecursive = 0;
60618 private $isRoot = false;
60619 private $exceptionHandler;
60620 private $bootstrappingLogger;
60621
60622 private static $reservedMemory;
60623 private static $stackedErrors = array();
60624 private static $stackedErrorLevels = array();
60625 private static $toStringException = null;
60626 private static $exitCode = 0;
60627
60628
60629
60630
60631
60632
60633 private $displayErrors = 0x1FFF;
60634
60635
60636
60637
60638
60639
60640
60641
60642
60643 public static function register($handler = null, $replace = true)
60644 {
60645 if (null === self::$reservedMemory) {
60646 self::$reservedMemory = str_repeat('x', 10240);
60647 register_shutdown_function(__CLASS__.'::handleFatalError');
60648 }
60649
60650 $levels = -1;
60651
60652 if ($handlerIsNew = !$handler instanceof self) {
60653
60654  if (null !== $handler) {
60655 $levels = $replace ? $handler : 0;
60656 $replace = true;
60657 }
60658 $handler = new static();
60659 }
60660
60661 if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
60662 restore_error_handler();
60663
60664  set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
60665 $handler->isRoot = true;
60666 }
60667
60668 if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) {
60669 $handler = $prev[0];
60670 $replace = false;
60671 }
60672 if ($replace || !$prev) {
60673 $handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException')));
60674 } else {
60675 restore_error_handler();
60676 }
60677
60678 $handler->throwAt($levels & $handler->thrownErrors, true);
60679
60680 return $handler;
60681 }
60682
60683 public function __construct(BufferingLogger $bootstrappingLogger = null)
60684 {
60685 if ($bootstrappingLogger) {
60686 $this->bootstrappingLogger = $bootstrappingLogger;
60687 $this->setDefaultLogger($bootstrappingLogger);
60688 }
60689 }
60690
60691
60692
60693
60694
60695
60696
60697
60698 public function setDefaultLogger(LoggerInterface $logger, $levels = null, $replace = false)
60699 {
60700 $loggers = array();
60701
60702 if (is_array($levels)) {
60703 foreach ($levels as $type => $logLevel) {
60704 if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
60705 $loggers[$type] = array($logger, $logLevel);
60706 }
60707 }
60708 } else {
60709 if (null === $levels) {
60710 $levels = E_ALL | E_STRICT;
60711 }
60712 foreach ($this->loggers as $type => $log) {
60713 if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
60714 $log[0] = $logger;
60715 $loggers[$type] = $log;
60716 }
60717 }
60718 }
60719
60720 $this->setLoggers($loggers);
60721 }
60722
60723
60724
60725
60726
60727
60728
60729
60730
60731
60732 public function setLoggers(array $loggers)
60733 {
60734 $prevLogged = $this->loggedErrors;
60735 $prev = $this->loggers;
60736 $flush = array();
60737
60738 foreach ($loggers as $type => $log) {
60739 if (!isset($prev[$type])) {
60740 throw new \InvalidArgumentException('Unknown error type: '.$type);
60741 }
60742 if (!is_array($log)) {
60743 $log = array($log);
60744 } elseif (!array_key_exists(0, $log)) {
60745 throw new \InvalidArgumentException('No logger provided');
60746 }
60747 if (null === $log[0]) {
60748 $this->loggedErrors &= ~$type;
60749 } elseif ($log[0] instanceof LoggerInterface) {
60750 $this->loggedErrors |= $type;
60751 } else {
60752 throw new \InvalidArgumentException('Invalid logger provided');
60753 }
60754 $this->loggers[$type] = $log + $prev[$type];
60755
60756 if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
60757 $flush[$type] = $type;
60758 }
60759 }
60760 $this->reRegister($prevLogged | $this->thrownErrors);
60761
60762 if ($flush) {
60763 foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
60764 $type = $log[2]['type'];
60765 if (!isset($flush[$type])) {
60766 $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
60767 } elseif ($this->loggers[$type][0]) {
60768 $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
60769 }
60770 }
60771 }
60772
60773 return $prev;
60774 }
60775
60776
60777
60778
60779
60780
60781
60782
60783
60784
60785 public function setExceptionHandler($handler)
60786 {
60787 if (null !== $handler && !is_callable($handler)) {
60788 throw new \LogicException('The exception handler must be a valid PHP callable.');
60789 }
60790 $prev = $this->exceptionHandler;
60791 $this->exceptionHandler = $handler;
60792
60793 return $prev;
60794 }
60795
60796
60797
60798
60799
60800
60801
60802
60803
60804 public function throwAt($levels, $replace = false)
60805 {
60806 $prev = $this->thrownErrors;
60807 $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
60808 if (!$replace) {
60809 $this->thrownErrors |= $prev;
60810 }
60811 $this->reRegister($prev | $this->loggedErrors);
60812
60813
60814  $this->displayErrors = $this->thrownErrors;
60815
60816 return $prev;
60817 }
60818
60819
60820
60821
60822
60823
60824
60825
60826
60827 public function scopeAt($levels, $replace = false)
60828 {
60829 $prev = $this->scopedErrors;
60830 $this->scopedErrors = (int) $levels;
60831 if (!$replace) {
60832 $this->scopedErrors |= $prev;
60833 }
60834
60835 return $prev;
60836 }
60837
60838
60839
60840
60841
60842
60843
60844
60845
60846 public function traceAt($levels, $replace = false)
60847 {
60848 $prev = $this->tracedErrors;
60849 $this->tracedErrors = (int) $levels;
60850 if (!$replace) {
60851 $this->tracedErrors |= $prev;
60852 }
60853
60854 return $prev;
60855 }
60856
60857
60858
60859
60860
60861
60862
60863
60864
60865 public function screamAt($levels, $replace = false)
60866 {
60867 $prev = $this->screamedErrors;
60868 $this->screamedErrors = (int) $levels;
60869 if (!$replace) {
60870 $this->screamedErrors |= $prev;
60871 }
60872
60873 return $prev;
60874 }
60875
60876
60877
60878
60879 private function reRegister($prev)
60880 {
60881 if ($prev !== $this->thrownErrors | $this->loggedErrors) {
60882 $handler = set_error_handler('var_dump');
60883 $handler = is_array($handler) ? $handler[0] : null;
60884 restore_error_handler();
60885 if ($handler === $this) {
60886 restore_error_handler();
60887 if ($this->isRoot) {
60888 set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
60889 } else {
60890 set_error_handler(array($this, 'handleError'));
60891 }
60892 }
60893 }
60894 }
60895
60896
60897
60898
60899
60900
60901
60902
60903
60904
60905
60906
60907
60908
60909
60910 public function handleError($type, $message, $file, $line)
60911 {
60912 $level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
60913 $log = $this->loggedErrors & $type;
60914 $throw = $this->thrownErrors & $type & $level;
60915 $type &= $level | $this->screamedErrors;
60916
60917 if (!$type || (!$log && !$throw)) {
60918 return $type && $log;
60919 }
60920 $scope = $this->scopedErrors & $type;
60921
60922 if (4 < $numArgs = func_num_args()) {
60923 $context = $scope ? (func_get_arg(4) ?: array()) : array();
60924 $backtrace = 5 < $numArgs ? func_get_arg(5) : null; 
60925  } else {
60926 $context = array();
60927 $backtrace = null;
60928 }
60929
60930 if (isset($context['GLOBALS']) && $scope) {
60931 $e = $context; 
60932  unset($e['GLOBALS'], $context); 
60933  $context = $e;
60934 }
60935
60936 if (null !== $backtrace && $type & E_ERROR) {
60937
60938  
60939  
60940  $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
60941
60942 return true;
60943 }
60944
60945 if ($throw) {
60946 if (null !== self::$toStringException) {
60947 $throw = self::$toStringException;
60948 self::$toStringException = null;
60949 } elseif ($scope && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
60950
60951  $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
60952 } else {
60953 $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
60954 }
60955
60956 if (\PHP_VERSION_ID <= 50407 && (\PHP_VERSION_ID >= 50400 || \PHP_VERSION_ID <= 50317)) {
60957
60958  
60959  
60960
60961 $throw->errorHandlerCanary = new ErrorHandlerCanary();
60962 }
60963
60964 if (E_USER_ERROR & $type) {
60965 $backtrace = $backtrace ?: $throw->getTrace();
60966
60967 for ($i = 1; isset($backtrace[$i]); ++$i) {
60968 if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
60969 && '__toString' === $backtrace[$i]['function']
60970 && '->' === $backtrace[$i]['type']
60971 && !isset($backtrace[$i - 1]['class'])
60972 && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
60973 ) {
60974
60975  
60976  
60977  
60978  
60979  
60980
60981 foreach ($context as $e) {
60982 if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
60983 if (1 === $i) {
60984
60985  $throw = $e;
60986 break;
60987 }
60988 self::$toStringException = $e;
60989
60990 return true;
60991 }
60992 }
60993
60994 if (1 < $i) {
60995
60996  $this->handleException($throw);
60997
60998
60999  return false;
61000 }
61001 }
61002 }
61003 }
61004
61005 throw $throw;
61006 }
61007
61008
61009  $e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
61010 $trace = true;
61011
61012 if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
61013 $trace = false;
61014 } else {
61015 $this->loggedTraces[$e] = 1;
61016 }
61017
61018 $e = compact('type', 'file', 'line', 'level');
61019
61020 if ($type & $level) {
61021 if ($scope) {
61022 $e['scope_vars'] = $context;
61023 if ($trace) {
61024 $e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
61025 }
61026 } elseif ($trace) {
61027 if (null === $backtrace) {
61028 $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
61029 } else {
61030 foreach ($backtrace as &$frame) {
61031 unset($frame['args'], $frame);
61032 }
61033 $e['stack'] = $backtrace;
61034 }
61035 }
61036 }
61037
61038 if ($this->isRecursive) {
61039 $log = 0;
61040 } elseif (self::$stackedErrorLevels) {
61041 self::$stackedErrors[] = array($this->loggers[$type][0], ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
61042 } else {
61043 try {
61044 $this->isRecursive = true;
61045 $this->loggers[$type][0]->log(($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
61046 $this->isRecursive = false;
61047 } catch (\Exception $e) {
61048 $this->isRecursive = false;
61049
61050 throw $e;
61051 } catch (\Throwable $e) {
61052 $this->isRecursive = false;
61053
61054 throw $e;
61055 }
61056 }
61057
61058 return $type && $log;
61059 }
61060
61061
61062
61063
61064
61065
61066
61067
61068
61069 public function handleException($exception, array $error = null)
61070 {
61071 if (null === $error) {
61072 self::$exitCode = 255;
61073 }
61074 if (!$exception instanceof \Exception) {
61075 $exception = new FatalThrowableError($exception);
61076 }
61077 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
61078
61079 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
61080 $e = array(
61081 'type' => $type,
61082 'file' => $exception->getFile(),
61083 'line' => $exception->getLine(),
61084 'level' => error_reporting(),
61085 'stack' => $exception->getTrace(),
61086 );
61087 if ($exception instanceof FatalErrorException) {
61088 if ($exception instanceof FatalThrowableError) {
61089 $error = array(
61090 'type' => $type,
61091 'message' => $message = $exception->getMessage(),
61092 'file' => $e['file'],
61093 'line' => $e['line'],
61094 );
61095 } else {
61096 $message = 'Fatal '.$exception->getMessage();
61097 }
61098 } elseif ($exception instanceof \ErrorException) {
61099 $message = 'Uncaught '.$exception->getMessage();
61100 if ($exception instanceof ContextErrorException) {
61101 $e['context'] = $exception->getContext();
61102 }
61103 } else {
61104 $message = 'Uncaught Exception: '.$exception->getMessage();
61105 }
61106 }
61107 if ($this->loggedErrors & $type) {
61108 try {
61109 $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
61110 } catch (\Exception $handlerException) {
61111 } catch (\Throwable $handlerException) {
61112 }
61113 }
61114 if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
61115 foreach ($this->getFatalErrorHandlers() as $handler) {
61116 if ($e = $handler->handleError($error, $exception)) {
61117 $exception = $e;
61118 break;
61119 }
61120 }
61121 }
61122 if (empty($this->exceptionHandler)) {
61123 throw $exception; 
61124  }
61125 try {
61126 call_user_func($this->exceptionHandler, $exception);
61127 } catch (\Exception $handlerException) {
61128 } catch (\Throwable $handlerException) {
61129 }
61130 if (isset($handlerException)) {
61131 $this->exceptionHandler = null;
61132 $this->handleException($handlerException);
61133 }
61134 }
61135
61136
61137
61138
61139
61140
61141
61142
61143 public static function handleFatalError(array $error = null)
61144 {
61145 if (null === self::$reservedMemory) {
61146 return;
61147 }
61148
61149 self::$reservedMemory = null;
61150
61151 $handler = set_error_handler('var_dump');
61152 $handler = is_array($handler) ? $handler[0] : null;
61153 restore_error_handler();
61154
61155 if (!$handler instanceof self) {
61156 return;
61157 }
61158
61159 if ($exit = null === $error) {
61160 $error = error_get_last();
61161 }
61162
61163 try {
61164 while (self::$stackedErrorLevels) {
61165 static::unstackErrors();
61166 }
61167 } catch (\Exception $exception) {
61168
61169  } catch (\Throwable $exception) {
61170
61171  }
61172
61173 if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
61174
61175  $handler->throwAt(0, true);
61176 $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
61177
61178 if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
61179 $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
61180 } else {
61181 $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
61182 }
61183 }
61184
61185 try {
61186 if (isset($exception)) {
61187 self::$exitCode = 255;
61188 $handler->handleException($exception, $error);
61189 }
61190 } catch (FatalErrorException $e) {
61191
61192  }
61193
61194 if ($exit && self::$exitCode) {
61195 $exitCode = self::$exitCode;
61196 register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); });
61197 }
61198 }
61199
61200
61201
61202
61203
61204
61205
61206
61207
61208
61209
61210
61211 public static function stackErrors()
61212 {
61213 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
61214 }
61215
61216
61217
61218
61219 public static function unstackErrors()
61220 {
61221 $level = array_pop(self::$stackedErrorLevels);
61222
61223 if (null !== $level) {
61224 $e = error_reporting($level);
61225 if ($e !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
61226
61227  error_reporting($e);
61228 }
61229 }
61230
61231 if (empty(self::$stackedErrorLevels)) {
61232 $errors = self::$stackedErrors;
61233 self::$stackedErrors = array();
61234
61235 foreach ($errors as $e) {
61236 $e[0]->log($e[1], $e[2], $e[3]);
61237 }
61238 }
61239 }
61240
61241
61242
61243
61244
61245
61246
61247
61248 protected function getFatalErrorHandlers()
61249 {
61250 return array(
61251 new UndefinedFunctionFatalErrorHandler(),
61252 new UndefinedMethodFatalErrorHandler(),
61253 new ClassNotFoundFatalErrorHandler(),
61254 );
61255 }
61256
61257
61258
61259
61260
61261
61262
61263
61264 public function setLevel($level)
61265 {
61266 @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);
61267
61268 $level = null === $level ? error_reporting() : $level;
61269 $this->throwAt($level, true);
61270 }
61271
61272
61273
61274
61275
61276
61277
61278
61279 public function setDisplayErrors($displayErrors)
61280 {
61281 @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);
61282
61283 if ($displayErrors) {
61284 $this->throwAt($this->displayErrors, true);
61285 } else {
61286 $displayErrors = $this->displayErrors;
61287 $this->throwAt(0, true);
61288 $this->displayErrors = $displayErrors;
61289 }
61290 }
61291
61292
61293
61294
61295
61296
61297
61298
61299
61300 public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
61301 {
61302 @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);
61303
61304 $handler = set_error_handler('var_dump');
61305 $handler = is_array($handler) ? $handler[0] : null;
61306 restore_error_handler();
61307 if (!$handler instanceof self) {
61308 return;
61309 }
61310 if ('deprecation' === $channel) {
61311 $handler->setDefaultLogger($logger, E_DEPRECATED | E_USER_DEPRECATED, true);
61312 $handler->screamAt(E_DEPRECATED | E_USER_DEPRECATED);
61313 } elseif ('scream' === $channel) {
61314 $handler->setDefaultLogger($logger, E_ALL | E_STRICT, false);
61315 $handler->screamAt(E_ALL | E_STRICT);
61316 } elseif ('emergency' === $channel) {
61317 $handler->setDefaultLogger($logger, E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR, true);
61318 $handler->screamAt(E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
61319 }
61320 }
61321
61322
61323
61324
61325 public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
61326 {
61327 $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());
61328
61329 return $this->handleError($level, $message, $file, $line, (array) $context);
61330 }
61331
61332
61333
61334
61335
61336
61337 public function handleFatal()
61338 {
61339 @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);
61340
61341 static::handleFatalError();
61342 }
61343 }
61344
61345
61346
61347
61348
61349
61350
61351
61352 class ErrorHandlerCanary
61353 {
61354 private static $displayErrors = null;
61355
61356 public function __construct()
61357 {
61358 if (null === self::$displayErrors) {
61359 self::$displayErrors = ini_set('display_errors', 1);
61360 }
61361 }
61362
61363 public function __destruct()
61364 {
61365 if (null !== self::$displayErrors) {
61366 ini_set('display_errors', self::$displayErrors);
61367 self::$displayErrors = null;
61368 }
61369 }
61370 }
61371 <?php
61372
61373
61374
61375
61376
61377
61378
61379
61380
61381
61382 namespace Symfony\Component\Debug\Exception;
61383
61384
61385
61386
61387
61388
61389 class ClassNotFoundException extends FatalErrorException
61390 {
61391 public function __construct($message, \ErrorException $previous)
61392 {
61393 parent::__construct(
61394 $message,
61395 $previous->getCode(),
61396 $previous->getSeverity(),
61397 $previous->getFile(),
61398 $previous->getLine(),
61399 $previous->getPrevious()
61400 );
61401 $this->setTrace($previous->getTrace());
61402 }
61403 }
61404 <?php
61405
61406
61407
61408
61409
61410
61411
61412
61413
61414
61415 namespace Symfony\Component\Debug\Exception;
61416
61417
61418
61419
61420
61421
61422 class ContextErrorException extends \ErrorException
61423 {
61424 private $context = array();
61425
61426 public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
61427 {
61428 parent::__construct($message, $code, $severity, $filename, $lineno);
61429 $this->context = $context;
61430 }
61431
61432
61433
61434
61435 public function getContext()
61436 {
61437 return $this->context;
61438 }
61439 }
61440 <?php
61441
61442
61443
61444
61445
61446
61447
61448
61449
61450
61451 namespace Symfony\Component\Debug\Exception;
61452
61453 @trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
61454
61455
61456
61457
61458
61459
61460 class DummyException extends \ErrorException
61461 {
61462 }
61463 <?php
61464
61465
61466
61467
61468
61469
61470
61471
61472
61473
61474 namespace Symfony\Component\HttpKernel\Exception;
61475
61476
61477
61478
61479
61480
61481
61482
61483
61484
61485 class FatalErrorException extends \ErrorException
61486 {
61487 }
61488
61489 namespace Symfony\Component\Debug\Exception;
61490
61491 use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
61492
61493
61494
61495
61496
61497
61498 class FatalErrorException extends LegacyFatalErrorException
61499 {
61500 public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null)
61501 {
61502 parent::__construct($message, $code, $severity, $filename, $lineno);
61503
61504 if (null !== $trace) {
61505 if (!$traceArgs) {
61506 foreach ($trace as &$frame) {
61507 unset($frame['args'], $frame['this'], $frame);
61508 }
61509 }
61510
61511 $this->setTrace($trace);
61512 } elseif (null !== $traceOffset) {
61513 if (function_exists('xdebug_get_function_stack')) {
61514 $trace = xdebug_get_function_stack();
61515 if (0 < $traceOffset) {
61516 array_splice($trace, -$traceOffset);
61517 }
61518
61519 foreach ($trace as &$frame) {
61520 if (!isset($frame['type'])) {
61521
61522  if (isset($frame['class'])) {
61523 $frame['type'] = '::';
61524 }
61525 } elseif ('dynamic' === $frame['type']) {
61526 $frame['type'] = '->';
61527 } elseif ('static' === $frame['type']) {
61528 $frame['type'] = '::';
61529 }
61530
61531
61532  if (!$traceArgs) {
61533 unset($frame['params'], $frame['args']);
61534 } elseif (isset($frame['params']) && !isset($frame['args'])) {
61535 $frame['args'] = $frame['params'];
61536 unset($frame['params']);
61537 }
61538 }
61539
61540 unset($frame);
61541 $trace = array_reverse($trace);
61542 } elseif (function_exists('symfony_debug_backtrace')) {
61543 $trace = symfony_debug_backtrace();
61544 if (0 < $traceOffset) {
61545 array_splice($trace, 0, $traceOffset);
61546 }
61547 } else {
61548 $trace = array();
61549 }
61550
61551 $this->setTrace($trace);
61552 }
61553 }
61554
61555 protected function setTrace($trace)
61556 {
61557 $traceReflector = new \ReflectionProperty('Exception', 'trace');
61558 $traceReflector->setAccessible(true);
61559 $traceReflector->setValue($this, $trace);
61560 }
61561 }
61562 <?php
61563
61564
61565
61566
61567
61568
61569
61570
61571
61572
61573 namespace Symfony\Component\Debug\Exception;
61574
61575
61576
61577
61578
61579
61580 class FatalThrowableError extends FatalErrorException
61581 {
61582 public function __construct(\Throwable $e)
61583 {
61584 if ($e instanceof \ParseError) {
61585 $message = 'Parse error: '.$e->getMessage();
61586 $severity = E_PARSE;
61587 } elseif ($e instanceof \TypeError) {
61588 $message = 'Type error: '.$e->getMessage();
61589 $severity = E_RECOVERABLE_ERROR;
61590 } else {
61591 $message = $e->getMessage();
61592 $severity = E_ERROR;
61593 }
61594
61595 \ErrorException::__construct(
61596 $message,
61597 $e->getCode(),
61598 $severity,
61599 $e->getFile(),
61600 $e->getLine()
61601 );
61602
61603 $this->setTrace($e->getTrace());
61604 }
61605 }
61606 <?php
61607
61608
61609
61610
61611
61612
61613
61614
61615
61616
61617 namespace Symfony\Component\HttpKernel\Exception;
61618
61619 use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;
61620
61621
61622
61623
61624
61625
61626
61627
61628
61629
61630 class FlattenException
61631 {
61632 private $handler;
61633
61634 public static function __callStatic($method, $args)
61635 {
61636 if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) {
61637 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_called_class(), $method));
61638 }
61639
61640 return call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
61641 }
61642
61643 public function __call($method, $args)
61644 {
61645 if (!isset($this->handler)) {
61646 $this->handler = new DebugFlattenException();
61647 }
61648
61649 if (!method_exists($this->handler, $method)) {
61650 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
61651 }
61652
61653 return call_user_func_array(array($this->handler, $method), $args);
61654 }
61655 }
61656
61657 namespace Symfony\Component\Debug\Exception;
61658
61659 use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
61660 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
61661
61662
61663
61664
61665
61666
61667
61668
61669 class FlattenException extends LegacyFlattenException
61670 {
61671 private $message;
61672 private $code;
61673 private $previous;
61674 private $trace;
61675 private $class;
61676 private $statusCode;
61677 private $headers;
61678 private $file;
61679 private $line;
61680
61681 public static function create(\Exception $exception, $statusCode = null, array $headers = array())
61682 {
61683 $e = new static();
61684 $e->setMessage($exception->getMessage());
61685 $e->setCode($exception->getCode());
61686
61687 if ($exception instanceof HttpExceptionInterface) {
61688 $statusCode = $exception->getStatusCode();
61689 $headers = array_merge($headers, $exception->getHeaders());
61690 }
61691
61692 if (null === $statusCode) {
61693 $statusCode = 500;
61694 }
61695
61696 $e->setStatusCode($statusCode);
61697 $e->setHeaders($headers);
61698 $e->setTraceFromException($exception);
61699 $e->setClass(get_class($exception));
61700 $e->setFile($exception->getFile());
61701 $e->setLine($exception->getLine());
61702
61703 $previous = $exception->getPrevious();
61704
61705 if ($previous instanceof \Exception) {
61706 $e->setPrevious(static::create($previous));
61707 } elseif ($previous instanceof \Throwable) {
61708 $e->setPrevious(static::create(new FatalThrowableError($previous)));
61709 }
61710
61711 return $e;
61712 }
61713
61714 public function toArray()
61715 {
61716 $exceptions = array();
61717 foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
61718 $exceptions[] = array(
61719 'message' => $exception->getMessage(),
61720 'class' => $exception->getClass(),
61721 'trace' => $exception->getTrace(),
61722 );
61723 }
61724
61725 return $exceptions;
61726 }
61727
61728 public function getStatusCode()
61729 {
61730 return $this->statusCode;
61731 }
61732
61733 public function setStatusCode($code)
61734 {
61735 $this->statusCode = $code;
61736 }
61737
61738 public function getHeaders()
61739 {
61740 return $this->headers;
61741 }
61742
61743 public function setHeaders(array $headers)
61744 {
61745 $this->headers = $headers;
61746 }
61747
61748 public function getClass()
61749 {
61750 return $this->class;
61751 }
61752
61753 public function setClass($class)
61754 {
61755 $this->class = $class;
61756 }
61757
61758 public function getFile()
61759 {
61760 return $this->file;
61761 }
61762
61763 public function setFile($file)
61764 {
61765 $this->file = $file;
61766 }
61767
61768 public function getLine()
61769 {
61770 return $this->line;
61771 }
61772
61773 public function setLine($line)
61774 {
61775 $this->line = $line;
61776 }
61777
61778 public function getMessage()
61779 {
61780 return $this->message;
61781 }
61782
61783 public function setMessage($message)
61784 {
61785 $this->message = $message;
61786 }
61787
61788 public function getCode()
61789 {
61790 return $this->code;
61791 }
61792
61793 public function setCode($code)
61794 {
61795 $this->code = $code;
61796 }
61797
61798 public function getPrevious()
61799 {
61800 return $this->previous;
61801 }
61802
61803 public function setPrevious(FlattenException $previous)
61804 {
61805 $this->previous = $previous;
61806 }
61807
61808 public function getAllPrevious()
61809 {
61810 $exceptions = array();
61811 $e = $this;
61812 while ($e = $e->getPrevious()) {
61813 $exceptions[] = $e;
61814 }
61815
61816 return $exceptions;
61817 }
61818
61819 public function getTrace()
61820 {
61821 return $this->trace;
61822 }
61823
61824 public function setTraceFromException(\Exception $exception)
61825 {
61826 $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
61827 }
61828
61829 public function setTrace($trace, $file, $line)
61830 {
61831 $this->trace = array();
61832 $this->trace[] = array(
61833 'namespace' => '',
61834 'short_class' => '',
61835 'class' => '',
61836 'type' => '',
61837 'function' => '',
61838 'file' => $file,
61839 'line' => $line,
61840 'args' => array(),
61841 );
61842 foreach ($trace as $entry) {
61843 $class = '';
61844 $namespace = '';
61845 if (isset($entry['class'])) {
61846 $parts = explode('\\', $entry['class']);
61847 $class = array_pop($parts);
61848 $namespace = implode('\\', $parts);
61849 }
61850
61851 $this->trace[] = array(
61852 'namespace' => $namespace,
61853 'short_class' => $class,
61854 'class' => isset($entry['class']) ? $entry['class'] : '',
61855 'type' => isset($entry['type']) ? $entry['type'] : '',
61856 'function' => isset($entry['function']) ? $entry['function'] : null,
61857 'file' => isset($entry['file']) ? $entry['file'] : null,
61858 'line' => isset($entry['line']) ? $entry['line'] : null,
61859 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
61860 );
61861 }
61862 }
61863
61864 private function flattenArgs($args, $level = 0, &$count = 0)
61865 {
61866 $result = array();
61867 foreach ($args as $key => $value) {
61868 if (++$count > 1e4) {
61869 return array('array', '*SKIPPED over 10000 entries*');
61870 }
61871 if ($value instanceof \__PHP_Incomplete_Class) {
61872
61873  $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
61874 } elseif (is_object($value)) {
61875 $result[$key] = array('object', get_class($value));
61876 } elseif (is_array($value)) {
61877 if ($level > 10) {
61878 $result[$key] = array('array', '*DEEP NESTED ARRAY*');
61879 } else {
61880 $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
61881 }
61882 } elseif (null === $value) {
61883 $result[$key] = array('null', null);
61884 } elseif (is_bool($value)) {
61885 $result[$key] = array('boolean', $value);
61886 } elseif (is_resource($value)) {
61887 $result[$key] = array('resource', get_resource_type($value));
61888 } else {
61889 $result[$key] = array('string', (string) $value);
61890 }
61891 }
61892
61893 return $result;
61894 }
61895
61896 private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
61897 {
61898 $array = new \ArrayObject($value);
61899
61900 return $array['__PHP_Incomplete_Class_Name'];
61901 }
61902 }
61903 <?php
61904
61905
61906
61907
61908
61909
61910
61911
61912
61913
61914 namespace Symfony\Component\Debug\Exception;
61915
61916
61917
61918
61919
61920
61921 class OutOfMemoryException extends FatalErrorException
61922 {
61923 }
61924 <?php
61925
61926
61927
61928
61929
61930
61931
61932
61933
61934
61935 namespace Symfony\Component\Debug\Exception;
61936
61937
61938
61939
61940
61941
61942 class UndefinedFunctionException extends FatalErrorException
61943 {
61944 public function __construct($message, \ErrorException $previous)
61945 {
61946 parent::__construct(
61947 $message,
61948 $previous->getCode(),
61949 $previous->getSeverity(),
61950 $previous->getFile(),
61951 $previous->getLine(),
61952 $previous->getPrevious()
61953 );
61954 $this->setTrace($previous->getTrace());
61955 }
61956 }
61957 <?php
61958
61959
61960
61961
61962
61963
61964
61965
61966
61967
61968 namespace Symfony\Component\Debug\Exception;
61969
61970
61971
61972
61973
61974
61975 class UndefinedMethodException extends FatalErrorException
61976 {
61977 public function __construct($message, \ErrorException $previous)
61978 {
61979 parent::__construct(
61980 $message,
61981 $previous->getCode(),
61982 $previous->getSeverity(),
61983 $previous->getFile(),
61984 $previous->getLine(),
61985 $previous->getPrevious()
61986 );
61987 $this->setTrace($previous->getTrace());
61988 }
61989 }
61990 <?php
61991
61992
61993
61994
61995
61996
61997
61998
61999
62000
62001 namespace Symfony\Component\Debug;
62002
62003 use Symfony\Component\HttpFoundation\Response;
62004 use Symfony\Component\Debug\Exception\FlattenException;
62005 use Symfony\Component\Debug\Exception\OutOfMemoryException;
62006
62007
62008
62009
62010
62011
62012
62013
62014
62015
62016
62017
62018
62019 class ExceptionHandler
62020 {
62021 private $debug;
62022 private $charset;
62023 private $handler;
62024 private $caughtBuffer;
62025 private $caughtLength;
62026 private $fileLinkFormat;
62027
62028 public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
62029 {
62030 if (false !== strpos($charset, '%')) {
62031 @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);
62032
62033
62034  $pivot = $fileLinkFormat;
62035 $fileLinkFormat = $charset;
62036 $charset = $pivot;
62037 }
62038 $this->debug = $debug;
62039 $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
62040 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
62041 }
62042
62043
62044
62045
62046
62047
62048
62049
62050
62051
62052 public static function register($debug = true, $charset = null, $fileLinkFormat = null)
62053 {
62054 $handler = new static($debug, $charset, $fileLinkFormat);
62055
62056 $prev = set_exception_handler(array($handler, 'handle'));
62057 if (is_array($prev) && $prev[0] instanceof ErrorHandler) {
62058 restore_exception_handler();
62059 $prev[0]->setExceptionHandler(array($handler, 'handle'));
62060 }
62061
62062 return $handler;
62063 }
62064
62065
62066
62067
62068
62069
62070
62071
62072 public function setHandler($handler)
62073 {
62074 if (null !== $handler && !is_callable($handler)) {
62075 throw new \LogicException('The exception handler must be a valid PHP callable.');
62076 }
62077 $old = $this->handler;
62078 $this->handler = $handler;
62079
62080 return $old;
62081 }
62082
62083
62084
62085
62086
62087
62088
62089
62090 public function setFileLinkFormat($format)
62091 {
62092 $old = $this->fileLinkFormat;
62093 $this->fileLinkFormat = $format;
62094
62095 return $old;
62096 }
62097
62098
62099
62100
62101
62102
62103
62104
62105
62106 public function handle(\Exception $exception)
62107 {
62108 if (null === $this->handler || $exception instanceof OutOfMemoryException) {
62109 $this->failSafeHandle($exception);
62110
62111 return;
62112 }
62113
62114 $caughtLength = $this->caughtLength = 0;
62115
62116 ob_start(array($this, 'catchOutput'));
62117 $this->failSafeHandle($exception);
62118 while (null === $this->caughtBuffer && ob_end_flush()) {
62119
62120  }
62121 if (isset($this->caughtBuffer[0])) {
62122 ob_start(array($this, 'cleanOutput'));
62123 echo $this->caughtBuffer;
62124 $caughtLength = ob_get_length();
62125 }
62126 $this->caughtBuffer = null;
62127
62128 try {
62129 call_user_func($this->handler, $exception);
62130 $this->caughtLength = $caughtLength;
62131 } catch (\Exception $e) {
62132 if (!$caughtLength) {
62133
62134  throw $exception;
62135 }
62136 }
62137 }
62138
62139
62140
62141
62142
62143
62144
62145
62146
62147
62148 private function failSafeHandle(\Exception $exception)
62149 {
62150 if (class_exists('Symfony\Component\HttpFoundation\Response', false)
62151 && __CLASS__ !== get_class($this)
62152 && ($reflector = new \ReflectionMethod($this, 'createResponse'))
62153 && __CLASS__ !== $reflector->class
62154 ) {
62155 $response = $this->createResponse($exception);
62156 $response->sendHeaders();
62157 $response->sendContent();
62158 @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);
62159
62160 return;
62161 }
62162
62163 $this->sendPhpResponse($exception);
62164 }
62165
62166
62167
62168
62169
62170
62171
62172
62173
62174 public function sendPhpResponse($exception)
62175 {
62176 if (!$exception instanceof FlattenException) {
62177 $exception = FlattenException::create($exception);
62178 }
62179
62180 if (!headers_sent()) {
62181 header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
62182 foreach ($exception->getHeaders() as $name => $value) {
62183 header($name.': '.$value, false);
62184 }
62185 header('Content-Type: text/html; charset='.$this->charset);
62186 }
62187
62188 echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
62189 }
62190
62191
62192
62193
62194
62195
62196
62197
62198
62199
62200 public function createResponse($exception)
62201 {
62202 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
62203
62204 if (!$exception instanceof FlattenException) {
62205 $exception = FlattenException::create($exception);
62206 }
62207
62208 return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
62209 }
62210
62211
62212
62213
62214
62215
62216
62217
62218 public function getHtml($exception)
62219 {
62220 if (!$exception instanceof FlattenException) {
62221 $exception = FlattenException::create($exception);
62222 }
62223
62224 return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
62225 }
62226
62227
62228
62229
62230
62231
62232
62233
62234 public function getContent(FlattenException $exception)
62235 {
62236 switch ($exception->getStatusCode()) {
62237 case 404:
62238 $title = 'Sorry, the page you are looking for could not be found.';
62239 break;
62240 default:
62241 $title = 'Whoops, looks like something went wrong.';
62242 }
62243
62244 $content = '';
62245 if ($this->debug) {
62246 try {
62247 $count = count($exception->getAllPrevious());
62248 $total = $count + 1;
62249 foreach ($exception->toArray() as $position => $e) {
62250 $ind = $count - $position + 1;
62251 $class = $this->formatClass($e['class']);
62252 $message = nl2br($this->escapeHtml($e['message']));
62253 $content .= sprintf(<<<'EOF'
62254                         <h2 class="block_exception clear_fix">
62255                             <span class="exception_counter">%d/%d</span>
62256                             <span class="exception_title">%s%s:</span>
62257                             <span class="exception_message">%s</span>
62258                         </h2>
62259                         <div class="block">
62260                             <ol class="traces list_exception">
62261
62262 EOF
62263 , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
62264 foreach ($e['trace'] as $trace) {
62265 $content .= '       <li>';
62266 if ($trace['function']) {
62267 $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
62268 }
62269 if (isset($trace['file']) && isset($trace['line'])) {
62270 $content .= $this->formatPath($trace['file'], $trace['line']);
62271 }
62272 $content .= "</li>\n";
62273 }
62274
62275 $content .= "    </ol>\n</div>\n";
62276 }
62277 } catch (\Exception $e) {
62278
62279  if ($this->debug) {
62280 $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $this->escapeHtml($e->getMessage()));
62281 } else {
62282 $title = 'Whoops, looks like something went wrong.';
62283 }
62284 }
62285 }
62286
62287 return <<<EOF
62288             <div id="sf-resetcontent" class="sf-reset">
62289                 <h1>$title</h1>
62290                 $content
62291             </div>
62292 EOF;
62293 }
62294
62295
62296
62297
62298
62299
62300
62301
62302 public function getStylesheet(FlattenException $exception)
62303 {
62304 return <<<'EOF'
62305             .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
62306             .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
62307             .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
62308             .sf-reset .clear_fix { display:inline-block; }
62309             .sf-reset * html .clear_fix { height:1%; }
62310             .sf-reset .clear_fix { display:block; }
62311             .sf-reset, .sf-reset .block { margin: auto }
62312             .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
62313             .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
62314             .sf-reset strong { font-weight:bold; }
62315             .sf-reset a { color:#6c6159; cursor: default; }
62316             .sf-reset a img { border:none; }
62317             .sf-reset a:hover { text-decoration:underline; }
62318             .sf-reset em { font-style:italic; }
62319             .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
62320             .sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
62321             .sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
62322             .sf-reset .exception_message { margin-left: 3em; display: block; }
62323             .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
62324             .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
62325                 -webkit-border-bottom-right-radius: 16px;
62326                 -webkit-border-bottom-left-radius: 16px;
62327                 -moz-border-radius-bottomright: 16px;
62328                 -moz-border-radius-bottomleft: 16px;
62329                 border-bottom-right-radius: 16px;
62330                 border-bottom-left-radius: 16px;
62331                 border-bottom:1px solid #ccc;
62332                 border-right:1px solid #ccc;
62333                 border-left:1px solid #ccc;
62334                 word-wrap: break-word;
62335             }
62336             .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
62337                 -webkit-border-top-left-radius: 16px;
62338                 -webkit-border-top-right-radius: 16px;
62339                 -moz-border-radius-topleft: 16px;
62340                 -moz-border-radius-topright: 16px;
62341                 border-top-left-radius: 16px;
62342                 border-top-right-radius: 16px;
62343                 border-top:1px solid #ccc;
62344                 border-right:1px solid #ccc;
62345                 border-left:1px solid #ccc;
62346                 overflow: hidden;
62347                 word-wrap: break-word;
62348             }
62349             .sf-reset a { background:none; color:#868686; text-decoration:none; }
62350             .sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
62351             .sf-reset ol { padding: 10px 0; }
62352             .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
62353                 -webkit-border-radius: 10px;
62354                 -moz-border-radius: 10px;
62355                 border-radius: 10px;
62356                 border: 1px solid #ccc;
62357             }
62358 EOF;
62359 }
62360
62361 private function decorate($content, $css)
62362 {
62363 return <<<EOF
62364 <!DOCTYPE html>
62365 <html>
62366     <head>
62367         <meta charset="{$this->charset}" />
62368         <meta name="robots" content="noindex,nofollow" />
62369         <style>
62370             /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
62371             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;}
62372
62373             html { background: #eee; padding: 10px }
62374             img { border: 0; }
62375             #sf-resetcontent { width:970px; margin:0 auto; }
62376             $css
62377         </style>
62378     </head>
62379     <body>
62380         $content
62381     </body>
62382 </html>
62383 EOF;
62384 }
62385
62386 private function formatClass($class)
62387 {
62388 $parts = explode('\\', $class);
62389
62390 return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
62391 }
62392
62393 private function formatPath($path, $line)
62394 {
62395 $path = $this->escapeHtml($path);
62396 $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
62397
62398 if ($linkFormat = $this->fileLinkFormat) {
62399 $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
62400
62401 return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
62402 }
62403
62404 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);
62405 }
62406
62407
62408
62409
62410
62411
62412
62413
62414 private function formatArgs(array $args)
62415 {
62416 $result = array();
62417 foreach ($args as $key => $item) {
62418 if ('object' === $item[0]) {
62419 $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
62420 } elseif ('array' === $item[0]) {
62421 $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
62422 } elseif ('string' === $item[0]) {
62423 $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1]));
62424 } elseif ('null' === $item[0]) {
62425 $formattedValue = '<em>null</em>';
62426 } elseif ('boolean' === $item[0]) {
62427 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
62428 } elseif ('resource' === $item[0]) {
62429 $formattedValue = '<em>resource</em>';
62430 } else {
62431 $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true));
62432 }
62433
62434 $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
62435 }
62436
62437 return implode(', ', $result);
62438 }
62439
62440
62441
62442
62443
62444
62445 protected static function utf8Htmlize($str)
62446 {
62447 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
62448
62449 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
62450 }
62451
62452
62453
62454
62455 private function escapeHtml($str)
62456 {
62457 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset);
62458 }
62459
62460
62461
62462
62463 public function catchOutput($buffer)
62464 {
62465 $this->caughtBuffer = $buffer;
62466
62467 return '';
62468 }
62469
62470
62471
62472
62473 public function cleanOutput($buffer)
62474 {
62475 if ($this->caughtLength) {
62476
62477  $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
62478 if (isset($cleanBuffer[0])) {
62479 $buffer = $cleanBuffer;
62480 }
62481 }
62482
62483 return $buffer;
62484 }
62485 }
62486 <?php
62487
62488
62489
62490
62491
62492
62493
62494
62495
62496
62497 namespace Symfony\Component\Debug\FatalErrorHandler;
62498
62499 use Symfony\Component\Debug\Exception\ClassNotFoundException;
62500 use Symfony\Component\Debug\Exception\FatalErrorException;
62501 use Symfony\Component\Debug\DebugClassLoader;
62502 use Composer\Autoload\ClassLoader as ComposerClassLoader;
62503 use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
62504 use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
62505
62506
62507
62508
62509
62510
62511 class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
62512 {
62513
62514
62515
62516 public function handleError(array $error, FatalErrorException $exception)
62517 {
62518 $messageLen = strlen($error['message']);
62519 $notFoundSuffix = '\' not found';
62520 $notFoundSuffixLen = strlen($notFoundSuffix);
62521 if ($notFoundSuffixLen > $messageLen) {
62522 return;
62523 }
62524
62525 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
62526 return;
62527 }
62528
62529 foreach (array('class', 'interface', 'trait') as $typeName) {
62530 $prefix = ucfirst($typeName).' \'';
62531 $prefixLen = strlen($prefix);
62532 if (0 !== strpos($error['message'], $prefix)) {
62533 continue;
62534 }
62535
62536 $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
62537 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
62538 $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
62539 $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
62540 $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
62541 $tail = ' for another namespace?';
62542 } else {
62543 $className = $fullyQualifiedClassName;
62544 $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
62545 $tail = '?';
62546 }
62547
62548 if ($candidates = $this->getClassCandidates($className)) {
62549 $tail = array_pop($candidates).'"?';
62550 if ($candidates) {
62551 $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
62552 } else {
62553 $tail = ' for "'.$tail;
62554 }
62555 }
62556 $message .= "\nDid you forget a \"use\" statement".$tail;
62557
62558 return new ClassNotFoundException($message, $exception);
62559 }
62560 }
62561
62562
62563
62564
62565
62566
62567
62568
62569
62570
62571
62572 private function getClassCandidates($class)
62573 {
62574 if (!is_array($functions = spl_autoload_functions())) {
62575 return array();
62576 }
62577
62578
62579  $classes = array();
62580
62581 foreach ($functions as $function) {
62582 if (!is_array($function)) {
62583 continue;
62584 }
62585
62586  if ($function[0] instanceof DebugClassLoader) {
62587 $function = $function[0]->getClassLoader();
62588
62589
62590  if (is_object($function)) {
62591 $function = array($function);
62592 }
62593
62594 if (!is_array($function)) {
62595 continue;
62596 }
62597 }
62598
62599 if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader || $function[0] instanceof SymfonyUniversalClassLoader) {
62600 foreach ($function[0]->getPrefixes() as $prefix => $paths) {
62601 foreach ($paths as $path) {
62602 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
62603 }
62604 }
62605 }
62606 if ($function[0] instanceof ComposerClassLoader) {
62607 foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
62608 foreach ($paths as $path) {
62609 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
62610 }
62611 }
62612 }
62613 }
62614
62615 return array_unique($classes);
62616 }
62617
62618
62619
62620
62621
62622
62623
62624
62625 private function findClassInPath($path, $class, $prefix)
62626 {
62627 if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
62628 return array();
62629 }
62630
62631 $classes = array();
62632 $filename = $class.'.php';
62633 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
62634 if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
62635 $classes[] = $class;
62636 }
62637 }
62638
62639 return $classes;
62640 }
62641
62642
62643
62644
62645
62646
62647
62648
62649 private function convertFileToClass($path, $file, $prefix)
62650 {
62651 $candidates = array(
62652
62653  $namespacedClass = str_replace(array($path.DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
62654
62655  $prefix.$namespacedClass,
62656
62657  $prefix.'\\'.$namespacedClass,
62658
62659  str_replace('\\', '_', $namespacedClass),
62660
62661  str_replace('\\', '_', $prefix.$namespacedClass),
62662
62663  str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
62664 );
62665
62666 if ($prefix) {
62667 $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
62668 }
62669
62670
62671  
62672  
62673  foreach ($candidates as $candidate) {
62674 if ($this->classExists($candidate)) {
62675 return $candidate;
62676 }
62677 }
62678
62679 require_once $file;
62680
62681 foreach ($candidates as $candidate) {
62682 if ($this->classExists($candidate)) {
62683 return $candidate;
62684 }
62685 }
62686 }
62687
62688
62689
62690
62691
62692
62693 private function classExists($class)
62694 {
62695 return class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
62696 }
62697 }
62698 <?php
62699
62700
62701
62702
62703
62704
62705
62706
62707
62708
62709 namespace Symfony\Component\Debug\FatalErrorHandler;
62710
62711 use Symfony\Component\Debug\Exception\FatalErrorException;
62712
62713
62714
62715
62716
62717
62718 interface FatalErrorHandlerInterface
62719 {
62720
62721
62722
62723
62724
62725
62726
62727
62728 public function handleError(array $error, FatalErrorException $exception);
62729 }
62730 <?php
62731
62732
62733
62734
62735
62736
62737
62738
62739
62740
62741 namespace Symfony\Component\Debug\FatalErrorHandler;
62742
62743 use Symfony\Component\Debug\Exception\UndefinedFunctionException;
62744 use Symfony\Component\Debug\Exception\FatalErrorException;
62745
62746
62747
62748
62749
62750
62751 class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
62752 {
62753
62754
62755
62756 public function handleError(array $error, FatalErrorException $exception)
62757 {
62758 $messageLen = strlen($error['message']);
62759 $notFoundSuffix = '()';
62760 $notFoundSuffixLen = strlen($notFoundSuffix);
62761 if ($notFoundSuffixLen > $messageLen) {
62762 return;
62763 }
62764
62765 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
62766 return;
62767 }
62768
62769 $prefix = 'Call to undefined function ';
62770 $prefixLen = strlen($prefix);
62771 if (0 !== strpos($error['message'], $prefix)) {
62772 return;
62773 }
62774
62775 $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
62776 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
62777 $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
62778 $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
62779 $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
62780 } else {
62781 $functionName = $fullyQualifiedFunctionName;
62782 $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
62783 }
62784
62785 $candidates = array();
62786 foreach (get_defined_functions() as $type => $definedFunctionNames) {
62787 foreach ($definedFunctionNames as $definedFunctionName) {
62788 if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
62789 $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
62790 } else {
62791 $definedFunctionNameBasename = $definedFunctionName;
62792 }
62793
62794 if ($definedFunctionNameBasename === $functionName) {
62795 $candidates[] = '\\'.$definedFunctionName;
62796 }
62797 }
62798 }
62799
62800 if ($candidates) {
62801 sort($candidates);
62802 $last = array_pop($candidates).'"?';
62803 if ($candidates) {
62804 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
62805 } else {
62806 $candidates = '"'.$last;
62807 }
62808 $message .= "\nDid you mean to call ".$candidates;
62809 }
62810
62811 return new UndefinedFunctionException($message, $exception);
62812 }
62813 }
62814 <?php
62815
62816
62817
62818
62819
62820
62821
62822
62823
62824
62825 namespace Symfony\Component\Debug\FatalErrorHandler;
62826
62827 use Symfony\Component\Debug\Exception\FatalErrorException;
62828 use Symfony\Component\Debug\Exception\UndefinedMethodException;
62829
62830
62831
62832
62833
62834
62835 class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
62836 {
62837
62838
62839
62840 public function handleError(array $error, FatalErrorException $exception)
62841 {
62842 preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
62843 if (!$matches) {
62844 return;
62845 }
62846
62847 $className = $matches[1];
62848 $methodName = $matches[2];
62849
62850 $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
62851
62852 if (!class_exists($className) || null === $methods = get_class_methods($className)) {
62853
62854  return new UndefinedMethodException($message, $exception);
62855 }
62856
62857 $candidates = array();
62858 foreach ($methods as $definedMethodName) {
62859 $lev = levenshtein($methodName, $definedMethodName);
62860 if ($lev <= strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
62861 $candidates[] = $definedMethodName;
62862 }
62863 }
62864
62865 if ($candidates) {
62866 sort($candidates);
62867 $last = array_pop($candidates).'"?';
62868 if ($candidates) {
62869 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
62870 } else {
62871 $candidates = '"'.$last;
62872 }
62873
62874 $message .= "\nDid you mean to call ".$candidates;
62875 }
62876
62877 return new UndefinedMethodException($message, $exception);
62878 }
62879 }
62880 Copyright (c) 2004-2017 Fabien Potencier
62881
62882 Permission is hereby granted, free of charge, to any person obtaining a copy
62883 of this software and associated documentation files (the "Software"), to deal
62884 in the Software without restriction, including without limitation the rights
62885 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
62886 copies of the Software, and to permit persons to whom the Software is furnished
62887 to do so, subject to the following conditions:
62888
62889 The above copyright notice and this permission notice shall be included in all
62890 copies or substantial portions of the Software.
62891
62892 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62893 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62894 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62895 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62896 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
62897 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
62898 THE SOFTWARE.
62899 <?php
62900
62901
62902
62903
62904
62905
62906
62907
62908
62909
62910 namespace Symfony\Component\Filesystem\Exception;
62911
62912
62913
62914
62915
62916
62917 interface ExceptionInterface
62918 {
62919 }
62920 <?php
62921
62922
62923
62924
62925
62926
62927
62928
62929
62930
62931 namespace Symfony\Component\Filesystem\Exception;
62932
62933
62934
62935
62936
62937
62938
62939 class FileNotFoundException extends IOException
62940 {
62941 public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
62942 {
62943 if (null === $message) {
62944 if (null === $path) {
62945 $message = 'File could not be found.';
62946 } else {
62947 $message = sprintf('File "%s" could not be found.', $path);
62948 }
62949 }
62950
62951 parent::__construct($message, $code, $previous, $path);
62952 }
62953 }
62954 <?php
62955
62956
62957
62958
62959
62960
62961
62962
62963
62964
62965 namespace Symfony\Component\Filesystem\Exception;
62966
62967
62968
62969
62970
62971
62972
62973
62974 class IOException extends \RuntimeException implements IOExceptionInterface
62975 {
62976 private $path;
62977
62978 public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
62979 {
62980 $this->path = $path;
62981
62982 parent::__construct($message, $code, $previous);
62983 }
62984
62985
62986
62987
62988 public function getPath()
62989 {
62990 return $this->path;
62991 }
62992 }
62993 <?php
62994
62995
62996
62997
62998
62999
63000
63001
63002
63003
63004 namespace Symfony\Component\Filesystem\Exception;
63005
63006
63007
63008
63009
63010
63011 interface IOExceptionInterface extends ExceptionInterface
63012 {
63013
63014
63015
63016
63017
63018 public function getPath();
63019 }
63020 <?php
63021
63022
63023
63024
63025
63026
63027
63028
63029
63030
63031 namespace Symfony\Component\Filesystem;
63032
63033 use Symfony\Component\Filesystem\Exception\IOException;
63034 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
63035
63036
63037
63038
63039
63040
63041 class Filesystem
63042 {
63043
63044
63045
63046
63047
63048
63049
63050
63051
63052
63053
63054
63055
63056
63057 public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
63058 {
63059 $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
63060 if ($originIsLocal && !is_file($originFile)) {
63061 throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
63062 }
63063
63064 $this->mkdir(dirname($targetFile));
63065
63066 $doCopy = true;
63067 if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
63068 $doCopy = filemtime($originFile) > filemtime($targetFile);
63069 }
63070
63071 if ($doCopy) {
63072
63073  if (false === $source = @fopen($originFile, 'r')) {
63074 throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
63075 }
63076
63077
63078  if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
63079 throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
63080 }
63081
63082 $bytesCopied = stream_copy_to_stream($source, $target);
63083 fclose($source);
63084 fclose($target);
63085 unset($source, $target);
63086
63087 if (!is_file($targetFile)) {
63088 throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
63089 }
63090
63091 if ($originIsLocal) {
63092
63093  @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
63094
63095 if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
63096 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);
63097 }
63098 }
63099 }
63100 }
63101
63102
63103
63104
63105
63106
63107
63108
63109
63110 public function mkdir($dirs, $mode = 0777)
63111 {
63112 foreach ($this->toIterator($dirs) as $dir) {
63113 if (is_dir($dir)) {
63114 continue;
63115 }
63116
63117 if (true !== @mkdir($dir, $mode, true)) {
63118 $error = error_get_last();
63119 if (!is_dir($dir)) {
63120
63121  if ($error) {
63122 throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']), 0, null, $dir);
63123 }
63124 throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
63125 }
63126 }
63127 }
63128 }
63129
63130
63131
63132
63133
63134
63135
63136
63137 public function exists($files)
63138 {
63139 foreach ($this->toIterator($files) as $file) {
63140 if ('\\' === DIRECTORY_SEPARATOR && strlen($file) > 258) {
63141 throw new IOException('Could not check if file exist because path length exceeds 258 characters.', 0, null, $file);
63142 }
63143
63144 if (!file_exists($file)) {
63145 return false;
63146 }
63147 }
63148
63149 return true;
63150 }
63151
63152
63153
63154
63155
63156
63157
63158
63159
63160
63161 public function touch($files, $time = null, $atime = null)
63162 {
63163 foreach ($this->toIterator($files) as $file) {
63164 $touch = $time ? @touch($file, $time, $atime) : @touch($file);
63165 if (true !== $touch) {
63166 throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
63167 }
63168 }
63169 }
63170
63171
63172
63173
63174
63175
63176
63177
63178 public function remove($files)
63179 {
63180 if ($files instanceof \Traversable) {
63181 $files = iterator_to_array($files, false);
63182 } elseif (!is_array($files)) {
63183 $files = array($files);
63184 }
63185 $files = array_reverse($files);
63186 foreach ($files as $file) {
63187 if (is_link($file)) {
63188
63189  if (!@(unlink($file) || '\\' !== DIRECTORY_SEPARATOR || rmdir($file)) && file_exists($file)) {
63190 $error = error_get_last();
63191 throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, $error['message']));
63192 }
63193 } elseif (is_dir($file)) {
63194 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
63195
63196 if (!@rmdir($file) && file_exists($file)) {
63197 $error = error_get_last();
63198 throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, $error['message']));
63199 }
63200 } elseif (!@unlink($file) && file_exists($file)) {
63201 $error = error_get_last();
63202 throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, $error['message']));
63203 }
63204 }
63205 }
63206
63207
63208
63209
63210
63211
63212
63213
63214
63215
63216
63217 public function chmod($files, $mode, $umask = 0000, $recursive = false)
63218 {
63219 foreach ($this->toIterator($files) as $file) {
63220 if (true !== @chmod($file, $mode & ~$umask)) {
63221 throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
63222 }
63223 if ($recursive && is_dir($file) && !is_link($file)) {
63224 $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
63225 }
63226 }
63227 }
63228
63229
63230
63231
63232
63233
63234
63235
63236
63237
63238 public function chown($files, $user, $recursive = false)
63239 {
63240 foreach ($this->toIterator($files) as $file) {
63241 if ($recursive && is_dir($file) && !is_link($file)) {
63242 $this->chown(new \FilesystemIterator($file), $user, true);
63243 }
63244 if (is_link($file) && function_exists('lchown')) {
63245 if (true !== @lchown($file, $user)) {
63246 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
63247 }
63248 } else {
63249 if (true !== @chown($file, $user)) {
63250 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
63251 }
63252 }
63253 }
63254 }
63255
63256
63257
63258
63259
63260
63261
63262
63263
63264
63265 public function chgrp($files, $group, $recursive = false)
63266 {
63267 foreach ($this->toIterator($files) as $file) {
63268 if ($recursive && is_dir($file) && !is_link($file)) {
63269 $this->chgrp(new \FilesystemIterator($file), $group, true);
63270 }
63271 if (is_link($file) && function_exists('lchgrp')) {
63272 if (true !== @lchgrp($file, $group) || (defined('HHVM_VERSION') && !posix_getgrnam($group))) {
63273 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
63274 }
63275 } else {
63276 if (true !== @chgrp($file, $group)) {
63277 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
63278 }
63279 }
63280 }
63281 }
63282
63283
63284
63285
63286
63287
63288
63289
63290
63291
63292
63293 public function rename($origin, $target, $overwrite = false)
63294 {
63295
63296  if (!$overwrite && $this->isReadable($target)) {
63297 throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
63298 }
63299
63300 if (true !== @rename($origin, $target)) {
63301 if (is_dir($origin)) {
63302
63303  $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
63304 $this->remove($origin);
63305
63306 return;
63307 }
63308 throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
63309 }
63310 }
63311
63312
63313
63314
63315
63316
63317
63318
63319
63320
63321 private function isReadable($filename)
63322 {
63323 if ('\\' === DIRECTORY_SEPARATOR && strlen($filename) > 258) {
63324 throw new IOException('Could not check if file is readable because path length exceeds 258 characters.', 0, null, $filename);
63325 }
63326
63327 return is_readable($filename);
63328 }
63329
63330
63331
63332
63333
63334
63335
63336
63337
63338
63339 public function symlink($originDir, $targetDir, $copyOnWindows = false)
63340 {
63341 if ('\\' === DIRECTORY_SEPARATOR) {
63342 $originDir = strtr($originDir, '/', '\\');
63343 $targetDir = strtr($targetDir, '/', '\\');
63344
63345 if ($copyOnWindows) {
63346 $this->mirror($originDir, $targetDir);
63347
63348 return;
63349 }
63350 }
63351
63352 $this->mkdir(dirname($targetDir));
63353
63354 $ok = false;
63355 if (is_link($targetDir)) {
63356 if (readlink($targetDir) != $originDir) {
63357 $this->remove($targetDir);
63358 } else {
63359 $ok = true;
63360 }
63361 }
63362
63363 if (!$ok && true !== @symlink($originDir, $targetDir)) {
63364 $report = error_get_last();
63365 if (is_array($report)) {
63366 if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
63367 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);
63368 }
63369 }
63370 throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
63371 }
63372 }
63373
63374
63375
63376
63377
63378
63379
63380
63381
63382 public function makePathRelative($endPath, $startPath)
63383 {
63384
63385  if ('\\' === DIRECTORY_SEPARATOR) {
63386 $endPath = str_replace('\\', '/', $endPath);
63387 $startPath = str_replace('\\', '/', $startPath);
63388 }
63389
63390
63391  $startPathArr = explode('/', trim($startPath, '/'));
63392 $endPathArr = explode('/', trim($endPath, '/'));
63393
63394 if ('/' !== $startPath[0]) {
63395 array_shift($startPathArr);
63396 }
63397
63398 if ('/' !== $endPath[0]) {
63399 array_shift($endPathArr);
63400 }
63401
63402 $normalizePathArray = function ($pathSegments) {
63403 $result = array();
63404
63405 foreach ($pathSegments as $segment) {
63406 if ('..' === $segment) {
63407 array_pop($result);
63408 } else {
63409 $result[] = $segment;
63410 }
63411 }
63412
63413 return $result;
63414 };
63415
63416 $startPathArr = $normalizePathArray($startPathArr);
63417 $endPathArr = $normalizePathArray($endPathArr);
63418
63419
63420  $index = 0;
63421 while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
63422 ++$index;
63423 }
63424
63425
63426  if (count($startPathArr) === 1 && $startPathArr[0] === '') {
63427 $depth = 0;
63428 } else {
63429 $depth = count($startPathArr) - $index;
63430 }
63431
63432
63433  if ('/' === $startPath[0] && 0 === $index && 0 === $depth) {
63434 $traverser = '';
63435 } else {
63436
63437  $traverser = str_repeat('../', $depth);
63438 }
63439
63440 $endPathRemainder = implode('/', array_slice($endPathArr, $index));
63441
63442
63443  $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
63444
63445 return '' === $relativePath ? './' : $relativePath;
63446 }
63447
63448
63449
63450
63451
63452
63453
63454
63455
63456
63457
63458
63459
63460
63461
63462 public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
63463 {
63464 $targetDir = rtrim($targetDir, '/\\');
63465 $originDir = rtrim($originDir, '/\\');
63466
63467
63468  if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
63469 $deleteIterator = $iterator;
63470 if (null === $deleteIterator) {
63471 $flags = \FilesystemIterator::SKIP_DOTS;
63472 $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
63473 }
63474 foreach ($deleteIterator as $file) {
63475 $origin = str_replace($targetDir, $originDir, $file->getPathname());
63476 if (!$this->exists($origin)) {
63477 $this->remove($file);
63478 }
63479 }
63480 }
63481
63482 $copyOnWindows = false;
63483 if (isset($options['copy_on_windows'])) {
63484 $copyOnWindows = $options['copy_on_windows'];
63485 }
63486
63487 if (null === $iterator) {
63488 $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
63489 $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
63490 }
63491
63492 if ($this->exists($originDir)) {
63493 $this->mkdir($targetDir);
63494 }
63495
63496 foreach ($iterator as $file) {
63497 $target = str_replace($originDir, $targetDir, $file->getPathname());
63498
63499 if ($copyOnWindows) {
63500 if (is_file($file)) {
63501 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
63502 } elseif (is_dir($file)) {
63503 $this->mkdir($target);
63504 } else {
63505 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
63506 }
63507 } else {
63508 if (is_link($file)) {
63509 $this->symlink($file->getLinkTarget(), $target);
63510 } elseif (is_dir($file)) {
63511 $this->mkdir($target);
63512 } elseif (is_file($file)) {
63513 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
63514 } else {
63515 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
63516 }
63517 }
63518 }
63519 }
63520
63521
63522
63523
63524
63525
63526
63527
63528 public function isAbsolutePath($file)
63529 {
63530 return strspn($file, '/\\', 0, 1)
63531 || (strlen($file) > 3 && ctype_alpha($file[0])
63532 && substr($file, 1, 1) === ':'
63533 && strspn($file, '/\\', 2, 1)
63534 )
63535 || null !== parse_url($file, PHP_URL_SCHEME)
63536 ;
63537 }
63538
63539
63540
63541
63542
63543
63544
63545
63546
63547
63548 public function tempnam($dir, $prefix)
63549 {
63550 list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
63551
63552
63553  if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) {
63554 $tmpFile = @tempnam($hierarchy, $prefix);
63555
63556
63557  if (false !== $tmpFile) {
63558 if (null !== $scheme && 'gs' !== $scheme) {
63559 return $scheme.'://'.$tmpFile;
63560 }
63561
63562 return $tmpFile;
63563 }
63564
63565 throw new IOException('A temporary file could not be created.');
63566 }
63567
63568
63569  for ($i = 0; $i < 10; ++$i) {
63570
63571  $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true);
63572
63573
63574  
63575  $handle = @fopen($tmpFile, 'x+');
63576
63577
63578  if (false === $handle) {
63579 continue;
63580 }
63581
63582
63583  @fclose($handle);
63584
63585 return $tmpFile;
63586 }
63587
63588 throw new IOException('A temporary file could not be created.');
63589 }
63590
63591
63592
63593
63594
63595
63596
63597
63598
63599
63600
63601 public function dumpFile($filename, $content, $mode = 0666)
63602 {
63603 $dir = dirname($filename);
63604
63605 if (!is_dir($dir)) {
63606 $this->mkdir($dir);
63607 }
63608
63609 if (!is_writable($dir)) {
63610 throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
63611 }
63612
63613 $tmpFile = $this->tempnam($dir, basename($filename));
63614
63615 if (false === @file_put_contents($tmpFile, $content)) {
63616 throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
63617 }
63618
63619 if (null !== $mode) {
63620 if (func_num_args() > 2) {
63621 @trigger_error('Support for modifying file permissions is deprecated since version 2.3.12 and will be removed in 3.0.', E_USER_DEPRECATED);
63622 }
63623
63624 $this->chmod($tmpFile, $mode);
63625 } elseif (file_exists($filename)) {
63626 @chmod($tmpFile, fileperms($filename));
63627 }
63628
63629 $this->rename($tmpFile, $filename, true);
63630 }
63631
63632
63633
63634
63635
63636
63637 private function toIterator($files)
63638 {
63639 if (!$files instanceof \Traversable) {
63640 $files = new \ArrayObject(is_array($files) ? $files : array($files));
63641 }
63642
63643 return $files;
63644 }
63645
63646
63647
63648
63649
63650
63651
63652
63653 private function getSchemeAndHierarchy($filename)
63654 {
63655 $components = explode('://', $filename, 2);
63656
63657 return 2 === count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
63658 }
63659 }
63660 Copyright (c) 2004-2017 Fabien Potencier
63661
63662 Permission is hereby granted, free of charge, to any person obtaining a copy
63663 of this software and associated documentation files (the "Software"), to deal
63664 in the Software without restriction, including without limitation the rights
63665 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
63666 copies of the Software, and to permit persons to whom the Software is furnished
63667 to do so, subject to the following conditions:
63668
63669 The above copyright notice and this permission notice shall be included in all
63670 copies or substantial portions of the Software.
63671
63672 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63673 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63674 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63675 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63676 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63677 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
63678 THE SOFTWARE.
63679 <?php
63680
63681
63682
63683
63684
63685
63686
63687
63688
63689
63690 namespace Symfony\Component\Filesystem;
63691
63692 use Symfony\Component\Filesystem\Exception\IOException;
63693
63694
63695
63696
63697
63698
63699
63700
63701
63702
63703
63704
63705
63706
63707 class LockHandler
63708 {
63709 private $file;
63710 private $handle;
63711
63712
63713
63714
63715
63716
63717
63718 public function __construct($name, $lockPath = null)
63719 {
63720 $lockPath = $lockPath ?: sys_get_temp_dir();
63721
63722 if (!is_dir($lockPath)) {
63723 $fs = new Filesystem();
63724 $fs->mkdir($lockPath);
63725 }
63726
63727 if (!is_writable($lockPath)) {
63728 throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
63729 }
63730
63731 $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
63732 }
63733
63734
63735
63736
63737
63738
63739
63740
63741
63742
63743 public function lock($blocking = false)
63744 {
63745 if ($this->handle) {
63746 return true;
63747 }
63748
63749 $error = null;
63750
63751
63752  set_error_handler(function ($errno, $msg) use (&$error) {
63753 $error = $msg;
63754 });
63755
63756 if (!$this->handle = fopen($this->file, 'r')) {
63757 if ($this->handle = fopen($this->file, 'x')) {
63758 chmod($this->file, 0444);
63759 } elseif (!$this->handle = fopen($this->file, 'r')) {
63760 usleep(100); 
63761  $this->handle = fopen($this->file, 'r');
63762 }
63763 }
63764 restore_error_handler();
63765
63766 if (!$this->handle) {
63767 throw new IOException($error, 0, null, $this->file);
63768 }
63769
63770
63771  
63772  if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
63773 fclose($this->handle);
63774 $this->handle = null;
63775
63776 return false;
63777 }
63778
63779 return true;
63780 }
63781
63782
63783
63784
63785 public function release()
63786 {
63787 if ($this->handle) {
63788 flock($this->handle, LOCK_UN | LOCK_NB);
63789 fclose($this->handle);
63790 $this->handle = null;
63791 }
63792 }
63793 }
63794 <?php
63795
63796
63797
63798
63799
63800
63801
63802
63803
63804
63805 namespace Symfony\Component\Finder\Adapter;
63806
63807 @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);
63808
63809
63810
63811
63812
63813
63814
63815
63816 abstract class AbstractAdapter implements AdapterInterface
63817 {
63818 protected $followLinks = false;
63819 protected $mode = 0;
63820 protected $minDepth = 0;
63821 protected $maxDepth = PHP_INT_MAX;
63822 protected $exclude = array();
63823 protected $names = array();
63824 protected $notNames = array();
63825 protected $contains = array();
63826 protected $notContains = array();
63827 protected $sizes = array();
63828 protected $dates = array();
63829 protected $filters = array();
63830 protected $sort = false;
63831 protected $paths = array();
63832 protected $notPaths = array();
63833 protected $ignoreUnreadableDirs = false;
63834
63835 private static $areSupported = array();
63836
63837
63838
63839
63840 public function isSupported()
63841 {
63842 $name = $this->getName();
63843
63844 if (!array_key_exists($name, self::$areSupported)) {
63845 self::$areSupported[$name] = $this->canBeUsed();
63846 }
63847
63848 return self::$areSupported[$name];
63849 }
63850
63851
63852
63853
63854 public function setFollowLinks($followLinks)
63855 {
63856 $this->followLinks = $followLinks;
63857
63858 return $this;
63859 }
63860
63861
63862
63863
63864 public function setMode($mode)
63865 {
63866 $this->mode = $mode;
63867
63868 return $this;
63869 }
63870
63871
63872
63873
63874 public function setDepths(array $depths)
63875 {
63876 $this->minDepth = 0;
63877 $this->maxDepth = PHP_INT_MAX;
63878
63879 foreach ($depths as $comparator) {
63880 switch ($comparator->getOperator()) {
63881 case '>':
63882 $this->minDepth = $comparator->getTarget() + 1;
63883 break;
63884 case '>=':
63885 $this->minDepth = $comparator->getTarget();
63886 break;
63887 case '<':
63888 $this->maxDepth = $comparator->getTarget() - 1;
63889 break;
63890 case '<=':
63891 $this->maxDepth = $comparator->getTarget();
63892 break;
63893 default:
63894 $this->minDepth = $this->maxDepth = $comparator->getTarget();
63895 }
63896 }
63897
63898 return $this;
63899 }
63900
63901
63902
63903
63904 public function setExclude(array $exclude)
63905 {
63906 $this->exclude = $exclude;
63907
63908 return $this;
63909 }
63910
63911
63912
63913
63914 public function setNames(array $names)
63915 {
63916 $this->names = $names;
63917
63918 return $this;
63919 }
63920
63921
63922
63923
63924 public function setNotNames(array $notNames)
63925 {
63926 $this->notNames = $notNames;
63927
63928 return $this;
63929 }
63930
63931
63932
63933
63934 public function setContains(array $contains)
63935 {
63936 $this->contains = $contains;
63937
63938 return $this;
63939 }
63940
63941
63942
63943
63944 public function setNotContains(array $notContains)
63945 {
63946 $this->notContains = $notContains;
63947
63948 return $this;
63949 }
63950
63951
63952
63953
63954 public function setSizes(array $sizes)
63955 {
63956 $this->sizes = $sizes;
63957
63958 return $this;
63959 }
63960
63961
63962
63963
63964 public function setDates(array $dates)
63965 {
63966 $this->dates = $dates;
63967
63968 return $this;
63969 }
63970
63971
63972
63973
63974 public function setFilters(array $filters)
63975 {
63976 $this->filters = $filters;
63977
63978 return $this;
63979 }
63980
63981
63982
63983
63984 public function setSort($sort)
63985 {
63986 $this->sort = $sort;
63987
63988 return $this;
63989 }
63990
63991
63992
63993
63994 public function setPath(array $paths)
63995 {
63996 $this->paths = $paths;
63997
63998 return $this;
63999 }
64000
64001
64002
64003
64004 public function setNotPath(array $notPaths)
64005 {
64006 $this->notPaths = $notPaths;
64007
64008 return $this;
64009 }
64010
64011
64012
64013
64014 public function ignoreUnreadableDirs($ignore = true)
64015 {
64016 $this->ignoreUnreadableDirs = (bool) $ignore;
64017
64018 return $this;
64019 }
64020
64021
64022
64023
64024
64025
64026
64027
64028
64029
64030
64031
64032 abstract protected function canBeUsed();
64033 }
64034 <?php
64035
64036
64037
64038
64039
64040
64041
64042
64043
64044
64045 namespace Symfony\Component\Finder\Adapter;
64046
64047 @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);
64048
64049 use Symfony\Component\Finder\Exception\AccessDeniedException;
64050 use Symfony\Component\Finder\Iterator;
64051 use Symfony\Component\Finder\Shell\Shell;
64052 use Symfony\Component\Finder\Expression\Expression;
64053 use Symfony\Component\Finder\Shell\Command;
64054 use Symfony\Component\Finder\Comparator\NumberComparator;
64055 use Symfony\Component\Finder\Comparator\DateComparator;
64056
64057
64058
64059
64060
64061
64062
64063
64064 abstract class AbstractFindAdapter extends AbstractAdapter
64065 {
64066
64067
64068
64069 protected $shell;
64070
64071
64072
64073
64074 public function __construct()
64075 {
64076 $this->shell = new Shell();
64077 }
64078
64079
64080
64081
64082 public function searchInDirectory($dir)
64083 {
64084
64085  $dir = realpath($dir);
64086
64087
64088  if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
64089 return new Iterator\FilePathsIterator(array(), $dir);
64090 }
64091
64092 $command = Command::create();
64093 $find = $this->buildFindCommand($command, $dir);
64094
64095 if ($this->followLinks) {
64096 $find->add('-follow');
64097 }
64098
64099 $find->add('-mindepth')->add($this->minDepth + 1);
64100
64101 if (PHP_INT_MAX !== $this->maxDepth) {
64102 $find->add('-maxdepth')->add($this->maxDepth + 1);
64103 }
64104
64105 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
64106 $find->add('-type d');
64107 } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
64108 $find->add('-type f');
64109 }
64110
64111 $this->buildNamesFiltering($find, $this->names);
64112 $this->buildNamesFiltering($find, $this->notNames, true);
64113 $this->buildPathsFiltering($find, $dir, $this->paths);
64114 $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
64115 $this->buildSizesFiltering($find, $this->sizes);
64116 $this->buildDatesFiltering($find, $this->dates);
64117
64118 $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
64119 $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
64120
64121 if ($useGrep && ($this->contains || $this->notContains)) {
64122 $grep = $command->ins('grep');
64123 $this->buildContentFiltering($grep, $this->contains);
64124 $this->buildContentFiltering($grep, $this->notContains, true);
64125 }
64126
64127 if ($useSort) {
64128 $this->buildSorting($command, $this->sort);
64129 }
64130
64131 $command->setErrorHandler(
64132 $this->ignoreUnreadableDirs
64133
64134  ? function ($stderr) { }
64135 : function ($stderr) { throw new AccessDeniedException($stderr); }
64136 );
64137
64138 $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
64139 $iterator = new Iterator\FilePathsIterator($paths, $dir);
64140
64141 if ($this->exclude) {
64142 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
64143 }
64144
64145 if (!$useGrep && ($this->contains || $this->notContains)) {
64146 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
64147 }
64148
64149 if ($this->filters) {
64150 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
64151 }
64152
64153 if (!$useSort && $this->sort) {
64154 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
64155 $iterator = $iteratorAggregate->getIterator();
64156 }
64157
64158 return $iterator;
64159 }
64160
64161
64162
64163
64164 protected function canBeUsed()
64165 {
64166 return $this->shell->testCommand('find');
64167 }
64168
64169
64170
64171
64172
64173
64174
64175 protected function buildFindCommand(Command $command, $dir)
64176 {
64177 return $command
64178 ->ins('find')
64179 ->add('find ')
64180 ->arg($dir)
64181 ->add('-noleaf'); 
64182  }
64183
64184
64185
64186
64187
64188
64189 private function buildNamesFiltering(Command $command, array $names, $not = false)
64190 {
64191 if (0 === count($names)) {
64192 return;
64193 }
64194
64195 $command->add($not ? '-not' : null)->cmd('(');
64196
64197 foreach ($names as $i => $name) {
64198 $expr = Expression::create($name);
64199
64200
64201  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
64202 $expr = Expression::create($expr->getGlob()->toRegex(false));
64203 }
64204
64205
64206  
64207  
64208  if ($expr->isRegex()) {
64209 $regex = $expr->getRegex();
64210 $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
64211 ->setStartFlag(false)
64212 ->setStartJoker(true)
64213 ->replaceJokers('[^/]');
64214 if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
64215 $regex->setEndJoker(false)->append('[^/]*');
64216 }
64217 }
64218
64219 $command
64220 ->add($i > 0 ? '-or' : null)
64221 ->add($expr->isRegex()
64222 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
64223 : ($expr->isCaseSensitive() ? '-name' : '-iname')
64224 )
64225 ->arg($expr->renderPattern());
64226 }
64227
64228 $command->cmd(')');
64229 }
64230
64231
64232
64233
64234
64235
64236
64237 private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
64238 {
64239 if (0 === count($paths)) {
64240 return;
64241 }
64242
64243 $command->add($not ? '-not' : null)->cmd('(');
64244
64245 foreach ($paths as $i => $path) {
64246 $expr = Expression::create($path);
64247
64248
64249  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
64250 $expr = Expression::create($expr->getGlob()->toRegex(false));
64251 }
64252
64253
64254  if ($expr->isRegex()) {
64255 $regex = $expr->getRegex();
64256 $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
64257 } else {
64258 $expr->prepend('*')->append('*');
64259 }
64260
64261 $command
64262 ->add($i > 0 ? '-or' : null)
64263 ->add($expr->isRegex()
64264 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
64265 : ($expr->isCaseSensitive() ? '-path' : '-ipath')
64266 )
64267 ->arg($expr->renderPattern());
64268 }
64269
64270 $command->cmd(')');
64271 }
64272
64273
64274
64275
64276
64277 private function buildSizesFiltering(Command $command, array $sizes)
64278 {
64279 foreach ($sizes as $i => $size) {
64280 $command->add($i > 0 ? '-and' : null);
64281
64282 switch ($size->getOperator()) {
64283 case '<=':
64284 $command->add('-size -'.($size->getTarget() + 1).'c');
64285 break;
64286 case '>=':
64287 $command->add('-size +'.($size->getTarget() - 1).'c');
64288 break;
64289 case '>':
64290 $command->add('-size +'.$size->getTarget().'c');
64291 break;
64292 case '!=':
64293 $command->add('-size -'.$size->getTarget().'c');
64294 $command->add('-size +'.$size->getTarget().'c');
64295 break;
64296 case '<':
64297 default:
64298 $command->add('-size -'.$size->getTarget().'c');
64299 }
64300 }
64301 }
64302
64303
64304
64305
64306
64307 private function buildDatesFiltering(Command $command, array $dates)
64308 {
64309 foreach ($dates as $i => $date) {
64310 $command->add($i > 0 ? '-and' : null);
64311
64312 $mins = (int) round((time() - $date->getTarget()) / 60);
64313
64314 if (0 > $mins) {
64315
64316  $command->add(' -mmin -0');
64317
64318  return;
64319 }
64320
64321 switch ($date->getOperator()) {
64322 case '<=':
64323 $command->add('-mmin +'.($mins - 1));
64324 break;
64325 case '>=':
64326 $command->add('-mmin -'.($mins + 1));
64327 break;
64328 case '>':
64329 $command->add('-mmin -'.$mins);
64330 break;
64331 case '!=':
64332 $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
64333 break;
64334 case '<':
64335 default:
64336 $command->add('-mmin +'.$mins);
64337 }
64338 }
64339 }
64340
64341
64342
64343
64344
64345
64346
64347 private function buildSorting(Command $command, $sort)
64348 {
64349 $this->buildFormatSorting($command, $sort);
64350 }
64351
64352
64353
64354
64355
64356 abstract protected function buildFormatSorting(Command $command, $sort);
64357
64358
64359
64360
64361
64362
64363 abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
64364 }
64365 <?php
64366
64367
64368
64369
64370
64371
64372
64373
64374
64375
64376 namespace Symfony\Component\Finder\Adapter;
64377
64378
64379
64380
64381
64382
64383 interface AdapterInterface
64384 {
64385
64386
64387
64388
64389
64390 public function setFollowLinks($followLinks);
64391
64392
64393
64394
64395
64396
64397 public function setMode($mode);
64398
64399
64400
64401
64402
64403
64404 public function setExclude(array $exclude);
64405
64406
64407
64408
64409
64410
64411 public function setDepths(array $depths);
64412
64413
64414
64415
64416
64417
64418 public function setNames(array $names);
64419
64420
64421
64422
64423
64424
64425 public function setNotNames(array $notNames);
64426
64427
64428
64429
64430
64431
64432 public function setContains(array $contains);
64433
64434
64435
64436
64437
64438
64439 public function setNotContains(array $notContains);
64440
64441
64442
64443
64444
64445
64446 public function setSizes(array $sizes);
64447
64448
64449
64450
64451
64452
64453 public function setDates(array $dates);
64454
64455
64456
64457
64458
64459
64460 public function setFilters(array $filters);
64461
64462
64463
64464
64465
64466
64467 public function setSort($sort);
64468
64469
64470
64471
64472
64473
64474 public function setPath(array $paths);
64475
64476
64477
64478
64479
64480
64481 public function setNotPath(array $notPaths);
64482
64483
64484
64485
64486
64487
64488 public function ignoreUnreadableDirs($ignore = true);
64489
64490
64491
64492
64493
64494
64495 public function searchInDirectory($dir);
64496
64497
64498
64499
64500
64501
64502 public function isSupported();
64503
64504
64505
64506
64507
64508
64509 public function getName();
64510 }
64511 <?php
64512
64513
64514
64515
64516
64517
64518
64519
64520
64521
64522 namespace Symfony\Component\Finder\Adapter;
64523
64524 @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);
64525
64526 use Symfony\Component\Finder\Shell\Shell;
64527 use Symfony\Component\Finder\Shell\Command;
64528 use Symfony\Component\Finder\Iterator\SortableIterator;
64529 use Symfony\Component\Finder\Expression\Expression;
64530
64531
64532
64533
64534
64535
64536
64537
64538 class BsdFindAdapter extends AbstractFindAdapter
64539 {
64540
64541
64542
64543 public function getName()
64544 {
64545 return 'bsd_find';
64546 }
64547
64548
64549
64550
64551 protected function canBeUsed()
64552 {
64553 return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
64554 }
64555
64556
64557
64558
64559 protected function buildFormatSorting(Command $command, $sort)
64560 {
64561 switch ($sort) {
64562 case SortableIterator::SORT_BY_NAME:
64563 $command->ins('sort')->add('| sort');
64564
64565 return;
64566 case SortableIterator::SORT_BY_TYPE:
64567 $format = '%HT';
64568 break;
64569 case SortableIterator::SORT_BY_ACCESSED_TIME:
64570 $format = '%a';
64571 break;
64572 case SortableIterator::SORT_BY_CHANGED_TIME:
64573 $format = '%c';
64574 break;
64575 case SortableIterator::SORT_BY_MODIFIED_TIME:
64576 $format = '%m';
64577 break;
64578 default:
64579 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
64580 }
64581
64582 $command
64583 ->add('-print0 | xargs -0 stat -f')
64584 ->arg($format.'%t%N')
64585 ->add('| sort | cut -f 2');
64586 }
64587
64588
64589
64590
64591 protected function buildFindCommand(Command $command, $dir)
64592 {
64593 parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
64594
64595 return $command;
64596 }
64597
64598
64599
64600
64601 protected function buildContentFiltering(Command $command, array $contains, $not = false)
64602 {
64603 foreach ($contains as $contain) {
64604 $expr = Expression::create($contain);
64605
64606
64607  $command
64608 ->add('| grep -v \'^$\'')
64609 ->add('| xargs -I{} grep -I')
64610 ->add($expr->isCaseSensitive() ? null : '-i')
64611 ->add($not ? '-L' : '-l')
64612 ->add('-Ee')->arg($expr->renderPattern())
64613 ->add('{}')
64614 ;
64615 }
64616 }
64617 }
64618 <?php
64619
64620
64621
64622
64623
64624
64625
64626
64627
64628
64629 namespace Symfony\Component\Finder\Adapter;
64630
64631 @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);
64632
64633 use Symfony\Component\Finder\Shell\Shell;
64634 use Symfony\Component\Finder\Shell\Command;
64635 use Symfony\Component\Finder\Iterator\SortableIterator;
64636 use Symfony\Component\Finder\Expression\Expression;
64637
64638
64639
64640
64641
64642
64643
64644
64645 class GnuFindAdapter extends AbstractFindAdapter
64646 {
64647
64648
64649
64650 public function getName()
64651 {
64652 return 'gnu_find';
64653 }
64654
64655
64656
64657
64658 protected function buildFormatSorting(Command $command, $sort)
64659 {
64660 switch ($sort) {
64661 case SortableIterator::SORT_BY_NAME:
64662 $command->ins('sort')->add('| sort');
64663
64664 return;
64665 case SortableIterator::SORT_BY_TYPE:
64666 $format = '%y';
64667 break;
64668 case SortableIterator::SORT_BY_ACCESSED_TIME:
64669 $format = '%A@';
64670 break;
64671 case SortableIterator::SORT_BY_CHANGED_TIME:
64672 $format = '%C@';
64673 break;
64674 case SortableIterator::SORT_BY_MODIFIED_TIME:
64675 $format = '%T@';
64676 break;
64677 default:
64678 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
64679 }
64680
64681 $command
64682 ->get('find')
64683 ->add('-printf')
64684 ->arg($format.' %h/%f\\n')
64685 ->add('| sort | cut')
64686 ->arg('-d ')
64687 ->arg('-f2-')
64688 ;
64689 }
64690
64691
64692
64693
64694 protected function canBeUsed()
64695 {
64696 return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed();
64697 }
64698
64699
64700
64701
64702 protected function buildFindCommand(Command $command, $dir)
64703 {
64704 return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
64705 }
64706
64707
64708
64709
64710 protected function buildContentFiltering(Command $command, array $contains, $not = false)
64711 {
64712 foreach ($contains as $contain) {
64713 $expr = Expression::create($contain);
64714
64715
64716  $command
64717 ->add('| xargs -I{} -r grep -I')
64718 ->add($expr->isCaseSensitive() ? null : '-i')
64719 ->add($not ? '-L' : '-l')
64720 ->add('-Ee')->arg($expr->renderPattern())
64721 ->add('{}')
64722 ;
64723 }
64724 }
64725 }
64726 <?php
64727
64728
64729
64730
64731
64732
64733
64734
64735
64736
64737 namespace Symfony\Component\Finder\Adapter;
64738
64739 @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);
64740
64741 use Symfony\Component\Finder\Iterator;
64742
64743
64744
64745
64746
64747
64748
64749
64750 class PhpAdapter extends AbstractAdapter
64751 {
64752
64753
64754
64755 public function searchInDirectory($dir)
64756 {
64757 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
64758
64759 if ($this->followLinks) {
64760 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
64761 }
64762
64763 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
64764
64765 if ($this->exclude) {
64766 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
64767 }
64768
64769 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
64770
64771 if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
64772 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
64773 }
64774
64775 if ($this->mode) {
64776 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
64777 }
64778
64779 if ($this->names || $this->notNames) {
64780 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
64781 }
64782
64783 if ($this->contains || $this->notContains) {
64784 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
64785 }
64786
64787 if ($this->sizes) {
64788 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
64789 }
64790
64791 if ($this->dates) {
64792 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
64793 }
64794
64795 if ($this->filters) {
64796 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
64797 }
64798
64799 if ($this->paths || $this->notPaths) {
64800 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
64801 }
64802
64803 if ($this->sort) {
64804 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
64805 $iterator = $iteratorAggregate->getIterator();
64806 }
64807
64808 return $iterator;
64809 }
64810
64811
64812
64813
64814 public function getName()
64815 {
64816 return 'php';
64817 }
64818
64819
64820
64821
64822 protected function canBeUsed()
64823 {
64824 return true;
64825 }
64826 }
64827 <?php
64828
64829
64830
64831
64832
64833
64834
64835
64836
64837
64838 namespace Symfony\Component\Finder\Comparator;
64839
64840
64841
64842
64843
64844
64845 class Comparator
64846 {
64847 private $target;
64848 private $operator = '==';
64849
64850
64851
64852
64853
64854
64855 public function getTarget()
64856 {
64857 return $this->target;
64858 }
64859
64860
64861
64862
64863
64864
64865 public function setTarget($target)
64866 {
64867 $this->target = $target;
64868 }
64869
64870
64871
64872
64873
64874
64875 public function getOperator()
64876 {
64877 return $this->operator;
64878 }
64879
64880
64881
64882
64883
64884
64885
64886
64887 public function setOperator($operator)
64888 {
64889 if (!$operator) {
64890 $operator = '==';
64891 }
64892
64893 if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
64894 throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
64895 }
64896
64897 $this->operator = $operator;
64898 }
64899
64900
64901
64902
64903
64904
64905
64906
64907 public function test($test)
64908 {
64909 switch ($this->operator) {
64910 case '>':
64911 return $test > $this->target;
64912 case '>=':
64913 return $test >= $this->target;
64914 case '<':
64915 return $test < $this->target;
64916 case '<=':
64917 return $test <= $this->target;
64918 case '!=':
64919 return $test != $this->target;
64920 }
64921
64922 return $test == $this->target;
64923 }
64924 }
64925 <?php
64926
64927
64928
64929
64930
64931
64932
64933
64934
64935
64936 namespace Symfony\Component\Finder\Comparator;
64937
64938
64939
64940
64941
64942
64943 class DateComparator extends Comparator
64944 {
64945
64946
64947
64948
64949
64950
64951
64952 public function __construct($test)
64953 {
64954 if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
64955 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
64956 }
64957
64958 try {
64959 $date = new \DateTime($matches[2]);
64960 $target = $date->format('U');
64961 } catch (\Exception $e) {
64962 throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
64963 }
64964
64965 $operator = isset($matches[1]) ? $matches[1] : '==';
64966 if ('since' === $operator || 'after' === $operator) {
64967 $operator = '>';
64968 }
64969
64970 if ('until' === $operator || 'before' === $operator) {
64971 $operator = '<';
64972 }
64973
64974 $this->setOperator($operator);
64975 $this->setTarget($target);
64976 }
64977 }
64978 <?php
64979
64980
64981
64982
64983
64984
64985
64986
64987
64988
64989 namespace Symfony\Component\Finder\Comparator;
64990
64991
64992
64993
64994
64995
64996
64997
64998
64999
65000
65001
65002
65003
65004
65005
65006
65007
65008
65009
65010
65011
65012 class NumberComparator extends Comparator
65013 {
65014
65015
65016
65017
65018
65019
65020
65021 public function __construct($test)
65022 {
65023 if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
65024 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
65025 }
65026
65027 $target = $matches[2];
65028 if (!is_numeric($target)) {
65029 throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
65030 }
65031 if (isset($matches[3])) {
65032
65033  switch (strtolower($matches[3])) {
65034 case 'k':
65035 $target *= 1000;
65036 break;
65037 case 'ki':
65038 $target *= 1024;
65039 break;
65040 case 'm':
65041 $target *= 1000000;
65042 break;
65043 case 'mi':
65044 $target *= 1024 * 1024;
65045 break;
65046 case 'g':
65047 $target *= 1000000000;
65048 break;
65049 case 'gi':
65050 $target *= 1024 * 1024 * 1024;
65051 break;
65052 }
65053 }
65054
65055 $this->setTarget($target);
65056 $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
65057 }
65058 }
65059 <?php
65060
65061
65062
65063
65064
65065
65066
65067
65068
65069
65070 namespace Symfony\Component\Finder\Exception;
65071
65072
65073
65074
65075 class AccessDeniedException extends \UnexpectedValueException
65076 {
65077 }
65078 <?php
65079
65080
65081
65082
65083
65084
65085
65086
65087
65088
65089 namespace Symfony\Component\Finder\Exception;
65090
65091 @trigger_error('The '.__NAMESPACE__.'\AdapterFailureException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65092
65093 use Symfony\Component\Finder\Adapter\AdapterInterface;
65094
65095
65096
65097
65098
65099
65100
65101
65102 class AdapterFailureException extends \RuntimeException implements ExceptionInterface
65103 {
65104
65105
65106
65107 private $adapter;
65108
65109
65110
65111
65112
65113
65114 public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
65115 {
65116 $this->adapter = $adapter;
65117 parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
65118 }
65119
65120
65121
65122
65123 public function getAdapter()
65124 {
65125 return $this->adapter;
65126 }
65127 }
65128 <?php
65129
65130
65131
65132
65133
65134
65135
65136
65137
65138
65139 namespace Symfony\Component\Finder\Exception;
65140
65141
65142
65143
65144 interface ExceptionInterface
65145 {
65146
65147
65148
65149 public function getAdapter();
65150 }
65151 <?php
65152
65153
65154
65155
65156
65157
65158
65159
65160
65161
65162 namespace Symfony\Component\Finder\Exception;
65163
65164 @trigger_error('The '.__NAMESPACE__.'\OperationNotPermitedException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65165
65166
65167
65168
65169
65170
65171 class OperationNotPermitedException extends AdapterFailureException
65172 {
65173 }
65174 <?php
65175
65176
65177
65178
65179
65180
65181
65182
65183
65184
65185 namespace Symfony\Component\Finder\Exception;
65186
65187 @trigger_error('The '.__NAMESPACE__.'\ShellCommandFailureException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65188
65189 use Symfony\Component\Finder\Adapter\AdapterInterface;
65190 use Symfony\Component\Finder\Shell\Command;
65191
65192
65193
65194
65195
65196
65197 class ShellCommandFailureException extends AdapterFailureException
65198 {
65199
65200
65201
65202 private $command;
65203
65204
65205
65206
65207
65208
65209 public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
65210 {
65211 $this->command = $command;
65212 parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
65213 }
65214
65215
65216
65217
65218 public function getCommand()
65219 {
65220 return $this->command;
65221 }
65222 }
65223 <?php
65224
65225
65226
65227
65228
65229
65230
65231
65232
65233
65234 namespace Symfony\Component\Finder\Expression;
65235
65236 @trigger_error('The '.__NAMESPACE__.'\Expression class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65237
65238
65239
65240
65241 class Expression implements ValueInterface
65242 {
65243 const TYPE_REGEX = 1;
65244 const TYPE_GLOB = 2;
65245
65246
65247
65248
65249 private $value;
65250
65251
65252
65253
65254
65255
65256 public static function create($expr)
65257 {
65258 return new self($expr);
65259 }
65260
65261
65262
65263
65264 public function __construct($expr)
65265 {
65266 try {
65267 $this->value = Regex::create($expr);
65268 } catch (\InvalidArgumentException $e) {
65269 $this->value = new Glob($expr);
65270 }
65271 }
65272
65273
65274
65275
65276 public function __toString()
65277 {
65278 return $this->render();
65279 }
65280
65281
65282
65283
65284 public function render()
65285 {
65286 return $this->value->render();
65287 }
65288
65289
65290
65291
65292 public function renderPattern()
65293 {
65294 return $this->value->renderPattern();
65295 }
65296
65297
65298
65299
65300 public function isCaseSensitive()
65301 {
65302 return $this->value->isCaseSensitive();
65303 }
65304
65305
65306
65307
65308 public function getType()
65309 {
65310 return $this->value->getType();
65311 }
65312
65313
65314
65315
65316 public function prepend($expr)
65317 {
65318 $this->value->prepend($expr);
65319
65320 return $this;
65321 }
65322
65323
65324
65325
65326 public function append($expr)
65327 {
65328 $this->value->append($expr);
65329
65330 return $this;
65331 }
65332
65333
65334
65335
65336 public function isRegex()
65337 {
65338 return self::TYPE_REGEX === $this->value->getType();
65339 }
65340
65341
65342
65343
65344 public function isGlob()
65345 {
65346 return self::TYPE_GLOB === $this->value->getType();
65347 }
65348
65349
65350
65351
65352
65353
65354 public function getGlob()
65355 {
65356 if (self::TYPE_GLOB !== $this->value->getType()) {
65357 throw new \LogicException('Regex can\'t be transformed to glob.');
65358 }
65359
65360 return $this->value;
65361 }
65362
65363
65364
65365
65366 public function getRegex()
65367 {
65368 return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
65369 }
65370 }
65371 <?php
65372
65373
65374
65375
65376
65377
65378
65379
65380
65381
65382 namespace Symfony\Component\Finder\Expression;
65383
65384 @trigger_error('The '.__NAMESPACE__.'\Glob class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65385
65386 use Symfony\Component\Finder\Glob as FinderGlob;
65387
65388
65389
65390
65391 class Glob implements ValueInterface
65392 {
65393
65394
65395
65396 private $pattern;
65397
65398
65399
65400
65401 public function __construct($pattern)
65402 {
65403 $this->pattern = $pattern;
65404 }
65405
65406
65407
65408
65409 public function render()
65410 {
65411 return $this->pattern;
65412 }
65413
65414
65415
65416
65417 public function renderPattern()
65418 {
65419 return $this->pattern;
65420 }
65421
65422
65423
65424
65425 public function getType()
65426 {
65427 return Expression::TYPE_GLOB;
65428 }
65429
65430
65431
65432
65433 public function isCaseSensitive()
65434 {
65435 return true;
65436 }
65437
65438
65439
65440
65441 public function prepend($expr)
65442 {
65443 $this->pattern = $expr.$this->pattern;
65444
65445 return $this;
65446 }
65447
65448
65449
65450
65451 public function append($expr)
65452 {
65453 $this->pattern .= $expr;
65454
65455 return $this;
65456 }
65457
65458
65459
65460
65461
65462
65463 public function isExpandable()
65464 {
65465 return false !== strpos($this->pattern, '{')
65466 && false !== strpos($this->pattern, '}');
65467 }
65468
65469
65470
65471
65472
65473
65474
65475 public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
65476 {
65477 $regex = FinderGlob::toRegex($this->pattern, $strictLeadingDot, $strictWildcardSlash, '');
65478
65479 return new Regex($regex);
65480 }
65481 }
65482 <?php
65483
65484
65485
65486
65487
65488
65489
65490
65491
65492
65493 namespace Symfony\Component\Finder\Expression;
65494
65495 @trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65496
65497
65498
65499
65500 class Regex implements ValueInterface
65501 {
65502 const START_FLAG = '^';
65503 const END_FLAG = '$';
65504 const BOUNDARY = '~';
65505 const JOKER = '.*';
65506 const ESCAPING = '\\';
65507
65508
65509
65510
65511 private $pattern;
65512
65513
65514
65515
65516 private $options;
65517
65518
65519
65520
65521 private $startFlag;
65522
65523
65524
65525
65526 private $endFlag;
65527
65528
65529
65530
65531 private $startJoker;
65532
65533
65534
65535
65536 private $endJoker;
65537
65538
65539
65540
65541
65542
65543
65544
65545 public static function create($expr)
65546 {
65547 if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
65548 $start = substr($m[1], 0, 1);
65549 $end = substr($m[1], -1);
65550
65551 if (
65552 ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
65553 || ($start === '{' && $end === '}')
65554 || ($start === '(' && $end === ')')
65555 ) {
65556 return new self(substr($m[1], 1, -1), $m[2], $end);
65557 }
65558 }
65559
65560 throw new \InvalidArgumentException('Given expression is not a regex.');
65561 }
65562
65563
65564
65565
65566
65567
65568 public function __construct($pattern, $options = '', $delimiter = null)
65569 {
65570 if (null !== $delimiter) {
65571
65572  $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
65573 }
65574
65575 $this->parsePattern($pattern);
65576 $this->options = $options;
65577 }
65578
65579
65580
65581
65582 public function __toString()
65583 {
65584 return $this->render();
65585 }
65586
65587
65588
65589
65590 public function render()
65591 {
65592 return self::BOUNDARY
65593 .$this->renderPattern()
65594 .self::BOUNDARY
65595 .$this->options;
65596 }
65597
65598
65599
65600
65601 public function renderPattern()
65602 {
65603 return ($this->startFlag ? self::START_FLAG : '')
65604 .($this->startJoker ? self::JOKER : '')
65605 .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
65606 .($this->endJoker ? self::JOKER : '')
65607 .($this->endFlag ? self::END_FLAG : '');
65608 }
65609
65610
65611
65612
65613 public function isCaseSensitive()
65614 {
65615 return !$this->hasOption('i');
65616 }
65617
65618
65619
65620
65621 public function getType()
65622 {
65623 return Expression::TYPE_REGEX;
65624 }
65625
65626
65627
65628
65629 public function prepend($expr)
65630 {
65631 $this->pattern = $expr.$this->pattern;
65632
65633 return $this;
65634 }
65635
65636
65637
65638
65639 public function append($expr)
65640 {
65641 $this->pattern .= $expr;
65642
65643 return $this;
65644 }
65645
65646
65647
65648
65649
65650
65651 public function hasOption($option)
65652 {
65653 return false !== strpos($this->options, $option);
65654 }
65655
65656
65657
65658
65659
65660
65661 public function addOption($option)
65662 {
65663 if (!$this->hasOption($option)) {
65664 $this->options .= $option;
65665 }
65666
65667 return $this;
65668 }
65669
65670
65671
65672
65673
65674
65675 public function removeOption($option)
65676 {
65677 $this->options = str_replace($option, '', $this->options);
65678
65679 return $this;
65680 }
65681
65682
65683
65684
65685
65686
65687 public function setStartFlag($startFlag)
65688 {
65689 $this->startFlag = $startFlag;
65690
65691 return $this;
65692 }
65693
65694
65695
65696
65697 public function hasStartFlag()
65698 {
65699 return $this->startFlag;
65700 }
65701
65702
65703
65704
65705
65706
65707 public function setEndFlag($endFlag)
65708 {
65709 $this->endFlag = (bool) $endFlag;
65710
65711 return $this;
65712 }
65713
65714
65715
65716
65717 public function hasEndFlag()
65718 {
65719 return $this->endFlag;
65720 }
65721
65722
65723
65724
65725
65726
65727 public function setStartJoker($startJoker)
65728 {
65729 $this->startJoker = $startJoker;
65730
65731 return $this;
65732 }
65733
65734
65735
65736
65737 public function hasStartJoker()
65738 {
65739 return $this->startJoker;
65740 }
65741
65742
65743
65744
65745
65746
65747 public function setEndJoker($endJoker)
65748 {
65749 $this->endJoker = (bool) $endJoker;
65750
65751 return $this;
65752 }
65753
65754
65755
65756
65757 public function hasEndJoker()
65758 {
65759 return $this->endJoker;
65760 }
65761
65762
65763
65764
65765
65766
65767 public function replaceJokers($replacement)
65768 {
65769 $replace = function ($subject) use ($replacement) {
65770 $subject = $subject[0];
65771 $replace = 0 === substr_count($subject, '\\') % 2;
65772
65773 return $replace ? str_replace('.', $replacement, $subject) : $subject;
65774 };
65775
65776 $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
65777
65778 return $this;
65779 }
65780
65781
65782
65783
65784 private function parsePattern($pattern)
65785 {
65786 if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
65787 $pattern = substr($pattern, 1);
65788 }
65789
65790 if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
65791 $pattern = substr($pattern, 2);
65792 }
65793
65794 if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
65795 $pattern = substr($pattern, 0, -1);
65796 }
65797
65798 if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
65799 $pattern = substr($pattern, 0, -2);
65800 }
65801
65802 $this->pattern = $pattern;
65803 }
65804 }
65805 <?php
65806
65807
65808
65809
65810
65811
65812
65813
65814
65815
65816 namespace Symfony\Component\Finder\Expression;
65817
65818 @trigger_error('The '.__NAMESPACE__.'\ValueInterface interface is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65819
65820
65821
65822
65823 interface ValueInterface
65824 {
65825
65826
65827
65828
65829
65830 public function render();
65831
65832
65833
65834
65835
65836
65837 public function renderPattern();
65838
65839
65840
65841
65842
65843
65844 public function isCaseSensitive();
65845
65846
65847
65848
65849
65850
65851 public function getType();
65852
65853
65854
65855
65856
65857
65858 public function prepend($expr);
65859
65860
65861
65862
65863
65864
65865 public function append($expr);
65866 }
65867 <?php
65868
65869
65870
65871
65872
65873
65874
65875
65876
65877
65878 namespace Symfony\Component\Finder;
65879
65880 use Symfony\Component\Finder\Adapter\AdapterInterface;
65881 use Symfony\Component\Finder\Adapter\GnuFindAdapter;
65882 use Symfony\Component\Finder\Adapter\BsdFindAdapter;
65883 use Symfony\Component\Finder\Adapter\PhpAdapter;
65884 use Symfony\Component\Finder\Comparator\DateComparator;
65885 use Symfony\Component\Finder\Comparator\NumberComparator;
65886 use Symfony\Component\Finder\Exception\ExceptionInterface;
65887 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
65888 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
65889 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
65890 use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
65891 use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
65892 use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
65893 use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
65894 use Symfony\Component\Finder\Iterator\SortableIterator;
65895
65896
65897
65898
65899
65900
65901
65902
65903
65904
65905
65906
65907
65908
65909 class Finder implements \IteratorAggregate, \Countable
65910 {
65911 const IGNORE_VCS_FILES = 1;
65912 const IGNORE_DOT_FILES = 2;
65913
65914 private $mode = 0;
65915 private $names = array();
65916 private $notNames = array();
65917 private $exclude = array();
65918 private $filters = array();
65919 private $depths = array();
65920 private $sizes = array();
65921 private $followLinks = false;
65922 private $sort = false;
65923 private $ignore = 0;
65924 private $dirs = array();
65925 private $dates = array();
65926 private $iterators = array();
65927 private $contains = array();
65928 private $notContains = array();
65929 private $adapters = null;
65930 private $paths = array();
65931 private $notPaths = array();
65932 private $ignoreUnreadableDirs = false;
65933
65934 private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
65935
65936
65937
65938
65939 public function __construct()
65940 {
65941 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
65942 }
65943
65944
65945
65946
65947
65948
65949 public static function create()
65950 {
65951 return new static();
65952 }
65953
65954
65955
65956
65957
65958
65959
65960
65961
65962
65963
65964 public function addAdapter(AdapterInterface $adapter, $priority = 0)
65965 {
65966 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65967
65968 $this->initDefaultAdapters();
65969
65970 $this->adapters[$adapter->getName()] = array(
65971 'adapter' => $adapter,
65972 'priority' => $priority,
65973 'selected' => false,
65974 );
65975
65976 return $this->sortAdapters();
65977 }
65978
65979
65980
65981
65982
65983
65984
65985
65986 public function useBestAdapter()
65987 {
65988 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65989
65990 $this->initDefaultAdapters();
65991
65992 $this->resetAdapterSelection();
65993
65994 return $this->sortAdapters();
65995 }
65996
65997
65998
65999
66000
66001
66002
66003
66004
66005
66006
66007
66008 public function setAdapter($name)
66009 {
66010 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66011
66012 $this->initDefaultAdapters();
66013
66014 if (!isset($this->adapters[$name])) {
66015 throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
66016 }
66017
66018 $this->resetAdapterSelection();
66019 $this->adapters[$name]['selected'] = true;
66020
66021 return $this->sortAdapters();
66022 }
66023
66024
66025
66026
66027
66028
66029
66030
66031 public function removeAdapters()
66032 {
66033 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66034
66035 $this->adapters = array();
66036
66037 return $this;
66038 }
66039
66040
66041
66042
66043
66044
66045
66046
66047 public function getAdapters()
66048 {
66049 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66050
66051 $this->initDefaultAdapters();
66052
66053 return array_values(array_map(function (array $adapter) {
66054 return $adapter['adapter'];
66055 }, $this->adapters));
66056 }
66057
66058
66059
66060
66061
66062
66063 public function directories()
66064 {
66065 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
66066
66067 return $this;
66068 }
66069
66070
66071
66072
66073
66074
66075 public function files()
66076 {
66077 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
66078
66079 return $this;
66080 }
66081
66082
66083
66084
66085
66086
66087
66088
66089
66090
66091
66092
66093
66094
66095
66096
66097 public function depth($level)
66098 {
66099 $this->depths[] = new Comparator\NumberComparator($level);
66100
66101 return $this;
66102 }
66103
66104
66105
66106
66107
66108
66109
66110
66111
66112
66113
66114
66115
66116
66117
66118
66119
66120
66121
66122 public function date($date)
66123 {
66124 $this->dates[] = new Comparator\DateComparator($date);
66125
66126 return $this;
66127 }
66128
66129
66130
66131
66132
66133
66134
66135
66136
66137
66138
66139
66140
66141
66142
66143
66144 public function name($pattern)
66145 {
66146 $this->names[] = $pattern;
66147
66148 return $this;
66149 }
66150
66151
66152
66153
66154
66155
66156
66157
66158
66159
66160 public function notName($pattern)
66161 {
66162 $this->notNames[] = $pattern;
66163
66164 return $this;
66165 }
66166
66167
66168
66169
66170
66171
66172
66173
66174
66175
66176
66177
66178
66179
66180
66181 public function contains($pattern)
66182 {
66183 $this->contains[] = $pattern;
66184
66185 return $this;
66186 }
66187
66188
66189
66190
66191
66192
66193
66194
66195
66196
66197
66198
66199
66200
66201
66202 public function notContains($pattern)
66203 {
66204 $this->notContains[] = $pattern;
66205
66206 return $this;
66207 }
66208
66209
66210
66211
66212
66213
66214
66215
66216
66217
66218
66219
66220
66221
66222
66223
66224
66225 public function path($pattern)
66226 {
66227 $this->paths[] = $pattern;
66228
66229 return $this;
66230 }
66231
66232
66233
66234
66235
66236
66237
66238
66239
66240
66241
66242
66243
66244
66245
66246
66247
66248 public function notPath($pattern)
66249 {
66250 $this->notPaths[] = $pattern;
66251
66252 return $this;
66253 }
66254
66255
66256
66257
66258
66259
66260
66261
66262
66263
66264
66265
66266
66267
66268
66269 public function size($size)
66270 {
66271 $this->sizes[] = new Comparator\NumberComparator($size);
66272
66273 return $this;
66274 }
66275
66276
66277
66278
66279
66280
66281
66282
66283
66284
66285 public function exclude($dirs)
66286 {
66287 $this->exclude = array_merge($this->exclude, (array) $dirs);
66288
66289 return $this;
66290 }
66291
66292
66293
66294
66295
66296
66297
66298
66299
66300
66301 public function ignoreDotFiles($ignoreDotFiles)
66302 {
66303 if ($ignoreDotFiles) {
66304 $this->ignore |= static::IGNORE_DOT_FILES;
66305 } else {
66306 $this->ignore &= ~static::IGNORE_DOT_FILES;
66307 }
66308
66309 return $this;
66310 }
66311
66312
66313
66314
66315
66316
66317
66318
66319
66320
66321 public function ignoreVCS($ignoreVCS)
66322 {
66323 if ($ignoreVCS) {
66324 $this->ignore |= static::IGNORE_VCS_FILES;
66325 } else {
66326 $this->ignore &= ~static::IGNORE_VCS_FILES;
66327 }
66328
66329 return $this;
66330 }
66331
66332
66333
66334
66335
66336
66337
66338
66339 public static function addVCSPattern($pattern)
66340 {
66341 foreach ((array) $pattern as $p) {
66342 self::$vcsPatterns[] = $p;
66343 }
66344
66345 self::$vcsPatterns = array_unique(self::$vcsPatterns);
66346 }
66347
66348
66349
66350
66351
66352
66353
66354
66355
66356
66357
66358
66359
66360
66361 public function sort(\Closure $closure)
66362 {
66363 $this->sort = $closure;
66364
66365 return $this;
66366 }
66367
66368
66369
66370
66371
66372
66373
66374
66375
66376
66377 public function sortByName()
66378 {
66379 $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
66380
66381 return $this;
66382 }
66383
66384
66385
66386
66387
66388
66389
66390
66391
66392
66393 public function sortByType()
66394 {
66395 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
66396
66397 return $this;
66398 }
66399
66400
66401
66402
66403
66404
66405
66406
66407
66408
66409
66410
66411 public function sortByAccessedTime()
66412 {
66413 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
66414
66415 return $this;
66416 }
66417
66418
66419
66420
66421
66422
66423
66424
66425
66426
66427
66428
66429
66430
66431 public function sortByChangedTime()
66432 {
66433 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
66434
66435 return $this;
66436 }
66437
66438
66439
66440
66441
66442
66443
66444
66445
66446
66447
66448
66449 public function sortByModifiedTime()
66450 {
66451 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
66452
66453 return $this;
66454 }
66455
66456
66457
66458
66459
66460
66461
66462
66463
66464
66465
66466
66467
66468 public function filter(\Closure $closure)
66469 {
66470 $this->filters[] = $closure;
66471
66472 return $this;
66473 }
66474
66475
66476
66477
66478
66479
66480 public function followLinks()
66481 {
66482 $this->followLinks = true;
66483
66484 return $this;
66485 }
66486
66487
66488
66489
66490
66491
66492
66493
66494
66495
66496 public function ignoreUnreadableDirs($ignore = true)
66497 {
66498 $this->ignoreUnreadableDirs = (bool) $ignore;
66499
66500 return $this;
66501 }
66502
66503
66504
66505
66506
66507
66508
66509
66510
66511
66512 public function in($dirs)
66513 {
66514 $resolvedDirs = array();
66515
66516 foreach ((array) $dirs as $dir) {
66517 if (is_dir($dir)) {
66518 $resolvedDirs[] = $dir;
66519 } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
66520 $resolvedDirs = array_merge($resolvedDirs, $glob);
66521 } else {
66522 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
66523 }
66524 }
66525
66526 $this->dirs = array_merge($this->dirs, $resolvedDirs);
66527
66528 return $this;
66529 }
66530
66531
66532
66533
66534
66535
66536
66537
66538
66539
66540 public function getIterator()
66541 {
66542 if (0 === count($this->dirs) && 0 === count($this->iterators)) {
66543 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
66544 }
66545
66546 if (1 === count($this->dirs) && 0 === count($this->iterators)) {
66547 return $this->searchInDirectory($this->dirs[0]);
66548 }
66549
66550 $iterator = new \AppendIterator();
66551 foreach ($this->dirs as $dir) {
66552 $iterator->append($this->searchInDirectory($dir));
66553 }
66554
66555 foreach ($this->iterators as $it) {
66556 $iterator->append($it);
66557 }
66558
66559 return $iterator;
66560 }
66561
66562
66563
66564
66565
66566
66567
66568
66569
66570
66571
66572
66573 public function append($iterator)
66574 {
66575 if ($iterator instanceof \IteratorAggregate) {
66576 $this->iterators[] = $iterator->getIterator();
66577 } elseif ($iterator instanceof \Iterator) {
66578 $this->iterators[] = $iterator;
66579 } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
66580 $it = new \ArrayIterator();
66581 foreach ($iterator as $file) {
66582 $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
66583 }
66584 $this->iterators[] = $it;
66585 } else {
66586 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
66587 }
66588
66589 return $this;
66590 }
66591
66592
66593
66594
66595
66596
66597 public function count()
66598 {
66599 return iterator_count($this->getIterator());
66600 }
66601
66602
66603
66604
66605 private function sortAdapters()
66606 {
66607 uasort($this->adapters, function (array $a, array $b) {
66608 if ($a['selected'] || $b['selected']) {
66609 return $a['selected'] ? -1 : 1;
66610 }
66611
66612 return $a['priority'] > $b['priority'] ? -1 : 1;
66613 });
66614
66615 return $this;
66616 }
66617
66618
66619
66620
66621
66622
66623 private function searchInDirectory($dir)
66624 {
66625 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
66626 $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
66627 }
66628
66629 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
66630 $this->notPaths[] = '#(^|/)\..+(/|$)#';
66631 }
66632
66633 if ($this->adapters) {
66634 foreach ($this->adapters as $adapter) {
66635 if ($adapter['adapter']->isSupported()) {
66636 try {
66637 return $this
66638 ->buildAdapter($adapter['adapter'])
66639 ->searchInDirectory($dir);
66640 } catch (ExceptionInterface $e) {
66641 }
66642 }
66643 }
66644 }
66645
66646 $minDepth = 0;
66647 $maxDepth = PHP_INT_MAX;
66648
66649 foreach ($this->depths as $comparator) {
66650 switch ($comparator->getOperator()) {
66651 case '>':
66652 $minDepth = $comparator->getTarget() + 1;
66653 break;
66654 case '>=':
66655 $minDepth = $comparator->getTarget();
66656 break;
66657 case '<':
66658 $maxDepth = $comparator->getTarget() - 1;
66659 break;
66660 case '<=':
66661 $maxDepth = $comparator->getTarget();
66662 break;
66663 default:
66664 $minDepth = $maxDepth = $comparator->getTarget();
66665 }
66666 }
66667
66668 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
66669
66670 if ($this->followLinks) {
66671 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
66672 }
66673
66674 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
66675
66676 if ($this->exclude) {
66677 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
66678 }
66679
66680 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
66681
66682 if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
66683 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
66684 }
66685
66686 if ($this->mode) {
66687 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
66688 }
66689
66690 if ($this->names || $this->notNames) {
66691 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
66692 }
66693
66694 if ($this->contains || $this->notContains) {
66695 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
66696 }
66697
66698 if ($this->sizes) {
66699 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
66700 }
66701
66702 if ($this->dates) {
66703 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
66704 }
66705
66706 if ($this->filters) {
66707 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
66708 }
66709
66710 if ($this->paths || $this->notPaths) {
66711 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
66712 }
66713
66714 if ($this->sort) {
66715 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
66716 $iterator = $iteratorAggregate->getIterator();
66717 }
66718
66719 return $iterator;
66720 }
66721
66722
66723
66724
66725
66726
66727 private function buildAdapter(AdapterInterface $adapter)
66728 {
66729 return $adapter
66730 ->setFollowLinks($this->followLinks)
66731 ->setDepths($this->depths)
66732 ->setMode($this->mode)
66733 ->setExclude($this->exclude)
66734 ->setNames($this->names)
66735 ->setNotNames($this->notNames)
66736 ->setContains($this->contains)
66737 ->setNotContains($this->notContains)
66738 ->setSizes($this->sizes)
66739 ->setDates($this->dates)
66740 ->setFilters($this->filters)
66741 ->setSort($this->sort)
66742 ->setPath($this->paths)
66743 ->setNotPath($this->notPaths)
66744 ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
66745 }
66746
66747
66748
66749
66750 private function resetAdapterSelection()
66751 {
66752 $this->adapters = array_map(function (array $properties) {
66753 $properties['selected'] = false;
66754
66755 return $properties;
66756 }, $this->adapters);
66757 }
66758
66759 private function initDefaultAdapters()
66760 {
66761 if (null === $this->adapters) {
66762 $this->adapters = array();
66763 $this
66764 ->addAdapter(new GnuFindAdapter())
66765 ->addAdapter(new BsdFindAdapter())
66766 ->addAdapter(new PhpAdapter(), -50)
66767 ->setAdapter('php')
66768 ;
66769 }
66770 }
66771 }
66772 <?php
66773
66774
66775
66776
66777
66778
66779
66780
66781
66782
66783 namespace Symfony\Component\Finder;
66784
66785
66786
66787
66788
66789
66790
66791
66792
66793
66794
66795
66796
66797
66798
66799
66800
66801
66802
66803
66804
66805
66806
66807 class Glob
66808 {
66809
66810
66811
66812
66813
66814
66815
66816
66817
66818
66819 public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
66820 {
66821 $firstByte = true;
66822 $escaping = false;
66823 $inCurlies = 0;
66824 $regex = '';
66825 $sizeGlob = strlen($glob);
66826 for ($i = 0; $i < $sizeGlob; ++$i) {
66827 $car = $glob[$i];
66828 if ($firstByte) {
66829 if ($strictLeadingDot && '.' !== $car) {
66830 $regex .= '(?=[^\.])';
66831 }
66832
66833 $firstByte = false;
66834 }
66835
66836 if ('/' === $car) {
66837 $firstByte = true;
66838 }
66839
66840 if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
66841 $regex .= "\\$car";
66842 } elseif ('*' === $car) {
66843 $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
66844 } elseif ('?' === $car) {
66845 $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
66846 } elseif ('{' === $car) {
66847 $regex .= $escaping ? '\\{' : '(';
66848 if (!$escaping) {
66849 ++$inCurlies;
66850 }
66851 } elseif ('}' === $car && $inCurlies) {
66852 $regex .= $escaping ? '}' : ')';
66853 if (!$escaping) {
66854 --$inCurlies;
66855 }
66856 } elseif (',' === $car && $inCurlies) {
66857 $regex .= $escaping ? ',' : '|';
66858 } elseif ('\\' === $car) {
66859 if ($escaping) {
66860 $regex .= '\\\\';
66861 $escaping = false;
66862 } else {
66863 $escaping = true;
66864 }
66865
66866 continue;
66867 } else {
66868 $regex .= $car;
66869 }
66870 $escaping = false;
66871 }
66872
66873 return $delimiter.'^'.$regex.'$'.$delimiter;
66874 }
66875 }
66876 <?php
66877
66878
66879
66880
66881
66882
66883
66884
66885
66886
66887 namespace Symfony\Component\Finder\Iterator;
66888
66889
66890
66891
66892
66893
66894
66895
66896
66897 class CustomFilterIterator extends FilterIterator
66898 {
66899 private $filters = array();
66900
66901
66902
66903
66904
66905
66906
66907
66908
66909 public function __construct(\Iterator $iterator, array $filters)
66910 {
66911 foreach ($filters as $filter) {
66912 if (!is_callable($filter)) {
66913 throw new \InvalidArgumentException('Invalid PHP callback.');
66914 }
66915 }
66916 $this->filters = $filters;
66917
66918 parent::__construct($iterator);
66919 }
66920
66921
66922
66923
66924
66925
66926 public function accept()
66927 {
66928 $fileinfo = $this->current();
66929
66930 foreach ($this->filters as $filter) {
66931 if (false === call_user_func($filter, $fileinfo)) {
66932 return false;
66933 }
66934 }
66935
66936 return true;
66937 }
66938 }
66939 <?php
66940
66941
66942
66943
66944
66945
66946
66947
66948
66949
66950 namespace Symfony\Component\Finder\Iterator;
66951
66952 use Symfony\Component\Finder\Comparator\DateComparator;
66953
66954
66955
66956
66957
66958
66959 class DateRangeFilterIterator extends FilterIterator
66960 {
66961 private $comparators = array();
66962
66963
66964
66965
66966
66967
66968
66969 public function __construct(\Iterator $iterator, array $comparators)
66970 {
66971 $this->comparators = $comparators;
66972
66973 parent::__construct($iterator);
66974 }
66975
66976
66977
66978
66979
66980
66981 public function accept()
66982 {
66983 $fileinfo = $this->current();
66984
66985 if (!file_exists($fileinfo->getPathname())) {
66986 return false;
66987 }
66988
66989 $filedate = $fileinfo->getMTime();
66990 foreach ($this->comparators as $compare) {
66991 if (!$compare->test($filedate)) {
66992 return false;
66993 }
66994 }
66995
66996 return true;
66997 }
66998 }
66999 <?php
67000
67001
67002
67003
67004
67005
67006
67007
67008
67009
67010 namespace Symfony\Component\Finder\Iterator;
67011
67012
67013
67014
67015
67016
67017 class DepthRangeFilterIterator extends FilterIterator
67018 {
67019 private $minDepth = 0;
67020
67021
67022
67023
67024
67025
67026
67027
67028 public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
67029 {
67030 $this->minDepth = $minDepth;
67031 $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
67032
67033 parent::__construct($iterator);
67034 }
67035
67036
67037
67038
67039
67040
67041 public function accept()
67042 {
67043 return $this->getInnerIterator()->getDepth() >= $this->minDepth;
67044 }
67045 }
67046 <?php
67047
67048
67049
67050
67051
67052
67053
67054
67055
67056
67057 namespace Symfony\Component\Finder\Iterator;
67058
67059
67060
67061
67062
67063
67064 class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
67065 {
67066 private $iterator;
67067 private $isRecursive;
67068 private $excludedDirs = array();
67069 private $excludedPattern;
67070
67071
67072
67073
67074
67075
67076
67077 public function __construct(\Iterator $iterator, array $directories)
67078 {
67079 $this->iterator = $iterator;
67080 $this->isRecursive = $iterator instanceof \RecursiveIterator;
67081 $patterns = array();
67082 foreach ($directories as $directory) {
67083 $directory = rtrim($directory, '/');
67084 if (!$this->isRecursive || false !== strpos($directory, '/')) {
67085 $patterns[] = preg_quote($directory, '#');
67086 } else {
67087 $this->excludedDirs[$directory] = true;
67088 }
67089 }
67090 if ($patterns) {
67091 $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
67092 }
67093
67094 parent::__construct($iterator);
67095 }
67096
67097
67098
67099
67100
67101
67102 public function accept()
67103 {
67104 if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
67105 return false;
67106 }
67107
67108 if ($this->excludedPattern) {
67109 $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
67110 $path = str_replace('\\', '/', $path);
67111
67112 return !preg_match($this->excludedPattern, $path);
67113 }
67114
67115 return true;
67116 }
67117
67118 public function hasChildren()
67119 {
67120 return $this->isRecursive && $this->iterator->hasChildren();
67121 }
67122
67123 public function getChildren()
67124 {
67125 $children = new self($this->iterator->getChildren(), array());
67126 $children->excludedDirs = $this->excludedDirs;
67127 $children->excludedPattern = $this->excludedPattern;
67128
67129 return $children;
67130 }
67131 }
67132 <?php
67133
67134
67135
67136
67137
67138
67139
67140
67141
67142
67143 namespace Symfony\Component\Finder\Iterator;
67144
67145 @trigger_error('The '.__NAMESPACE__.'\FilePathsIterator class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67146
67147 use Symfony\Component\Finder\SplFileInfo;
67148
67149
67150
67151
67152
67153
67154
67155
67156 class FilePathsIterator extends \ArrayIterator
67157 {
67158
67159
67160
67161 private $baseDir;
67162
67163
67164
67165
67166 private $baseDirLength;
67167
67168
67169
67170
67171 private $subPath;
67172
67173
67174
67175
67176 private $subPathname;
67177
67178
67179
67180
67181 private $current;
67182
67183
67184
67185
67186
67187 public function __construct(array $paths, $baseDir)
67188 {
67189 $this->baseDir = $baseDir;
67190 $this->baseDirLength = strlen($baseDir);
67191
67192 parent::__construct($paths);
67193 }
67194
67195
67196
67197
67198
67199
67200
67201 public function __call($name, array $arguments)
67202 {
67203 return call_user_func_array(array($this->current(), $name), $arguments);
67204 }
67205
67206
67207
67208
67209
67210
67211 public function current()
67212 {
67213 return $this->current;
67214 }
67215
67216
67217
67218
67219 public function key()
67220 {
67221 return $this->current->getPathname();
67222 }
67223
67224 public function next()
67225 {
67226 parent::next();
67227 $this->buildProperties();
67228 }
67229
67230 public function rewind()
67231 {
67232 parent::rewind();
67233 $this->buildProperties();
67234 }
67235
67236
67237
67238
67239 public function getSubPath()
67240 {
67241 return $this->subPath;
67242 }
67243
67244
67245
67246
67247 public function getSubPathname()
67248 {
67249 return $this->subPathname;
67250 }
67251
67252 private function buildProperties()
67253 {
67254 $absolutePath = parent::current();
67255
67256 if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
67257 $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
67258 $dir = dirname($this->subPathname);
67259 $this->subPath = '.' === $dir ? '' : $dir;
67260 } else {
67261 $this->subPath = $this->subPathname = '';
67262 }
67263
67264 $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
67265 }
67266 }
67267 <?php
67268
67269
67270
67271
67272
67273
67274
67275
67276
67277
67278 namespace Symfony\Component\Finder\Iterator;
67279
67280
67281
67282
67283
67284
67285 class FileTypeFilterIterator extends FilterIterator
67286 {
67287 const ONLY_FILES = 1;
67288 const ONLY_DIRECTORIES = 2;
67289
67290 private $mode;
67291
67292
67293
67294
67295
67296
67297
67298 public function __construct(\Iterator $iterator, $mode)
67299 {
67300 $this->mode = $mode;
67301
67302 parent::__construct($iterator);
67303 }
67304
67305
67306
67307
67308
67309
67310 public function accept()
67311 {
67312 $fileinfo = $this->current();
67313 if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
67314 return false;
67315 } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
67316 return false;
67317 }
67318
67319 return true;
67320 }
67321 }
67322 <?php
67323
67324
67325
67326
67327
67328
67329
67330
67331
67332
67333 namespace Symfony\Component\Finder\Iterator;
67334
67335
67336
67337
67338
67339
67340
67341 class FilecontentFilterIterator extends MultiplePcreFilterIterator
67342 {
67343
67344
67345
67346
67347
67348 public function accept()
67349 {
67350 if (!$this->matchRegexps && !$this->noMatchRegexps) {
67351 return true;
67352 }
67353
67354 $fileinfo = $this->current();
67355
67356 if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
67357 return false;
67358 }
67359
67360 $content = $fileinfo->getContents();
67361 if (!$content) {
67362 return false;
67363 }
67364
67365 return $this->isAccepted($content);
67366 }
67367
67368
67369
67370
67371
67372
67373
67374
67375 protected function toRegex($str)
67376 {
67377 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
67378 }
67379 }
67380 <?php
67381
67382
67383
67384
67385
67386
67387
67388
67389
67390
67391 namespace Symfony\Component\Finder\Iterator;
67392
67393 use Symfony\Component\Finder\Glob;
67394
67395
67396
67397
67398
67399
67400 class FilenameFilterIterator extends MultiplePcreFilterIterator
67401 {
67402
67403
67404
67405
67406
67407 public function accept()
67408 {
67409 return $this->isAccepted($this->current()->getFilename());
67410 }
67411
67412
67413
67414
67415
67416
67417
67418
67419
67420
67421
67422 protected function toRegex($str)
67423 {
67424 return $this->isRegex($str) ? $str : Glob::toRegex($str);
67425 }
67426 }
67427 <?php
67428
67429
67430
67431
67432
67433
67434
67435
67436
67437
67438 namespace Symfony\Component\Finder\Iterator;
67439
67440
67441
67442
67443
67444
67445
67446
67447
67448 abstract class FilterIterator extends \FilterIterator
67449 {
67450
67451
67452
67453
67454
67455
67456 public function rewind()
67457 {
67458 if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
67459 parent::rewind();
67460
67461 return;
67462 }
67463
67464 $iterator = $this;
67465 while ($iterator instanceof \OuterIterator) {
67466 $innerIterator = $iterator->getInnerIterator();
67467
67468 if ($innerIterator instanceof RecursiveDirectoryIterator) {
67469
67470  if ($innerIterator->isRewindable()) {
67471 $innerIterator->next();
67472 $innerIterator->rewind();
67473 }
67474 } elseif ($innerIterator instanceof \FilesystemIterator) {
67475 $innerIterator->next();
67476 $innerIterator->rewind();
67477 }
67478
67479 $iterator = $innerIterator;
67480 }
67481
67482 parent::rewind();
67483 }
67484 }
67485 <?php
67486
67487
67488
67489
67490
67491
67492
67493
67494
67495
67496 namespace Symfony\Component\Finder\Iterator;
67497
67498
67499
67500
67501
67502
67503 abstract class MultiplePcreFilterIterator extends FilterIterator
67504 {
67505 protected $matchRegexps = array();
67506 protected $noMatchRegexps = array();
67507
67508
67509
67510
67511
67512
67513
67514
67515 public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
67516 {
67517 foreach ($matchPatterns as $pattern) {
67518 $this->matchRegexps[] = $this->toRegex($pattern);
67519 }
67520
67521 foreach ($noMatchPatterns as $pattern) {
67522 $this->noMatchRegexps[] = $this->toRegex($pattern);
67523 }
67524
67525 parent::__construct($iterator);
67526 }
67527
67528
67529
67530
67531
67532
67533
67534
67535
67536
67537
67538
67539 protected function isAccepted($string)
67540 {
67541
67542  foreach ($this->noMatchRegexps as $regex) {
67543 if (preg_match($regex, $string)) {
67544 return false;
67545 }
67546 }
67547
67548
67549  if ($this->matchRegexps) {
67550 foreach ($this->matchRegexps as $regex) {
67551 if (preg_match($regex, $string)) {
67552 return true;
67553 }
67554 }
67555
67556 return false;
67557 }
67558
67559
67560  return true;
67561 }
67562
67563
67564
67565
67566
67567
67568
67569
67570 protected function isRegex($str)
67571 {
67572 if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
67573 $start = substr($m[1], 0, 1);
67574 $end = substr($m[1], -1);
67575
67576 if ($start === $end) {
67577 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
67578 }
67579
67580 foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
67581 if ($start === $delimiters[0] && $end === $delimiters[1]) {
67582 return true;
67583 }
67584 }
67585 }
67586
67587 return false;
67588 }
67589
67590
67591
67592
67593
67594
67595
67596
67597 abstract protected function toRegex($str);
67598 }
67599 <?php
67600
67601
67602
67603
67604
67605
67606
67607
67608
67609
67610 namespace Symfony\Component\Finder\Iterator;
67611
67612
67613
67614
67615
67616
67617
67618 class PathFilterIterator extends MultiplePcreFilterIterator
67619 {
67620
67621
67622
67623
67624
67625 public function accept()
67626 {
67627 $filename = $this->current()->getRelativePathname();
67628
67629 if ('\\' === DIRECTORY_SEPARATOR) {
67630 $filename = str_replace('\\', '/', $filename);
67631 }
67632
67633 return $this->isAccepted($filename);
67634 }
67635
67636
67637
67638
67639
67640
67641
67642
67643
67644
67645
67646
67647
67648
67649
67650 protected function toRegex($str)
67651 {
67652 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
67653 }
67654 }
67655 <?php
67656
67657
67658
67659
67660
67661
67662
67663
67664
67665
67666 namespace Symfony\Component\Finder\Iterator;
67667
67668 use Symfony\Component\Finder\Exception\AccessDeniedException;
67669 use Symfony\Component\Finder\SplFileInfo;
67670
67671
67672
67673
67674
67675
67676 class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
67677 {
67678
67679
67680
67681 private $ignoreUnreadableDirs;
67682
67683
67684
67685
67686 private $rewindable;
67687
67688
67689  private $rootPath;
67690 private $subPath;
67691 private $directorySeparator = '/';
67692
67693
67694
67695
67696
67697
67698
67699
67700
67701
67702 public function __construct($path, $flags, $ignoreUnreadableDirs = false)
67703 {
67704 if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
67705 throw new \RuntimeException('This iterator only support returning current as fileinfo.');
67706 }
67707
67708 parent::__construct($path, $flags);
67709 $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
67710 $this->rootPath = (string) $path;
67711 if ('/' !== DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
67712 $this->directorySeparator = DIRECTORY_SEPARATOR;
67713 }
67714 }
67715
67716
67717
67718
67719
67720
67721 public function current()
67722 {
67723
67724
67725 if (null === $subPathname = $this->subPath) {
67726 $subPathname = $this->subPath = (string) $this->getSubPath();
67727 }
67728 if ('' !== $subPathname) {
67729 $subPathname .= $this->directorySeparator;
67730 }
67731 $subPathname .= $this->getFilename();
67732
67733 return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
67734 }
67735
67736
67737
67738
67739
67740
67741 public function getChildren()
67742 {
67743 try {
67744 $children = parent::getChildren();
67745
67746 if ($children instanceof self) {
67747
67748  $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
67749
67750
67751  $children->rewindable = &$this->rewindable;
67752 $children->rootPath = $this->rootPath;
67753 }
67754
67755 return $children;
67756 } catch (\UnexpectedValueException $e) {
67757 if ($this->ignoreUnreadableDirs) {
67758
67759  return new \RecursiveArrayIterator(array());
67760 } else {
67761 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
67762 }
67763 }
67764 }
67765
67766
67767
67768
67769 public function rewind()
67770 {
67771 if (false === $this->isRewindable()) {
67772 return;
67773 }
67774
67775
67776  if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
67777 parent::next();
67778 }
67779
67780 parent::rewind();
67781 }
67782
67783
67784
67785
67786
67787
67788 public function isRewindable()
67789 {
67790 if (null !== $this->rewindable) {
67791 return $this->rewindable;
67792 }
67793
67794
67795  if ('' === $this->getPath()) {
67796 return $this->rewindable = false;
67797 }
67798
67799 if (false !== $stream = @opendir($this->getPath())) {
67800 $infos = stream_get_meta_data($stream);
67801 closedir($stream);
67802
67803 if ($infos['seekable']) {
67804 return $this->rewindable = true;
67805 }
67806 }
67807
67808 return $this->rewindable = false;
67809 }
67810 }
67811 <?php
67812
67813
67814
67815
67816
67817
67818
67819
67820
67821
67822 namespace Symfony\Component\Finder\Iterator;
67823
67824 use Symfony\Component\Finder\Comparator\NumberComparator;
67825
67826
67827
67828
67829
67830
67831 class SizeRangeFilterIterator extends FilterIterator
67832 {
67833 private $comparators = array();
67834
67835
67836
67837
67838
67839
67840
67841 public function __construct(\Iterator $iterator, array $comparators)
67842 {
67843 $this->comparators = $comparators;
67844
67845 parent::__construct($iterator);
67846 }
67847
67848
67849
67850
67851
67852
67853 public function accept()
67854 {
67855 $fileinfo = $this->current();
67856 if (!$fileinfo->isFile()) {
67857 return true;
67858 }
67859
67860 $filesize = $fileinfo->getSize();
67861 foreach ($this->comparators as $compare) {
67862 if (!$compare->test($filesize)) {
67863 return false;
67864 }
67865 }
67866
67867 return true;
67868 }
67869 }
67870 <?php
67871
67872
67873
67874
67875
67876
67877
67878
67879
67880
67881 namespace Symfony\Component\Finder\Iterator;
67882
67883
67884
67885
67886
67887
67888 class SortableIterator implements \IteratorAggregate
67889 {
67890 const SORT_BY_NAME = 1;
67891 const SORT_BY_TYPE = 2;
67892 const SORT_BY_ACCESSED_TIME = 3;
67893 const SORT_BY_CHANGED_TIME = 4;
67894 const SORT_BY_MODIFIED_TIME = 5;
67895
67896 private $iterator;
67897 private $sort;
67898
67899
67900
67901
67902
67903
67904
67905
67906
67907 public function __construct(\Traversable $iterator, $sort)
67908 {
67909 $this->iterator = $iterator;
67910
67911 if (self::SORT_BY_NAME === $sort) {
67912 $this->sort = function ($a, $b) {
67913 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
67914 };
67915 } elseif (self::SORT_BY_TYPE === $sort) {
67916 $this->sort = function ($a, $b) {
67917 if ($a->isDir() && $b->isFile()) {
67918 return -1;
67919 } elseif ($a->isFile() && $b->isDir()) {
67920 return 1;
67921 }
67922
67923 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
67924 };
67925 } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
67926 $this->sort = function ($a, $b) {
67927 return $a->getATime() - $b->getATime();
67928 };
67929 } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
67930 $this->sort = function ($a, $b) {
67931 return $a->getCTime() - $b->getCTime();
67932 };
67933 } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
67934 $this->sort = function ($a, $b) {
67935 return $a->getMTime() - $b->getMTime();
67936 };
67937 } elseif (is_callable($sort)) {
67938 $this->sort = $sort;
67939 } else {
67940 throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
67941 }
67942 }
67943
67944 public function getIterator()
67945 {
67946 $array = iterator_to_array($this->iterator, true);
67947 uasort($array, $this->sort);
67948
67949 return new \ArrayIterator($array);
67950 }
67951 }
67952 Copyright (c) 2004-2017 Fabien Potencier
67953
67954 Permission is hereby granted, free of charge, to any person obtaining a copy
67955 of this software and associated documentation files (the "Software"), to deal
67956 in the Software without restriction, including without limitation the rights
67957 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
67958 copies of the Software, and to permit persons to whom the Software is furnished
67959 to do so, subject to the following conditions:
67960
67961 The above copyright notice and this permission notice shall be included in all
67962 copies or substantial portions of the Software.
67963
67964 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
67965 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
67966 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
67967 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
67968 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67969 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
67970 THE SOFTWARE.
67971 <?php
67972
67973
67974
67975
67976
67977
67978
67979
67980
67981
67982 namespace Symfony\Component\Finder\Shell;
67983
67984 @trigger_error('The '.__NAMESPACE__.'\Command class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67985
67986
67987
67988
67989
67990
67991 class Command
67992 {
67993
67994
67995
67996 private $parent;
67997
67998
67999
68000
68001 private $bits = array();
68002
68003
68004
68005
68006 private $labels = array();
68007
68008
68009
68010
68011 private $errorHandler;
68012
68013
68014
68015
68016
68017
68018 public function __construct(Command $parent = null)
68019 {
68020 $this->parent = $parent;
68021 }
68022
68023
68024
68025
68026
68027
68028 public function __toString()
68029 {
68030 return $this->join();
68031 }
68032
68033
68034
68035
68036
68037
68038
68039
68040 public static function create(Command $parent = null)
68041 {
68042 return new self($parent);
68043 }
68044
68045
68046
68047
68048
68049
68050
68051
68052 public static function escape($input)
68053 {
68054 return escapeshellcmd($input);
68055 }
68056
68057
68058
68059
68060
68061
68062
68063
68064 public static function quote($input)
68065 {
68066 return escapeshellarg($input);
68067 }
68068
68069
68070
68071
68072
68073
68074
68075
68076 public function add($bit)
68077 {
68078 $this->bits[] = $bit;
68079
68080 return $this;
68081 }
68082
68083
68084
68085
68086
68087
68088
68089
68090 public function top($bit)
68091 {
68092 array_unshift($this->bits, $bit);
68093
68094 foreach ($this->labels as $label => $index) {
68095 $this->labels[$label] += 1;
68096 }
68097
68098 return $this;
68099 }
68100
68101
68102
68103
68104
68105
68106
68107
68108 public function arg($arg)
68109 {
68110 $this->bits[] = self::quote($arg);
68111
68112 return $this;
68113 }
68114
68115
68116
68117
68118
68119
68120
68121
68122 public function cmd($esc)
68123 {
68124 $this->bits[] = self::escape($esc);
68125
68126 return $this;
68127 }
68128
68129
68130
68131
68132
68133
68134
68135
68136
68137
68138 public function ins($label)
68139 {
68140 if (isset($this->labels[$label])) {
68141 throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
68142 }
68143
68144 $this->bits[] = self::create($this);
68145 $this->labels[$label] = count($this->bits) - 1;
68146
68147 return $this->bits[$this->labels[$label]];
68148 }
68149
68150
68151
68152
68153
68154
68155
68156
68157
68158
68159 public function get($label)
68160 {
68161 if (!isset($this->labels[$label])) {
68162 throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
68163 }
68164
68165 return $this->bits[$this->labels[$label]];
68166 }
68167
68168
68169
68170
68171
68172
68173
68174
68175 public function end()
68176 {
68177 if (null === $this->parent) {
68178 throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
68179 }
68180
68181 return $this->parent;
68182 }
68183
68184
68185
68186
68187
68188
68189 public function length()
68190 {
68191 return count($this->bits);
68192 }
68193
68194
68195
68196
68197
68198
68199 public function setErrorHandler(\Closure $errorHandler)
68200 {
68201 $this->errorHandler = $errorHandler;
68202
68203 return $this;
68204 }
68205
68206
68207
68208
68209 public function getErrorHandler()
68210 {
68211 return $this->errorHandler;
68212 }
68213
68214
68215
68216
68217
68218
68219
68220
68221 public function execute()
68222 {
68223 if (null === $errorHandler = $this->errorHandler) {
68224 exec($this->join(), $output);
68225 } else {
68226 $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
68227 $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
68228
68229 if ($error = stream_get_contents($pipes[2])) {
68230 $errorHandler($error);
68231 }
68232
68233 proc_close($process);
68234 }
68235
68236 return $output ?: array();
68237 }
68238
68239
68240
68241
68242
68243
68244 public function join()
68245 {
68246 return implode(' ', array_filter(
68247 array_map(function ($bit) {
68248 return $bit instanceof Command ? $bit->join() : ($bit ?: null);
68249 }, $this->bits),
68250 function ($bit) { return null !== $bit; }
68251 ));
68252 }
68253
68254
68255
68256
68257
68258
68259
68260
68261
68262 public function addAtIndex($bit, $index)
68263 {
68264 array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit);
68265
68266 return $this;
68267 }
68268 }
68269 <?php
68270
68271
68272
68273
68274
68275
68276
68277
68278
68279
68280 namespace Symfony\Component\Finder\Shell;
68281
68282 @trigger_error('The '.__NAMESPACE__.'\Shell class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68283
68284
68285
68286
68287
68288
68289 class Shell
68290 {
68291 const TYPE_UNIX = 1;
68292 const TYPE_DARWIN = 2;
68293 const TYPE_CYGWIN = 3;
68294 const TYPE_WINDOWS = 4;
68295 const TYPE_BSD = 5;
68296
68297
68298
68299
68300 private $type;
68301
68302
68303
68304
68305
68306
68307 public function getType()
68308 {
68309 if (null === $this->type) {
68310 $this->type = $this->guessType();
68311 }
68312
68313 return $this->type;
68314 }
68315
68316
68317
68318
68319
68320
68321
68322
68323 public function testCommand($command)
68324 {
68325 if (!function_exists('exec')) {
68326 return false;
68327 }
68328
68329
68330  $testCommand = 'which ';
68331 if (self::TYPE_WINDOWS === $this->type) {
68332 $testCommand = 'where ';
68333 }
68334
68335 $command = escapeshellcmd($command);
68336
68337 exec($testCommand.$command, $output, $code);
68338
68339 return 0 === $code && count($output) > 0;
68340 }
68341
68342
68343
68344
68345
68346
68347 private function guessType()
68348 {
68349 $os = strtolower(PHP_OS);
68350
68351 if (false !== strpos($os, 'cygwin')) {
68352 return self::TYPE_CYGWIN;
68353 }
68354
68355 if (false !== strpos($os, 'darwin')) {
68356 return self::TYPE_DARWIN;
68357 }
68358
68359 if (false !== strpos($os, 'bsd')) {
68360 return self::TYPE_BSD;
68361 }
68362
68363 if (0 === strpos($os, 'win')) {
68364 return self::TYPE_WINDOWS;
68365 }
68366
68367 return self::TYPE_UNIX;
68368 }
68369 }
68370 <?php
68371
68372
68373
68374
68375
68376
68377
68378
68379
68380
68381 namespace Symfony\Component\Finder;
68382
68383
68384
68385
68386
68387
68388 class SplFileInfo extends \SplFileInfo
68389 {
68390 private $relativePath;
68391 private $relativePathname;
68392
68393
68394
68395
68396
68397
68398
68399
68400 public function __construct($file, $relativePath, $relativePathname)
68401 {
68402 parent::__construct($file);
68403 $this->relativePath = $relativePath;
68404 $this->relativePathname = $relativePathname;
68405 }
68406
68407
68408
68409
68410
68411
68412
68413
68414 public function getRelativePath()
68415 {
68416 return $this->relativePath;
68417 }
68418
68419
68420
68421
68422
68423
68424
68425
68426 public function getRelativePathname()
68427 {
68428 return $this->relativePathname;
68429 }
68430
68431
68432
68433
68434
68435
68436
68437
68438 public function getContents()
68439 {
68440 $level = error_reporting(0);
68441 $content = file_get_contents($this->getPathname());
68442 error_reporting($level);
68443 if (false === $content) {
68444 $error = error_get_last();
68445 throw new \RuntimeException($error['message']);
68446 }
68447
68448 return $content;
68449 }
68450 }
68451 Copyright (c) 2014-2016 Fabien Potencier
68452
68453 Permission is hereby granted, free of charge, to any person obtaining a copy
68454 of this software and associated documentation files (the "Software"), to deal
68455 in the Software without restriction, including without limitation the rights
68456 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
68457 copies of the Software, and to permit persons to whom the Software is furnished
68458 to do so, subject to the following conditions:
68459
68460 The above copyright notice and this permission notice shall be included in all
68461 copies or substantial portions of the Software.
68462
68463 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68464 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68465 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
68466 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
68467 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68468 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68469 THE SOFTWARE.
68470 <?php
68471
68472
68473
68474
68475
68476
68477
68478
68479
68480
68481 namespace Symfony\Polyfill\Mbstring;
68482
68483
68484
68485
68486
68487
68488
68489
68490
68491
68492
68493
68494
68495
68496
68497
68498
68499
68500
68501
68502
68503
68504
68505
68506
68507
68508
68509
68510
68511
68512
68513
68514
68515
68516
68517
68518
68519
68520
68521
68522
68523
68524
68525
68526
68527
68528
68529
68530
68531
68532
68533
68534
68535 final class Mbstring
68536 {
68537 const MB_CASE_FOLD = PHP_INT_MAX;
68538
68539 private static $encodingList = array('ASCII', 'UTF-8');
68540 private static $language = 'neutral';
68541 private static $internalEncoding = 'UTF-8';
68542 private static $caseFold = array(
68543 array('µ','ſ',"\xCD\x85",'ς',"\xCF\x90","\xCF\x91","\xCF\x95","\xCF\x96","\xCF\xB0","\xCF\xB1","\xCF\xB5","\xE1\xBA\x9B","\xE1\xBE\xBE"),
68544 array('μ','s','ι', 'σ','β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1",'ι'),
68545 );
68546
68547 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
68548 {
68549 if (is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
68550 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
68551 } else {
68552 $fromEncoding = self::getEncoding($fromEncoding);
68553 }
68554
68555 $toEncoding = self::getEncoding($toEncoding);
68556
68557 if ('BASE64' === $fromEncoding) {
68558 $s = base64_decode($s);
68559 $fromEncoding = $toEncoding;
68560 }
68561
68562 if ('BASE64' === $toEncoding) {
68563 return base64_encode($s);
68564 }
68565
68566 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
68567 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
68568 $fromEncoding = 'Windows-1252';
68569 }
68570 if ('UTF-8' !== $fromEncoding) {
68571 $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
68572 }
68573
68574 return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
68575 }
68576
68577 if ('HTML-ENTITIES' === $fromEncoding) {
68578 $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
68579 $fromEncoding = 'UTF-8';
68580 }
68581
68582 return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
68583 }
68584
68585 public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
68586 {
68587 $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
68588
68589 $ok = true;
68590 array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
68591 if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
68592 $ok = false;
68593 }
68594 });
68595
68596 return $ok ? $fromEncoding : false;
68597 }
68598
68599 public static function mb_decode_mimeheader($s)
68600 {
68601 return iconv_mime_decode($s, 2, self::$internalEncoding);
68602 }
68603
68604 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
68605 {
68606 trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
68607 }
68608
68609 public static function mb_convert_case($s, $mode, $encoding = null)
68610 {
68611 if ('' === $s .= '') {
68612 return '';
68613 }
68614
68615 $encoding = self::getEncoding($encoding);
68616
68617 if ('UTF-8' === $encoding) {
68618 $encoding = null;
68619 if (!preg_match('//u', $s)) {
68620 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
68621 }
68622 } else {
68623 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
68624 }
68625
68626 if (MB_CASE_TITLE == $mode) {
68627 $s = preg_replace_callback('/\b\p{Ll}/u', array(__CLASS__, 'title_case_upper'), $s);
68628 $s = preg_replace_callback('/\B[\p{Lu}\p{Lt}]+/u', array(__CLASS__, 'title_case_lower'), $s);
68629 } else {
68630 if (MB_CASE_UPPER == $mode) {
68631 static $upper = null;
68632 if (null === $upper) {
68633 $upper = self::getData('upperCase');
68634 }
68635 $map = $upper;
68636 } else {
68637 if (self::MB_CASE_FOLD === $mode) {
68638 $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
68639 }
68640
68641 static $lower = null;
68642 if (null === $lower) {
68643 $lower = self::getData('lowerCase');
68644 }
68645 $map = $lower;
68646 }
68647
68648 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
68649
68650 $i = 0;
68651 $len = strlen($s);
68652
68653 while ($i < $len) {
68654 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
68655 $uchr = substr($s, $i, $ulen);
68656 $i += $ulen;
68657
68658 if (isset($map[$uchr])) {
68659 $uchr = $map[$uchr];
68660 $nlen = strlen($uchr);
68661
68662 if ($nlen == $ulen) {
68663 $nlen = $i;
68664 do {
68665 $s[--$nlen] = $uchr[--$ulen];
68666 } while ($ulen);
68667 } else {
68668 $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
68669 $len += $nlen - $ulen;
68670 $i += $nlen - $ulen;
68671 }
68672 }
68673 }
68674 }
68675
68676 if (null === $encoding) {
68677 return $s;
68678 }
68679
68680 return iconv('UTF-8', $encoding.'//IGNORE', $s);
68681 }
68682
68683 public static function mb_internal_encoding($encoding = null)
68684 {
68685 if (null === $encoding) {
68686 return self::$internalEncoding;
68687 }
68688
68689 $encoding = self::getEncoding($encoding);
68690
68691 if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
68692 self::$internalEncoding = $encoding;
68693
68694 return true;
68695 }
68696
68697 return false;
68698 }
68699
68700 public static function mb_language($lang = null)
68701 {
68702 if (null === $lang) {
68703 return self::$language;
68704 }
68705
68706 switch ($lang = strtolower($lang)) {
68707 case 'uni':
68708 case 'neutral':
68709 self::$language = $lang;
68710
68711 return true;
68712 }
68713
68714 return false;
68715 }
68716
68717 public static function mb_list_encodings()
68718 {
68719 return array('UTF-8');
68720 }
68721
68722 public static function mb_encoding_aliases($encoding)
68723 {
68724 switch (strtoupper($encoding)) {
68725 case 'UTF8':
68726 case 'UTF-8':
68727 return array('utf8');
68728 }
68729
68730 return false;
68731 }
68732
68733 public static function mb_check_encoding($var = null, $encoding = null)
68734 {
68735 if (null === $encoding) {
68736 if (null === $var) {
68737 return false;
68738 }
68739 $encoding = self::$internalEncoding;
68740 }
68741
68742 return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
68743 }
68744
68745 public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
68746 {
68747 if (null === $encodingList) {
68748 $encodingList = self::$encodingList;
68749 } else {
68750 if (!is_array($encodingList)) {
68751 $encodingList = array_map('trim', explode(',', $encodingList));
68752 }
68753 $encodingList = array_map('strtoupper', $encodingList);
68754 }
68755
68756 foreach ($encodingList as $enc) {
68757 switch ($enc) {
68758 case 'ASCII':
68759 if (!preg_match('/[\x80-\xFF]/', $str)) {
68760 return $enc;
68761 }
68762 break;
68763
68764 case 'UTF8':
68765 case 'UTF-8':
68766 if (preg_match('//u', $str)) {
68767 return 'UTF-8';
68768 }
68769 break;
68770
68771 default:
68772 if (0 === strncmp($enc, 'ISO-8859-', 9)) {
68773 return $enc;
68774 }
68775 }
68776 }
68777
68778 return false;
68779 }
68780
68781 public static function mb_detect_order($encodingList = null)
68782 {
68783 if (null === $encodingList) {
68784 return self::$encodingList;
68785 }
68786
68787 if (!is_array($encodingList)) {
68788 $encodingList = array_map('trim', explode(',', $encodingList));
68789 }
68790 $encodingList = array_map('strtoupper', $encodingList);
68791
68792 foreach ($encodingList as $enc) {
68793 switch ($enc) {
68794 default:
68795 if (strncmp($enc, 'ISO-8859-', 9)) {
68796 return false;
68797 }
68798 case 'ASCII':
68799 case 'UTF8':
68800 case 'UTF-8':
68801 }
68802 }
68803
68804 self::$encodingList = $encodingList;
68805
68806 return true;
68807 }
68808
68809 public static function mb_strlen($s, $encoding = null)
68810 {
68811 $encoding = self::getEncoding($encoding);
68812 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68813 return strlen($s);
68814 }
68815
68816 return @iconv_strlen($s, $encoding);
68817 }
68818
68819 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
68820 {
68821 $encoding = self::getEncoding($encoding);
68822 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68823 return strpos($haystack, $needle, $offset);
68824 }
68825
68826 if ('' === $needle .= '') {
68827 trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
68828
68829 return false;
68830 }
68831
68832 return iconv_strpos($haystack, $needle, $offset, $encoding);
68833 }
68834
68835 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
68836 {
68837 $encoding = self::getEncoding($encoding);
68838 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68839 return strrpos($haystack, $needle, $offset);
68840 }
68841
68842 if ($offset != (int) $offset) {
68843 $offset = 0;
68844 } elseif ($offset = (int) $offset) {
68845 if ($offset < 0) {
68846 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
68847 $offset = 0;
68848 } else {
68849 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
68850 }
68851 }
68852
68853 $pos = iconv_strrpos($haystack, $needle, $encoding);
68854
68855 return false !== $pos ? $offset + $pos : false;
68856 }
68857
68858 public static function mb_strtolower($s, $encoding = null)
68859 {
68860 return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
68861 }
68862
68863 public static function mb_strtoupper($s, $encoding = null)
68864 {
68865 return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
68866 }
68867
68868 public static function mb_substitute_character($c = null)
68869 {
68870 if (0 === strcasecmp($c, 'none')) {
68871 return true;
68872 }
68873
68874 return null !== $c ? false : 'none';
68875 }
68876
68877 public static function mb_substr($s, $start, $length = null, $encoding = null)
68878 {
68879 $encoding = self::getEncoding($encoding);
68880 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68881 return substr($s, $start, null === $length ? 2147483647 : $length);
68882 }
68883
68884 if ($start < 0) {
68885 $start = iconv_strlen($s, $encoding) + $start;
68886 if ($start < 0) {
68887 $start = 0;
68888 }
68889 }
68890
68891 if (null === $length) {
68892 $length = 2147483647;
68893 } elseif ($length < 0) {
68894 $length = iconv_strlen($s, $encoding) + $length - $start;
68895 if ($length < 0) {
68896 return '';
68897 }
68898 }
68899
68900 return iconv_substr($s, $start, $length, $encoding).'';
68901 }
68902
68903 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
68904 {
68905 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
68906 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
68907
68908 return self::mb_strpos($haystack, $needle, $offset, $encoding);
68909 }
68910
68911 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
68912 {
68913 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
68914
68915 return self::getSubpart($pos, $part, $haystack, $encoding);
68916 }
68917
68918 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
68919 {
68920 $encoding = self::getEncoding($encoding);
68921 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68922 return strrchr($haystack, $needle, $part);
68923 }
68924 $needle = self::mb_substr($needle, 0, 1, $encoding);
68925 $pos = iconv_strrpos($haystack, $needle, $encoding);
68926
68927 return self::getSubpart($pos, $part, $haystack, $encoding);
68928 }
68929
68930 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
68931 {
68932 $needle = self::mb_substr($needle, 0, 1, $encoding);
68933 $pos = self::mb_strripos($haystack, $needle, $encoding);
68934
68935 return self::getSubpart($pos, $part, $haystack, $encoding);
68936 }
68937
68938 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
68939 {
68940 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
68941 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
68942
68943 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
68944 }
68945
68946 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
68947 {
68948 $pos = strpos($haystack, $needle);
68949 if (false === $pos) {
68950 return false;
68951 }
68952 if ($part) {
68953 return substr($haystack, 0, $pos);
68954 }
68955
68956 return substr($haystack, $pos);
68957 }
68958
68959 public static function mb_get_info($type = 'all')
68960 {
68961 $info = array(
68962 'internal_encoding' => self::$internalEncoding,
68963 'http_output' => 'pass',
68964 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
68965 'func_overload' => 0,
68966 'func_overload_list' => 'no overload',
68967 'mail_charset' => 'UTF-8',
68968 'mail_header_encoding' => 'BASE64',
68969 'mail_body_encoding' => 'BASE64',
68970 'illegal_chars' => 0,
68971 'encoding_translation' => 'Off',
68972 'language' => self::$language,
68973 'detect_order' => self::$encodingList,
68974 'substitute_character' => 'none',
68975 'strict_detection' => 'Off',
68976 );
68977
68978 if ('all' === $type) {
68979 return $info;
68980 }
68981 if (isset($info[$type])) {
68982 return $info[$type];
68983 }
68984
68985 return false;
68986 }
68987
68988 public static function mb_http_input($type = '')
68989 {
68990 return false;
68991 }
68992
68993 public static function mb_http_output($encoding = null)
68994 {
68995 return null !== $encoding ? 'pass' === $encoding : 'pass';
68996 }
68997
68998 public static function mb_strwidth($s, $encoding = null)
68999 {
69000 $encoding = self::getEncoding($encoding);
69001
69002 if ('UTF-8' !== $encoding) {
69003 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
69004 }
69005
69006 $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);
69007
69008 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
69009 }
69010
69011 public static function mb_substr_count($haystack, $needle, $encoding = null)
69012 {
69013 return substr_count($haystack, $needle);
69014 }
69015
69016 public static function mb_output_handler($contents, $status)
69017 {
69018 return $contents;
69019 }
69020
69021 public static function mb_chr($code, $encoding = null)
69022 {
69023 if (0x80 > $code %= 0x200000) {
69024 $s = chr($code);
69025 } elseif (0x800 > $code) {
69026 $s = chr(0xC0 | $code >> 6).chr(0x80 | $code & 0x3F);
69027 } elseif (0x10000 > $code) {
69028 $s = chr(0xE0 | $code >> 12).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
69029 } else {
69030 $s = chr(0xF0 | $code >> 18).chr(0x80 | $code >> 12 & 0x3F).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
69031 }
69032
69033 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
69034 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
69035 }
69036
69037 return $s;
69038 }
69039
69040 public static function mb_ord($s, $encoding = null)
69041 {
69042 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
69043 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
69044 }
69045
69046 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
69047 if (0xF0 <= $code) {
69048 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
69049 }
69050 if (0xE0 <= $code) {
69051 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
69052 }
69053 if (0xC0 <= $code) {
69054 return (($code - 0xC0) << 6) + $s[2] - 0x80;
69055 }
69056
69057 return $code;
69058 }
69059
69060 private static function getSubpart($pos, $part, $haystack, $encoding)
69061 {
69062 if (false === $pos) {
69063 return false;
69064 }
69065 if ($part) {
69066 return self::mb_substr($haystack, 0, $pos, $encoding);
69067 }
69068
69069 return self::mb_substr($haystack, $pos, null, $encoding);
69070 }
69071
69072 private static function html_encoding_callback($m)
69073 {
69074 $i = 1;
69075 $entities = '';
69076 $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
69077
69078 while (isset($m[$i])) {
69079 if (0x80 > $m[$i]) {
69080 $entities .= chr($m[$i++]);
69081 continue;
69082 }
69083 if (0xF0 <= $m[$i]) {
69084 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
69085 } elseif (0xE0 <= $m[$i]) {
69086 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
69087 } else {
69088 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
69089 }
69090
69091 $entities .= '&#'.$c.';';
69092 }
69093
69094 return $entities;
69095 }
69096
69097 private static function title_case_lower($s)
69098 {
69099 return self::mb_convert_case($s[0], MB_CASE_LOWER, 'UTF-8');
69100 }
69101
69102 private static function title_case_upper($s)
69103 {
69104 return self::mb_convert_case($s[0], MB_CASE_UPPER, 'UTF-8');
69105 }
69106
69107 private static function getData($file)
69108 {
69109 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
69110 return require $file;
69111 }
69112
69113 return false;
69114 }
69115
69116 private static function getEncoding($encoding)
69117 {
69118 if (null === $encoding) {
69119 return self::$internalEncoding;
69120 }
69121
69122 $encoding = strtoupper($encoding);
69123
69124 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
69125 return 'CP850';
69126 }
69127 if ('UTF8' === $encoding) {
69128 return 'UTF-8';
69129 }
69130
69131 return $encoding;
69132 }
69133 }
69134 <?php
69135
69136 static $data = array (
69137 'A' => 'a',
69138 'B' => 'b',
69139 'C' => 'c',
69140 'D' => 'd',
69141 'E' => 'e',
69142 'F' => 'f',
69143 'G' => 'g',
69144 'H' => 'h',
69145 'I' => 'i',
69146 'J' => 'j',
69147 'K' => 'k',
69148 'L' => 'l',
69149 'M' => 'm',
69150 'N' => 'n',
69151 'O' => 'o',
69152 'P' => 'p',
69153 'Q' => 'q',
69154 'R' => 'r',
69155 'S' => 's',
69156 'T' => 't',
69157 'U' => 'u',
69158 'V' => 'v',
69159 'W' => 'w',
69160 'X' => 'x',
69161 'Y' => 'y',
69162 'Z' => 'z',
69163 'À' => 'à',
69164 'Á' => 'á',
69165 'Â' => 'â',
69166 'Ã' => 'ã',
69167 'Ä' => 'ä',
69168 'Å' => 'å',
69169 'Æ' => 'æ',
69170 'Ç' => 'ç',
69171 'È' => 'è',
69172 'É' => 'é',
69173 'Ê' => 'ê',
69174 'Ë' => 'ë',
69175 'Ì' => 'ì',
69176 'Í' => 'í',
69177 'Î' => 'î',
69178 'Ï' => 'ï',
69179 'Ð' => 'ð',
69180 'Ñ' => 'ñ',
69181 'Ò' => 'ò',
69182 'Ó' => 'ó',
69183 'Ô' => 'ô',
69184 'Õ' => 'õ',
69185 'Ö' => 'ö',
69186 'Ø' => 'ø',
69187 'Ù' => 'ù',
69188 'Ú' => 'ú',
69189 'Û' => 'û',
69190 'Ü' => 'ü',
69191 'Ý' => 'ý',
69192 'Þ' => 'þ',
69193 'Ā' => 'ā',
69194 'Ă' => 'ă',
69195 'Ą' => 'ą',
69196 'Ć' => 'ć',
69197 'Ĉ' => 'ĉ',
69198 'Ċ' => 'ċ',
69199 'Č' => 'č',
69200 'Ď' => 'ď',
69201 'Đ' => 'đ',
69202 'Ē' => 'ē',
69203 'Ĕ' => 'ĕ',
69204 'Ė' => 'ė',
69205 'Ę' => 'ę',
69206 'Ě' => 'ě',
69207 'Ĝ' => 'ĝ',
69208 'Ğ' => 'ğ',
69209 'Ġ' => 'ġ',
69210 'Ģ' => 'ģ',
69211 'Ĥ' => 'ĥ',
69212 'Ħ' => 'ħ',
69213 'Ĩ' => 'ĩ',
69214 'Ī' => 'ī',
69215 'Ĭ' => 'ĭ',
69216 'Į' => 'į',
69217 'İ' => 'i',
69218 'IJ' => 'ij',
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 'Ź' => 'ź',
69254 'Ż' => 'ż',
69255 'Ž' => 'ž',
69256 'Ɓ' => 'ɓ',
69257 'Ƃ' => 'ƃ',
69258 'Ƅ' => 'ƅ',
69259 'Ɔ' => 'ɔ',
69260 'Ƈ' => 'ƈ',
69261 'Ɖ' => 'ɖ',
69262 'Ɗ' => 'ɗ',
69263 'Ƌ' => 'ƌ',
69264 'Ǝ' => 'ǝ',
69265 'Ə' => 'ə',
69266 'Ɛ' => 'ɛ',
69267 'Ƒ' => 'ƒ',
69268 'Ɠ' => 'ɠ',
69269 'Ɣ' => 'ɣ',
69270 'Ɩ' => 'ɩ',
69271 'Ɨ' => 'ɨ',
69272 'Ƙ' => 'ƙ',
69273 'Ɯ' => 'ɯ',
69274 'Ɲ' => 'ɲ',
69275 'Ɵ' => 'ɵ',
69276 'Ơ' => 'ơ',
69277 'Ƣ' => 'ƣ',
69278 'Ƥ' => 'ƥ',
69279 'Ʀ' => 'ʀ',
69280 'Ƨ' => 'ƨ',
69281 'Ʃ' => 'ʃ',
69282 'Ƭ' => 'ƭ',
69283 'Ʈ' => 'ʈ',
69284 'Ư' => 'ư',
69285 'Ʊ' => 'ʊ',
69286 'Ʋ' => 'ʋ',
69287 'Ƴ' => 'ƴ',
69288 'Ƶ' => 'ƶ',
69289 'Ʒ' => 'ʒ',
69290 'Ƹ' => 'ƹ',
69291 'Ƽ' => 'ƽ',
69292 'DŽ' => 'dž',
69293 'Dž' => 'dž',
69294 'LJ' => 'lj',
69295 'Lj' => 'lj',
69296 'NJ' => 'nj',
69297 'Nj' => 'nj',
69298 'Ǎ' => 'ǎ',
69299 'Ǐ' => 'ǐ',
69300 'Ǒ' => 'ǒ',
69301 'Ǔ' => 'ǔ',
69302 'Ǖ' => 'ǖ',
69303 'Ǘ' => 'ǘ',
69304 'Ǚ' => 'ǚ',
69305 'Ǜ' => 'ǜ',
69306 'Ǟ' => 'ǟ',
69307 'Ǡ' => 'ǡ',
69308 'Ǣ' => 'ǣ',
69309 'Ǥ' => 'ǥ',
69310 'Ǧ' => 'ǧ',
69311 'Ǩ' => 'ǩ',
69312 'Ǫ' => 'ǫ',
69313 'Ǭ' => 'ǭ',
69314 'Ǯ' => 'ǯ',
69315 'DZ' => 'dz',
69316 'Dz' => 'dz',
69317 'Ǵ' => 'ǵ',
69318 'Ƕ' => 'ƕ',
69319 'Ƿ' => 'ƿ',
69320 'Ǹ' => 'ǹ',
69321 'Ǻ' => 'ǻ',
69322 'Ǽ' => 'ǽ',
69323 'Ǿ' => 'ǿ',
69324 'Ȁ' => 'ȁ',
69325 'Ȃ' => 'ȃ',
69326 'Ȅ' => 'ȅ',
69327 'Ȇ' => 'ȇ',
69328 'Ȉ' => 'ȉ',
69329 'Ȋ' => 'ȋ',
69330 'Ȍ' => 'ȍ',
69331 'Ȏ' => 'ȏ',
69332 'Ȑ' => 'ȑ',
69333 'Ȓ' => 'ȓ',
69334 'Ȕ' => 'ȕ',
69335 'Ȗ' => 'ȗ',
69336 'Ș' => 'ș',
69337 'Ț' => 'ț',
69338 'Ȝ' => 'ȝ',
69339 'Ȟ' => 'ȟ',
69340 'Ƞ' => 'ƞ',
69341 'Ȣ' => 'ȣ',
69342 'Ȥ' => 'ȥ',
69343 'Ȧ' => 'ȧ',
69344 'Ȩ' => 'ȩ',
69345 'Ȫ' => 'ȫ',
69346 'Ȭ' => 'ȭ',
69347 'Ȯ' => 'ȯ',
69348 'Ȱ' => 'ȱ',
69349 'Ȳ' => 'ȳ',
69350 'Ⱥ' => 'ⱥ',
69351 'Ȼ' => 'ȼ',
69352 'Ƚ' => 'ƚ',
69353 'Ⱦ' => 'ⱦ',
69354 'Ɂ' => 'ɂ',
69355 'Ƀ' => 'ƀ',
69356 'Ʉ' => 'ʉ',
69357 'Ʌ' => 'ʌ',
69358 'Ɇ' => 'ɇ',
69359 'Ɉ' => 'ɉ',
69360 'Ɋ' => 'ɋ',
69361 'Ɍ' => 'ɍ',
69362 'Ɏ' => 'ɏ',
69363 'Ͱ' => 'ͱ',
69364 'Ͳ' => 'ͳ',
69365 'Ͷ' => 'ͷ',
69366 'Ϳ' => 'ϳ',
69367 'Ά' => 'ά',
69368 'Έ' => 'έ',
69369 'Ή' => 'ή',
69370 'Ί' => 'ί',
69371 'Ό' => 'ό',
69372 'Ύ' => 'ύ',
69373 'Ώ' => 'ώ',
69374 'Α' => 'α',
69375 'Β' => 'β',
69376 'Γ' => 'γ',
69377 'Δ' => 'δ',
69378 'Ε' => 'ε',
69379 'Ζ' => 'ζ',
69380 'Η' => 'η',
69381 'Θ' => 'θ',
69382 'Ι' => 'ι',
69383 'Κ' => 'κ',
69384 'Λ' => 'λ',
69385 'Μ' => 'μ',
69386 'Ν' => 'ν',
69387 'Ξ' => 'ξ',
69388 'Ο' => 'ο',
69389 'Π' => 'π',
69390 'Ρ' => 'ρ',
69391 'Σ' => 'σ',
69392 'Τ' => 'τ',
69393 'Υ' => 'υ',
69394 'Φ' => 'φ',
69395 'Χ' => 'χ',
69396 'Ψ' => 'ψ',
69397 'Ω' => 'ω',
69398 'Ϊ' => 'ϊ',
69399 'Ϋ' => 'ϋ',
69400 'Ϗ' => 'ϗ',
69401 'Ϙ' => 'ϙ',
69402 'Ϛ' => 'ϛ',
69403 'Ϝ' => 'ϝ',
69404 'Ϟ' => 'ϟ',
69405 'Ϡ' => 'ϡ',
69406 'Ϣ' => 'ϣ',
69407 'Ϥ' => 'ϥ',
69408 'Ϧ' => 'ϧ',
69409 'Ϩ' => 'ϩ',
69410 'Ϫ' => 'ϫ',
69411 'Ϭ' => 'ϭ',
69412 'Ϯ' => 'ϯ',
69413 'ϴ' => 'θ',
69414 'Ϸ' => 'ϸ',
69415 'Ϲ' => 'ϲ',
69416 'Ϻ' => 'ϻ',
69417 'Ͻ' => 'ͻ',
69418 'Ͼ' => 'ͼ',
69419 'Ͽ' => 'ͽ',
69420 'Ѐ' => 'ѐ',
69421 'Ё' => 'ё',
69422 'Ђ' => 'ђ',
69423 'Ѓ' => 'ѓ',
69424 'Є' => 'є',
69425 'Ѕ' => 'ѕ',
69426 'І' => 'і',
69427 'Ї' => 'ї',
69428 'Ј' => 'ј',
69429 'Љ' => 'љ',
69430 'Њ' => 'њ',
69431 'Ћ' => 'ћ',
69432 'Ќ' => 'ќ',
69433 'Ѝ' => 'ѝ',
69434 'Ў' => 'ў',
69435 'Џ' => 'џ',
69436 'А' => 'а',
69437 'Б' => 'б',
69438 'В' => 'в',
69439 'Г' => 'г',
69440 'Д' => 'д',
69441 'Е' => 'е',
69442 'Ж' => 'ж',
69443 'З' => 'з',
69444 'И' => 'и',
69445 'Й' => 'й',
69446 'К' => 'к',
69447 'Л' => 'л',
69448 'М' => 'м',
69449 'Н' => 'н',
69450 'О' => 'о',
69451 'П' => 'п',
69452 'Р' => 'р',
69453 'С' => 'с',
69454 'Т' => 'т',
69455 'У' => 'у',
69456 'Ф' => 'ф',
69457 'Х' => 'х',
69458 'Ц' => 'ц',
69459 'Ч' => 'ч',
69460 'Ш' => 'ш',
69461 'Щ' => 'щ',
69462 'Ъ' => 'ъ',
69463 'Ы' => 'ы',
69464 'Ь' => 'ь',
69465 'Э' => 'э',
69466 'Ю' => 'ю',
69467 'Я' => 'я',
69468 'Ѡ' => 'ѡ',
69469 'Ѣ' => 'ѣ',
69470 'Ѥ' => 'ѥ',
69471 'Ѧ' => 'ѧ',
69472 'Ѩ' => 'ѩ',
69473 'Ѫ' => 'ѫ',
69474 'Ѭ' => 'ѭ',
69475 'Ѯ' => 'ѯ',
69476 'Ѱ' => 'ѱ',
69477 'Ѳ' => 'ѳ',
69478 'Ѵ' => 'ѵ',
69479 'Ѷ' => 'ѷ',
69480 'Ѹ' => 'ѹ',
69481 'Ѻ' => 'ѻ',
69482 'Ѽ' => 'ѽ',
69483 'Ѿ' => 'ѿ',
69484 'Ҁ' => 'ҁ',
69485 'Ҋ' => 'ҋ',
69486 'Ҍ' => 'ҍ',
69487 'Ҏ' => 'ҏ',
69488 'Ґ' => 'ґ',
69489 'Ғ' => 'ғ',
69490 'Ҕ' => 'ҕ',
69491 'Җ' => 'җ',
69492 'Ҙ' => 'ҙ',
69493 'Қ' => 'қ',
69494 'Ҝ' => 'ҝ',
69495 'Ҟ' => 'ҟ',
69496 'Ҡ' => 'ҡ',
69497 'Ң' => 'ң',
69498 'Ҥ' => 'ҥ',
69499 'Ҧ' => 'ҧ',
69500 'Ҩ' => 'ҩ',
69501 'Ҫ' => 'ҫ',
69502 'Ҭ' => 'ҭ',
69503 'Ү' => 'ү',
69504 'Ұ' => 'ұ',
69505 'Ҳ' => 'ҳ',
69506 'Ҵ' => 'ҵ',
69507 'Ҷ' => 'ҷ',
69508 'Ҹ' => 'ҹ',
69509 'Һ' => 'һ',
69510 'Ҽ' => 'ҽ',
69511 'Ҿ' => 'ҿ',
69512 'Ӏ' => 'ӏ',
69513 'Ӂ' => 'ӂ',
69514 'Ӄ' => 'ӄ',
69515 'Ӆ' => 'ӆ',
69516 'Ӈ' => 'ӈ',
69517 'Ӊ' => 'ӊ',
69518 'Ӌ' => 'ӌ',
69519 'Ӎ' => 'ӎ',
69520 'Ӑ' => 'ӑ',
69521 'Ӓ' => 'ӓ',
69522 'Ӕ' => 'ӕ',
69523 'Ӗ' => 'ӗ',
69524 'Ә' => 'ә',
69525 'Ӛ' => 'ӛ',
69526 'Ӝ' => 'ӝ',
69527 'Ӟ' => 'ӟ',
69528 'Ӡ' => 'ӡ',
69529 'Ӣ' => 'ӣ',
69530 'Ӥ' => 'ӥ',
69531 'Ӧ' => 'ӧ',
69532 'Ө' => 'ө',
69533 'Ӫ' => 'ӫ',
69534 'Ӭ' => 'ӭ',
69535 'Ӯ' => 'ӯ',
69536 'Ӱ' => 'ӱ',
69537 'Ӳ' => 'ӳ',
69538 'Ӵ' => 'ӵ',
69539 'Ӷ' => 'ӷ',
69540 'Ӹ' => 'ӹ',
69541 'Ӻ' => 'ӻ',
69542 'Ӽ' => 'ӽ',
69543 'Ӿ' => 'ӿ',
69544 'Ԁ' => 'ԁ',
69545 'Ԃ' => 'ԃ',
69546 'Ԅ' => 'ԅ',
69547 'Ԇ' => 'ԇ',
69548 'Ԉ' => 'ԉ',
69549 'Ԋ' => 'ԋ',
69550 'Ԍ' => 'ԍ',
69551 'Ԏ' => 'ԏ',
69552 'Ԑ' => 'ԑ',
69553 'Ԓ' => 'ԓ',
69554 'Ԕ' => 'ԕ',
69555 'Ԗ' => 'ԗ',
69556 'Ԙ' => 'ԙ',
69557 'Ԛ' => 'ԛ',
69558 'Ԝ' => 'ԝ',
69559 'Ԟ' => 'ԟ',
69560 'Ԡ' => 'ԡ',
69561 'Ԣ' => 'ԣ',
69562 'Ԥ' => 'ԥ',
69563 'Ԧ' => 'ԧ',
69564 'Ԩ' => 'ԩ',
69565 'Ԫ' => 'ԫ',
69566 'Ԭ' => 'ԭ',
69567 'Ԯ' => 'ԯ',
69568 'Ա' => 'ա',
69569 'Բ' => 'բ',
69570 'Գ' => 'գ',
69571 'Դ' => 'դ',
69572 'Ե' => 'ե',
69573 'Զ' => 'զ',
69574 'Է' => 'է',
69575 'Ը' => 'ը',
69576 'Թ' => 'թ',
69577 'Ժ' => 'ժ',
69578 'Ի' => 'ի',
69579 'Լ' => 'լ',
69580 'Խ' => 'խ',
69581 'Ծ' => 'ծ',
69582 'Կ' => 'կ',
69583 'Հ' => 'հ',
69584 'Ձ' => 'ձ',
69585 'Ղ' => 'ղ',
69586 'Ճ' => 'ճ',
69587 'Մ' => 'մ',
69588 'Յ' => 'յ',
69589 'Ն' => 'ն',
69590 'Շ' => 'շ',
69591 'Ո' => 'ո',
69592 'Չ' => 'չ',
69593 'Պ' => 'պ',
69594 'Ջ' => 'ջ',
69595 'Ռ' => 'ռ',
69596 'Ս' => 'ս',
69597 'Վ' => 'վ',
69598 'Տ' => 'տ',
69599 'Ր' => 'ր',
69600 'Ց' => 'ց',
69601 'Ւ' => 'ւ',
69602 'Փ' => 'փ',
69603 'Ք' => 'ք',
69604 'Օ' => 'օ',
69605 'Ֆ' => 'ֆ',
69606 'Ⴀ' => 'ⴀ',
69607 'Ⴁ' => 'ⴁ',
69608 'Ⴂ' => 'ⴂ',
69609 'Ⴃ' => 'ⴃ',
69610 'Ⴄ' => 'ⴄ',
69611 'Ⴅ' => 'ⴅ',
69612 'Ⴆ' => 'ⴆ',
69613 'Ⴇ' => 'ⴇ',
69614 'Ⴈ' => 'ⴈ',
69615 'Ⴉ' => 'ⴉ',
69616 'Ⴊ' => 'ⴊ',
69617 'Ⴋ' => 'ⴋ',
69618 'Ⴌ' => 'ⴌ',
69619 'Ⴍ' => 'ⴍ',
69620 'Ⴎ' => 'ⴎ',
69621 'Ⴏ' => 'ⴏ',
69622 'Ⴐ' => 'ⴐ',
69623 'Ⴑ' => 'ⴑ',
69624 'Ⴒ' => 'ⴒ',
69625 'Ⴓ' => 'ⴓ',
69626 'Ⴔ' => 'ⴔ',
69627 'Ⴕ' => 'ⴕ',
69628 'Ⴖ' => 'ⴖ',
69629 'Ⴗ' => 'ⴗ',
69630 'Ⴘ' => 'ⴘ',
69631 'Ⴙ' => 'ⴙ',
69632 'Ⴚ' => 'ⴚ',
69633 'Ⴛ' => 'ⴛ',
69634 'Ⴜ' => 'ⴜ',
69635 'Ⴝ' => 'ⴝ',
69636 'Ⴞ' => 'ⴞ',
69637 'Ⴟ' => 'ⴟ',
69638 'Ⴠ' => 'ⴠ',
69639 'Ⴡ' => 'ⴡ',
69640 'Ⴢ' => 'ⴢ',
69641 'Ⴣ' => 'ⴣ',
69642 'Ⴤ' => 'ⴤ',
69643 'Ⴥ' => 'ⴥ',
69644 'Ⴧ' => 'ⴧ',
69645 'Ⴭ' => 'ⴭ',
69646 'Ḁ' => 'ḁ',
69647 'Ḃ' => 'ḃ',
69648 'Ḅ' => 'ḅ',
69649 'Ḇ' => 'ḇ',
69650 'Ḉ' => 'ḉ',
69651 'Ḋ' => 'ḋ',
69652 'Ḍ' => 'ḍ',
69653 'Ḏ' => 'ḏ',
69654 'Ḑ' => 'ḑ',
69655 'Ḓ' => 'ḓ',
69656 'Ḕ' => 'ḕ',
69657 'Ḗ' => 'ḗ',
69658 'Ḙ' => 'ḙ',
69659 'Ḛ' => 'ḛ',
69660 'Ḝ' => 'ḝ',
69661 'Ḟ' => 'ḟ',
69662 'Ḡ' => 'ḡ',
69663 'Ḣ' => 'ḣ',
69664 'Ḥ' => 'ḥ',
69665 'Ḧ' => 'ḧ',
69666 'Ḩ' => 'ḩ',
69667 'Ḫ' => 'ḫ',
69668 'Ḭ' => 'ḭ',
69669 'Ḯ' => 'ḯ',
69670 'Ḱ' => 'ḱ',
69671 'Ḳ' => 'ḳ',
69672 'Ḵ' => 'ḵ',
69673 'Ḷ' => 'ḷ',
69674 'Ḹ' => 'ḹ',
69675 'Ḻ' => 'ḻ',
69676 'Ḽ' => 'ḽ',
69677 'Ḿ' => 'ḿ',
69678 'Ṁ' => 'ṁ',
69679 'Ṃ' => 'ṃ',
69680 'Ṅ' => 'ṅ',
69681 'Ṇ' => 'ṇ',
69682 'Ṉ' => 'ṉ',
69683 'Ṋ' => 'ṋ',
69684 'Ṍ' => 'ṍ',
69685 'Ṏ' => 'ṏ',
69686 'Ṑ' => 'ṑ',
69687 'Ṓ' => 'ṓ',
69688 'Ṕ' => 'ṕ',
69689 'Ṗ' => 'ṗ',
69690 'Ṙ' => 'ṙ',
69691 'Ṛ' => 'ṛ',
69692 'Ṝ' => 'ṝ',
69693 'Ṟ' => 'ṟ',
69694 'Ṡ' => 'ṡ',
69695 'Ṣ' => 'ṣ',
69696 'Ṥ' => 'ṥ',
69697 'Ṧ' => 'ṧ',
69698 'Ṩ' => 'ṩ',
69699 'Ṫ' => 'ṫ',
69700 'Ṭ' => 'ṭ',
69701 'Ṯ' => 'ṯ',
69702 'Ṱ' => 'ṱ',
69703 'Ṳ' => 'ṳ',
69704 'Ṵ' => 'ṵ',
69705 'Ṷ' => 'ṷ',
69706 'Ṹ' => 'ṹ',
69707 'Ṻ' => 'ṻ',
69708 'Ṽ' => 'ṽ',
69709 'Ṿ' => 'ṿ',
69710 'Ẁ' => 'ẁ',
69711 'Ẃ' => 'ẃ',
69712 'Ẅ' => 'ẅ',
69713 'Ẇ' => 'ẇ',
69714 'Ẉ' => 'ẉ',
69715 'Ẋ' => 'ẋ',
69716 'Ẍ' => 'ẍ',
69717 'Ẏ' => 'ẏ',
69718 'Ẑ' => 'ẑ',
69719 'Ẓ' => 'ẓ',
69720 'Ẕ' => 'ẕ',
69721 'ẞ' => 'ß',
69722 'Ạ' => 'ạ',
69723 'Ả' => 'ả',
69724 'Ấ' => 'ấ',
69725 'Ầ' => 'ầ',
69726 'Ẩ' => 'ẩ',
69727 'Ẫ' => 'ẫ',
69728 'Ậ' => 'ậ',
69729 'Ắ' => 'ắ',
69730 'Ằ' => 'ằ',
69731 'Ẳ' => 'ẳ',
69732 'Ẵ' => 'ẵ',
69733 'Ặ' => 'ặ',
69734 'Ẹ' => 'ẹ',
69735 'Ẻ' => 'ẻ',
69736 'Ẽ' => 'ẽ',
69737 'Ế' => 'ế',
69738 'Ề' => 'ề',
69739 'Ể' => 'ể',
69740 'Ễ' => 'ễ',
69741 'Ệ' => 'ệ',
69742 'Ỉ' => 'ỉ',
69743 'Ị' => 'ị',
69744 'Ọ' => 'ọ',
69745 'Ỏ' => 'ỏ',
69746 'Ố' => 'ố',
69747 'Ồ' => 'ồ',
69748 'Ổ' => 'ổ',
69749 'Ỗ' => 'ỗ',
69750 'Ộ' => 'ộ',
69751 'Ớ' => 'ớ',
69752 'Ờ' => 'ờ',
69753 'Ở' => 'ở',
69754 'Ỡ' => 'ỡ',
69755 'Ợ' => 'ợ',
69756 'Ụ' => 'ụ',
69757 'Ủ' => 'ủ',
69758 'Ứ' => 'ứ',
69759 'Ừ' => 'ừ',
69760 'Ử' => 'ử',
69761 'Ữ' => 'ữ',
69762 'Ự' => 'ự',
69763 'Ỳ' => 'ỳ',
69764 'Ỵ' => 'ỵ',
69765 'Ỷ' => 'ỷ',
69766 'Ỹ' => 'ỹ',
69767 'Ỻ' => 'ỻ',
69768 'Ỽ' => 'ỽ',
69769 'Ỿ' => 'ỿ',
69770 'Ἀ' => 'ἀ',
69771 'Ἁ' => 'ἁ',
69772 'Ἂ' => 'ἂ',
69773 'Ἃ' => 'ἃ',
69774 'Ἄ' => 'ἄ',
69775 'Ἅ' => 'ἅ',
69776 'Ἆ' => 'ἆ',
69777 'Ἇ' => 'ἇ',
69778 'Ἐ' => 'ἐ',
69779 'Ἑ' => 'ἑ',
69780 'Ἒ' => 'ἒ',
69781 'Ἓ' => 'ἓ',
69782 'Ἔ' => 'ἔ',
69783 'Ἕ' => 'ἕ',
69784 'Ἠ' => 'ἠ',
69785 'Ἡ' => 'ἡ',
69786 'Ἢ' => 'ἢ',
69787 'Ἣ' => 'ἣ',
69788 'Ἤ' => 'ἤ',
69789 'Ἥ' => 'ἥ',
69790 'Ἦ' => 'ἦ',
69791 'Ἧ' => 'ἧ',
69792 'Ἰ' => 'ἰ',
69793 'Ἱ' => 'ἱ',
69794 'Ἲ' => 'ἲ',
69795 'Ἳ' => 'ἳ',
69796 'Ἴ' => 'ἴ',
69797 'Ἵ' => 'ἵ',
69798 'Ἶ' => 'ἶ',
69799 'Ἷ' => 'ἷ',
69800 'Ὀ' => 'ὀ',
69801 'Ὁ' => 'ὁ',
69802 'Ὂ' => 'ὂ',
69803 'Ὃ' => 'ὃ',
69804 'Ὄ' => 'ὄ',
69805 'Ὅ' => 'ὅ',
69806 'Ὑ' => 'ὑ',
69807 'Ὓ' => 'ὓ',
69808 'Ὕ' => 'ὕ',
69809 'Ὗ' => 'ὗ',
69810 'Ὠ' => 'ὠ',
69811 'Ὡ' => 'ὡ',
69812 'Ὢ' => 'ὢ',
69813 'Ὣ' => 'ὣ',
69814 'Ὤ' => 'ὤ',
69815 'Ὥ' => 'ὥ',
69816 'Ὦ' => 'ὦ',
69817 'Ὧ' => 'ὧ',
69818 'ᾈ' => 'ᾀ',
69819 'ᾉ' => 'ᾁ',
69820 'ᾊ' => 'ᾂ',
69821 'ᾋ' => 'ᾃ',
69822 'ᾌ' => 'ᾄ',
69823 'ᾍ' => 'ᾅ',
69824 'ᾎ' => 'ᾆ',
69825 'ᾏ' => 'ᾇ',
69826 'ᾘ' => 'ᾐ',
69827 'ᾙ' => 'ᾑ',
69828 'ᾚ' => 'ᾒ',
69829 'ᾛ' => 'ᾓ',
69830 'ᾜ' => 'ᾔ',
69831 'ᾝ' => 'ᾕ',
69832 'ᾞ' => 'ᾖ',
69833 'ᾟ' => 'ᾗ',
69834 'ᾨ' => 'ᾠ',
69835 'ᾩ' => 'ᾡ',
69836 'ᾪ' => 'ᾢ',
69837 'ᾫ' => 'ᾣ',
69838 'ᾬ' => 'ᾤ',
69839 'ᾭ' => 'ᾥ',
69840 'ᾮ' => 'ᾦ',
69841 'ᾯ' => 'ᾧ',
69842 'Ᾰ' => 'ᾰ',
69843 'Ᾱ' => 'ᾱ',
69844 'Ὰ' => 'ὰ',
69845 'Ά' => 'ά',
69846 'ᾼ' => 'ᾳ',
69847 'Ὲ' => 'ὲ',
69848 'Έ' => 'έ',
69849 'Ὴ' => 'ὴ',
69850 'Ή' => 'ή',
69851 'ῌ' => 'ῃ',
69852 'Ῐ' => 'ῐ',
69853 'Ῑ' => 'ῑ',
69854 'Ὶ' => 'ὶ',
69855 'Ί' => 'ί',
69856 'Ῠ' => 'ῠ',
69857 'Ῡ' => 'ῡ',
69858 'Ὺ' => 'ὺ',
69859 'Ύ' => 'ύ',
69860 'Ῥ' => 'ῥ',
69861 'Ὸ' => 'ὸ',
69862 'Ό' => 'ό',
69863 'Ὼ' => 'ὼ',
69864 'Ώ' => 'ώ',
69865 'ῼ' => 'ῳ',
69866 'Ω' => 'ω',
69867 'K' => 'k',
69868 'Å' => 'å',
69869 'Ⅎ' => 'ⅎ',
69870 'Ⅰ' => 'ⅰ',
69871 'Ⅱ' => 'ⅱ',
69872 'Ⅲ' => 'ⅲ',
69873 'Ⅳ' => 'ⅳ',
69874 'Ⅴ' => 'ⅴ',
69875 'Ⅵ' => 'ⅵ',
69876 'Ⅶ' => 'ⅶ',
69877 'Ⅷ' => 'ⅷ',
69878 'Ⅸ' => 'ⅸ',
69879 'Ⅹ' => 'ⅹ',
69880 'Ⅺ' => 'ⅺ',
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 'Ⱆ' => 'ⱆ',
69936 'Ⱇ' => 'ⱇ',
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 'Ⳇ' => 'ⳇ',
70011 'Ⳉ' => 'ⳉ',
70012 'Ⳋ' => 'ⳋ',
70013 'Ⳍ' => 'ⳍ',
70014 'Ⳏ' => 'ⳏ',
70015 'Ⳑ' => 'ⳑ',
70016 'Ⳓ' => 'ⳓ',
70017 'Ⳕ' => 'ⳕ',
70018 'Ⳗ' => 'ⳗ',
70019 'Ⳙ' => 'ⳙ',
70020 'Ⳛ' => 'ⳛ',
70021 'Ⳝ' => 'ⳝ',
70022 'Ⳟ' => 'ⳟ',
70023 'Ⳡ' => 'ⳡ',
70024 'Ⳣ' => 'ⳣ',
70025 'Ⳬ' => 'ⳬ',
70026 'Ⳮ' => 'ⳮ',
70027 'Ⳳ' => 'ⳳ',
70028 'Ꙁ' => 'ꙁ',
70029 'Ꙃ' => 'ꙃ',
70030 'Ꙅ' => 'ꙅ',
70031 'Ꙇ' => 'ꙇ',
70032 'Ꙉ' => 'ꙉ',
70033 'Ꙋ' => 'ꙋ',
70034 'Ꙍ' => 'ꙍ',
70035 'Ꙏ' => 'ꙏ',
70036 'Ꙑ' => 'ꙑ',
70037 'Ꙓ' => 'ꙓ',
70038 'Ꙕ' => 'ꙕ',
70039 'Ꙗ' => 'ꙗ',
70040 'Ꙙ' => 'ꙙ',
70041 'Ꙛ' => 'ꙛ',
70042 'Ꙝ' => 'ꙝ',
70043 'Ꙟ' => 'ꙟ',
70044 'Ꙡ' => 'ꙡ',
70045 'Ꙣ' => 'ꙣ',
70046 'Ꙥ' => 'ꙥ',
70047 'Ꙧ' => 'ꙧ',
70048 'Ꙩ' => 'ꙩ',
70049 'Ꙫ' => 'ꙫ',
70050 'Ꙭ' => 'ꙭ',
70051 'Ꚁ' => 'ꚁ',
70052 'Ꚃ' => 'ꚃ',
70053 'Ꚅ' => 'ꚅ',
70054 'Ꚇ' => 'ꚇ',
70055 'Ꚉ' => 'ꚉ',
70056 'Ꚋ' => 'ꚋ',
70057 'Ꚍ' => 'ꚍ',
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 'A' => 'a',
70132 'B' => 'b',
70133 'C' => 'c',
70134 'D' => 'd',
70135 'E' => 'e',
70136 'F' => 'f',
70137 'G' => 'g',
70138 'H' => 'h',
70139 'I' => 'i',
70140 'J' => 'j',
70141 'K' => 'k',
70142 'L' => 'l',
70143 'M' => 'm',
70144 'N' => 'n',
70145 'O' => 'o',
70146 'P' => 'p',
70147 'Q' => 'q',
70148 'R' => 'r',
70149 'S' => 's',
70150 'T' => 't',
70151 'U' => 'u',
70152 'V' => 'v',
70153 'W' => 'w',
70154 'X' => 'x',
70155 'Y' => 'y',
70156 'Z' => 'z',
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 $result =& $data;
70232 unset($data);
70233
70234 return $result;
70235 <?php
70236
70237 static $data = array (
70238 'a' => 'A',
70239 'b' => 'B',
70240 'c' => 'C',
70241 'd' => 'D',
70242 'e' => 'E',
70243 'f' => 'F',
70244 'g' => 'G',
70245 'h' => 'H',
70246 'i' => 'I',
70247 'j' => 'J',
70248 'k' => 'K',
70249 'l' => 'L',
70250 'm' => 'M',
70251 'n' => 'N',
70252 'o' => 'O',
70253 'p' => 'P',
70254 'q' => 'Q',
70255 'r' => 'R',
70256 's' => 'S',
70257 't' => 'T',
70258 'u' => 'U',
70259 'v' => 'V',
70260 'w' => 'W',
70261 'x' => 'X',
70262 'y' => 'Y',
70263 'z' => 'Z',
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 'ı' => 'I',
70321 'ij' => 'IJ',
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 'ſ' => 'S',
70359 'ƀ' => 'Ƀ',
70360 'ƃ' => 'Ƃ',
70361 'ƅ' => 'Ƅ',
70362 'ƈ' => 'Ƈ',
70363 'ƌ' => 'Ƌ',
70364 'ƒ' => 'Ƒ',
70365 'ƕ' => 'Ƕ',
70366 'ƙ' => 'Ƙ',
70367 'ƚ' => 'Ƚ',
70368 'ƞ' => 'Ƞ',
70369 'ơ' => 'Ơ',
70370 'ƣ' => 'Ƣ',
70371 'ƥ' => 'Ƥ',
70372 'ƨ' => 'Ƨ',
70373 'ƭ' => 'Ƭ',
70374 'ư' => 'Ư',
70375 'ƴ' => 'Ƴ',
70376 'ƶ' => 'Ƶ',
70377 'ƹ' => 'Ƹ',
70378 'ƽ' => 'Ƽ',
70379 'ƿ' => 'Ƿ',
70380 'Dž' => 'DŽ',
70381 'dž' => 'DŽ',
70382 'Lj' => 'LJ',
70383 'lj' => 'LJ',
70384 'Nj' => 'NJ',
70385 'nj' => 'NJ',
70386 'ǎ' => 'Ǎ',
70387 'ǐ' => 'Ǐ',
70388 'ǒ' => 'Ǒ',
70389 'ǔ' => 'Ǔ',
70390 'ǖ' => 'Ǖ',
70391 'ǘ' => 'Ǘ',
70392 'ǚ' => 'Ǚ',
70393 'ǜ' => 'Ǜ',
70394 'ǝ' => 'Ǝ',
70395 'ǟ' => 'Ǟ',
70396 'ǡ' => 'Ǡ',
70397 'ǣ' => 'Ǣ',
70398 'ǥ' => 'Ǥ',
70399 'ǧ' => 'Ǧ',
70400 'ǩ' => 'Ǩ',
70401 'ǫ' => 'Ǫ',
70402 'ǭ' => 'Ǭ',
70403 'ǯ' => 'Ǯ',
70404 'Dz' => 'DZ',
70405 'dz' => 'DZ',
70406 'ǵ' => 'Ǵ',
70407 'ǹ' => 'Ǹ',
70408 'ǻ' => 'Ǻ',
70409 'ǽ' => 'Ǽ',
70410 'ǿ' => 'Ǿ',
70411 'ȁ' => 'Ȁ',
70412 'ȃ' => 'Ȃ',
70413 'ȅ' => 'Ȅ',
70414 'ȇ' => 'Ȇ',
70415 'ȉ' => 'Ȉ',
70416 'ȋ' => 'Ȋ',
70417 'ȍ' => 'Ȍ',
70418 'ȏ' => 'Ȏ',
70419 'ȑ' => 'Ȑ',
70420 'ȓ' => 'Ȓ',
70421 'ȕ' => 'Ȕ',
70422 'ȗ' => 'Ȗ',
70423 'ș' => 'Ș',
70424 'ț' => 'Ț',
70425 'ȝ' => 'Ȝ',
70426 'ȟ' => 'Ȟ',
70427 'ȣ' => 'Ȣ',
70428 'ȥ' => 'Ȥ',
70429 'ȧ' => 'Ȧ',
70430 'ȩ' => 'Ȩ',
70431 'ȫ' => 'Ȫ',
70432 'ȭ' => 'Ȭ',
70433 'ȯ' => 'Ȯ',
70434 'ȱ' => 'Ȱ',
70435 'ȳ' => 'Ȳ',
70436 'ȼ' => 'Ȼ',
70437 'ȿ' => 'Ȿ',
70438 'ɀ' => 'Ɀ',
70439 'ɂ' => 'Ɂ',
70440 'ɇ' => 'Ɇ',
70441 'ɉ' => 'Ɉ',
70442 'ɋ' => 'Ɋ',
70443 'ɍ' => 'Ɍ',
70444 'ɏ' => 'Ɏ',
70445 'ɐ' => 'Ɐ',
70446 'ɑ' => 'Ɑ',
70447 'ɒ' => 'Ɒ',
70448 'ɓ' => 'Ɓ',
70449 'ɔ' => 'Ɔ',
70450 'ɖ' => 'Ɖ',
70451 'ɗ' => 'Ɗ',
70452 'ə' => 'Ə',
70453 'ɛ' => 'Ɛ',
70454 'ɜ' => 'Ɜ',
70455 'ɠ' => 'Ɠ',
70456 'ɡ' => 'Ɡ',
70457 'ɣ' => 'Ɣ',
70458 'ɥ' => 'Ɥ',
70459 'ɦ' => 'Ɦ',
70460 'ɨ' => 'Ɨ',
70461 'ɩ' => 'Ɩ',
70462 'ɫ' => 'Ɫ',
70463 'ɬ' => 'Ɬ',
70464 'ɯ' => 'Ɯ',
70465 'ɱ' => 'Ɱ',
70466 'ɲ' => 'Ɲ',
70467 'ɵ' => 'Ɵ',
70468 'ɽ' => 'Ɽ',
70469 'ʀ' => 'Ʀ',
70470 'ʃ' => 'Ʃ',
70471 'ʇ' => 'Ʇ',
70472 'ʈ' => 'Ʈ',
70473 'ʉ' => 'Ʉ',
70474 'ʊ' => 'Ʊ',
70475 'ʋ' => 'Ʋ',
70476 'ʌ' => 'Ʌ',
70477 'ʒ' => 'Ʒ',
70478 'ʞ' => 'Ʞ',
70479 'ͅ' => 'Ι',
70480 'ͱ' => 'Ͱ',
70481 'ͳ' => 'Ͳ',
70482 'ͷ' => 'Ͷ',
70483 'ͻ' => 'Ͻ',
70484 'ͼ' => 'Ͼ',
70485 'ͽ' => 'Ͽ',
70486 'ά' => 'Ά',
70487 'έ' => 'Έ',
70488 'ή' => 'Ή',
70489 'ί' => 'Ί',
70490 'α' => 'Α',
70491 'β' => 'Β',
70492 'γ' => 'Γ',
70493 'δ' => 'Δ',
70494 'ε' => 'Ε',
70495 'ζ' => 'Ζ',
70496 'η' => 'Η',
70497 'θ' => 'Θ',
70498 'ι' => 'Ι',
70499 'κ' => 'Κ',
70500 'λ' => 'Λ',
70501 'μ' => 'Μ',
70502 'ν' => 'Ν',
70503 'ξ' => 'Ξ',
70504 'ο' => 'Ο',
70505 'π' => 'Π',
70506 'ρ' => 'Ρ',
70507 'ς' => 'Σ',
70508 'σ' => 'Σ',
70509 'τ' => 'Τ',
70510 'υ' => 'Υ',
70511 'φ' => 'Φ',
70512 'χ' => 'Χ',
70513 'ψ' => 'Ψ',
70514 'ω' => 'Ω',
70515 'ϊ' => 'Ϊ',
70516 'ϋ' => 'Ϋ',
70517 'ό' => 'Ό',
70518 'ύ' => 'Ύ',
70519 'ώ' => 'Ώ',
70520 'ϐ' => 'Β',
70521 'ϑ' => 'Θ',
70522 'ϕ' => 'Φ',
70523 'ϖ' => 'Π',
70524 'ϗ' => 'Ϗ',
70525 'ϙ' => 'Ϙ',
70526 'ϛ' => 'Ϛ',
70527 'ϝ' => 'Ϝ',
70528 'ϟ' => 'Ϟ',
70529 'ϡ' => 'Ϡ',
70530 'ϣ' => 'Ϣ',
70531 'ϥ' => 'Ϥ',
70532 'ϧ' => 'Ϧ',
70533 'ϩ' => 'Ϩ',
70534 'ϫ' => 'Ϫ',
70535 'ϭ' => 'Ϭ',
70536 'ϯ' => 'Ϯ',
70537 'ϰ' => 'Κ',
70538 'ϱ' => 'Ρ',
70539 'ϲ' => 'Ϲ',
70540 'ϳ' => 'Ϳ',
70541 'ϵ' => 'Ε',
70542 'ϸ' => 'Ϸ',
70543 'ϻ' => 'Ϻ',
70544 'а' => 'А',
70545 'б' => 'Б',
70546 'в' => 'В',
70547 'г' => 'Г',
70548 'д' => 'Д',
70549 'е' => 'Е',
70550 'ж' => 'Ж',
70551 'з' => 'З',
70552 'и' => 'И',
70553 'й' => 'Й',
70554 'к' => 'К',
70555 'л' => 'Л',
70556 'м' => 'М',
70557 'н' => 'Н',
70558 'о' => 'О',
70559 'п' => 'П',
70560 'р' => 'Р',
70561 'с' => 'С',
70562 'т' => 'Т',
70563 'у' => 'У',
70564 'ф' => 'Ф',
70565 'х' => 'Х',
70566 'ц' => 'Ц',
70567 'ч' => 'Ч',
70568 'ш' => 'Ш',
70569 'щ' => 'Щ',
70570 'ъ' => 'Ъ',
70571 'ы' => 'Ы',
70572 'ь' => 'Ь',
70573 'э' => 'Э',
70574 'ю' => 'Ю',
70575 'я' => 'Я',
70576 'ѐ' => 'Ѐ',
70577 'ё' => 'Ё',
70578 'ђ' => 'Ђ',
70579 'ѓ' => 'Ѓ',
70580 'є' => 'Є',
70581 'ѕ' => 'Ѕ',
70582 'і' => 'І',
70583 'ї' => 'Ї',
70584 'ј' => 'Ј',
70585 'љ' => 'Љ',
70586 'њ' => 'Њ',
70587 'ћ' => 'Ћ',
70588 'ќ' => 'Ќ',
70589 'ѝ' => 'Ѝ',
70590 'ў' => 'Ў',
70591 'џ' => 'Џ',
70592 'ѡ' => 'Ѡ',
70593 'ѣ' => 'Ѣ',
70594 'ѥ' => 'Ѥ',
70595 'ѧ' => 'Ѧ',
70596 'ѩ' => 'Ѩ',
70597 'ѫ' => 'Ѫ',
70598 'ѭ' => 'Ѭ',
70599 'ѯ' => 'Ѯ',
70600 'ѱ' => 'Ѱ',
70601 'ѳ' => 'Ѳ',
70602 'ѵ' => 'Ѵ',
70603 'ѷ' => 'Ѷ',
70604 'ѹ' => 'Ѹ',
70605 'ѻ' => 'Ѻ',
70606 'ѽ' => 'Ѽ',
70607 'ѿ' => 'Ѿ',
70608 'ҁ' => 'Ҁ',
70609 'ҋ' => 'Ҋ',
70610 'ҍ' => 'Ҍ',
70611 'ҏ' => 'Ҏ',
70612 'ґ' => 'Ґ',
70613 'ғ' => 'Ғ',
70614 'ҕ' => 'Ҕ',
70615 'җ' => 'Җ',
70616 'ҙ' => 'Ҙ',
70617 'қ' => 'Қ',
70618 'ҝ' => 'Ҝ',
70619 'ҟ' => 'Ҟ',
70620 'ҡ' => 'Ҡ',
70621 'ң' => 'Ң',
70622 'ҥ' => 'Ҥ',
70623 'ҧ' => 'Ҧ',
70624 'ҩ' => 'Ҩ',
70625 'ҫ' => 'Ҫ',
70626 'ҭ' => 'Ҭ',
70627 'ү' => 'Ү',
70628 'ұ' => 'Ұ',
70629 'ҳ' => 'Ҳ',
70630 'ҵ' => 'Ҵ',
70631 'ҷ' => 'Ҷ',
70632 'ҹ' => 'Ҹ',
70633 'һ' => 'Һ',
70634 'ҽ' => 'Ҽ',
70635 'ҿ' => 'Ҿ',
70636 'ӂ' => 'Ӂ',
70637 'ӄ' => 'Ӄ',
70638 'ӆ' => 'Ӆ',
70639 'ӈ' => 'Ӈ',
70640 'ӊ' => 'Ӊ',
70641 'ӌ' => 'Ӌ',
70642 'ӎ' => 'Ӎ',
70643 'ӏ' => 'Ӏ',
70644 'ӑ' => 'Ӑ',
70645 'ӓ' => 'Ӓ',
70646 'ӕ' => 'Ӕ',
70647 'ӗ' => 'Ӗ',
70648 'ә' => 'Ә',
70649 'ӛ' => 'Ӛ',
70650 'ӝ' => 'Ӝ',
70651 'ӟ' => 'Ӟ',
70652 'ӡ' => 'Ӡ',
70653 'ӣ' => 'Ӣ',
70654 'ӥ' => 'Ӥ',
70655 'ӧ' => 'Ӧ',
70656 'ө' => 'Ө',
70657 'ӫ' => 'Ӫ',
70658 'ӭ' => 'Ӭ',
70659 'ӯ' => 'Ӯ',
70660 'ӱ' => 'Ӱ',
70661 'ӳ' => 'Ӳ',
70662 'ӵ' => 'Ӵ',
70663 'ӷ' => 'Ӷ',
70664 'ӹ' => 'Ӹ',
70665 'ӻ' => 'Ӻ',
70666 'ӽ' => 'Ӽ',
70667 'ӿ' => 'Ӿ',
70668 'ԁ' => 'Ԁ',
70669 'ԃ' => 'Ԃ',
70670 'ԅ' => 'Ԅ',
70671 'ԇ' => 'Ԇ',
70672 'ԉ' => 'Ԉ',
70673 'ԋ' => 'Ԋ',
70674 'ԍ' => 'Ԍ',
70675 'ԏ' => 'Ԏ',
70676 'ԑ' => 'Ԑ',
70677 'ԓ' => 'Ԓ',
70678 'ԕ' => 'Ԕ',
70679 'ԗ' => 'Ԗ',
70680 'ԙ' => 'Ԙ',
70681 'ԛ' => 'Ԛ',
70682 'ԝ' => 'Ԝ',
70683 'ԟ' => 'Ԟ',
70684 'ԡ' => 'Ԡ',
70685 'ԣ' => 'Ԣ',
70686 'ԥ' => 'Ԥ',
70687 'ԧ' => 'Ԧ',
70688 'ԩ' => 'Ԩ',
70689 'ԫ' => 'Ԫ',
70690 'ԭ' => 'Ԭ',
70691 'ԯ' => 'Ԯ',
70692 'ա' => 'Ա',
70693 'բ' => 'Բ',
70694 'գ' => 'Գ',
70695 'դ' => 'Դ',
70696 'ե' => 'Ե',
70697 'զ' => 'Զ',
70698 'է' => 'Է',
70699 'ը' => 'Ը',
70700 'թ' => 'Թ',
70701 'ժ' => 'Ժ',
70702 'ի' => 'Ի',
70703 'լ' => 'Լ',
70704 'խ' => 'Խ',
70705 'ծ' => 'Ծ',
70706 'կ' => 'Կ',
70707 'հ' => 'Հ',
70708 'ձ' => 'Ձ',
70709 'ղ' => 'Ղ',
70710 'ճ' => 'Ճ',
70711 'մ' => 'Մ',
70712 'յ' => 'Յ',
70713 'ն' => 'Ն',
70714 'շ' => 'Շ',
70715 'ո' => 'Ո',
70716 'չ' => 'Չ',
70717 'պ' => 'Պ',
70718 'ջ' => 'Ջ',
70719 'ռ' => 'Ռ',
70720 'ս' => 'Ս',
70721 'վ' => 'Վ',
70722 'տ' => 'Տ',
70723 'ր' => 'Ր',
70724 'ց' => 'Ց',
70725 'ւ' => 'Ւ',
70726 'փ' => 'Փ',
70727 'ք' => 'Ք',
70728 'օ' => 'Օ',
70729 'ֆ' => 'Ֆ',
70730 'ᵹ' => 'Ᵹ',
70731 'ᵽ' => 'Ᵽ',
70732 'ḁ' => 'Ḁ',
70733 'ḃ' => 'Ḃ',
70734 'ḅ' => 'Ḅ',
70735 'ḇ' => 'Ḇ',
70736 'ḉ' => 'Ḉ',
70737 'ḋ' => 'Ḋ',
70738 'ḍ' => 'Ḍ',
70739 'ḏ' => 'Ḏ',
70740 'ḑ' => 'Ḑ',
70741 'ḓ' => 'Ḓ',
70742 'ḕ' => 'Ḕ',
70743 'ḗ' => 'Ḗ',
70744 'ḙ' => 'Ḙ',
70745 'ḛ' => 'Ḛ',
70746 'ḝ' => 'Ḝ',
70747 'ḟ' => 'Ḟ',
70748 'ḡ' => 'Ḡ',
70749 'ḣ' => 'Ḣ',
70750 'ḥ' => 'Ḥ',
70751 'ḧ' => 'Ḧ',
70752 'ḩ' => 'Ḩ',
70753 'ḫ' => 'Ḫ',
70754 'ḭ' => 'Ḭ',
70755 'ḯ' => 'Ḯ',
70756 'ḱ' => 'Ḱ',
70757 'ḳ' => 'Ḳ',
70758 'ḵ' => 'Ḵ',
70759 'ḷ' => 'Ḷ',
70760 'ḹ' => 'Ḹ',
70761 'ḻ' => 'Ḻ',
70762 'ḽ' => 'Ḽ',
70763 'ḿ' => 'Ḿ',
70764 'ṁ' => 'Ṁ',
70765 'ṃ' => 'Ṃ',
70766 'ṅ' => 'Ṅ',
70767 'ṇ' => 'Ṇ',
70768 'ṉ' => 'Ṉ',
70769 'ṋ' => 'Ṋ',
70770 'ṍ' => 'Ṍ',
70771 'ṏ' => 'Ṏ',
70772 'ṑ' => 'Ṑ',
70773 'ṓ' => 'Ṓ',
70774 'ṕ' => 'Ṕ',
70775 'ṗ' => 'Ṗ',
70776 'ṙ' => 'Ṙ',
70777 'ṛ' => 'Ṛ',
70778 'ṝ' => 'Ṝ',
70779 'ṟ' => 'Ṟ',
70780 'ṡ' => 'Ṡ',
70781 'ṣ' => 'Ṣ',
70782 'ṥ' => 'Ṥ',
70783 'ṧ' => 'Ṧ',
70784 'ṩ' => 'Ṩ',
70785 'ṫ' => 'Ṫ',
70786 'ṭ' => 'Ṭ',
70787 'ṯ' => 'Ṯ',
70788 'ṱ' => 'Ṱ',
70789 'ṳ' => 'Ṳ',
70790 'ṵ' => 'Ṵ',
70791 'ṷ' => 'Ṷ',
70792 'ṹ' => 'Ṹ',
70793 'ṻ' => 'Ṻ',
70794 'ṽ' => 'Ṽ',
70795 'ṿ' => 'Ṿ',
70796 'ẁ' => 'Ẁ',
70797 'ẃ' => 'Ẃ',
70798 'ẅ' => 'Ẅ',
70799 'ẇ' => 'Ẇ',
70800 'ẉ' => 'Ẉ',
70801 'ẋ' => 'Ẋ',
70802 'ẍ' => 'Ẍ',
70803 'ẏ' => 'Ẏ',
70804 'ẑ' => 'Ẑ',
70805 'ẓ' => 'Ẓ',
70806 'ẕ' => 'Ẕ',
70807 'ẛ' => 'Ṡ',
70808 'ạ' => 'Ạ',
70809 'ả' => 'Ả',
70810 'ấ' => 'Ấ',
70811 'ầ' => 'Ầ',
70812 'ẩ' => 'Ẩ',
70813 'ẫ' => 'Ẫ',
70814 'ậ' => 'Ậ',
70815 'ắ' => 'Ắ',
70816 'ằ' => 'Ằ',
70817 'ẳ' => 'Ẳ',
70818 'ẵ' => 'Ẵ',
70819 'ặ' => 'Ặ',
70820 'ẹ' => 'Ẹ',
70821 'ẻ' => 'Ẻ',
70822 'ẽ' => 'Ẽ',
70823 'ế' => 'Ế',
70824 'ề' => 'Ề',
70825 'ể' => 'Ể',
70826 'ễ' => 'Ễ',
70827 'ệ' => 'Ệ',
70828 'ỉ' => 'Ỉ',
70829 'ị' => 'Ị',
70830 'ọ' => 'Ọ',
70831 'ỏ' => 'Ỏ',
70832 'ố' => 'Ố',
70833 'ồ' => 'Ồ',
70834 'ổ' => 'Ổ',
70835 'ỗ' => 'Ỗ',
70836 'ộ' => 'Ộ',
70837 'ớ' => 'Ớ',
70838 'ờ' => 'Ờ',
70839 'ở' => 'Ở',
70840 'ỡ' => 'Ỡ',
70841 'ợ' => 'Ợ',
70842 'ụ' => 'Ụ',
70843 'ủ' => 'Ủ',
70844 'ứ' => 'Ứ',
70845 'ừ' => 'Ừ',
70846 'ử' => 'Ử',
70847 'ữ' => 'Ữ',
70848 'ự' => 'Ự',
70849 'ỳ' => 'Ỳ',
70850 'ỵ' => 'Ỵ',
70851 'ỷ' => 'Ỷ',
70852 'ỹ' => 'Ỹ',
70853 'ỻ' => 'Ỻ',
70854 'ỽ' => 'Ỽ',
70855 'ỿ' => 'Ỿ',
70856 'ἀ' => 'Ἀ',
70857 'ἁ' => 'Ἁ',
70858 'ἂ' => 'Ἂ',
70859 'ἃ' => 'Ἃ',
70860 'ἄ' => 'Ἄ',
70861 'ἅ' => 'Ἅ',
70862 'ἆ' => 'Ἆ',
70863 'ἇ' => 'Ἇ',
70864 'ἐ' => 'Ἐ',
70865 'ἑ' => 'Ἑ',
70866 'ἒ' => 'Ἒ',
70867 'ἓ' => 'Ἓ',
70868 'ἔ' => 'Ἔ',
70869 'ἕ' => 'Ἕ',
70870 'ἠ' => 'Ἠ',
70871 'ἡ' => 'Ἡ',
70872 'ἢ' => 'Ἢ',
70873 'ἣ' => 'Ἣ',
70874 'ἤ' => 'Ἤ',
70875 'ἥ' => 'Ἥ',
70876 'ἦ' => 'Ἦ',
70877 'ἧ' => 'Ἧ',
70878 'ἰ' => 'Ἰ',
70879 'ἱ' => 'Ἱ',
70880 'ἲ' => 'Ἲ',
70881 'ἳ' => 'Ἳ',
70882 'ἴ' => 'Ἴ',
70883 'ἵ' => 'Ἵ',
70884 'ἶ' => 'Ἶ',
70885 'ἷ' => 'Ἷ',
70886 'ὀ' => 'Ὀ',
70887 'ὁ' => 'Ὁ',
70888 'ὂ' => 'Ὂ',
70889 'ὃ' => 'Ὃ',
70890 'ὄ' => 'Ὄ',
70891 'ὅ' => 'Ὅ',
70892 'ὑ' => 'Ὑ',
70893 'ὓ' => 'Ὓ',
70894 'ὕ' => 'Ὕ',
70895 'ὗ' => 'Ὗ',
70896 'ὠ' => 'Ὠ',
70897 'ὡ' => 'Ὡ',
70898 'ὢ' => 'Ὢ',
70899 'ὣ' => 'Ὣ',
70900 'ὤ' => 'Ὤ',
70901 'ὥ' => 'Ὥ',
70902 'ὦ' => 'Ὦ',
70903 'ὧ' => 'Ὧ',
70904 'ὰ' => 'Ὰ',
70905 'ά' => 'Ά',
70906 'ὲ' => 'Ὲ',
70907 'έ' => 'Έ',
70908 'ὴ' => 'Ὴ',
70909 'ή' => 'Ή',
70910 'ὶ' => 'Ὶ',
70911 'ί' => 'Ί',
70912 'ὸ' => 'Ὸ',
70913 'ό' => 'Ό',
70914 'ὺ' => 'Ὺ',
70915 'ύ' => 'Ύ',
70916 'ὼ' => 'Ὼ',
70917 'ώ' => 'Ώ',
70918 'ᾀ' => 'ᾈ',
70919 'ᾁ' => 'ᾉ',
70920 'ᾂ' => 'ᾊ',
70921 'ᾃ' => 'ᾋ',
70922 'ᾄ' => 'ᾌ',
70923 'ᾅ' => 'ᾍ',
70924 'ᾆ' => 'ᾎ',
70925 'ᾇ' => 'ᾏ',
70926 'ᾐ' => 'ᾘ',
70927 'ᾑ' => 'ᾙ',
70928 'ᾒ' => 'ᾚ',
70929 'ᾓ' => 'ᾛ',
70930 'ᾔ' => 'ᾜ',
70931 'ᾕ' => 'ᾝ',
70932 'ᾖ' => 'ᾞ',
70933 'ᾗ' => 'ᾟ',
70934 'ᾠ' => 'ᾨ',
70935 'ᾡ' => 'ᾩ',
70936 'ᾢ' => 'ᾪ',
70937 'ᾣ' => 'ᾫ',
70938 'ᾤ' => 'ᾬ',
70939 'ᾥ' => 'ᾭ',
70940 'ᾦ' => 'ᾮ',
70941 'ᾧ' => 'ᾯ',
70942 'ᾰ' => 'Ᾰ',
70943 'ᾱ' => 'Ᾱ',
70944 'ᾳ' => 'ᾼ',
70945 'ι' => 'Ι',
70946 'ῃ' => 'ῌ',
70947 'ῐ' => 'Ῐ',
70948 'ῑ' => 'Ῑ',
70949 'ῠ' => 'Ῠ',
70950 'ῡ' => 'Ῡ',
70951 'ῥ' => 'Ῥ',
70952 'ῳ' => 'ῼ',
70953 'ⅎ' => 'Ⅎ',
70954 'ⅰ' => 'Ⅰ',
70955 'ⅱ' => 'Ⅱ',
70956 'ⅲ' => 'Ⅲ',
70957 'ⅳ' => 'Ⅳ',
70958 'ⅴ' => 'Ⅴ',
70959 'ⅵ' => 'Ⅵ',
70960 'ⅶ' => 'Ⅶ',
70961 'ⅷ' => 'Ⅷ',
70962 'ⅸ' => 'Ⅸ',
70963 'ⅹ' => 'Ⅹ',
70964 'ⅺ' => 'Ⅺ',
70965 'ⅻ' => 'Ⅻ',
70966 'ⅼ' => 'Ⅼ',
70967 'ⅽ' => 'Ⅽ',
70968 'ⅾ' => 'Ⅾ',
70969 'ⅿ' => 'Ⅿ',
70970 'ↄ' => 'Ↄ',
70971 'ⓐ' => 'Ⓐ',
70972 'ⓑ' => 'Ⓑ',
70973 'ⓒ' => 'Ⓒ',
70974 'ⓓ' => 'Ⓓ',
70975 'ⓔ' => 'Ⓔ',
70976 'ⓕ' => 'Ⓕ',
70977 'ⓖ' => 'Ⓖ',
70978 'ⓗ' => 'Ⓗ',
70979 'ⓘ' => 'Ⓘ',
70980 'ⓙ' => 'Ⓙ',
70981 'ⓚ' => 'Ⓚ',
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 'ⱙ' => 'Ⱙ',
71039 'ⱚ' => 'Ⱚ',
71040 'ⱛ' => 'Ⱛ',
71041 'ⱜ' => 'Ⱜ',
71042 'ⱝ' => 'Ⱝ',
71043 'ⱞ' => 'Ⱞ',
71044 'ⱡ' => 'Ⱡ',
71045 'ⱥ' => 'Ⱥ',
71046 'ⱦ' => 'Ⱦ',
71047 'ⱨ' => 'Ⱨ',
71048 'ⱪ' => 'Ⱪ',
71049 'ⱬ' => 'Ⱬ',
71050 'ⱳ' => 'Ⱳ',
71051 'ⱶ' => 'Ⱶ',
71052 'ⲁ' => 'Ⲁ',
71053 'ⲃ' => 'Ⲃ',
71054 'ⲅ' => 'Ⲅ',
71055 'ⲇ' => 'Ⲇ',
71056 'ⲉ' => 'Ⲉ',
71057 'ⲋ' => 'Ⲋ',
71058 'ⲍ' => 'Ⲍ',
71059 'ⲏ' => 'Ⲏ',
71060 'ⲑ' => 'Ⲑ',
71061 'ⲓ' => 'Ⲓ',
71062 'ⲕ' => 'Ⲕ',
71063 'ⲗ' => 'Ⲗ',
71064 'ⲙ' => 'Ⲙ',
71065 'ⲛ' => 'Ⲛ',
71066 'ⲝ' => 'Ⲝ',
71067 'ⲟ' => 'Ⲟ',
71068 'ⲡ' => 'Ⲡ',
71069 'ⲣ' => 'Ⲣ',
71070 'ⲥ' => 'Ⲥ',
71071 'ⲧ' => 'Ⲧ',
71072 'ⲩ' => 'Ⲩ',
71073 'ⲫ' => 'Ⲫ',
71074 'ⲭ' => 'Ⲭ',
71075 'ⲯ' => 'Ⲯ',
71076 'ⲱ' => 'Ⲱ',
71077 'ⲳ' => 'Ⲳ',
71078 'ⲵ' => 'Ⲵ',
71079 'ⲷ' => 'Ⲷ',
71080 'ⲹ' => 'Ⲹ',
71081 'ⲻ' => 'Ⲻ',
71082 'ⲽ' => 'Ⲽ',
71083 'ⲿ' => 'Ⲿ',
71084 'ⳁ' => 'Ⳁ',
71085 'ⳃ' => 'Ⳃ',
71086 'ⳅ' => 'Ⳅ',
71087 'ⳇ' => 'Ⳇ',
71088 'ⳉ' => 'Ⳉ',
71089 'ⳋ' => 'Ⳋ',
71090 'ⳍ' => 'Ⳍ',
71091 'ⳏ' => 'Ⳏ',
71092 'ⳑ' => 'Ⳑ',
71093 'ⳓ' => 'Ⳓ',
71094 'ⳕ' => 'Ⳕ',
71095 'ⳗ' => 'Ⳗ',
71096 'ⳙ' => 'Ⳙ',
71097 'ⳛ' => 'Ⳛ',
71098 'ⳝ' => 'Ⳝ',
71099 'ⳟ' => 'Ⳟ',
71100 'ⳡ' => 'Ⳡ',
71101 'ⳣ' => 'Ⳣ',
71102 'ⳬ' => 'Ⳬ',
71103 'ⳮ' => 'Ⳮ',
71104 'ⳳ' => 'Ⳳ',
71105 'ⴀ' => 'Ⴀ',
71106 'ⴁ' => 'Ⴁ',
71107 'ⴂ' => 'Ⴂ',
71108 'ⴃ' => 'Ⴃ',
71109 'ⴄ' => 'Ⴄ',
71110 'ⴅ' => 'Ⴅ',
71111 'ⴆ' => 'Ⴆ',
71112 'ⴇ' => 'Ⴇ',
71113 'ⴈ' => 'Ⴈ',
71114 'ⴉ' => 'Ⴉ',
71115 'ⴊ' => 'Ⴊ',
71116 'ⴋ' => 'Ⴋ',
71117 'ⴌ' => 'Ⴌ',
71118 'ⴍ' => 'Ⴍ',
71119 'ⴎ' => 'Ⴎ',
71120 'ⴏ' => 'Ⴏ',
71121 'ⴐ' => 'Ⴐ',
71122 'ⴑ' => 'Ⴑ',
71123 'ⴒ' => 'Ⴒ',
71124 'ⴓ' => 'Ⴓ',
71125 'ⴔ' => 'Ⴔ',
71126 'ⴕ' => 'Ⴕ',
71127 'ⴖ' => 'Ⴖ',
71128 'ⴗ' => 'Ⴗ',
71129 'ⴘ' => 'Ⴘ',
71130 'ⴙ' => 'Ⴙ',
71131 'ⴚ' => 'Ⴚ',
71132 'ⴛ' => 'Ⴛ',
71133 'ⴜ' => 'Ⴜ',
71134 'ⴝ' => 'Ⴝ',
71135 'ⴞ' => 'Ⴞ',
71136 'ⴟ' => 'Ⴟ',
71137 'ⴠ' => 'Ⴠ',
71138 'ⴡ' => 'Ⴡ',
71139 'ⴢ' => 'Ⴢ',
71140 'ⴣ' => 'Ⴣ',
71141 'ⴤ' => 'Ⴤ',
71142 'ⴥ' => 'Ⴥ',
71143 'ⴧ' => 'Ⴧ',
71144 'ⴭ' => 'Ⴭ',
71145 'ꙁ' => 'Ꙁ',
71146 'ꙃ' => 'Ꙃ',
71147 'ꙅ' => 'Ꙅ',
71148 'ꙇ' => 'Ꙇ',
71149 'ꙉ' => 'Ꙉ',
71150 'ꙋ' => 'Ꙋ',
71151 'ꙍ' => 'Ꙍ',
71152 'ꙏ' => 'Ꙏ',
71153 'ꙑ' => 'Ꙑ',
71154 'ꙓ' => 'Ꙓ',
71155 'ꙕ' => 'Ꙕ',
71156 'ꙗ' => 'Ꙗ',
71157 'ꙙ' => 'Ꙙ',
71158 'ꙛ' => 'Ꙛ',
71159 'ꙝ' => 'Ꙝ',
71160 'ꙟ' => 'Ꙟ',
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 'a' => 'A',
71241 'b' => 'B',
71242 'c' => 'C',
71243 'd' => 'D',
71244 'e' => 'E',
71245 'f' => 'F',
71246 'g' => 'G',
71247 'h' => 'H',
71248 'i' => 'I',
71249 'j' => 'J',
71250 'k' => 'K',
71251 'l' => 'L',
71252 'm' => 'M',
71253 'n' => 'N',
71254 'o' => 'O',
71255 'p' => 'P',
71256 'q' => 'Q',
71257 'r' => 'R',
71258 's' => 'S',
71259 't' => 'T',
71260 'u' => 'U',
71261 'v' => 'V',
71262 'w' => 'W',
71263 'x' => 'X',
71264 'y' => 'Y',
71265 'z' => 'Z',
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 $result =& $data;
71341 unset($data);
71342
71343 return $result;
71344 <?php
71345
71346
71347
71348
71349
71350
71351
71352
71353
71354
71355 use Symfony\Polyfill\Mbstring as p;
71356
71357 if (!function_exists('mb_strlen')) {
71358 define('MB_CASE_UPPER', 0);
71359 define('MB_CASE_LOWER', 1);
71360 define('MB_CASE_TITLE', 2);
71361
71362 function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
71363 function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
71364 function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
71365 function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
71366 function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
71367 function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
71368 function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
71369 function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
71370 function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
71371 function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
71372 function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
71373 function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
71374 function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
71375 function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
71376 function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
71377 function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
71378 function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
71379 function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
71380 function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
71381 function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
71382 function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
71383 function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
71384 function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
71385 function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
71386 function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
71387 function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
71388 function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
71389 function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
71390 function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
71391 function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
71392 function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
71393 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); }
71394 }
71395 if (!function_exists('mb_chr')) {
71396 function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
71397 function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
71398 function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
71399 }
71400 <?php
71401
71402
71403
71404
71405
71406
71407
71408
71409
71410
71411 namespace Symfony\Component\Process\Exception;
71412
71413
71414
71415
71416
71417
71418 interface ExceptionInterface
71419 {
71420 }
71421 <?php
71422
71423
71424
71425
71426
71427
71428
71429
71430
71431
71432 namespace Symfony\Component\Process\Exception;
71433
71434
71435
71436
71437
71438
71439 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
71440 {
71441 }
71442 <?php
71443
71444
71445
71446
71447
71448
71449
71450
71451
71452
71453 namespace Symfony\Component\Process\Exception;
71454
71455
71456
71457
71458
71459
71460 class LogicException extends \LogicException implements ExceptionInterface
71461 {
71462 }
71463 <?php
71464
71465
71466
71467
71468
71469
71470
71471
71472
71473
71474 namespace Symfony\Component\Process\Exception;
71475
71476 use Symfony\Component\Process\Process;
71477
71478
71479
71480
71481
71482
71483 class ProcessFailedException extends RuntimeException
71484 {
71485 private $process;
71486
71487 public function __construct(Process $process)
71488 {
71489 if ($process->isSuccessful()) {
71490 throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
71491 }
71492
71493 $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
71494 $process->getCommandLine(),
71495 $process->getExitCode(),
71496 $process->getExitCodeText(),
71497 $process->getWorkingDirectory()
71498 );
71499
71500 if (!$process->isOutputDisabled()) {
71501 $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
71502 $process->getOutput(),
71503 $process->getErrorOutput()
71504 );
71505 }
71506
71507 parent::__construct($error);
71508
71509 $this->process = $process;
71510 }
71511
71512 public function getProcess()
71513 {
71514 return $this->process;
71515 }
71516 }
71517 <?php
71518
71519
71520
71521
71522
71523
71524
71525
71526
71527
71528 namespace Symfony\Component\Process\Exception;
71529
71530 use Symfony\Component\Process\Process;
71531
71532
71533
71534
71535
71536
71537 class ProcessTimedOutException extends RuntimeException
71538 {
71539 const TYPE_GENERAL = 1;
71540 const TYPE_IDLE = 2;
71541
71542 private $process;
71543 private $timeoutType;
71544
71545 public function __construct(Process $process, $timeoutType)
71546 {
71547 $this->process = $process;
71548 $this->timeoutType = $timeoutType;
71549
71550 parent::__construct(sprintf(
71551 'The process "%s" exceeded the timeout of %s seconds.',
71552 $process->getCommandLine(),
71553 $this->getExceededTimeout()
71554 ));
71555 }
71556
71557 public function getProcess()
71558 {
71559 return $this->process;
71560 }
71561
71562 public function isGeneralTimeout()
71563 {
71564 return $this->timeoutType === self::TYPE_GENERAL;
71565 }
71566
71567 public function isIdleTimeout()
71568 {
71569 return $this->timeoutType === self::TYPE_IDLE;
71570 }
71571
71572 public function getExceededTimeout()
71573 {
71574 switch ($this->timeoutType) {
71575 case self::TYPE_GENERAL:
71576 return $this->process->getTimeout();
71577
71578 case self::TYPE_IDLE:
71579 return $this->process->getIdleTimeout();
71580
71581 default:
71582 throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
71583 }
71584 }
71585 }
71586 <?php
71587
71588
71589
71590
71591
71592
71593
71594
71595
71596
71597 namespace Symfony\Component\Process\Exception;
71598
71599
71600
71601
71602
71603
71604 class RuntimeException extends \RuntimeException implements ExceptionInterface
71605 {
71606 }
71607 <?php
71608
71609
71610
71611
71612
71613
71614
71615
71616
71617
71618 namespace Symfony\Component\Process;
71619
71620
71621
71622
71623
71624
71625
71626 class ExecutableFinder
71627 {
71628 private $suffixes = array('.exe', '.bat', '.cmd', '.com');
71629
71630
71631
71632
71633
71634
71635 public function setSuffixes(array $suffixes)
71636 {
71637 $this->suffixes = $suffixes;
71638 }
71639
71640
71641
71642
71643
71644
71645 public function addSuffix($suffix)
71646 {
71647 $this->suffixes[] = $suffix;
71648 }
71649
71650
71651
71652
71653
71654
71655
71656
71657
71658
71659 public function find($name, $default = null, array $extraDirs = array())
71660 {
71661 if (ini_get('open_basedir')) {
71662 $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
71663 $dirs = array();
71664 foreach ($searchPath as $path) {
71665
71666  if (@is_dir($path)) {
71667 $dirs[] = $path;
71668 } else {
71669 if (basename($path) == $name && @is_executable($path)) {
71670 return $path;
71671 }
71672 }
71673 }
71674 } else {
71675 $dirs = array_merge(
71676 explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
71677 $extraDirs
71678 );
71679 }
71680
71681 $suffixes = array('');
71682 if ('\\' === DIRECTORY_SEPARATOR) {
71683 $pathExt = getenv('PATHEXT');
71684 $suffixes = array_merge($suffixes, $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes);
71685 }
71686 foreach ($suffixes as $suffix) {
71687 foreach ($dirs as $dir) {
71688 if (@is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) {
71689 return $file;
71690 }
71691 }
71692 }
71693
71694 return $default;
71695 }
71696 }
71697 Copyright (c) 2004-2017 Fabien Potencier
71698
71699 Permission is hereby granted, free of charge, to any person obtaining a copy
71700 of this software and associated documentation files (the "Software"), to deal
71701 in the Software without restriction, including without limitation the rights
71702 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71703 copies of the Software, and to permit persons to whom the Software is furnished
71704 to do so, subject to the following conditions:
71705
71706 The above copyright notice and this permission notice shall be included in all
71707 copies or substantial portions of the Software.
71708
71709 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71710 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71711 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71712 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71713 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71714 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
71715 THE SOFTWARE.
71716 <?php
71717
71718
71719
71720
71721
71722
71723
71724
71725
71726
71727 namespace Symfony\Component\Process;
71728
71729
71730
71731
71732
71733
71734
71735 class PhpExecutableFinder
71736 {
71737 private $executableFinder;
71738
71739 public function __construct()
71740 {
71741 $this->executableFinder = new ExecutableFinder();
71742 }
71743
71744
71745
71746
71747
71748
71749
71750
71751 public function find($includeArgs = true)
71752 {
71753 $args = $this->findArguments();
71754 $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
71755
71756
71757  if (defined('HHVM_VERSION')) {
71758 return (getenv('PHP_BINARY') ?: PHP_BINARY).$args;
71759 }
71760
71761
71762  if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg')) && is_file(PHP_BINARY)) {
71763 return PHP_BINARY.$args;
71764 }
71765
71766 if ($php = getenv('PHP_PATH')) {
71767 if (!is_executable($php)) {
71768 return false;
71769 }
71770
71771 return $php;
71772 }
71773
71774 if ($php = getenv('PHP_PEAR_PHP_BIN')) {
71775 if (is_executable($php)) {
71776 return $php;
71777 }
71778 }
71779
71780 $dirs = array(PHP_BINDIR);
71781 if ('\\' === DIRECTORY_SEPARATOR) {
71782 $dirs[] = 'C:\xampp\php\\';
71783 }
71784
71785 return $this->executableFinder->find('php', false, $dirs);
71786 }
71787
71788
71789
71790
71791
71792
71793 public function findArguments()
71794 {
71795 $arguments = array();
71796
71797 if (defined('HHVM_VERSION')) {
71798 $arguments[] = '--php';
71799 } elseif ('phpdbg' === PHP_SAPI) {
71800 $arguments[] = '-qrr';
71801 }
71802
71803 return $arguments;
71804 }
71805 }
71806 <?php
71807
71808
71809
71810
71811
71812
71813
71814
71815
71816
71817 namespace Symfony\Component\Process;
71818
71819 use Symfony\Component\Process\Exception\RuntimeException;
71820
71821
71822
71823
71824
71825
71826
71827
71828
71829
71830 class PhpProcess extends Process
71831 {
71832
71833
71834
71835
71836
71837
71838
71839
71840
71841 public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = array())
71842 {
71843 $executableFinder = new PhpExecutableFinder();
71844 if (false === $php = $executableFinder->find()) {
71845 $php = null;
71846 }
71847 if ('phpdbg' === PHP_SAPI) {
71848 $file = tempnam(sys_get_temp_dir(), 'dbg');
71849 file_put_contents($file, $script);
71850 register_shutdown_function('unlink', $file);
71851 $php .= ' '.ProcessUtils::escapeArgument($file);
71852 $script = null;
71853 }
71854 if ('\\' !== DIRECTORY_SEPARATOR && null !== $php) {
71855
71856  
71857  
71858  $php = 'exec '.$php;
71859 }
71860
71861 parent::__construct($php, $cwd, $env, $script, $timeout, $options);
71862 }
71863
71864
71865
71866
71867 public function setPhpBinary($php)
71868 {
71869 $this->setCommandLine($php);
71870 }
71871
71872
71873
71874
71875 public function start($callback = null)
71876 {
71877 if (null === $this->getCommandLine()) {
71878 throw new RuntimeException('Unable to find the PHP executable.');
71879 }
71880
71881 parent::start($callback);
71882 }
71883 }
71884 <?php
71885
71886
71887
71888
71889
71890
71891
71892
71893
71894
71895 namespace Symfony\Component\Process\Pipes;
71896
71897
71898
71899
71900
71901
71902 abstract class AbstractPipes implements PipesInterface
71903 {
71904
71905 public $pipes = array();
71906
71907
71908 private $inputBuffer = '';
71909
71910 private $input;
71911
71912 private $blocked = true;
71913
71914 public function __construct($input)
71915 {
71916 if (is_resource($input)) {
71917 $this->input = $input;
71918 } elseif (is_string($input)) {
71919 $this->inputBuffer = $input;
71920 } else {
71921 $this->inputBuffer = (string) $input;
71922 }
71923 }
71924
71925
71926
71927
71928 public function close()
71929 {
71930 foreach ($this->pipes as $pipe) {
71931 fclose($pipe);
71932 }
71933 $this->pipes = array();
71934 }
71935
71936
71937
71938
71939
71940
71941 protected function hasSystemCallBeenInterrupted()
71942 {
71943 $lastError = error_get_last();
71944
71945
71946  return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
71947 }
71948
71949
71950
71951
71952 protected function unblock()
71953 {
71954 if (!$this->blocked) {
71955 return;
71956 }
71957
71958 foreach ($this->pipes as $pipe) {
71959 stream_set_blocking($pipe, 0);
71960 }
71961 if (null !== $this->input) {
71962 stream_set_blocking($this->input, 0);
71963 }
71964
71965 $this->blocked = false;
71966 }
71967
71968
71969
71970
71971 protected function write()
71972 {
71973 if (!isset($this->pipes[0])) {
71974 return;
71975 }
71976 $input = $this->input;
71977 $r = $e = array();
71978 $w = array($this->pipes[0]);
71979
71980
71981  if (false === $n = @stream_select($r, $w, $e, 0, 0)) {
71982 return;
71983 }
71984
71985 foreach ($w as $stdin) {
71986 if (isset($this->inputBuffer[0])) {
71987 $written = fwrite($stdin, $this->inputBuffer);
71988 $this->inputBuffer = substr($this->inputBuffer, $written);
71989 if (isset($this->inputBuffer[0])) {
71990 return array($this->pipes[0]);
71991 }
71992 }
71993
71994 if ($input) {
71995 for (;;) {
71996 $data = fread($input, self::CHUNK_SIZE);
71997 if (!isset($data[0])) {
71998 break;
71999 }
72000 $written = fwrite($stdin, $data);
72001 $data = substr($data, $written);
72002 if (isset($data[0])) {
72003 $this->inputBuffer = $data;
72004
72005 return array($this->pipes[0]);
72006 }
72007 }
72008 if (feof($input)) {
72009
72010  
72011  $this->input = null;
72012 }
72013 }
72014 }
72015
72016
72017  if (null === $this->input && !isset($this->inputBuffer[0])) {
72018 fclose($this->pipes[0]);
72019 unset($this->pipes[0]);
72020 } elseif (!$w) {
72021 return array($this->pipes[0]);
72022 }
72023 }
72024 }
72025 <?php
72026
72027
72028
72029
72030
72031
72032
72033
72034
72035
72036 namespace Symfony\Component\Process\Pipes;
72037
72038
72039
72040
72041
72042
72043
72044
72045 interface PipesInterface
72046 {
72047 const CHUNK_SIZE = 16384;
72048
72049
72050
72051
72052
72053
72054 public function getDescriptors();
72055
72056
72057
72058
72059
72060
72061 public function getFiles();
72062
72063
72064
72065
72066
72067
72068
72069
72070
72071 public function readAndWrite($blocking, $close = false);
72072
72073
72074
72075
72076
72077
72078 public function areOpen();
72079
72080
72081
72082
72083 public function close();
72084 }
72085 <?php
72086
72087
72088
72089
72090
72091
72092
72093
72094
72095
72096 namespace Symfony\Component\Process\Pipes;
72097
72098 use Symfony\Component\Process\Process;
72099
72100
72101
72102
72103
72104
72105
72106
72107 class UnixPipes extends AbstractPipes
72108 {
72109
72110 private $ttyMode;
72111
72112 private $ptyMode;
72113
72114 private $disableOutput;
72115
72116 public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
72117 {
72118 $this->ttyMode = (bool) $ttyMode;
72119 $this->ptyMode = (bool) $ptyMode;
72120 $this->disableOutput = (bool) $disableOutput;
72121
72122 parent::__construct($input);
72123 }
72124
72125 public function __destruct()
72126 {
72127 $this->close();
72128 }
72129
72130
72131
72132
72133 public function getDescriptors()
72134 {
72135 if ($this->disableOutput) {
72136 $nullstream = fopen('/dev/null', 'c');
72137
72138 return array(
72139 array('pipe', 'r'),
72140 $nullstream,
72141 $nullstream,
72142 );
72143 }
72144
72145 if ($this->ttyMode) {
72146 return array(
72147 array('file', '/dev/tty', 'r'),
72148 array('file', '/dev/tty', 'w'),
72149 array('file', '/dev/tty', 'w'),
72150 );
72151 }
72152
72153 if ($this->ptyMode && Process::isPtySupported()) {
72154 return array(
72155 array('pty'),
72156 array('pty'),
72157 array('pty'),
72158 );
72159 }
72160
72161 return array(
72162 array('pipe', 'r'),
72163 array('pipe', 'w'), 
72164  array('pipe', 'w'), 
72165  );
72166 }
72167
72168
72169
72170
72171 public function getFiles()
72172 {
72173 return array();
72174 }
72175
72176
72177
72178
72179 public function readAndWrite($blocking, $close = false)
72180 {
72181 $this->unblock();
72182 $w = $this->write();
72183
72184 $read = $e = array();
72185 $r = $this->pipes;
72186 unset($r[0]);
72187
72188
72189  if (($r || $w) && false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
72190
72191  
72192  if (!$this->hasSystemCallBeenInterrupted()) {
72193 $this->pipes = array();
72194 }
72195
72196 return $read;
72197 }
72198
72199 foreach ($r as $pipe) {
72200
72201  
72202  $read[$type = array_search($pipe, $this->pipes, true)] = '';
72203
72204 do {
72205 $data = fread($pipe, self::CHUNK_SIZE);
72206 $read[$type] .= $data;
72207 } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
72208
72209 if (!isset($read[$type][0])) {
72210 unset($read[$type]);
72211 }
72212
72213 if ($close && feof($pipe)) {
72214 fclose($pipe);
72215 unset($this->pipes[$type]);
72216 }
72217 }
72218
72219 return $read;
72220 }
72221
72222
72223
72224
72225 public function areOpen()
72226 {
72227 return (bool) $this->pipes;
72228 }
72229
72230
72231
72232
72233
72234
72235
72236
72237
72238 public static function create(Process $process, $input)
72239 {
72240 return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
72241 }
72242 }
72243 <?php
72244
72245
72246
72247
72248
72249
72250
72251
72252
72253
72254 namespace Symfony\Component\Process\Pipes;
72255
72256 use Symfony\Component\Process\Process;
72257 use Symfony\Component\Process\Exception\RuntimeException;
72258
72259
72260
72261
72262
72263
72264
72265
72266
72267
72268
72269 class WindowsPipes extends AbstractPipes
72270 {
72271
72272 private $files = array();
72273
72274 private $fileHandles = array();
72275
72276 private $readBytes = array(
72277 Process::STDOUT => 0,
72278 Process::STDERR => 0,
72279 );
72280
72281 private $disableOutput;
72282
72283 public function __construct($disableOutput, $input)
72284 {
72285 $this->disableOutput = (bool) $disableOutput;
72286
72287 if (!$this->disableOutput) {
72288
72289  
72290  
72291  
72292  $pipes = array(
72293 Process::STDOUT => Process::OUT,
72294 Process::STDERR => Process::ERR,
72295 );
72296 $tmpCheck = false;
72297 $tmpDir = sys_get_temp_dir();
72298 $lastError = 'unknown reason';
72299 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
72300 for ($i = 0;; ++$i) {
72301 foreach ($pipes as $pipe => $name) {
72302 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
72303 if (file_exists($file) && !unlink($file)) {
72304 continue 2;
72305 }
72306 $h = fopen($file, 'xb');
72307 if (!$h) {
72308 $error = $lastError;
72309 if ($tmpCheck || $tmpCheck = unlink(tempnam(false, 'sf_check_'))) {
72310 continue;
72311 }
72312 restore_error_handler();
72313 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error));
72314 }
72315 if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) {
72316 continue 2;
72317 }
72318 if (isset($this->files[$pipe])) {
72319 unlink($this->files[$pipe]);
72320 }
72321 $this->files[$pipe] = $file;
72322 }
72323 break;
72324 }
72325 restore_error_handler();
72326 }
72327
72328 parent::__construct($input);
72329 }
72330
72331 public function __destruct()
72332 {
72333 $this->close();
72334 $this->removeFiles();
72335 }
72336
72337
72338
72339
72340 public function getDescriptors()
72341 {
72342 if ($this->disableOutput) {
72343 $nullstream = fopen('NUL', 'c');
72344
72345 return array(
72346 array('pipe', 'r'),
72347 $nullstream,
72348 $nullstream,
72349 );
72350 }
72351
72352
72353  
72354  
72355  return array(
72356 array('pipe', 'r'),
72357 array('file', 'NUL', 'w'),
72358 array('file', 'NUL', 'w'),
72359 );
72360 }
72361
72362
72363
72364
72365 public function getFiles()
72366 {
72367 return $this->files;
72368 }
72369
72370
72371
72372
72373 public function readAndWrite($blocking, $close = false)
72374 {
72375 $this->unblock();
72376 $w = $this->write();
72377 $read = $r = $e = array();
72378
72379 if ($blocking) {
72380 if ($w) {
72381 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
72382 } elseif ($this->fileHandles) {
72383 usleep(Process::TIMEOUT_PRECISION * 1E6);
72384 }
72385 }
72386 foreach ($this->fileHandles as $type => $fileHandle) {
72387 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
72388
72389 if (isset($data[0])) {
72390 $this->readBytes[$type] += strlen($data);
72391 $read[$type] = $data;
72392 }
72393 if ($close) {
72394 fclose($fileHandle);
72395 unset($this->fileHandles[$type]);
72396 }
72397 }
72398
72399 return $read;
72400 }
72401
72402
72403
72404
72405 public function areOpen()
72406 {
72407 return $this->pipes && $this->fileHandles;
72408 }
72409
72410
72411
72412
72413 public function close()
72414 {
72415 parent::close();
72416 foreach ($this->fileHandles as $handle) {
72417 fclose($handle);
72418 }
72419 $this->fileHandles = array();
72420 }
72421
72422
72423
72424
72425
72426
72427
72428
72429
72430 public static function create(Process $process, $input)
72431 {
72432 return new static($process->isOutputDisabled(), $input);
72433 }
72434
72435
72436
72437
72438 private function removeFiles()
72439 {
72440 foreach ($this->files as $filename) {
72441 if (file_exists($filename)) {
72442 @unlink($filename);
72443 }
72444 }
72445 $this->files = array();
72446 }
72447 }
72448 <?php
72449
72450
72451
72452
72453
72454
72455
72456
72457
72458
72459 namespace Symfony\Component\Process;
72460
72461 use Symfony\Component\Process\Exception\InvalidArgumentException;
72462 use Symfony\Component\Process\Exception\LogicException;
72463 use Symfony\Component\Process\Exception\ProcessFailedException;
72464 use Symfony\Component\Process\Exception\ProcessTimedOutException;
72465 use Symfony\Component\Process\Exception\RuntimeException;
72466 use Symfony\Component\Process\Pipes\PipesInterface;
72467 use Symfony\Component\Process\Pipes\UnixPipes;
72468 use Symfony\Component\Process\Pipes\WindowsPipes;
72469
72470
72471
72472
72473
72474
72475
72476
72477 class Process
72478 {
72479 const ERR = 'err';
72480 const OUT = 'out';
72481
72482 const STATUS_READY = 'ready';
72483 const STATUS_STARTED = 'started';
72484 const STATUS_TERMINATED = 'terminated';
72485
72486 const STDIN = 0;
72487 const STDOUT = 1;
72488 const STDERR = 2;
72489
72490
72491  const TIMEOUT_PRECISION = 0.2;
72492
72493 private $callback;
72494 private $commandline;
72495 private $cwd;
72496 private $env;
72497 private $input;
72498 private $starttime;
72499 private $lastOutputTime;
72500 private $timeout;
72501 private $idleTimeout;
72502 private $options;
72503 private $exitcode;
72504 private $fallbackStatus = array();
72505 private $processInformation;
72506 private $outputDisabled = false;
72507 private $stdout;
72508 private $stderr;
72509 private $enhanceWindowsCompatibility = true;
72510 private $enhanceSigchildCompatibility;
72511 private $process;
72512 private $status = self::STATUS_READY;
72513 private $incrementalOutputOffset = 0;
72514 private $incrementalErrorOutputOffset = 0;
72515 private $tty;
72516 private $pty;
72517
72518 private $useFileHandles = false;
72519
72520 private $processPipes;
72521
72522 private $latestSignal;
72523
72524 private static $sigchild;
72525
72526
72527
72528
72529
72530
72531
72532
72533 public static $exitCodes = array(
72534 0 => 'OK',
72535 1 => 'General error',
72536 2 => 'Misuse of shell builtins',
72537
72538 126 => 'Invoked command cannot execute',
72539 127 => 'Command not found',
72540 128 => 'Invalid exit argument',
72541
72542
72543  129 => 'Hangup',
72544 130 => 'Interrupt',
72545 131 => 'Quit and dump core',
72546 132 => 'Illegal instruction',
72547 133 => 'Trace/breakpoint trap',
72548 134 => 'Process aborted',
72549 135 => 'Bus error: "access to undefined portion of memory object"',
72550 136 => 'Floating point exception: "erroneous arithmetic operation"',
72551 137 => 'Kill (terminate immediately)',
72552 138 => 'User-defined 1',
72553 139 => 'Segmentation violation',
72554 140 => 'User-defined 2',
72555 141 => 'Write to pipe with no one reading',
72556 142 => 'Signal raised by alarm',
72557 143 => 'Termination (request to terminate)',
72558
72559  145 => 'Child process terminated, stopped (or continued*)',
72560 146 => 'Continue if stopped',
72561 147 => 'Stop executing temporarily',
72562 148 => 'Terminal stop signal',
72563 149 => 'Background process attempting to read from tty ("in")',
72564 150 => 'Background process attempting to write to tty ("out")',
72565 151 => 'Urgent data available on socket',
72566 152 => 'CPU time limit exceeded',
72567 153 => 'File size limit exceeded',
72568 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
72569 155 => 'Profiling timer expired',
72570
72571  157 => 'Pollable event',
72572
72573  159 => 'Bad syscall',
72574 );
72575
72576
72577
72578
72579
72580
72581
72582
72583
72584
72585
72586
72587
72588 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
72589 {
72590 if (!function_exists('proc_open')) {
72591 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
72592 }
72593
72594 $this->commandline = $commandline;
72595 $this->cwd = $cwd;
72596
72597
72598  
72599  
72600  
72601  if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || '\\' === DIRECTORY_SEPARATOR)) {
72602 $this->cwd = getcwd();
72603 }
72604 if (null !== $env) {
72605 $this->setEnv($env);
72606 }
72607
72608 $this->setInput($input);
72609 $this->setTimeout($timeout);
72610 $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR;
72611 $this->pty = false;
72612 $this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
72613 $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
72614 }
72615
72616 public function __destruct()
72617 {
72618 $this->stop(0);
72619 }
72620
72621 public function __clone()
72622 {
72623 $this->resetProcessData();
72624 }
72625
72626
72627
72628
72629
72630
72631
72632
72633
72634
72635
72636
72637
72638
72639
72640
72641
72642
72643
72644
72645 public function run($callback = null)
72646 {
72647 $this->start($callback);
72648
72649 return $this->wait();
72650 }
72651
72652
72653
72654
72655
72656
72657
72658
72659
72660
72661
72662
72663
72664
72665 public function mustRun($callback = null)
72666 {
72667 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
72668 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
72669 }
72670
72671 if (0 !== $this->run($callback)) {
72672 throw new ProcessFailedException($this);
72673 }
72674
72675 return $this;
72676 }
72677
72678
72679
72680
72681
72682
72683
72684
72685
72686
72687
72688
72689
72690
72691
72692
72693
72694
72695
72696
72697 public function start($callback = null)
72698 {
72699 if ($this->isRunning()) {
72700 throw new RuntimeException('Process is already running');
72701 }
72702 if ($this->outputDisabled && null !== $callback) {
72703 throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
72704 }
72705
72706 $this->resetProcessData();
72707 $this->starttime = $this->lastOutputTime = microtime(true);
72708 $this->callback = $this->buildCallback($callback);
72709 $descriptors = $this->getDescriptors();
72710
72711 $commandline = $this->commandline;
72712
72713 if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
72714 $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')';
72715 foreach ($this->processPipes->getFiles() as $offset => $filename) {
72716 $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
72717 }
72718 $commandline .= '"';
72719
72720 if (!isset($this->options['bypass_shell'])) {
72721 $this->options['bypass_shell'] = true;
72722 }
72723 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
72724
72725  $descriptors[3] = array('pipe', 'w');
72726
72727
72728  $commandline = '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
72729 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
72730
72731
72732  
72733  $ptsWorkaround = fopen(__FILE__, 'r');
72734 }
72735
72736 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
72737
72738 if (!is_resource($this->process)) {
72739 throw new RuntimeException('Unable to launch a new process.');
72740 }
72741 $this->status = self::STATUS_STARTED;
72742
72743 if (isset($descriptors[3])) {
72744 $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
72745 }
72746
72747 if ($this->tty) {
72748 return;
72749 }
72750
72751 $this->updateStatus(false);
72752 $this->checkTimeout();
72753 }
72754
72755
72756
72757
72758
72759
72760
72761
72762
72763
72764
72765
72766
72767
72768
72769
72770 public function restart($callback = null)
72771 {
72772 if ($this->isRunning()) {
72773 throw new RuntimeException('Process is already running');
72774 }
72775
72776 $process = clone $this;
72777 $process->start($callback);
72778
72779 return $process;
72780 }
72781
72782
72783
72784
72785
72786
72787
72788
72789
72790
72791
72792
72793
72794
72795
72796
72797 public function wait($callback = null)
72798 {
72799 $this->requireProcessIsStarted(__FUNCTION__);
72800
72801 $this->updateStatus(false);
72802 if (null !== $callback) {
72803 $this->callback = $this->buildCallback($callback);
72804 }
72805
72806 do {
72807 $this->checkTimeout();
72808 $running = '\\' === DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
72809 $this->readPipes($running, '\\' !== DIRECTORY_SEPARATOR || !$running);
72810 } while ($running);
72811
72812 while ($this->isRunning()) {
72813 usleep(1000);
72814 }
72815
72816 if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
72817 throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
72818 }
72819
72820 return $this->exitcode;
72821 }
72822
72823
72824
72825
72826
72827
72828 public function getPid()
72829 {
72830 return $this->isRunning() ? $this->processInformation['pid'] : null;
72831 }
72832
72833
72834
72835
72836
72837
72838
72839
72840
72841
72842
72843
72844 public function signal($signal)
72845 {
72846 $this->doSignal($signal, true);
72847
72848 return $this;
72849 }
72850
72851
72852
72853
72854
72855
72856
72857
72858
72859 public function disableOutput()
72860 {
72861 if ($this->isRunning()) {
72862 throw new RuntimeException('Disabling output while the process is running is not possible.');
72863 }
72864 if (null !== $this->idleTimeout) {
72865 throw new LogicException('Output can not be disabled while an idle timeout is set.');
72866 }
72867
72868 $this->outputDisabled = true;
72869
72870 return $this;
72871 }
72872
72873
72874
72875
72876
72877
72878
72879
72880 public function enableOutput()
72881 {
72882 if ($this->isRunning()) {
72883 throw new RuntimeException('Enabling output while the process is running is not possible.');
72884 }
72885
72886 $this->outputDisabled = false;
72887
72888 return $this;
72889 }
72890
72891
72892
72893
72894
72895
72896 public function isOutputDisabled()
72897 {
72898 return $this->outputDisabled;
72899 }
72900
72901
72902
72903
72904
72905
72906
72907
72908
72909 public function getOutput()
72910 {
72911 $this->readPipesForOutput(__FUNCTION__);
72912
72913 if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
72914 return '';
72915 }
72916
72917 return $ret;
72918 }
72919
72920
72921
72922
72923
72924
72925
72926
72927
72928
72929
72930
72931 public function getIncrementalOutput()
72932 {
72933 $this->readPipesForOutput(__FUNCTION__);
72934
72935 $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
72936 $this->incrementalOutputOffset = ftell($this->stdout);
72937
72938 if (false === $latest) {
72939 return '';
72940 }
72941
72942 return $latest;
72943 }
72944
72945
72946
72947
72948
72949
72950 public function clearOutput()
72951 {
72952 ftruncate($this->stdout, 0);
72953 fseek($this->stdout, 0);
72954 $this->incrementalOutputOffset = 0;
72955
72956 return $this;
72957 }
72958
72959
72960
72961
72962
72963
72964
72965
72966
72967 public function getErrorOutput()
72968 {
72969 $this->readPipesForOutput(__FUNCTION__);
72970
72971 if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
72972 return '';
72973 }
72974
72975 return $ret;
72976 }
72977
72978
72979
72980
72981
72982
72983
72984
72985
72986
72987
72988
72989
72990 public function getIncrementalErrorOutput()
72991 {
72992 $this->readPipesForOutput(__FUNCTION__);
72993
72994 $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
72995 $this->incrementalErrorOutputOffset = ftell($this->stderr);
72996
72997 if (false === $latest) {
72998 return '';
72999 }
73000
73001 return $latest;
73002 }
73003
73004
73005
73006
73007
73008
73009 public function clearErrorOutput()
73010 {
73011 ftruncate($this->stderr, 0);
73012 fseek($this->stderr, 0);
73013 $this->incrementalErrorOutputOffset = 0;
73014
73015 return $this;
73016 }
73017
73018
73019
73020
73021
73022
73023
73024
73025 public function getExitCode()
73026 {
73027 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73028 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
73029 }
73030
73031 $this->updateStatus(false);
73032
73033 return $this->exitcode;
73034 }
73035
73036
73037
73038
73039
73040
73041
73042
73043
73044
73045
73046
73047 public function getExitCodeText()
73048 {
73049 if (null === $exitcode = $this->getExitCode()) {
73050 return;
73051 }
73052
73053 return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
73054 }
73055
73056
73057
73058
73059
73060
73061 public function isSuccessful()
73062 {
73063 return 0 === $this->getExitCode();
73064 }
73065
73066
73067
73068
73069
73070
73071
73072
73073
73074
73075
73076 public function hasBeenSignaled()
73077 {
73078 $this->requireProcessIsTerminated(__FUNCTION__);
73079
73080 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73081 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
73082 }
73083
73084 return $this->processInformation['signaled'];
73085 }
73086
73087
73088
73089
73090
73091
73092
73093
73094
73095
73096
73097 public function getTermSignal()
73098 {
73099 $this->requireProcessIsTerminated(__FUNCTION__);
73100
73101 if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) {
73102 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
73103 }
73104
73105 return $this->processInformation['termsig'];
73106 }
73107
73108
73109
73110
73111
73112
73113
73114
73115
73116
73117 public function hasBeenStopped()
73118 {
73119 $this->requireProcessIsTerminated(__FUNCTION__);
73120
73121 return $this->processInformation['stopped'];
73122 }
73123
73124
73125
73126
73127
73128
73129
73130
73131
73132
73133 public function getStopSignal()
73134 {
73135 $this->requireProcessIsTerminated(__FUNCTION__);
73136
73137 return $this->processInformation['stopsig'];
73138 }
73139
73140
73141
73142
73143
73144
73145 public function isRunning()
73146 {
73147 if (self::STATUS_STARTED !== $this->status) {
73148 return false;
73149 }
73150
73151 $this->updateStatus(false);
73152
73153 return $this->processInformation['running'];
73154 }
73155
73156
73157
73158
73159
73160
73161 public function isStarted()
73162 {
73163 return $this->status != self::STATUS_READY;
73164 }
73165
73166
73167
73168
73169
73170
73171 public function isTerminated()
73172 {
73173 $this->updateStatus(false);
73174
73175 return $this->status == self::STATUS_TERMINATED;
73176 }
73177
73178
73179
73180
73181
73182
73183
73184
73185 public function getStatus()
73186 {
73187 $this->updateStatus(false);
73188
73189 return $this->status;
73190 }
73191
73192
73193
73194
73195
73196
73197
73198
73199
73200 public function stop($timeout = 10, $signal = null)
73201 {
73202 $timeoutMicro = microtime(true) + $timeout;
73203 if ($this->isRunning()) {
73204
73205  $this->doSignal(15, false);
73206 do {
73207 usleep(1000);
73208 } while ($this->isRunning() && microtime(true) < $timeoutMicro);
73209
73210 if ($this->isRunning()) {
73211
73212  
73213  $this->doSignal($signal ?: 9, false);
73214 }
73215 }
73216
73217 if ($this->isRunning()) {
73218 if (isset($this->fallbackStatus['pid'])) {
73219 unset($this->fallbackStatus['pid']);
73220
73221 return $this->stop(0, $signal);
73222 }
73223 $this->close();
73224 }
73225
73226 return $this->exitcode;
73227 }
73228
73229
73230
73231
73232
73233
73234
73235
73236 public function addOutput($line)
73237 {
73238 $this->lastOutputTime = microtime(true);
73239
73240 fseek($this->stdout, 0, SEEK_END);
73241 fwrite($this->stdout, $line);
73242 fseek($this->stdout, $this->incrementalOutputOffset);
73243 }
73244
73245
73246
73247
73248
73249
73250
73251
73252 public function addErrorOutput($line)
73253 {
73254 $this->lastOutputTime = microtime(true);
73255
73256 fseek($this->stderr, 0, SEEK_END);
73257 fwrite($this->stderr, $line);
73258 fseek($this->stderr, $this->incrementalErrorOutputOffset);
73259 }
73260
73261
73262
73263
73264
73265
73266 public function getCommandLine()
73267 {
73268 return $this->commandline;
73269 }
73270
73271
73272
73273
73274
73275
73276
73277
73278 public function setCommandLine($commandline)
73279 {
73280 $this->commandline = $commandline;
73281
73282 return $this;
73283 }
73284
73285
73286
73287
73288
73289
73290 public function getTimeout()
73291 {
73292 return $this->timeout;
73293 }
73294
73295
73296
73297
73298
73299
73300 public function getIdleTimeout()
73301 {
73302 return $this->idleTimeout;
73303 }
73304
73305
73306
73307
73308
73309
73310
73311
73312
73313
73314
73315
73316 public function setTimeout($timeout)
73317 {
73318 $this->timeout = $this->validateTimeout($timeout);
73319
73320 return $this;
73321 }
73322
73323
73324
73325
73326
73327
73328
73329
73330
73331
73332
73333
73334
73335 public function setIdleTimeout($timeout)
73336 {
73337 if (null !== $timeout && $this->outputDisabled) {
73338 throw new LogicException('Idle timeout can not be set while the output is disabled.');
73339 }
73340
73341 $this->idleTimeout = $this->validateTimeout($timeout);
73342
73343 return $this;
73344 }
73345
73346
73347
73348
73349
73350
73351
73352
73353
73354
73355 public function setTty($tty)
73356 {
73357 if ('\\' === DIRECTORY_SEPARATOR && $tty) {
73358 throw new RuntimeException('TTY mode is not supported on Windows platform.');
73359 }
73360 if ($tty) {
73361 static $isTtySupported;
73362
73363 if (null === $isTtySupported) {
73364 $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);
73365 }
73366
73367 if (!$isTtySupported) {
73368 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
73369 }
73370 }
73371
73372 $this->tty = (bool) $tty;
73373
73374 return $this;
73375 }
73376
73377
73378
73379
73380
73381
73382 public function isTty()
73383 {
73384 return $this->tty;
73385 }
73386
73387
73388
73389
73390
73391
73392
73393
73394 public function setPty($bool)
73395 {
73396 $this->pty = (bool) $bool;
73397
73398 return $this;
73399 }
73400
73401
73402
73403
73404
73405
73406 public function isPty()
73407 {
73408 return $this->pty;
73409 }
73410
73411
73412
73413
73414
73415
73416 public function getWorkingDirectory()
73417 {
73418 if (null === $this->cwd) {
73419
73420  
73421  return getcwd() ?: null;
73422 }
73423
73424 return $this->cwd;
73425 }
73426
73427
73428
73429
73430
73431
73432
73433
73434 public function setWorkingDirectory($cwd)
73435 {
73436 $this->cwd = $cwd;
73437
73438 return $this;
73439 }
73440
73441
73442
73443
73444
73445
73446 public function getEnv()
73447 {
73448 return $this->env;
73449 }
73450
73451
73452
73453
73454
73455
73456
73457
73458
73459
73460
73461
73462
73463
73464 public function setEnv(array $env)
73465 {
73466
73467  $env = array_filter($env, function ($value) {
73468 return !is_array($value);
73469 });
73470
73471 $this->env = array();
73472 foreach ($env as $key => $value) {
73473 $this->env[$key] = (string) $value;
73474 }
73475
73476 return $this;
73477 }
73478
73479
73480
73481
73482
73483
73484
73485
73486
73487
73488 public function getStdin()
73489 {
73490 @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);
73491
73492 return $this->getInput();
73493 }
73494
73495
73496
73497
73498
73499
73500 public function getInput()
73501 {
73502 return $this->input;
73503 }
73504
73505
73506
73507
73508
73509
73510
73511
73512
73513
73514
73515
73516
73517
73518 public function setStdin($stdin)
73519 {
73520 @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);
73521
73522 return $this->setInput($stdin);
73523 }
73524
73525
73526
73527
73528
73529
73530
73531
73532
73533
73534
73535
73536
73537
73538 public function setInput($input)
73539 {
73540 if ($this->isRunning()) {
73541 throw new LogicException('Input can not be set while the process is running.');
73542 }
73543
73544 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
73545
73546 return $this;
73547 }
73548
73549
73550
73551
73552
73553
73554 public function getOptions()
73555 {
73556 return $this->options;
73557 }
73558
73559
73560
73561
73562
73563
73564
73565
73566 public function setOptions(array $options)
73567 {
73568 $this->options = $options;
73569
73570 return $this;
73571 }
73572
73573
73574
73575
73576
73577
73578
73579
73580 public function getEnhanceWindowsCompatibility()
73581 {
73582 return $this->enhanceWindowsCompatibility;
73583 }
73584
73585
73586
73587
73588
73589
73590
73591
73592 public function setEnhanceWindowsCompatibility($enhance)
73593 {
73594 $this->enhanceWindowsCompatibility = (bool) $enhance;
73595
73596 return $this;
73597 }
73598
73599
73600
73601
73602
73603
73604 public function getEnhanceSigchildCompatibility()
73605 {
73606 return $this->enhanceSigchildCompatibility;
73607 }
73608
73609
73610
73611
73612
73613
73614
73615
73616
73617
73618
73619
73620 public function setEnhanceSigchildCompatibility($enhance)
73621 {
73622 $this->enhanceSigchildCompatibility = (bool) $enhance;
73623
73624 return $this;
73625 }
73626
73627
73628
73629
73630
73631
73632
73633
73634
73635 public function checkTimeout()
73636 {
73637 if ($this->status !== self::STATUS_STARTED) {
73638 return;
73639 }
73640
73641 if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
73642 $this->stop(0);
73643
73644 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
73645 }
73646
73647 if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
73648 $this->stop(0);
73649
73650 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
73651 }
73652 }
73653
73654
73655
73656
73657
73658
73659 public static function isPtySupported()
73660 {
73661 static $result;
73662
73663 if (null !== $result) {
73664 return $result;
73665 }
73666
73667 if ('\\' === DIRECTORY_SEPARATOR) {
73668 return $result = false;
73669 }
73670
73671 return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes);
73672 }
73673
73674
73675
73676
73677
73678
73679 private function getDescriptors()
73680 {
73681 if ('\\' === DIRECTORY_SEPARATOR) {
73682 $this->processPipes = WindowsPipes::create($this, $this->input);
73683 } else {
73684 $this->processPipes = UnixPipes::create($this, $this->input);
73685 }
73686
73687 return $this->processPipes->getDescriptors();
73688 }
73689
73690
73691
73692
73693
73694
73695
73696
73697
73698
73699
73700 protected function buildCallback($callback)
73701 {
73702 $that = $this;
73703 $out = self::OUT;
73704 $callback = function ($type, $data) use ($that, $callback, $out) {
73705 if ($out == $type) {
73706 $that->addOutput($data);
73707 } else {
73708 $that->addErrorOutput($data);
73709 }
73710
73711 if (null !== $callback) {
73712 call_user_func($callback, $type, $data);
73713 }
73714 };
73715
73716 return $callback;
73717 }
73718
73719
73720
73721
73722
73723
73724 protected function updateStatus($blocking)
73725 {
73726 if (self::STATUS_STARTED !== $this->status) {
73727 return;
73728 }
73729
73730 $this->processInformation = proc_get_status($this->process);
73731 $running = $this->processInformation['running'];
73732
73733 $this->readPipes($running && $blocking, '\\' !== DIRECTORY_SEPARATOR || !$running);
73734
73735 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73736 $this->processInformation = $this->fallbackStatus + $this->processInformation;
73737 }
73738
73739 if (!$running) {
73740 $this->close();
73741 }
73742 }
73743
73744
73745
73746
73747
73748
73749 protected function isSigchildEnabled()
73750 {
73751 if (null !== self::$sigchild) {
73752 return self::$sigchild;
73753 }
73754
73755 if (!function_exists('phpinfo') || defined('HHVM_VERSION')) {
73756 return self::$sigchild = false;
73757 }
73758
73759 ob_start();
73760 phpinfo(INFO_GENERAL);
73761
73762 return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
73763 }
73764
73765
73766
73767
73768
73769
73770
73771
73772 private function readPipesForOutput($caller)
73773 {
73774 if ($this->outputDisabled) {
73775 throw new LogicException('Output has been disabled.');
73776 }
73777
73778 $this->requireProcessIsStarted($caller);
73779
73780 $this->updateStatus(false);
73781 }
73782
73783
73784
73785
73786
73787
73788
73789
73790
73791
73792 private function validateTimeout($timeout)
73793 {
73794 $timeout = (float) $timeout;
73795
73796 if (0.0 === $timeout) {
73797 $timeout = null;
73798 } elseif ($timeout < 0) {
73799 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
73800 }
73801
73802 return $timeout;
73803 }
73804
73805
73806
73807
73808
73809
73810
73811 private function readPipes($blocking, $close)
73812 {
73813 $result = $this->processPipes->readAndWrite($blocking, $close);
73814
73815 $callback = $this->callback;
73816 foreach ($result as $type => $data) {
73817 if (3 !== $type) {
73818 $callback($type === self::STDOUT ? self::OUT : self::ERR, $data);
73819 } elseif (!isset($this->fallbackStatus['signaled'])) {
73820 $this->fallbackStatus['exitcode'] = (int) $data;
73821 }
73822 }
73823 }
73824
73825
73826
73827
73828
73829
73830 private function close()
73831 {
73832 $this->processPipes->close();
73833 if (is_resource($this->process)) {
73834 proc_close($this->process);
73835 }
73836 $this->exitcode = $this->processInformation['exitcode'];
73837 $this->status = self::STATUS_TERMINATED;
73838
73839 if (-1 === $this->exitcode) {
73840 if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
73841
73842  $this->exitcode = 128 + $this->processInformation['termsig'];
73843 } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73844 $this->processInformation['signaled'] = true;
73845 $this->processInformation['termsig'] = -1;
73846 }
73847 }
73848
73849
73850  
73851  
73852  $this->callback = null;
73853
73854 return $this->exitcode;
73855 }
73856
73857
73858
73859
73860 private function resetProcessData()
73861 {
73862 $this->starttime = null;
73863 $this->callback = null;
73864 $this->exitcode = null;
73865 $this->fallbackStatus = array();
73866 $this->processInformation = null;
73867 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
73868 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
73869 $this->process = null;
73870 $this->latestSignal = null;
73871 $this->status = self::STATUS_READY;
73872 $this->incrementalOutputOffset = 0;
73873 $this->incrementalErrorOutputOffset = 0;
73874 }
73875
73876
73877
73878
73879
73880
73881
73882
73883
73884
73885
73886
73887
73888 private function doSignal($signal, $throwException)
73889 {
73890 if (null === $pid = $this->getPid()) {
73891 if ($throwException) {
73892 throw new LogicException('Can not send signal on a non running process.');
73893 }
73894
73895 return false;
73896 }
73897
73898 if ('\\' === DIRECTORY_SEPARATOR) {
73899 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
73900 if ($exitCode && $this->isRunning()) {
73901 if ($throwException) {
73902 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
73903 }
73904
73905 return false;
73906 }
73907 } else {
73908 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
73909 $ok = @proc_terminate($this->process, $signal);
73910 } elseif (function_exists('posix_kill')) {
73911 $ok = @posix_kill($pid, $signal);
73912 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
73913 $ok = false === fgets($pipes[2]);
73914 }
73915 if (!$ok) {
73916 if ($throwException) {
73917 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
73918 }
73919
73920 return false;
73921 }
73922 }
73923
73924 $this->latestSignal = (int) $signal;
73925 $this->fallbackStatus['signaled'] = true;
73926 $this->fallbackStatus['exitcode'] = -1;
73927 $this->fallbackStatus['termsig'] = $this->latestSignal;
73928
73929 return true;
73930 }
73931
73932
73933
73934
73935
73936
73937
73938
73939 private function requireProcessIsStarted($functionName)
73940 {
73941 if (!$this->isStarted()) {
73942 throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
73943 }
73944 }
73945
73946
73947
73948
73949
73950
73951
73952
73953 private function requireProcessIsTerminated($functionName)
73954 {
73955 if (!$this->isTerminated()) {
73956 throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
73957 }
73958 }
73959 }
73960 <?php
73961
73962
73963
73964
73965
73966
73967
73968
73969
73970
73971 namespace Symfony\Component\Process;
73972
73973 use Symfony\Component\Process\Exception\InvalidArgumentException;
73974 use Symfony\Component\Process\Exception\LogicException;
73975
73976
73977
73978
73979
73980
73981 class ProcessBuilder
73982 {
73983 private $arguments;
73984 private $cwd;
73985 private $env = array();
73986 private $input;
73987 private $timeout = 60;
73988 private $options = array();
73989 private $inheritEnv = true;
73990 private $prefix = array();
73991 private $outputDisabled = false;
73992
73993
73994
73995
73996
73997
73998 public function __construct(array $arguments = array())
73999 {
74000 $this->arguments = $arguments;
74001 }
74002
74003
74004
74005
74006
74007
74008
74009
74010 public static function create(array $arguments = array())
74011 {
74012 return new static($arguments);
74013 }
74014
74015
74016
74017
74018
74019
74020
74021
74022 public function add($argument)
74023 {
74024 $this->arguments[] = $argument;
74025
74026 return $this;
74027 }
74028
74029
74030
74031
74032
74033
74034
74035
74036
74037
74038 public function setPrefix($prefix)
74039 {
74040 $this->prefix = is_array($prefix) ? $prefix : array($prefix);
74041
74042 return $this;
74043 }
74044
74045
74046
74047
74048
74049
74050
74051
74052
74053
74054
74055 public function setArguments(array $arguments)
74056 {
74057 $this->arguments = $arguments;
74058
74059 return $this;
74060 }
74061
74062
74063
74064
74065
74066
74067
74068
74069 public function setWorkingDirectory($cwd)
74070 {
74071 $this->cwd = $cwd;
74072
74073 return $this;
74074 }
74075
74076
74077
74078
74079
74080
74081
74082
74083 public function inheritEnvironmentVariables($inheritEnv = true)
74084 {
74085 $this->inheritEnv = $inheritEnv;
74086
74087 return $this;
74088 }
74089
74090
74091
74092
74093
74094
74095
74096
74097
74098
74099
74100
74101 public function setEnv($name, $value)
74102 {
74103 $this->env[$name] = $value;
74104
74105 return $this;
74106 }
74107
74108
74109
74110
74111
74112
74113
74114
74115
74116
74117
74118
74119 public function addEnvironmentVariables(array $variables)
74120 {
74121 $this->env = array_replace($this->env, $variables);
74122
74123 return $this;
74124 }
74125
74126
74127
74128
74129
74130
74131
74132
74133
74134
74135
74136
74137 public function setInput($input)
74138 {
74139 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
74140
74141 return $this;
74142 }
74143
74144
74145
74146
74147
74148
74149
74150
74151
74152
74153
74154
74155 public function setTimeout($timeout)
74156 {
74157 if (null === $timeout) {
74158 $this->timeout = null;
74159
74160 return $this;
74161 }
74162
74163 $timeout = (float) $timeout;
74164
74165 if ($timeout < 0) {
74166 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
74167 }
74168
74169 $this->timeout = $timeout;
74170
74171 return $this;
74172 }
74173
74174
74175
74176
74177
74178
74179
74180
74181
74182 public function setOption($name, $value)
74183 {
74184 $this->options[$name] = $value;
74185
74186 return $this;
74187 }
74188
74189
74190
74191
74192
74193
74194 public function disableOutput()
74195 {
74196 $this->outputDisabled = true;
74197
74198 return $this;
74199 }
74200
74201
74202
74203
74204
74205
74206 public function enableOutput()
74207 {
74208 $this->outputDisabled = false;
74209
74210 return $this;
74211 }
74212
74213
74214
74215
74216
74217
74218
74219
74220 public function getProcess()
74221 {
74222 if (0 === count($this->prefix) && 0 === count($this->arguments)) {
74223 throw new LogicException('You must add() command arguments before calling getProcess().');
74224 }
74225
74226 $options = $this->options;
74227
74228 $arguments = array_merge($this->prefix, $this->arguments);
74229 $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
74230
74231 if ($this->inheritEnv) {
74232
74233  $env = array_replace($_ENV, $_SERVER, $this->env);
74234 } else {
74235 $env = $this->env;
74236 }
74237
74238 $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
74239
74240 if ($this->outputDisabled) {
74241 $process->disableOutput();
74242 }
74243
74244 return $process;
74245 }
74246 }
74247 <?php
74248
74249
74250
74251
74252
74253
74254
74255
74256
74257
74258 namespace Symfony\Component\Process;
74259
74260 use Symfony\Component\Process\Exception\InvalidArgumentException;
74261
74262
74263
74264
74265
74266
74267
74268
74269 class ProcessUtils
74270 {
74271
74272
74273
74274 private function __construct()
74275 {
74276 }
74277
74278
74279
74280
74281
74282
74283
74284
74285 public static function escapeArgument($argument)
74286 {
74287
74288  
74289  
74290  
74291  if ('\\' === DIRECTORY_SEPARATOR) {
74292 if ('' === $argument) {
74293 return escapeshellarg($argument);
74294 }
74295
74296 $escapedArgument = '';
74297 $quote = false;
74298 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
74299 if ('"' === $part) {
74300 $escapedArgument .= '\\"';
74301 } elseif (self::isSurroundedBy($part, '%')) {
74302
74303  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
74304 } else {
74305
74306  if ('\\' === substr($part, -1)) {
74307 $part .= '\\';
74308 }
74309 $quote = true;
74310 $escapedArgument .= $part;
74311 }
74312 }
74313 if ($quote) {
74314 $escapedArgument = '"'.$escapedArgument.'"';
74315 }
74316
74317 return $escapedArgument;
74318 }
74319
74320 return "'".str_replace("'", "'\\''", $argument)."'";
74321 }
74322
74323
74324
74325
74326
74327
74328
74329
74330
74331
74332
74333
74334
74335 public static function validateInput($caller, $input)
74336 {
74337 if (null !== $input) {
74338 if (is_resource($input)) {
74339 return $input;
74340 }
74341 if (is_string($input)) {
74342 return $input;
74343 }
74344 if (is_scalar($input)) {
74345 return (string) $input;
74346 }
74347
74348  if (is_object($input) && method_exists($input, '__toString')) {
74349 @trigger_error('Passing an object as an input is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
74350
74351 return (string) $input;
74352 }
74353
74354 throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
74355 }
74356
74357 return $input;
74358 }
74359
74360 private static function isSurroundedBy($arg, $char)
74361 {
74362 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
74363 }
74364 }
74365 Copyright (c) 2011 Jordi Boggiano
74366
74367 Permission is hereby granted, free of charge, to any person obtaining a copy
74368 of this software and associated documentation files (the "Software"), to deal
74369 in the Software without restriction, including without limitation the rights
74370 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
74371 copies of the Software, and to permit persons to whom the Software is furnished
74372 to do so, subject to the following conditions:
74373
74374 The above copyright notice and this permission notice shall be included in all
74375 copies or substantial portions of the Software.
74376
74377 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
74378 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74379 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
74380 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74381 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
74382 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
74383 THE SOFTWARE.
74384 <?php
74385
74386
74387
74388
74389
74390
74391
74392
74393
74394
74395 namespace Seld\JsonLint;
74396
74397 class DuplicateKeyException extends ParsingException
74398 {
74399 public function __construct($message, $key, array $details = array())
74400 {
74401 $details['key'] = $key;
74402 parent::__construct($message, $details);
74403 }
74404
74405 public function getKey()
74406 {
74407 return $this->details['key'];
74408 }
74409 }
74410 <?php
74411
74412
74413
74414
74415
74416
74417
74418
74419
74420
74421 namespace Seld\JsonLint;
74422 use stdClass;
74423
74424
74425
74426
74427
74428
74429
74430
74431
74432
74433
74434
74435
74436
74437 class JsonParser
74438 {
74439 const DETECT_KEY_CONFLICTS = 1;
74440 const ALLOW_DUPLICATE_KEYS = 2;
74441 const PARSE_TO_ASSOC = 4;
74442
74443 private $lexer;
74444
74445 private $flags;
74446 private $stack;
74447 private $vstack; 
74448  private $lstack; 
74449
74450 private $symbols = array(
74451 'error' => 2,
74452 'JSONString' => 3,
74453 'STRING' => 4,
74454 'JSONNumber' => 5,
74455 'NUMBER' => 6,
74456 'JSONNullLiteral' => 7,
74457 'NULL' => 8,
74458 'JSONBooleanLiteral' => 9,
74459 'TRUE' => 10,
74460 'FALSE' => 11,
74461 'JSONText' => 12,
74462 'JSONValue' => 13,
74463 'EOF' => 14,
74464 'JSONObject' => 15,
74465 'JSONArray' => 16,
74466 '{' => 17,
74467 '}' => 18,
74468 'JSONMemberList' => 19,
74469 'JSONMember' => 20,
74470 ':' => 21,
74471 ',' => 22,
74472 '[' => 23,
74473 ']' => 24,
74474 'JSONElementList' => 25,
74475 '$accept' => 0,
74476 '$end' => 1,
74477 );
74478
74479 private $terminals_ = array(
74480 2 => "error",
74481 4 => "STRING",
74482 6 => "NUMBER",
74483 8 => "NULL",
74484 10 => "TRUE",
74485 11 => "FALSE",
74486 14 => "EOF",
74487 17 => "{",
74488 18 => "}",
74489 21 => ":",
74490 22 => ",",
74491 23 => "[",
74492 24 => "]",
74493 );
74494
74495 private $productions_ = array(
74496 0,
74497 array(3, 1),
74498 array(5, 1),
74499 array(7, 1),
74500 array(9, 1),
74501 array(9, 1),
74502 array(12, 2),
74503 array(13, 1),
74504 array(13, 1),
74505 array(13, 1),
74506 array(13, 1),
74507 array(13, 1),
74508 array(13, 1),
74509 array(15, 2),
74510 array(15, 3),
74511 array(20, 3),
74512 array(19, 1),
74513 array(19, 3),
74514 array(16, 2),
74515 array(16, 3),
74516 array(25, 1),
74517 array(25, 3)
74518 );
74519
74520 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)),
74521 );
74522
74523 private $defaultActions = array(
74524 16 => array(2, 6)
74525 );
74526
74527
74528
74529
74530
74531
74532 public function lint($input, $flags = 0)
74533 {
74534 try {
74535 $this->parse($input, $flags);
74536 } catch (ParsingException $e) {
74537 return $e;
74538 }
74539 }
74540
74541
74542
74543
74544
74545
74546
74547 public function parse($input, $flags = 0)
74548 {
74549 $this->failOnBOM($input);
74550
74551 $this->flags = $flags;
74552
74553 $this->stack = array(0);
74554 $this->vstack = array(null);
74555 $this->lstack = array();
74556
74557 $yytext = '';
74558 $yylineno = 0;
74559 $yyleng = 0;
74560 $recovering = 0;
74561 $TERROR = 2;
74562 $EOF = 1;
74563
74564 $this->lexer = new Lexer();
74565 $this->lexer->setInput($input);
74566
74567 $yyloc = $this->lexer->yylloc;
74568 $this->lstack[] = $yyloc;
74569
74570 $symbol = null;
74571 $preErrorSymbol = null;
74572 $state = null;
74573 $action = null;
74574 $a = null;
74575 $r = null;
74576 $yyval = new stdClass;
74577 $p = null;
74578 $len = null;
74579 $newState = null;
74580 $expected = null;
74581 $errStr = null;
74582
74583 while (true) {
74584
74585  $state = $this->stack[count($this->stack)-1];
74586
74587
74588  if (isset($this->defaultActions[$state])) {
74589 $action = $this->defaultActions[$state];
74590 } else {
74591 if ($symbol == null) {
74592 $symbol = $this->lex();
74593 }
74594
74595  $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false;
74596 }
74597
74598
74599  if (!$action || !$action[0]) {
74600 if (!$recovering) {
74601
74602  $expected = array();
74603 foreach ($this->table[$state] as $p => $ignore) {
74604 if (isset($this->terminals_[$p]) && $p > 2) {
74605 $expected[] = "'" . $this->terminals_[$p] . "'";
74606 }
74607 }
74608
74609 $message = null;
74610 if (in_array("'STRING'", $expected) && in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
74611 $message = "Invalid string";
74612 if ("'" === substr($this->lexer->match, 0, 1)) {
74613 $message .= ", it appears you used single quotes instead of double quotes";
74614 } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u])}', $this->lexer->getUpcomingInput(), $match)) {
74615 $message .= ", it appears you have an unescaped backslash at: ".$match[1];
74616 } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getUpcomingInput())) {
74617 $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
74618 }
74619 }
74620
74621 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
74622 $errStr .= $this->lexer->showPosition() . "\n";
74623 if ($message) {
74624 $errStr .= $message;
74625 } else {
74626 $errStr .= (count($expected) > 1) ? "Expected one of: " : "Expected: ";
74627 $errStr .= implode(', ', $expected);
74628 }
74629
74630 if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
74631 $errStr .= " - It appears you have an extra trailing comma";
74632 }
74633
74634 $this->parseError($errStr, array(
74635 'text' => $this->lexer->match,
74636 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol,
74637 'line' => $this->lexer->yylineno,
74638 'loc' => $yyloc,
74639 'expected' => $expected,
74640 ));
74641 }
74642
74643
74644  if ($recovering == 3) {
74645 if ($symbol == $EOF) {
74646 throw new ParsingException($errStr ?: 'Parsing halted.');
74647 }
74648
74649
74650  $yyleng = $this->lexer->yyleng;
74651 $yytext = $this->lexer->yytext;
74652 $yylineno = $this->lexer->yylineno;
74653 $yyloc = $this->lexer->yylloc;
74654 $symbol = $this->lex();
74655 }
74656
74657
74658  while (true) {
74659
74660  if (array_key_exists($TERROR, $this->table[$state])) {
74661 break;
74662 }
74663 if ($state == 0) {
74664 throw new ParsingException($errStr ?: 'Parsing halted.');
74665 }
74666 $this->popStack(1);
74667 $state = $this->stack[count($this->stack)-1];
74668 }
74669
74670 $preErrorSymbol = $symbol; 
74671  $symbol = $TERROR; 
74672  $state = $this->stack[count($this->stack)-1];
74673 $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false;
74674 $recovering = 3; 
74675  }
74676
74677
74678  if (is_array($action[0]) && count($action) > 1) {
74679 throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
74680 }
74681
74682 switch ($action[0]) {
74683 case 1: 
74684  $this->stack[] = $symbol;
74685 $this->vstack[] = $this->lexer->yytext;
74686 $this->lstack[] = $this->lexer->yylloc;
74687 $this->stack[] = $action[1]; 
74688  $symbol = null;
74689 if (!$preErrorSymbol) { 
74690  $yyleng = $this->lexer->yyleng;
74691 $yytext = $this->lexer->yytext;
74692 $yylineno = $this->lexer->yylineno;
74693 $yyloc = $this->lexer->yylloc;
74694 if ($recovering > 0) {
74695 $recovering--;
74696 }
74697 } else { 
74698  $symbol = $preErrorSymbol;
74699 $preErrorSymbol = null;
74700 }
74701 break;
74702
74703 case 2: 
74704  $len = $this->productions_[$action[1]][1];
74705
74706
74707  $yyval->token = $this->vstack[count($this->vstack) - $len]; 
74708  
74709  $yyval->store = array( 
74710  'first_line' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_line'],
74711 'last_line' => $this->lstack[count($this->lstack) - 1]['last_line'],
74712 'first_column' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_column'],
74713 'last_column' => $this->lstack[count($this->lstack) - 1]['last_column'],
74714 );
74715 $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack, $this->lstack);
74716
74717 if (!$r instanceof Undefined) {
74718 return $r;
74719 }
74720
74721 if ($len) {
74722 $this->popStack($len);
74723 }
74724
74725 $this->stack[] = $this->productions_[$action[1]][0]; 
74726  $this->vstack[] = $yyval->token;
74727 $this->lstack[] = $yyval->store;
74728 $newState = $this->table[$this->stack[count($this->stack)-2]][$this->stack[count($this->stack)-1]];
74729 $this->stack[] = $newState;
74730 break;
74731
74732 case 3: 
74733
74734 return true;
74735 }
74736 }
74737
74738 return true;
74739 }
74740
74741 protected function parseError($str, $hash)
74742 {
74743 throw new ParsingException($str, $hash);
74744 }
74745
74746
74747  
74748  
74749  private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens)
74750 {
74751
74752  $len = count($tokens) - 1;
74753 switch ($yystate) {
74754 case 1:
74755 $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
74756 $yyval->token = $yytext;
74757 break;
74758 case 2:
74759 if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) {
74760 $yyval->token = floatval($yytext);
74761 } else {
74762 $yyval->token = strpos($yytext, '.') === false ? intval($yytext) : floatval($yytext);
74763 }
74764 break;
74765 case 3:
74766 $yyval->token = null;
74767 break;
74768 case 4:
74769 $yyval->token = true;
74770 break;
74771 case 5:
74772 $yyval->token = false;
74773 break;
74774 case 6:
74775 return $yyval->token = $tokens[$len-1];
74776 case 13:
74777 if ($this->flags & self::PARSE_TO_ASSOC) {
74778 $yyval->token = array();
74779 } else {
74780 $yyval->token = new stdClass;
74781 }
74782 break;
74783 case 14:
74784 $yyval->token = $tokens[$len-1];
74785 break;
74786 case 15:
74787 $yyval->token = array($tokens[$len-2], $tokens[$len]);
74788 break;
74789 case 16:
74790 if (PHP_VERSION_ID < 70100) {
74791 $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
74792 } else {
74793 $property = $tokens[$len][0];
74794 }
74795 if ($this->flags & self::PARSE_TO_ASSOC) {
74796 $yyval->token = array();
74797 $yyval->token[$property] = $tokens[$len][1];
74798 } else {
74799 $yyval->token = new stdClass;
74800 $yyval->token->$property = $tokens[$len][1];
74801 }
74802 break;
74803 case 17:
74804 if ($this->flags & self::PARSE_TO_ASSOC) {
74805 $yyval->token =& $tokens[$len-2];
74806 $key = $tokens[$len][0];
74807 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
74808 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
74809 $errStr .= $this->lexer->showPosition() . "\n";
74810 $errStr .= "Duplicate key: ".$tokens[$len][0];
74811 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
74812 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) {
74813 $duplicateCount = 1;
74814 do {
74815 $duplicateKey = $key . '.' . $duplicateCount++;
74816 } while (isset($tokens[$len-2][$duplicateKey]));
74817 $key = $duplicateKey;
74818 }
74819 $tokens[$len-2][$key] = $tokens[$len][1];
74820 } else {
74821 $yyval->token = $tokens[$len-2];
74822 if (PHP_VERSION_ID < 70100) {
74823 $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
74824 } else {
74825 $key = $tokens[$len][0];
74826 }
74827 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
74828 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
74829 $errStr .= $this->lexer->showPosition() . "\n";
74830 $errStr .= "Duplicate key: ".$tokens[$len][0];
74831 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
74832 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) {
74833 $duplicateCount = 1;
74834 do {
74835 $duplicateKey = $key . '.' . $duplicateCount++;
74836 } while (isset($tokens[$len-2]->$duplicateKey));
74837 $key = $duplicateKey;
74838 }
74839 $tokens[$len-2]->$key = $tokens[$len][1];
74840 }
74841 break;
74842 case 18:
74843 $yyval->token = array();
74844 break;
74845 case 19:
74846 $yyval->token = $tokens[$len-1];
74847 break;
74848 case 20:
74849 $yyval->token = array($tokens[$len]);
74850 break;
74851 case 21:
74852 $tokens[$len-2][] = $tokens[$len];
74853 $yyval->token = $tokens[$len-2];
74854 break;
74855 }
74856
74857 return new Undefined();
74858 }
74859
74860 private function stringInterpolation($match)
74861 {
74862 switch ($match[0]) {
74863 case '\\\\':
74864 return '\\';
74865 case '\"':
74866 return '"';
74867 case '\b':
74868 return chr(8);
74869 case '\f':
74870 return chr(12);
74871 case '\n':
74872 return "\n";
74873 case '\r':
74874 return "\r";
74875 case '\t':
74876 return "\t";
74877 case '\/':
74878 return "/";
74879 default:
74880 return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', 0, 'UTF-8');
74881 }
74882 }
74883
74884 private function popStack($n)
74885 {
74886 $this->stack = array_slice($this->stack, 0, - (2 * $n));
74887 $this->vstack = array_slice($this->vstack, 0, - $n);
74888 $this->lstack = array_slice($this->lstack, 0, - $n);
74889 }
74890
74891 private function lex()
74892 {
74893 $token = $this->lexer->lex() ?: 1; 
74894  
74895  if (!is_numeric($token)) {
74896 $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token;
74897 }
74898
74899 return $token;
74900 }
74901
74902 private function failOnBOM($input)
74903 {
74904
74905  $bom = "\xEF\xBB\xBF";
74906
74907 if (substr($input, 0, 3) === $bom) {
74908 $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array());
74909 }
74910 }
74911 }
74912 <?php
74913
74914
74915
74916
74917
74918
74919
74920
74921
74922
74923 namespace Seld\JsonLint;
74924
74925
74926
74927
74928
74929
74930 class Lexer
74931 {
74932 private $EOF = 1;
74933 private $rules = array(
74934 0 => '/^\s+/',
74935 1 => '/^-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/',
74936 2 => '{^"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x1f\\\\"]++)*+"}',
74937 3 => '/^\{/',
74938 4 => '/^\}/',
74939 5 => '/^\[/',
74940 6 => '/^\]/',
74941 7 => '/^,/',
74942 8 => '/^:/',
74943 9 => '/^true\b/',
74944 10 => '/^false\b/',
74945 11 => '/^null\b/',
74946 12 => '/^$/',
74947 13 => '/^./',
74948 );
74949
74950 private $conditions = array(
74951 "INITIAL" => array(
74952 "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13),
74953 "inclusive" => true,
74954 ),
74955 );
74956
74957 private $conditionStack;
74958 private $input;
74959 private $more;
74960 private $done;
74961 private $matched;
74962
74963 public $match;
74964 public $yylineno;
74965 public $yyleng;
74966 public $yytext;
74967 public $yylloc;
74968
74969 public function lex()
74970 {
74971 $r = $this->next();
74972 if (!$r instanceof Undefined) {
74973 return $r;
74974 }
74975
74976 return $this->lex();
74977 }
74978
74979 public function setInput($input)
74980 {
74981 $this->input = $input;
74982 $this->more = false;
74983 $this->done = false;
74984 $this->yylineno = $this->yyleng = 0;
74985 $this->yytext = $this->matched = $this->match = '';
74986 $this->conditionStack = array('INITIAL');
74987 $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
74988
74989 return $this;
74990 }
74991
74992 public function showPosition()
74993 {
74994 $pre = str_replace("\n", '', $this->getPastInput());
74995 $c = str_repeat('-', max(0, strlen($pre) - 1)); 
74996
74997 return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
74998 }
74999
75000 public function getPastInput()
75001 {
75002 $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match));
75003
75004 return (strlen($past) > 20 ? '...' : '') . substr($past, -20);
75005 }
75006
75007 public function getUpcomingInput()
75008 {
75009 $next = $this->match;
75010 if (strlen($next) < 20) {
75011 $next .= substr($this->input, 0, 20 - strlen($next));
75012 }
75013
75014 return substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '');
75015 }
75016
75017 protected function parseError($str, $hash)
75018 {
75019 throw new \Exception($str);
75020 }
75021
75022 private function next()
75023 {
75024 if ($this->done) {
75025 return $this->EOF;
75026 }
75027 if ($this->input === '') {
75028 $this->done = true;
75029 }
75030
75031 $token = null;
75032 $match = null;
75033 $col = null;
75034 $lines = null;
75035
75036 if (!$this->more) {
75037 $this->yytext = '';
75038 $this->match = '';
75039 }
75040
75041 $rules = $this->getCurrentRules();
75042 $rulesLen = count($rules);
75043
75044 for ($i=0; $i < $rulesLen; $i++) {
75045 if (preg_match($this->rules[$rules[$i]], $this->input, $match)) {
75046 preg_match_all('/\n.*/', $match[0], $lines);
75047 $lines = $lines[0];
75048 if ($lines) {
75049 $this->yylineno += count($lines);
75050 }
75051
75052 $this->yylloc = array(
75053 'first_line' => $this->yylloc['last_line'],
75054 'last_line' => $this->yylineno+1,
75055 'first_column' => $this->yylloc['last_column'],
75056 'last_column' => $lines ? strlen($lines[count($lines) - 1]) - 1 : $this->yylloc['last_column'] + strlen($match[0]),
75057 );
75058 $this->yytext .= $match[0];
75059 $this->match .= $match[0];
75060 $this->yyleng = strlen($this->yytext);
75061 $this->more = false;
75062 $this->input = substr($this->input, strlen($match[0]));
75063 $this->matched .= $match[0];
75064 $token = $this->performAction($rules[$i], $this->conditionStack[count($this->conditionStack)-1]);
75065 if ($token) {
75066 return $token;
75067 }
75068
75069 return new Undefined();
75070 }
75071 }
75072
75073 if ($this->input === "") {
75074 return $this->EOF;
75075 }
75076
75077 $this->parseError(
75078 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(),
75079 array(
75080 'text' => "",
75081 'token' => null,
75082 'line' => $this->yylineno,
75083 )
75084 );
75085 }
75086
75087 private function getCurrentRules()
75088 {
75089 return $this->conditions[$this->conditionStack[count($this->conditionStack)-1]]['rules'];
75090 }
75091
75092 private function performAction($avoiding_name_collisions, $YY_START)
75093 {
75094 switch ($avoiding_name_collisions) {
75095 case 0:
75096 break;
75097 case 1:
75098 return 6;
75099 break;
75100 case 2:
75101 $this->yytext = substr($this->yytext, 1, $this->yyleng-2);
75102
75103 return 4;
75104 case 3:
75105 return 17;
75106 case 4:
75107 return 18;
75108 case 5:
75109 return 23;
75110 case 6:
75111 return 24;
75112 case 7:
75113 return 22;
75114 case 8:
75115 return 21;
75116 case 9:
75117 return 10;
75118 case 10:
75119 return 11;
75120 case 11:
75121 return 8;
75122 case 12:
75123 return 14;
75124 case 13:
75125 return 'INVALID';
75126 }
75127 }
75128 }
75129 <?php
75130
75131
75132
75133
75134
75135
75136
75137
75138
75139
75140 namespace Seld\JsonLint;
75141
75142 class ParsingException extends \Exception
75143 {
75144 protected $details;
75145
75146 public function __construct($message, $details = array())
75147 {
75148 $this->details = $details;
75149 parent::__construct($message);
75150 }
75151
75152 public function getDetails()
75153 {
75154 return $this->details;
75155 }
75156 }
75157 <?php
75158
75159
75160
75161
75162
75163
75164
75165
75166
75167
75168 namespace Seld\JsonLint;
75169
75170 class Undefined
75171 {
75172 }
75173 Copyright (c) 2015 Jordi Boggiano
75174
75175 Permission is hereby granted, free of charge, to any person obtaining a copy
75176 of this software and associated documentation files (the "Software"), to deal
75177 in the Software without restriction, including without limitation the rights
75178 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75179 copies of the Software, and to permit persons to whom the Software is furnished
75180 to do so, subject to the following conditions:
75181
75182 The above copyright notice and this permission notice shall be included in all
75183 copies or substantial portions of the Software.
75184
75185 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75186 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75187 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75188 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75189 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75190 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75191 THE SOFTWARE.
75192 <?php
75193
75194 require __DIR__.'/../vendor/autoload.php';
75195
75196 echo 'Say hello (visible): ';
75197
75198 $answer = Seld\CliPrompt\CliPrompt::prompt();
75199
75200 echo 'You answered: '.$answer . PHP_EOL;
75201
75202 echo 'Say hello (hidden): ';
75203
75204 $answer = Seld\CliPrompt\CliPrompt::hiddenPrompt();
75205
75206 echo 'You answered: '.$answer . PHP_EOL;
75207 <?php
75208
75209
75210
75211
75212
75213
75214
75215
75216
75217
75218 namespace Seld\CliPrompt;
75219
75220 class CliPrompt
75221 {
75222
75223
75224
75225
75226
75227 public static function prompt()
75228 {
75229 $stdin = fopen('php://stdin', 'r');
75230 $answer = self::trimAnswer(fgets($stdin, 4096));
75231 fclose($stdin);
75232
75233 return $answer;
75234 }
75235
75236
75237
75238
75239
75240
75241
75242
75243
75244
75245 public static function hiddenPrompt($allowFallback = false)
75246 {
75247
75248  if (defined('PHP_WINDOWS_VERSION_BUILD')) {
75249
75250  $exe = __DIR__.'\\..\\res\\hiddeninput.exe';
75251
75252
75253  if ('phar:' === substr(__FILE__, 0, 5)) {
75254 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
75255
75256
75257  
75258  $source = fopen($exe, 'r');
75259 $target = fopen($tmpExe, 'w+');
75260 stream_copy_to_stream($source, $target);
75261 fclose($source);
75262 fclose($target);
75263 unset($source, $target);
75264
75265 $exe = $tmpExe;
75266 }
75267
75268 $output = shell_exec($exe);
75269
75270
75271  if (isset($tmpExe)) {
75272 unlink($tmpExe);
75273 }
75274
75275 if ($output !== null) {
75276
75277  echo PHP_EOL;
75278
75279 return self::trimAnswer($output);
75280 }
75281 }
75282
75283 if (file_exists('/usr/bin/env')) {
75284
75285  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
75286 foreach (array('bash', 'zsh', 'ksh', 'csh', 'sh') as $sh) {
75287 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
75288 $shell = $sh;
75289 break;
75290 }
75291 }
75292
75293 if (isset($shell)) {
75294 $readCmd = ($shell === 'csh') ? 'set mypassword = $<' : 'read -r mypassword';
75295 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
75296 $output = shell_exec($command);
75297
75298 if ($output !== null) {
75299
75300  echo PHP_EOL;
75301
75302 return self::trimAnswer($output);
75303 }
75304 }
75305 }
75306
75307
75308  if (!$allowFallback) {
75309 throw new \RuntimeException('Could not prompt for input in a secure fashion, aborting');
75310 }
75311
75312 return self::prompt();
75313 }
75314
75315 private static function trimAnswer($str)
75316 {
75317 return preg_replace('{\r?\n$}D', '', $str);
75318 }
75319 }
75320 MIT License
75321
75322 Copyright (c) 2016
75323
75324 Permission is hereby granted, free of charge, to any person obtaining a copy
75325 of this software and associated documentation files (the "Software"), to deal
75326 in the Software without restriction, including without limitation the rights
75327 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75328 copies of the Software, and to permit persons to whom the Software is
75329 furnished to do so, subject to the following conditions:
75330
75331 The above copyright notice and this permission notice shall be included in all
75332 copies or substantial portions of the Software.
75333
75334 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75335 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75336 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75337 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75338 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75339 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
75340 SOFTWARE.
75341 <?php
75342
75343 require __DIR__ . '/../vendor/autoload.php';
75344
75345 $data = json_decode(file_get_contents('data.json'));
75346
75347
75348 $validator = new JsonSchema\Validator();
75349 $validator->check($data, (object) array('$ref' => 'file://' . realpath('schema.json')));
75350
75351 if ($validator->isValid()) {
75352 echo "The supplied JSON validates against the schema.\n";
75353 } else {
75354 echo "JSON does not validate. Violations:\n";
75355 foreach ($validator->getErrors() as $error) {
75356 echo sprintf("[%s] %s\n", $error['property'], $error['message']);
75357 }
75358 }
75359 <?php
75360
75361
75362
75363
75364
75365
75366
75367
75368 namespace JsonSchema\Constraints;
75369
75370 use JsonSchema\Entity\JsonPointer;
75371 use JsonSchema\Exception\InvalidArgumentException;
75372 use JsonSchema\Exception\ValidationException;
75373 use JsonSchema\Validator;
75374
75375
75376
75377
75378
75379 class BaseConstraint
75380 {
75381
75382
75383
75384 protected $errors = array();
75385
75386
75387
75388
75389 protected $errorMask = Validator::ERROR_NONE;
75390
75391
75392
75393
75394 protected $factory;
75395
75396
75397
75398
75399 public function __construct(Factory $factory = null)
75400 {
75401 $this->factory = $factory ?: new Factory();
75402 }
75403
75404 public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null)
75405 {
75406 $error = array(
75407 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')),
75408 'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
75409 'message' => $message,
75410 'constraint' => $constraint,
75411 'context' => $this->factory->getErrorContext(),
75412 );
75413
75414 if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
75415 throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
75416 }
75417
75418 if (is_array($more) && count($more) > 0) {
75419 $error += $more;
75420 }
75421
75422 $this->errors[] = $error;
75423 $this->errorMask |= $error['context'];
75424 }
75425
75426 public function addErrors(array $errors)
75427 {
75428 if ($errors) {
75429 $this->errors = array_merge($this->errors, $errors);
75430 $errorMask = &$this->errorMask;
75431 array_walk($errors, function ($error) use (&$errorMask) {
75432 if (isset($error['context'])) {
75433 $errorMask |= $error['context'];
75434 }
75435 });
75436 }
75437 }
75438
75439 public function getErrors($errorContext = Validator::ERROR_ALL)
75440 {
75441 if ($errorContext === Validator::ERROR_ALL) {
75442 return $this->errors;
75443 }
75444
75445 return array_filter($this->errors, function ($error) use ($errorContext) {
75446 if ($errorContext & $error['context']) {
75447 return true;
75448 }
75449 });
75450 }
75451
75452 public function numErrors($errorContext = Validator::ERROR_ALL)
75453 {
75454 if ($errorContext === Validator::ERROR_ALL) {
75455 return count($this->errors);
75456 }
75457
75458 return count($this->getErrors($errorContext));
75459 }
75460
75461 public function isValid()
75462 {
75463 return !$this->getErrors();
75464 }
75465
75466
75467
75468
75469
75470 public function reset()
75471 {
75472 $this->errors = array();
75473 $this->errorMask = Validator::ERROR_NONE;
75474 }
75475
75476
75477
75478
75479
75480
75481 public function getErrorMask()
75482 {
75483 return $this->errorMask;
75484 }
75485
75486
75487
75488
75489
75490
75491
75492
75493 public static function arrayToObjectRecursive($array)
75494 {
75495 $json = json_encode($array);
75496 if (json_last_error() !== \JSON_ERROR_NONE) {
75497 $message = 'Unable to encode schema array as JSON';
75498 if (function_exists('json_last_error_msg')) {
75499 $message .= ': ' . json_last_error_msg();
75500 }
75501 throw new InvalidArgumentException($message);
75502 }
75503
75504 return (object) json_decode($json);
75505 }
75506 }
75507 <?php
75508
75509
75510
75511
75512
75513
75514
75515
75516 namespace JsonSchema\Constraints;
75517
75518 use JsonSchema\Entity\JsonPointer;
75519
75520
75521
75522
75523
75524
75525
75526 class CollectionConstraint extends Constraint
75527 {
75528
75529
75530
75531 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null)
75532 {
75533
75534  if (isset($schema->minItems) && count($value) < $schema->minItems) {
75535 $this->addError($path, 'There must be a minimum of ' . $schema->minItems . ' items in the array', 'minItems', array('minItems' => $schema->minItems));
75536 }
75537
75538
75539  if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
75540 $this->addError($path, 'There must be a maximum of ' . $schema->maxItems . ' items in the array', 'maxItems', array('maxItems' => $schema->maxItems));
75541 }
75542
75543
75544  if (isset($schema->uniqueItems) && $schema->uniqueItems) {
75545 $unique = $value;
75546 if (is_array($value) && count($value)) {
75547 $unique = array_map(function ($e) {
75548 return var_export($e, true);
75549 }, $value);
75550 }
75551 if (count(array_unique($unique)) != count($value)) {
75552 $this->addError($path, 'There are no duplicates allowed in the array', 'uniqueItems');
75553 }
75554 }
75555
75556
75557  if (isset($schema->items)) {
75558 $this->validateItems($value, $schema, $path, $i);
75559 }
75560 }
75561
75562
75563
75564
75565
75566
75567
75568
75569
75570 protected function validateItems(&$value, $schema = null, JsonPointer $path = null, $i = null)
75571 {
75572 if (is_object($schema->items)) {
75573
75574
75575 if (isset($schema->items->type)
75576 && (
75577 $schema->items->type == 'string'
75578 || $schema->items->type == 'number'
75579 || $schema->items->type == 'integer'
75580 )
75581 && !isset($schema->additionalItems)
75582 ) {
75583
75584  $type = $schema->items->type;
75585 $typeValidator = $this->factory->createInstanceFor('type');
75586 $validator = $this->factory->createInstanceFor($type === 'integer' ? 'number' : $type);
75587
75588 foreach ($value as $k => &$v) {
75589 $k_path = $this->incrementPath($path, $k);
75590 $typeValidator->check($v, $schema->items, $k_path, $i);
75591
75592 $validator->check($v, $schema->items, $k_path, $i);
75593 }
75594 unset($v); 
75595  
75596  $this->addErrors($typeValidator->getErrors());
75597 $this->addErrors($validator->getErrors());
75598 } else {
75599 foreach ($value as $k => &$v) {
75600 $initErrors = $this->getErrors();
75601
75602
75603  $this->checkUndefined($v, $schema->items, $path, $k);
75604
75605
75606  if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
75607 $secondErrors = $this->getErrors();
75608 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
75609 }
75610
75611
75612  if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
75613 $this->errors = $secondErrors;
75614 } elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
75615 $this->errors = $initErrors;
75616 }
75617 }
75618 unset($v); 
75619  
75620  }
75621 } else {
75622
75623  foreach ($value as $k => &$v) {
75624 if (array_key_exists($k, $schema->items)) {
75625 $this->checkUndefined($v, $schema->items[$k], $path, $k);
75626 } else {
75627
75628  if (property_exists($schema, 'additionalItems')) {
75629 if ($schema->additionalItems !== false) {
75630 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
75631 } else {
75632 $this->addError(
75633 $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems));
75634 }
75635 } else {
75636
75637  $this->checkUndefined($v, new \stdClass(), $path, $k);
75638 }
75639 }
75640 }
75641 unset($v); 
75642  
75643
75644
75645  if (count($value) > 0) {
75646 for ($k = count($value); $k < count($schema->items); $k++) {
75647 $undefinedInstance = $this->factory->createInstanceFor('undefined');
75648 $this->checkUndefined($undefinedInstance, $schema->items[$k], $path, $k);
75649 }
75650 }
75651 }
75652 }
75653 }
75654 <?php
75655
75656
75657
75658
75659
75660
75661
75662
75663 namespace JsonSchema\Constraints;
75664
75665 use JsonSchema\Entity\JsonPointer;
75666 use JsonSchema\SchemaStorage;
75667 use JsonSchema\Uri\UriRetriever;
75668 use JsonSchema\UriRetrieverInterface;
75669
75670
75671
75672
75673
75674
75675
75676 abstract class Constraint extends BaseConstraint implements ConstraintInterface
75677 {
75678 protected $inlineSchemaProperty = '$schema';
75679
75680 const CHECK_MODE_NONE = 0x00000000;
75681 const CHECK_MODE_NORMAL = 0x00000001;
75682 const CHECK_MODE_TYPE_CAST = 0x00000002;
75683 const CHECK_MODE_COERCE_TYPES = 0x00000004;
75684 const CHECK_MODE_APPLY_DEFAULTS = 0x00000008;
75685 const CHECK_MODE_EXCEPTIONS = 0x00000010;
75686 const CHECK_MODE_DISABLE_FORMAT = 0x00000020;
75687 const CHECK_MODE_ONLY_REQUIRED_DEFAULTS = 0x00000080;
75688 const CHECK_MODE_VALIDATE_SCHEMA = 0x00000100;
75689
75690
75691
75692
75693
75694
75695
75696
75697
75698 protected function incrementPath(JsonPointer $path = null, $i)
75699 {
75700 $path = $path ?: new JsonPointer('');
75701 $path = $path->withPropertyPaths(
75702 array_merge(
75703 $path->getPropertyPaths(),
75704 array_filter(array($i), 'strlen')
75705 )
75706 );
75707
75708 return $path;
75709 }
75710
75711
75712
75713
75714
75715
75716
75717
75718
75719 protected function checkArray(&$value, $schema = null, JsonPointer $path = null, $i = null)
75720 {
75721 $validator = $this->factory->createInstanceFor('collection');
75722 $validator->check($value, $schema, $path, $i);
75723
75724 $this->addErrors($validator->getErrors());
75725 }
75726
75727
75728
75729
75730
75731
75732
75733
75734
75735
75736
75737 protected function checkObject(&$value, $schema = null, JsonPointer $path = null, $properties = null,
75738 $additionalProperties = null, $patternProperties = null, $appliedDefaults = array())
75739 {
75740 $validator = $this->factory->createInstanceFor('object');
75741 $validator->check($value, $schema, $path, $properties, $additionalProperties, $patternProperties, $appliedDefaults);
75742
75743 $this->addErrors($validator->getErrors());
75744 }
75745
75746
75747
75748
75749
75750
75751
75752
75753
75754 protected function checkType(&$value, $schema = null, JsonPointer $path = null, $i = null)
75755 {
75756 $validator = $this->factory->createInstanceFor('type');
75757 $validator->check($value, $schema, $path, $i);
75758
75759 $this->addErrors($validator->getErrors());
75760 }
75761
75762
75763
75764
75765
75766
75767
75768
75769
75770 protected function checkUndefined(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
75771 {
75772 $validator = $this->factory->createInstanceFor('undefined');
75773
75774 $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i, $fromDefault);
75775
75776 $this->addErrors($validator->getErrors());
75777 }
75778
75779
75780
75781
75782
75783
75784
75785
75786
75787 protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
75788 {
75789 $validator = $this->factory->createInstanceFor('string');
75790 $validator->check($value, $schema, $path, $i);
75791
75792 $this->addErrors($validator->getErrors());
75793 }
75794
75795
75796
75797
75798
75799
75800
75801
75802
75803 protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
75804 {
75805 $validator = $this->factory->createInstanceFor('number');
75806 $validator->check($value, $schema, $path, $i);
75807
75808 $this->addErrors($validator->getErrors());
75809 }
75810
75811
75812
75813
75814
75815
75816
75817
75818
75819 protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
75820 {
75821 $validator = $this->factory->createInstanceFor('enum');
75822 $validator->check($value, $schema, $path, $i);
75823
75824 $this->addErrors($validator->getErrors());
75825 }
75826
75827
75828
75829
75830
75831
75832
75833
75834
75835 protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
75836 {
75837 $validator = $this->factory->createInstanceFor('format');
75838 $validator->check($value, $schema, $path, $i);
75839
75840 $this->addErrors($validator->getErrors());
75841 }
75842
75843
75844
75845
75846
75847
75848 protected function getTypeCheck()
75849 {
75850 return $this->factory->getTypeCheck();
75851 }
75852
75853
75854
75855
75856
75857
75858 protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
75859 {
75860 $result = array_map(
75861 function ($path) {
75862 return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
75863 },
75864 $pointer->getPropertyPaths()
75865 );
75866
75867 return trim(implode('', $result), '.');
75868 }
75869 }
75870 <?php
75871
75872
75873
75874
75875
75876
75877
75878
75879 namespace JsonSchema\Constraints;
75880
75881 use JsonSchema\Entity\JsonPointer;
75882
75883
75884
75885
75886
75887
75888 interface ConstraintInterface
75889 {
75890
75891
75892
75893
75894
75895 public function getErrors();
75896
75897
75898
75899
75900
75901
75902 public function addErrors(array $errors);
75903
75904
75905
75906
75907
75908
75909
75910
75911
75912 public function addError(JsonPointer $path = null, $message, $constraint='', array $more = null);
75913
75914
75915
75916
75917
75918
75919 public function isValid();
75920
75921
75922
75923
75924
75925
75926
75927
75928
75929
75930
75931
75932
75933 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null);
75934 }
75935 <?php
75936
75937
75938
75939
75940
75941
75942
75943
75944 namespace JsonSchema\Constraints;
75945
75946 use JsonSchema\Entity\JsonPointer;
75947
75948
75949
75950
75951
75952
75953
75954 class EnumConstraint extends Constraint
75955 {
75956
75957
75958
75959 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
75960 {
75961
75962  if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
75963 return;
75964 }
75965 $type = gettype($element);
75966
75967 foreach ($schema->enum as $enum) {
75968 $enumType = gettype($enum);
75969 if ($this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && $type == 'array' && $enumType == 'object') {
75970 if ((object) $element == $enum) {
75971 return;
75972 }
75973 }
75974
75975 if ($type === gettype($enum)) {
75976 if ($type == 'object') {
75977 if ($element == $enum) {
75978 return;
75979 }
75980 } elseif ($element === $enum) {
75981 return;
75982 }
75983 }
75984 }
75985
75986 $this->addError($path, 'Does not have a value in the enumeration ' . json_encode($schema->enum), 'enum', array('enum' => $schema->enum));
75987 }
75988 }
75989 <?php
75990
75991
75992
75993
75994
75995
75996
75997
75998 namespace JsonSchema\Constraints;
75999
76000 use JsonSchema\Constraints\Constraint;
76001 use JsonSchema\Exception\InvalidArgumentException;
76002 use JsonSchema\Exception\InvalidConfigException;
76003 use JsonSchema\SchemaStorage;
76004 use JsonSchema\SchemaStorageInterface;
76005 use JsonSchema\Uri\UriRetriever;
76006 use JsonSchema\UriRetrieverInterface;
76007 use JsonSchema\Validator;
76008
76009
76010
76011
76012 class Factory
76013 {
76014
76015
76016
76017 protected $schemaStorage;
76018
76019
76020
76021
76022 protected $uriRetriever;
76023
76024
76025
76026
76027 private $checkMode = Constraint::CHECK_MODE_NORMAL;
76028
76029
76030
76031
76032 private $typeCheck = array();
76033
76034
76035
76036
76037 protected $errorContext = Validator::ERROR_DOCUMENT_VALIDATION;
76038
76039
76040
76041
76042 protected $constraintMap = array(
76043 'array' => 'JsonSchema\Constraints\CollectionConstraint',
76044 'collection' => 'JsonSchema\Constraints\CollectionConstraint',
76045 'object' => 'JsonSchema\Constraints\ObjectConstraint',
76046 'type' => 'JsonSchema\Constraints\TypeConstraint',
76047 'undefined' => 'JsonSchema\Constraints\UndefinedConstraint',
76048 'string' => 'JsonSchema\Constraints\StringConstraint',
76049 'number' => 'JsonSchema\Constraints\NumberConstraint',
76050 'enum' => 'JsonSchema\Constraints\EnumConstraint',
76051 'format' => 'JsonSchema\Constraints\FormatConstraint',
76052 'schema' => 'JsonSchema\Constraints\SchemaConstraint',
76053 'validator' => 'JsonSchema\Validator'
76054 );
76055
76056
76057
76058
76059 private $instanceCache = array();
76060
76061
76062
76063
76064
76065
76066 public function __construct(
76067 SchemaStorageInterface $schemaStorage = null,
76068 UriRetrieverInterface $uriRetriever = null,
76069 $checkMode = Constraint::CHECK_MODE_NORMAL
76070 ) {
76071
76072  $this->setConfig($checkMode);
76073
76074 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
76075 $this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
76076 }
76077
76078
76079
76080
76081
76082
76083 public function setConfig($checkMode = Constraint::CHECK_MODE_NORMAL)
76084 {
76085 $this->checkMode = $checkMode;
76086 }
76087
76088
76089
76090
76091
76092
76093 public function addConfig($options)
76094 {
76095 $this->checkMode |= $options;
76096 }
76097
76098
76099
76100
76101
76102
76103 public function removeConfig($options)
76104 {
76105 $this->checkMode &= ~$options;
76106 }
76107
76108
76109
76110
76111
76112
76113
76114
76115 public function getConfig($options = null)
76116 {
76117 if ($options === null) {
76118 return $this->checkMode;
76119 }
76120
76121 return $this->checkMode & $options;
76122 }
76123
76124
76125
76126
76127 public function getUriRetriever()
76128 {
76129 return $this->uriRetriever;
76130 }
76131
76132 public function getSchemaStorage()
76133 {
76134 return $this->schemaStorage;
76135 }
76136
76137 public function getTypeCheck()
76138 {
76139 if (!isset($this->typeCheck[$this->checkMode])) {
76140 $this->typeCheck[$this->checkMode] = ($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST)
76141 ? new TypeCheck\LooseTypeCheck()
76142 : new TypeCheck\StrictTypeCheck();
76143 }
76144
76145 return $this->typeCheck[$this->checkMode];
76146 }
76147
76148
76149
76150
76151
76152
76153
76154 public function setConstraintClass($name, $class)
76155 {
76156
76157  if (!class_exists($class)) {
76158 throw new InvalidArgumentException('Unknown constraint ' . $name);
76159 }
76160
76161  if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
76162 throw new InvalidArgumentException('Invalid class ' . $name);
76163 }
76164 $this->constraintMap[$name] = $class;
76165
76166 return $this;
76167 }
76168
76169
76170
76171
76172
76173
76174
76175
76176
76177
76178 public function createInstanceFor($constraintName)
76179 {
76180 if (!isset($this->constraintMap[$constraintName])) {
76181 throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
76182 }
76183
76184 if (!isset($this->instanceCache[$constraintName])) {
76185 $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
76186 }
76187
76188 return clone $this->instanceCache[$constraintName];
76189 }
76190
76191
76192
76193
76194
76195
76196 public function getErrorContext()
76197 {
76198 return $this->errorContext;
76199 }
76200
76201
76202
76203
76204
76205
76206 public function setErrorContext($errorContext)
76207 {
76208 $this->errorContext = $errorContext;
76209 }
76210 }
76211 <?php
76212
76213
76214
76215
76216
76217
76218
76219
76220 namespace JsonSchema\Constraints;
76221
76222 use JsonSchema\Entity\JsonPointer;
76223 use JsonSchema\Rfc3339;
76224
76225
76226
76227
76228
76229
76230
76231
76232 class FormatConstraint extends Constraint
76233 {
76234
76235
76236
76237 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76238 {
76239 if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
76240 return;
76241 }
76242
76243 switch ($schema->format) {
76244 case 'date':
76245 if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
76246 $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format));
76247 }
76248 break;
76249
76250 case 'time':
76251 if (!$this->validateDateTime($element, 'H:i:s')) {
76252 $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format));
76253 }
76254 break;
76255
76256 case 'date-time':
76257 if (null === Rfc3339::createFromString($element)) {
76258 $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));
76259 }
76260 break;
76261
76262 case 'utc-millisec':
76263 if (!$this->validateDateTime($element, 'U')) {
76264 $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format));
76265 }
76266 break;
76267
76268 case 'regex':
76269 if (!$this->validateRegex($element)) {
76270 $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format));
76271 }
76272 break;
76273
76274 case 'color':
76275 if (!$this->validateColor($element)) {
76276 $this->addError($path, 'Invalid color', 'format', array('format' => $schema->format));
76277 }
76278 break;
76279
76280 case 'style':
76281 if (!$this->validateStyle($element)) {
76282 $this->addError($path, 'Invalid style', 'format', array('format' => $schema->format));
76283 }
76284 break;
76285
76286 case 'phone':
76287 if (!$this->validatePhone($element)) {
76288 $this->addError($path, 'Invalid phone number', 'format', array('format' => $schema->format));
76289 }
76290 break;
76291
76292 case 'uri':
76293 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
76294 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
76295 }
76296 break;
76297
76298 case 'uriref':
76299 case 'uri-reference':
76300 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
76301
76302  
76303  
76304  if (substr($element, 0, 2) === '//') { 
76305  $validURL = filter_var('scheme:' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
76306 } elseif (substr($element, 0, 1) === '/') { 
76307  $validURL = filter_var('scheme://host' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
76308 } elseif (strlen($element)) { 
76309  $pathParts = explode('/', $element, 2);
76310 if (strpos($pathParts[0], ':') !== false) {
76311 $validURL = null;
76312 } else {
76313 $validURL = filter_var('scheme://host/' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
76314 }
76315 } else {
76316 $validURL = null;
76317 }
76318 if ($validURL === null) {
76319 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
76320 }
76321 }
76322 break;
76323
76324 case 'email':
76325 $filterFlags = FILTER_NULL_ON_FAILURE;
76326 if (defined('FILTER_FLAG_EMAIL_UNICODE')) {
76327
76328  $filterFlags |= constant('FILTER_FLAG_EMAIL_UNICODE'); 
76329  }
76330 if (null === filter_var($element, FILTER_VALIDATE_EMAIL, $filterFlags)) {
76331 $this->addError($path, 'Invalid email', 'format', array('format' => $schema->format));
76332 }
76333 break;
76334
76335 case 'ip-address':
76336 case 'ipv4':
76337 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
76338 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
76339 }
76340 break;
76341
76342 case 'ipv6':
76343 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
76344 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
76345 }
76346 break;
76347
76348 case 'host-name':
76349 case 'hostname':
76350 if (!$this->validateHostname($element)) {
76351 $this->addError($path, 'Invalid hostname', 'format', array('format' => $schema->format));
76352 }
76353 break;
76354
76355 default:
76356
76357  
76358  
76359  
76360  
76361  
76362  break;
76363 }
76364 }
76365
76366 protected function validateDateTime($datetime, $format)
76367 {
76368 $dt = \DateTime::createFromFormat($format, $datetime);
76369
76370 if (!$dt) {
76371 return false;
76372 }
76373
76374 if ($datetime === $dt->format($format)) {
76375 return true;
76376 }
76377
76378
76379  
76380  
76381  
76382  if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', $datetime))) {
76383 return true;
76384 }
76385
76386 return false;
76387 }
76388
76389 protected function validateRegex($regex)
76390 {
76391 return false !== @preg_match('/' . $regex . '/u', '');
76392 }
76393
76394 protected function validateColor($color)
76395 {
76396 if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
76397 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
76398 'red', 'silver', 'teal', 'white', 'yellow'))) {
76399 return true;
76400 }
76401
76402 return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
76403 }
76404
76405 protected function validateStyle($style)
76406 {
76407 $properties = explode(';', rtrim($style, ';'));
76408 $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
76409
76410 return empty($invalidEntries);
76411 }
76412
76413 protected function validatePhone($phone)
76414 {
76415 return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
76416 }
76417
76418 protected function validateHostname($host)
76419 {
76420 $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';
76421
76422 return preg_match($hostnameRegex, $host);
76423 }
76424 }
76425 <?php
76426
76427
76428
76429
76430
76431
76432
76433
76434 namespace JsonSchema\Constraints;
76435
76436 use JsonSchema\Entity\JsonPointer;
76437
76438
76439
76440
76441
76442
76443
76444 class NumberConstraint extends Constraint
76445 {
76446
76447
76448
76449 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76450 {
76451
76452  if (isset($schema->exclusiveMinimum)) {
76453 if (isset($schema->minimum)) {
76454 if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
76455 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum));
76456 } elseif ($element < $schema->minimum) {
76457 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
76458 }
76459 } else {
76460 $this->addError($path, 'Use of exclusiveMinimum requires presence of minimum', 'missingMinimum');
76461 }
76462 } elseif (isset($schema->minimum) && $element < $schema->minimum) {
76463 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
76464 }
76465
76466
76467  if (isset($schema->exclusiveMaximum)) {
76468 if (isset($schema->maximum)) {
76469 if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
76470 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum));
76471 } elseif ($element > $schema->maximum) {
76472 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
76473 }
76474 } else {
76475 $this->addError($path, 'Use of exclusiveMaximum requires presence of maximum', 'missingMaximum');
76476 }
76477 } elseif (isset($schema->maximum) && $element > $schema->maximum) {
76478 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
76479 }
76480
76481
76482  if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
76483 $this->addError($path, 'Is not divisible by ' . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy));
76484 }
76485
76486
76487  if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
76488 $this->addError($path, 'Must be a multiple of ' . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf));
76489 }
76490
76491 $this->checkFormat($element, $schema, $path, $i);
76492 }
76493
76494 private function fmod($number1, $number2)
76495 {
76496 $number1 = abs($number1);
76497 $modulus = fmod($number1, $number2);
76498 $precision = abs(0.0000000001);
76499 $diff = (float) ($modulus - $number2);
76500
76501 if (-$precision < $diff && $diff < $precision) {
76502 return 0.0;
76503 }
76504
76505 $decimals1 = mb_strpos($number1, '.') ? mb_strlen($number1) - mb_strpos($number1, '.') - 1 : 0;
76506 $decimals2 = mb_strpos($number2, '.') ? mb_strlen($number2) - mb_strpos($number2, '.') - 1 : 0;
76507
76508 return (float) round($modulus, max($decimals1, $decimals2));
76509 }
76510 }
76511 <?php
76512
76513
76514
76515
76516
76517
76518
76519
76520 namespace JsonSchema\Constraints;
76521
76522 use JsonSchema\Entity\JsonPointer;
76523
76524
76525
76526
76527
76528
76529
76530 class ObjectConstraint extends Constraint
76531 {
76532
76533
76534
76535 protected $appliedDefaults = array();
76536
76537
76538
76539
76540 public function check(&$element, $schema = null, JsonPointer $path = null, $properties = null,
76541 $additionalProp = null, $patternProperties = null, $appliedDefaults = array())
76542 {
76543 if ($element instanceof UndefinedConstraint) {
76544 return;
76545 }
76546
76547 $this->appliedDefaults = $appliedDefaults;
76548
76549 $matches = array();
76550 if ($patternProperties) {
76551
76552  $matches = $this->validatePatternProperties($element, $path, $patternProperties);
76553 }
76554
76555 if ($properties) {
76556
76557  $this->validateProperties($element, $properties, $path);
76558 }
76559
76560
76561  $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp);
76562 }
76563
76564 public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties)
76565 {
76566 $try = array('/', '#', '+', '~', '%');
76567 $matches = array();
76568 foreach ($patternProperties as $pregex => $schema) {
76569 $delimiter = '/';
76570
76571  foreach ($try as $delimiter) {
76572 if (strpos($pregex, $delimiter) === false) { 
76573  break;
76574 }
76575 }
76576
76577
76578  if (@preg_match($delimiter . $pregex . $delimiter . 'u', '') === false) {
76579 $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex));
76580 continue;
76581 }
76582 foreach ($element as $i => $value) {
76583 if (preg_match($delimiter . $pregex . $delimiter . 'u', $i)) {
76584 $matches[] = $i;
76585 $this->checkUndefined($value, $schema ?: new \stdClass(), $path, $i, in_array($i, $this->appliedDefaults));
76586 }
76587 }
76588 }
76589
76590 return $matches;
76591 }
76592
76593
76594
76595
76596
76597
76598
76599
76600
76601
76602
76603 public function validateElement($element, $matches, $schema = null, JsonPointer $path = null,
76604 $properties = null, $additionalProp = null)
76605 {
76606 $this->validateMinMaxConstraint($element, $schema, $path);
76607
76608 foreach ($element as $i => $value) {
76609 $definition = $this->getProperty($properties, $i);
76610
76611
76612  if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
76613 $this->addError($path, 'The property ' . $i . ' is not defined and the definition does not allow additional properties', 'additionalProp');
76614 }
76615
76616
76617  if (!in_array($i, $matches) && $additionalProp && !$definition) {
76618 if ($additionalProp === true) {
76619 $this->checkUndefined($value, null, $path, $i, in_array($i, $this->appliedDefaults));
76620 } else {
76621 $this->checkUndefined($value, $additionalProp, $path, $i, in_array($i, $this->appliedDefaults));
76622 }
76623 }
76624
76625
76626  $require = $this->getProperty($definition, 'requires');
76627 if ($require && !$this->getProperty($element, $require)) {
76628 $this->addError($path, 'The presence of the property ' . $i . ' requires that ' . $require . ' also be present', 'requires');
76629 }
76630
76631 $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
76632 if (is_object($property)) {
76633 $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
76634 }
76635 }
76636 }
76637
76638
76639
76640
76641
76642
76643
76644
76645 public function validateProperties(&$element, $properties = null, JsonPointer $path = null)
76646 {
76647 $undefinedConstraint = $this->factory->createInstanceFor('undefined');
76648
76649 foreach ($properties as $i => $value) {
76650 $property = &$this->getProperty($element, $i, $undefinedConstraint);
76651 $definition = $this->getProperty($properties, $i);
76652
76653 if (is_object($definition)) {
76654
76655  $this->checkUndefined($property, $definition, $path, $i, in_array($i, $this->appliedDefaults));
76656 }
76657 }
76658 }
76659
76660
76661
76662
76663
76664
76665
76666
76667
76668
76669 protected function &getProperty(&$element, $property, $fallback = null)
76670 {
76671 if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) ) {
76672 return $element[$property];
76673 } elseif (is_object($element) && property_exists($element, $property)) {
76674 return $element->$property;
76675 }
76676
76677 return $fallback;
76678 }
76679
76680
76681
76682
76683
76684
76685
76686
76687 protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null)
76688 {
76689
76690  if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
76691 if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
76692 $this->addError($path, 'Must contain a minimum of ' . $objectDefinition->minProperties . ' properties', 'minProperties', array('minProperties' => $objectDefinition->minProperties));
76693 }
76694 }
76695
76696  if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
76697 if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
76698 $this->addError($path, 'Must contain no more than ' . $objectDefinition->maxProperties . ' properties', 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties));
76699 }
76700 }
76701 }
76702 }
76703 <?php
76704
76705
76706
76707
76708
76709
76710
76711
76712 namespace JsonSchema\Constraints;
76713
76714 use JsonSchema\Entity\JsonPointer;
76715 use JsonSchema\Exception\InvalidArgumentException;
76716 use JsonSchema\Exception\InvalidSchemaException;
76717 use JsonSchema\Exception\RuntimeException;
76718 use JsonSchema\SchemaStorage;
76719 use JsonSchema\Validator;
76720
76721
76722
76723
76724
76725
76726
76727 class SchemaConstraint extends Constraint
76728 {
76729 const DEFAULT_SCHEMA_SPEC = 'http://json-schema.org/draft-04/schema#';
76730
76731
76732
76733
76734 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76735 {
76736 if ($schema !== null) {
76737
76738  $validationSchema = $schema;
76739 } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
76740
76741  $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
76742 } else {
76743 throw new InvalidArgumentException('no schema found to verify against');
76744 }
76745
76746
76747  if (is_array($validationSchema)) {
76748 $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema);
76749 }
76750
76751
76752  
76753  if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) {
76754 if (!$this->getTypeCheck()->isObject($validationSchema)) {
76755 throw new RuntimeException('Cannot validate the schema of a non-object');
76756 }
76757 if ($this->getTypeCheck()->propertyExists($validationSchema, '$schema')) {
76758 $schemaSpec = $this->getTypeCheck()->propertyGet($validationSchema, '$schema');
76759 } else {
76760 $schemaSpec = self::DEFAULT_SCHEMA_SPEC;
76761 }
76762
76763
76764  $schemaStorage = $this->factory->getSchemaStorage();
76765 if (!$this->getTypeCheck()->isObject($schemaSpec)) {
76766 $schemaSpec = $schemaStorage->getSchema($schemaSpec);
76767 }
76768
76769
76770  $initialErrorCount = $this->numErrors();
76771 $initialConfig = $this->factory->getConfig();
76772 $initialContext = $this->factory->getErrorContext();
76773 $this->factory->removeConfig(self::CHECK_MODE_VALIDATE_SCHEMA | self::CHECK_MODE_APPLY_DEFAULTS);
76774 $this->factory->addConfig(self::CHECK_MODE_TYPE_CAST);
76775 $this->factory->setErrorContext(Validator::ERROR_SCHEMA_VALIDATION);
76776
76777
76778  try {
76779 $this->check($validationSchema, $schemaSpec);
76780 } catch (\Exception $e) {
76781 if ($this->factory->getConfig(self::CHECK_MODE_EXCEPTIONS)) {
76782 throw new InvalidSchemaException('Schema did not pass validation', 0, $e);
76783 }
76784 }
76785 if ($this->numErrors() > $initialErrorCount) {
76786 $this->addError($path, 'Schema is not valid', 'schema');
76787 }
76788
76789
76790  $this->factory->setConfig($initialConfig);
76791 $this->factory->setErrorContext($initialContext);
76792 }
76793
76794
76795  $this->checkUndefined($element, $validationSchema, $path, $i);
76796 }
76797 }
76798 <?php
76799
76800
76801
76802
76803
76804
76805
76806
76807 namespace JsonSchema\Constraints;
76808
76809 use JsonSchema\Entity\JsonPointer;
76810
76811
76812
76813
76814
76815
76816
76817 class StringConstraint extends Constraint
76818 {
76819
76820
76821
76822 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76823 {
76824
76825  if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
76826 $this->addError($path, 'Must be at most ' . $schema->maxLength . ' characters long', 'maxLength', array(
76827 'maxLength' => $schema->maxLength,
76828 ));
76829 }
76830
76831
76832  if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
76833 $this->addError($path, 'Must be at least ' . $schema->minLength . ' characters long', 'minLength', array(
76834 'minLength' => $schema->minLength,
76835 ));
76836 }
76837
76838
76839  if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#u', $element)) {
76840 $this->addError($path, 'Does not match the regex pattern ' . $schema->pattern, 'pattern', array(
76841 'pattern' => $schema->pattern,
76842 ));
76843 }
76844
76845 $this->checkFormat($element, $schema, $path, $i);
76846 }
76847
76848 private function strlen($string)
76849 {
76850 if (extension_loaded('mbstring')) {
76851 return mb_strlen($string, mb_detect_encoding($string));
76852 }
76853
76854
76855  return strlen($string); 
76856  }
76857 }
76858 <?php
76859
76860 namespace JsonSchema\Constraints\TypeCheck;
76861
76862 class LooseTypeCheck implements TypeCheckInterface
76863 {
76864 public static function isObject($value)
76865 {
76866 return
76867 is_object($value) ||
76868 (is_array($value) && (count($value) == 0 || self::isAssociativeArray($value)));
76869 }
76870
76871 public static function isArray($value)
76872 {
76873 return
76874 is_array($value) &&
76875 (count($value) == 0 || !self::isAssociativeArray($value));
76876 }
76877
76878 public static function propertyGet($value, $property)
76879 {
76880 if (is_object($value)) {
76881 return $value->{$property};
76882 }
76883
76884 return $value[$property];
76885 }
76886
76887 public static function propertySet(&$value, $property, $data)
76888 {
76889 if (is_object($value)) {
76890 $value->{$property} = $data;
76891 } else {
76892 $value[$property] = $data;
76893 }
76894 }
76895
76896 public static function propertyExists($value, $property)
76897 {
76898 if (is_object($value)) {
76899 return property_exists($value, $property);
76900 }
76901
76902 return array_key_exists($property, $value);
76903 }
76904
76905 public static function propertyCount($value)
76906 {
76907 if (is_object($value)) {
76908 return count(get_object_vars($value));
76909 }
76910
76911 return count($value);
76912 }
76913
76914
76915
76916
76917
76918
76919
76920
76921 private static function isAssociativeArray($arr)
76922 {
76923 return array_keys($arr) !== range(0, count($arr) - 1);
76924 }
76925 }
76926 <?php
76927
76928 namespace JsonSchema\Constraints\TypeCheck;
76929
76930 class StrictTypeCheck implements TypeCheckInterface
76931 {
76932 public static function isObject($value)
76933 {
76934 return is_object($value);
76935 }
76936
76937 public static function isArray($value)
76938 {
76939 return is_array($value);
76940 }
76941
76942 public static function propertyGet($value, $property)
76943 {
76944 return $value->{$property};
76945 }
76946
76947 public static function propertySet(&$value, $property, $data)
76948 {
76949 $value->{$property} = $data;
76950 }
76951
76952 public static function propertyExists($value, $property)
76953 {
76954 return property_exists($value, $property);
76955 }
76956
76957 public static function propertyCount($value)
76958 {
76959 return count(get_object_vars($value));
76960 }
76961 }
76962 <?php
76963
76964 namespace JsonSchema\Constraints\TypeCheck;
76965
76966 interface TypeCheckInterface
76967 {
76968 public static function isObject($value);
76969
76970 public static function isArray($value);
76971
76972 public static function propertyGet($value, $property);
76973
76974 public static function propertySet(&$value, $property, $data);
76975
76976 public static function propertyExists($value, $property);
76977
76978 public static function propertyCount($value);
76979 }
76980 <?php
76981
76982
76983
76984
76985
76986
76987
76988
76989 namespace JsonSchema\Constraints;
76990
76991 use JsonSchema\Entity\JsonPointer;
76992 use JsonSchema\Exception\InvalidArgumentException;
76993 use UnexpectedValueException as StandardUnexpectedValueException;
76994
76995
76996
76997
76998
76999
77000
77001 class TypeConstraint extends Constraint
77002 {
77003
77004
77005
77006 public static $wording = array(
77007 'integer' => 'an integer',
77008 'number' => 'a number',
77009 'boolean' => 'a boolean',
77010 'object' => 'an object',
77011 'array' => 'an array',
77012 'string' => 'a string',
77013 'null' => 'a null',
77014 'any' => null, 
77015  0 => null, 
77016  );
77017
77018
77019
77020
77021 public function check(&$value = null, $schema = null, JsonPointer $path = null, $i = null)
77022 {
77023 $type = isset($schema->type) ? $schema->type : null;
77024 $isValid = false;
77025 $wording = array();
77026
77027 if (is_array($type)) {
77028 $this->validateTypesArray($value, $type, $wording, $isValid, $path);
77029 } elseif (is_object($type)) {
77030 $this->checkUndefined($value, $type, $path);
77031
77032 return;
77033 } else {
77034 $isValid = $this->validateType($value, $type);
77035 }
77036
77037 if ($isValid === false) {
77038 if (!is_array($type)) {
77039 $this->validateTypeNameWording($type);
77040 $wording[] = self::$wording[$type];
77041 }
77042 $this->addError($path, ucwords(gettype($value)) . ' value found, but ' .
77043 $this->implodeWith($wording, ', ', 'or') . ' is required', 'type');
77044 }
77045 }
77046
77047
77048
77049
77050
77051
77052
77053
77054
77055
77056
77057
77058 protected function validateTypesArray(&$value, array $type, &$validTypesWording, &$isValid, $path)
77059 {
77060 foreach ($type as $tp) {
77061
77062  
77063  if (is_object($tp)) {
77064 if (!$isValid) {
77065 $validator = $this->factory->createInstanceFor('type');
77066 $subSchema = new \stdClass();
77067 $subSchema->type = $tp;
77068 $validator->check($value, $subSchema, $path, null);
77069 $error = $validator->getErrors();
77070 $isValid = !(bool) $error;
77071 $validTypesWording[] = self::$wording['object'];
77072 }
77073 } else {
77074 $this->validateTypeNameWording($tp);
77075 $validTypesWording[] = self::$wording[$tp];
77076 if (!$isValid) {
77077 $isValid = $this->validateType($value, $tp);
77078 }
77079 }
77080 }
77081 }
77082
77083
77084
77085
77086
77087
77088
77089
77090
77091
77092
77093
77094 protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = false)
77095 {
77096 if ($listEnd === false || !isset($elements[1])) {
77097 return implode($delimiter, $elements);
77098 }
77099 $lastElement = array_slice($elements, -1);
77100 $firsElements = join($delimiter, array_slice($elements, 0, -1));
77101 $implodedElements = array_merge(array($firsElements), $lastElement);
77102
77103 return join(" $listEnd ", $implodedElements);
77104 }
77105
77106
77107
77108
77109
77110
77111
77112
77113
77114 protected function validateTypeNameWording($type)
77115 {
77116 if (!isset(self::$wording[$type])) {
77117 throw new StandardUnexpectedValueException(
77118 sprintf(
77119 'No wording for %s available, expected wordings are: [%s]',
77120 var_export($type, true),
77121 implode(', ', array_filter(self::$wording)))
77122 );
77123 }
77124 }
77125
77126
77127
77128
77129
77130
77131
77132
77133
77134
77135
77136 protected function validateType(&$value, $type)
77137 {
77138
77139  if (!$type) {
77140 return true;
77141 }
77142
77143 if ('any' === $type) {
77144 return true;
77145 }
77146
77147 if ('object' === $type) {
77148 return $this->getTypeCheck()->isObject($value);
77149 }
77150
77151 if ('array' === $type) {
77152 return $this->getTypeCheck()->isArray($value);
77153 }
77154
77155 $coerce = $this->factory->getConfig(Constraint::CHECK_MODE_COERCE_TYPES);
77156
77157 if ('integer' === $type) {
77158 if ($coerce) {
77159 $value = $this->toInteger($value);
77160 }
77161
77162 return is_int($value);
77163 }
77164
77165 if ('number' === $type) {
77166 if ($coerce) {
77167 $value = $this->toNumber($value);
77168 }
77169
77170 return is_numeric($value) && !is_string($value);
77171 }
77172
77173 if ('boolean' === $type) {
77174 if ($coerce) {
77175 $value = $this->toBoolean($value);
77176 }
77177
77178 return is_bool($value);
77179 }
77180
77181 if ('string' === $type) {
77182 return is_string($value);
77183 }
77184
77185 if ('email' === $type) {
77186 return is_string($value);
77187 }
77188
77189 if ('null' === $type) {
77190 return is_null($value);
77191 }
77192
77193 throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
77194 }
77195
77196
77197
77198
77199
77200
77201
77202
77203 protected function toBoolean($value)
77204 {
77205 if ($value === 'true') {
77206 return true;
77207 }
77208
77209 if ($value === 'false') {
77210 return false;
77211 }
77212
77213 return $value;
77214 }
77215
77216
77217
77218
77219
77220
77221
77222
77223 protected function toNumber($value)
77224 {
77225 if (is_numeric($value)) {
77226 return $value + 0; 
77227  }
77228
77229 return $value;
77230 }
77231
77232 protected function toInteger($value)
77233 {
77234 if (is_numeric($value) && (int) $value == $value) {
77235 return (int) $value; 
77236  }
77237
77238 return $value;
77239 }
77240 }
77241 <?php
77242
77243
77244
77245
77246
77247
77248
77249
77250 namespace JsonSchema\Constraints;
77251
77252 use JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
77253 use JsonSchema\Entity\JsonPointer;
77254 use JsonSchema\Exception\ValidationException;
77255 use JsonSchema\Uri\UriResolver;
77256
77257
77258
77259
77260
77261
77262
77263 class UndefinedConstraint extends Constraint
77264 {
77265
77266
77267
77268 protected $appliedDefaults = array();
77269
77270
77271
77272
77273 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
77274 {
77275 if (is_null($schema) || !is_object($schema)) {
77276 return;
77277 }
77278
77279 $path = $this->incrementPath($path ?: new JsonPointer(''), $i);
77280 if ($fromDefault) {
77281 $path->setFromDefault();
77282 }
77283
77284
77285  $this->validateCommonProperties($value, $schema, $path, $i);
77286
77287
77288  $this->validateOfProperties($value, $schema, $path, '');
77289
77290
77291  $this->validateTypes($value, $schema, $path, $i);
77292 }
77293
77294
77295
77296
77297
77298
77299
77300
77301
77302 public function validateTypes(&$value, $schema = null, JsonPointer $path, $i = null)
77303 {
77304
77305  if ($this->getTypeCheck()->isArray($value)) {
77306 $this->checkArray($value, $schema, $path, $i);
77307 }
77308
77309
77310  if (LooseTypeCheck::isObject($value)) { 
77311  
77312  
77313  $this->checkObject(
77314 $value,
77315 $schema,
77316 $path,
77317 isset($schema->properties) ? $schema->properties : null,
77318 isset($schema->additionalProperties) ? $schema->additionalProperties : null,
77319 isset($schema->patternProperties) ? $schema->patternProperties : null,
77320 $this->appliedDefaults
77321 );
77322 }
77323
77324
77325  if (is_string($value)) {
77326 $this->checkString($value, $schema, $path, $i);
77327 }
77328
77329
77330  if (is_numeric($value)) {
77331 $this->checkNumber($value, $schema, $path, $i);
77332 }
77333
77334
77335  if (isset($schema->enum)) {
77336 $this->checkEnum($value, $schema, $path, $i);
77337 }
77338 }
77339
77340
77341
77342
77343
77344
77345
77346
77347
77348 protected function validateCommonProperties(&$value, $schema = null, JsonPointer $path, $i = '')
77349 {
77350
77351  if (isset($schema->extends)) {
77352 if (is_string($schema->extends)) {
77353 $schema->extends = $this->validateUri($schema, $schema->extends);
77354 }
77355 if (is_array($schema->extends)) {
77356 foreach ($schema->extends as $extends) {
77357 $this->checkUndefined($value, $extends, $path, $i);
77358 }
77359 } else {
77360 $this->checkUndefined($value, $schema->extends, $path, $i);
77361 }
77362 }
77363
77364
77365  if (!$path->fromDefault()) {
77366 $this->applyDefaultValues($value, $schema, $path);
77367 }
77368
77369
77370  if ($this->getTypeCheck()->isObject($value)) {
77371 if (!($value instanceof self) && isset($schema->required) && is_array($schema->required)) {
77372
77373  foreach ($schema->required as $required) {
77374 if (!$this->getTypeCheck()->propertyExists($value, $required)) {
77375 $this->addError(
77376 $this->incrementPath($path ?: new JsonPointer(''), $required),
77377 'The property ' . $required . ' is required',
77378 'required'
77379 );
77380 }
77381 }
77382 } elseif (isset($schema->required) && !is_array($schema->required)) {
77383
77384  if ($schema->required && $value instanceof self) {
77385 $this->addError($path, 'Is missing and it is required', 'required');
77386 }
77387 }
77388 }
77389
77390
77391  if (!($value instanceof self)) {
77392 $this->checkType($value, $schema, $path, $i);
77393 }
77394
77395
77396  if (isset($schema->disallow)) {
77397 $initErrors = $this->getErrors();
77398
77399 $typeSchema = new \stdClass();
77400 $typeSchema->type = $schema->disallow;
77401 $this->checkType($value, $typeSchema, $path);
77402
77403
77404  if (count($this->getErrors()) == count($initErrors)) {
77405 $this->addError($path, 'Disallowed value was matched', 'disallow');
77406 } else {
77407 $this->errors = $initErrors;
77408 }
77409 }
77410
77411 if (isset($schema->not)) {
77412 $initErrors = $this->getErrors();
77413 $this->checkUndefined($value, $schema->not, $path, $i);
77414
77415
77416  if (count($this->getErrors()) == count($initErrors)) {
77417 $this->addError($path, 'Matched a schema which it should not', 'not');
77418 } else {
77419 $this->errors = $initErrors;
77420 }
77421 }
77422
77423
77424  if (isset($schema->dependencies) && $this->getTypeCheck()->isObject($value)) {
77425 $this->validateDependencies($value, $schema->dependencies, $path);
77426 }
77427 }
77428
77429
77430
77431
77432
77433
77434
77435
77436
77437
77438 private function shouldApplyDefaultValue($requiredOnly, $schema, $name = null, $parentSchema = null)
77439 {
77440
77441  if (!$requiredOnly) {
77442 return true;
77443 }
77444
77445  if (
77446 $name !== null
77447 && isset($parentSchema->required)
77448 && is_array($parentSchema->required)
77449 && in_array($name, $parentSchema->required)
77450 ) {
77451 return true;
77452 }
77453
77454  if (isset($schema->required) && !is_array($schema->required) && $schema->required) {
77455 return true;
77456 }
77457
77458  return false;
77459 }
77460
77461
77462
77463
77464
77465
77466
77467
77468 protected function applyDefaultValues(&$value, $schema, $path)
77469 {
77470
77471  if (!$this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
77472 return;
77473 }
77474
77475
77476  $requiredOnly = $this->factory->getConfig(self::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);
77477 if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
77478
77479  foreach ($schema->properties as $currentProperty => $propertyDefinition) {
77480 if (
77481 !LooseTypeCheck::propertyExists($value, $currentProperty)
77482 && property_exists($propertyDefinition, 'default')
77483 && $this->shouldApplyDefaultValue($requiredOnly, $propertyDefinition, $currentProperty, $schema)
77484 ) {
77485
77486  if (is_object($propertyDefinition->default)) {
77487 LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
77488 } else {
77489 LooseTypeCheck::propertySet($value, $currentProperty, $propertyDefinition->default);
77490 }
77491 $this->appliedDefaults[] = $currentProperty;
77492 }
77493 }
77494 } elseif (isset($schema->items) && LooseTypeCheck::isArray($value)) {
77495 $items = array();
77496 if (LooseTypeCheck::isArray($schema->items)) {
77497 $items = $schema->items;
77498 } elseif (isset($schema->minItems) && count($value) < $schema->minItems) {
77499 $items = array_fill(count($value), $schema->minItems - count($value), $schema->items);
77500 }
77501
77502  foreach ($items as $currentItem => $itemDefinition) {
77503 if (
77504 !array_key_exists($currentItem, $value)
77505 && property_exists($itemDefinition, 'default')
77506 && $this->shouldApplyDefaultValue($requiredOnly, $itemDefinition)) {
77507 if (is_object($itemDefinition->default)) {
77508 $value[$currentItem] = clone $itemDefinition->default;
77509 } else {
77510 $value[$currentItem] = $itemDefinition->default;
77511 }
77512 }
77513 $path->setFromDefault();
77514 }
77515 } elseif (
77516 $value instanceof self
77517 && property_exists($schema, 'default')
77518 && $this->shouldApplyDefaultValue($requiredOnly, $schema)) {
77519
77520  $value = is_object($schema->default) ? clone $schema->default : $schema->default;
77521 $path->setFromDefault();
77522 }
77523 }
77524
77525
77526
77527
77528
77529
77530
77531
77532
77533 protected function validateOfProperties(&$value, $schema, JsonPointer $path, $i = '')
77534 {
77535
77536  if ($value instanceof self) {
77537 return;
77538 }
77539
77540 if (isset($schema->allOf)) {
77541 $isValid = true;
77542 foreach ($schema->allOf as $allOf) {
77543 $initErrors = $this->getErrors();
77544 $this->checkUndefined($value, $allOf, $path, $i);
77545 $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
77546 }
77547 if (!$isValid) {
77548 $this->addError($path, 'Failed to match all schemas', 'allOf');
77549 }
77550 }
77551
77552 if (isset($schema->anyOf)) {
77553 $isValid = false;
77554 $startErrors = $this->getErrors();
77555 $caughtException = null;
77556 foreach ($schema->anyOf as $anyOf) {
77557 $initErrors = $this->getErrors();
77558 try {
77559 $this->checkUndefined($value, $anyOf, $path, $i);
77560 if ($isValid = (count($this->getErrors()) == count($initErrors))) {
77561 break;
77562 }
77563 } catch (ValidationException $e) {
77564 $isValid = false;
77565 }
77566 }
77567 if (!$isValid) {
77568 $this->addError($path, 'Failed to match at least one schema', 'anyOf');
77569 } else {
77570 $this->errors = $startErrors;
77571 }
77572 }
77573
77574 if (isset($schema->oneOf)) {
77575 $allErrors = array();
77576 $matchedSchemas = 0;
77577 $startErrors = $this->getErrors();
77578 foreach ($schema->oneOf as $oneOf) {
77579 try {
77580 $this->errors = array();
77581 $this->checkUndefined($value, $oneOf, $path, $i);
77582 if (count($this->getErrors()) == 0) {
77583 $matchedSchemas++;
77584 }
77585 $allErrors = array_merge($allErrors, array_values($this->getErrors()));
77586 } catch (ValidationException $e) {
77587
77588  
77589  }
77590 }
77591 if ($matchedSchemas !== 1) {
77592 $this->addErrors(array_merge($allErrors, $startErrors));
77593 $this->addError($path, 'Failed to match exactly one schema', 'oneOf');
77594 } else {
77595 $this->errors = $startErrors;
77596 }
77597 }
77598 }
77599
77600
77601
77602
77603
77604
77605
77606
77607
77608 protected function validateDependencies($value, $dependencies, JsonPointer $path, $i = '')
77609 {
77610 foreach ($dependencies as $key => $dependency) {
77611 if ($this->getTypeCheck()->propertyExists($value, $key)) {
77612 if (is_string($dependency)) {
77613
77614  if (!$this->getTypeCheck()->propertyExists($value, $dependency)) {
77615 $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
77616 }
77617 } elseif (is_array($dependency)) {
77618
77619  foreach ($dependency as $d) {
77620 if (!$this->getTypeCheck()->propertyExists($value, $d)) {
77621 $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
77622 }
77623 }
77624 } elseif (is_object($dependency)) {
77625
77626  $this->checkUndefined($value, $dependency, $path, $i);
77627 }
77628 }
77629 }
77630 }
77631
77632 protected function validateUri($schema, $schemaUri = null)
77633 {
77634 $resolver = new UriResolver();
77635 $retriever = $this->factory->getUriRetriever();
77636
77637 $jsonSchema = null;
77638 if ($resolver->isValid($schemaUri)) {
77639 $schemaId = property_exists($schema, 'id') ? $schema->id : null;
77640 $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
77641 }
77642
77643 return $jsonSchema;
77644 }
77645 }
77646 <?php
77647
77648
77649
77650
77651
77652
77653
77654
77655 namespace JsonSchema\Entity;
77656
77657 use JsonSchema\Exception\InvalidArgumentException;
77658
77659
77660
77661
77662
77663
77664 class JsonPointer
77665 {
77666
77667 private $filename;
77668
77669
77670 private $propertyPaths = array();
77671
77672
77673
77674
77675 private $fromDefault = false;
77676
77677
77678
77679
77680
77681
77682 public function __construct($value)
77683 {
77684 if (!is_string($value)) {
77685 throw new InvalidArgumentException('Ref value must be a string');
77686 }
77687
77688 $splitRef = explode('#', $value, 2);
77689 $this->filename = $splitRef[0];
77690 if (array_key_exists(1, $splitRef)) {
77691 $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
77692 }
77693 }
77694
77695
77696
77697
77698
77699
77700 private function decodePropertyPaths($propertyPathString)
77701 {
77702 $paths = array();
77703 foreach (explode('/', trim($propertyPathString, '/')) as $path) {
77704 $path = $this->decodePath($path);
77705 if (is_string($path) && '' !== $path) {
77706 $paths[] = $path;
77707 }
77708 }
77709
77710 return $paths;
77711 }
77712
77713
77714
77715
77716 private function encodePropertyPaths()
77717 {
77718 return array_map(
77719 array($this, 'encodePath'),
77720 $this->getPropertyPaths()
77721 );
77722 }
77723
77724
77725
77726
77727
77728
77729 private function decodePath($path)
77730 {
77731 return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
77732 }
77733
77734
77735
77736
77737
77738
77739 private function encodePath($path)
77740 {
77741 return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
77742 }
77743
77744
77745
77746
77747 public function getFilename()
77748 {
77749 return $this->filename;
77750 }
77751
77752
77753
77754
77755 public function getPropertyPaths()
77756 {
77757 return $this->propertyPaths;
77758 }
77759
77760
77761
77762
77763
77764
77765 public function withPropertyPaths(array $propertyPaths)
77766 {
77767 $new = clone $this;
77768 $new->propertyPaths = $propertyPaths;
77769
77770 return $new;
77771 }
77772
77773
77774
77775
77776 public function getPropertyPathAsString()
77777 {
77778 return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
77779 }
77780
77781
77782
77783
77784 public function __toString()
77785 {
77786 return $this->getFilename() . $this->getPropertyPathAsString();
77787 }
77788
77789
77790
77791
77792 public function setFromDefault()
77793 {
77794 $this->fromDefault = true;
77795 }
77796
77797
77798
77799
77800
77801
77802 public function fromDefault()
77803 {
77804 return $this->fromDefault;
77805 }
77806 }
77807 <?php
77808
77809 namespace JsonSchema\Exception;
77810
77811 interface ExceptionInterface
77812 {
77813 }
77814 <?php
77815
77816
77817
77818
77819
77820
77821
77822
77823 namespace JsonSchema\Exception;
77824
77825
77826
77827
77828 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
77829 {
77830 }
77831 <?php
77832
77833
77834
77835
77836
77837
77838
77839
77840 namespace JsonSchema\Exception;
77841
77842
77843
77844
77845 class InvalidConfigException extends RuntimeException
77846 {
77847 }
77848 <?php
77849
77850
77851
77852
77853
77854
77855
77856
77857 namespace JsonSchema\Exception;
77858
77859
77860
77861
77862 class InvalidSchemaException extends RuntimeException
77863 {
77864 }
77865 <?php
77866
77867
77868
77869
77870
77871
77872
77873
77874 namespace JsonSchema\Exception;
77875
77876
77877
77878
77879 class InvalidSchemaMediaTypeException extends RuntimeException
77880 {
77881 }
77882 <?php
77883
77884
77885
77886
77887
77888
77889
77890
77891 namespace JsonSchema\Exception;
77892
77893
77894
77895
77896 class InvalidSourceUriException extends InvalidArgumentException
77897 {
77898 }
77899 <?php
77900
77901
77902
77903
77904
77905
77906
77907
77908 namespace JsonSchema\Exception;
77909
77910
77911
77912
77913 class JsonDecodingException extends RuntimeException
77914 {
77915 public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
77916 {
77917 switch ($code) {
77918 case JSON_ERROR_DEPTH:
77919 $message = 'The maximum stack depth has been exceeded';
77920 break;
77921 case JSON_ERROR_STATE_MISMATCH:
77922 $message = 'Invalid or malformed JSON';
77923 break;
77924 case JSON_ERROR_CTRL_CHAR:
77925 $message = 'Control character error, possibly incorrectly encoded';
77926 break;
77927 case JSON_ERROR_UTF8:
77928 $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
77929 break;
77930 case JSON_ERROR_SYNTAX:
77931 $message = 'JSON syntax is malformed';
77932 break;
77933 default:
77934 $message = 'Syntax error';
77935 }
77936 parent::__construct($message, $code, $previous);
77937 }
77938 }
77939 <?php
77940
77941
77942
77943
77944
77945
77946
77947
77948 namespace JsonSchema\Exception;
77949
77950
77951
77952
77953 class ResourceNotFoundException extends RuntimeException
77954 {
77955 }
77956 <?php
77957
77958
77959
77960
77961
77962
77963
77964
77965 namespace JsonSchema\Exception;
77966
77967
77968
77969
77970 class RuntimeException extends \RuntimeException implements ExceptionInterface
77971 {
77972 }
77973 <?php
77974
77975
77976
77977
77978
77979
77980
77981
77982 namespace JsonSchema\Exception;
77983
77984
77985
77986
77987
77988
77989 class UnresolvableJsonPointerException extends InvalidArgumentException
77990 {
77991 }
77992 <?php
77993
77994
77995
77996
77997
77998
77999
78000
78001 namespace JsonSchema\Exception;
78002
78003
78004
78005
78006 class UriResolverException extends RuntimeException
78007 {
78008 }
78009 <?php
78010
78011
78012
78013
78014
78015
78016
78017
78018 namespace JsonSchema\Exception;
78019
78020 class ValidationException extends RuntimeException
78021 {
78022 }
78023 <?php
78024
78025
78026
78027
78028
78029
78030
78031
78032 namespace JsonSchema\Iterator;
78033
78034
78035
78036
78037
78038
78039 class ObjectIterator implements \Iterator, \Countable
78040 {
78041
78042 private $object;
78043
78044
78045 private $position = 0;
78046
78047
78048 private $data = array();
78049
78050
78051 private $initialized = false;
78052
78053
78054
78055
78056 public function __construct($object)
78057 {
78058 $this->object = $object;
78059 }
78060
78061
78062
78063
78064 public function current()
78065 {
78066 $this->initialize();
78067
78068 return $this->data[$this->position];
78069 }
78070
78071
78072
78073
78074 public function next()
78075 {
78076 $this->initialize();
78077 $this->position++;
78078 }
78079
78080
78081
78082
78083 public function key()
78084 {
78085 $this->initialize();
78086
78087 return $this->position;
78088 }
78089
78090
78091
78092
78093 public function valid()
78094 {
78095 $this->initialize();
78096
78097 return isset($this->data[$this->position]);
78098 }
78099
78100
78101
78102
78103 public function rewind()
78104 {
78105 $this->initialize();
78106 $this->position = 0;
78107 }
78108
78109
78110
78111
78112 public function count()
78113 {
78114 $this->initialize();
78115
78116 return count($this->data);
78117 }
78118
78119
78120
78121
78122 private function initialize()
78123 {
78124 if (!$this->initialized) {
78125 $this->data = $this->buildDataFromObject($this->object);
78126 $this->initialized = true;
78127 }
78128 }
78129
78130
78131
78132
78133
78134
78135 private function buildDataFromObject($object)
78136 {
78137 $result = array();
78138
78139 $stack = new \SplStack();
78140 $stack->push($object);
78141
78142 while (!$stack->isEmpty()) {
78143 $current = $stack->pop();
78144 if (is_object($current)) {
78145 array_push($result, $current);
78146 }
78147
78148 foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
78149 if (is_object($propertyValue) || is_array($propertyValue)) {
78150 $stack->push($propertyValue);
78151 }
78152 }
78153 }
78154
78155 return $result;
78156 }
78157
78158
78159
78160
78161
78162
78163 private function getDataFromItem($item)
78164 {
78165 if (!is_object($item) && !is_array($item)) {
78166 return array();
78167 }
78168
78169 return is_object($item) ? get_object_vars($item) : $item;
78170 }
78171 }
78172 <?php
78173
78174 namespace JsonSchema;
78175
78176 class Rfc3339
78177 {
78178 const REGEX = '/^(\d{4}-\d{2}-\d{2}[T ]{1}\d{2}:\d{2}:\d{2})(\.\d+)?(Z|([+-]\d{2}):?(\d{2}))$/';
78179
78180
78181
78182
78183
78184
78185
78186
78187 public static function createFromString($string)
78188 {
78189 if (!preg_match(self::REGEX, strtoupper($string), $matches)) {
78190 return null;
78191 }
78192
78193 $dateAndTime = $matches[1];
78194 $microseconds = $matches[2] ?: '.000000';
78195 $timeZone = 'Z' !== $matches[3] ? $matches[4] . ':' . $matches[5] : '+00:00';
78196 $dateFormat = strpos($dateAndTime, 'T') === false ? 'Y-m-d H:i:s.uP' : 'Y-m-d\TH:i:s.uP';
78197 $dateTime = \DateTime::createFromFormat($dateFormat, $dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
78198
78199 return $dateTime ?: null;
78200 }
78201 }
78202 <?php
78203
78204 namespace JsonSchema;
78205
78206 use JsonSchema\Constraints\BaseConstraint;
78207 use JsonSchema\Entity\JsonPointer;
78208 use JsonSchema\Exception\UnresolvableJsonPointerException;
78209 use JsonSchema\Iterator\ObjectIterator;
78210 use JsonSchema\Uri\UriResolver;
78211 use JsonSchema\Uri\UriRetriever;
78212
78213 class SchemaStorage implements SchemaStorageInterface
78214 {
78215 const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema';
78216
78217 protected $uriRetriever;
78218 protected $uriResolver;
78219 protected $schemas = array();
78220
78221 public function __construct(
78222 UriRetrieverInterface $uriRetriever = null,
78223 UriResolverInterface $uriResolver = null
78224 ) {
78225 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
78226 $this->uriResolver = $uriResolver ?: new UriResolver();
78227 }
78228
78229
78230
78231
78232 public function getUriRetriever()
78233 {
78234 return $this->uriRetriever;
78235 }
78236
78237
78238
78239
78240 public function getUriResolver()
78241 {
78242 return $this->uriResolver;
78243 }
78244
78245
78246
78247
78248 public function addSchema($id, $schema = null)
78249 {
78250 if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) {
78251
78252  
78253  
78254  $schema = $this->uriRetriever->retrieve($id);
78255 }
78256
78257
78258  if (is_array($schema)) {
78259 $schema = BaseConstraint::arrayToObjectRecursive($schema);
78260 }
78261
78262
78263  
78264  if (is_object($schema) && property_exists($schema, 'id')) {
78265 if ($schema->id == 'http://json-schema.org/draft-04/schema#') {
78266 $schema->properties->id->format = 'uri-reference';
78267 } elseif ($schema->id == 'http://json-schema.org/draft-03/schema#') {
78268 $schema->properties->id->format = 'uri-reference';
78269 $schema->properties->{'$ref'}->format = 'uri-reference';
78270 }
78271 }
78272
78273 $objectIterator = new ObjectIterator($schema);
78274 foreach ($objectIterator as $toResolveSchema) {
78275 if (property_exists($toResolveSchema, '$ref') && is_string($toResolveSchema->{'$ref'})) {
78276 $jsonPointer = new JsonPointer($this->uriResolver->resolve($toResolveSchema->{'$ref'}, $id));
78277 $toResolveSchema->{'$ref'} = (string) $jsonPointer;
78278 }
78279 }
78280 $this->schemas[$id] = $schema;
78281 }
78282
78283
78284
78285
78286 public function getSchema($id)
78287 {
78288 if (!array_key_exists($id, $this->schemas)) {
78289 $this->addSchema($id);
78290 }
78291
78292 return $this->schemas[$id];
78293 }
78294
78295
78296
78297
78298 public function resolveRef($ref)
78299 {
78300 $jsonPointer = new JsonPointer($ref);
78301
78302
78303  $fileName = $jsonPointer->getFilename();
78304 if (!strlen($fileName)) {
78305 throw new UnresolvableJsonPointerException(sprintf(
78306 "Could not resolve fragment '%s': no file is defined",
78307 $jsonPointer->getPropertyPathAsString()
78308 ));
78309 }
78310
78311
78312  $refSchema = $this->getSchema($fileName);
78313 foreach ($jsonPointer->getPropertyPaths() as $path) {
78314 if (is_object($refSchema) && property_exists($refSchema, $path)) {
78315 $refSchema = $this->resolveRefSchema($refSchema->{$path});
78316 } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) {
78317 $refSchema = $this->resolveRefSchema($refSchema[$path]);
78318 } else {
78319 throw new UnresolvableJsonPointerException(sprintf(
78320 'File: %s is found, but could not resolve fragment: %s',
78321 $jsonPointer->getFilename(),
78322 $jsonPointer->getPropertyPathAsString()
78323 ));
78324 }
78325 }
78326
78327 return $refSchema;
78328 }
78329
78330
78331
78332
78333 public function resolveRefSchema($refSchema)
78334 {
78335 if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) {
78336 $newSchema = $this->resolveRef($refSchema->{'$ref'});
78337 $refSchema = (object) (get_object_vars($refSchema) + get_object_vars($newSchema));
78338 unset($refSchema->{'$ref'});
78339 }
78340
78341 return $refSchema;
78342 }
78343 }
78344 <?php
78345
78346 namespace JsonSchema;
78347
78348 interface SchemaStorageInterface
78349 {
78350
78351
78352
78353
78354
78355
78356 public function addSchema($id, $schema = null);
78357
78358
78359
78360
78361
78362
78363
78364
78365 public function getSchema($id);
78366
78367
78368
78369
78370
78371
78372
78373
78374 public function resolveRef($ref);
78375
78376
78377
78378
78379
78380
78381
78382
78383 public function resolveRefSchema($refSchema);
78384 }
78385 <?php
78386
78387
78388
78389
78390
78391
78392 namespace JsonSchema\Uri\Retrievers;
78393
78394
78395
78396
78397
78398
78399
78400 abstract class AbstractRetriever implements UriRetrieverInterface
78401 {
78402
78403
78404
78405
78406
78407 protected $contentType;
78408
78409
78410
78411
78412
78413
78414 public function getContentType()
78415 {
78416 return $this->contentType;
78417 }
78418 }
78419 <?php
78420
78421
78422
78423
78424
78425
78426
78427
78428 namespace JsonSchema\Uri\Retrievers;
78429
78430 use JsonSchema\Exception\RuntimeException;
78431 use JsonSchema\Validator;
78432
78433
78434
78435
78436
78437
78438 class Curl extends AbstractRetriever
78439 {
78440 protected $messageBody;
78441
78442 public function __construct()
78443 {
78444 if (!function_exists('curl_init')) {
78445
78446  throw new RuntimeException('cURL not installed'); 
78447  }
78448 }
78449
78450
78451
78452
78453
78454
78455 public function retrieve($uri)
78456 {
78457 $ch = curl_init();
78458
78459 curl_setopt($ch, CURLOPT_URL, $uri);
78460 curl_setopt($ch, CURLOPT_HEADER, true);
78461 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
78462 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
78463
78464 $response = curl_exec($ch);
78465 if (false === $response) {
78466 throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
78467 }
78468
78469 $this->fetchMessageBody($response);
78470 $this->fetchContentType($response);
78471
78472 curl_close($ch);
78473
78474 return $this->messageBody;
78475 }
78476
78477
78478
78479
78480 private function fetchMessageBody($response)
78481 {
78482 preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
78483 $this->messageBody = $match[1];
78484 }
78485
78486
78487
78488
78489
78490
78491 protected function fetchContentType($response)
78492 {
78493 if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
78494 $this->contentType = trim($match[1]);
78495
78496 return true;
78497 }
78498
78499 return false;
78500 }
78501 }
78502 <?php
78503
78504
78505
78506
78507
78508
78509
78510
78511 namespace JsonSchema\Uri\Retrievers;
78512
78513 use JsonSchema\Exception\ResourceNotFoundException;
78514
78515
78516
78517
78518
78519
78520 class FileGetContents extends AbstractRetriever
78521 {
78522 protected $messageBody;
78523
78524
78525
78526
78527
78528
78529 public function retrieve($uri)
78530 {
78531 $errorMessage = null;
78532 set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
78533 $errorMessage = $errstr;
78534 });
78535 $response = file_get_contents($uri);
78536 restore_error_handler();
78537
78538 if ($errorMessage) {
78539 throw new ResourceNotFoundException($errorMessage);
78540 }
78541
78542 if (false === $response) {
78543 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
78544 }
78545
78546 if ($response == ''
78547 && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
78548 ) {
78549 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
78550 }
78551
78552 $this->messageBody = $response;
78553 if (!empty($http_response_header)) {
78554
78555  
78556  $this->fetchContentType($http_response_header); 
78557  } else { 
78558  
78559  $this->contentType = null;
78560 }
78561
78562 return $this->messageBody;
78563 }
78564
78565
78566
78567
78568
78569
78570 private function fetchContentType(array $headers)
78571 {
78572 foreach ($headers as $header) {
78573 if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
78574 return true;
78575 }
78576 }
78577
78578 return false;
78579 }
78580
78581
78582
78583
78584
78585
78586 protected static function getContentTypeMatchInHeader($header)
78587 {
78588 if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
78589 return trim($match[1]);
78590 }
78591
78592 return null;
78593 }
78594 }
78595 <?php
78596
78597 namespace JsonSchema\Uri\Retrievers;
78598
78599 use JsonSchema\Validator;
78600
78601
78602
78603
78604
78605
78606
78607
78608
78609
78610
78611
78612
78613 class PredefinedArray extends AbstractRetriever
78614 {
78615
78616
78617
78618
78619
78620 private $schemas;
78621
78622
78623
78624
78625
78626
78627
78628 public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
78629 {
78630 $this->schemas = $schemas;
78631 $this->contentType = $contentType;
78632 }
78633
78634
78635
78636
78637
78638
78639 public function retrieve($uri)
78640 {
78641 if (!array_key_exists($uri, $this->schemas)) {
78642 throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
78643 'The JSON schema "%s" was not found.',
78644 $uri
78645 ));
78646 }
78647
78648 return $this->schemas[$uri];
78649 }
78650 }
78651 <?php
78652
78653
78654
78655
78656
78657
78658
78659
78660 namespace JsonSchema\Uri\Retrievers;
78661
78662
78663
78664
78665
78666
78667 interface UriRetrieverInterface
78668 {
78669
78670
78671
78672
78673
78674
78675
78676
78677
78678 public function retrieve($uri);
78679
78680
78681
78682
78683
78684
78685 public function getContentType();
78686 }
78687 <?php
78688
78689
78690
78691
78692
78693
78694
78695
78696 namespace JsonSchema\Uri;
78697
78698 use JsonSchema\Exception\UriResolverException;
78699 use JsonSchema\UriResolverInterface;
78700
78701
78702
78703
78704
78705
78706 class UriResolver implements UriResolverInterface
78707 {
78708
78709
78710
78711
78712
78713
78714
78715 public function parse($uri)
78716 {
78717 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
78718
78719 $components = array();
78720 if (5 < count($match)) {
78721 $components = array(
78722 'scheme' => $match[2],
78723 'authority' => $match[4],
78724 'path' => $match[5]
78725 );
78726 }
78727 if (7 < count($match)) {
78728 $components['query'] = $match[7];
78729 }
78730 if (9 < count($match)) {
78731 $components['fragment'] = $match[9];
78732 }
78733
78734 return $components;
78735 }
78736
78737
78738
78739
78740
78741
78742
78743
78744 public function generate(array $components)
78745 {
78746 $uri = $components['scheme'] . '://'
78747 . $components['authority']
78748 . $components['path'];
78749
78750 if (array_key_exists('query', $components)) {
78751 $uri .= $components['query'];
78752 }
78753 if (array_key_exists('fragment', $components)) {
78754 $uri .= '#' . $components['fragment'];
78755 }
78756
78757 return $uri;
78758 }
78759
78760
78761
78762
78763 public function resolve($uri, $baseUri = null)
78764 {
78765 if ($uri == '') {
78766 return $baseUri;
78767 }
78768
78769 $components = $this->parse($uri);
78770 $path = $components['path'];
78771
78772 if (!empty($components['scheme'])) {
78773 return $uri;
78774 }
78775 $baseComponents = $this->parse($baseUri);
78776 $basePath = $baseComponents['path'];
78777
78778 $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
78779 if (isset($components['fragment'])) {
78780 $baseComponents['fragment'] = $components['fragment'];
78781 }
78782
78783 return $this->generate($baseComponents);
78784 }
78785
78786
78787
78788
78789
78790
78791
78792
78793
78794
78795
78796 public static function combineRelativePathWithBasePath($relativePath, $basePath)
78797 {
78798 $relativePath = self::normalizePath($relativePath);
78799 if ($relativePath == '') {
78800 return $basePath;
78801 }
78802 if ($relativePath[0] == '/') {
78803 return $relativePath;
78804 }
78805
78806 $basePathSegments = explode('/', $basePath);
78807
78808 preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
78809 $numLevelUp = strlen($match[0]) /3 + 1;
78810 if ($numLevelUp >= count($basePathSegments)) {
78811 throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
78812 }
78813
78814 $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
78815 $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
78816
78817 return implode('/', $basePathSegments) . '/' . $path;
78818 }
78819
78820
78821
78822
78823
78824
78825
78826
78827 private static function normalizePath($path)
78828 {
78829 $path = preg_replace('|((?<!\.)\./)*|', '', $path);
78830 $path = preg_replace('|//|', '/', $path);
78831
78832 return $path;
78833 }
78834
78835
78836
78837
78838
78839
78840 public function isValid($uri)
78841 {
78842 $components = $this->parse($uri);
78843
78844 return !empty($components);
78845 }
78846 }
78847 <?php
78848
78849
78850
78851
78852
78853
78854
78855
78856 namespace JsonSchema\Uri;
78857
78858 use JsonSchema\Exception\InvalidSchemaMediaTypeException;
78859 use JsonSchema\Exception\JsonDecodingException;
78860 use JsonSchema\Exception\ResourceNotFoundException;
78861 use JsonSchema\Uri\Retrievers\FileGetContents;
78862 use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
78863 use JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
78864 use JsonSchema\Validator;
78865
78866
78867
78868
78869
78870
78871 class UriRetriever implements BaseUriRetrieverInterface
78872 {
78873
78874
78875
78876 protected $translationMap = array(
78877
78878  '|^https?://json-schema.org/draft-(0[34])/schema#?|' => 'package://dist/schema/json-schema-draft-$1.json'
78879 );
78880
78881
78882
78883
78884 protected $uriRetriever = null;
78885
78886
78887
78888
78889
78890
78891 private $schemaCache = array();
78892
78893
78894
78895
78896
78897
78898
78899
78900
78901 public function confirmMediaType($uriRetriever, $uri)
78902 {
78903 $contentType = $uriRetriever->getContentType();
78904
78905 if (is_null($contentType)) {
78906
78907  return;
78908 }
78909
78910 if (in_array($contentType, array(Validator::SCHEMA_MEDIA_TYPE, 'application/json'))) {
78911 return;
78912 }
78913
78914 if (substr($uri, 0, 23) == 'http://json-schema.org/') {
78915
78916  return true;
78917 }
78918
78919 throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
78920 }
78921
78922
78923
78924
78925
78926
78927
78928
78929
78930 public function getUriRetriever()
78931 {
78932 if (is_null($this->uriRetriever)) {
78933 $this->setUriRetriever(new FileGetContents());
78934 }
78935
78936 return $this->uriRetriever;
78937 }
78938
78939
78940
78941
78942
78943
78944
78945
78946
78947
78948
78949
78950
78951
78952
78953 public function resolvePointer($jsonSchema, $uri)
78954 {
78955 $resolver = new UriResolver();
78956 $parsed = $resolver->parse($uri);
78957 if (empty($parsed['fragment'])) {
78958 return $jsonSchema;
78959 }
78960
78961 $path = explode('/', $parsed['fragment']);
78962 while ($path) {
78963 $pathElement = array_shift($path);
78964 if (!empty($pathElement)) {
78965 $pathElement = str_replace('~1', '/', $pathElement);
78966 $pathElement = str_replace('~0', '~', $pathElement);
78967 if (!empty($jsonSchema->$pathElement)) {
78968 $jsonSchema = $jsonSchema->$pathElement;
78969 } else {
78970 throw new ResourceNotFoundException(
78971 'Fragment "' . $parsed['fragment'] . '" not found'
78972 . ' in ' . $uri
78973 );
78974 }
78975
78976 if (!is_object($jsonSchema)) {
78977 throw new ResourceNotFoundException(
78978 'Fragment part "' . $pathElement . '" is no object '
78979 . ' in ' . $uri
78980 );
78981 }
78982 }
78983 }
78984
78985 return $jsonSchema;
78986 }
78987
78988
78989
78990
78991 public function retrieve($uri, $baseUri = null, $translate = true)
78992 {
78993 $resolver = new UriResolver();
78994 $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
78995
78996
78997  $arParts = $resolver->parse($resolvedUri);
78998 if (isset($arParts['fragment'])) {
78999 unset($arParts['fragment']);
79000 $fetchUri = $resolver->generate($arParts);
79001 }
79002
79003
79004  if ($translate) {
79005 $fetchUri = $this->translate($fetchUri);
79006 }
79007
79008 $jsonSchema = $this->loadSchema($fetchUri);
79009
79010
79011  $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
79012
79013 if ($jsonSchema instanceof \stdClass) {
79014 $jsonSchema->id = $resolvedUri;
79015 }
79016
79017 return $jsonSchema;
79018 }
79019
79020
79021
79022
79023
79024
79025
79026
79027
79028 protected function loadSchema($fetchUri)
79029 {
79030 if (isset($this->schemaCache[$fetchUri])) {
79031 return $this->schemaCache[$fetchUri];
79032 }
79033
79034 $uriRetriever = $this->getUriRetriever();
79035 $contents = $this->uriRetriever->retrieve($fetchUri);
79036 $this->confirmMediaType($uriRetriever, $fetchUri);
79037 $jsonSchema = json_decode($contents);
79038
79039 if (JSON_ERROR_NONE < $error = json_last_error()) {
79040 throw new JsonDecodingException($error);
79041 }
79042
79043 $this->schemaCache[$fetchUri] = $jsonSchema;
79044
79045 return $jsonSchema;
79046 }
79047
79048
79049
79050
79051
79052
79053
79054
79055 public function setUriRetriever(UriRetrieverInterface $uriRetriever)
79056 {
79057 $this->uriRetriever = $uriRetriever;
79058
79059 return $this;
79060 }
79061
79062
79063
79064
79065
79066
79067
79068
79069 public function parse($uri)
79070 {
79071 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
79072
79073 $components = array();
79074 if (5 < count($match)) {
79075 $components = array(
79076 'scheme' => $match[2],
79077 'authority' => $match[4],
79078 'path' => $match[5]
79079 );
79080 }
79081
79082 if (7 < count($match)) {
79083 $components['query'] = $match[7];
79084 }
79085
79086 if (9 < count($match)) {
79087 $components['fragment'] = $match[9];
79088 }
79089
79090 return $components;
79091 }
79092
79093
79094
79095
79096
79097
79098
79099
79100 public function generate(array $components)
79101 {
79102 $uri = $components['scheme'] . '://'
79103 . $components['authority']
79104 . $components['path'];
79105
79106 if (array_key_exists('query', $components)) {
79107 $uri .= $components['query'];
79108 }
79109
79110 if (array_key_exists('fragment', $components)) {
79111 $uri .= $components['fragment'];
79112 }
79113
79114 return $uri;
79115 }
79116
79117
79118
79119
79120
79121
79122
79123
79124
79125 public function resolve($uri, $baseUri = null)
79126 {
79127 $components = $this->parse($uri);
79128 $path = $components['path'];
79129
79130 if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
79131 return $uri;
79132 }
79133
79134 $baseComponents = $this->parse($baseUri);
79135 $basePath = $baseComponents['path'];
79136
79137 $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
79138
79139 return $this->generate($baseComponents);
79140 }
79141
79142
79143
79144
79145
79146
79147 public function isValid($uri)
79148 {
79149 $components = $this->parse($uri);
79150
79151 return !empty($components);
79152 }
79153
79154
79155
79156
79157 public function setTranslation($from, $to)
79158 {
79159 $this->translationMap[$from] = $to;
79160 }
79161
79162
79163
79164
79165 public function translate($uri)
79166 {
79167 foreach ($this->translationMap as $from => $to) {
79168 $uri = preg_replace($from, $to, $uri);
79169 }
79170
79171
79172  $uri = preg_replace('|^package://|', sprintf('file://%s/', realpath(__DIR__ . '/../../..')), $uri);
79173
79174 return $uri;
79175 }
79176 }
79177 <?php
79178
79179
79180
79181
79182
79183
79184
79185
79186 namespace JsonSchema;
79187
79188
79189
79190
79191 interface UriResolverInterface
79192 {
79193
79194
79195
79196
79197
79198
79199
79200
79201 public function resolve($uri, $baseUri = null);
79202 }
79203 <?php
79204
79205
79206
79207
79208
79209
79210
79211
79212 namespace JsonSchema;
79213
79214
79215
79216
79217 interface UriRetrieverInterface
79218 {
79219
79220
79221
79222
79223
79224
79225
79226
79227 public function retrieve($uri, $baseUri = null);
79228 }
79229 <?php
79230
79231
79232
79233
79234
79235
79236
79237
79238 namespace JsonSchema;
79239
79240 use JsonSchema\Constraints\BaseConstraint;
79241 use JsonSchema\Constraints\Constraint;
79242 use JsonSchema\Exception\InvalidConfigException;
79243 use JsonSchema\SchemaStorage;
79244
79245
79246
79247
79248
79249
79250
79251
79252
79253 class Validator extends BaseConstraint
79254 {
79255 const SCHEMA_MEDIA_TYPE = 'application/schema+json';
79256
79257 const ERROR_NONE = 0x00000000;
79258 const ERROR_ALL = 0xFFFFFFFF;
79259 const ERROR_DOCUMENT_VALIDATION = 0x00000001;
79260 const ERROR_SCHEMA_VALIDATION = 0x00000002;
79261
79262
79263
79264
79265
79266
79267
79268
79269
79270
79271 public function validate(&$value, $schema = null, $checkMode = null)
79272 {
79273
79274  if (is_array($schema)) {
79275 $schema = self::arrayToObjectRecursive($schema);
79276 }
79277
79278
79279  $initialCheckMode = $this->factory->getConfig();
79280 if ($checkMode !== null) {
79281 $this->factory->setConfig($checkMode);
79282 }
79283
79284
79285  $this->factory->getSchemaStorage()->addSchema(SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI, $schema);
79286
79287 $validator = $this->factory->createInstanceFor('schema');
79288 $validator->check(
79289 $value,
79290 $this->factory->getSchemaStorage()->getSchema(SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI)
79291 );
79292
79293 $this->factory->setConfig($initialCheckMode);
79294
79295 $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
79296
79297 return $validator->getErrorMask();
79298 }
79299
79300
79301
79302
79303 public function check($value, $schema)
79304 {
79305 return $this->validate($value, $schema);
79306 }
79307
79308
79309
79310
79311 public function coerce(&$value, $schema)
79312 {
79313 return $this->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
79314 }
79315 }
79316 Copyright (C) 2015 Composer
79317
79318 Permission is hereby granted, free of charge, to any person obtaining a copy of
79319 this software and associated documentation files (the "Software"), to deal in
79320 the Software without restriction, including without limitation the rights to
79321 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
79322 of the Software, and to permit persons to whom the Software is furnished to do
79323 so, subject to the following conditions:
79324
79325 The above copyright notice and this permission notice shall be included in all
79326 copies or substantial portions of the Software.
79327
79328 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
79329 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
79330 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
79331 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
79332 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
79333 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
79334 SOFTWARE.
79335 <?php
79336
79337
79338
79339
79340
79341
79342
79343
79344
79345
79346 namespace Composer\Spdx;
79347
79348 class SpdxLicenses
79349 {
79350
79351 const LICENSES_FILE = 'spdx-licenses.json';
79352
79353
79354 const EXCEPTIONS_FILE = 'spdx-exceptions.json';
79355
79356
79357
79358
79359
79360
79361
79362
79363
79364
79365
79366
79367
79368
79369 private $licenses;
79370
79371
79372
79373
79374 private $licensesExpression;
79375
79376
79377
79378
79379
79380
79381
79382
79383
79384
79385
79386
79387
79388
79389 private $exceptions;
79390
79391
79392
79393
79394 private $exceptionsExpression;
79395
79396 public function __construct()
79397 {
79398 $this->loadLicenses();
79399 $this->loadExceptions();
79400 }
79401
79402
79403
79404
79405
79406
79407
79408
79409
79410
79411
79412
79413
79414 public function getLicenseByIdentifier($identifier)
79415 {
79416 if (!isset($this->licenses[$identifier])) {
79417 return;
79418 }
79419
79420 $license = $this->licenses[$identifier];
79421 $license[] = 'https://spdx.org/licenses/' . $identifier . '.html#licenseText';
79422
79423 return $license;
79424 }
79425
79426
79427
79428
79429
79430
79431
79432
79433
79434
79435
79436
79437
79438 public function getExceptionByIdentifier($identifier)
79439 {
79440 if (!isset($this->exceptions[$identifier])) {
79441 return;
79442 }
79443
79444 $license = $this->exceptions[$identifier];
79445 $license[] = 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText';
79446
79447 return $license;
79448 }
79449
79450
79451
79452
79453
79454
79455
79456
79457 public function getIdentifierByName($name)
79458 {
79459 foreach ($this->licenses as $identifier => $licenseData) {
79460 if ($licenseData[0] === $name) {
79461 return $identifier;
79462 }
79463 }
79464
79465 foreach ($this->exceptions as $identifier => $licenseData) {
79466 if ($licenseData[0] === $name) {
79467 return $identifier;
79468 }
79469 }
79470 }
79471
79472
79473
79474
79475
79476
79477
79478
79479 public function isOsiApprovedByIdentifier($identifier)
79480 {
79481 return $this->licenses[$identifier][1];
79482 }
79483
79484
79485
79486
79487
79488
79489
79490
79491 public function validate($license)
79492 {
79493 if (is_array($license)) {
79494 $count = count($license);
79495 if ($count !== count(array_filter($license, 'is_string'))) {
79496 throw new \InvalidArgumentException('Array of strings expected.');
79497 }
79498 $license = $count > 1 ? '(' . implode(' OR ', $license) . ')' : (string) reset($license);
79499 }
79500
79501 if (!is_string($license)) {
79502 throw new \InvalidArgumentException(sprintf(
79503 'Array or String expected, %s given.',
79504 gettype($license)
79505 ));
79506 }
79507
79508 return $this->isValidLicenseString($license);
79509 }
79510
79511
79512
79513
79514 public static function getResourcesDir()
79515 {
79516 return dirname(__DIR__) . '/res';
79517 }
79518
79519 private function loadLicenses()
79520 {
79521 if (null === $this->licenses) {
79522 $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
79523 $this->licenses = json_decode($json, true);
79524 }
79525 }
79526
79527 private function loadExceptions()
79528 {
79529 if (null === $this->exceptions) {
79530 $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
79531 $this->exceptions = json_decode($json, true);
79532 }
79533 }
79534
79535
79536
79537
79538 private function getLicensesExpression()
79539 {
79540 if (null === $this->licensesExpression) {
79541 $licenses = array_map('preg_quote', array_keys($this->licenses));
79542 rsort($licenses);
79543 $licenses = implode('|', $licenses);
79544 $this->licensesExpression = $licenses;
79545 }
79546
79547 return $this->licensesExpression;
79548 }
79549
79550
79551
79552
79553 private function getExceptionsExpression()
79554 {
79555 if (null === $this->exceptionsExpression) {
79556 $exceptions = array_map('preg_quote', array_keys($this->exceptions));
79557 rsort($exceptions);
79558 $exceptions = implode('|', $exceptions);
79559 $this->exceptionsExpression = $exceptions;
79560 }
79561
79562 return $this->exceptionsExpression;
79563 }
79564
79565
79566
79567
79568
79569
79570
79571
79572 private function isValidLicenseString($license)
79573 {
79574 if (isset($this->licenses[$license])) {
79575 return true;
79576 }
79577
79578 $licenses = $this->getLicensesExpression();
79579 $exceptions = $this->getExceptionsExpression();
79580
79581 $regex = <<<REGEX
79582 {
79583 (?(DEFINE)
79584     # idstring: 1*( ALPHA / DIGIT / - / . )
79585     (?<idstring>[\pL\pN.-]{1,})
79586
79587     # license-id: taken from list
79588     (?<licenseid>${licenses})
79589
79590     # license-exception-id: taken from list
79591     (?<licenseexceptionid>${exceptions})
79592
79593     # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
79594     (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))
79595
79596     # simple-expresssion: license-id / license-id+ / license-ref
79597     (?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref))
79598
79599     # compound-expression: 1*(
79600     #   simple-expression /
79601     #   simple-expression WITH license-exception-id /
79602     #   compound-expression AND compound-expression /
79603     #   compound-expression OR compound-expression
79604     # ) / ( compound-expression ) )
79605     (?<compound_head>
79606         (?&simple_expression) ( \s+ (?:with|WITH) \s+ (?&licenseexceptionid))?
79607             | \( \s* (?&compound_expression) \s* \)
79608     )
79609     (?<compound_expression>
79610         (?&compound_head) (?: \s+ (?:and|AND|or|OR) \s+ (?&compound_expression))?
79611     )
79612
79613     # license-expression: 1*1(simple-expression / compound-expression)
79614     (?<license_expression>(?&compound_expression) | (?&simple_expression))
79615 ) # end of define
79616
79617 ^(NONE | NOASSERTION | (?&license_expression))$
79618 }x
79619 REGEX;
79620
79621 $match = preg_match($regex, $license);
79622
79623 if (0 === $match) {
79624 return false;
79625 }
79626
79627 if (false === $match) {
79628 throw new \RuntimeException('Regex failed to compile/run.');
79629 }
79630
79631 return true;
79632 }
79633 }
79634 Copyright (C) 2015 Composer
79635
79636 Permission is hereby granted, free of charge, to any person obtaining a copy of
79637 this software and associated documentation files (the "Software"), to deal in
79638 the Software without restriction, including without limitation the rights to
79639 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
79640 of the Software, and to permit persons to whom the Software is furnished to do
79641 so, subject to the following conditions:
79642
79643 The above copyright notice and this permission notice shall be included in all
79644 copies or substantial portions of the Software.
79645
79646 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
79647 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
79648 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
79649 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
79650 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
79651 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
79652 SOFTWARE.
79653 <?php
79654
79655
79656
79657
79658
79659
79660
79661
79662
79663
79664 namespace Composer\Semver;
79665
79666 use Composer\Semver\Constraint\Constraint;
79667
79668 class Comparator
79669 {
79670
79671
79672
79673
79674
79675
79676
79677
79678 public static function greaterThan($version1, $version2)
79679 {
79680 return self::compare($version1, '>', $version2);
79681 }
79682
79683
79684
79685
79686
79687
79688
79689
79690
79691 public static function greaterThanOrEqualTo($version1, $version2)
79692 {
79693 return self::compare($version1, '>=', $version2);
79694 }
79695
79696
79697
79698
79699
79700
79701
79702
79703
79704 public static function lessThan($version1, $version2)
79705 {
79706 return self::compare($version1, '<', $version2);
79707 }
79708
79709
79710
79711
79712
79713
79714
79715
79716
79717 public static function lessThanOrEqualTo($version1, $version2)
79718 {
79719 return self::compare($version1, '<=', $version2);
79720 }
79721
79722
79723
79724
79725
79726
79727
79728
79729
79730 public static function equalTo($version1, $version2)
79731 {
79732 return self::compare($version1, '==', $version2);
79733 }
79734
79735
79736
79737
79738
79739
79740
79741
79742
79743 public static function notEqualTo($version1, $version2)
79744 {
79745 return self::compare($version1, '!=', $version2);
79746 }
79747
79748
79749
79750
79751
79752
79753
79754
79755
79756
79757 public static function compare($version1, $operator, $version2)
79758 {
79759 $constraint = new Constraint($operator, $version2);
79760
79761 return $constraint->matches(new Constraint('==', $version1));
79762 }
79763 }
79764 <?php
79765
79766
79767
79768
79769
79770
79771
79772
79773
79774
79775 namespace Composer\Semver\Constraint;
79776
79777 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);
79778
79779
79780
79781
79782 abstract class AbstractConstraint implements ConstraintInterface
79783 {
79784
79785 protected $prettyString;
79786
79787
79788
79789
79790
79791
79792 public function matches(ConstraintInterface $provider)
79793 {
79794 if ($provider instanceof $this) {
79795
79796  return $this->matchSpecific($provider);
79797 }
79798
79799
79800  return $provider->matches($this);
79801 }
79802
79803
79804
79805
79806 public function setPrettyString($prettyString)
79807 {
79808 $this->prettyString = $prettyString;
79809 }
79810
79811
79812
79813
79814 public function getPrettyString()
79815 {
79816 if ($this->prettyString) {
79817 return $this->prettyString;
79818 }
79819
79820 return $this->__toString();
79821 }
79822
79823
79824  
79825  
79826 }
79827 <?php
79828
79829
79830
79831
79832
79833
79834
79835
79836
79837
79838 namespace Composer\Semver\Constraint;
79839
79840
79841
79842
79843 class Constraint implements ConstraintInterface
79844 {
79845
79846 const OP_EQ = 0;
79847 const OP_LT = 1;
79848 const OP_LE = 2;
79849 const OP_GT = 3;
79850 const OP_GE = 4;
79851 const OP_NE = 5;
79852
79853
79854
79855
79856
79857
79858 private static $transOpStr = array(
79859 '=' => self::OP_EQ,
79860 '==' => self::OP_EQ,
79861 '<' => self::OP_LT,
79862 '<=' => self::OP_LE,
79863 '>' => self::OP_GT,
79864 '>=' => self::OP_GE,
79865 '<>' => self::OP_NE,
79866 '!=' => self::OP_NE,
79867 );
79868
79869
79870
79871
79872
79873
79874 private static $transOpInt = array(
79875 self::OP_EQ => '==',
79876 self::OP_LT => '<',
79877 self::OP_LE => '<=',
79878 self::OP_GT => '>',
79879 self::OP_GE => '>=',
79880 self::OP_NE => '!=',
79881 );
79882
79883
79884 protected $operator;
79885
79886
79887 protected $version;
79888
79889
79890 protected $prettyString;
79891
79892
79893
79894
79895
79896
79897 public function matches(ConstraintInterface $provider)
79898 {
79899 if ($provider instanceof $this) {
79900 return $this->matchSpecific($provider);
79901 }
79902
79903
79904  return $provider->matches($this);
79905 }
79906
79907
79908
79909
79910 public function setPrettyString($prettyString)
79911 {
79912 $this->prettyString = $prettyString;
79913 }
79914
79915
79916
79917
79918 public function getPrettyString()
79919 {
79920 if ($this->prettyString) {
79921 return $this->prettyString;
79922 }
79923
79924 return $this->__toString();
79925 }
79926
79927
79928
79929
79930
79931
79932 public static function getSupportedOperators()
79933 {
79934 return array_keys(self::$transOpStr);
79935 }
79936
79937
79938
79939
79940
79941
79942
79943
79944
79945 public function __construct($operator, $version)
79946 {
79947 if (!isset(self::$transOpStr[$operator])) {
79948 throw new \InvalidArgumentException(sprintf(
79949 'Invalid operator "%s" given, expected one of: %s',
79950 $operator,
79951 implode(', ', self::getSupportedOperators())
79952 ));
79953 }
79954
79955 $this->operator = self::$transOpStr[$operator];
79956 $this->version = $version;
79957 }
79958
79959
79960
79961
79962
79963
79964
79965
79966
79967
79968
79969 public function versionCompare($a, $b, $operator, $compareBranches = false)
79970 {
79971 if (!isset(self::$transOpStr[$operator])) {
79972 throw new \InvalidArgumentException(sprintf(
79973 'Invalid operator "%s" given, expected one of: %s',
79974 $operator,
79975 implode(', ', self::getSupportedOperators())
79976 ));
79977 }
79978
79979 $aIsBranch = 'dev-' === substr($a, 0, 4);
79980 $bIsBranch = 'dev-' === substr($b, 0, 4);
79981
79982 if ($aIsBranch && $bIsBranch) {
79983 return $operator === '==' && $a === $b;
79984 }
79985
79986
79987  if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
79988 return false;
79989 }
79990
79991 return version_compare($a, $b, $operator);
79992 }
79993
79994
79995
79996
79997
79998
79999
80000 public function matchSpecific(Constraint $provider, $compareBranches = false)
80001 {
80002 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
80003 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
80004
80005 $isEqualOp = self::OP_EQ === $this->operator;
80006 $isNonEqualOp = self::OP_NE === $this->operator;
80007 $isProviderEqualOp = self::OP_EQ === $provider->operator;
80008 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
80009
80010
80011  
80012  if ($isNonEqualOp || $isProviderNonEqualOp) {
80013 return !$isEqualOp && !$isProviderEqualOp
80014 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
80015 }
80016
80017
80018  
80019  if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
80020 return true;
80021 }
80022
80023 if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
80024
80025  
80026  if ($provider->version === $this->version
80027 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
80028 && self::$transOpInt[$this->operator] !== $noEqualOp) {
80029 return false;
80030 }
80031
80032 return true;
80033 }
80034
80035 return false;
80036 }
80037
80038
80039
80040
80041 public function __toString()
80042 {
80043 return self::$transOpInt[$this->operator] . ' ' . $this->version;
80044 }
80045 }
80046 <?php
80047
80048
80049
80050
80051
80052
80053
80054
80055
80056
80057 namespace Composer\Semver\Constraint;
80058
80059 interface ConstraintInterface
80060 {
80061
80062
80063
80064
80065
80066 public function matches(ConstraintInterface $provider);
80067
80068
80069
80070
80071 public function getPrettyString();
80072
80073
80074
80075
80076 public function __toString();
80077 }
80078 <?php
80079
80080
80081
80082
80083
80084
80085
80086
80087
80088
80089 namespace Composer\Semver\Constraint;
80090
80091
80092
80093
80094 class EmptyConstraint implements ConstraintInterface
80095 {
80096
80097 protected $prettyString;
80098
80099
80100
80101
80102
80103
80104 public function matches(ConstraintInterface $provider)
80105 {
80106 return true;
80107 }
80108
80109
80110
80111
80112 public function setPrettyString($prettyString)
80113 {
80114 $this->prettyString = $prettyString;
80115 }
80116
80117
80118
80119
80120 public function getPrettyString()
80121 {
80122 if ($this->prettyString) {
80123 return $this->prettyString;
80124 }
80125
80126 return $this->__toString();
80127 }
80128
80129
80130
80131
80132 public function __toString()
80133 {
80134 return '[]';
80135 }
80136 }
80137 <?php
80138
80139
80140
80141
80142
80143
80144
80145
80146
80147
80148 namespace Composer\Semver\Constraint;
80149
80150
80151
80152
80153 class MultiConstraint implements ConstraintInterface
80154 {
80155
80156 protected $constraints;
80157
80158
80159 protected $prettyString;
80160
80161
80162 protected $conjunctive;
80163
80164
80165
80166
80167
80168 public function __construct(array $constraints, $conjunctive = true)
80169 {
80170 $this->constraints = $constraints;
80171 $this->conjunctive = $conjunctive;
80172 }
80173
80174
80175
80176
80177 public function getConstraints()
80178 {
80179 return $this->constraints;
80180 }
80181
80182
80183
80184
80185 public function isConjunctive()
80186 {
80187 return $this->conjunctive;
80188 }
80189
80190
80191
80192
80193 public function isDisjunctive()
80194 {
80195 return !$this->conjunctive;
80196 }
80197
80198
80199
80200
80201
80202
80203 public function matches(ConstraintInterface $provider)
80204 {
80205 if (false === $this->conjunctive) {
80206 foreach ($this->constraints as $constraint) {
80207 if ($constraint->matches($provider)) {
80208 return true;
80209 }
80210 }
80211
80212 return false;
80213 }
80214
80215 foreach ($this->constraints as $constraint) {
80216 if (!$constraint->matches($provider)) {
80217 return false;
80218 }
80219 }
80220
80221 return true;
80222 }
80223
80224
80225
80226
80227 public function setPrettyString($prettyString)
80228 {
80229 $this->prettyString = $prettyString;
80230 }
80231
80232
80233
80234
80235 public function getPrettyString()
80236 {
80237 if ($this->prettyString) {
80238 return $this->prettyString;
80239 }
80240
80241 return $this->__toString();
80242 }
80243
80244
80245
80246
80247 public function __toString()
80248 {
80249 $constraints = array();
80250 foreach ($this->constraints as $constraint) {
80251 $constraints[] = (string) $constraint;
80252 }
80253
80254 return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
80255 }
80256 }
80257 <?php
80258
80259
80260
80261
80262
80263
80264
80265
80266
80267
80268 namespace Composer\Semver;
80269
80270 use Composer\Semver\Constraint\Constraint;
80271
80272 class Semver
80273 {
80274 const SORT_ASC = 1;
80275 const SORT_DESC = -1;
80276
80277
80278 private static $versionParser;
80279
80280
80281
80282
80283
80284
80285
80286
80287
80288 public static function satisfies($version, $constraints)
80289 {
80290 if (null === self::$versionParser) {
80291 self::$versionParser = new VersionParser();
80292 }
80293
80294 $versionParser = self::$versionParser;
80295 $provider = new Constraint('==', $versionParser->normalize($version));
80296 $constraints = $versionParser->parseConstraints($constraints);
80297
80298 return $constraints->matches($provider);
80299 }
80300
80301
80302
80303
80304
80305
80306
80307
80308
80309 public static function satisfiedBy(array $versions, $constraints)
80310 {
80311 $versions = array_filter($versions, function ($version) use ($constraints) {
80312 return Semver::satisfies($version, $constraints);
80313 });
80314
80315 return array_values($versions);
80316 }
80317
80318
80319
80320
80321
80322
80323
80324
80325 public static function sort(array $versions)
80326 {
80327 return self::usort($versions, self::SORT_ASC);
80328 }
80329
80330
80331
80332
80333
80334
80335
80336
80337 public static function rsort(array $versions)
80338 {
80339 return self::usort($versions, self::SORT_DESC);
80340 }
80341
80342
80343
80344
80345
80346
80347
80348 private static function usort(array $versions, $direction)
80349 {
80350 if (null === self::$versionParser) {
80351 self::$versionParser = new VersionParser();
80352 }
80353
80354 $versionParser = self::$versionParser;
80355 $normalized = array();
80356
80357
80358  
80359  foreach ($versions as $key => $version) {
80360 $normalized[] = array($versionParser->normalize($version), $key);
80361 }
80362
80363 usort($normalized, function (array $left, array $right) use ($direction) {
80364 if ($left[0] === $right[0]) {
80365 return 0;
80366 }
80367
80368 if (Comparator::lessThan($left[0], $right[0])) {
80369 return -$direction;
80370 }
80371
80372 return $direction;
80373 });
80374
80375
80376  $sorted = array();
80377 foreach ($normalized as $item) {
80378 $sorted[] = $versions[$item[1]];
80379 }
80380
80381 return $sorted;
80382 }
80383 }
80384 <?php
80385
80386
80387
80388
80389
80390
80391
80392
80393
80394
80395 namespace Composer\Semver;
80396
80397 use Composer\Semver\Constraint\ConstraintInterface;
80398 use Composer\Semver\Constraint\EmptyConstraint;
80399 use Composer\Semver\Constraint\MultiConstraint;
80400 use Composer\Semver\Constraint\Constraint;
80401
80402
80403
80404
80405
80406
80407 class VersionParser
80408 {
80409
80410
80411
80412
80413
80414
80415
80416
80417
80418
80419
80420
80421
80422 private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
80423
80424
80425 private static $stabilities = array('stable', 'RC', 'beta', 'alpha', 'dev');
80426
80427
80428
80429
80430
80431
80432
80433
80434 public static function parseStability($version)
80435 {
80436 $version = preg_replace('{#.+$}i', '', $version);
80437
80438 if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
80439 return 'dev';
80440 }
80441
80442 preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
80443 if (!empty($match[3])) {
80444 return 'dev';
80445 }
80446
80447 if (!empty($match[1])) {
80448 if ('beta' === $match[1] || 'b' === $match[1]) {
80449 return 'beta';
80450 }
80451 if ('alpha' === $match[1] || 'a' === $match[1]) {
80452 return 'alpha';
80453 }
80454 if ('rc' === $match[1]) {
80455 return 'RC';
80456 }
80457 }
80458
80459 return 'stable';
80460 }
80461
80462
80463
80464
80465
80466
80467 public static function normalizeStability($stability)
80468 {
80469 $stability = strtolower($stability);
80470
80471 return $stability === 'rc' ? 'RC' : $stability;
80472 }
80473
80474
80475
80476
80477
80478
80479
80480
80481
80482
80483
80484 public function normalize($version, $fullVersion = null)
80485 {
80486 $version = trim($version);
80487 if (null === $fullVersion) {
80488 $fullVersion = $version;
80489 }
80490
80491
80492  if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
80493 $version = $match[1];
80494 }
80495
80496
80497  if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
80498 return '9999999-dev';
80499 }
80500
80501
80502  if ('dev-' === strtolower(substr($version, 0, 4))) {
80503 return 'dev-' . substr($version, 4);
80504 }
80505
80506
80507  if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
80508 $version = $match[1];
80509 }
80510
80511
80512  if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
80513 $version = $matches[1]
80514 . (!empty($matches[2]) ? $matches[2] : '.0')
80515 . (!empty($matches[3]) ? $matches[3] : '.0')
80516 . (!empty($matches[4]) ? $matches[4] : '.0');
80517 $index = 5;
80518
80519  } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) {
80520 $version = preg_replace('{\D}', '.', $matches[1]);
80521 $index = 2;
80522 }
80523
80524
80525  if (isset($index)) {
80526 if (!empty($matches[$index])) {
80527 if ('stable' === $matches[$index]) {
80528 return $version;
80529 }
80530 $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? ltrim($matches[$index + 1], '.-') : '');
80531 }
80532
80533 if (!empty($matches[$index + 2])) {
80534 $version .= '-dev';
80535 }
80536
80537 return $version;
80538 }
80539
80540
80541  if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
80542 try {
80543 return $this->normalizeBranch($match[1]);
80544 } catch (\Exception $e) {
80545 }
80546 }
80547
80548 $extraMessage = '';
80549 if (preg_match('{ +as +' . preg_quote($version) . '$}', $fullVersion)) {
80550 $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
80551 } elseif (preg_match('{^' . preg_quote($version) . ' +as +}', $fullVersion)) {
80552 $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
80553 }
80554
80555 throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage);
80556 }
80557
80558
80559
80560
80561
80562
80563
80564
80565 public function parseNumericAliasPrefix($branch)
80566 {
80567 if (preg_match('{^(?P<version>(\d++\\.)*\d++)(?:\.x)?-dev$}i', $branch, $matches)) {
80568 return $matches['version'] . '.';
80569 }
80570
80571 return false;
80572 }
80573
80574
80575
80576
80577
80578
80579
80580
80581 public function normalizeBranch($name)
80582 {
80583 $name = trim($name);
80584
80585 if (in_array($name, array('master', 'trunk', 'default'))) {
80586 return $this->normalize($name);
80587 }
80588
80589 if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
80590 $version = '';
80591 for ($i = 1; $i < 5; ++$i) {
80592 $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
80593 }
80594
80595 return str_replace('x', '9999999', $version) . '-dev';
80596 }
80597
80598 return 'dev-' . $name;
80599 }
80600
80601
80602
80603
80604
80605
80606
80607
80608 public function parseConstraints($constraints)
80609 {
80610 $prettyConstraint = $constraints;
80611
80612 if (preg_match('{^([^,\s]*?)@(' . implode('|', self::$stabilities) . ')$}i', $constraints, $match)) {
80613 $constraints = empty($match[1]) ? '*' : $match[1];
80614 }
80615
80616 if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) {
80617 $constraints = $match[1];
80618 }
80619
80620 $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
80621 $orGroups = array();
80622 foreach ($orConstraints as $constraints) {
80623 $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
80624 if (count($andConstraints) > 1) {
80625 $constraintObjects = array();
80626 foreach ($andConstraints as $constraint) {
80627 foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
80628 $constraintObjects[] = $parsedConstraint;
80629 }
80630 }
80631 } else {
80632 $constraintObjects = $this->parseConstraint($andConstraints[0]);
80633 }
80634
80635 if (1 === count($constraintObjects)) {
80636 $constraint = $constraintObjects[0];
80637 } else {
80638 $constraint = new MultiConstraint($constraintObjects);
80639 }
80640
80641 $orGroups[] = $constraint;
80642 }
80643
80644 if (1 === count($orGroups)) {
80645 $constraint = $orGroups[0];
80646 } elseif (2 === count($orGroups)
80647
80648  
80649  && $orGroups[0] instanceof MultiConstraint
80650 && $orGroups[1] instanceof MultiConstraint
80651 && 2 === count($orGroups[0]->getConstraints())
80652 && 2 === count($orGroups[1]->getConstraints())
80653 && ($a = (string) $orGroups[0])
80654 && substr($a, 0, 3) === '[>=' && (false !== ($posA = strpos($a, '<', 4)))
80655 && ($b = (string) $orGroups[1])
80656 && substr($b, 0, 3) === '[>=' && (false !== ($posB = strpos($b, '<', 4)))
80657 && substr($a, $posA + 2, -1) === substr($b, 4, $posB - 5)
80658 ) {
80659 $constraint = new MultiConstraint(array(
80660 new Constraint('>=', substr($a, 4, $posA - 5)),
80661 new Constraint('<', substr($b, $posB + 2, -1)),
80662 ));
80663 } else {
80664 $constraint = new MultiConstraint($orGroups, false);
80665 }
80666
80667 $constraint->setPrettyString($prettyConstraint);
80668
80669 return $constraint;
80670 }
80671
80672
80673
80674
80675
80676
80677
80678
80679 private function parseConstraint($constraint)
80680 {
80681 if (preg_match('{^([^,\s]+?)@(' . implode('|', self::$stabilities) . ')$}i', $constraint, $match)) {
80682 $constraint = $match[1];
80683 if ($match[2] !== 'stable') {
80684 $stabilityModifier = $match[2];
80685 }
80686 }
80687
80688 if (preg_match('{^v?[xX*](\.[xX*])*$}i', $constraint)) {
80689 return array(new EmptyConstraint());
80690 }
80691
80692 $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?' . self::$modifierRegex . '(?:\+[^\s]+)?';
80693
80694
80695  
80696  
80697  
80698  
80699  if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
80700 if (substr($constraint, 0, 2) === '~>') {
80701 throw new \UnexpectedValueException(
80702 'Could not parse version constraint ' . $constraint . ': ' .
80703 'Invalid operator "~>", you probably meant to use the "~" operator'
80704 );
80705 }
80706
80707
80708  if (isset($matches[4]) && '' !== $matches[4]) {
80709 $position = 4;
80710 } elseif (isset($matches[3]) && '' !== $matches[3]) {
80711 $position = 3;
80712 } elseif (isset($matches[2]) && '' !== $matches[2]) {
80713 $position = 2;
80714 } else {
80715 $position = 1;
80716 }
80717
80718
80719  $stabilitySuffix = '';
80720 if (!empty($matches[5])) {
80721 $stabilitySuffix .= '-' . $this->expandStability($matches[5]) . (!empty($matches[6]) ? $matches[6] : '');
80722 }
80723
80724 if (!empty($matches[7])) {
80725 $stabilitySuffix .= '-dev';
80726 }
80727
80728 if (!$stabilitySuffix) {
80729 $stabilitySuffix = '-dev';
80730 }
80731
80732 $lowVersion = $this->manipulateVersionString($matches, $position, 0) . $stabilitySuffix;
80733 $lowerBound = new Constraint('>=', $lowVersion);
80734
80735
80736  
80737  $highPosition = max(1, $position - 1);
80738 $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
80739 $upperBound = new Constraint('<', $highVersion);
80740
80741 return array(
80742 $lowerBound,
80743 $upperBound,
80744 );
80745 }
80746
80747
80748  
80749  
80750  
80751  
80752  if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
80753
80754  if ('0' !== $matches[1] || '' === $matches[2]) {
80755 $position = 1;
80756 } elseif ('0' !== $matches[2] || '' === $matches[3]) {
80757 $position = 2;
80758 } else {
80759 $position = 3;
80760 }
80761
80762
80763  $stabilitySuffix = '';
80764 if (empty($matches[5]) && empty($matches[7])) {
80765 $stabilitySuffix .= '-dev';
80766 }
80767
80768 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
80769 $lowerBound = new Constraint('>=', $lowVersion);
80770
80771
80772  
80773  $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
80774 $upperBound = new Constraint('<', $highVersion);
80775
80776 return array(
80777 $lowerBound,
80778 $upperBound,
80779 );
80780 }
80781
80782
80783  
80784  
80785  
80786  if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
80787 if (isset($matches[3]) && '' !== $matches[3]) {
80788 $position = 3;
80789 } elseif (isset($matches[2]) && '' !== $matches[2]) {
80790 $position = 2;
80791 } else {
80792 $position = 1;
80793 }
80794
80795 $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
80796 $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
80797
80798 if ($lowVersion === '0.0.0.0-dev') {
80799 return array(new Constraint('<', $highVersion));
80800 }
80801
80802 return array(
80803 new Constraint('>=', $lowVersion),
80804 new Constraint('<', $highVersion),
80805 );
80806 }
80807
80808
80809  
80810  
80811  
80812  
80813  
80814  if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
80815
80816  $lowStabilitySuffix = '';
80817 if (empty($matches[6]) && empty($matches[8])) {
80818 $lowStabilitySuffix = '-dev';
80819 }
80820
80821 $lowVersion = $this->normalize($matches['from']);
80822 $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
80823
80824 $empty = function ($x) {
80825 return ($x === 0 || $x === '0') ? false : empty($x);
80826 };
80827
80828 if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) {
80829 $highVersion = $this->normalize($matches['to']);
80830 $upperBound = new Constraint('<=', $highVersion);
80831 } else {
80832 $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]);
80833 $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev';
80834 $upperBound = new Constraint('<', $highVersion);
80835 }
80836
80837 return array(
80838 $lowerBound,
80839 $upperBound,
80840 );
80841 }
80842
80843
80844  if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
80845 try {
80846 $version = $this->normalize($matches[2]);
80847
80848 if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') {
80849 $version .= '-' . $stabilityModifier;
80850 } elseif ('<' === $matches[1] || '>=' === $matches[1]) {
80851 if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
80852 if (substr($matches[2], 0, 4) !== 'dev-') {
80853 $version .= '-dev';
80854 }
80855 }
80856 }
80857
80858 return array(new Constraint($matches[1] ?: '=', $version));
80859 } catch (\Exception $e) {
80860 }
80861 }
80862
80863 $message = 'Could not parse version constraint ' . $constraint;
80864 if (isset($e)) {
80865 $message .= ': ' . $e->getMessage();
80866 }
80867
80868 throw new \UnexpectedValueException($message);
80869 }
80870
80871
80872
80873
80874
80875
80876
80877
80878
80879
80880
80881
80882
80883 private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
80884 {
80885 for ($i = 4; $i > 0; --$i) {
80886 if ($i > $position) {
80887 $matches[$i] = $pad;
80888 } elseif ($i === $position && $increment) {
80889 $matches[$i] += $increment;
80890
80891  if ($matches[$i] < 0) {
80892 $matches[$i] = $pad;
80893 --$position;
80894
80895
80896  if ($i === 1) {
80897 return;
80898 }
80899 }
80900 }
80901 }
80902
80903 return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
80904 }
80905
80906
80907
80908
80909
80910
80911
80912
80913 private function expandStability($stability)
80914 {
80915 $stability = strtolower($stability);
80916
80917 switch ($stability) {
80918 case 'a':
80919 return 'alpha';
80920 case 'b':
80921 return 'beta';
80922 case 'p':
80923 case 'pl':
80924 return 'patch';
80925 case 'rc':
80926 return 'RC';
80927 default:
80928 return $stability;
80929 }
80930 }
80931 }
80932 Copyright (C) 2016 Composer
80933
80934 Permission is hereby granted, free of charge, to any person obtaining a copy of
80935 this software and associated documentation files (the "Software"), to deal in
80936 the Software without restriction, including without limitation the rights to
80937 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
80938 of the Software, and to permit persons to whom the Software is furnished to do
80939 so, subject to the following conditions:
80940
80941 The above copyright notice and this permission notice shall be included in all
80942 copies or substantial portions of the Software.
80943
80944 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
80945 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
80946 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
80947 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
80948 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
80949 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
80950 SOFTWARE.
80951 <?php
80952
80953
80954
80955
80956
80957
80958
80959
80960
80961
80962 namespace Composer\CaBundle;
80963
80964 use Psr\Log\LoggerInterface;
80965 use Symfony\Component\Process\PhpProcess;
80966
80967
80968
80969
80970
80971 class CaBundle
80972 {
80973 private static $caPath;
80974 private static $caFileValidity = array();
80975 private static $useOpensslParse;
80976
80977
80978
80979
80980
80981
80982
80983
80984
80985
80986
80987
80988
80989
80990
80991
80992
80993
80994
80995
80996
80997
80998
80999
81000
81001
81002
81003
81004
81005
81006
81007
81008
81009
81010
81011
81012
81013
81014 public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
81015 {
81016 if (self::$caPath !== null) {
81017 return self::$caPath;
81018 }
81019
81020
81021  
81022  $envCertFile = getenv('SSL_CERT_FILE');
81023 if ($envCertFile && is_readable($envCertFile) && static::validateCaFile($envCertFile, $logger)) {
81024 return self::$caPath = $envCertFile;
81025 }
81026
81027
81028  
81029  $envCertDir = getenv('SSL_CERT_DIR');
81030 if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) {
81031 return self::$caPath = $envCertDir;
81032 }
81033
81034 $configured = ini_get('openssl.cafile');
81035 if ($configured && strlen($configured) > 0 && is_readable($configured) && static::validateCaFile($configured, $logger)) {
81036 return self::$caPath = $configured;
81037 }
81038
81039 $configured = ini_get('openssl.capath');
81040 if ($configured && is_dir($configured) && is_readable($configured)) {
81041 return self::$caPath = $configured;
81042 }
81043
81044 $caBundlePaths = array(
81045 '/etc/pki/tls/certs/ca-bundle.crt', 
81046  '/etc/ssl/certs/ca-certificates.crt', 
81047  '/etc/ssl/ca-bundle.pem', 
81048  '/usr/local/share/certs/ca-root-nss.crt', 
81049  '/usr/ssl/certs/ca-bundle.crt', 
81050  '/opt/local/share/curl/curl-ca-bundle.crt', 
81051  '/usr/local/share/curl/curl-ca-bundle.crt', 
81052  '/usr/share/ssl/certs/ca-bundle.crt', 
81053  '/etc/ssl/cert.pem', 
81054  '/usr/local/etc/ssl/cert.pem', 
81055  '/usr/local/etc/openssl/cert.pem', 
81056  );
81057
81058 foreach ($caBundlePaths as $caBundle) {
81059 if (@is_readable($caBundle) && static::validateCaFile($caBundle, $logger)) {
81060 return self::$caPath = $caBundle;
81061 }
81062 }
81063
81064 foreach ($caBundlePaths as $caBundle) {
81065 $caBundle = dirname($caBundle);
81066 if (@is_dir($caBundle) && glob($caBundle.'/*')) {
81067 return self::$caPath = $caBundle;
81068 }
81069 }
81070
81071 return self::$caPath = static::getBundledCaBundlePath(); 
81072  }
81073
81074
81075
81076
81077
81078
81079
81080
81081 public static function getBundledCaBundlePath()
81082 {
81083 return __DIR__.'/../res/cacert.pem';
81084 }
81085
81086
81087
81088
81089
81090
81091
81092
81093
81094 public static function validateCaFile($filename, LoggerInterface $logger = null)
81095 {
81096 static $warned = false;
81097
81098 if (isset(self::$caFileValidity[$filename])) {
81099 return self::$caFileValidity[$filename];
81100 }
81101
81102 $contents = file_get_contents($filename);
81103
81104
81105  
81106  if (!static::isOpensslParseSafe()) {
81107 if (!$warned && $logger) {
81108 $logger->warning(sprintf(
81109 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
81110 PHP_VERSION
81111 ));
81112 $warned = true;
81113 }
81114
81115 $isValid = !empty($contents);
81116 } else {
81117 $isValid = (bool) openssl_x509_parse($contents);
81118 }
81119
81120 if ($logger) {
81121 $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
81122 }
81123
81124 return self::$caFileValidity[$filename] = $isValid;
81125 }
81126
81127
81128
81129
81130
81131
81132
81133
81134
81135 public static function isOpensslParseSafe()
81136 {
81137 if (null !== self::$useOpensslParse) {
81138 return self::$useOpensslParse;
81139 }
81140
81141 if (PHP_VERSION_ID >= 50600) {
81142 return self::$useOpensslParse = true;
81143 }
81144
81145
81146  
81147  
81148  
81149  if (
81150 (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
81151 || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
81152 || (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
81153 ) {
81154
81155  return self::$useOpensslParse = true;
81156 }
81157
81158 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
81159
81160  return self::$useOpensslParse = false;
81161 }
81162
81163 $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
81164 $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
81165
81166 if (preg_match($regex, PHP_VERSION, $m)) {
81167 return ((int) $m[1]) >= $fixedVersion;
81168 }
81169
81170 return false;
81171 };
81172
81173
81174  if (
81175 $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) 
81176  || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) 
81177  || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) 
81178  ) {
81179 return self::$useOpensslParse = true;
81180 }
81181
81182
81183  if (!class_exists('Symfony\Component\Process\PhpProcess')) {
81184 return self::$useOpensslParse = false;
81185 }
81186
81187
81188  
81189  
81190  
81191  
81192  
81193
81194
81195  
81196  $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
81197 $script = <<<'EOT'
81198
81199 error_reporting(-1);
81200 $info = openssl_x509_parse(base64_decode('%s'));
81201 var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
81202
81203 EOT;
81204 $script = '<'."?php\n".sprintf($script, $cert);
81205
81206 try {
81207 $process = new PhpProcess($script);
81208 $process->mustRun();
81209 } catch (\Exception $e) {
81210
81211  
81212  return self::$useOpensslParse = false;
81213 }
81214
81215 $output = preg_split('{\r?\n}', trim($process->getOutput()));
81216 $errorOutput = trim($process->getErrorOutput());
81217
81218 if (
81219 count($output) === 3
81220 && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
81221 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
81222 && $output[2] === 'int(-1)'
81223 && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
81224 ) {
81225
81226  return self::$useOpensslParse = true;
81227 }
81228
81229 return self::$useOpensslParse = false;
81230 }
81231
81232
81233
81234
81235 public static function reset()
81236 {
81237 self::$caFileValidity = array();
81238 self::$caPath = null;
81239 self::$useOpensslParse = null;
81240 }
81241 }
81242 Copyright (c) 2012 PHP Framework Interoperability Group
81243
81244 Permission is hereby granted, free of charge, to any person obtaining a copy 
81245 of this software and associated documentation files (the "Software"), to deal
81246 in the Software without restriction, including without limitation the rights 
81247 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
81248 copies of the Software, and to permit persons to whom the Software is 
81249 furnished to do so, subject to the following conditions:
81250
81251 The above copyright notice and this permission notice shall be included in 
81252 all copies or substantial portions of the Software.
81253
81254 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81255 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81256 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
81257 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81258 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
81259 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
81260 THE SOFTWARE.
81261 <?php
81262
81263 namespace Psr\Log;
81264
81265
81266
81267
81268
81269
81270
81271
81272 abstract class AbstractLogger implements LoggerInterface
81273 {
81274
81275
81276
81277
81278
81279
81280
81281
81282 public function emergency($message, array $context = array())
81283 {
81284 $this->log(LogLevel::EMERGENCY, $message, $context);
81285 }
81286
81287
81288
81289
81290
81291
81292
81293
81294
81295
81296
81297
81298 public function alert($message, array $context = array())
81299 {
81300 $this->log(LogLevel::ALERT, $message, $context);
81301 }
81302
81303
81304
81305
81306
81307
81308
81309
81310
81311
81312
81313 public function critical($message, array $context = array())
81314 {
81315 $this->log(LogLevel::CRITICAL, $message, $context);
81316 }
81317
81318
81319
81320
81321
81322
81323
81324
81325
81326
81327 public function error($message, array $context = array())
81328 {
81329 $this->log(LogLevel::ERROR, $message, $context);
81330 }
81331
81332
81333
81334
81335
81336
81337
81338
81339
81340
81341
81342
81343 public function warning($message, array $context = array())
81344 {
81345 $this->log(LogLevel::WARNING, $message, $context);
81346 }
81347
81348
81349
81350
81351
81352
81353
81354
81355
81356 public function notice($message, array $context = array())
81357 {
81358 $this->log(LogLevel::NOTICE, $message, $context);
81359 }
81360
81361
81362
81363
81364
81365
81366
81367
81368
81369
81370
81371 public function info($message, array $context = array())
81372 {
81373 $this->log(LogLevel::INFO, $message, $context);
81374 }
81375
81376
81377
81378
81379
81380
81381
81382
81383
81384 public function debug($message, array $context = array())
81385 {
81386 $this->log(LogLevel::DEBUG, $message, $context);
81387 }
81388 }
81389 <?php
81390
81391 namespace Psr\Log;
81392
81393 class InvalidArgumentException extends \InvalidArgumentException
81394 {
81395 }
81396 <?php
81397
81398 namespace Psr\Log;
81399
81400
81401
81402
81403 class LogLevel
81404 {
81405 const EMERGENCY = 'emergency';
81406 const ALERT = 'alert';
81407 const CRITICAL = 'critical';
81408 const ERROR = 'error';
81409 const WARNING = 'warning';
81410 const NOTICE = 'notice';
81411 const INFO = 'info';
81412 const DEBUG = 'debug';
81413 }
81414 <?php
81415
81416 namespace Psr\Log;
81417
81418
81419
81420
81421 interface LoggerAwareInterface
81422 {
81423
81424
81425
81426
81427
81428
81429
81430 public function setLogger(LoggerInterface $logger);
81431 }
81432 <?php
81433
81434 namespace Psr\Log;
81435
81436
81437
81438
81439 trait LoggerAwareTrait
81440 {
81441
81442
81443
81444
81445
81446 protected $logger;
81447
81448
81449
81450
81451
81452
81453 public function setLogger(LoggerInterface $logger)
81454 {
81455 $this->logger = $logger;
81456 }
81457 }
81458 <?php
81459
81460 namespace Psr\Log;
81461
81462
81463
81464
81465
81466
81467
81468
81469
81470
81471
81472
81473
81474
81475
81476
81477 interface LoggerInterface
81478 {
81479
81480
81481
81482
81483
81484
81485
81486
81487 public function emergency($message, array $context = array());
81488
81489
81490
81491
81492
81493
81494
81495
81496
81497
81498
81499
81500 public function alert($message, array $context = array());
81501
81502
81503
81504
81505
81506
81507
81508
81509
81510
81511
81512 public function critical($message, array $context = array());
81513
81514
81515
81516
81517
81518
81519
81520
81521
81522
81523 public function error($message, array $context = array());
81524
81525
81526
81527
81528
81529
81530
81531
81532
81533
81534
81535
81536 public function warning($message, array $context = array());
81537
81538
81539
81540
81541
81542
81543
81544
81545
81546 public function notice($message, array $context = array());
81547
81548
81549
81550
81551
81552
81553
81554
81555
81556
81557
81558 public function info($message, array $context = array());
81559
81560
81561
81562
81563
81564
81565
81566
81567
81568 public function debug($message, array $context = array());
81569
81570
81571
81572
81573
81574
81575
81576
81577
81578
81579 public function log($level, $message, array $context = array());
81580 }
81581 <?php
81582
81583 namespace Psr\Log;
81584
81585
81586
81587
81588
81589
81590
81591
81592
81593 trait LoggerTrait
81594 {
81595
81596
81597
81598
81599
81600
81601
81602
81603 public function emergency($message, array $context = array())
81604 {
81605 $this->log(LogLevel::EMERGENCY, $message, $context);
81606 }
81607
81608
81609
81610
81611
81612
81613
81614
81615
81616
81617
81618
81619 public function alert($message, array $context = array())
81620 {
81621 $this->log(LogLevel::ALERT, $message, $context);
81622 }
81623
81624
81625
81626
81627
81628
81629
81630
81631
81632
81633
81634 public function critical($message, array $context = array())
81635 {
81636 $this->log(LogLevel::CRITICAL, $message, $context);
81637 }
81638
81639
81640
81641
81642
81643
81644
81645
81646
81647
81648 public function error($message, array $context = array())
81649 {
81650 $this->log(LogLevel::ERROR, $message, $context);
81651 }
81652
81653
81654
81655
81656
81657
81658
81659
81660
81661
81662
81663
81664 public function warning($message, array $context = array())
81665 {
81666 $this->log(LogLevel::WARNING, $message, $context);
81667 }
81668
81669
81670
81671
81672
81673
81674
81675
81676
81677 public function notice($message, array $context = array())
81678 {
81679 $this->log(LogLevel::NOTICE, $message, $context);
81680 }
81681
81682
81683
81684
81685
81686
81687
81688
81689
81690
81691
81692 public function info($message, array $context = array())
81693 {
81694 $this->log(LogLevel::INFO, $message, $context);
81695 }
81696
81697
81698
81699
81700
81701
81702
81703
81704
81705 public function debug($message, array $context = array())
81706 {
81707 $this->log(LogLevel::DEBUG, $message, $context);
81708 }
81709
81710
81711
81712
81713
81714
81715
81716
81717
81718
81719 abstract public function log($level, $message, array $context = array());
81720 }
81721 <?php
81722
81723 namespace Psr\Log;
81724
81725
81726
81727
81728
81729
81730
81731
81732
81733 class NullLogger extends AbstractLogger
81734 {
81735
81736
81737
81738
81739
81740
81741
81742
81743
81744 public function log($level, $message, array $context = array())
81745 {
81746
81747  }
81748 }
81749 <?php
81750
81751 namespace Psr\Log\Test;
81752
81753 use Psr\Log\LoggerInterface;
81754 use Psr\Log\LogLevel;
81755
81756
81757
81758
81759
81760
81761
81762 abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase
81763 {
81764
81765
81766
81767 abstract public function getLogger();
81768
81769
81770
81771
81772
81773
81774
81775
81776
81777
81778 abstract public function getLogs();
81779
81780 public function testImplements()
81781 {
81782 $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
81783 }
81784
81785
81786
81787
81788 public function testLogsAtAllLevels($level, $message)
81789 {
81790 $logger = $this->getLogger();
81791 $logger->{$level}($message, array('user' => 'Bob'));
81792 $logger->log($level, $message, array('user' => 'Bob'));
81793
81794 $expected = array(
81795 $level.' message of level '.$level.' with context: Bob',
81796 $level.' message of level '.$level.' with context: Bob',
81797 );
81798 $this->assertEquals($expected, $this->getLogs());
81799 }
81800
81801 public function provideLevelsAndMessages()
81802 {
81803 return array(
81804 LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
81805 LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
81806 LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
81807 LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
81808 LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
81809 LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
81810 LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
81811 LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
81812 );
81813 }
81814
81815
81816
81817
81818 public function testThrowsOnInvalidLevel()
81819 {
81820 $logger = $this->getLogger();
81821 $logger->log('invalid level', 'Foo');
81822 }
81823
81824 public function testContextReplacement()
81825 {
81826 $logger = $this->getLogger();
81827 $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
81828
81829 $expected = array('info {Message {nothing} Bob Bar a}');
81830 $this->assertEquals($expected, $this->getLogs());
81831 }
81832
81833 public function testObjectCastToString()
81834 {
81835 if (method_exists($this, 'createPartialMock')) {
81836 $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
81837 } else {
81838 $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
81839 }
81840 $dummy->expects($this->once())
81841 ->method('__toString')
81842 ->will($this->returnValue('DUMMY'));
81843
81844 $this->getLogger()->warning($dummy);
81845
81846 $expected = array('warning DUMMY');
81847 $this->assertEquals($expected, $this->getLogs());
81848 }
81849
81850 public function testContextCanContainAnything()
81851 {
81852 $context = array(
81853 'bool' => true,
81854 'null' => null,
81855 'string' => 'Foo',
81856 'int' => 0,
81857 'float' => 0.5,
81858 'nested' => array('with object' => new DummyTest),
81859 'object' => new \DateTime,
81860 'resource' => fopen('php://memory', 'r'),
81861 );
81862
81863 $this->getLogger()->warning('Crazy context data', $context);
81864
81865 $expected = array('warning Crazy context data');
81866 $this->assertEquals($expected, $this->getLogs());
81867 }
81868
81869 public function testContextExceptionKeyCanBeExceptionOrOtherValues()
81870 {
81871 $logger = $this->getLogger();
81872 $logger->warning('Random message', array('exception' => 'oops'));
81873 $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
81874
81875 $expected = array(
81876 'warning Random message',
81877 'critical Uncaught Exception!'
81878 );
81879 $this->assertEquals($expected, $this->getLogs());
81880 }
81881 }
81882
81883 class DummyTest
81884 {
81885 public function __toString()
81886 {
81887 }
81888 }
81889 <?php
81890
81891
81892
81893 require_once __DIR__ . '/composer/autoload_real.php';
81894
81895 return ComposerAutoloaderInitComposerPhar1502287642::getLoader();
81896 <?php
81897
81898
81899
81900 $vendorDir = dirname(dirname(__FILE__));
81901 $baseDir = dirname($vendorDir);
81902
81903 return array(
81904 );
81905 <?php
81906
81907
81908
81909 $vendorDir = dirname(dirname(__FILE__));
81910 $baseDir = dirname($vendorDir);
81911
81912 return array(
81913 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
81914 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
81915 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
81916 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
81917 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
81918 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
81919 'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
81920 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
81921 'Seld\\CliPrompt\\' => array($vendorDir . '/seld/cli-prompt/src'),
81922 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
81923 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
81924 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
81925 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
81926 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
81927 'Composer\\' => array($baseDir . '/src/Composer'),
81928 );
81929 <?php
81930
81931
81932
81933 $vendorDir = dirname(dirname(__FILE__));
81934 $baseDir = dirname($vendorDir);
81935
81936 return array(
81937 );
81938 <?php
81939
81940
81941
81942 $vendorDir = dirname(dirname(__FILE__));
81943 $baseDir = dirname($vendorDir);
81944
81945 return array(
81946 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
81947 );
81948 <?php
81949
81950
81951
81952 class ComposerAutoloaderInitComposerPhar1502287642
81953 {
81954 private static $loader;
81955
81956 public static function loadClassLoader($class)
81957 {
81958 if ('Composer\Autoload\ClassLoader' === $class) {
81959 require __DIR__ . '/ClassLoader.php';
81960 }
81961 }
81962
81963 public static function getLoader()
81964 {
81965 if (null !== self::$loader) {
81966 return self::$loader;
81967 }
81968
81969 spl_autoload_register(array('ComposerAutoloaderInitComposerPhar1502287642', 'loadClassLoader'), true, true);
81970 self::$loader = $loader = new \Composer\Autoload\ClassLoader();
81971 spl_autoload_unregister(array('ComposerAutoloaderInitComposerPhar1502287642', 'loadClassLoader'));
81972
81973 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
81974 if ($useStaticLoader) {
81975 require_once __DIR__ . '/autoload_static.php';
81976
81977 call_user_func(\Composer\Autoload\ComposerStaticInitComposerPhar1502287642::getInitializer($loader));
81978 } else {
81979 $map = require __DIR__ . '/autoload_namespaces.php';
81980 foreach ($map as $namespace => $path) {
81981 $loader->set($namespace, $path);
81982 }
81983
81984 $map = require __DIR__ . '/autoload_psr4.php';
81985 foreach ($map as $namespace => $path) {
81986 $loader->setPsr4($namespace, $path);
81987 }
81988
81989 $classMap = require __DIR__ . '/autoload_classmap.php';
81990 if ($classMap) {
81991 $loader->addClassMap($classMap);
81992 }
81993 }
81994
81995 $loader->register(true);
81996
81997 if ($useStaticLoader) {
81998 $includeFiles = Composer\Autoload\ComposerStaticInitComposerPhar1502287642::$files;
81999 } else {
82000 $includeFiles = require __DIR__ . '/autoload_files.php';
82001 }
82002 foreach ($includeFiles as $fileIdentifier => $file) {
82003 composerRequireComposerPhar1502287642($fileIdentifier, $file);
82004 }
82005
82006 return $loader;
82007 }
82008 }
82009
82010 function composerRequireComposerPhar1502287642($fileIdentifier, $file)
82011 {
82012 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
82013 require $file;
82014
82015 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
82016 }
82017 }
82018 <?php
82019
82020
82021
82022 namespace Composer\Autoload;
82023
82024 class ComposerStaticInitComposerPhar1502287642
82025 {
82026 public static $files = array (
82027 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
82028 );
82029
82030 public static $prefixLengthsPsr4 = array (
82031 'S' => 
82032 array (
82033 'Symfony\\Polyfill\\Mbstring\\' => 26,
82034 'Symfony\\Component\\Process\\' => 26,
82035 'Symfony\\Component\\Finder\\' => 25,
82036 'Symfony\\Component\\Filesystem\\' => 29,
82037 'Symfony\\Component\\Debug\\' => 24,
82038 'Symfony\\Component\\Console\\' => 26,
82039 'Seld\\PharUtils\\' => 15,
82040 'Seld\\JsonLint\\' => 14,
82041 'Seld\\CliPrompt\\' => 15,
82042 ),
82043 'P' => 
82044 array (
82045 'Psr\\Log\\' => 8,
82046 ),
82047 'J' => 
82048 array (
82049 'JsonSchema\\' => 11,
82050 ),
82051 'C' => 
82052 array (
82053 'Composer\\Spdx\\' => 14,
82054 'Composer\\Semver\\' => 16,
82055 'Composer\\CaBundle\\' => 18,
82056 'Composer\\' => 9,
82057 ),
82058 );
82059
82060 public static $prefixDirsPsr4 = array (
82061 'Symfony\\Polyfill\\Mbstring\\' => 
82062 array (
82063 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
82064 ),
82065 'Symfony\\Component\\Process\\' => 
82066 array (
82067 0 => __DIR__ . '/..' . '/symfony/process',
82068 ),
82069 'Symfony\\Component\\Finder\\' => 
82070 array (
82071 0 => __DIR__ . '/..' . '/symfony/finder',
82072 ),
82073 'Symfony\\Component\\Filesystem\\' => 
82074 array (
82075 0 => __DIR__ . '/..' . '/symfony/filesystem',
82076 ),
82077 'Symfony\\Component\\Debug\\' => 
82078 array (
82079 0 => __DIR__ . '/..' . '/symfony/debug',
82080 ),
82081 'Symfony\\Component\\Console\\' => 
82082 array (
82083 0 => __DIR__ . '/..' . '/symfony/console',
82084 ),
82085 'Seld\\PharUtils\\' => 
82086 array (
82087 0 => __DIR__ . '/..' . '/seld/phar-utils/src',
82088 ),
82089 'Seld\\JsonLint\\' => 
82090 array (
82091 0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
82092 ),
82093 'Seld\\CliPrompt\\' => 
82094 array (
82095 0 => __DIR__ . '/..' . '/seld/cli-prompt/src',
82096 ),
82097 'Psr\\Log\\' => 
82098 array (
82099 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
82100 ),
82101 'JsonSchema\\' => 
82102 array (
82103 0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema',
82104 ),
82105 'Composer\\Spdx\\' => 
82106 array (
82107 0 => __DIR__ . '/..' . '/composer/spdx-licenses/src',
82108 ),
82109 'Composer\\Semver\\' => 
82110 array (
82111 0 => __DIR__ . '/..' . '/composer/semver/src',
82112 ),
82113 'Composer\\CaBundle\\' => 
82114 array (
82115 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
82116 ),
82117 'Composer\\' => 
82118 array (
82119 0 => __DIR__ . '/../..' . '/src/Composer',
82120 ),
82121 );
82122
82123 public static function getInitializer(ClassLoader $loader)
82124 {
82125 return \Closure::bind(function () use ($loader) {
82126 $loader->prefixLengthsPsr4 = ComposerStaticInitComposerPhar1502287642::$prefixLengthsPsr4;
82127 $loader->prefixDirsPsr4 = ComposerStaticInitComposerPhar1502287642::$prefixDirsPsr4;
82128
82129 }, null, ClassLoader::class);
82130 }
82131 }
82132 <?php
82133
82134
82135
82136
82137
82138
82139
82140
82141
82142
82143
82144 namespace Composer\Autoload;
82145
82146
82147
82148
82149
82150
82151
82152
82153
82154
82155
82156
82157
82158
82159
82160
82161
82162
82163
82164
82165
82166
82167
82168
82169
82170
82171
82172
82173
82174 class ClassLoader
82175 {
82176
82177  private $prefixLengthsPsr4 = array();
82178 private $prefixDirsPsr4 = array();
82179 private $fallbackDirsPsr4 = array();
82180
82181
82182  private $prefixesPsr0 = array();
82183 private $fallbackDirsPsr0 = array();
82184
82185 private $useIncludePath = false;
82186 private $classMap = array();
82187 private $classMapAuthoritative = false;
82188 private $missingClasses = array();
82189 private $apcuPrefix;
82190
82191 public function getPrefixes()
82192 {
82193 if (!empty($this->prefixesPsr0)) {
82194 return call_user_func_array('array_merge', $this->prefixesPsr0);
82195 }
82196
82197 return array();
82198 }
82199
82200 public function getPrefixesPsr4()
82201 {
82202 return $this->prefixDirsPsr4;
82203 }
82204
82205 public function getFallbackDirs()
82206 {
82207 return $this->fallbackDirsPsr0;
82208 }
82209
82210 public function getFallbackDirsPsr4()
82211 {
82212 return $this->fallbackDirsPsr4;
82213 }
82214
82215 public function getClassMap()
82216 {
82217 return $this->classMap;
82218 }
82219
82220
82221
82222
82223 public function addClassMap(array $classMap)
82224 {
82225 if ($this->classMap) {
82226 $this->classMap = array_merge($this->classMap, $classMap);
82227 } else {
82228 $this->classMap = $classMap;
82229 }
82230 }
82231
82232
82233
82234
82235
82236
82237
82238
82239
82240 public function add($prefix, $paths, $prepend = false)
82241 {
82242 if (!$prefix) {
82243 if ($prepend) {
82244 $this->fallbackDirsPsr0 = array_merge(
82245 (array) $paths,
82246 $this->fallbackDirsPsr0
82247 );
82248 } else {
82249 $this->fallbackDirsPsr0 = array_merge(
82250 $this->fallbackDirsPsr0,
82251 (array) $paths
82252 );
82253 }
82254
82255 return;
82256 }
82257
82258 $first = $prefix[0];
82259 if (!isset($this->prefixesPsr0[$first][$prefix])) {
82260 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
82261
82262 return;
82263 }
82264 if ($prepend) {
82265 $this->prefixesPsr0[$first][$prefix] = array_merge(
82266 (array) $paths,
82267 $this->prefixesPsr0[$first][$prefix]
82268 );
82269 } else {
82270 $this->prefixesPsr0[$first][$prefix] = array_merge(
82271 $this->prefixesPsr0[$first][$prefix],
82272 (array) $paths
82273 );
82274 }
82275 }
82276
82277
82278
82279
82280
82281
82282
82283
82284
82285
82286
82287 public function addPsr4($prefix, $paths, $prepend = false)
82288 {
82289 if (!$prefix) {
82290
82291  if ($prepend) {
82292 $this->fallbackDirsPsr4 = array_merge(
82293 (array) $paths,
82294 $this->fallbackDirsPsr4
82295 );
82296 } else {
82297 $this->fallbackDirsPsr4 = array_merge(
82298 $this->fallbackDirsPsr4,
82299 (array) $paths
82300 );
82301 }
82302 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
82303
82304  $length = strlen($prefix);
82305 if ('\\' !== $prefix[$length - 1]) {
82306 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
82307 }
82308 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
82309 $this->prefixDirsPsr4[$prefix] = (array) $paths;
82310 } elseif ($prepend) {
82311
82312  $this->prefixDirsPsr4[$prefix] = array_merge(
82313 (array) $paths,
82314 $this->prefixDirsPsr4[$prefix]
82315 );
82316 } else {
82317
82318  $this->prefixDirsPsr4[$prefix] = array_merge(
82319 $this->prefixDirsPsr4[$prefix],
82320 (array) $paths
82321 );
82322 }
82323 }
82324
82325
82326
82327
82328
82329
82330
82331
82332 public function set($prefix, $paths)
82333 {
82334 if (!$prefix) {
82335 $this->fallbackDirsPsr0 = (array) $paths;
82336 } else {
82337 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
82338 }
82339 }
82340
82341
82342
82343
82344
82345
82346
82347
82348
82349
82350 public function setPsr4($prefix, $paths)
82351 {
82352 if (!$prefix) {
82353 $this->fallbackDirsPsr4 = (array) $paths;
82354 } else {
82355 $length = strlen($prefix);
82356 if ('\\' !== $prefix[$length - 1]) {
82357 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
82358 }
82359 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
82360 $this->prefixDirsPsr4[$prefix] = (array) $paths;
82361 }
82362 }
82363
82364
82365
82366
82367
82368
82369 public function setUseIncludePath($useIncludePath)
82370 {
82371 $this->useIncludePath = $useIncludePath;
82372 }
82373
82374
82375
82376
82377
82378
82379
82380 public function getUseIncludePath()
82381 {
82382 return $this->useIncludePath;
82383 }
82384
82385
82386
82387
82388
82389
82390
82391 public function setClassMapAuthoritative($classMapAuthoritative)
82392 {
82393 $this->classMapAuthoritative = $classMapAuthoritative;
82394 }
82395
82396
82397
82398
82399
82400
82401 public function isClassMapAuthoritative()
82402 {
82403 return $this->classMapAuthoritative;
82404 }
82405
82406
82407
82408
82409
82410
82411 public function setApcuPrefix($apcuPrefix)
82412 {
82413 $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
82414 }
82415
82416
82417
82418
82419
82420
82421 public function getApcuPrefix()
82422 {
82423 return $this->apcuPrefix;
82424 }
82425
82426
82427
82428
82429
82430
82431 public function register($prepend = false)
82432 {
82433 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
82434 }
82435
82436
82437
82438
82439 public function unregister()
82440 {
82441 spl_autoload_unregister(array($this, 'loadClass'));
82442 }
82443
82444
82445
82446
82447
82448
82449
82450 public function loadClass($class)
82451 {
82452 if ($file = $this->findFile($class)) {
82453 includeFile($file);
82454
82455 return true;
82456 }
82457 }
82458
82459
82460
82461
82462
82463
82464
82465
82466 public function findFile($class)
82467 {
82468
82469  if (isset($this->classMap[$class])) {
82470 return $this->classMap[$class];
82471 }
82472 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
82473 return false;
82474 }
82475 if (null !== $this->apcuPrefix) {
82476 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
82477 if ($hit) {
82478 return $file;
82479 }
82480 }
82481
82482 $file = $this->findFileWithExtension($class, '.php');
82483
82484
82485  if (false === $file && defined('HHVM_VERSION')) {
82486 $file = $this->findFileWithExtension($class, '.hh');
82487 }
82488
82489 if (null !== $this->apcuPrefix) {
82490 apcu_add($this->apcuPrefix.$class, $file);
82491 }
82492
82493 if (false === $file) {
82494
82495  $this->missingClasses[$class] = true;
82496 }
82497
82498 return $file;
82499 }
82500
82501 private function findFileWithExtension($class, $ext)
82502 {
82503
82504  $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
82505
82506 $first = $class[0];
82507 if (isset($this->prefixLengthsPsr4[$first])) {
82508 $subPath = $class;
82509 while (false !== $lastPos = strrpos($subPath, '\\')) {
82510 $subPath = substr($subPath, 0, $lastPos);
82511 $search = $subPath.'\\';
82512 if (isset($this->prefixDirsPsr4[$search])) {
82513 foreach ($this->prefixDirsPsr4[$search] as $dir) {
82514 $length = $this->prefixLengthsPsr4[$first][$search];
82515 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
82516 return $file;
82517 }
82518 }
82519 }
82520 }
82521 }
82522
82523
82524  foreach ($this->fallbackDirsPsr4 as $dir) {
82525 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
82526 return $file;
82527 }
82528 }
82529
82530
82531  if (false !== $pos = strrpos($class, '\\')) {
82532
82533  $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
82534 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
82535 } else {
82536
82537  $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
82538 }
82539
82540 if (isset($this->prefixesPsr0[$first])) {
82541 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
82542 if (0 === strpos($class, $prefix)) {
82543 foreach ($dirs as $dir) {
82544 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
82545 return $file;
82546 }
82547 }
82548 }
82549 }
82550 }
82551
82552
82553  foreach ($this->fallbackDirsPsr0 as $dir) {
82554 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
82555 return $file;
82556 }
82557 }
82558
82559
82560  if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
82561 return $file;
82562 }
82563
82564 return false;
82565 }
82566 }
82567
82568
82569
82570
82571
82572
82573 function includeFile($file)
82574 {
82575 include $file;
82576 }
82577 ##
82578 ## Bundle of CA Root Certificates
82579 ##
82580 ## Certificate data from Mozilla as of: Wed Jan 18 04:12:05 2017 GMT
82581 ##
82582 ## This is a bundle of X.509 certificates of public Certificate Authorities
82583 ## (CA). These were automatically extracted from Mozilla's root certificates
82584 ## file (certdata.txt).  This file can be found in the mozilla source tree:
82585 ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
82586 ##
82587 ## It contains the certificates in PEM format and therefore
82588 ## can be directly used with curl / libcurl / php_curl, or with
82589 ## an Apache+mod_ssl webserver for SSL client authentication.
82590 ## Just configure this file as the SSLCACertificateFile.
82591 ##
82592 ## Conversion done with mk-ca-bundle.pl version 1.27.
82593 ## SHA256: dffa79e6aa993f558e82884abf7bb54bf440ab66ee91d82a27a627f6f2a4ace4
82594 ##
82595
82596
82597 GlobalSign Root CA
82598 ==================
82599 -----BEGIN CERTIFICATE-----
82600 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
82601 GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
82602 b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
82603 BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
82604 VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
82605 DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
82606 THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
82607 Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
82608 c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
82609 gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
82610 HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
82611 AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
82612 Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
82613 j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
82614 hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
82615 X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
82616 -----END CERTIFICATE-----
82617
82618 GlobalSign Root CA - R2
82619 =======================
82620 -----BEGIN CERTIFICATE-----
82621 MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
82622 YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
82623 bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
82624 aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
82625 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
82626 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
82627 s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
82628 S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
82629 TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
82630 ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
82631 FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
82632 YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
82633 BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
82634 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
82635 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
82636 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
82637 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
82638 -----END CERTIFICATE-----
82639
82640 Verisign Class 3 Public Primary Certification Authority - G3
82641 ============================================================
82642 -----BEGIN CERTIFICATE-----
82643 MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
82644 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
82645 cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
82646 IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
82647 dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
82648 CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
82649 dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
82650 cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
82651 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
82652 ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
82653 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
82654 cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
82655 EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
82656 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
82657 ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
82658 j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
82659 /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
82660 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
82661 t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
82662 -----END CERTIFICATE-----
82663
82664 Entrust.net Premium 2048 Secure Server CA
82665 =========================================
82666 -----BEGIN CERTIFICATE-----
82667 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
82668 ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
82669 bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
82670 BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
82671 NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
82672 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
82673 MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
82674 ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
82675 MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
82676 Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
82677 hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
82678 nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
82679 VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
82680 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
82681 KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
82682 T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
82683 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
82684 J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
82685 nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
82686 -----END CERTIFICATE-----
82687
82688 Baltimore CyberTrust Root
82689 =========================
82690 -----BEGIN CERTIFICATE-----
82691 MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
82692 ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
82693 ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
82694 SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
82695 dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
82696 uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
82697 UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
82698 G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
82699 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
82700 l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
82701 VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
82702 BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
82703 cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
82704 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
82705 Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
82706 RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
82707 -----END CERTIFICATE-----
82708
82709 AddTrust Low-Value Services Root
82710 ================================
82711 -----BEGIN CERTIFICATE-----
82712 MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82713 QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU
82714 cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw
82715 CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO
82716 ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB
82717 AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6
82718 54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr
82719 oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1
82720 Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui
82721 GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w
82722 HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD
82723 AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT
82724 RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw
82725 HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt
82726 ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph
82727 iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
82728 eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr
82729 mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj
82730 ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
82731 -----END CERTIFICATE-----
82732
82733 AddTrust External Root
82734 ======================
82735 -----BEGIN CERTIFICATE-----
82736 MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82737 QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
82738 VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
82739 NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
82740 cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
82741 Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
82742 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
82743 Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
82744 aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
82745 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
82746 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
82747 BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
82748 VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
82749 VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
82750 IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
82751 j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
82752 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
82753 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
82754 G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
82755 -----END CERTIFICATE-----
82756
82757 AddTrust Public Services Root
82758 =============================
82759 -----BEGIN CERTIFICATE-----
82760 MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82761 QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU
82762 cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ
82763 BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l
82764 dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF
82765 AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu
82766 nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i
82767 d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG
82768 Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw
82769 HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G
82770 A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
82771 /zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux
82772 FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G
82773 A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4
82774 JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL
82775 +YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
82776 GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9
82777 Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H
82778 EufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
82779 -----END CERTIFICATE-----
82780
82781 AddTrust Qualified Certificates Root
82782 ====================================
82783 -----BEGIN CERTIFICATE-----
82784 MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82785 QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU
82786 cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx
82787 CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ
82788 IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG
82789 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx
82790 64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3
82791 KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o
82792 L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR
82793 wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU
82794 MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/
82795 BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE
82796 BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y
82797 azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD
82798 ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG
82799 GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
82800 dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze
82801 RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB
82802 iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE=
82803 -----END CERTIFICATE-----
82804
82805 Entrust Root Certification Authority
82806 ====================================
82807 -----BEGIN CERTIFICATE-----
82808 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
82809 BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
82810 b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
82811 A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
82812 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
82813 MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
82814 Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
82815 dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
82816 ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
82817 A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
82818 Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
82819 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
82820 rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
82821 DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
82822 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
82823 hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
82824 A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
82825 Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
82826 v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
82827 W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
82828 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
82829 -----END CERTIFICATE-----
82830
82831 GeoTrust Global CA
82832 ==================
82833 -----BEGIN CERTIFICATE-----
82834 MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
82835 Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
82836 MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
82837 LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
82838 CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
82839 BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
82840 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
82841 T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
82842 vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
82843 AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
82844 DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
82845 zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
82846 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
82847 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
82848 XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
82849 Mw==
82850 -----END CERTIFICATE-----
82851
82852 GeoTrust Global CA 2
82853 ====================
82854 -----BEGIN CERTIFICATE-----
82855 MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
82856 R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw
82857 MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
82858 LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
82859 ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/
82860 NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k
82861 LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA
82862 Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b
82863 HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF
82864 MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH
82865 K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7
82866 srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh
82867 ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL
82868 OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC
82869 x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF
82870 H4z1Ir+rzoPz4iIprn2DQKi6bA==
82871 -----END CERTIFICATE-----
82872
82873 GeoTrust Universal CA
82874 =====================
82875 -----BEGIN CERTIFICATE-----
82876 MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
82877 R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
82878 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
82879 Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
82880 ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
82881 JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
82882 RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
82883 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
82884 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
82885 qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
82886 Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
82887 Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
82888 KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
82889 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
82890 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
82891 hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
82892 aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
82893 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
82894 oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
82895 xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
82896 KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
82897 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
82898 xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
82899 p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
82900 P/rmMuGNG2+k5o7Y+SlIis5z/iw=
82901 -----END CERTIFICATE-----
82902
82903 GeoTrust Universal CA 2
82904 =======================
82905 -----BEGIN CERTIFICATE-----
82906 MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
82907 R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
82908 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
82909 SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
82910 A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
82911 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
82912 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
82913 JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
82914 QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
82915 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
82916 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
82917 ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
82918 SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
82919 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
82920 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
82921 BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
82922 dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
82923 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
82924 mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
82925 A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
82926 Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
82927 pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
82928 FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
82929 gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
82930 X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
82931 -----END CERTIFICATE-----
82932
82933 Visa eCommerce Root
82934 ===================
82935 -----BEGIN CERTIFICATE-----
82936 MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
82937 EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
82938 QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
82939 WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
82940 VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
82941 bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
82942 F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
82943 RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
82944 TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
82945 /k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
82946 GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
82947 MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
82948 CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
82949 YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
82950 zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
82951 YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
82952 398znM/jra6O1I7mT1GvFpLgXPYHDw==
82953 -----END CERTIFICATE-----
82954
82955 Certum Root CA
82956 ==============
82957 -----BEGIN CERTIFICATE-----
82958 MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK
82959 ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla
82960 Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u
82961 by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x
82962 wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL
82963 kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ
82964 89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K
82965 Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P
82966 NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq
82967 hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+
82968 GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg
82969 GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/
82970 0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS
82971 qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw==
82972 -----END CERTIFICATE-----
82973
82974 Comodo AAA Services root
82975 ========================
82976 -----BEGIN CERTIFICATE-----
82977 MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
82978 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
82979 TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
82980 MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
82981 c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
82982 BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
82983 ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
82984 C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
82985 i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
82986 Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
82987 Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
82988 Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
82989 BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
82990 cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
82991 LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
82992 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
82993 Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
82994 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
82995 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
82996 -----END CERTIFICATE-----
82997
82998 Comodo Secure Services root
82999 ===========================
83000 -----BEGIN CERTIFICATE-----
83001 MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
83002 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
83003 TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw
83004 MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu
83005 Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi
83006 BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
83007 ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP
83008 9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc
83009 rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC
83010 oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V
83011 p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E
83012 FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
83013 gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj
83014 YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm
83015 aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm
83016 4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
83017 Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL
83018 DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw
83019 pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H
83020 RR3B7Hzs/Sk=
83021 -----END CERTIFICATE-----
83022
83023 Comodo Trusted Services root
83024 ============================
83025 -----BEGIN CERTIFICATE-----
83026 MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
83027 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
83028 TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw
83029 MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h
83030 bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw
83031 IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC
83032 AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7
83033 3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y
83034 /9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6
83035 juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS
83036 ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud
83037 DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
83038 /zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp
83039 ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl
83040 cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw
83041 uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
83042 pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA
83043 BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l
83044 R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O
83045 9y5Xt5hwXsjEeLBi
83046 -----END CERTIFICATE-----
83047
83048 QuoVadis Root CA
83049 ================
83050 -----BEGIN CERTIFICATE-----
83051 MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
83052 ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
83053 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
83054 MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
83055 cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
83056 EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
83057 AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
83058 J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
83059 F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
83060 YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
83061 AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
83062 PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
83063 ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
83064 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
83065 YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
83066 ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
83067 Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
83068 Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
83069 BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
83070 FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
83071 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
83072 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
83073 fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
83074 LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
83075 gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
83076 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
83077 5nrQNiOKSnQ2+Q==
83078 -----END CERTIFICATE-----
83079
83080 QuoVadis Root CA 2
83081 ==================
83082 -----BEGIN CERTIFICATE-----
83083 MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
83084 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
83085 ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
83086 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
83087 DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
83088 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
83089 lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
83090 lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
83091 lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
83092 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
83093 wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
83094 D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
83095 BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
83096 J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
83097 DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
83098 a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
83099 ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
83100 Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
83101 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
83102 VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
83103 +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
83104 IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
83105 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
83106 f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
83107 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
83108 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
83109 -----END CERTIFICATE-----
83110
83111 QuoVadis Root CA 3
83112 ==================
83113 -----BEGIN CERTIFICATE-----
83114 MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
83115 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
83116 OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
83117 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
83118 DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
83119 DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
83120 KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
83121 DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
83122 BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
83123 p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
83124 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
83125 MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
83126 Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
83127 uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
83128 BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
83129 YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
83130 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
83131 BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
83132 VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
83133 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
83134 AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
83135 qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
83136 hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
83137 POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
83138 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
83139 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
83140 bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
83141 g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
83142 vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
83143 qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
83144 -----END CERTIFICATE-----
83145
83146 Security Communication Root CA
83147 ==============================
83148 -----BEGIN CERTIFICATE-----
83149 MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
83150 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
83151 HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
83152 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
83153 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
83154 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
83155 DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
83156 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
83157 DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
83158 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
83159 DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
83160 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
83161 mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
83162 s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
83163 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
83164 FL39vmwLAw==
83165 -----END CERTIFICATE-----
83166
83167 Sonera Class 2 Root CA
83168 ======================
83169 -----BEGIN CERTIFICATE-----
83170 MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
83171 U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
83172 NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
83173 IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
83174 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
83175 dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
83176 f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
83177 tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
83178 nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
83179 XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
83180 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
83181 cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
83182 Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
83183 EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
83184 llpwrN9M
83185 -----END CERTIFICATE-----
83186
83187 UTN USERFirst Hardware Root CA
83188 ==============================
83189 -----BEGIN CERTIFICATE-----
83190 MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE
83191 BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
83192 IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd
83193 BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx
83194 OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0
83195 eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz
83196 ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3
83197 DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI
83198 wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd
83199 tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8
83200 i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf
83201 Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw
83202 gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF
83203 lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF
83204 UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF
83205 BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
83206 //bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW
83207 XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2
83208 lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn
83209 iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67
83210 nfhmqA==
83211 -----END CERTIFICATE-----
83212
83213 Camerfirma Chambers of Commerce Root
83214 ====================================
83215 -----BEGIN CERTIFICATE-----
83216 MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
83217 QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
83218 ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx
83219 NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp
83220 cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn
83221 MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC
83222 AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU
83223 xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH
83224 NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW
83225 DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV
83226 d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud
83227 EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v
83228 cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P
83229 AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh
83230 bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD
83231 VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
83232 aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi
83233 fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD
83234 L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN
83235 UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n
83236 ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1
83237 erfutGWaIZDgqtCYvDi1czyL+Nw=
83238 -----END CERTIFICATE-----
83239
83240 Camerfirma Global Chambersign Root
83241 ==================================
83242 -----BEGIN CERTIFICATE-----
83243 MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
83244 QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
83245 ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx
83246 NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
83247 YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg
83248 MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw
83249 ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J
83250 1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O
83251 by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl
83252 6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c
83253 8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/
83254 BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j
83255 aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B
83256 Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj
83257 aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y
83258 ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
83259 bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA
83260 PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y
83261 gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ
83262 PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4
83263 IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes
83264 t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
83265 -----END CERTIFICATE-----
83266
83267 XRamp Global CA Root
83268 ====================
83269 -----BEGIN CERTIFICATE-----
83270 MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
83271 BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
83272 dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
83273 dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
83274 HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
83275 U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
83276 dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
83277 IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
83278 foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
83279 zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
83280 AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
83281 xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
83282 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
83283 oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
83284 AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
83285 /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
83286 qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
83287 nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
83288 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
83289 -----END CERTIFICATE-----
83290
83291 Go Daddy Class 2 CA
83292 ===================
83293 -----BEGIN CERTIFICATE-----
83294 MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
83295 VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
83296 ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
83297 A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
83298 RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
83299 ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
83300 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
83301 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
83302 YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
83303 vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
83304 BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
83305 atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
83306 MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
83307 A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
83308 PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
83309 I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
83310 HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
83311 Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
83312 vZ8=
83313 -----END CERTIFICATE-----
83314
83315 Starfield Class 2 CA
83316 ====================
83317 -----BEGIN CERTIFICATE-----
83318 MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
83319 U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
83320 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
83321 MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
83322 A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
83323 SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
83324 bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
83325 JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
83326 epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
83327 F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
83328 MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
83329 hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
83330 bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
83331 QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
83332 afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
83333 PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
83334 xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
83335 KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
83336 QBFGmh95DmK/D5fs4C8fF5Q=
83337 -----END CERTIFICATE-----
83338
83339 StartCom Certification Authority
83340 ================================
83341 -----BEGIN CERTIFICATE-----
83342 MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
83343 U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
83344 ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
83345 NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
83346 LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
83347 U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
83348 ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
83349 o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
83350 Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
83351 eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
83352 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
83353 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
83354 osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
83355 untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
83356 UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
83357 37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
83358 FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0
83359 Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj
83360 YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH
83361 AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw
83362 Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg
83363 U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5
83364 LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl
83365 cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh
83366 cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT
83367 dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC
83368 AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh
83369 3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm
83370 vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk
83371 fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3
83372 fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ
83373 EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
83374 yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl
83375 1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/
83376 lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro
83377 g14=
83378 -----END CERTIFICATE-----
83379
83380 Taiwan GRCA
83381 ===========
83382 -----BEGIN CERTIFICATE-----
83383 MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
83384 EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
83385 DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
83386 dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
83387 ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
83388 w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
83389 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
83390 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
83391 htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
83392 J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
83393 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
83394 B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
83395 O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
83396 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
83397 HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
83398 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
83399 TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
83400 Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
83401 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
83402 D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
83403 DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
83404 Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
83405 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
83406 CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
83407 +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
83408 -----END CERTIFICATE-----
83409
83410 Swisscom Root CA 1
83411 ==================
83412 -----BEGIN CERTIFICATE-----
83413 MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG
83414 EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
83415 dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4
83416 MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
83417 aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC
83418 IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM
83419 MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF
83420 NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe
83421 AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC
83422 b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn
83423 7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN
83424 cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp
83425 WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5
83426 haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY
83427 MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
83428 HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j
83429 BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9
83430 MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn
83431 jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ
83432 MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H
83433 VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl
83434 vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl
83435 OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3
83436 1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq
83437 nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy
83438 x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW
83439 NY6E0F/6MBr1mmz0DlP5OlvRHA==
83440 -----END CERTIFICATE-----
83441
83442 DigiCert Assured ID Root CA
83443 ===========================
83444 -----BEGIN CERTIFICATE-----
83445 MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
83446 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
83447 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
83448 MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
83449 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
83450 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
83451 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
83452 UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
83453 /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
83454 oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
83455 GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
83456 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
83457 hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
83458 EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
83459 SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
83460 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
83461 +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
83462 -----END CERTIFICATE-----
83463
83464 DigiCert Global Root CA
83465 =======================
83466 -----BEGIN CERTIFICATE-----
83467 MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
83468 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
83469 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
83470 MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
83471 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
83472 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
83473 TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
83474 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
83475 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
83476 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
83477 o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
83478 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
83479 BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
83480 EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
83481 tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
83482 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
83483 CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
83484 -----END CERTIFICATE-----
83485
83486 DigiCert High Assurance EV Root CA
83487 ==================================
83488 -----BEGIN CERTIFICATE-----
83489 MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
83490 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
83491 KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
83492 MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
83493 MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
83494 Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
83495 Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
83496 OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
83497 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
83498 NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
83499 h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
83500 Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
83501 JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
83502 V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
83503 myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
83504 mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
83505 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
83506 -----END CERTIFICATE-----
83507
83508 Certplus Class 2 Primary CA
83509 ===========================
83510 -----BEGIN CERTIFICATE-----
83511 MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
83512 BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
83513 OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
83514 dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
83515 ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
83516 5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
83517 Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
83518 YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
83519 e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
83520 CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
83521 YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
83522 L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
83523 P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
83524 TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
83525 7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
83526 //1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
83527 l7+ijrRU
83528 -----END CERTIFICATE-----
83529
83530 DST Root CA X3
83531 ==============
83532 -----BEGIN CERTIFICATE-----
83533 MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
83534 ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
83535 DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
83536 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
83537 ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
83538 rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
83539 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
83540 xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
83541 utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
83542 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
83543 MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
83544 dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
83545 GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
83546 RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
83547 fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
83548 -----END CERTIFICATE-----
83549
83550 DST ACES CA X6
83551 ==============
83552 -----BEGIN CERTIFICATE-----
83553 MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG
83554 EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT
83555 MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha
83556 MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE
83557 CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC
83558 AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI
83559 DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa
83560 pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow
83561 GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy
83562 MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud
83563 EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu
83564 Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy
83565 dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU
83566 CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2
83567 5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t
83568 Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
83569 nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs
83570 vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3
83571 oKfN5XozNmr6mis=
83572 -----END CERTIFICATE-----
83573
83574 SwissSign Gold CA - G2
83575 ======================
83576 -----BEGIN CERTIFICATE-----
83577 MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
83578 EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
83579 MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
83580 c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
83581 AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
83582 t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
83583 jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
83584 vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
83585 ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
83586 AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
83587 jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
83588 peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
83589 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
83590 GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
83591 AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
83592 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
83593 L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
83594 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
83595 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
83596 Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
83597 Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
83598 mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
83599 vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
83600 KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
83601 NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
83602 viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
83603 -----END CERTIFICATE-----
83604
83605 SwissSign Silver CA - G2
83606 ========================
83607 -----BEGIN CERTIFICATE-----
83608 MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
83609 BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
83610 DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
83611 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
83612 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
83613 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
83614 +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
83615 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
83616 MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
83617 qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
83618 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
83619 ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
83620 celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
83621 CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
83622 BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
83623 tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
83624 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
83625 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
83626 kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
83627 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
83628 /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
83629 DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
83630 e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
83631 WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
83632 DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
83633 DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
83634 -----END CERTIFICATE-----
83635
83636 GeoTrust Primary Certification Authority
83637 ========================================
83638 -----BEGIN CERTIFICATE-----
83639 MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
83640 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
83641 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
83642 CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
83643 cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
83644 CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
83645 b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
83646 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
83647 RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
83648 tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
83649 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
83650 hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
83651 Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
83652 NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
83653 Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
83654 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
83655 -----END CERTIFICATE-----
83656
83657 thawte Primary Root CA
83658 ======================
83659 -----BEGIN CERTIFICATE-----
83660 MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
83661 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
83662 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
83663 cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
83664 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
83665 SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
83666 KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
83667 FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
83668 oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
83669 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
83670 q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
83671 aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
83672 afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
83673 VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
83674 AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
83675 uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
83676 xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
83677 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
83678 z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
83679 -----END CERTIFICATE-----
83680
83681 VeriSign Class 3 Public Primary Certification Authority - G5
83682 ============================================================
83683 -----BEGIN CERTIFICATE-----
83684 MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
83685 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
83686 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
83687 IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
83688 ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
83689 yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
83690 biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
83691 dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
83692 YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
83693 ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
83694 j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
83695 Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
83696 Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
83697 fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
83698 BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
83699 Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
83700 aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
83701 SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
83702 X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
83703 KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
83704 Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
83705 ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
83706 -----END CERTIFICATE-----
83707
83708 SecureTrust CA
83709 ==============
83710 -----BEGIN CERTIFICATE-----
83711 MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
83712 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
83713 dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
83714 BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
83715 ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
83716 OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
83717 DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
83718 GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
83719 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
83720 ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
83721 BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
83722 aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
83723 KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
83724 SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
83725 mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
83726 nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
83727 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
83728 -----END CERTIFICATE-----
83729
83730 Secure Global CA
83731 ================
83732 -----BEGIN CERTIFICATE-----
83733 MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
83734 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
83735 bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
83736 MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
83737 Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
83738 YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
83739 bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
83740 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
83741 HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
83742 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
83743 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
83744 oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
83745 MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
83746 OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
83747 CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
83748 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
83749 f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
83750 -----END CERTIFICATE-----
83751
83752 COMODO Certification Authority
83753 ==============================
83754 -----BEGIN CERTIFICATE-----
83755 MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
83756 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
83757 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
83758 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
83759 MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
83760 T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
83761 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
83762 +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
83763 xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
83764 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
83765 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
83766 rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
83767 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
83768 b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
83769 AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
83770 OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
83771 RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
83772 IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
83773 +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
83774 -----END CERTIFICATE-----
83775
83776 Network Solutions Certificate Authority
83777 =======================================
83778 -----BEGIN CERTIFICATE-----
83779 MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
83780 EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
83781 IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
83782 MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
83783 MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
83784 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
83785 jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
83786 aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
83787 crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
83788 /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
83789 AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
83790 BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
83791 bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
83792 A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
83793 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
83794 GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
83795 wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
83796 ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
83797 -----END CERTIFICATE-----
83798
83799 WellsSecure Public Root Certificate Authority
83800 =============================================
83801 -----BEGIN CERTIFICATE-----
83802 MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM
83803 F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw
83804 NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN
83805 MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl
83806 bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD
83807 VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
83808 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1
83809 iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13
83810 i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8
83811 bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB
83812 K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB
83813 AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu
83814 cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm
83815 lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB
83816 i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww
83817 GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg
83818 Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI
83819 K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0
83820 bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj
83821 qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es
83822 E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ
83823 tylv2G0xffX8oRAHh84vWdw+WNs=
83824 -----END CERTIFICATE-----
83825
83826 COMODO ECC Certification Authority
83827 ==================================
83828 -----BEGIN CERTIFICATE-----
83829 MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
83830 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
83831 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
83832 dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
83833 GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
83834 Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
83835 b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
83836 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
83837 wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
83838 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
83839 FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
83840 U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
83841 -----END CERTIFICATE-----
83842
83843 Security Communication EV RootCA1
83844 =================================
83845 -----BEGIN CERTIFICATE-----
83846 MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
83847 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh
83848 dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE
83849 BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl
83850 Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
83851 AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO
83852 /VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX
83853 WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z
83854 ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4
83855 bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK
83856 9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
83857 SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm
83858 iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG
83859 Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW
83860 mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW
83861 T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
83862 -----END CERTIFICATE-----
83863
83864 OISTE WISeKey Global Root GA CA
83865 ===============================
83866 -----BEGIN CERTIFICATE-----
83867 MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
83868 BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
83869 A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
83870 bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
83871 VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
83872 IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
83873 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
83874 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
83875 Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
83876 d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
83877 /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
83878 LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
83879 AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
83880 KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
83881 MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
83882 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
83883 hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
83884 okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
83885 -----END CERTIFICATE-----
83886
83887 Microsec e-Szigno Root CA
83888 =========================
83889 -----BEGIN CERTIFICATE-----
83890 MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE
83891 BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL
83892 EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0
83893 MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz
83894 dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT
83895 GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
83896 AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG
83897 d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N
83898 oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc
83899 QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ
83900 PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb
83901 MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG
83902 IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD
83903 VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3
83904 LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A
83905 dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn
83906 AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA
83907 4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg
83908 AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA
83909 egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6
83910 Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO
83911 PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv
83912 c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h
83913 cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw
83914 IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT
83915 WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV
83916 MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER
83917 MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp
83918 Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal
83919 HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT
83920 nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE
83921 aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a
83922 86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK
83923 yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB
83924 S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU=
83925 -----END CERTIFICATE-----
83926
83927 Certigna
83928 ========
83929 -----BEGIN CERTIFICATE-----
83930 MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
83931 EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
83932 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
83933 Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
83934 XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
83935 GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
83936 ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
83937 DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
83938 Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
83939 tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
83940 BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
83941 SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
83942 hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
83943 ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
83944 PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
83945 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
83946 WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
83947 -----END CERTIFICATE-----
83948
83949 Deutsche Telekom Root CA 2
83950 ==========================
83951 -----BEGIN CERTIFICATE-----
83952 MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
83953 RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
83954 A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
83955 MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
83956 A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
83957 b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
83958 bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
83959 KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
83960 AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
83961 Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
83962 jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
83963 HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
83964 E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
83965 zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
83966 rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
83967 dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
83968 Cm26OWMohpLzGITY+9HPBVZkVw==
83969 -----END CERTIFICATE-----
83970
83971 Cybertrust Global Root
83972 ======================
83973 -----BEGIN CERTIFICATE-----
83974 MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
83975 ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
83976 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
83977 ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
83978 +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
83979 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
83980 AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
83981 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
83982 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
83983 BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
83984 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
83985 A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
83986 lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
83987 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
83988 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
83989 X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
83990 WL1WMRJOEcgh4LMRkWXbtKaIOM5V
83991 -----END CERTIFICATE-----
83992
83993 ePKI Root Certification Authority
83994 =================================
83995 -----BEGIN CERTIFICATE-----
83996 MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
83997 EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
83998 Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
83999 MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
84000 MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
84001 AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
84002 IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
84003 lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
84004 qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
84005 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
84006 WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
84007 ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
84008 lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
84009 vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
84010 Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
84011 MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
84012 ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
84013 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
84014 KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
84015 xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
84016 NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
84017 GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
84018 xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
84019 gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
84020 sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
84021 BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
84022 -----END CERTIFICATE-----
84023
84024 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
84025 =============================================================================================================================
84026 -----BEGIN CERTIFICATE-----
84027 MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH
84028 DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q
84029 aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry
84030 b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV
84031 BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg
84032 S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4
84033 MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl
84034 IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF
84035 n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl
84036 IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft
84037 dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl
84038 cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B
84039 AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO
84040 Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1
84041 xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR
84042 6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
84043 hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd
84044 BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
84045 MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4
84046 N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT
84047 y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh
84048 LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M
84049 dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI=
84050 -----END CERTIFICATE-----
84051
84052 certSIGN ROOT CA
84053 ================
84054 -----BEGIN CERTIFICATE-----
84055 MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
84056 VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
84057 Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
84058 CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
84059 JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
84060 rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
84061 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
84062 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
84063 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
84064 Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
84065 AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
84066 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
84067 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
84068 vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
84069 TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
84070 -----END CERTIFICATE-----
84071
84072 CNNIC ROOT
84073 ==========
84074 -----BEGIN CERTIFICATE-----
84075 MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE
84076 ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw
84077 OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw
84078 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD
84079 o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz
84080 VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT
84081 VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or
84082 czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK
84083 y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC
84084 wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S
84085 lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5
84086 Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM
84087 O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8
84088 BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2
84089 G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m
84090 mxE=
84091 -----END CERTIFICATE-----
84092
84093 ApplicationCA - Japanese Government
84094 ===================================
84095 -----BEGIN CERTIFICATE-----
84096 MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT
84097 SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw
84098 MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl
84099 cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
84100 CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4
84101 fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN
84102 wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE
84103 jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu
84104 nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU
84105 WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV
84106 BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD
84107 vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs
84108 o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g
84109 /DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD
84110 io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW
84111 dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL
84112 rosot4LKGAfmt1t06SAZf7IbiVQ=
84113 -----END CERTIFICATE-----
84114
84115 GeoTrust Primary Certification Authority - G3
84116 =============================================
84117 -----BEGIN CERTIFICATE-----
84118 MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
84119 BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
84120 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
84121 eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
84122 NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
84123 YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
84124 LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
84125 hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
84126 K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
84127 c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
84128 IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
84129 dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
84130 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
84131 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
84132 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
84133 Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
84134 AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
84135 t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
84136 -----END CERTIFICATE-----
84137
84138 thawte Primary Root CA - G2
84139 ===========================
84140 -----BEGIN CERTIFICATE-----
84141 MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
84142 VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
84143 IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
84144 Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
84145 MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
84146 b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
84147 IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
84148 LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
84149 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
84150 mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
84151 G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
84152 rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
84153 -----END CERTIFICATE-----
84154
84155 thawte Primary Root CA - G3
84156 ===========================
84157 -----BEGIN CERTIFICATE-----
84158 MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
84159 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
84160 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
84161 cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
84162 ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
84163 d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
84164 VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
84165 A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
84166 MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
84167 P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
84168 +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
84169 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
84170 vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
84171 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
84172 KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
84173 A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
84174 t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
84175 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
84176 er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
84177 -----END CERTIFICATE-----
84178
84179 GeoTrust Primary Certification Authority - G2
84180 =============================================
84181 -----BEGIN CERTIFICATE-----
84182 MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
84183 VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
84184 Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
84185 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
84186 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
84187 MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
84188 b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
84189 BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
84190 KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
84191 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
84192 EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
84193 ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
84194 npaqBA+K
84195 -----END CERTIFICATE-----
84196
84197 VeriSign Universal Root Certification Authority
84198 ===============================================
84199 -----BEGIN CERTIFICATE-----
84200 MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
84201 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
84202 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
84203 IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
84204 IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
84205 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
84206 cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
84207 IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
84208 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
84209 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
84210 MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
84211 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
84212 AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
84213 tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
84214 CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
84215 a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
84216 DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
84217 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
84218 Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
84219 P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
84220 wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
84221 mJO37M2CYfE45k+XmCpajQ==
84222 -----END CERTIFICATE-----
84223
84224 VeriSign Class 3 Public Primary Certification Authority - G4
84225 ============================================================
84226 -----BEGIN CERTIFICATE-----
84227 MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
84228 VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
84229 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
84230 ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
84231 YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
84232 MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
84233 cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
84234 b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
84235 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
84236 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
84237 rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
84238 /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
84239 HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
84240 Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
84241 A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
84242 AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
84243 -----END CERTIFICATE-----
84244
84245 NetLock Arany (Class Gold) Főtanúsítvány
84246 ========================================
84247 -----BEGIN CERTIFICATE-----
84248 MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
84249 A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
84250 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
84251 cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
84252 MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
84253 ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
84254 biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
84255 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
84256 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
84257 /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
84258 H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
84259 fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
84260 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
84261 BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
84262 qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
84263 YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
84264 bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
84265 NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
84266 dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
84267 -----END CERTIFICATE-----
84268
84269 Staat der Nederlanden Root CA - G2
84270 ==================================
84271 -----BEGIN CERTIFICATE-----
84272 MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
84273 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
84274 Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
84275 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
84276 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
84277 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
84278 vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
84279 CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
84280 e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
84281 OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
84282 CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
84283 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
84284 trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
84285 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
84286 AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
84287 ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
84288 HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
84289 A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
84290 +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
84291 f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
84292 kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
84293 CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
84294 URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
84295 CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
84296 oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
84297 IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
84298 66+KAQ==
84299 -----END CERTIFICATE-----
84300
84301 Hongkong Post Root CA 1
84302 =======================
84303 -----BEGIN CERTIFICATE-----
84304 MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
84305 DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
84306 NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
84307 IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
84308 AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
84309 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
84310 auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
84311 qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
84312 V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
84313 HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
84314 h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
84315 l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
84316 IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
84317 T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
84318 c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
84319 -----END CERTIFICATE-----
84320
84321 SecureSign RootCA11
84322 ===================
84323 -----BEGIN CERTIFICATE-----
84324 MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
84325 SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
84326 b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
84327 KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
84328 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
84329 TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
84330 wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
84331 g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
84332 O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
84333 bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
84334 t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
84335 OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
84336 bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
84337 Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
84338 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
84339 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
84340 -----END CERTIFICATE-----
84341
84342 ACEDICOM Root
84343 =============
84344 -----BEGIN CERTIFICATE-----
84345 MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD
84346 T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4
84347 MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG
84348 A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF
84349 AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk
84350 WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD
84351 YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew
84352 MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb
84353 m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk
84354 HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT
84355 xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2
84356 3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9
84357 2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq
84358 TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz
84359 4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU
84360 9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
84361 bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg
84362 aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP
84363 eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk
84364 zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1
84365 ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI
84366 KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq
84367 nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE
84368 I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp
84369 MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o
84370 tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA==
84371 -----END CERTIFICATE-----
84372
84373 Microsec e-Szigno Root CA 2009
84374 ==============================
84375 -----BEGIN CERTIFICATE-----
84376 MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
84377 MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
84378 c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
84379 dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
84380 BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
84381 U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
84382 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
84383 fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
84384 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
84385 pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
84386 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
84387 AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
84388 QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
84389 FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
84390 lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
84391 I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
84392 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
84393 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
84394 LXpUq3DDfSJlgnCW
84395 -----END CERTIFICATE-----
84396
84397 GlobalSign Root CA - R3
84398 =======================
84399 -----BEGIN CERTIFICATE-----
84400 MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
84401 YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
84402 bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
84403 aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
84404 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
84405 iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
84406 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
84407 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
84408 OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
84409 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
84410 FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
84411 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
84412 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
84413 bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
84414 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
84415 kpeDMdmztcpHWD9f
84416 -----END CERTIFICATE-----
84417
84418 Autoridad de Certificacion Firmaprofesional CIF A62634068
84419 =========================================================
84420 -----BEGIN CERTIFICATE-----
84421 MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
84422 BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
84423 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
84424 QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
84425 NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
84426 Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
84427 B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
84428 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
84429 ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
84430 plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
84431 MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
84432 LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
84433 bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
84434 vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
84435 EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
84436 DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
84437 cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
84438 bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
84439 ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
84440 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
84441 R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
84442 T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
84443 Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
84444 osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
84445 crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
84446 saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
84447 KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
84448 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
84449 -----END CERTIFICATE-----
84450
84451 Izenpe.com
84452 ==========
84453 -----BEGIN CERTIFICATE-----
84454 MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
84455 EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
84456 MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
84457 QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
84458 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
84459 ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
84460 +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
84461 PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
84462 OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
84463 F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
84464 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
84465 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
84466 leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
84467 AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
84468 SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
84469 NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
84470 MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
84471 BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
84472 Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
84473 kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
84474 hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
84475 g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
84476 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
84477 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
84478 ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
84479 Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
84480 WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
84481 -----END CERTIFICATE-----
84482
84483 Chambers of Commerce Root - 2008
84484 ================================
84485 -----BEGIN CERTIFICATE-----
84486 MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
84487 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
84488 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
84489 QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
84490 Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
84491 ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
84492 EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
84493 cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
84494 AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
84495 XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
84496 h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
84497 ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
84498 NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
84499 D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
84500 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
84501 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
84502 ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
84503 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
84504 G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
84505 BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
84506 bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
84507 bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
84508 CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
84509 AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
84510 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
84511 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
84512 RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
84513 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
84514 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
84515 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
84516 zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
84517 nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
84518 OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
84519 -----END CERTIFICATE-----
84520
84521 Global Chambersign Root - 2008
84522 ==============================
84523 -----BEGIN CERTIFICATE-----
84524 MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
84525 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
84526 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
84527 QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
84528 NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
84529 Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
84530 QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
84531 aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
84532 VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
84533 XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
84534 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
84535 /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
84536 TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
84537 H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
84538 Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
84539 HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
84540 wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
84541 AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
84542 BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
84543 BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
84544 aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
84545 aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
84546 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
84547 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
84548 /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
84549 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
84550 dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
84551 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
84552 foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
84553 qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
84554 P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
84555 c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
84556 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
84557 -----END CERTIFICATE-----
84558
84559 Go Daddy Root Certificate Authority - G2
84560 ========================================
84561 -----BEGIN CERTIFICATE-----
84562 MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
84563 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
84564 MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
84565 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
84566 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
84567 A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
84568 hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
84569 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
84570 +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
84571 fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
84572 NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
84573 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
84574 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
84575 vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
84576 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
84577 N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
84578 LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
84579 -----END CERTIFICATE-----
84580
84581 Starfield Root Certificate Authority - G2
84582 =========================================
84583 -----BEGIN CERTIFICATE-----
84584 MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
84585 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
84586 b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
84587 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
84588 DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
84589 VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
84590 dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
84591 W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
84592 bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
84593 N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
84594 ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
84595 JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
84596 AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
84597 TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
84598 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
84599 F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
84600 pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
84601 c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
84602 -----END CERTIFICATE-----
84603
84604 Starfield Services Root Certificate Authority - G2
84605 ==================================================
84606 -----BEGIN CERTIFICATE-----
84607 MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
84608 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
84609 b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
84610 IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
84611 BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
84612 dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
84613 Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
84614 AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
84615 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
84616 hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
84617 LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
84618 rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
84619 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
84620 SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
84621 E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
84622 xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
84623 iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
84624 YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
84625 -----END CERTIFICATE-----
84626
84627 AffirmTrust Commercial
84628 ======================
84629 -----BEGIN CERTIFICATE-----
84630 MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
84631 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
84632 MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
84633 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
84634 AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
84635 DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
84636 C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
84637 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
84638 MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
84639 HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
84640 AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
84641 hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
84642 qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
84643 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
84644 sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
84645 -----END CERTIFICATE-----
84646
84647 AffirmTrust Networking
84648 ======================
84649 -----BEGIN CERTIFICATE-----
84650 MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
84651 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
84652 MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
84653 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
84654 AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
84655 Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
84656 dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
84657 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
84658 h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
84659 HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
84660 AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
84661 UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
84662 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
84663 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
84664 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
84665 -----END CERTIFICATE-----
84666
84667 AffirmTrust Premium
84668 ===================
84669 -----BEGIN CERTIFICATE-----
84670 MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
84671 BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
84672 OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
84673 dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
84674 MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
84675 BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
84676 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
84677 +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
84678 GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
84679 p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
84680 S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
84681 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
84682 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
84683 +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
84684 /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
84685 MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
84686 Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
84687 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
84688 L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
84689 +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
84690 BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
84691 IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
84692 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
84693 zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
84694 -----END CERTIFICATE-----
84695
84696 AffirmTrust Premium ECC
84697 =======================
84698 -----BEGIN CERTIFICATE-----
84699 MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
84700 BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
84701 MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
84702 cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
84703 IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
84704 N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
84705 BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
84706 BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
84707 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
84708 eQ==
84709 -----END CERTIFICATE-----
84710
84711 Certum Trusted Network CA
84712 =========================
84713 -----BEGIN CERTIFICATE-----
84714 MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
84715 ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
84716 biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
84717 MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
84718 ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
84719 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
84720 AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
84721 l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
84722 J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
84723 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
84724 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
84725 Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
84726 DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
84727 jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
84728 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
84729 Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
84730 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
84731 -----END CERTIFICATE-----
84732
84733 Certinomis - Autorité Racine
84734 ============================
84735 -----BEGIN CERTIFICATE-----
84736 MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
84737 Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg
84738 LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG
84739 A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw
84740 JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD
84741 ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa
84742 wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly
84743 Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw
84744 2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N
84745 jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q
84746 c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC
84747 lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb
84748 xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g
84749 530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna
84750 4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
84751 A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ
84752 KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x
84753 WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva
84754 R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40
84755 nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B
84756 CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv
84757 JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE
84758 qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b
84759 WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE
84760 wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/
84761 vgt2Fl43N+bYdJeimUV5
84762 -----END CERTIFICATE-----
84763
84764 TWCA Root Certification Authority
84765 =================================
84766 -----BEGIN CERTIFICATE-----
84767 MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
84768 VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
84769 dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
84770 EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
84771 IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
84772 AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
84773 QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
84774 oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
84775 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
84776 y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
84777 BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
84778 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
84779 mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
84780 QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
84781 T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
84782 Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
84783 -----END CERTIFICATE-----
84784
84785 Security Communication RootCA2
84786 ==============================
84787 -----BEGIN CERTIFICATE-----
84788 MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
84789 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
84790 dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
84791 SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
84792 aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
84793 ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
84794 +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
84795 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
84796 spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
84797 EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
84798 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
84799 CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
84800 u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
84801 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
84802 tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
84803 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
84804 -----END CERTIFICATE-----
84805
84806 EC-ACC
84807 ======
84808 -----BEGIN CERTIFICATE-----
84809 MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
84810 BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
84811 ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
84812 VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
84813 CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
84814 BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
84815 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
84816 SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
84817 Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
84818 cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
84819 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
84820 w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
84821 ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
84822 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
84823 E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
84824 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
84825 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
84826 VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
84827 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
84828 dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
84829 lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
84830 Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
84831 l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
84832 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
84833 5EI=
84834 -----END CERTIFICATE-----
84835
84836 Hellenic Academic and Research Institutions RootCA 2011
84837 =======================================================
84838 -----BEGIN CERTIFICATE-----
84839 MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
84840 O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
84841 aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
84842 IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
84843 AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
84844 IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
84845 IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
84846 AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
84847 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
84848 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
84849 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
84850 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
84851 MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
84852 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
84853 b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
84854 XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
84855 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
84856 /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
84857 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
84858 -----END CERTIFICATE-----
84859
84860 Actalis Authentication Root CA
84861 ==============================
84862 -----BEGIN CERTIFICATE-----
84863 MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
84864 BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
84865 AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
84866 MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
84867 IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
84868 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
84869 wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
84870 by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
84871 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
84872 YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
84873 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
84874 EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
84875 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
84876 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
84877 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
84878 iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
84879 ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
84880 WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
84881 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
84882 K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
84883 Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
84884 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
84885 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
84886 lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
84887 OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
84888 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
84889 -----END CERTIFICATE-----
84890
84891 Trustis FPS Root CA
84892 ===================
84893 -----BEGIN CERTIFICATE-----
84894 MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
84895 EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
84896 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
84897 BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
84898 KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
84899 RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
84900 H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
84901 cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
84902 o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
84903 AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
84904 BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
84905 GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
84906 yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
84907 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
84908 l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
84909 iB6XzCGcKQENZetX2fNXlrtIzYE=
84910 -----END CERTIFICATE-----
84911
84912 StartCom Certification Authority
84913 ================================
84914 -----BEGIN CERTIFICATE-----
84915 MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
84916 U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
84917 ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
84918 NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
84919 LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
84920 U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
84921 ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
84922 o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
84923 Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
84924 eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
84925 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
84926 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
84927 osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
84928 untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
84929 UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
84930 37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
84931 VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ
84932 Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0
84933 dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu
84934 c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv
84935 bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0
84936 aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0
84937 aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t
84938 L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG
84939 cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5
84940 fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm
84941 N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN
84942 Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T
84943 tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX
84944 e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA
84945 2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs
84946 HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
84947 JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib
84948 D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8=
84949 -----END CERTIFICATE-----
84950
84951 StartCom Certification Authority G2
84952 ===================================
84953 -----BEGIN CERTIFICATE-----
84954 MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
84955 U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
84956 RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE
84957 ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp
84958 dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O
84959 o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG
84960 4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi
84961 Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul
84962 Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs
84963 O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H
84964 vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L
84965 nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS
84966 FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa
84967 z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E
84968 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ
84969 KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
84970 2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk
84971 J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+
84972 JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG
84973 /+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc
84974 nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld
84975 blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc
84976 l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm
84977 7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm
84978 obp573PYtlNXLfbQ4ddI
84979 -----END CERTIFICATE-----
84980
84981 Buypass Class 2 Root CA
84982 =======================
84983 -----BEGIN CERTIFICATE-----
84984 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
84985 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
84986 DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
84987 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
84988 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
84989 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
84990 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
84991 /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
84992 CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
84993 awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
84994 zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
84995 Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
84996 Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
84997 M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
84998 VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
84999 AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
85000 A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
85001 osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
85002 aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
85003 DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
85004 LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
85005 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
85006 wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
85007 CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
85008 rJgWVqA=
85009 -----END CERTIFICATE-----
85010
85011 Buypass Class 3 Root CA
85012 =======================
85013 -----BEGIN CERTIFICATE-----
85014 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
85015 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
85016 DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
85017 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
85018 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
85019 sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
85020 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
85021 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
85022 ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
85023 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
85024 /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
85025 RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
85026 Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
85027 j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
85028 VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
85029 AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
85030 cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
85031 uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
85032 Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
85033 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
85034 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
85035 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
85036 UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
85037 eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
85038 Cp/HuZc=
85039 -----END CERTIFICATE-----
85040
85041 T-TeleSec GlobalRoot Class 3
85042 ============================
85043 -----BEGIN CERTIFICATE-----
85044 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
85045 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
85046 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
85047 MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
85048 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
85049 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
85050 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
85051 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
85052 NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
85053 iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
85054 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
85055 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
85056 AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
85057 fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
85058 ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
85059 P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
85060 e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
85061 -----END CERTIFICATE-----
85062
85063 EE Certification Centre Root CA
85064 ===============================
85065 -----BEGIN CERTIFICATE-----
85066 MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
85067 EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
85068 dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
85069 MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
85070 UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
85071 ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
85072 DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
85073 TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
85074 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
85075 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
85076 P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
85077 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
85078 MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
85079 BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
85080 xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
85081 lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
85082 uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
85083 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
85084 dcGWxZ0=
85085 -----END CERTIFICATE-----
85086
85087 TURKTRUST Certificate Services Provider Root 2007
85088 =================================================
85089 -----BEGIN CERTIFICATE-----
85090 MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
85091 bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
85092 MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
85093 QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X
85094 DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl
85095 a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN
85096 BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
85097 bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw
85098 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N
85099 YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv
85100 KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya
85101 KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT
85102 rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC
85103 AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP
85104 BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s
85105 Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I
85106 aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO
85107 Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb
85108 BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK
85109 poRq0Tl9
85110 -----END CERTIFICATE-----
85111
85112 D-TRUST Root Class 3 CA 2 2009
85113 ==============================
85114 -----BEGIN CERTIFICATE-----
85115 MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85116 DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
85117 Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
85118 LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
85119 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
85120 ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
85121 BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
85122 KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
85123 p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
85124 AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
85125 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
85126 eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
85127 MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
85128 PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
85129 OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
85130 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
85131 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
85132 dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
85133 X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
85134 -----END CERTIFICATE-----
85135
85136 D-TRUST Root Class 3 CA 2 EV 2009
85137 =================================
85138 -----BEGIN CERTIFICATE-----
85139 MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85140 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
85141 OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85142 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
85143 OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
85144 egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
85145 zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
85146 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
85147 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
85148 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
85149 cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
85150 ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
85151 MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
85152 b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
85153 c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
85154 PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
85155 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
85156 ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
85157 NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
85158 w9y4AyHqnxbxLFS1
85159 -----END CERTIFICATE-----
85160
85161 PSCProcert
85162 ==========
85163 -----BEGIN CERTIFICATE-----
85164 MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1dG9yaWRhZCBk
85165 ZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9sYW5vMQswCQYDVQQGEwJWRTEQ
85166 MA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlzdHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lz
85167 dGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBl
85168 cmludGVuZGVuY2lhIGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUw
85169 IwYJKoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEwMFoXDTIw
85170 MTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHByb2NlcnQubmV0LnZlMQ8w
85171 DQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGExKjAoBgNVBAsTIVByb3ZlZWRvciBkZSBD
85172 ZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZp
85173 Y2FjaW9uIEVsZWN0cm9uaWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIw
85174 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo97BVC
85175 wfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74BCXfgI8Qhd19L3uA
85176 3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38GieU89RLAu9MLmV+QfI4tL3czkkoh
85177 RqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmO
85178 EO8GqQKJ/+MMbpfg353bIdD0PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG2
85179 0qCZyFSTXai20b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH
85180 0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/6mnbVSKVUyqU
85181 td+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1mv6JpIzi4mWCZDlZTOpx+FIyw
85182 Bm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvp
85183 r2uKGcfLFFb14dq12fy/czja+eevbqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/
85184 AgEBMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAz
85185 Ni0wMB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFDgBStuyId
85186 xuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRp
85187 ZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQH
85188 EwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5h
85189 Y2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5k
85190 ZW5jaWEgZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG
85191 9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQDAgEGME0GA1UdEQRG
85192 MESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0wMDAwMDKgGwYFYIZeAgKgEgwQUklG
85193 LUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEagRKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52
85194 ZS9sY3IvQ0VSVElGSUNBRE8tUkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNy
85195 YWl6LnN1c2NlcnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v
85196 Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsGAQUFBwIBFh5o
85197 dHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcNAQELBQADggIBACtZ6yKZu4Sq
85198 T96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmN
85199 g7+mvTV+LFwxNG9s2/NkAZiqlCxB3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4q
85200 uxtxj7mkoP3YldmvWb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1
85201 n8GhHVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHmpHmJWhSn
85202 FFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXzsOfIt+FTvZLm8wyWuevo
85203 5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bEqCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq
85204 3TNWOByyrYDT13K9mmyZY+gAu0F2BbdbmRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5
85205 poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y
85206 eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km
85207 -----END CERTIFICATE-----
85208
85209 China Internet Network Information Center EV Certificates Root
85210 ==============================================================
85211 -----BEGIN CERTIFICATE-----
85212 MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCQ04xMjAwBgNV
85213 BAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyMUcwRQYDVQQDDD5D
85214 aGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMg
85215 Um9vdDAeFw0xMDA4MzEwNzExMjVaFw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAG
85216 A1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMM
85217 PkNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRl
85218 cyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z7r07eKpkQ0H1UN+U8i6y
85219 jUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV
85220 98YPjUesWgbdYavi7NifFy2cyjw1l1VxzUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2H
85221 klY0bBoQCxfVWhyXWIQ8hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23
85222 KzhmBsUs4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54ugQEC
85223 7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oYNJKiyoOCWTAPBgNV
85224 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUfHJLOcfA22KlT5uqGDSSosqD
85225 glkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd5
85226 0XPFtQO3WKwMVC/GVhMPMdoG52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM
85227 7+czV0I664zBechNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws
85228 ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrIzo9uoV1/A3U0
85229 5K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATywy39FCqQmbkHzJ8=
85230 -----END CERTIFICATE-----
85231
85232 Swisscom Root CA 2
85233 ==================
85234 -----BEGIN CERTIFICATE-----
85235 MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQG
85236 EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
85237 dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2
85238 MjUwNzM4MTRaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
85239 aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIIC
85240 IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvErjw0DzpPM
85241 LgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r0rk0X2s682Q2zsKwzxNo
85242 ysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJ
85243 wDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVPACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpH
85244 Wrumnf2U5NGKpV+GY3aFy6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1a
85245 SgJA/MTAtukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL6yxS
85246 NLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0uPoTXGiTOmekl9Ab
85247 mbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrALacywlKinh/LTSlDcX3KwFnUey7QY
85248 Ypqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velhk6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3
85249 qPyZ7iVNTA6z00yPhOgpD/0QVAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
85250 HQYDVR0hBBYwFDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O
85251 BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqhb97iEoHF8Twu
85252 MA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4RfbgZPnm3qKhyN2abGu2sEzsO
85253 v2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ
85254 82YqZh6NM4OKb3xuqFp1mrjX2lhIREeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLz
85255 o9v/tdhZsnPdTSpxsrpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcs
85256 a0vvaGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciATwoCqISxx
85257 OQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99nBjx8Oto0QuFmtEYE3saW
85258 mA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5Wt6NlUe07qxS/TFED6F+KBZvuim6c779o
85259 +sjaC+NCydAXFJy3SuCvkychVSa1ZC+N8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TC
85260 rvJcwhbtkj6EPnNgiLx29CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX
85261 5OfNeOI5wSsSnqaeG8XmDtkx2Q==
85262 -----END CERTIFICATE-----
85263
85264 Swisscom Root EV CA 2
85265 =====================
85266 -----BEGIN CERTIFICATE-----
85267 MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UE
85268 BhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdpdGFsIENlcnRpZmljYXRlIFNl
85269 cnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcN
85270 MzEwNjI1MDg0NTA4WjBnMQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsT
85271 HERpZ2l0YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYg
85272 Q0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7BxUglgRCgz
85273 o3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD1ycfMQ4jFrclyxy0uYAy
85274 Xhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPHoCE2G3pXKSinLr9xJZDzRINpUKTk4Rti
85275 GZQJo/PDvO/0vezbE53PnUgJUmfANykRHvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8Li
85276 qG12W0OfvrSdsyaGOx9/5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaH
85277 Za0zKcQvidm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHLOdAG
85278 alNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaCNYGu+HuB5ur+rPQa
85279 m3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f46Fq9mDU5zXNysRojddxyNMkM3Ox
85280 bPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCBUWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDi
85281 xzgHcgplwLa7JSnaFp6LNYth7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/
85282 BAQDAgGGMB0GA1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED
85283 MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWBbj2ITY1x0kbB
85284 bkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6xXCX5145v9Ydkn+0UjrgEjihL
85285 j6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98TPLr+flaYC/NUn81ETm484T4VvwYmneTwkLbU
85286 wp4wLh/vx3rEUMfqe9pQy3omywC0Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7
85287 XwgiG/W9mR4U9s70WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH
85288 59yLGn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm7JFe3VE/
85289 23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4Snr8PyQUQ3nqjsTzyP6Wq
85290 J3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VNvBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyA
85291 HmBR3NdUIR7KYndP+tiPsys6DXhyyWhBWkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/gi
85292 uMod89a2GQ+fYWVq6nTIfI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuW
85293 l8PVP3wbI+2ksx0WckNLIOFZfsLorSa/ovc=
85294 -----END CERTIFICATE-----
85295
85296 CA Disig Root R1
85297 ================
85298 -----BEGIN CERTIFICATE-----
85299 MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNVBAYTAlNLMRMw
85300 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
85301 ZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQyMDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sx
85302 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
85303 c2lnIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy
85304 3QRkD2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/oOI7bm+V8
85305 u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3AfQ+lekLZWnDZv6fXARz2
85306 m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJeIgpFy4QxTaz+29FHuvlglzmxZcfe+5nk
85307 CiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8noc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTa
85308 YVKvJrT1cU/J19IG32PK/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6
85309 vpmumwKjrckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD3AjL
85310 LhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE7cderVC6xkGbrPAX
85311 ZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkCyC2fg69naQanMVXVz0tv/wQFx1is
85312 XxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLdqvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNV
85313 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ
85314 04IwDQYJKoZIhvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR
85315 xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaASfX8MPWbTx9B
85316 LxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXoHqJPYNcHKfyyo6SdbhWSVhlM
85317 CrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpBemOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5Gfb
85318 VSUZP/3oNn6z4eGBrxEWi1CXYBmCAMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85
85319 YmLLW1AL14FABZyb7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKS
85320 ds+xDzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvkF7mGnjix
85321 lAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqFa3qdnom2piiZk4hA9z7N
85322 UaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsTQ6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJ
85323 a7+h89n07eLw4+1knj0vllJPgFOL
85324 -----END CERTIFICATE-----
85325
85326 CA Disig Root R2
85327 ================
85328 -----BEGIN CERTIFICATE-----
85329 MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
85330 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
85331 ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
85332 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
85333 c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
85334 w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
85335 xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
85336 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
85337 GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
85338 g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
85339 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
85340 koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
85341 Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
85342 Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
85343 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
85344 Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
85345 tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
85346 sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
85347 dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
85348 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
85349 mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
85350 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
85351 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
85352 UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
85353 7+ZtsH8tZ/3zbBt1RqPlShfppNcL
85354 -----END CERTIFICATE-----
85355
85356 ACCVRAIZ1
85357 =========
85358 -----BEGIN CERTIFICATE-----
85359 MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
85360 SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
85361 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
85362 UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
85363 DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
85364 jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
85365 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
85366 aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
85367 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
85368 WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
85369 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
85370 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
85371 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
85372 Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
85373 Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
85374 Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
85375 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
85376 Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
85377 QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
85378 AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
85379 YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
85380 AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
85381 IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
85382 aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
85383 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
85384 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
85385 hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
85386 R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
85387 YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
85388 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
85389 TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
85390 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
85391 I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
85392 Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
85393 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
85394 EfbRD0tVNEYqi4Y7
85395 -----END CERTIFICATE-----
85396
85397 TWCA Global Root CA
85398 ===================
85399 -----BEGIN CERTIFICATE-----
85400 MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
85401 CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
85402 QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
85403 EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
85404 Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
85405 nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
85406 r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
85407 Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
85408 tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
85409 KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
85410 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
85411 yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
85412 kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
85413 zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
85414 AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
85415 cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
85416 LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
85417 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
85418 /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
85419 lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
85420 A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
85421 i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
85422 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
85423 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
85424 -----END CERTIFICATE-----
85425
85426 TeliaSonera Root CA v1
85427 ======================
85428 -----BEGIN CERTIFICATE-----
85429 MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
85430 CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
85431 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
85432 VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
85433 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
85434 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
85435 B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
85436 Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
85437 oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
85438 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
85439 oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
85440 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
85441 TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
85442 AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
85443 DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
85444 zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
85445 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
85446 pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
85447 G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
85448 c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
85449 JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
85450 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
85451 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
85452 WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
85453 -----END CERTIFICATE-----
85454
85455 E-Tugra Certification Authority
85456 ===============================
85457 -----BEGIN CERTIFICATE-----
85458 MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
85459 DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
85460 ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
85461 ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
85462 NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
85463 QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
85464 cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
85465 DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
85466 MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
85467 hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
85468 CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
85469 ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
85470 BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
85471 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
85472 rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
85473 jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
85474 rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
85475 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
85476 /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
85477 MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
85478 kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
85479 XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
85480 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
85481 a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
85482 dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
85483 KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
85484 Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
85485 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
85486 C7TbO6Orb1wdtn7os4I07QZcJA==
85487 -----END CERTIFICATE-----
85488
85489 T-TeleSec GlobalRoot Class 2
85490 ============================
85491 -----BEGIN CERTIFICATE-----
85492 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
85493 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
85494 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
85495 MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
85496 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
85497 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
85498 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
85499 SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
85500 vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
85501 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
85502 WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
85503 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
85504 YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
85505 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
85506 vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
85507 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
85508 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
85509 -----END CERTIFICATE-----
85510
85511 Atos TrustedRoot 2011
85512 =====================
85513 -----BEGIN CERTIFICATE-----
85514 MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
85515 cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
85516 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
85517 A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
85518 hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
85519 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
85520 DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
85521 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
85522 z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
85523 l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
85524 bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
85525 CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
85526 k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
85527 TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
85528 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
85529 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
85530 -----END CERTIFICATE-----
85531
85532 QuoVadis Root CA 1 G3
85533 =====================
85534 -----BEGIN CERTIFICATE-----
85535 MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
85536 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85537 b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
85538 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
85539 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
85540 PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
85541 PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
85542 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
85543 ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
85544 g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
85545 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
85546 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
85547 iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
85548 t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85549 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
85550 hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
85551 MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
85552 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
85553 Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
85554 +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
85555 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
85556 wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
85557 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
85558 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
85559 hMJKzRwuJIczYOXD
85560 -----END CERTIFICATE-----
85561
85562 QuoVadis Root CA 2 G3
85563 =====================
85564 -----BEGIN CERTIFICATE-----
85565 MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
85566 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85567 b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
85568 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
85569 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
85570 ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
85571 NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
85572 oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
85573 MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
85574 V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
85575 L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
85576 sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
85577 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
85578 lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85579 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
85580 hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
85581 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
85582 pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
85583 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
85584 dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
85585 U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
85586 mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
85587 zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
85588 JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
85589 O3jtZsSOeWmD3n+M
85590 -----END CERTIFICATE-----
85591
85592 QuoVadis Root CA 3 G3
85593 =====================
85594 -----BEGIN CERTIFICATE-----
85595 MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
85596 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85597 b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
85598 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
85599 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
85600 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
85601 Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
85602 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
85603 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
85604 VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
85605 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
85606 Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
85607 dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
85608 rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85609 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
85610 hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
85611 KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
85612 t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
85613 TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
85614 DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
85615 Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
85616 hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
85617 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
85618 dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
85619 PpxxVJkES/1Y+Zj0
85620 -----END CERTIFICATE-----
85621
85622 DigiCert Assured ID Root G2
85623 ===========================
85624 -----BEGIN CERTIFICATE-----
85625 MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
85626 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
85627 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
85628 MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
85629 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
85630 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
85631 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
85632 bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
85633 VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
85634 YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
85635 lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
85636 w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
85637 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
85638 d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
85639 hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
85640 jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
85641 IhNzbM8m9Yop5w==
85642 -----END CERTIFICATE-----
85643
85644 DigiCert Assured ID Root G3
85645 ===========================
85646 -----BEGIN CERTIFICATE-----
85647 MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
85648 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
85649 VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
85650 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
85651 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
85652 BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
85653 RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
85654 KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
85655 UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
85656 YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
85657 1vUhZscv6pZjamVFkpUBtA==
85658 -----END CERTIFICATE-----
85659
85660 DigiCert Global Root G2
85661 =======================
85662 -----BEGIN CERTIFICATE-----
85663 MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
85664 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
85665 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
85666 MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
85667 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
85668 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
85669 kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
85670 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
85671 BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
85672 UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
85673 o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
85674 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
85675 F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
85676 WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
85677 QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
85678 iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
85679 MrY=
85680 -----END CERTIFICATE-----
85681
85682 DigiCert Global Root G3
85683 =======================
85684 -----BEGIN CERTIFICATE-----
85685 MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
85686 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
85687 VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
85688 MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
85689 aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
85690 AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
85691 YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
85692 BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
85693 Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
85694 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
85695 VOKa5Vt8sycX
85696 -----END CERTIFICATE-----
85697
85698 DigiCert Trusted Root G4
85699 ========================
85700 -----BEGIN CERTIFICATE-----
85701 MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
85702 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
85703 HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
85704 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
85705 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
85706 CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
85707 pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
85708 k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
85709 vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
85710 QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
85711 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
85712 mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
85713 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
85714 dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
85715 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
85716 DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
85717 ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
85718 ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
85719 yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
85720 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
85721 ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
85722 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
85723 /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
85724 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
85725 G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
85726 82Z+
85727 -----END CERTIFICATE-----
85728
85729 WoSign
85730 ======
85731 -----BEGIN CERTIFICATE-----
85732 MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQG
85733 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNVBAMTIUNlcnRpZmljYXRpb24g
85734 QXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJ
85735 BgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNh
85736 dGlvbiBBdXRob3JpdHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
85737 vcqNrLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1UfcIiePyO
85738 CbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcSccf+Hb0v1naMQFXQoOXXDX
85739 2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2ZjC1vt7tj/id07sBMOby8w7gLJKA84X5
85740 KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4Mx1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR
85741 +ScPewavVIMYe+HdVHpRaG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ez
85742 EC8wQjchzDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDaruHqk
85743 lWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221KmYo0SLwX3OSACCK2
85744 8jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvASh0JWzko/amrzgD5LkhLJuYwTKVY
85745 yrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWvHYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0C
85746 AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R
85747 8bNLtwYgFP6HEtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1
85748 LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJMuYhOZO9sxXq
85749 T2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2eJXLOC62qx1ViC777Y7NhRCOj
85750 y+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VNg64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC
85751 2nz4SNAzqfkHx5Xh9T71XXG68pWpdIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes
85752 5cVAWubXbHssw1abR80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/
85753 EaEQPkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGcexGATVdVh
85754 mVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+J7x6v+Db9NpSvd4MVHAx
85755 kUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMlOtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGi
85756 kpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWTee5Ehr7XHuQe+w==
85757 -----END CERTIFICATE-----
85758
85759 WoSign China
85760 ============
85761 -----BEGIN CERTIFICATE-----
85762 MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQG
85763 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMMEkNBIOayg+mAmuagueiv
85764 geS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYD
85765 VQQKExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjAN
85766 BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k
85767 8H/rD195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld19AXbbQs5
85768 uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExfv5RxadmWPgxDT74wwJ85
85769 dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnkUkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5
85770 Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+LNVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFy
85771 b7Ao65vh4YOhn0pdr8yb+gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc
85772 76DbT52VqyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6KyX2m
85773 +Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0GAbQOXDBGVWCvOGU6
85774 yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaKJ/kR8slC/k7e3x9cxKSGhxYzoacX
85775 GKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwECAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
85776 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUA
85777 A4ICAQBqinA4WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6
85778 yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj/feTZU7n85iY
85779 r83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6jBAyvd0zaziGfjk9DgNyp115
85780 j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0A
85781 kLppRQjbbpCBhqcqBT/mhDn4t/lXX0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97
85782 qA4bLJyuQHCH2u2nFoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Y
85783 jj4Du9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10lO1Hm13ZB
85784 ONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Leie2uPAmvylezkolwQOQv
85785 T8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR12KvxAmLBsX5VYc8T1yaw15zLKYs4SgsO
85786 kI26oQ==
85787 -----END CERTIFICATE-----
85788
85789 COMODO RSA Certification Authority
85790 ==================================
85791 -----BEGIN CERTIFICATE-----
85792 MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
85793 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
85794 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
85795 biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
85796 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
85797 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
85798 dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
85799 dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
85800 FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
85801 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
85802 x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
85803 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
85804 OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
85805 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
85806 GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
85807 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
85808 FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
85809 DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
85810 rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
85811 nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
85812 tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
85813 sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
85814 pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
85815 zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
85816 ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
85817 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
85818 LaZRfyHBNVOFBkpdn627G190
85819 -----END CERTIFICATE-----
85820
85821 USERTrust RSA Certification Authority
85822 =====================================
85823 -----BEGIN CERTIFICATE-----
85824 MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
85825 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
85826 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
85827 dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
85828 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
85829 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
85830 dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
85831 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
85832 Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
85833 RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
85834 +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
85835 /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
85836 Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
85837 lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
85838 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
85839 eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
85840 BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
85841 MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
85842 FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
85843 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
85844 Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
85845 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
85846 FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
85847 yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
85848 J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
85849 sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
85850 Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
85851 -----END CERTIFICATE-----
85852
85853 USERTrust ECC Certification Authority
85854 =====================================
85855 -----BEGIN CERTIFICATE-----
85856 MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
85857 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
85858 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
85859 biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
85860 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
85861 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
85862 biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
85863 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
85864 nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
85865 HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
85866 HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
85867 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
85868 -----END CERTIFICATE-----
85869
85870 GlobalSign ECC Root CA - R4
85871 ===========================
85872 -----BEGIN CERTIFICATE-----
85873 MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
85874 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85875 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
85876 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85877 EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
85878 OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
85879 AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
85880 MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
85881 JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
85882 -----END CERTIFICATE-----
85883
85884 GlobalSign ECC Root CA - R5
85885 ===========================
85886 -----BEGIN CERTIFICATE-----
85887 MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
85888 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85889 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
85890 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85891 EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
85892 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
85893 h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
85894 BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
85895 uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
85896 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
85897 -----END CERTIFICATE-----
85898
85899 Staat der Nederlanden Root CA - G3
85900 ==================================
85901 -----BEGIN CERTIFICATE-----
85902 MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
85903 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
85904 Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
85905 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
85906 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
85907 olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
85908 x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
85909 EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
85910 Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
85911 mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
85912 1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
85913 07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
85914 FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
85915 41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
85916 AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
85917 yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
85918 U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
85919 KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
85920 v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
85921 8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
85922 8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
85923 mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
85924 1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
85925 JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
85926 tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
85927 -----END CERTIFICATE-----
85928
85929 Staat der Nederlanden EV Root CA
85930 ================================
85931 -----BEGIN CERTIFICATE-----
85932 MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
85933 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
85934 RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
85935 MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
85936 cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
85937 SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
85938 O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
85939 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
85940 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
85941 XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
85942 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
85943 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
85944 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
85945 fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
85946 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
85947 ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
85948 eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
85949 c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
85950 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
85951 b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
85952 f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
85953 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
85954 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
85955 DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
85956 eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
85957 -----END CERTIFICATE-----
85958
85959 IdenTrust Commercial Root CA 1
85960 ==============================
85961 -----BEGIN CERTIFICATE-----
85962 MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
85963 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
85964 b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
85965 MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
85966 IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
85967 hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
85968 mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
85969 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
85970 XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
85971 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
85972 NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
85973 WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
85974 xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
85975 uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
85976 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
85977 hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
85978 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
85979 ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
85980 ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
85981 YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
85982 feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
85983 kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
85984 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
85985 Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
85986 cGzM7vRX+Bi6hG6H
85987 -----END CERTIFICATE-----
85988
85989 IdenTrust Public Sector Root CA 1
85990 =================================
85991 -----BEGIN CERTIFICATE-----
85992 MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
85993 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
85994 ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
85995 UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
85996 b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
85997 P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
85998 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
85999 rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
86000 qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
86001 mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
86002 ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
86003 LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
86004 iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
86005 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
86006 Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
86007 DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
86008 t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
86009 mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
86010 GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
86011 m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
86012 NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
86013 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
86014 ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
86015 ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
86016 3Wl9af0AVqW3rLatt8o+Ae+c
86017 -----END CERTIFICATE-----
86018
86019 Entrust Root Certification Authority - G2
86020 =========================================
86021 -----BEGIN CERTIFICATE-----
86022 MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
86023 BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
86024 bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
86025 b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
86026 HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
86027 DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
86028 OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
86029 eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
86030 MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
86031 /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
86032 HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
86033 s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
86034 TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
86035 AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
86036 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
86037 iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
86038 Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
86039 nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
86040 vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
86041 e4pIb4tF9g==
86042 -----END CERTIFICATE-----
86043
86044 Entrust Root Certification Authority - EC1
86045 ==========================================
86046 -----BEGIN CERTIFICATE-----
86047 MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
86048 FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
86049 YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
86050 ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
86051 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
86052 FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
86053 LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
86054 dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
86055 IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
86056 AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
86057 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
86058 FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
86059 vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
86060 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
86061 -----END CERTIFICATE-----
86062
86063 CFCA EV ROOT
86064 ============
86065 -----BEGIN CERTIFICATE-----
86066 MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
86067 CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
86068 IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
86069 MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
86070 DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
86071 BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
86072 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
86073 uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
86074 ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
86075 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
86076 py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
86077 gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
86078 hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
86079 tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
86080 BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
86081 /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
86082 ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
86083 ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
86084 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
86085 E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
86086 BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
86087 aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
86088 PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
86089 kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
86090 ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
86091 -----END CERTIFICATE-----
86092
86093 TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5
86094 ====================================================
86095 -----BEGIN CERTIFICATE-----
86096 MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UEBhMCVFIxDzAN
86097 BgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
86098 bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1Qg
86099 RWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAw
86100 ODA3MDFaFw0yMzA0MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0w
86101 SwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnE
86102 n2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRp
86103 ZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
86104 CgKCAQEApCUZ4WWe60ghUEoI5RHwWrom/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537
86105 jVJp45wnEFPzpALFp/kRGml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1m
86106 ep5Fimh34khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z5UNP
86107 9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0hO8EuPbJbKoCPrZV
86108 4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QIDAQABo0IwQDAdBgNVHQ4EFgQUVpkH
86109 HtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
86110 hvcNAQELBQADggEBAJ5FdnsXSDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPo
86111 BP5yCccLqh0lVX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq
86112 URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nfpeYVhDfwwvJl
86113 lpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CFYv4HAqGEVka+lgqaE9chTLd8
86114 B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW+qtB4Uu2NQvAmxU=
86115 -----END CERTIFICATE-----
86116
86117 TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6
86118 ====================================================
86119 -----BEGIN CERTIFICATE-----
86120 MIIEJjCCAw6gAwIBAgIGfaHyZeyKMA0GCSqGSIb3DQEBCwUAMIGxMQswCQYDVQQGEwJUUjEPMA0G
86121 A1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls
86122 acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF
86123 bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg2MB4XDTEzMTIxODA5
86124 MDQxMFoXDTIzMTIxNjA5MDQxMFowgbExCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExTTBL
86125 BgNVBAoMRFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSf
86126 aSBIaXptZXRsZXJpIEEuxZ4uMUIwQAYDVQQDDDlUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2VydGlm
86127 aWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLEgSDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
86128 AoIBAQCdsGjW6L0UlqMACprx9MfMkU1xeHe59yEmFXNRFpQJRwXiM/VomjX/3EsvMsew7eKC5W/a
86129 2uqsxgbPJQ1BgfbBOCK9+bGlprMBvD9QFyv26WZV1DOzXPhDIHiTVRZwGTLmiddk671IUP320EED
86130 wnS3/faAz1vFq6TWlRKb55cTMgPp1KtDWxbtMyJkKbbSk60vbNg9tvYdDjTu0n2pVQ8g9P0pu5Fb
86131 HH3GQjhtQiht1AH7zYiXSX6484P4tZgvsycLSF5W506jM7NE1qXyGJTtHB6plVxiSvgNZ1GpryHV
86132 +DKdeboaX+UEVU0TRv/yz3THGmNtwx8XEsMeED5gCLMxAgMBAAGjQjBAMB0GA1UdDgQWBBTdVRcT
86133 9qzoSCHK77Wv0QAy7Z6MtTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
86134 9w0BAQsFAAOCAQEAb1gNl0OqFlQ+v6nfkkU/hQu7VtMMUszIv3ZnXuaqs6fvuay0EBQNdH49ba3R
86135 fdCaqaXKGDsCQC4qnFAUi/5XfldcEQlLNkVS9z2sFP1E34uXI9TDwe7UU5X+LEr+DXCqu4svLcsy
86136 o4LyVN/Y8t3XSHLuSqMplsNEzm61kod2pLv0kmzOLBQJZo6NrRa1xxsJYTvjIKIDgI6tflEATseW
86137 hvtDmHd9KMeP2Cpu54Rvl0EpABZeTeIT6lnAY2c6RPuY/ATTMHKm9ocJV612ph1jmv3XZch4gyt1
86138 O6VbuA1df74jrlZVlFjvH4GMKrLN5ptjnhi85WsGtAuYSyher4hYyw==
86139 -----END CERTIFICATE-----
86140
86141 Certinomis - Root CA
86142 ====================
86143 -----BEGIN CERTIFICATE-----
86144 MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
86145 Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg
86146 LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx
86147 EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD
86148 ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos
86149 P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo
86150 d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap
86151 z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00
86152 8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x
86153 RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE
86154 6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t
86155 FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV
86156 PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH
86157 i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj
86158 YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I
86159 6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF
86160 AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV
86161 WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw
86162 Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX
86163 lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ
86164 y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9
86165 Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng
86166 DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi
86167 I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM
86168 cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr
86169 hkIGuUE=
86170 -----END CERTIFICATE-----
86171
86172 OISTE WISeKey Global Root GB CA
86173 ===============================
86174 -----BEGIN CERTIFICATE-----
86175 MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
86176 EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
86177 ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
86178 MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
86179 VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
86180 b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
86181 scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
86182 rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
86183 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
86184 Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
86185 GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
86186 /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
86187 hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
86188 dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
86189 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
86190 HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
86191 Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
86192 -----END CERTIFICATE-----
86193
86194 Certification Authority of WoSign G2
86195 ====================================
86196 -----BEGIN CERTIFICATE-----
86197 MIIDfDCCAmSgAwIBAgIQayXaioidfLwPBbOxemFFRDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQG
86198 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxLTArBgNVBAMTJENlcnRpZmljYXRpb24g
86199 QXV0aG9yaXR5IG9mIFdvU2lnbiBHMjAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMFgx
86200 CzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEtMCsGA1UEAxMkQ2VydGlm
86201 aWNhdGlvbiBBdXRob3JpdHkgb2YgV29TaWduIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
86202 CgKCAQEAvsXEoCKASU+/2YcRxlPhuw+9YH+v9oIOH9ywjj2X4FA8jzrvZjtFB5sg+OPXJYY1kBai
86203 XW8wGQiHC38Gsp1ij96vkqVg1CuAmlI/9ZqD6TRay9nVYlzmDuDfBpgOgHzKtB0TiGsOqCR3A9Du
86204 W/PKaZE1OVbFbeP3PU9ekzgkyhjpJMuSA93MHD0JcOQg5PGurLtzaaNjOg9FD6FKmsLRY6zLEPg9
86205 5k4ot+vElbGs/V6r+kHLXZ1L3PR8du9nfwB6jdKgGlxNIuG12t12s9R23164i5jIFFTMaxeSt+BK
86206 v0mUYQs4kI9dJGwlezt52eJ+na2fmKEG/HgUYFf47oB3sQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
86207 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU+mCp62XF3RYUCE4MD42b4Pdkr2cwDQYJKoZI
86208 hvcNAQELBQADggEBAFfDejaCnI2Y4qtAqkePx6db7XznPWZaOzG73/MWM5H8fHulwqZm46qwtyeY
86209 P0nXYGdnPzZPSsvxFPpahygc7Y9BMsaV+X3avXtbwrAh449G3CE4Q3RM+zD4F3LBMvzIkRfEzFg3
86210 TgvMWvchNSiDbGAtROtSjFA9tWwS1/oJu2yySrHFieT801LYYRf+epSEj3m2M1m6D8QL4nCgS3gu
86211 +sif/a+RZQp4OBXllxcU3fngLDT4ONCEIgDAFFEYKwLcMFrw6AF8NTojrwjkr6qOKEJJLvD1mTS+
86212 7Q9LGOHSJDy7XUe3IfKN0QqZjuNuPq1w4I+5ysxugTH2e5x6eeRncRg=
86213 -----END CERTIFICATE-----
86214
86215 CA WoSign ECC Root
86216 ==================
86217 -----BEGIN CERTIFICATE-----
86218 MIICCTCCAY+gAwIBAgIQaEpYcIBr8I8C+vbe6LCQkDAKBggqhkjOPQQDAzBGMQswCQYDVQQGEwJD
86219 TjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMTEkNBIFdvU2lnbiBFQ0MgUm9v
86220 dDAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQK
86221 ExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAxMSQ0EgV29TaWduIEVDQyBSb290MHYwEAYHKoZI
86222 zj0CAQYFK4EEACIDYgAE4f2OuEMkq5Z7hcK6C62N4DrjJLnSsb6IOsq/Srj57ywvr1FQPEd1bPiU
86223 t5v8KB7FVMxjnRZLU8HnIKvNrCXSf4/CwVqCXjCLelTOA7WRf6qU0NGKSMyCBSah1VES1ns2o0Iw
86224 QDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqv3VWqP2h4syhf3R
86225 MluARZPzA7gwCgYIKoZIzj0EAwMDaAAwZQIxAOSkhLCB1T2wdKyUpOgOPQB0TKGXa/kNUTyh2Tv0
86226 Daupn75OcsqF1NnstTJFGG+rrQIwfcf3aWMvoeGY7xMQ0Xk/0f7qO3/eVvSQsRUR2LIiFdAvwyYu
86227 a/GRspBl9JrmkO5K
86228 -----END CERTIFICATE-----
86229
86230 SZAFIR ROOT CA2
86231 ===============
86232 -----BEGIN CERTIFICATE-----
86233 MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
86234 A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
86235 BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
86236 BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
86237 VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
86238 qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
86239 DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
86240 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
86241 ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
86242 ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
86243 AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
86244 AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
86245 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
86246 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
86247 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
86248 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
86249 -----END CERTIFICATE-----
86250
86251 Certum Trusted Network CA 2
86252 ===========================
86253 -----BEGIN CERTIFICATE-----
86254 MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
86255 BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
86256 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
86257 ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
86258 TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
86259 cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
86260 IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
86261 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
86262 CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
86263 Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
86264 uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
86265 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
86266 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
86267 Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
86268 hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
86269 BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86270 AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
86271 hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
86272 Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
86273 L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
86274 clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
86275 pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
86276 w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
86277 J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
86278 ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
86279 is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
86280 zAYspsbiDrW5viSP
86281 -----END CERTIFICATE-----
86282
86283 Hellenic Academic and Research Institutions RootCA 2015
86284 =======================================================
86285 -----BEGIN CERTIFICATE-----
86286 MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
86287 BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
86288 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
86289 YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
86290 MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
86291 QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
86292 BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
86293 MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
86294 bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
86295 iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
86296 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
86297 FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
86298 i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
86299 GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
86300 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
86301 iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
86302 Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86303 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
86304 hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
86305 D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
86306 d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
86307 d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
86308 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
86309 davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
86310 Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
86311 J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
86312 JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
86313 p/UsQu0yrbYhnr68
86314 -----END CERTIFICATE-----
86315
86316 Hellenic Academic and Research Institutions ECC RootCA 2015
86317 ===========================================================
86318 -----BEGIN CERTIFICATE-----
86319 MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
86320 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
86321 cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
86322 aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
86323 MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
86324 IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
86325 VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
86326 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
86327 dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
86328 Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
86329 BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
86330 GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
86331 dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
86332 -----END CERTIFICATE-----
86333
86334 Certplus Root CA G1
86335 ===================
86336 -----BEGIN CERTIFICATE-----
86337 MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUAMD4xCzAJBgNV
86338 BAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTAe
86339 Fw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhD
86340 ZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQAD
86341 ggIPADCCAgoCggIBANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHN
86342 r49aiZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt6kuJPKNx
86343 Qv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP0FG7Yn2ksYyy/yARujVj
86344 BYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTv
86345 LRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDEEW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2
86346 z4QTd28n6v+WZxcIbekN1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc
86347 4nBvCGrch2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCTmehd
86348 4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV4EJQeIQEQWGw9CEj
86349 jy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPOWftwenMGE9nTdDckQQoRb5fc5+R+
86350 ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G
86351 A1UdDgQWBBSowcCbkahDFXxdBie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHY
86352 lwuBsTANBgkqhkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh
86353 66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7/SMNkPX0XtPG
86354 YX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BSS7CTKtQ+FjPlnsZlFT5kOwQ/
86355 2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F
86356 6ALEUz65noe8zDUa3qHpimOHZR4RKttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilX
86357 CNQ314cnrUlZp5GrRHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWe
86358 tUNy6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEVV/xuZDDC
86359 VRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5g4VCXA9DO2pJNdWY9BW/
86360 +mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl++O/QmueD6i9a5jc2NvLi6Td11n0bt3+
86361 qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo=
86362 -----END CERTIFICATE-----
86363
86364 Certplus Root CA G2
86365 ===================
86366 -----BEGIN CERTIFICATE-----
86367 MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4xCzAJBgNVBAYT
86368 AkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjAeFw0x
86369 NDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0
86370 cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IA
86371 BM0PW1aC3/BFGtat93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uN
86372 Am8xIk0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0PAQH/BAQD
86373 AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMB8GA1Ud
86374 IwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqGSM49BAMDA2gAMGUCMHD+sAvZ94OX7PNV
86375 HdTcswYO/jOYnYs5kGuUIe22113WTNchp+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjl
86376 vPl5adytRSv3tjFzzAalU5ORGpOucGpnutee5WEaXw==
86377 -----END CERTIFICATE-----
86378
86379 OpenTrust Root CA G1
86380 ====================
86381 -----BEGIN CERTIFICATE-----
86382 MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV
86383 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx
86384 MB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
86385 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEB
86386 AQUAA4ICDwAwggIKAoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7fa
86387 Yp6bwiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX/uMftk87
86388 ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR077F9jAHiOH3BX2pfJLKO
86389 YheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGPuY4zbGneWK2gDqdkVBFpRGZPTBKnjix9
86390 xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLxp2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO
86391 9z0M+Yo0FMT7MzUj8czxKselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq
86392 3ywgsNw2TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+WG+Oi
86393 n6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPwvFEVVJSmdz7QdFG9
86394 URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYYEQRVzXR7z2FwefR7LFxckvzluFqr
86395 TJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
86396 /zAdBgNVHQ4EFgQUl0YhVyE12jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/Px
86397 N3DlCPaTKbYwDQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E
86398 PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kfgLMtMrpkZ2Cv
86399 uVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbSFXJfLkur1J1juONI5f6ELlgK
86400 n0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLh
86401 X4SPgPL0DTatdrOjteFkdjpY3H1PXlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80
86402 nR14SohWZ25g/4/Ii+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcm
86403 GS3tTAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L9109S5zvE/
86404 bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/KyPu1svf0OnWZzsD2097+o
86405 4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJAwSQiumPv+i2tCqjI40cHLI5kqiPAlxA
86406 OXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj1oxx
86407 -----END CERTIFICATE-----
86408
86409 OpenTrust Root CA G2
86410 ====================
86411 -----BEGIN CERTIFICATE-----
86412 MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUAMEAxCzAJBgNV
86413 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcy
86414 MB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
86415 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEB
86416 AQUAA4ICDwAwggIKAoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+
86417 Ntmh/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78eCbY2albz
86418 4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/61UWY0jUJ9gNDlP7ZvyCV
86419 eYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fEFY8ElggGQgT4hNYdvJGmQr5J1WqIP7wt
86420 UdGejeBSzFfdNTVY27SPJIjki9/ca1TSgSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz
86421 3GIZ38i1MH/1PCZ1Eb3XG7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj
86422 3CzMpSZyYhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaHvGOz
86423 9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4t/bQWVyJ98LVtZR0
86424 0dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/gh7PU3+06yzbXfZqfUAkBXKJOAGT
86425 y3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
86426 /zAdBgNVHQ4EFgQUajn6QiL35okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59
86427 M4PLuG53hq8wDQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz
86428 Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0nXGEL8pZ0keI
86429 mUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qTRmTFAHneIWv2V6CG1wZy7HBG
86430 S4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpTwm+bREx50B1ws9efAvSyB7DH5fitIw6mVskp
86431 EndI2S9G/Tvw/HRwkqWOOAgfZDC2t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ
86432 6e18CL13zSdkzJTaTkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97kr
86433 gCf2o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU3jg9CcCo
86434 SmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eAiN1nE28daCSLT7d0geX0
86435 YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14fWKGVyasvc0rQLW6aWQ9VGHgtPFGml4vm
86436 u7JwqkwR3v98KzfUetF3NI/n+UL3PIEMS1IK
86437 -----END CERTIFICATE-----
86438
86439 OpenTrust Root CA G3
86440 ====================
86441 -----BEGIN CERTIFICATE-----
86442 MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAxCzAJBgNVBAYT
86443 AkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEczMB4X
86444 DTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9w
86445 ZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQA
86446 IgNiAARK7liuTcpm3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5B
86447 ta1doYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4GA1UdDwEB
86448 /wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAf
86449 BgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAKBggqhkjOPQQDAwNpADBmAjEAj6jcnboM
86450 BBf6Fek9LykBl7+BFjNAk2z8+e2AcG+qj9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta
86451 3U1fJAuwACEl74+nBCZx4nxp5V2a+EEfOzmTk51V6s2N8fvB
86452 -----END CERTIFICATE-----
86453
86454 ISRG Root X1
86455 ============
86456 -----BEGIN CERTIFICATE-----
86457 MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
86458 BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
86459 EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
86460 EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
86461 DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
86462 Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
86463 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
86464 b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
86465 Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
86466 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
86467 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
86468 hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
86469 usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
86470 OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
86471 A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
86472 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
86473 ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
86474 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
86475 hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
86476 TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
86477 e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
86478 JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
86479 YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
86480 JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
86481 m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
86482 -----END CERTIFICATE-----
86483
86484 AC RAIZ FNMT-RCM
86485 ================
86486 -----BEGIN CERTIFICATE-----
86487 MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
86488 AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
86489 MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
86490 TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
86491 ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
86492 qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
86493 btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
86494 j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
86495 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
86496 WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
86497 tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
86498 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
86499 ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
86500 i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
86501 FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
86502 dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
86503 nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
86504 D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
86505 j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
86506 Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
86507 +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
86508 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
86509 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
86510 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
86511 rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
86512 -----END CERTIFICATE-----
86513
86514 Amazon Root CA 1
86515 ================
86516 -----BEGIN CERTIFICATE-----
86517 MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
86518 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
86519 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
86520 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
86521 ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
86522 FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
86523 gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
86524 dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
86525 VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
86526 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
86527 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
86528 CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
86529 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
86530 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
86531 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
86532 -----END CERTIFICATE-----
86533
86534 Amazon Root CA 2
86535 ================
86536 -----BEGIN CERTIFICATE-----
86537 MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
86538 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
86539 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
86540 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
86541 ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
86542 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
86543 N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
86544 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
86545 fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
86546 kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
86547 btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
86548 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
86549 c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
86550 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
86551 DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
86552 A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
86553 +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
86554 YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
86555 xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
86556 gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
86557 aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
86558 Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
86559 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
86560 JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
86561 -----END CERTIFICATE-----
86562
86563 Amazon Root CA 3
86564 ================
86565 -----BEGIN CERTIFICATE-----
86566 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
86567 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
86568 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
86569 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
86570 f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
86571 Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
86572 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
86573 eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
86574 -----END CERTIFICATE-----
86575
86576 Amazon Root CA 4
86577 ================
86578 -----BEGIN CERTIFICATE-----
86579 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
86580 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
86581 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
86582 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
86583 /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
86584 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
86585 HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
86586 MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
86587 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
86588 -----END CERTIFICATE-----
86589
86590 LuxTrust Global Root 2
86591 ======================
86592 -----BEGIN CERTIFICATE-----
86593 MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG
86594 A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh
86595 bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW
86596 MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC
86597 AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm
86598 Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2
86599 xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC
86600 wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm
86601 1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm
86602 FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF
86603 wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/
86604 a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U
86605 ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ
86606 MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB
86607 /zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5
86608 Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
86609 +Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ
86610 FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN
86611 H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW
86612 7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu
86613 ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA
86614 VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR
86615 TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
86616 /f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc
86617 7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
86618 iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
86619 -----END CERTIFICATE-----
86620 <?php
86621
86622 if (PHP_SAPI !== 'cli') {
86623     echo 'Warning: Composer should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
86624 }
86625
86626 require __DIR__.'/../src/bootstrap.php';
86627
86628 use Composer\Factory;
86629 use Composer\XdebugHandler;
86630 use Composer\Console\Application;
86631
86632 error_reporting(-1);
86633
86634 // Create output for XdebugHandler and Application
86635 $output = Factory::createOutput();
86636
86637 $xdebug = new XdebugHandler($output);
86638 $xdebug->check();
86639 unset($xdebug);
86640
86641 if (function_exists('ini_set')) {
86642     @ini_set('display_errors', 1);
86643
86644     $memoryInBytes = function ($value) {
86645         $unit = strtolower(substr($value, -1, 1));
86646         $value = (int) $value;
86647         switch($unit) {
86648             case 'g':
86649                 $value *= 1024;
86650                 // no break (cumulative multiplier)
86651             case 'm':
86652                 $value *= 1024;
86653                 // no break (cumulative multiplier)
86654             case 'k':
86655                 $value *= 1024;
86656         }
86657
86658         return $value;
86659     };
86660
86661     $memoryLimit = trim(ini_get('memory_limit'));
86662     // Increase memory_limit if it is lower than 1.5GB
86663     if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
86664         @ini_set('memory_limit', '1536M');
86665     }
86666     unset($memoryInBytes, $memoryLimit);
86667 }
86668
86669 putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
86670
86671 // run the command application
86672 $application = new Application();
86673 $application->run(null, $output);
86674
86675 Copyright (c) Nils Adermann, Jordi Boggiano
86676
86677 Permission is hereby granted, free of charge, to any person obtaining a copy
86678 of this software and associated documentation files (the "Software"), to deal
86679 in the Software without restriction, including without limitation the rights
86680 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
86681 copies of the Software, and to permit persons to whom the Software is furnished
86682 to do so, subject to the following conditions:
86683
86684 The above copyright notice and this permission notice shall be included in all
86685 copies or substantial portions of the Software.
86686
86687 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86688 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
86689 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
86690 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
86691 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
86692 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
86693 THE SOFTWARE.
86694
86695 ö\9d\11Ä[\ 5zEÞ=m\8e¨Í\87B\ 2£\1ce\ 2\0\0\0GBMB